Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/config/translation-engines.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
2. 点击设置图标,进入设置页面
3. 选择 "翻译引擎" 选项卡
4. 在引擎列表中选择 "DeepSeek"
5. 选择 `deepseek-chat` 模型,并填入配置信息
5. 选择 `deepseek-v4-flash` 模型,并填入配置信息

<img src="/click-fluent_read.png" alt="点击流畅阅读图标" style="width: 80%; max-width: 100%;border: 1px solid #eee;border-radius: 4px;box-shadow: 0 1px 2px rgba(0,0,0,0.05);" />

Expand Down
16 changes: 14 additions & 2 deletions entrypoints/service/deepseek.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,23 @@ async function deepseek(message: any) {
}

const result = await resp.json();
return contentPostHandler(result.choices[0].message.content);
return extractDeepSeekContent(result);
} catch (error) {
console.error('API调用失败:', error);
throw error;
}
}

export default deepseek;
function extractDeepSeekContent(result: any): string {
const content = result?.choices?.[0]?.message?.content;

if (typeof content !== 'string') {
throw new Error('DeepSeek 返回数据格式异常:缺少 choices[0].message.content');
}

// Only final message.content is rendered. DeepSeek thinking fields such as
// reasoning_content are intentionally ignored and must never reach the page.
return contentPostHandler(content);
}

export default deepseek;
8 changes: 3 additions & 5 deletions entrypoints/utils/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,6 @@ export function searchClassName(node: Node, className: string): Node | null {
}

export function contentPostHandler(text: string) {
// 替换掉<think>与</think>之间的内容
let content = text;
content = content.replace(/^<think>[\s\S]*?<\/think>/, "");
return content;
}
// Never render model reasoning tags in translated page content.
return text.replace(/<think>[\s\S]*?<\/think>/gi, "").trim();
Comment on lines +101 to +102

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): The added trim() may unintentionally alter intentional leading/trailing whitespace or layout.

The previous handler only removed the <think>...</think> block and preserved surrounding whitespace. Now you both globally replace and call trim(). The global replace seems fine, but trim() changes output semantics (e.g., stripping final newlines or leading spaces important for markdown/preformatted text). If that formatting is user-visible, consider dropping trim() or limiting whitespace cleanup to the reasoning tags only.

}
2 changes: 1 addition & 1 deletion entrypoints/utils/option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export const models = new Map<string, Array<string>>([
[services.infini, ["llama-2-13b-chat", "llama-3.3-70b-instruct", "qwen2.5-14b-instruct", "gemma-2-27b-it", "glm-4-9b-chat", customModelString]],
[services.baichuan, ["Baichuan4-Air", "Baichuan4-Turbo", "Baichuan4", customModelString]],
[services.lingyi, ["yi-lightning", customModelString]],
[services.deepseek, ["deepseek-chat", "deepseek-reasoner", customModelString]],
[services.deepseek, ["deepseek-v4-flash", "deepseek-v4-pro", customModelString]],
[services.minimax, ["chatcompletion_v2"]],
[services.jieyue, ["step-1-8k", customModelString]],
[services.huanYuan, ["hunyuan-turbos-latest", "hunyuan-t1-latest", "hunyuan-a13b", "hunyuan-lite", "hunyuan-standard", customModelString]],
Expand Down
41 changes: 34 additions & 7 deletions entrypoints/utils/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
import {customModelString, defaultOption, services} from "./option";
import {config} from "@/entrypoints/utils/config";

type DeepSeekThinkingMode = 'enabled' | 'disabled';

interface DeepSeekModelConfig {
model: string;
thinking: DeepSeekThinkingMode;
}

// openai 格式的消息模板(通用模板)
export function commonMsgTemplate(origin: string) {
// 检测是否使用自定义模型
Expand All @@ -27,31 +34,51 @@ export function commonMsgTemplate(origin: string) {
// deepseek
export function deepseekMsgTemplate(origin: string) {
// 检测是否使用自定义模型
let model = config.model[config.service] === customModelString ? config.customModel[config.service] : config.model[config.service]
const selectedModel = config.model[config.service] === customModelString ? config.customModel[config.service] : config.model[config.service]

// 删除模型名称中的中文括号及其内容,如"gpt-4(推荐)" -> "gpt-4"
model = model.replace(/(.*)/g, "");
const modelConfig = normalizeDeepSeekModel(selectedModel);

let system = config.system_role[config.service] || defaultOption.system_role;
let user = (config.user_role[config.service] || defaultOption.user_role)
.replace('{{to}}', config.to).replace('{{origin}}', origin);

const payload: any = {
'model': model,
'model': modelConfig.model,
'messages': [
{'role': 'system', 'content': system},
{'role': 'user', 'content': user},
]
],
// DeepSeek OpenAI-format Chat Completion / Thinking Mode docs, checked 2026-06-20:
// direct REST requests use top-level {"thinking": {"type": "enabled" | "disabled"}}.
'thinking': {'type': modelConfig.thinking}
};

// 如果不是 deepseek-reasoner 模型,则添加 temperature
if (model !== 'deepseek-reasoner') {
if (modelConfig.thinking === 'enabled') {
payload.reasoning_effort = 'high';
} else {
payload.temperature = 0.7;
}

return JSON.stringify(payload);
}

function normalizeDeepSeekModel(model: string): DeepSeekModelConfig {
const normalizedModel = (model || '').replace(/(.*)/g, "");

// Legacy DeepSeek names are scheduled for deprecation on 2026-07-24.
// Keep saved configs working while preserving their semantics:
// deepseek-chat stays non-thinking; deepseek-reasoner stays thinking-capable.
if (normalizedModel === 'deepseek-chat') {
return {model: 'deepseek-v4-flash', thinking: 'disabled'};
}

if (normalizedModel === 'deepseek-reasoner') {
return {model: 'deepseek-v4-pro', thinking: 'enabled'};
}

return {model: normalizedModel, thinking: 'disabled'};
}

// gemini
export function geminiMsgTemplate(origin: string) {
let user = (config.user_role[config.service] || defaultOption.user_role)
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@
"webextension-polyfill": "^0.12.0"
},
"devDependencies": {
"@types/chrome": "^0.2.0",
"@types/crypto-js": "^4.2.2",
"@types/webextension-polyfill": "^0.12.1",
"@vitejs/plugin-vue": "^5.2.1",
"@vuepress/client": "2.0.0-rc.19",
"@wxt-dev/webextension-polyfill": "^1.0.0",
"typescript": "^5.7.3",
"vite": "^5.4.11",
"vite": "^5.4.19",
"vite-plugin-imagemin": "^0.6.1",
"vitepress": "^1.6.3",
"vue": "^3.5.13",
Expand Down
116 changes: 21 additions & 95 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.