feat(chat): 添加深度思考模式支持

refactor
钟良源 3 weeks ago
parent df345447ca
commit 84bd2d1617

@ -41,12 +41,17 @@ document.addEventListener('DOMContentLoaded', () => {
return; return;
} }
// 获取深度思考开关状态
const deepThinkingCheckbox = document.getElementById('deep-thinking-checkbox');
const enableDeepThinking = deepThinkingCheckbox ? deepThinkingCheckbox.checked : false;
// 发送消息 // 发送消息
vscode.postMessage({ vscode.postMessage({
command: 'ask', command: 'ask',
text, text,
fileContent: selectedCodeForContext, fileContent: selectedCodeForContext,
fileContentPath: contextFilePath // 添加文件路径 fileContentPath: contextFilePath, // 添加文件路径
enableDeepThinking: enableDeepThinking // 添加深度思考标志
}); });
// 切换按钮为停止按钮 // 切换按钮为停止按钮

@ -64,46 +64,62 @@ code {
/* 表单区域 */ /* 表单区域 */
#chat-form { #chat-form {
display: flex;
gap: 10px;
margin-top: auto; margin-top: auto;
padding: 10px 0; padding: 10px 0;
} }
.input-container {
display: flex;
align-items: center;
gap: 10px;
padding: 8px;
background-color: var(--vscode-input-background);
border: 1px solid var(--vscode-dropdown-border);
border-radius: 6px;
transition: border-color 0.2s;
}
.input-container:focus-within {
border-color: var(--vscode-focusBorder);
box-shadow: 0 0 0 1px var(--vscode-focusBorder);
}
#user-input { #user-input {
flex: 1; flex: 1;
padding: 8px 12px; padding: 6px 8px;
border: 1px solid var(--vscode-dropdown-border); border: none;
border-radius: 4px; background-color: transparent;
background-color: var(--vscode-input-background);
color: var(--vscode-input-foreground); color: var(--vscode-input-foreground);
font-family: var(--vscode-font-family); font-family: var(--vscode-font-family);
font-size: var(--vscode-font-size); font-size: var(--vscode-font-size);
outline: none;
} }
#user-input:focus { #user-input::placeholder {
outline: none; color: var(--vscode-input-placeholderForeground);
border-color: var(--vscode-focusBorder);
} }
#chat-form button { #chat-form button {
padding: 8px 16px; padding: 6px 16px;
background-color: #007acc; background-color: var(--vscode-button-background);
color: white; color: var(--vscode-button-foreground);
border: none; border: none;
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
font-size: 14px; font-size: 13px;
font-weight: 500;
transition: background-color 0.2s; transition: background-color 0.2s;
white-space: nowrap;
} }
#chat-form button:hover { #chat-form button:hover {
background-color: #005a9e; background-color: var(--vscode-button-hoverBackground);
} }
/* 停止按钮样式 */ /* 停止按钮样式 */
#chat-form button.stop-button { #chat-form button.stop-button {
background-color: #f44336; background-color: #f44336;
color: white;
} }
#chat-form button.stop-button:hover { #chat-form button.stop-button:hover {
@ -501,3 +517,33 @@ code {
color: var(--vscode-descriptionForeground); color: var(--vscode-descriptionForeground);
font-size: 12px; font-size: 12px;
} }
/* 深度思考开关样式 */
.deep-thinking-toggle {
display: flex;
align-items: center;
gap: 6px;
cursor: pointer;
font-size: 12px;
white-space: nowrap;
user-select: none;
padding: 4px 8px;
border-radius: 4px;
transition: background-color 0.2s;
}
.deep-thinking-toggle:hover {
background-color: var(--vscode-list-hoverBackground);
}
.deep-thinking-toggle input[type="checkbox"] {
cursor: pointer;
width: 14px;
height: 14px;
margin: 0;
}
.deep-thinking-toggle .toggle-label {
color: var(--vscode-foreground);
font-weight: 500;
}

