diff --git a/README.md b/README.md
index 3092c52f..4975ea72 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@
- ✅ **工具系统:** 内置文件读写、终端执行、浏览器操作、定时任务等工具,Agent 自主调用以完成复杂任务
- ✅ **CLI系统:** 提供终端命令和对话命令,支持进程管理、技能安装、配置修改等操作
- ✅ **多模态消息:** 支持对文本、图片、语音、文件等多类型消息进行解析、处理、生成、发送等操作
-- ✅ **多模型支持:** 支持 OpenAI, Claude, Gemini, DeepSeek, MiniMax、GLM、Qwen、Kimi、Doubao 等国内外主流模型厂商
+- ✅ **多模型支持:** 支持 MiniMax、DeepSeek、Claude、Gemini、OpenAI、GLM、Qwen、Doubao、Kimi 等国内外主流模型厂商
- ✅ **多通道接入:** 支持运行在本地计算机或服务器,可集成到微信、飞书、钉钉、企业微信、QQ、微信公众号、网页中使用
## 声明
@@ -313,47 +313,6 @@ sudo docker logs -f chatgpt-on-wechat
推荐通过 Web 控制台在线管理模型配置,无需手动编辑文件,详见 [模型文档](https://docs.cowagent.ai/models)。以下是手动修改 `config.json` 配置模型的说明:
-
-OpenAI
-
-1. API Key 创建:在 [OpenAI平台](https://platform.openai.com/api-keys) 创建 API Key
-
-2. 填写配置
-
-```json
-{
- "model": "gpt-5.4",
- "open_ai_api_key": "YOUR_API_KEY",
- "open_ai_api_base": "https://api.openai.com/v1",
- "bot_type": "openai"
-}
-```
-
- - `model`: 与 OpenAI 接口的 [model参数](https://platform.openai.com/docs/models) 一致,支持包括 gpt-5.4、gpt-5.4-mini、gpt-5.4-nano、o 系列、gpt-4.1 等模型,Agent 模式推荐使用 `gpt-5.4`、`gpt-5.4-mini`
- - `open_ai_api_base`: 如果需要接入第三方代理接口,可通过修改该参数进行接入
- - `bot_type`: 使用 OpenAI 相关模型时无需填写。当使用第三方代理接口接入 Claude 等非 OpenAI 官方模型时,该参数设为 `openai`
-
-
-
-LinkAI
-
-1. API Key 创建:在 [LinkAI平台](https://link-ai.tech/console/interface) 创建 API Key
-
-2. 填写配置
-
-```json
-{
- "model": "gpt-5.4-mini",
- "use_linkai": true,
- "linkai_api_key": "YOUR API KEY"
-}
-```
-
-+ `use_linkai`: 是否使用 LinkAI 接口,默认关闭,设置为 true 后可对接 LinkAI 平台的模型,并使用知识库、工作流、数据库、插件等丰富的 Agent 技能
-+ `linkai_api_key`: LinkAI 平台的 API Key,可在 [控制台](https://link-ai.tech/console/interface) 中创建
-+ `model`: [模型列表](https://link-ai.tech/console/models)中的全部模型均可使用
-
-
MiniMax
@@ -383,6 +342,89 @@ sudo docker logs -f chatgpt-on-wechat
- `open_ai_api_key`: MiniMax 平台的 API-KEY
+
+DeepSeek
+
+1. API Key 创建:在 [DeepSeek 平台](https://platform.deepseek.com/api_keys) 创建 API Key
+
+2. 填写配置
+
+方式一:官方接入(推荐):
+
+```json
+{
+ "model": "deepseek-v4-pro",
+ "deepseek_api_key": "sk-xxxxxxxxxxx"
+}
+```
+
+ - `model`: 推荐填写 `deepseek-v4-pro`、`deepseek-v4-flash`
+ - `deepseek_api_key`: DeepSeek 平台的 API Key
+ - `deepseek_api_base`: 可选,默认为 `https://api.deepseek.com/v1`,可修改为第三方代理地址
+
+方式二:OpenAI 兼容方式接入:
+
+```json
+{
+ "model": "deepseek-v4-pro",
+ "bot_type": "openai",
+ "open_ai_api_key": "sk-xxxxxxxxxxx",
+ "open_ai_api_base": "https://api.deepseek.com/v1"
+}
+```
+
+
+
+
+Claude
+
+1. API Key 创建:在 [Claude控制台](https://console.anthropic.com/settings/keys) 创建 API Key
+
+2. 填写配置
+
+```json
+{
+ "model": "claude-sonnet-4-6",
+ "claude_api_key": "YOUR_API_KEY"
+}
+```
+ - `model`: 参考 [官方模型ID](https://docs.anthropic.com/en/docs/about-claude/models/overview#model-aliases) ,支持 `claude-sonnet-4-6、claude-opus-4-7、claude-opus-4-6、claude-sonnet-4-5、claude-sonnet-4-0、claude-opus-4-0、claude-3-5-sonnet-latest` 等
+
+
+
+Gemini
+
+API Key 创建:在 [控制台](https://aistudio.google.com/app/apikey?hl=zh-cn) 创建 API Key ,配置如下
+```json
+{
+ "model": "gemini-3.1-flash-lite-preview",
+ "gemini_api_key": ""
+}
+```
+ - `model`: 参考[官方文档-模型列表](https://ai.google.dev/gemini-api/docs/models?hl=zh-cn),支持 `gemini-3.1-flash-lite-preview、gemini-3.1-pro-preview、gemini-3-flash-preview、gemini-3-pro-preview` 等
+
+
+
+OpenAI
+
+1. API Key 创建:在 [OpenAI平台](https://platform.openai.com/api-keys) 创建 API Key
+
+2. 填写配置
+
+```json
+{
+ "model": "gpt-5.4",
+ "open_ai_api_key": "YOUR_API_KEY",
+ "open_ai_api_base": "https://api.openai.com/v1",
+ "bot_type": "openai"
+}
+```
+
+ - `model`: 与 OpenAI 接口的 [model参数](https://platform.openai.com/docs/models) 一致,支持包括 gpt-5.4、gpt-5.4-mini、gpt-5.4-nano、o 系列、gpt-4.1 等模型,Agent 模式推荐使用 `gpt-5.4`、`gpt-5.4-mini`
+ - `open_ai_api_base`: 如果需要接入第三方代理接口,可通过修改该参数进行接入
+ - `bot_type`: 使用 OpenAI 相关模型时无需填写。当使用第三方代理接口接入 Claude 等非 OpenAI 官方模型时,该参数设为 `openai`
+
+
智谱AI (GLM)
@@ -441,35 +483,6 @@ sudo docker logs -f chatgpt-on-wechat
- `open_ai_api_key`: 通义千问的 API-KEY
-
-Kimi (Moonshot)
-
-方式一:官方接入,配置如下:
-
-```json
-{
- "model": "kimi-k2.6",
- "moonshot_api_key": ""
-}
-```
- - `model`: 可填写 `kimi-k2.6、kimi-k2.5、kimi-k2、moonshot-v1-8k、moonshot-v1-32k、moonshot-v1-128k`
- - `moonshot_api_key`: Moonshot 的 API-KEY,在 [控制台](https://platform.moonshot.cn/console/api-keys) 创建
-
-方式二:OpenAI 兼容方式接入,配置如下:
-```json
-{
- "bot_type": "openai",
- "model": "kimi-k2.6",
- "open_ai_api_base": "https://api.moonshot.cn/v1",
- "open_ai_api_key": ""
-}
-```
-- `bot_type`: OpenAI 兼容方式
-- `model`: 可填写 `kimi-k2.6、kimi-k2.5、kimi-k2、moonshot-v1-8k、moonshot-v1-32k、moonshot-v1-128k`
-- `open_ai_api_base`: Moonshot 的 BASE URL
-- `open_ai_api_key`: Moonshot 的 API-KEY
-
-
豆包 (Doubao)
@@ -489,67 +502,74 @@ sudo docker logs -f chatgpt-on-wechat
-Claude
+Kimi (Moonshot)
-1. API Key 创建:在 [Claude控制台](https://console.anthropic.com/settings/keys) 创建 API Key
+方式一:官方接入,配置如下:
+
+```json
+{
+ "model": "kimi-k2.6",
+ "moonshot_api_key": ""
+}
+```
+ - `model`: 可填写 `kimi-k2.6、kimi-k2.5、kimi-k2、moonshot-v1-8k、moonshot-v1-32k、moonshot-v1-128k`
+ - `moonshot_api_key`: Moonshot 的 API-KEY,在 [控制台](https://platform.moonshot.cn/console/api-keys) 创建
+
+方式二:OpenAI 兼容方式接入,配置如下:
+```json
+{
+ "bot_type": "openai",
+ "model": "kimi-k2.6",
+ "open_ai_api_base": "https://api.moonshot.cn/v1",
+ "open_ai_api_key": ""
+}
+```
+- `bot_type`: OpenAI 兼容方式
+- `model`: 可填写 `kimi-k2.6、kimi-k2.5、kimi-k2、moonshot-v1-8k、moonshot-v1-32k、moonshot-v1-128k`
+- `open_ai_api_base`: Moonshot 的 BASE URL
+- `open_ai_api_key`: Moonshot 的 API-KEY
+
+
+
+ModelScope
+
+```json
+{
+ "bot_type": "modelscope",
+ "model": "Qwen/QwQ-32B",
+ "modelscope_api_key": "your_api_key",
+ "modelscope_base_url": "https://api-inference.modelscope.cn/v1/chat/completions",
+ "text_to_image": "MusePublic/489_ckpt_FLUX_1"
+}
+```
+
+- `bot_type`: modelscope 接口格式
+- `model`: 参考[模型列表](https://www.modelscope.cn/models?filter=inference_type&page=1)
+- `modelscope_api_key`: 参考 [官方文档-访问令牌](https://modelscope.cn/docs/accounts/token) ,在 [控制台](https://modelscope.cn/my/myaccesstoken)
+- `modelscope_base_url`: modelscope 平台的 BASE URL
+- `text_to_image`: 图像生成模型,参考[模型列表](https://www.modelscope.cn/models?filter=inference_type&page=1)
+
+
+
+LinkAI
+
+1. API Key 创建:在 [LinkAI平台](https://link-ai.tech/console/interface) 创建 API Key
2. 填写配置
```json
{
- "model": "claude-sonnet-4-6",
- "claude_api_key": "YOUR_API_KEY"
+ "model": "gpt-5.4-mini",
+ "use_linkai": true,
+ "linkai_api_key": "YOUR API KEY"
}
```
- - `model`: 参考 [官方模型ID](https://docs.anthropic.com/en/docs/about-claude/models/overview#model-aliases) ,支持 `claude-sonnet-4-6、claude-opus-4-7、claude-opus-4-6、claude-sonnet-4-5、claude-sonnet-4-0、claude-opus-4-0、claude-3-5-sonnet-latest` 等
+
++ `use_linkai`: 是否使用 LinkAI 接口,默认关闭,设置为 true 后可对接 LinkAI 平台的模型,并使用知识库、工作流、数据库、插件等丰富的 Agent 技能
++ `linkai_api_key`: LinkAI 平台的 API Key,可在 [控制台](https://link-ai.tech/console/interface) 中创建
++ `model`: [模型列表](https://link-ai.tech/console/models)中的全部模型均可使用
-
-Gemini
-
-API Key 创建:在 [控制台](https://aistudio.google.com/app/apikey?hl=zh-cn) 创建 API Key ,配置如下
-```json
-{
- "model": "gemini-3.1-flash-lite-preview",
- "gemini_api_key": ""
-}
-```
- - `model`: 参考[官方文档-模型列表](https://ai.google.dev/gemini-api/docs/models?hl=zh-cn),支持 `gemini-3.1-flash-lite-preview、gemini-3.1-pro-preview、gemini-3-flash-preview、gemini-3-pro-preview` 等
-
-
-
-DeepSeek
-
-1. API Key 创建:在 [DeepSeek 平台](https://platform.deepseek.com/api_keys) 创建 API Key
-
-2. 填写配置
-
-方式一:官方接入(推荐):
-
-```json
-{
- "model": "deepseek-chat",
- "deepseek_api_key": "sk-xxxxxxxxxxx"
-}
-```
-
- - `model`: 可填 `deepseek-chat、deepseek-reasoner`,分别对应的是 DeepSeek-V3.2(非思考模式)和 DeepSeek-R1(思考模式)
- - `deepseek_api_key`: DeepSeek 平台的 API Key
- - `deepseek_api_base`: 可选,默认为 `https://api.deepseek.com/v1`,可修改为第三方代理地址
-
-方式二:OpenAI 兼容方式接入:
-
-```json
-{
- "model": "deepseek-chat",
- "bot_type": "openai",
- "open_ai_api_key": "sk-xxxxxxxxxxx",
- "open_ai_api_base": "https://api.deepseek.com/v1"
-}
-```
-
-
-
Azure
@@ -642,26 +662,6 @@ API Key 创建:在 [控制台](https://aistudio.google.com/app/apikey?hl=zh-cn
- `open_ai_api_key`: 讯飞星火平台的[APIPassword](https://console.xfyun.cn/services/bm3) ,因模型而已
-
-ModelScope
-
-```json
-{
- "bot_type": "modelscope",
- "model": "Qwen/QwQ-32B",
- "modelscope_api_key": "your_api_key",
- "modelscope_base_url": "https://api-inference.modelscope.cn/v1/chat/completions",
- "text_to_image": "MusePublic/489_ckpt_FLUX_1"
-}
-```
-
-- `bot_type`: modelscope 接口格式
-- `model`: 参考[模型列表](https://www.modelscope.cn/models?filter=inference_type&page=1)
-- `modelscope_api_key`: 参考 [官方文档-访问令牌](https://modelscope.cn/docs/accounts/token) ,在 [控制台](https://modelscope.cn/my/myaccesstoken)
-- `modelscope_base_url`: modelscope 平台的 BASE URL
-- `text_to_image`: 图像生成模型,参考[模型列表](https://www.modelscope.cn/models?filter=inference_type&page=1)
-
-
Coding Plan
diff --git a/channel/web/web_channel.py b/channel/web/web_channel.py
index 2c21ceb9..ad1301aa 100644
--- a/channel/web/web_channel.py
+++ b/channel/web/web_channel.py
@@ -771,14 +771,14 @@ class ConfigHandler:
_RECOMMENDED_MODELS = [
const.MINIMAX_M2_7_HIGHSPEED, const.MINIMAX_M2_7, const.MINIMAX_M2_5, const.MINIMAX_M2_1, const.MINIMAX_M2_1_LIGHTNING,
- const.GLM_5_1, const.GLM_5_TURBO, const.GLM_5, const.GLM_4_7,
- const.QWEN36_PLUS, const.QWEN35_PLUS, const.QWEN3_MAX,
- const.KIMI_K2_6, const.KIMI_K2_5, const.KIMI_K2,
- const.DOUBAO_SEED_2_PRO, const.DOUBAO_SEED_2_CODE,
+ const.DEEPSEEK_V4_PRO, const.DEEPSEEK_V4_FLASH, const.DEEPSEEK_CHAT, const.DEEPSEEK_REASONER,
const.CLAUDE_4_6_SONNET, const.CLAUDE_4_7_OPUS, const.CLAUDE_4_6_OPUS, const.CLAUDE_4_5_SONNET,
const.GEMINI_31_FLASH_LITE_PRE, const.GEMINI_31_PRO_PRE, const.GEMINI_3_FLASH_PRE,
const.GPT_54, const.GPT_54_MINI, const.GPT_54_NANO, const.GPT_5, const.GPT_41, const.GPT_4o,
- const.DEEPSEEK_CHAT, const.DEEPSEEK_REASONER,
+ const.GLM_5_1, const.GLM_5_TURBO, const.GLM_5, const.GLM_4_7,
+ const.QWEN36_PLUS, const.QWEN35_PLUS, const.QWEN3_MAX,
+ const.DOUBAO_SEED_2_PRO, const.DOUBAO_SEED_2_CODE,
+ const.KIMI_K2_6, const.KIMI_K2_5, const.KIMI_K2,
]
PROVIDER_MODELS = OrderedDict([
@@ -789,33 +789,12 @@ class ConfigHandler:
"api_base_default": None,
"models": [const.MINIMAX_M2_7, const.MINIMAX_M2_7_HIGHSPEED, const.MINIMAX_M2_5, const.MINIMAX_M2_1, const.MINIMAX_M2_1_LIGHTNING],
}),
- ("zhipu", {
- "label": "智谱AI",
- "api_key_field": "zhipu_ai_api_key",
- "api_base_key": "zhipu_ai_api_base",
- "api_base_default": "https://open.bigmodel.cn/api/paas/v4",
- "models": [const.GLM_5_1, const.GLM_5_TURBO, const.GLM_5, const.GLM_4_7],
- }),
- ("dashscope", {
- "label": "通义千问",
- "api_key_field": "dashscope_api_key",
- "api_base_key": None,
- "api_base_default": None,
- "models": [const.QWEN36_PLUS, const.QWEN35_PLUS, const.QWEN3_MAX],
- }),
- ("moonshot", {
- "label": "Kimi",
- "api_key_field": "moonshot_api_key",
- "api_base_key": "moonshot_base_url",
- "api_base_default": "https://api.moonshot.cn/v1",
- "models": [const.KIMI_K2_6, const.KIMI_K2_5, const.KIMI_K2],
- }),
- ("doubao", {
- "label": "豆包",
- "api_key_field": "ark_api_key",
- "api_base_key": "ark_base_url",
- "api_base_default": "https://ark.cn-beijing.volces.com/api/v3",
- "models": [const.DOUBAO_SEED_2_PRO, const.DOUBAO_SEED_2_CODE],
+ ("deepseek", {
+ "label": "DeepSeek",
+ "api_key_field": "deepseek_api_key",
+ "api_base_key": "deepseek_api_base",
+ "api_base_default": "https://api.deepseek.com/v1",
+ "models": [const.DEEPSEEK_V4_PRO, const.DEEPSEEK_V4_FLASH, const.DEEPSEEK_CHAT, const.DEEPSEEK_REASONER],
}),
("claudeAPI", {
"label": "Claude",
@@ -838,12 +817,33 @@ class ConfigHandler:
"api_base_default": "https://api.openai.com/v1",
"models": [const.GPT_54, const.GPT_54_MINI, const.GPT_54_NANO, const.GPT_5, const.GPT_41, const.GPT_4o],
}),
- ("deepseek", {
- "label": "DeepSeek",
- "api_key_field": "deepseek_api_key",
- "api_base_key": "deepseek_api_base",
- "api_base_default": "https://api.deepseek.com/v1",
- "models": [const.DEEPSEEK_CHAT, const.DEEPSEEK_REASONER],
+ ("zhipu", {
+ "label": "智谱AI",
+ "api_key_field": "zhipu_ai_api_key",
+ "api_base_key": "zhipu_ai_api_base",
+ "api_base_default": "https://open.bigmodel.cn/api/paas/v4",
+ "models": [const.GLM_5_1, const.GLM_5_TURBO, const.GLM_5, const.GLM_4_7],
+ }),
+ ("dashscope", {
+ "label": "通义千问",
+ "api_key_field": "dashscope_api_key",
+ "api_base_key": None,
+ "api_base_default": None,
+ "models": [const.QWEN36_PLUS, const.QWEN35_PLUS, const.QWEN3_MAX],
+ }),
+ ("doubao", {
+ "label": "豆包",
+ "api_key_field": "ark_api_key",
+ "api_base_key": "ark_base_url",
+ "api_base_default": "https://ark.cn-beijing.volces.com/api/v3",
+ "models": [const.DOUBAO_SEED_2_PRO, const.DOUBAO_SEED_2_CODE],
+ }),
+ ("moonshot", {
+ "label": "Kimi",
+ "api_key_field": "moonshot_api_key",
+ "api_base_key": "moonshot_base_url",
+ "api_base_default": "https://api.moonshot.cn/v1",
+ "models": [const.KIMI_K2_6, const.KIMI_K2_5, const.KIMI_K2],
}),
("modelscope", {
"label": "ModelScope",
diff --git a/common/const.py b/common/const.py
index 94b7c955..b9b945fe 100644
--- a/common/const.py
+++ b/common/const.py
@@ -82,6 +82,8 @@ TTS_1_HD = "tts-1-hd"
# DeepSeek
DEEPSEEK_CHAT = "deepseek-chat" # DeepSeek-V3对话模型
DEEPSEEK_REASONER = "deepseek-reasoner" # DeepSeek-R1模型
+DEEPSEEK_V4_FLASH = "deepseek-v4-flash" # DeepSeek V4 Flash - 思考模式 + 工具调用
+DEEPSEEK_V4_PRO = "deepseek-v4-pro" # DeepSeek V4 Pro - Agent推荐模型 (思考模式 + 工具调用)
# Qwen (通义千问 - 阿里云 DashScope)
QWEN_TURBO = "qwen-turbo"
@@ -154,15 +156,21 @@ MODELSCOPE_MODEL_LIST = ["deepseek-ai/DeepSeek-R1-0528", "deepseek-ai/DeepSeek-R
MODEL_LIST = [
+ # MiniMax
+ MiniMax, MINIMAX_M2_7, MINIMAX_M2_7_HIGHSPEED, MINIMAX_M2_5, MINIMAX_M2_1, MINIMAX_M2_1_LIGHTNING, MINIMAX_M2, MINIMAX_ABAB6_5,
+
+ # DeepSeek
+ DEEPSEEK_V4_PRO, DEEPSEEK_V4_FLASH, DEEPSEEK_CHAT, DEEPSEEK_REASONER,
+
# Claude
- CLAUDE3, CLAUDE_4_6_SONNET, CLAUDE_4_7_OPUS, CLAUDE_4_6_OPUS, CLAUDE_4_OPUS, CLAUDE_4_5_SONNET, CLAUDE_4_SONNET, CLAUDE_3_OPUS, CLAUDE_3_OPUS_0229,
- CLAUDE_35_SONNET, CLAUDE_35_SONNET_1022, CLAUDE_35_SONNET_0620, CLAUDE_3_SONNET, CLAUDE_3_HAIKU,
+ CLAUDE3, CLAUDE_4_6_SONNET, CLAUDE_4_7_OPUS, CLAUDE_4_6_OPUS, CLAUDE_4_OPUS, CLAUDE_4_5_SONNET, CLAUDE_4_SONNET, CLAUDE_3_OPUS, CLAUDE_3_OPUS_0229,
+ CLAUDE_35_SONNET, CLAUDE_35_SONNET_1022, CLAUDE_35_SONNET_0620, CLAUDE_3_SONNET, CLAUDE_3_HAIKU,
"claude", "claude-3-haiku", "claude-3-sonnet", "claude-3-opus", "claude-3.5-sonnet",
-
+
# Gemini
GEMINI_31_FLASH_LITE_PRE, GEMINI_31_PRO_PRE, GEMINI_3_PRO_PRE, GEMINI_3_FLASH_PRE, GEMINI_25_PRO_PRE, GEMINI_25_FLASH_PRE,
GEMINI_20_FLASH, GEMINI_20_flash_exp, GEMINI_15_PRO, GEMINI_15_flash, GEMINI_PRO, GEMINI,
-
+
# OpenAI
GPT35, GPT35_0125, GPT35_1106, "gpt-3.5-turbo-16k",
GPT4, GPT4_06_13, GPT4_32k, GPT4_32k_06_13,
@@ -172,31 +180,29 @@ MODEL_LIST = [
GPT_5, GPT_5_MINI, GPT_5_NANO,
GPT_54, GPT_54_MINI, GPT_54_NANO,
O1, O1_MINI,
-
- # DeepSeek
- DEEPSEEK_CHAT, DEEPSEEK_REASONER,
-
- # Qwen
- QWEN36_PLUS, QWEN35_PLUS, QWEN3_MAX, QWEN_MAX, QWEN_PLUS, QWEN_TURBO, QWEN_LONG,
-
- # MiniMax
- MiniMax, MINIMAX_M2_7, MINIMAX_M2_7_HIGHSPEED, MINIMAX_M2_5, MINIMAX_M2_1, MINIMAX_M2_1_LIGHTNING, MINIMAX_M2, MINIMAX_ABAB6_5,
- # GLM
+ # GLM (智谱AI)
ZHIPU_AI, GLM_5_1, GLM_5_TURBO, GLM_5, GLM_4, GLM_4_PLUS, GLM_4_flash, GLM_4_LONG, GLM_4_ALLTOOLS,
GLM_4_0520, GLM_4_AIR, GLM_4_AIRX, GLM_4_7,
- # Kimi
+ # Qwen (通义千问)
+ QWEN36_PLUS, QWEN35_PLUS, QWEN3_MAX, QWEN_MAX, QWEN_PLUS, QWEN_TURBO, QWEN_LONG,
+
+ # Doubao (豆包)
+ DOUBAO, DOUBAO_SEED_2_CODE, DOUBAO_SEED_2_PRO, DOUBAO_SEED_2_LITE, DOUBAO_SEED_2_MINI,
+
+ # Kimi (Moonshot)
MOONSHOT, "moonshot-v1-8k", "moonshot-v1-32k", "moonshot-v1-128k",
KIMI_K2_6, KIMI_K2_5, KIMI_K2,
- # Doubao
- DOUBAO, DOUBAO_SEED_2_CODE, DOUBAO_SEED_2_PRO, DOUBAO_SEED_2_LITE, DOUBAO_SEED_2_MINI,
+ # ModelScope
+ MODELSCOPE,
+
+ # LinkAI
+ LINKAI_35, LINKAI_4_TURBO, LINKAI_4o,
# 其他模型
WEN_XIN, WEN_XIN_4, XUNFEI,
- LINKAI_35, LINKAI_4_TURBO, LINKAI_4o,
- MODELSCOPE
]
MODEL_LIST = MODEL_LIST + GITEE_AI_MODEL_LIST + MODELSCOPE_MODEL_LIST
diff --git a/docs/cli/general.mdx b/docs/cli/general.mdx
index 62d69ad2..5b972da0 100644
--- a/docs/cli/general.mdx
+++ b/docs/cli/general.mdx
@@ -58,14 +58,14 @@ Session: 12 messages | 8 skills loaded
**修改配置项:**
```text
-/config model deepseek-chat
+/config model deepseek-v4-pro
```
**支持修改的配置项:**
| 配置项 | 说明 | 示例值 |
| --- | --- | --- |
-| `model` | AI 模型名称 | `deepseek-chat` |
+| `model` | AI 模型名称 | `deepseek-v4-pro` |
| `agent_max_context_tokens` | 最大上下文 tokens | `40000` |
| `agent_max_context_turns` | 最大上下文记忆轮次 | `30` |
| `agent_max_steps` | 单次任务最大决策步数 | `15` |
diff --git a/docs/en/README.md b/docs/en/README.md
index c1c59f97..a61d47e0 100644
--- a/docs/en/README.md
+++ b/docs/en/README.md
@@ -28,7 +28,7 @@
- ✅ **Tool System**: Built-in tools for file I/O, terminal execution, browser automation, scheduled tasks, messaging, and more — autonomously invoked by the Agent.
- ✅ **CLI System**: Provides terminal commands and in-chat commands for process management, skill installation, configuration, and more.
- ✅ **Multimodal Messages**: Supports parsing, processing, generating, and sending text, images, voice, files, and other message types.
-- ✅ **Multiple Model Support**: Supports OpenAI, Claude, Gemini, DeepSeek, MiniMax, GLM, Qwen, Kimi, Doubao, and other mainstream model providers.
+- ✅ **Multiple Model Support**: Supports MiniMax, DeepSeek, Claude, Gemini, OpenAI, GLM, Qwen, Doubao, Kimi, and other mainstream model providers.
- ✅ **Multi-platform Deployment**: Runs on local computers or servers, integrable into WeChat, Web, Feishu, DingTalk, WeChat Official Account, and WeCom applications.
## Disclaimer
@@ -165,14 +165,14 @@ Supports mainstream model providers. Recommended models for Agent mode:
| Provider | Recommended Model |
| --- | --- |
| MiniMax | `MiniMax-M2.7` |
-| GLM | `glm-5.1` |
-| Kimi | `kimi-k2.6` |
-| Doubao | `doubao-seed-2-0-code-preview-260215` |
-| Qwen | `qwen3.6-plus` |
+| DeepSeek | `deepseek-v4-pro` |
| Claude | `claude-sonnet-4-6` |
| Gemini | `gemini-3.1-pro-preview` |
| OpenAI | `gpt-5.4` |
-| DeepSeek | `deepseek-chat` |
+| GLM | `glm-5.1` |
+| Qwen | `qwen3.6-plus` |
+| Doubao | `doubao-seed-2-0-code-preview-260215` |
+| Kimi | `kimi-k2.6` |
For detailed configuration of each model, see the [Models documentation](https://docs.cowagent.ai/en/models/index).
diff --git a/docs/en/cli/general.mdx b/docs/en/cli/general.mdx
index 3f55425e..8d6dce68 100644
--- a/docs/en/cli/general.mdx
+++ b/docs/en/cli/general.mdx
@@ -44,14 +44,14 @@ View or modify runtime configuration. Changes take effect immediately without re
**Modify a config item:**
```text
-/config model deepseek-chat
+/config model deepseek-v4-pro
```
**Configurable items:**
| Item | Description | Example |
| --- | --- | --- |
-| `model` | AI model name | `deepseek-chat` |
+| `model` | AI model name | `deepseek-v4-pro` |
| `agent_max_context_tokens` | Max context tokens | `40000` |
| `agent_max_context_turns` | Max context memory turns | `30` |
| `agent_max_steps` | Max decision steps per task | `15` |
diff --git a/docs/en/models/custom.mdx b/docs/en/models/custom.mdx
index 94bc825c..d422c333 100644
--- a/docs/en/models/custom.mdx
+++ b/docs/en/models/custom.mdx
@@ -20,7 +20,7 @@ For models accessed via OpenAI-compatible APIs, such as:
```json
{
"bot_type": "custom",
- "model": "deepseek-chat",
+ "model": "deepseek-v4-pro",
"custom_api_key": "YOUR_API_KEY",
"custom_api_base": "https://{your-proxy.com}/v1"
}
diff --git a/docs/en/models/deepseek.mdx b/docs/en/models/deepseek.mdx
index ae765e3b..e39b4db3 100644
--- a/docs/en/models/deepseek.mdx
+++ b/docs/en/models/deepseek.mdx
@@ -7,26 +7,28 @@ Option 1: Native integration (recommended):
```json
{
- "model": "deepseek-chat",
+ "model": "deepseek-v4-pro",
"deepseek_api_key": "YOUR_API_KEY"
}
```
| Parameter | Description |
| --- | --- |
-| `model` | `deepseek-chat` (DeepSeek-V3.2, non-thinking mode), `deepseek-reasoner` (DeepSeek-R1, thinking mode) |
+| `model` | `deepseek-v4-pro` (V4 Pro, thinking mode + tool calls, Agent recommended), `deepseek-v4-flash` (V4 Flash, thinking mode + tool calls), `deepseek-chat` (DeepSeek-V3.2, non-thinking), `deepseek-reasoner` (DeepSeek-R1, thinking mode) |
| `deepseek_api_key` | Create at [DeepSeek Platform](https://platform.deepseek.com/api_keys) |
| `deepseek_api_base` | Optional, defaults to `https://api.deepseek.com/v1`. Can be changed to a third-party proxy |
+
+ The V4 series (`deepseek-v4-pro`, `deepseek-v4-flash`) supports thinking mode together with tool calls, enabling multi-round reasoning + tool orchestration in Agent mode. The thinking switch is controlled by the global `enable_thinking` setting, and `reasoning_content` is automatically round-tripped on tool-call turns.
+
+
Option 2: OpenAI-compatible configuration:
```json
{
- "model": "deepseek-chat",
+ "model": "deepseek-v4-pro",
"bot_type": "openai",
"open_ai_api_key": "YOUR_API_KEY",
"open_ai_api_base": "https://api.deepseek.com/v1"
}
```
-
-
diff --git a/docs/en/models/index.mdx b/docs/en/models/index.mdx
index dab4f434..ecac9729 100644
--- a/docs/en/models/index.mdx
+++ b/docs/en/models/index.mdx
@@ -6,7 +6,7 @@ description: Supported models and recommended choices for CowAgent
CowAgent supports mainstream LLMs from domestic and international providers. Model interfaces are implemented in the project's `models/` directory.
- For Agent mode, the following models are recommended based on quality and cost: MiniMax-M2.7, glm-5.1, kimi-k2.6, qwen3.6-plus, claude-sonnet-4-6, gemini-3.1-pro-preview
+ For Agent mode, the following models are recommended based on quality and cost: MiniMax-M2.7, deepseek-v4-pro, claude-sonnet-4-6, gemini-3.1-pro-preview, glm-5.1, qwen3.6-plus, kimi-k2.6
## Configuration
@@ -21,17 +21,8 @@ You can also use the [LinkAI](https://link-ai.tech) platform interface to flexib
MiniMax-M2.7 and other series models
-
- glm-5.1, glm-5-turbo, glm-5 and other series models
-
-
- qwen3.6-plus, qwen3-max and more
-
-
- kimi-k2.6, kimi-k2.5, kimi-k2 and more
-
-
- doubao-seed series models
+
+ deepseek-v4-pro, deepseek-v4-flash, deepseek-chat, deepseek-reasoner
claude-sonnet-4-6 and more
@@ -42,8 +33,17 @@ You can also use the [LinkAI](https://link-ai.tech) platform interface to flexib
gpt-5.4, gpt-4.1, o-series and more
-
- deepseek-chat, deepseek-reasoner
+
+ glm-5.1, glm-5-turbo, glm-5 and other series models
+
+
+ qwen3.6-plus, qwen3-max and more
+
+
+ doubao-seed series models
+
+
+ kimi-k2.6, kimi-k2.5, kimi-k2 and more
Unified multi-model interface + knowledge base
diff --git a/docs/ja/README.md b/docs/ja/README.md
index ad01cdd7..4404622a 100644
--- a/docs/ja/README.md
+++ b/docs/ja/README.md
@@ -28,7 +28,7 @@
- ✅ **ツールシステム**: ファイル読み書き、ターミナル実行、ブラウザ操作、スケジュールタスク、メッセージ送信などの組み込みツールを提供。Agentが自律的に呼び出して複雑なタスクを完了します。
- ✅ **CLIシステム**: ターミナルコマンドとチャットコマンドを提供し、プロセス管理、Skillインストール、設定変更などの操作をサポートします。
- ✅ **マルチモーダルメッセージ**: テキスト、画像、音声、ファイルなど、さまざまなメッセージタイプの解析・処理・生成・送信に対応しています。
-- ✅ **複数モデル対応**: OpenAI、Claude、Gemini、DeepSeek、MiniMax、GLM、Qwen、Kimi、Doubaoなど、主要なモデルプロバイダーに対応しています。
+- ✅ **複数モデル対応**: MiniMax、DeepSeek、Claude、Gemini、OpenAI、GLM、Qwen、Doubao、Kimiなど、主要なモデルプロバイダーに対応しています。
- ✅ **マルチプラットフォームデプロイ**: ローカルPCやサーバー上で実行でき、WeChat、Web、Feishu、DingTalk、WeChat公式アカウント、WeComアプリケーションに統合可能です。
## 免責事項
@@ -165,14 +165,14 @@ sudo docker logs -f chatgpt-on-wechat
| プロバイダー | 推奨モデル |
| --- | --- |
| MiniMax | `MiniMax-M2.7` |
-| GLM | `glm-5.1` |
-| Kimi | `kimi-k2.6` |
-| Doubao | `doubao-seed-2-0-code-preview-260215` |
-| Qwen | `qwen3.6-plus` |
+| DeepSeek | `deepseek-v4-pro` |
| Claude | `claude-sonnet-4-6` |
| Gemini | `gemini-3.1-pro-preview` |
| OpenAI | `gpt-5.4` |
-| DeepSeek | `deepseek-chat` |
+| GLM | `glm-5.1` |
+| Qwen | `qwen3.6-plus` |
+| Doubao | `doubao-seed-2-0-code-preview-260215` |
+| Kimi | `kimi-k2.6` |
各モデルの詳細設定については、[モデルドキュメント](https://docs.cowagent.ai/en/models/index)を参照してください。
diff --git a/docs/ja/cli/general.mdx b/docs/ja/cli/general.mdx
index d65c3464..de597b01 100644
--- a/docs/ja/cli/general.mdx
+++ b/docs/ja/cli/general.mdx
@@ -44,14 +44,14 @@ description: ステータスの確認、設定管理、コンテキスト制御
**設定項目を変更:**
```text
-/config model deepseek-chat
+/config model deepseek-v4-pro
```
**変更可能な設定項目:**
| 項目 | 説明 | 例 |
| --- | --- | --- |
-| `model` | AI モデル名 | `deepseek-chat` |
+| `model` | AI モデル名 | `deepseek-v4-pro` |
| `agent_max_context_tokens` | 最大コンテキストトークン数 | `40000` |
| `agent_max_context_turns` | 最大コンテキスト記憶ターン数 | `30` |
| `agent_max_steps` | タスクごとの最大判断ステップ数 | `15` |
diff --git a/docs/ja/models/custom.mdx b/docs/ja/models/custom.mdx
index 7746faa9..f03c244a 100644
--- a/docs/ja/models/custom.mdx
+++ b/docs/ja/models/custom.mdx
@@ -20,7 +20,7 @@ OpenAI互換プロトコルでアクセスするモデルサービスに適用
```json
{
"bot_type": "custom",
- "model": "deepseek-chat",
+ "model": "deepseek-v4-pro",
"custom_api_key": "YOUR_API_KEY",
"custom_api_base": "https://{your-proxy.com}/v1"
}
diff --git a/docs/ja/models/deepseek.mdx b/docs/ja/models/deepseek.mdx
index 168c459d..9d9242c6 100644
--- a/docs/ja/models/deepseek.mdx
+++ b/docs/ja/models/deepseek.mdx
@@ -7,22 +7,26 @@ description: DeepSeekモデルの設定
```json
{
- "model": "deepseek-chat",
+ "model": "deepseek-v4-pro",
"deepseek_api_key": "YOUR_API_KEY"
}
```
| パラメータ | 説明 |
| --- | --- |
-| `model` | `deepseek-chat`(DeepSeek-V3.2、非思考モード)、`deepseek-reasoner`(DeepSeek-R1、思考モード) |
+| `model` | `deepseek-v4-pro`(V4 Pro、思考モード + ツール呼び出し、Agent推奨)、`deepseek-v4-flash`(V4 Flash、思考モード + ツール呼び出し)、`deepseek-chat`(DeepSeek-V3.2、非思考モード)、`deepseek-reasoner`(DeepSeek-R1、思考モード) |
| `deepseek_api_key` | [DeepSeek Platform](https://platform.deepseek.com/api_keys)で作成 |
| `deepseek_api_base` | オプション、デフォルトは `https://api.deepseek.com/v1`。サードパーティプロキシに変更可能 |
+
+ V4シリーズ(`deepseek-v4-pro`、`deepseek-v4-flash`)は思考モードとツール呼び出しに対応しており、Agentモードでの多段思考とツール連携が可能です。思考のオン/オフはグローバル設定 `enable_thinking` で制御され、ツール呼び出しのターンでは `reasoning_content` が自動的にAPIへ往復されます。
+
+
方法2:OpenAI互換方式:
```json
{
- "model": "deepseek-chat",
+ "model": "deepseek-v4-pro",
"bot_type": "openai",
"open_ai_api_key": "YOUR_API_KEY",
"open_ai_api_base": "https://api.deepseek.com/v1"
diff --git a/docs/ja/models/index.mdx b/docs/ja/models/index.mdx
index 2d231a19..33f5121f 100644
--- a/docs/ja/models/index.mdx
+++ b/docs/ja/models/index.mdx
@@ -6,7 +6,7 @@ description: CowAgentがサポートするモデルとおすすめの選択肢
CowAgentは国内外の主要なLLMをサポートしています。モデルインターフェースはプロジェクトの`models/`ディレクトリに実装されています。
- Agent モードでは、品質とコストのバランスから以下のモデルをおすすめします: MiniMax-M2.7、glm-5.1、kimi-k2.6、qwen3.6-plus、claude-sonnet-4-6、gemini-3.1-pro-preview
+ Agent モードでは、品質とコストのバランスから以下のモデルをおすすめします: MiniMax-M2.7、deepseek-v4-pro、claude-sonnet-4-6、gemini-3.1-pro-preview、glm-5.1、qwen3.6-plus、kimi-k2.6
## 設定
@@ -21,17 +21,8 @@ CowAgentは国内外の主要なLLMをサポートしています。モデルイ
MiniMax-M2.7およびその他のシリーズモデル
-
- glm-5.1、glm-5-turbo、glm-5およびその他のシリーズモデル
-
-
- qwen3.6-plus、qwen3-maxなど
-
-
- kimi-k2.6、kimi-k2.5、kimi-k2など
-
-
- doubao-seedシリーズモデル
+
+ deepseek-v4-pro、deepseek-v4-flash、deepseek-chat、deepseek-reasoner
claude-sonnet-4-6など
@@ -42,8 +33,17 @@ CowAgentは国内外の主要なLLMをサポートしています。モデルイ
gpt-5.4、gpt-4.1、oシリーズなど
-
- deepseek-chat、deepseek-reasoner
+
+ glm-5.1、glm-5-turbo、glm-5およびその他のシリーズモデル
+
+
+ qwen3.6-plus、qwen3-maxなど
+
+
+ doubao-seedシリーズモデル
+
+
+ kimi-k2.6、kimi-k2.5、kimi-k2など
統合マルチモデルインターフェース + ナレッジベース
diff --git a/docs/models/deepseek.mdx b/docs/models/deepseek.mdx
index e7d23e69..e87e55f4 100644
--- a/docs/models/deepseek.mdx
+++ b/docs/models/deepseek.mdx
@@ -7,25 +7,28 @@ description: DeepSeek 模型配置
```json
{
- "model": "deepseek-chat",
+ "model": "deepseek-v4-pro",
"deepseek_api_key": "YOUR_API_KEY"
}
```
| 参数 | 说明 |
| --- | --- |
-| `model` | `deepseek-chat`(DeepSeek-V3.2,非思考模式)、`deepseek-reasoner`(DeepSeek-R1,思考模式) |
+| `model` | `deepseek-v4-pro`(V4 Pro,思考模式 + 工具调用,Agent 推荐)、`deepseek-v4-flash`(V4 Flash,思考模式 + 工具调用)、`deepseek-chat`(DeepSeek-V3.2,非思考模式)、`deepseek-reasoner`(DeepSeek-R1,思考模式) |
| `deepseek_api_key` | 在 [DeepSeek 平台](https://platform.deepseek.com/api_keys) 创建 |
| `deepseek_api_base` | 可选,默认为 `https://api.deepseek.com/v1`,可修改为第三方代理地址 |
+
+ V4 系列模型(`deepseek-v4-pro`、`deepseek-v4-flash`)支持思考模式与工具调用,可在 Agent 模式下进行多轮思考与工具协同。思考开关由全局 `enable_thinking` 配置控制,工具调用轮次的 `reasoning_content` 会自动回传给 API。
+
+
方式二:OpenAI 兼容方式接入:
```json
{
- "model": "deepseek-chat",
+ "model": "deepseek-v4-pro",
"bot_type": "openai",
"open_ai_api_key": "YOUR_API_KEY",
"open_ai_api_base": "https://api.deepseek.com/v1"
}
```
-
diff --git a/docs/models/index.mdx b/docs/models/index.mdx
index 01169347..7a677561 100644
--- a/docs/models/index.mdx
+++ b/docs/models/index.mdx
@@ -6,7 +6,7 @@ description: CowAgent 支持的模型及推荐选择
CowAgent 支持国内外主流厂商的大语言模型,模型接口实现在项目的 `models/` 目录下。
- Agent 模式下推荐使用以下模型,可根据效果及成本综合选择:MiniMax-M2.7、glm-5.1、kimi-k2.6、qwen3.6-plus、claude-sonnet-4-6、gemini-3.1-pro-preview
+ Agent 模式下推荐使用以下模型,可根据效果及成本综合选择:MiniMax-M2.7、deepseek-v4-pro、claude-sonnet-4-6、gemini-3.1-pro-preview、glm-5.1、qwen3.6-plus、kimi-k2.6
同时支持使用 [LinkAI](https://link-ai.tech) 平台接口,可灵活切换多种模型,并支持知识库、工作流、插件等 Agent 能力。
@@ -26,17 +26,8 @@ CowAgent 支持国内外主流厂商的大语言模型,模型接口实现在
MiniMax-M2.7 等系列模型
-
- glm-5.1、glm-5-turbo、glm-5 等系列模型
-
-
- qwen3.6-plus、qwen3-max 等
-
-
- kimi-k2.6、kimi-k2.5、kimi-k2 等
-
-
- doubao-seed 系列模型
+
+ deepseek-v4-pro、deepseek-v4-flash、deepseek-chat、deepseek-reasoner
claude-sonnet-4-6 等
@@ -47,8 +38,17 @@ CowAgent 支持国内外主流厂商的大语言模型,模型接口实现在
gpt-5.4、gpt-4.1、o 系列等
-
- deepseek-chat、deepseek-reasoner
+
+ glm-5.1、glm-5-turbo、glm-5 等系列模型
+
+
+ qwen3.6-plus、qwen3-max 等
+
+
+ doubao-seed 系列模型
+
+
+ kimi-k2.6、kimi-k2.5、kimi-k2 等
多模型统一接口 + 知识库
diff --git a/models/deepseek/deepseek_bot.py b/models/deepseek/deepseek_bot.py
index 033e0216..9f03771b 100644
--- a/models/deepseek/deepseek_bot.py
+++ b/models/deepseek/deepseek_bot.py
@@ -2,9 +2,26 @@
"""
DeepSeek Bot — fully OpenAI-compatible, uses its own API key / base config.
+
+Supported models:
+- deepseek-chat (V3, no thinking)
+- deepseek-reasoner (R1, built-in reasoning, no `thinking` switch)
+- deepseek-v4-flash (V4, supports thinking mode + tool calls)
+- deepseek-v4-pro (V4, supports thinking mode + tool calls, agent recommended)
+
+Thinking mode notes (for V4 models):
+- Toggle: ``{"thinking": {"type": "enabled" | "disabled"}}`` (default: enabled)
+- Effort: ``reasoning_effort`` ∈ {"high", "max"} (low/medium → high, xhigh → max)
+- In thinking mode, ``temperature``/``top_p``/``presence_penalty``/``frequency_penalty``
+ are silently ignored by the server; we drop them locally to avoid confusion.
+- ``reasoning_content`` is returned alongside ``content``. For turns that triggered
+ tool calls, ``reasoning_content`` MUST be echoed back in subsequent requests, or
+ the API returns 400.
"""
+import json
import time
+from typing import Optional
import requests
from models.bot import Bot
@@ -25,9 +42,9 @@ class DeepSeekBot(Bot, OpenAICompatibleBot):
super().__init__()
self.sessions = SessionManager(
DeepSeekSession,
- model=conf().get("model") or const.DEEPSEEK_CHAT,
+ model=conf().get("model") or const.DEEPSEEK_V4_PRO,
)
- conf_model = conf().get("model") or const.DEEPSEEK_CHAT
+ conf_model = conf().get("model") or const.DEEPSEEK_V4_PRO
self.args = {
"model": conf_model,
"temperature": conf().get("temperature", 0.7),
@@ -56,13 +73,32 @@ class DeepSeekBot(Bot, OpenAICompatibleBot):
return {
"api_key": self.api_key,
"api_base": self.api_base,
- "model": conf().get("model", const.DEEPSEEK_CHAT),
+ "model": conf().get("model", const.DEEPSEEK_V4_PRO),
"default_temperature": conf().get("temperature", 0.7),
"default_top_p": conf().get("top_p", 1.0),
"default_frequency_penalty": conf().get("frequency_penalty", 0.0),
"default_presence_penalty": conf().get("presence_penalty", 0.0),
}
+ @staticmethod
+ def _model_supports_thinking(model_name: str) -> bool:
+ """V4 series models expose the explicit `thinking` switch."""
+ if not model_name:
+ return False
+ m = model_name.lower()
+ return m.startswith("deepseek-v4")
+
+ @staticmethod
+ def _is_reasoner_model(model_name: str) -> bool:
+ """deepseek-reasoner (R1) always thinks internally; no toggle."""
+ return bool(model_name) and "reasoner" in model_name.lower()
+
+ def _build_headers(self) -> dict:
+ return {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ }
+
# ---------- simple chat (non-agent mode) ----------
def reply(self, query, context=None):
@@ -112,13 +148,16 @@ class DeepSeekBot(Bot, OpenAICompatibleBot):
def reply_text(self, session, args=None, retry_count: int = 0) -> dict:
try:
- headers = {
- "Content-Type": "application/json",
- "Authorization": "Bearer " + self.api_key,
- }
- body = args.copy()
+ headers = self._build_headers()
+ body = dict(args) if args else dict(self.args)
body["messages"] = session.messages
+ # Thinking mode ignores temperature/top_p/penalties — strip to avoid noise.
+ model_name = str(body.get("model", ""))
+ if self._model_supports_thinking(model_name) or self._is_reasoner_model(model_name):
+ for k in ("temperature", "top_p", "presence_penalty", "frequency_penalty"):
+ body.pop(k, None)
+
res = requests.post(
f"{self.api_base}/chat/completions",
headers=headers,
@@ -158,3 +197,448 @@ class DeepSeekBot(Bot, OpenAICompatibleBot):
if retry_count < 2:
return self.reply_text(session, args, retry_count + 1)
return {"completion_tokens": 0, "content": "我现在有点累了,等会再来吧"}
+
+ # ==================== Agent mode support ====================
+
+ def call_with_tools(self, messages, tools=None, stream: bool = False, **kwargs):
+ """
+ Call DeepSeek API with tool support for agent integration.
+
+ Handles:
+ - Claude → OpenAI message/tool format conversion (with reasoning_content round-trip)
+ - System prompt injection
+ - Streaming SSE with tool_calls + reasoning_content delta
+ - Thinking mode toggle and reasoning_effort for V4 models
+ """
+ try:
+ converted_messages = self._convert_messages_to_openai_format(messages)
+
+ system_prompt = kwargs.pop("system", None)
+ if system_prompt:
+ if not converted_messages or converted_messages[0].get("role") != "system":
+ converted_messages.insert(0, {"role": "system", "content": system_prompt})
+ else:
+ converted_messages[0] = {"role": "system", "content": system_prompt}
+
+ converted_tools = None
+ if tools:
+ converted_tools = self._convert_tools_to_openai_format(tools)
+
+ model = kwargs.pop("model", None) or self.args["model"]
+ max_tokens = kwargs.pop("max_tokens", None)
+
+ request_body = {
+ "model": model,
+ "messages": converted_messages,
+ "stream": stream,
+ }
+ if max_tokens is not None:
+ request_body["max_tokens"] = max_tokens
+
+ if converted_tools:
+ request_body["tools"] = converted_tools
+ request_body["tool_choice"] = kwargs.pop("tool_choice", "auto")
+
+ # Thinking mode (V4 only). Honour the toggle propagated by agent_bridge.
+ thinking_param = kwargs.pop("thinking", None)
+ reasoning_effort = kwargs.pop("reasoning_effort", None)
+ thinking_active = False
+
+ if self._model_supports_thinking(model):
+ # Default to enabled per DeepSeek docs unless caller explicitly disables.
+ thinking_param = thinking_param or {"type": "enabled"}
+ request_body["thinking"] = thinking_param
+ thinking_active = thinking_param.get("type") == "enabled"
+ if thinking_active:
+ # Default to "high"; allow caller override (e.g. "max" for heavy agent loops).
+ request_body["reasoning_effort"] = reasoning_effort or "high"
+ elif self._is_reasoner_model(model):
+ # R1 thinks unconditionally — no `thinking` field, but reasoning_content still flows.
+ thinking_active = True
+
+ # Strip params silently ignored under thinking mode to keep the wire clean.
+ if thinking_active:
+ for k in ("temperature", "top_p", "presence_penalty", "frequency_penalty"):
+ request_body.pop(k, None)
+ kwargs.pop(k, None)
+ else:
+ # Non-thinking path: forward standard sampling controls.
+ temperature = kwargs.pop("temperature", None)
+ if temperature is not None:
+ request_body["temperature"] = temperature
+ top_p = kwargs.pop("top_p", None)
+ if top_p is not None:
+ request_body["top_p"] = top_p
+
+ logger.debug(
+ f"[DEEPSEEK] API call: model={model}, "
+ f"tools={len(converted_tools) if converted_tools else 0}, "
+ f"stream={stream}, thinking={thinking_active}"
+ )
+
+ if stream:
+ return self._handle_stream_response(request_body)
+ else:
+ return self._handle_sync_response(request_body)
+
+ except Exception as e:
+ logger.error(f"[DEEPSEEK] call_with_tools error: {e}")
+ import traceback
+ logger.error(traceback.format_exc())
+
+ def error_generator():
+ yield {"error": True, "message": str(e), "status_code": 500}
+ return error_generator()
+
+ # -------------------- streaming --------------------
+
+ def _handle_stream_response(self, request_body: dict):
+ """Stream SSE chunks from DeepSeek and yield OpenAI-format deltas (with reasoning_content)."""
+ try:
+ headers = self._build_headers()
+ url = f"{self.api_base}/chat/completions"
+ response = requests.post(url, headers=headers, json=request_body, stream=True, timeout=180)
+
+ if response.status_code != 200:
+ error_msg = response.text
+ logger.error(f"[DEEPSEEK] API error: status={response.status_code}, msg={error_msg}")
+ yield {"error": True, "message": error_msg, "status_code": response.status_code}
+ return
+
+ current_tool_calls = {}
+ finish_reason = None
+
+ for line in response.iter_lines():
+ if not line:
+ continue
+
+ line = line.decode("utf-8")
+ if line.startswith("data: "):
+ data_str = line[6:]
+ elif line.startswith("data:"):
+ data_str = line[5:]
+ else:
+ continue
+ if data_str.strip() == "[DONE]":
+ break
+
+ try:
+ chunk = json.loads(data_str)
+ except json.JSONDecodeError as e:
+ logger.warning(f"[DEEPSEEK] JSON decode error: {e}, data: {data_str[:200]}")
+ continue
+
+ if chunk.get("error"):
+ error_data = chunk["error"]
+ error_msg = error_data.get("message", "Unknown error") if isinstance(error_data, dict) else str(error_data)
+ logger.error(f"[DEEPSEEK] stream error: {error_msg}")
+ yield {"error": True, "message": error_msg, "status_code": 500}
+ return
+
+ if not chunk.get("choices"):
+ continue
+ choice = chunk["choices"][0]
+ delta = choice.get("delta", {})
+
+ if choice.get("finish_reason"):
+ finish_reason = choice["finish_reason"]
+
+ # Reasoning content (thinking mode). Forward as its own delta so
+ # agent_stream.py can stitch it into a `thinking` block.
+ if delta.get("reasoning_content"):
+ yield {
+ "choices": [{
+ "index": 0,
+ "delta": {
+ "role": "assistant",
+ "reasoning_content": delta["reasoning_content"],
+ },
+ "finish_reason": None,
+ }]
+ }
+
+ if delta.get("content"):
+ yield {
+ "choices": [{
+ "index": 0,
+ "delta": {
+ "role": "assistant",
+ "content": delta["content"],
+ },
+ }]
+ }
+
+ if "tool_calls" in delta and delta["tool_calls"]:
+ for tool_call_chunk in delta["tool_calls"]:
+ index = tool_call_chunk.get("index", 0)
+ if index not in current_tool_calls:
+ current_tool_calls[index] = {
+ "id": tool_call_chunk.get("id", ""),
+ "name": tool_call_chunk.get("function", {}).get("name", ""),
+ "arguments": "",
+ }
+ if "function" in tool_call_chunk and "arguments" in tool_call_chunk["function"]:
+ current_tool_calls[index]["arguments"] += tool_call_chunk["function"]["arguments"]
+
+ yield {
+ "choices": [{
+ "index": 0,
+ "delta": {"tool_calls": [tool_call_chunk]},
+ }]
+ }
+
+ yield {
+ "choices": [{
+ "index": 0,
+ "delta": {},
+ "finish_reason": finish_reason,
+ }]
+ }
+
+ except requests.exceptions.Timeout:
+ logger.error("[DEEPSEEK] Request timeout")
+ yield {"error": True, "message": "Request timeout", "status_code": 500}
+ except Exception as e:
+ logger.error(f"[DEEPSEEK] stream response error: {e}")
+ import traceback
+ logger.error(traceback.format_exc())
+ yield {"error": True, "message": str(e), "status_code": 500}
+
+ # -------------------- sync --------------------
+
+ def _handle_sync_response(self, request_body: dict):
+ """Single-shot response. Yields a Claude-format dict for symmetry with stream path."""
+ try:
+ headers = self._build_headers()
+ request_body.pop("stream", None)
+ url = f"{self.api_base}/chat/completions"
+ response = requests.post(url, headers=headers, json=request_body, timeout=180)
+
+ if response.status_code != 200:
+ error_msg = response.text
+ logger.error(f"[DEEPSEEK] API error: status={response.status_code}, msg={error_msg}")
+ yield {"error": True, "message": error_msg, "status_code": response.status_code}
+ return
+
+ result = response.json()
+ message = result["choices"][0]["message"]
+ finish_reason = result["choices"][0]["finish_reason"]
+
+ response_data = {"role": "assistant", "content": []}
+
+ # Surface reasoning as a `thinking` block so the agent layer can persist it
+ # and round-trip it on tool-call turns (required by DeepSeek API).
+ if message.get("reasoning_content"):
+ response_data["content"].append({
+ "type": "thinking",
+ "thinking": message["reasoning_content"],
+ })
+
+ if message.get("content"):
+ response_data["content"].append({
+ "type": "text",
+ "text": message["content"],
+ })
+
+ if message.get("tool_calls"):
+ for tool_call in message["tool_calls"]:
+ try:
+ tool_input = json.loads(tool_call["function"]["arguments"])
+ except (json.JSONDecodeError, TypeError):
+ tool_input = {}
+ response_data["content"].append({
+ "type": "tool_use",
+ "id": tool_call["id"],
+ "name": tool_call["function"]["name"],
+ "input": tool_input,
+ })
+
+ if finish_reason == "tool_calls":
+ response_data["stop_reason"] = "tool_use"
+ elif finish_reason == "stop":
+ response_data["stop_reason"] = "end_turn"
+ else:
+ response_data["stop_reason"] = finish_reason
+
+ yield response_data
+
+ except requests.exceptions.Timeout:
+ logger.error("[DEEPSEEK] Request timeout")
+ yield {"error": True, "message": "Request timeout", "status_code": 500}
+ except Exception as e:
+ logger.error(f"[DEEPSEEK] sync response error: {e}")
+ import traceback
+ logger.error(traceback.format_exc())
+ yield {"error": True, "message": str(e), "status_code": 500}
+
+ # -------------------- format conversion --------------------
+
+ def _convert_messages_to_openai_format(self, messages):
+ """
+ Convert Claude-format messages (content blocks) to OpenAI format.
+
+ Crucially, for any assistant turn with tool_use, the accompanying `thinking`
+ block must be re-emitted as `reasoning_content` — DeepSeek returns 400 if
+ omitted on tool-call rounds.
+ """
+ if not messages:
+ return []
+
+ converted = []
+
+ for msg in messages:
+ role = msg.get("role")
+ content = msg.get("content")
+
+ if isinstance(content, str):
+ converted.append(msg)
+ continue
+
+ if not isinstance(content, list):
+ converted.append(msg)
+ continue
+
+ if role == "user":
+ has_tool_result = any(
+ isinstance(b, dict) and b.get("type") == "tool_result" for b in content
+ )
+ if has_tool_result:
+ text_parts = []
+ tool_results = []
+
+ for block in content:
+ if not isinstance(block, dict):
+ continue
+ if block.get("type") == "text":
+ text_parts.append(block.get("text", ""))
+ elif block.get("type") == "tool_result":
+ tool_call_id = block.get("tool_use_id") or ""
+ result_content = block.get("content", "")
+ if not isinstance(result_content, str):
+ result_content = json.dumps(result_content, ensure_ascii=False)
+ tool_results.append({
+ "role": "tool",
+ "tool_call_id": tool_call_id,
+ "content": result_content,
+ })
+
+ converted.extend(tool_results)
+
+ if text_parts:
+ converted.append({"role": "user", "content": "\n".join(text_parts)})
+ else:
+ converted.append(msg)
+
+ elif role == "assistant":
+ openai_msg = {"role": "assistant"}
+ text_parts = []
+ tool_calls = []
+ reasoning_parts = []
+
+ for block in content:
+ if not isinstance(block, dict):
+ continue
+ btype = block.get("type")
+ if btype == "text":
+ text_parts.append(block.get("text", ""))
+ elif btype == "tool_use":
+ tool_calls.append({
+ "id": block.get("id"),
+ "type": "function",
+ "function": {
+ "name": block.get("name"),
+ "arguments": json.dumps(block.get("input", {})),
+ },
+ })
+ elif btype == "thinking":
+ reasoning_parts.append(block.get("thinking", ""))
+
+ if text_parts:
+ openai_msg["content"] = "\n".join(text_parts)
+ elif not tool_calls:
+ openai_msg["content"] = ""
+
+ if tool_calls:
+ openai_msg["tool_calls"] = tool_calls
+ if not text_parts:
+ openai_msg["content"] = None
+
+ # Round-trip reasoning_content: required for tool-call turns,
+ # harmless (server-ignored) for plain text turns.
+ if reasoning_parts:
+ openai_msg["reasoning_content"] = "\n".join(reasoning_parts)
+
+ converted.append(openai_msg)
+ else:
+ converted.append(msg)
+
+ return converted
+
+ def _convert_tools_to_openai_format(self, tools):
+ """
+ Convert tools from Claude format to OpenAI format.
+
+ Claude: {name, description, input_schema}
+ OpenAI: {type: "function", function: {name, description, parameters}}
+ """
+ if not tools:
+ return None
+
+ converted = []
+ for tool in tools:
+ if "type" in tool and tool["type"] == "function":
+ converted.append(tool)
+ else:
+ converted.append({
+ "type": "function",
+ "function": {
+ "name": tool.get("name"),
+ "description": tool.get("description"),
+ "parameters": tool.get("input_schema", {}),
+ },
+ })
+ return converted
+
+ # -------------------- vision --------------------
+
+ def call_vision(self, image_url: str, question: str,
+ model: Optional[str] = None,
+ max_tokens: int = 1000) -> dict:
+ """Analyse an image via DeepSeek's OpenAI-compatible /chat/completions endpoint."""
+ try:
+ vision_model = model or self.args.get("model", const.DEEPSEEK_V4_PRO)
+ payload = {
+ "model": vision_model,
+ "max_tokens": max_tokens,
+ "messages": [{
+ "role": "user",
+ "content": [
+ {"type": "text", "text": question},
+ {"type": "image_url", "image_url": {"url": image_url}},
+ ],
+ }],
+ }
+ headers = self._build_headers()
+ resp = requests.post(
+ f"{self.api_base}/chat/completions",
+ headers=headers, json=payload, timeout=60,
+ )
+ if resp.status_code != 200:
+ return {"error": True, "message": f"HTTP {resp.status_code}: {resp.text[:300]}"}
+ data = resp.json()
+ if "error" in data:
+ return {"error": True, "message": data["error"].get("message", str(data["error"]))}
+ content = data.get("choices", [{}])[0].get("message", {}).get("content", "")
+ usage = data.get("usage", {})
+ return {
+ "model": vision_model,
+ "content": content,
+ "usage": {
+ "prompt_tokens": usage.get("prompt_tokens", 0),
+ "completion_tokens": usage.get("completion_tokens", 0),
+ "total_tokens": usage.get("total_tokens", 0),
+ },
+ }
+ except Exception as e:
+ logger.error(f"[DEEPSEEK] call_vision error: {e}")
+ return {"error": True, "message": str(e)}
diff --git a/models/deepseek/deepseek_session.py b/models/deepseek/deepseek_session.py
index 9500c8f4..0518d2fb 100644
--- a/models/deepseek/deepseek_session.py
+++ b/models/deepseek/deepseek_session.py
@@ -3,7 +3,7 @@ from common.log import logger
class DeepSeekSession(Session):
- def __init__(self, session_id, system_prompt=None, model="deepseek-chat"):
+ def __init__(self, session_id, system_prompt=None, model="deepseek-v4-pro"):
super().__init__(session_id, system_prompt)
self.model = model
self.reset()
diff --git a/run.sh b/run.sh
index 5bfacf51..82a26124 100755
--- a/run.sh
+++ b/run.sh
@@ -310,25 +310,26 @@ select_model() {
echo -e "${CYAN}${BOLD} Select AI Model${NC}"
echo -e "${CYAN}${BOLD}=========================================${NC}"
echo -e "${YELLOW}1) MiniMax (MiniMax-M2.7, MiniMax-M2.5, etc.)${NC}"
- echo -e "${YELLOW}2) Zhipu AI (glm-5.1, glm-5-turbo, glm-5, etc.)${NC}"
- echo -e "${YELLOW}3) Kimi (kimi-k2.6, kimi-k2.5, kimi-k2, etc.)${NC}"
- echo -e "${YELLOW}4) Doubao (doubao-seed-2-0-code-preview-260215, etc.)${NC}"
- echo -e "${YELLOW}5) Qwen (qwen3.6-plus, qwen3.5-plus, qwen3-max, qwq-plus, etc.)${NC}"
- echo -e "${YELLOW}6) Claude (claude-sonnet-4-6, claude-opus-4-7, claude-opus-4-6, etc.)${NC}"
- echo -e "${YELLOW}7) Gemini (gemini-3.1-flash-lite-preview, gemini-3.1-pro-preview, etc.)${NC}"
- echo -e "${YELLOW}8) OpenAI GPT (gpt-5.4, gpt-5.2, gpt-4.1, etc.)${NC}"
- echo -e "${YELLOW}9) LinkAI (access multiple models via one API)${NC}"
+ echo -e "${YELLOW}2) DeepSeek (deepseek-v4-pro, deepseek-v4-flash, etc.)${NC}"
+ echo -e "${YELLOW}3) Claude (claude-sonnet-4-6, claude-opus-4-7, claude-opus-4-6, etc.)${NC}"
+ echo -e "${YELLOW}4) Gemini (gemini-3.1-flash-lite-preview, gemini-3.1-pro-preview, etc.)${NC}"
+ echo -e "${YELLOW}5) OpenAI GPT (gpt-5.4, gpt-5.2, gpt-4.1, etc.)${NC}"
+ echo -e "${YELLOW}6) Zhipu AI (glm-5.1, glm-5-turbo, glm-5, etc.)${NC}"
+ echo -e "${YELLOW}7) Qwen (qwen3.6-plus, qwen3.5-plus, qwen3-max, qwq-plus, etc.)${NC}"
+ echo -e "${YELLOW}8) Doubao (doubao-seed-2-0-code-preview-260215, etc.)${NC}"
+ echo -e "${YELLOW}9) Kimi (kimi-k2.6, kimi-k2.5, kimi-k2, etc.)${NC}"
+ echo -e "${YELLOW}10) LinkAI (access multiple models via one API)${NC}"
echo ""
while true; do
read -p "Enter your choice [press Enter for default: 1 - MiniMax]: " model_choice
model_choice=${model_choice:-1}
case "$model_choice" in
- 1|2|3|4|5|6|7|8|9)
+ 1|2|3|4|5|6|7|8|9|10)
break
;;
*)
- echo -e "${RED}Invalid choice. Please enter 1-9.${NC}"
+ echo -e "${RED}Invalid choice. Please enter 1-10.${NC}"
;;
esac
done
@@ -357,23 +358,27 @@ read_api_base() {
configure_model() {
case "$model_choice" in
1) read_model_config "MiniMax" "MiniMax-M2.7" "MINIMAX_KEY" ;;
- 2) read_model_config "Zhipu AI" "glm-5.1" "ZHIPU_KEY" ;;
- 3) read_model_config "Kimi (Moonshot)" "kimi-k2.6" "MOONSHOT_KEY" ;;
- 4) read_model_config "Doubao (Volcengine Ark)" "doubao-seed-2-0-code-preview-260215" "ARK_KEY" ;;
- 5) read_model_config "Qwen (DashScope)" "qwen3.6-plus" "DASHSCOPE_KEY" ;;
- 6)
+ 2)
+ read_model_config "DeepSeek" "deepseek-v4-pro" "DEEPSEEK_KEY"
+ read_api_base "DEEPSEEK_BASE" "https://api.deepseek.com/v1"
+ ;;
+ 3)
read_model_config "Claude" "claude-sonnet-4-6" "CLAUDE_KEY"
read_api_base "CLAUDE_BASE" "https://api.anthropic.com/v1"
;;
- 7)
+ 4)
read_model_config "Gemini" "gemini-3.1-pro-preview" "GEMINI_KEY"
read_api_base "GEMINI_BASE" "https://generativelanguage.googleapis.com"
;;
- 8)
+ 5)
read_model_config "OpenAI GPT" "gpt-5.4" "OPENAI_KEY"
read_api_base "OPENAI_BASE" "https://api.openai.com/v1"
;;
- 9)
+ 6) read_model_config "Zhipu AI" "glm-5.1" "ZHIPU_KEY" ;;
+ 7) read_model_config "Qwen (DashScope)" "qwen3.6-plus" "DASHSCOPE_KEY" ;;
+ 8) read_model_config "Doubao (Volcengine Ark)" "doubao-seed-2-0-code-preview-260215" "ARK_KEY" ;;
+ 9) read_model_config "Kimi (Moonshot)" "kimi-k2.6" "MOONSHOT_KEY" ;;
+ 10)
read_model_config "LinkAI" "MiniMax-M2.7" "LINKAI_KEY"
USE_LINKAI="true"
;;
@@ -511,6 +516,8 @@ create_config_file() {
ARK_KEY="${ARK_KEY:-}" \
DASHSCOPE_KEY="${DASHSCOPE_KEY:-}" \
MINIMAX_KEY="${MINIMAX_KEY:-}" \
+ DEEPSEEK_KEY="${DEEPSEEK_KEY:-}" \
+ DEEPSEEK_BASE="${DEEPSEEK_BASE:-https://api.deepseek.com/v1}" \
USE_LINKAI="${USE_LINKAI:-false}" \
LINKAI_KEY="${LINKAI_KEY:-}" \
FEISHU_APP_ID="${FEISHU_APP_ID:-}" \
@@ -545,6 +552,8 @@ base = {
'ark_api_key': e('ARK_KEY', ''),
'dashscope_api_key': e('DASHSCOPE_KEY', ''),
'minimax_api_key': e('MINIMAX_KEY', ''),
+ 'deepseek_api_key': e('DEEPSEEK_KEY', ''),
+ 'deepseek_api_base': e('DEEPSEEK_BASE'),
'voice_to_text': 'openai',
'text_to_voice': 'openai',
'voice_reply_voice': False,