add: 为AI设置增加了thinking的开关

This commit is contained in:
rarnu 2026-05-12 01:16:40 +08:00
parent ab1b4ae227
commit 4f0a13f24f
5 changed files with 65 additions and 6 deletions

View File

@ -74,6 +74,12 @@ pub struct AiConfig {
pub proxy_enabled: bool,
#[serde(default)]
pub proxy_url: String,
#[serde(default = "default_enable_thinking")]
pub enable_thinking: bool,
}
fn default_enable_thinking() -> bool {
true
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -281,17 +287,22 @@ pub async fn call_openai_compatible(client: &reqwest::Client, request: AiComplet
let mut messages = vec![json!({ "role": "system", "content": request.system_prompt })];
messages.extend(request.messages.iter().map(|message| json!({ "role": message.role, "content": message.content })));
let body = json!({
let mut body_obj = json!({
"model": request.config.model,
"messages": messages,
"max_tokens": request.max_tokens.unwrap_or(2048),
"temperature": request.temperature.unwrap_or(0.2),
});
if !request.config.enable_thinking {
body_obj["extra_body"] = json!({
"chat_template_kwargs": { "enable_thinking": false }
});
}
let res = client
.post(&resolve_endpoint(&request.config))
.headers(headers)
.json(&body)
.json(&body_obj)
.send()
.await
.map_err(|e| format!("AI request failed: {e}"))?;
@ -519,18 +530,23 @@ async fn stream_openai(
let mut messages = vec![json!({ "role": "system", "content": request.system_prompt })];
messages.extend(request.messages.iter().map(|m| json!({ "role": m.role, "content": m.content })));
let body = json!({
let mut body_obj = json!({
"model": request.config.model,
"messages": messages,
"max_tokens": request.max_tokens.unwrap_or(2048),
"temperature": request.temperature.unwrap_or(0.2),
"stream": true,
});
if !request.config.enable_thinking {
body_obj["extra_body"] = json!({
"chat_template_kwargs": { "enable_thinking": false }
});
}
let res = client
.post(&resolve_endpoint(&request.config))
.headers(headers)
.json(&body)
.json(&body_obj)
.send()
.await
.map_err(|e| format!("AI request failed: {e}"))?;
@ -752,6 +768,7 @@ mod tests {
assert_eq!(config.proxy_enabled, false);
assert_eq!(config.proxy_url, "");
assert_eq!(config.enable_thinking, true);
}
#[test]
@ -764,6 +781,7 @@ mod tests {
api_style: AiApiStyle::Completions,
proxy_enabled: true,
proxy_url: "not a proxy url".to_string(),
enable_thinking: true,
};
let err = build_ai_http_client(&config, 1).unwrap_err();

View File

@ -2,11 +2,12 @@
import { ref, watch, shallowRef, computed } from "vue";
import type { EditorView as EditorViewType } from "@codemirror/view";
import { useI18n } from "vue-i18n";
import { FolderOpen, Loader2, Settings, Trash2 } from "lucide-vue-next";
import { CircleHelp, FolderOpen, Loader2, Settings, Trash2 } from "lucide-vue-next";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Separator } from "@/components/ui/separator";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
@ -298,6 +299,9 @@ const aiEditModel = ref(settingsStore.aiConfig.model);
const aiEditApiStyle = ref<AiApiStyle>(settingsStore.aiConfig.apiStyle || "completions");
const aiEditProxyEnabled = ref(!!settingsStore.aiConfig.proxyEnabled);
const aiEditProxyUrl = ref(settingsStore.aiConfig.proxyUrl || "");
const aiEditEnableThinking = ref(settingsStore.aiConfig.enableThinking ?? true);
const aiCompletionsMode = computed(() => aiEditApiStyle.value === "completions");
const aiTesting = ref(false);
const aiTestResult = ref<"" | "success" | "error">("");
@ -311,6 +315,7 @@ function syncAiEditState() {
aiEditApiStyle.value = settingsStore.aiConfig.apiStyle || "completions";
aiEditProxyEnabled.value = !!settingsStore.aiConfig.proxyEnabled;
aiEditProxyUrl.value = settingsStore.aiConfig.proxyUrl || "";
aiEditEnableThinking.value = settingsStore.aiConfig.enableThinking ?? true;
aiTestResult.value = "";
aiTestError.value = "";
}
@ -329,7 +334,8 @@ function aiHasChanges(): boolean {
aiEditModel.value !== settingsStore.aiConfig.model ||
aiEditApiStyle.value !== (settingsStore.aiConfig.apiStyle || "completions") ||
aiEditProxyEnabled.value !== !!settingsStore.aiConfig.proxyEnabled ||
aiEditProxyUrl.value !== (settingsStore.aiConfig.proxyUrl || "")
aiEditProxyUrl.value !== (settingsStore.aiConfig.proxyUrl || "") ||
aiEditEnableThinking.value !== (settingsStore.aiConfig.enableThinking ?? true)
);
}
@ -342,6 +348,7 @@ function aiApplySettings() {
apiStyle: aiEditApiStyle.value,
proxyEnabled: aiEditProxyEnabled.value,
proxyUrl: aiEditProxyUrl.value,
enableThinking: aiEditEnableThinking.value,
});
}
@ -718,6 +725,29 @@ watch(
</div>
</div>
<div class="grid grid-cols-3 items-center gap-3">
<Label class="text-right text-xs">{{ t("ai.enableThinking") }}</Label>
<div class="col-span-2 flex items-center gap-2">
<label class="flex items-center gap-2 text-xs text-muted-foreground">
<input
v-model="aiEditEnableThinking"
type="checkbox"
class="h-4 w-4 shrink-0 accent-primary"
:disabled="!aiCompletionsMode"
/>
{{ aiEditEnableThinking ? t("ai.enableThinkingOn") : t("ai.enableThinkingOff") }}
</label>
<Popover>
<PopoverTrigger as-child>
<CircleHelp class="h-3.5 w-3.5 cursor-help text-muted-foreground hover:text-foreground" />
</PopoverTrigger>
<PopoverContent class="max-w-[320px] text-xs leading-relaxed" side="top" align="start">
{{ t("ai.enableThinkingHint") }}
</PopoverContent>
</Popover>
</div>
</div>
<div class="grid grid-cols-3 items-center gap-3">
<Label class="text-right text-xs">{{ t("ai.proxy") }}</Label>
<label class="col-span-2 flex items-center gap-2 text-xs text-muted-foreground">

View File

@ -481,6 +481,11 @@ export default {
proxyUrl: "Proxy URL",
settingsHint:
"The config is stored in the local app data directory. Requests are sent by the Tauri backend instead of directly from the frontend.",
enableThinking: "Thinking",
enableThinkingOn: "Enabled",
enableThinkingOff: "Disabled",
enableThinkingHint:
"This option only takes effect on /chat/completions APIs and supported models. When disabled, it can significantly reduce token usage, but the quality of generated results may decrease slightly.",
actions: {
generate: "Generate SQL",
explain: "Explain SQL",

View File

@ -471,6 +471,11 @@ export default {
proxyEnable: "AI 请求通过代理发送",
proxyUrl: "代理地址",
settingsHint: "配置会保存在本机应用数据目录中。请求由 Tauri 后端发出,避免在前端直接暴露给模型服务。",
enableThinking: "Thinking",
enableThinkingOn: "已启用",
enableThinkingOff: "已禁用",
enableThinkingHint:
"此选项仅对 /chat/completions API 且部分支持的模型生效。设为禁用后可大幅节省 token但生成结果质量可能会略微下降。",
actions: {
generate: "生成 SQL",
explain: "解释 SQL",

View File

@ -13,6 +13,7 @@ export interface AiConfig {
apiStyle: AiApiStyle;
proxyEnabled?: boolean;
proxyUrl?: string;
enableThinking?: boolean;
}
const defaultConfigs: Record<AiProvider, Omit<AiConfig, "apiKey">> = {