Skip to content

Commit 1044915

Browse files
committed
refactor: OpenAI integration
* supports configure multiple services * supports select service when generate commit message by OpenAI Signed-off-by: leo <[email protected]>
1 parent 8280287 commit 1044915

File tree

13 files changed

+279
-225
lines changed

13 files changed

+279
-225
lines changed

src/Commands/GenerateCommitMessage.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ public GetDiffContent(string repo, Models.DiffOption opt)
2020
}
2121
}
2222

23-
public GenerateCommitMessage(string repo, List<Models.Change> changes, CancellationToken cancelToken, Action<string> onProgress)
23+
public GenerateCommitMessage(Models.OpenAIService service, string repo, List<Models.Change> changes, CancellationToken cancelToken, Action<string> onProgress)
2424
{
25+
_service = service;
2526
_repo = repo;
2627
_changes = changes;
2728
_cancelToken = cancelToken;
@@ -75,7 +76,7 @@ private string GenerateChangeSummary(Models.Change change)
7576
var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd();
7677
var diff = rs.IsSuccess ? rs.StdOut : "unknown change";
7778

78-
var rsp = Models.OpenAI.Chat(Models.OpenAI.AnalyzeDiffPrompt, $"Here is the `git diff` output: {diff}", _cancelToken);
79+
var rsp = _service.Chat(_service.AnalyzeDiffPrompt, $"Here is the `git diff` output: {diff}", _cancelToken);
7980
if (rsp != null && rsp.Choices.Count > 0)
8081
return rsp.Choices[0].Message.Content;
8182

@@ -84,13 +85,14 @@ private string GenerateChangeSummary(Models.Change change)
8485

8586
private string GenerateSubject(string summary)
8687
{
87-
var rsp = Models.OpenAI.Chat(Models.OpenAI.GenerateSubjectPrompt, $"Here are the summaries changes:\n{summary}", _cancelToken);
88+
var rsp = _service.Chat(_service.GenerateSubjectPrompt, $"Here are the summaries changes:\n{summary}", _cancelToken);
8889
if (rsp != null && rsp.Choices.Count > 0)
8990
return rsp.Choices[0].Message.Content;
9091

9192
return string.Empty;
9293
}
9394

95+
private Models.OpenAIService _service;
9496
private string _repo;
9597
private List<Models.Change> _changes;
9698
private CancellationToken _cancelToken;

src/Models/OpenAI.cs

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
using System.Text.Json.Serialization;
77
using System.Threading;
88

9+
using CommunityToolkit.Mvvm.ComponentModel;
10+
911
namespace SourceGit.Models
1012
{
1113
public class OpenAIChatMessage
@@ -74,44 +76,78 @@ public void AddMessage(string role, string content)
7476
}
7577
}
7678

