Skip to content

Commit 75aa553

Browse files
committed
修复续传功能的bug
1 parent c9e34f1 commit 75aa553

File tree

1 file changed

+63
-30
lines changed

1 file changed

+63
-30
lines changed

src/deepseekApi.ts

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,21 @@ function getDeepSeekApiKey(): string | null {
1515
return apiKey;
1616
}
1717

18+
/**
19+
* 调用 DeepSeek API
20+
* @param userContent 用户输入内容
21+
* @param systemContent 系统提示内容
22+
* @param outputChannel 输出通道,用于实时显示流式内容
23+
* @param streamMode 是否启用流式模式
24+
* @param endstring 结束字符串,用于检查输出是否包含特定字符串
25+
* @returns API 返回的完整内容
26+
*/
1827
async function callDeepSeekApi(
1928
userContent: string,
2029
systemContent: string = 'You are a helpful assistant.',
2130
outputChannel?: vscode.OutputChannel,
22-
streamMode: boolean = true
31+
streamMode: boolean = true,
32+
endstring?: string
2333
): Promise<string | null> {
2434
const apiKey = getDeepSeekApiKey();
2535
if (!apiKey) {
@@ -42,9 +52,11 @@ async function callDeepSeekApi(
4252
{ role: 'user', content: userContent },
4353
];
4454
let fullResponse = '';
45-
let continueResponse = true;
55+
let maxAttempts = 5;
56+
let attempts = 0;
4657

47-
while (continueResponse) {
58+
while (attempts < maxAttempts) {
59+
attempts++;
4860
const response = await openai.chat.completions.create({
4961
model: 'deepseek-chat',
5062
messages: messages_body,
@@ -53,41 +65,53 @@ async function callDeepSeekApi(
5365
temperature: 0
5466
});
5567

68+
let chunkResponse = '';
69+
let finishReason: string | null = null;
70+
5671
if (streamMode) {
57-
let lastChunk: any = null;
5872
for await (const chunk of response as AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>) {
5973
const content = chunk.choices[0]?.delta?.content || '';
60-
fullResponse += content;
74+
chunkResponse += content;
6175
if (outputChannel) {
6276
outputChannel.append(content);
6377
}
64-
lastChunk = chunk;
65-
}
66-
// 检查最后的 finish_reason
67-
if (lastChunk && lastChunk.choices[0].finish_reason === 'length') {
68-
// 需要继续
69-
messages_body.push({ role: 'user', content: 'Please continue.' });
70-
} else {
71-
continueResponse = false;
78+
finishReason = chunk.choices[0]?.finish_reason || null;
7279
}
7380
} else {
74-
fullResponse = (response as OpenAI.Chat.Completions.ChatCompletion).choices[0].message.content || "";
81+
const completion = response as OpenAI.Chat.Completions.ChatCompletion;
82+
chunkResponse = completion.choices[0].message.content || "";
83+
finishReason = completion.choices[0].finish_reason || null;
7584
if (outputChannel) {
76-
outputChannel.append(fullResponse);
77-
}
78-
if ((response as OpenAI.Chat.Completions.ChatCompletion).choices[0].finish_reason === 'length') {
79-
// 需要继续
80-
messages_body.push({ role: 'user', content: 'Please continue.' });
81-
} else {
82-
continueResponse = false;
85+
outputChannel.append(chunkResponse);
8386
}
8487
}
88+
89+
// 累积完整响应
90+
fullResponse += chunkResponse;
91+
92+
// 检查终止条件
93+
const shouldContinue =
94+
finishReason === 'length' ||
95+
(endstring && !fullResponse.includes(endstring));
96+
97+
if (!shouldContinue) {break};
98+
99+
// 准备下一次请求
100+
messages_body.push(
101+
{ role: 'assistant', content: fullResponse },
102+
{ role: 'user', content: '你的输出被截断了,请继续输出剩余部分:' }
103+
);
104+
}
105+
106+
// 最终检查
107+
if (endstring && !fullResponse.includes(endstring)) {
108+
vscode.window.showWarningMessage('响应未包含结束标记');
85109
}
86110

87111
return fullResponse;
88112

89113
} catch (error) {
90-
vscode.window.showErrorMessage('Failed to call DeepSeek API: ' + (error as Error).message);
114+
vscode.window.showErrorMessage('API调用失败: ' + (error as Error).message);
91115
return null;
92116
}
93117
}
@@ -121,14 +145,24 @@ ${getCvbFormatDescription()}
121145
${cvbContent}
122146
`;
123147

124-
return callDeepSeekApi(requestContent, undefined, outputChannel, true);
148+
return callDeepSeekApi(requestContent, undefined, outputChannel, true, '## END_CVB'); // 添加结束字符串
125149
}
126150

151+
/**
152+
* 清理文件名
153+
* @param str 原始字符串
154+
* @returns 清理后的文件名
155+
*/
127156
function cleanFilename(str: string) {
128-
// Replace invalid filename characters for Windows with underscores
157+
// 替换 Windows 文件名中的非法字符
129158
return str.replace(/[\\/:*?"<>|]/g, '_');
130159
}
131160

161+
/**
162+
* 根据用户需求生成文件名
163+
* @param userRequest 用户需求
164+
* @returns 生成的文件名
165+
*/
132166
export async function generateFilenameFromRequest(userRequest: string): Promise<string> {
133167
const summaryResponse = await callDeepSeekApi(
134168
`请简单概括一下需求,输出字符串作为文件名。如果描述里有版本名称,这个名称一定要保留并放在开头。 需求:"${userRequest}"`,
@@ -140,16 +174,15 @@ export async function generateFilenameFromRequest(userRequest: string): Promise<
140174
let summary = summaryResponse || '';
141175
console.log('Raw Summary:', summary);
142176

143-
// Clean the summary
177+
// 清理文件名
144178
summary = cleanFilename(summary);
145-
summary = summary.replace(/^\.+|\.+$/g, ''); // Remove leading/trailing dots
146-
summary = summary.replace(/^ +| +$/g, ''); // Remove leading/trailing spaces
147-
summary = summary.substring(0, 15); // Truncate to 15 characters
179+
summary = summary.replace(/^\.+|\.+$/g, ''); // 移除开头和结尾的点
180+
summary = summary.replace(/^ +| +$/g, ''); // 移除开头和结尾的空格
181+
summary = summary.substring(0, 15); // 截取前15个字符
148182

149183
if (summary.length === 0) {
150184
summary = 'summary';
151185
}
152186

153187
return summary;
154-
}
155-
188+
}

0 commit comments

Comments
 (0)