@ -74,13 +74,14 @@ export class MessageHandler {
const fileContent = message.fileContent; const fileContent = message.fileContent;
const fileName = message.fileContentPath ? path.basename(message.fileContentPath) : "current_file.txt"; const fileName = message.fileContentPath ? path.basename(message.fileContentPath) : "current_file.txt";
const history = currentSessionHistory; const history = currentSessionHistory;
const enableDeepThinking = message.enableDeepThinking || false;
currentSessionHistory = [...history, {role: 'user', content: question}]; currentSessionHistory = [...history, {role: 'user', content: question}];
this.provider._postMessage({command: 'addMessage', role: 'user', content: question}); this.provider._postMessage({command: 'addMessage', role: 'user', content: question});
try { try {
const response = await callQwenAPI(question, history, fileContent, this.context, fileName); const response = await callQwenAPI(question, history, fileContent, this.context, fileName, enableDeepThinking);
// 发送开始流式传输的消息 // 发送开始流式传输的消息
this.provider._postMessage({command: 'startStream', role: 'assistant'}); this.provider._postMessage({command: 'startStream', role: 'assistant'});
@ -98,7 +99,7 @@ export class MessageHandler {
if (done) break; if (done) break;
const chunk = decoder.decode(value, {stream: true}); const chunk = decoder.decode(value, {stream: true});
console.log("chunk:",chunk)
// 检查是否包含event: end事件 // 检查是否包含event: end事件
let processedChunk = chunk; let processedChunk = chunk;
if (chunk.includes('event: end')) { if (chunk.includes('event: end')) {

@ -2,69 +2,74 @@ import vscode from "vscode";
import path from "path"; import path from "path";
// 获取API配置的函数 // 获取API配置的函数
function getApiConfig(context: vscode.ExtensionContext) { function getApiConfig(context: vscode.ExtensionContext, enableDeepThinking: boolean = false) {
// 从用户配置中获取设置 // 从用户配置中获取设置
const config = vscode.workspace.getConfiguration('ai-chat.api'); const config = vscode.workspace.getConfiguration('ai-chat.api');
const userUrl = config.get<string>('url'); const userUrl = config.get<string>('url');
const userBaseUrl = config.get<string>('baseUrl'); const userBaseUrl = config.get<string>('baseUrl');
const userApiKey = config.get<string>('key'); const userApiKey = config.get<string>('key');
// 如果用户配置了完整URL优先使用 // 根据是否启用深度思考选择不同的端点
if (userUrl) { const endpoint = enableDeepThinking
return { ? '/comp/api/v1/chat/completions-stream-cot'
url: userUrl, : '/comp/api/v1/chat/completions-stream';
apiKey: userApiKey || 'dev-token'
}; // 如果用户配置了完整URL优先使用
} if (userUrl) {
return {
// 如果用户配置了基础URL使用基础URL加上默认路径 url: userUrl,
if (userBaseUrl) { apiKey: userApiKey || 'dev-token'
return { };
url: `${userBaseUrl}/comp/api/v1/chat/completions-stream`,
apiKey: userApiKey || 'dev-token'
};
}
// 检测code-server环境
const codeServerUrl = process.env.CODE_SERVER_URL;
if (codeServerUrl) {
// 在code-server环境中尝试使用相对路径或者基于当前地址的API地址
try {
const baseUrl = new URL(codeServerUrl);
return {
url: `${baseUrl.origin}/comp/api/v1/chat/completions-stream`,
apiKey: userApiKey || 'dev-token'
};
} catch (e) {
// 如果解析失败,使用默认地址
} }
}
// 如果用户配置了基础URL使用基础URL加上对应端点
// 检查CODE_SERVER_CONFIG环境变量 if (userBaseUrl) {
const codeServerConfig = process.env.CODE_SERVER_CONFIG; return {
if (codeServerConfig) { url: `${userBaseUrl}${endpoint}`,
try {
// 尝试从配置中解析bindAddr
const configObj = JSON.parse(codeServerConfig);
if (configObj.bindAddr) {
const [host, port] = configObj.bindAddr.split(':');
if (host && port) {
return {
url: `http://${host}:${port}/comp/api/v1/chat/completions-stream`,
apiKey: userApiKey || 'dev-token' apiKey: userApiKey || 'dev-token'
}; };
}
// 检测code-server环境
const codeServerUrl = process.env.CODE_SERVER_URL;
if (codeServerUrl) {
// 在code-server环境中尝试使用相对路径或者基于当前地址的API地址
try {
const baseUrl = new URL(codeServerUrl);
return {
url: `${baseUrl.origin}${endpoint}`,
apiKey: userApiKey || 'dev-token'
};
} catch (e) {
// 如果解析失败,使用默认地址
} }
}
} catch (e) {
// 解析失败则继续使用默认配置
} }
}
// 检查CODE_SERVER_CONFIG环境变量
// 默认配置 const codeServerConfig = process.env.CODE_SERVER_CONFIG;
return { if (codeServerConfig) {
url: 'https://p13-ai.ngsk.tech:7001/comp/api/v1/chat/completions-stream', try {
apiKey: userApiKey || 'dev-token' // 尝试从配置中解析bindAddr
}; const configObj = JSON.parse(codeServerConfig);
if (configObj.bindAddr) {
const [host, port] = configObj.bindAddr.split(':');
if (host && port) {
return {
url: `http://${host}:${port}${endpoint}`,
apiKey: userApiKey || 'dev-token'
};
}
}
} catch (e) {
// 解析失败则继续使用默认配置
}
}
// 默认配置
return {
url: `https://p13-ai.ngsk.tech:7001${endpoint}`,
apiKey: userApiKey || 'dev-token'
};
} }
export async function callQwenAPI( export async function callQwenAPI(
@ -72,9 +77,10 @@ export async function callQwenAPI(
history: any[], history: any[],
fileContent: string, fileContent: string,
context: vscode.ExtensionContext, context: vscode.ExtensionContext,
filename: string = "" filename: string = "",
enableDeepThinking: boolean = false
): Promise<any> { ): Promise<any> {
const { url, apiKey } = getApiConfig(context); const {url, apiKey} = getApiConfig(context, enableDeepThinking);
const messages = [ const messages = [
{ {
@ -91,6 +97,21 @@ export async function callQwenAPI(
console.log("messages:", messages) console.log("messages:", messages)
try { try {
const requestBody: any = {
model: 'Qwen2_5_Coder',
messages,
context_file: {
filename: filename,
section_type: "code",
content: fileContent
}
};
// 如果启用深度思考,添加 enable_cot 参数
if (enableDeepThinking) {
requestBody.enable_cot = true;
}
const params = { const params = {
method: 'POST', method: 'POST',
headers: { headers: {
@ -98,15 +119,7 @@ export async function callQwenAPI(
'Content-Type': 'application/json', 'Content-Type': 'application/json',
// 'Accept': 'text/event-stream' // 'Accept': 'text/event-stream'
}, },
body: JSON.stringify({ body: JSON.stringify(requestBody)
model: 'Qwen2_5_Coder',
messages,
context_file: {
filename: filename,
section_type: "code",
content: fileContent
}
})
} }
console.log("params:", JSON.stringify(params)) console.log("params:", JSON.stringify(params))

@ -75,8 +75,14 @@ export function getWebviewContent(styleUri: vscode.Uri, scriptUri: vscode.Uri,hi
<!-- --> <!-- -->
<form id="chat-form"> <form id="chat-form">
<input type="text" id="user-input" placeholder="输入你的问题..."/> <div class="input-container">
<button type="submit" id="send-btn"></button> <input type="text" id="user-input" placeholder="输入你的问题..."/>
<label class="deep-thinking-toggle" title="启用深度思考模式">
<input type="checkbox" id="deep-thinking-checkbox"/>
<span class="toggle-label"></span>
</label>
<button type="submit" id="send-btn"></button>
</div>
</form> </form>
<div id="loading" class="hidden">AI ...</div> <div id="loading" class="hidden">AI ...</div>
</div> </div>

Loading…
Cancel
Save