77-
public static class OpenAI
79+
public class OpenAIService : ObservableObject
7880
{
79-
public static string Server
81+
public string Name
8082
{
81-
get;
82-
set;
83+
get => _name;
84+
set => SetProperty(ref _name, value);
8385
}
8486

85-
public static string ApiKey
87+
public string Server
8688
{
87-
get;
88-
set;
89+
get => _server;
90+
set => SetProperty(ref _server, value);
8991
}
9092

91-
public static string Model
93+
public string ApiKey
9294
{
93-
get;
94-
set;
95+
get => _apiKey;
96+
set => SetProperty(ref _apiKey, value);
97+
}
98+
99+
public string Model
100+
{
101+
get => _model;
102+
set => SetProperty(ref _model, value);
95103
}
96104

97-
public static string AnalyzeDiffPrompt
105+
public string AnalyzeDiffPrompt
98106
{
99-
get;
100-
set;
107+
get => _analyzeDiffPrompt;
108+
set => SetProperty(ref _analyzeDiffPrompt, value);
101109
}
102110

103-
public static string GenerateSubjectPrompt
111+
public string GenerateSubjectPrompt
104112
{
105-
get;
106-
set;
113+
get => _generateSubjectPrompt;
114+
set => SetProperty(ref _generateSubjectPrompt, value);
107115
}
108116

109-
public static bool IsValid
117+
public OpenAIService()
110118
{
111-
get => !string.IsNullOrEmpty(Server) && !string.IsNullOrEmpty(Model);
119+
AnalyzeDiffPrompt = """
120+
You are an expert developer specialist in creating commits.
121+
Provide a super concise one sentence overall changes summary of the user `git diff` output following strictly the next rules:
122+
- Do not use any code snippets, imports, file routes or bullets points.
123+
- Do not mention the route of file that has been change.
124+
- Write clear, concise, and descriptive messages that explain the MAIN GOAL made of the changes.
125+
- Use the present tense and active voice in the message, for example, "Fix bug" instead of "Fixed bug.".
126+
- Use the imperative mood, which gives the message a sense of command, e.g. "Add feature" instead of "Added feature".
127+
- Avoid using general terms like "update" or "change", be specific about what was updated or changed.
128+
- Avoid using terms like "The main goal of", just output directly the summary in plain text
129+
""";
130+
131+
GenerateSubjectPrompt = """
132+
You are an expert developer specialist in creating commits messages.
133+
Your only goal is to retrieve a single commit message.
134+
Based on the provided user changes, combine them in ONE SINGLE commit message retrieving the global idea, following strictly the next rules:
135+
- Assign the commit {type} according to the next conditions:
136+
feat: Only when adding a new feature.
137+
fix: When fixing a bug.
138+
docs: When updating documentation.
139+
style: When changing elements styles or design and/or making changes to the code style (formatting, missing semicolons, etc.) without changing the code logic.
140+
test: When adding or updating tests.
141+
chore: When making changes to the build process or auxiliary tools and libraries.
142+
revert: When undoing a previous commit.
143+
refactor: When restructuring code without changing its external behavior, or is any of the other refactor types.
144+
- Do not add any issues numeration, explain your output nor introduce your answer.
145+
- Output directly only one commit message in plain text with the next format: {type}: {commit_message}.
146+
- Be as concise as possible, keep the message under 50 characters.
147+
""";
112148
}
113149

114-
public static OpenAIChatResponse Chat(string prompt, string question, CancellationToken cancellation)
150+
public OpenAIChatResponse Chat(string prompt, string question, CancellationToken cancellation)
115151
{
116152
var chat = new OpenAIChatRequest() { Model = Model };
117153
chat.AddMessage("system", prompt);
@@ -144,5 +180,12 @@ public static OpenAIChatResponse Chat(string prompt, string question, Cancellati
144180
throw;
145181
}
146182
}
183+
184+
private string _name;
185+
private string _server;
186+
private string _apiKey;
187+
private string _model;
188+
private string _analyzeDiffPrompt;
189+
private string _generateSubjectPrompt;
147190
}
148191
}

src/Resources/Locales/en_US.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,12 +401,12 @@
401401
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">Last year</x:String>
402402
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} years ago</x:String>
403403
<x:String x:Key="Text.Preference" xml:space="preserve">Preference</x:String>
404-
<x:String x:Key="Text.Preference.Advanced" xml:space="preserve">Advanced Options</x:String>
405404
<x:String x:Key="Text.Preference.AI" xml:space="preserve">OPEN AI</x:String>
406405
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyze Diff Prompt</x:String>
407406
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API Key</x:String>
408407
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Generate Subject Prompt</x:String>
409408
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">Model</x:String>
409+
<x:String x:Key="Text.Preference.AI.Name" xml:space="preserve">Name</x:String>
410410
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">Server</x:String>
411411
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">APPEARANCE</x:String>
412412
<x:String x:Key="Text.Preference.Appearance.DefaultFont" xml:space="preserve">Default Font</x:String>

