add: 为AI设置增加了thinking的开关
This commit is contained in:
parent
ab1b4ae227
commit
4f0a13f24f
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ export interface AiConfig {
|
|||
apiStyle: AiApiStyle;
|
||||
proxyEnabled?: boolean;
|
||||
proxyUrl?: string;
|
||||
enableThinking?: boolean;
|
||||
}
|
||||
|
||||
const defaultConfigs: Record<AiProvider, Omit<AiConfig, "apiKey">> = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue