Skip to content

Commit 2ac74cb

Browse files
committed
Add ChatClientFactory.
1 parent fb0712e commit 2ac74cb

2 files changed

Lines changed: 93 additions & 0 deletions

File tree

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using Microsoft.Extensions.AI;
2+
using Microsoft.Extensions.Configuration;
3+
using OllamaSharp;
4+
using OpenAI;
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Net.Http;
9+
using System.Threading;
10+
using System.Threading.Tasks;
11+
12+
namespace Estranged.Automation
13+
{
14+
public interface IChatClientFactory
15+
{
16+
IChatClient CreateClient(string urn);
17+
Task<IList<string>> GetModels(string urn, CancellationToken token);
18+
}
19+
20+
internal sealed class ChatClientFactory : IChatClientFactory
21+
{
22+
private readonly OpenAIClient _openAIClient;
23+
private readonly IHttpClientFactory _httpClientFactory;
24+
private readonly IConfiguration _configuration;
25+
26+
public ChatClientFactory(OpenAIClient openAIClient, IHttpClientFactory httpClientFactory, IConfiguration configuration)
27+
{
28+
_openAIClient = openAIClient;
29+
_httpClientFactory = httpClientFactory;
30+
_configuration = configuration;
31+
}
32+
33+
public IChatClient CreateClient(string urn)
34+
{
35+
var parts = urn.Split(':', 3, StringSplitOptions.RemoveEmptyEntries);
36+
if (parts.Length != 3 || !parts[0].Equals("urn", StringComparison.OrdinalIgnoreCase))
37+
{
38+
throw new ArgumentException("Invalid URN format. Expected 'urn:<provider>:<model>'.", nameof(urn));
39+
}
40+
41+
var provider = parts[1].ToLowerInvariant();
42+
var model = parts[2];
43+
44+
switch (provider)
45+
{
46+
case "openai":
47+
return _openAIClient.GetChatClient(model).AsIChatClient();
48+
case "ollama":
49+
{
50+
var httpClient = _httpClientFactory.CreateClient();
51+
httpClient.Timeout = TimeSpan.FromHours(1);
52+
httpClient.BaseAddress = new Uri(_configuration["OLLAMA_HOST"]);
53+
return new OllamaApiClient(httpClient, model);
54+
}
55+
default:
56+
throw new NotSupportedException($"Provider '{provider}' is not supported.");
57+
}
58+
}
59+
60+
public async Task<IList<string>> GetModels(string urn, CancellationToken token)
61+
{
62+
var parts = urn.Split(':', 2, StringSplitOptions.RemoveEmptyEntries);
63+
if (parts.Length != 2 || !parts[0].Equals("urn", StringComparison.OrdinalIgnoreCase))
64+
{
65+
throw new ArgumentException("Invalid URN format. Expected 'urn:<provider>:<model>'.", nameof(urn));
66+
}
67+
68+
var provider = parts[1].ToLowerInvariant();
69+
70+
switch (provider)
71+
{
72+
case "openai":
73+
var openAiModels = await _openAIClient.GetOpenAIModelClient().GetModelsAsync(token);
74+
return [.. openAiModels.Value.Select(x => x.Id)];
75+
case "ollama":
76+
{
77+
using var httpClient = _httpClientFactory.CreateClient();
78+
httpClient.Timeout = TimeSpan.FromHours(1);
79+
httpClient.BaseAddress = new Uri(_configuration["OLLAMA_HOST"]);
80+
using var client = new OllamaApiClient(httpClient);
81+
var ollamaModels = await client.ListLocalModelsAsync(token);
82+
return [.. ollamaModels.Select(x => x.Name)];
83+
}
84+
default:
85+
throw new NotSupportedException($"Provider '{provider}' is not supported.");
86+
}
87+
}
88+
89+
}
90+
}
91+
92+

src/Automation/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public static int Main(string[] args)
6565
httpClient.BaseAddress = new Uri(configuration["OLLAMA_HOST"]);
6666
return new OllamaApiClient(httpClient);
6767
})
68+
.AddSingleton<IChatClientFactory, ChatClientFactory>()
6869
.AddSingleton<IDiscordClient>(discordSocketClient)
6970
.AddTransient<IAmazonDynamoDB, AmazonDynamoDBClient>()
7071
.AddResponderServices();

0 commit comments

Comments
 (0)