src/Resources/Locales/ru_RU.axaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,6 @@
405405
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">В пролому году</x:String>
406406
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} лет назад</x:String>
407407
<x:String x:Key="Text.Preference" xml:space="preserve">Параметры</x:String>
408-
<x:String x:Key="Text.Preference.Advanced" xml:space="preserve">Расширенные опции</x:String>
409408
<x:String x:Key="Text.Preference.AI" xml:space="preserve">ОТКРЫТЬ ИИ</x:String>
410409
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">Ключ API</x:String>
411410
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">Запрос на анализ различий</x:String>

src/Resources/Locales/zh_CN.axaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,13 @@
404404
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">一年前</x:String>
405405
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0}年前</x:String>
406406
<x:String x:Key="Text.Preference" xml:space="preserve">偏好设置</x:String>
407-
<x:String x:Key="Text.Preference.Advanced" xml:space="preserve">高级设置</x:String>
407+
<x:String x:Key="Text.Preference.AI" xml:space="preserve">OPEN AI</x:String>
408+
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyze Diff Prompt</x:String>
409+
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API密钥</x:String>
410+
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">Generate Subject Prompt</x:String>
411+
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">模型</x:String>
412+
<x:String x:Key="Text.Preference.AI.Name" xml:space="preserve">配置名称</x:String>
413+
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">服务地址</x:String>
408414
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">外观配置</x:String>
409415
<x:String x:Key="Text.Preference.Appearance.DefaultFont" xml:space="preserve">缺省字体</x:String>
410416
<x:String x:Key="Text.Preference.Appearance.DefaultFontSize" xml:space="preserve">默认字体大小</x:String>

src/Resources/Locales/zh_TW.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,12 +403,12 @@
403403
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} 個月前</x:String>
404404
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">一年前</x:String>
405405
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} 年前</x:String>
406-
<x:String x:Key="Text.Preference" xml:space="preserve">偏好設定</x:String>
407406
<x:String x:Key="Text.Preference.Advanced" xml:space="preserve">進階設定</x:String>
408407
<x:String x:Key="Text.Preference.AI" xml:space="preserve">OpenAI</x:String>
409408
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">伺服器</x:String>
410409
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API 金鑰</x:String>
411410
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">模型</x:String>
411+
<x:String x:Key="Text.Preference.AI.Name" xml:space="preserve">名稱</x:String>
412412
<x:String x:Key="Text.Preference.AI.AnalyzeDiffPrompt" xml:space="preserve">分析變更差異提示詞</x:String>
413413
<x:String x:Key="Text.Preference.AI.GenerateSubjectPrompt" xml:space="preserve">產生提交訊息提示詞</x:String>
414414
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">外觀設定</x:String>

src/ViewModels/Preference.cs

Lines changed: 7 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using System.IO;
44
using System.Text.Json;
55
using System.Text.Json.Serialization;
6-
6+
using Avalonia.Collections;
77
using CommunityToolkit.Mvvm.ComponentModel;
88

99
namespace SourceGit.ViewModels
@@ -25,7 +25,6 @@ public static Preference Instance
2525
_instance.PrepareGit();
2626
_instance.PrepareShellOrTerminal();
2727
_instance.PrepareWorkspaces();
28-
_instance.PrepareOpenAIPrompt();
2928

3029
return _instance;
3130
}
@@ -277,71 +276,6 @@ public string ExternalMergeToolPath
277276
set => SetProperty(ref _externalMergeToolPath, value);
278277
}
279278

