Skip to content

Commit ef2e0a8

Browse files
authored
fix: Ignore the Chain-of-Thought in AI response (#952)
- Improve chat response processing to handle thinking patterns using regular expressions. - Migrate server value by removing trailing '/chat/completions' path.
1 parent 8cc056d commit ef2e0a8

File tree

2 files changed

+78
-10
lines changed

2 files changed

+78
-10
lines changed

src/Commands/GenerateCommitMessage.cs

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Text;
4+
using System.Text.RegularExpressions;
45
using System.Threading;
56

67
using Avalonia.Threading;
@@ -48,16 +49,18 @@ public void Exec()
4849
var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd();
4950
if (rs.IsSuccess)
5051
{
52+
var hasFirstValidChar = false;
53+
var thinkingBuffer = new StringBuilder();
5154
_service.Chat(
5255
_service.AnalyzeDiffPrompt,
5356
$"Here is the `git diff` output: {rs.StdOut}",
5457
_cancelToken,
5558
update =>
56-
{
57-
responseBuilder.Append(update);
58-
summaryBuilder.Append(update);
59-
_onResponse?.Invoke("Waiting for pre-file analyzing to complated...\n\n" + responseBuilder.ToString());
60-
});
59+
ProcessChatResponse(update, ref hasFirstValidChar, thinkingBuffer,
60+
(responseBuilder, text =>
61+
_onResponse?.Invoke(
62+
$"Waiting for pre-file analyzing to completed...\n\n{text}")),
63+
(summaryBuilder, null)));
6164
}
6265

6366
responseBuilder.Append("\n");
@@ -71,26 +74,83 @@ public void Exec()
7174

7275
var responseBody = responseBuilder.ToString();
7376
var subjectBuilder = new StringBuilder();
77+
var hasSubjectFirstValidChar = false;
78+
var subjectThinkingBuffer = new StringBuilder();
7479
_service.Chat(
7580
_service.GenerateSubjectPrompt,
7681
$"Here are the summaries changes:\n{summaryBuilder}",
7782
_cancelToken,
7883
update =>
79-
{
80-
subjectBuilder.Append(update);
81-
_onResponse?.Invoke($"{subjectBuilder}\n\n{responseBody}");
82-
});
84+
ProcessChatResponse(update, ref hasSubjectFirstValidChar, subjectThinkingBuffer,
85+
(subjectBuilder, text => _onResponse?.Invoke($"{text}\n\n{responseBody}"))));
8386
}
8487
catch (Exception e)
8588
{
8689
Dispatcher.UIThread.Post(() => App.RaiseException(_repo, $"Failed to generate commit message: {e}"));
8790
}
8891
}
8992

93+
private void ProcessChatResponse(
94+
string update,
95+
ref bool hasFirstValidChar,
96+
StringBuilder thinkingBuffer,
97+
params (StringBuilder builder, Action<string> callback)[] outputs)
98+
{
99+
if (!hasFirstValidChar)
100+
{
101+
update = update.TrimStart();
102+
if (string.IsNullOrEmpty(update))
103+
return;
104+
if (update.StartsWith("<", StringComparison.Ordinal))
105+
thinkingBuffer.Append(update);
106+
hasFirstValidChar = true;
107+
}
108+
109+
if (thinkingBuffer.Length > 0)
110+
thinkingBuffer.Append(update);
111+
112+
if (thinkingBuffer.Length > 15)
113+
{
114+
var match = REG_COT.Match(thinkingBuffer.ToString());
115+
if (match.Success)
116+
{
117+
update = REG_COT.Replace(thinkingBuffer.ToString(), "").TrimStart();
118+
if (update.Length > 0)
119+
{
120+
foreach (var output in outputs)
121+
output.builder.Append(update);
122+
thinkingBuffer.Clear();
123+
}
124+
return;
125+
}
126+
127+
match = REG_THINK_START.Match(thinkingBuffer.ToString());
128+
if (!match.Success)
129+
{
130+
foreach (var output in outputs)
131+
output.builder.Append(thinkingBuffer);
132+
thinkingBuffer.Clear();
133+
return;
134+
}
135+
}
136+
137+
if (thinkingBuffer.Length == 0)
138+
{
139+
foreach (var output in outputs)
140+
{
141+
output.builder.Append(update);
142+
output.callback?.Invoke(output.builder.ToString());
143+
}
144+
}
145+
}
146+
90147
private Models.OpenAIService _service;
91148
private string _repo;
92149
private List<Models.Change> _changes;
93150
private CancellationToken _cancelToken;
94151
private Action<string> _onResponse;
152+
153+
private static readonly Regex REG_COT = new(@"^<(think|thought|thinking|thought_chain)>(.*?)</\1>", RegexOptions.Singleline);
154+
private static readonly Regex REG_THINK_START = new(@"^<(think|thought|thinking|thought_chain)>", RegexOptions.Singleline);
95155
}
96156
}

src/Models/OpenAI.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,15 @@ public string Name
1919
public string Server
2020
{
2121
get => _server;
22-
set => SetProperty(ref _server, value);
22+
set
23+
{
24+
// migrate old server value
25+
if (!string.IsNullOrEmpty(value) && value.EndsWith("/chat/completions", StringComparison.Ordinal))
26+
{
27+
value = value.Substring(0, value.Length - "/chat/completions".Length);
28+
}
29+
SetProperty(ref _server, value);
30+
}
2331
}
2432

2533
public string ApiKey

0 commit comments

Comments
 (0)