From 4f0a13f24f44549294f4f5241b43de5e16f44489 Mon Sep 17 00:00:00 2001 From: rarnu Date: Tue, 12 May 2026 01:16:40 +0800 Subject: [PATCH] =?UTF-8?q?add:=20=E4=B8=BAAI=E8=AE=BE=E7=BD=AE=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BA=86thinking=E7=9A=84=E5=BC=80=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/dbx-core/src/ai.rs | 26 +++++++++++--- .../editor/EditorSettingsDialog.vue | 34 +++++++++++++++++-- src/i18n/locales/en.ts | 5 +++ src/i18n/locales/zh-CN.ts | 5 +++ src/stores/settingsStore.ts | 1 + 5 files changed, 65 insertions(+), 6 deletions(-) diff --git a/crates/dbx-core/src/ai.rs b/crates/dbx-core/src/ai.rs index a8923eb57..77a11e0cc 100644 --- a/crates/dbx-core/src/ai.rs +++ b/crates/dbx-core/src/ai.rs @@ -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(); diff --git a/src/components/editor/EditorSettingsDialog.vue b/src/components/editor/EditorSettingsDialog.vue index 6b01dc263..adc046843 100644 --- a/src/components/editor/EditorSettingsDialog.vue +++ b/src/components/editor/EditorSettingsDialog.vue @@ -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(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( +
+ +
+ + + + + + + {{ t("ai.enableThinkingHint") }} + + +
+
+