280-
public string OpenAIServer
281-
{
282-
get => Models.OpenAI.Server;
283-
set
284-
{
285-
if (value != Models.OpenAI.Server)
286-
{
287-
Models.OpenAI.Server = value;
288-
OnPropertyChanged();
289-
}
290-
}
291-
}
292-
293-
public string OpenAIApiKey
294-
{
295-
get => Models.OpenAI.ApiKey;
296-
set
297-
{
298-
if (value != Models.OpenAI.ApiKey)
299-
{
300-
Models.OpenAI.ApiKey = value;
301-
OnPropertyChanged();
302-
}
303-
}
304-
}
305-
306-
public string OpenAIModel
307-
{
308-
get => Models.OpenAI.Model;
309-
set
310-
{
311-
if (value != Models.OpenAI.Model)
312-
{
313-
Models.OpenAI.Model = value;
314-
OnPropertyChanged();
315-
}
316-
}
317-
}
318-
319-
public string OpenAIAnalyzeDiffPrompt
320-
{
321-
get => Models.OpenAI.AnalyzeDiffPrompt;
322-
set
323-
{
324-
if (value != Models.OpenAI.AnalyzeDiffPrompt)
325-
{
326-
Models.OpenAI.AnalyzeDiffPrompt = value;
327-
OnPropertyChanged();
328-
}
329-
}
330-
}
331-
332-
public string OpenAIGenerateSubjectPrompt
333-
{
334-
get => Models.OpenAI.GenerateSubjectPrompt;
335-
set
336-
{
337-
if (value != Models.OpenAI.GenerateSubjectPrompt)
338-
{
339-
Models.OpenAI.GenerateSubjectPrompt = value;
340-
OnPropertyChanged();
341-
}
342-
}
343-
}
344-
345279
public uint StatisticsSampleColor
346280
{
347281
get => _statisticsSampleColor;
@@ -360,6 +294,12 @@ public List<Workspace> Workspaces
360294
set;
361295
} = [];
362296

297+
public AvaloniaList<Models.OpenAIService> OpenAIServices
298+
{
299+
get;
300+
set;
301+
} = [];
302+
363303
public double LastCheckUpdateTime
364304
{
365305
get => _lastCheckUpdateTime;
@@ -554,45 +494,6 @@ private void PrepareWorkspaces()
554494
}
555495
}
556496

557-
private void PrepareOpenAIPrompt()
558-
{
559-
if (string.IsNullOrEmpty(Models.OpenAI.AnalyzeDiffPrompt))
560-
{
561-
Models.OpenAI.AnalyzeDiffPrompt = """
562-
You are an expert developer specialist in creating commits.
563-
Provide a super concise one sentence overall changes summary of the user `git diff` output following strictly the next rules:
564-
- Do not use any code snippets, imports, file routes or bullets points.
565-
- Do not mention the route of file that has been change.
566-
- Write clear, concise, and descriptive messages that explain the MAIN GOAL made of the changes.
567-
- Use the present tense and active voice in the message, for example, "Fix bug" instead of "Fixed bug.".
568-
- Use the imperative mood, which gives the message a sense of command, e.g. "Add feature" instead of "Added feature".
569-
- Avoid using general terms like "update" or "change", be specific about what was updated or changed.
570-
- Avoid using terms like "The main goal of", just output directly the summary in plain text
571-
""";
572-
}
573-
574-
if (string.IsNullOrEmpty(Models.OpenAI.GenerateSubjectPrompt))
575-
{
576-
Models.OpenAI.GenerateSubjectPrompt = """
577-
You are an expert developer specialist in creating commits messages.
578-
Your only goal is to retrieve a single commit message.
579-
Based on the provided user changes, combine them in ONE SINGLE commit message retrieving the global idea, following strictly the next rules:
580-
- Assign the commit {type} according to the next conditions:
581-
feat: Only when adding a new feature.
582-
fix: When fixing a bug.
583-
docs: When updating documentation.
584-
style: When changing elements styles or design and/or making changes to the code style (formatting, missing semicolons, etc.) without changing the code logic.
585-
test: When adding or updating tests.
586-
chore: When making changes to the build process or auxiliary tools and libraries.
587-
revert: When undoing a previous commit.
588-
refactor: When restructuring code without changing its external behavior, or is any of the other refactor types.
589-
- Do not add any issues numeration, explain your output nor introduce your answer.
590-
- Output directly only one commit message in plain text with the next format: {type}: {commit_message}.
591-
- Be as concise as possible, keep the message under 50 characters.
592-
""";
593-
}
594-
}
595-
596497
private RepositoryNode FindNodeRecursive(string id, List<RepositoryNode> collection)
597498
{
598499
foreach (var node in collection)

0 commit comments

Comments
 (0)