Skip to content

Commit e684d71

Browse files
committed
refactor: dynamic loading and choosing AI model in assistant dialog (#2228)
Signed-off-by: leo <longshuang@msn.cn>
1 parent 7ca1c55 commit e684d71

23 files changed

Lines changed: 163 additions & 39 deletions

src/AI/Agent.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ public Agent(Service service)
1717
public async Task GenerateCommitMessageAsync(string repo, string changeList, Action<string> onUpdate, CancellationToken cancellation)
1818
{
1919
var chatClient = _service.GetChatClient();
20+
if (chatClient == null)
21+
throw new Exception("Failed to fetch available models from this service. Please check your configuration and try again.");
22+
2023
var options = new ChatCompletionOptions() { Tools = { ChatTools.GetDetailChangesInFile } };
2124

2225
var userMessageBuilder = new StringBuilder();

src/AI/Service.cs

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,98 @@
11
using System;
22
using System.ClientModel;
3+
using System.Collections.Generic;
4+
using System.Text.Json.Serialization;
5+
using System.Threading.Tasks;
36
using Azure.AI.OpenAI;
7+
using CommunityToolkit.Mvvm.ComponentModel;
48
using OpenAI;
59
using OpenAI.Chat;
610

711
namespace SourceGit.AI
812
{
9-
public class Service
13+
public class Service : ObservableObject
1014
{
11-
public string Name { get; set; } = string.Empty;
12-
public string Server { get; set; } = string.Empty;
13-
public string Model { get; set; } = string.Empty;
14-
public string ApiKey { get; set; } = string.Empty;
15-
public bool ReadApiKeyFromEnv { get; set; } = false;
16-
public string AdditionalPrompt { get; set; } = string.Empty;
15+
public string Name
16+
{
17+
get => _name;
18+
set => SetProperty(ref _name, value);
19+
}
20+
21+
public string Server
22+
{
23+
get;
24+
set;
25+
} = string.Empty;
26+
27+
public string ApiKey
28+
{
29+
get;
30+
set;
31+
} = string.Empty;
32+
33+
public bool ReadApiKeyFromEnv
34+
{
35+
get;
36+
set;
37+
} = false;
38+
39+
public string AdditionalPrompt
40+
{
41+
get;
42+
set;
43+
} = string.Empty;
44+
45+
[JsonIgnore]
46+
public List<string> AvailableModels
47+
{
48+
get;
49+
private set;
50+
} = [];
51+
52+
public string Model
53+
{
54+
get;
55+
set;
56+
} = string.Empty;
57+
58+
public async Task<List<string>> FetchAvailableModelsAsync()
59+
{
60+
var credential = new ApiKeyCredential(ReadApiKeyFromEnv ? Environment.GetEnvironmentVariable(ApiKey) : ApiKey);
61+
var client = Server.Contains("openai.azure.com/", StringComparison.Ordinal)
62+
? new AzureOpenAIClient(new Uri(Server), credential)
63+
: new OpenAIClient(credential, new() { Endpoint = new Uri(Server) });
64+
65+
var allModels = client.GetOpenAIModelClient().GetModels();
66+
AvailableModels = new List<string>();
67+
foreach (var model in allModels.Value)
68+
AvailableModels.Add(model.Id);
69+
70+
if (AvailableModels.Count > 0)
71+
{
72+
if (string.IsNullOrEmpty(Model) || !AvailableModels.Contains(Model))
73+
Model = AvailableModels[0];
74+
}
75+
else
76+
{
77+
Model = null;
78+
}
79+
80+
return AvailableModels;
81+
}
1782

1883
public ChatClient GetChatClient()
1984
{
85+
if (string.IsNullOrEmpty(Model))
86+
return null;
87+
2088
var credential = new ApiKeyCredential(ReadApiKeyFromEnv ? Environment.GetEnvironmentVariable(ApiKey) : ApiKey);
2189
var client = Server.Contains("openai.azure.com/", StringComparison.Ordinal)
2290
? new AzureOpenAIClient(new Uri(Server), credential)
2391
: new OpenAIClient(credential, new() { Endpoint = new Uri(Server) });
2492

2593
return client.GetChatClient(Model);
2694
}
95+
96+
private string _name = string.Empty;
2797
}
2898
}

src/Resources/Locales/de_DE.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente</x:String>
602602
<x:String x:Key="Text.Preferences" xml:space="preserve">Einstellungen</x:String>
603603
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
604604
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API-Schlüssel</x:String>
605-
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modell</x:String>
605+
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Modell</x:String>
606606
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Name</x:String>
607607
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">Der eingegebene Wert ist der Name der Umgebungsvariable, aus der der API-Schlüssel gelesen wird</x:String>
608608
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>

src/Resources/Locales/en_US.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">Create New Branch</x:String>
1919
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">Existing Branch</x:String>
2020
<x:String x:Key="Text.AIAssistant" xml:space="preserve">AI Assistant</x:String>
21+
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">MODEL</x:String>
2122
<x:String x:Key="Text.AIAssistant.Regen" xml:space="preserve">RE-GENERATE</x:String>
2223
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Use AI to generate commit message</x:String>
2324
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">Use</x:String>
@@ -616,7 +617,6 @@
616617
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
617618
<x:String x:Key="Text.Preferences.AI.AdditionalPrompt" xml:space="preserve">Additional Prompt (Use `-` to list your requirements)</x:String>
618619
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API Key</x:String>
619-
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Model</x:String>
620620
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Name</x:String>
621621
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">Entered value is the name to load API key from ENV</x:String>
622622
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>

src/Resources/Locales/es_ES.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@
616616
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">OPEN AI</x:String>
617617
<x:String x:Key="Text.Preferences.AI.AdditionalPrompt" xml:space="preserve">Prompt adicional (Usa `-` para listar tus requerimientos)</x:String>
618618
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">Clave API</x:String>
619-
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modelo</x:String>
619+
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Modelo</x:String>
620620
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Nombre</x:String>
621621
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">El valor ingresado es el nombre de la clave API a cargar desde ENV</x:String>
622622
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Servidor</x:String>

src/Resources/Locales/fr_FR.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@
561561
<x:String x:Key="Text.Preferences" xml:space="preserve">Préférences</x:String>
562562
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">IA</x:String>
563563
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">Clé d'API</x:String>
564-
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modèle</x:String>
564+
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Modèle</x:String>
565565
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Nom</x:String>
566566
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">La valeur saisie est le nom pour charger la clé API depuis l'ENV</x:String>
567567
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Serveur</x:String>

src/Resources/Locales/id_ID.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@
535535
<x:String x:Key="Text.Preferences" xml:space="preserve">Preferensi</x:String>
536536
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
537537
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API Key</x:String>
538-
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Model</x:String>
538+
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Model</x:String>
539539
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Nama</x:String>
540540
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">Nilai yang dimasukkan adalah nama untuk memuat API key dari ENV</x:String>
541541
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>

src/Resources/Locales/it_IT.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ ${pure_files:N} Come ${files:N}, ma senza cartelle</x:String>
598598
<x:String x:Key="Text.Preferences" xml:space="preserve">Preferenze</x:String>
599599
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
600600
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">Chiave API</x:String>
601-
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modello</x:String>
601+
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Modello</x:String>
602602
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Nome</x:String>
603603
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">Il valore inserito è il nome per caricare la chiave API da ENV</x:String>
604604
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>

src/Resources/Locales/ja_JP.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@
604604
<x:String x:Key="Text.Preferences" xml:space="preserve">設定</x:String>
605605
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
606606
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API キー</x:String>
607-
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">モデル</x:String>
607+
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">モデル</x:String>
608608
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">名前</x:String>
609609
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">この値を環境変数の名前とし、そこから API キーを読み込む</x:String>
610610
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">サーバー</x:String>

src/Resources/Locales/ko_KR.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@
537537
<x:String x:Key="Text.Preferences" xml:space="preserve">환경설정</x:String>
538538
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
539539
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API 키</x:String>
540-
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">모델</x:String>
540+
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">모델</x:String>
541541
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">이름</x:String>
542542
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">입력된 값은 환경변수(ENV)에서 API 키를 불러올 이름입니다</x:String>
543543
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">서버</x:String>

0 commit comments

Comments
 (0)