You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5.5 KiB
5.5 KiB
Qwen3-VL 工具调用兼容性修复
问题描述
选择 Qwen3-VL-8B-Instruct 模型发送消息后,模型回复被误判为"仅返回思考过程"而被删除,用户看不到任何回复内容。
根本原因
Qwen3-VL 不支持 function calling/tools。当请求携带 tools 参数时,SiliconFlow 平台会将模型输出放到 reasoning_content 字段而非 content 字段:
// 带 tools 时
{"delta":{"content":null,"reasoning_content":"Hello"}}
// 不带 tools 时
{"delta":{"content":"Hello"}}
同时前端 validateAssistantContent 只检查 content 是否为空,未考虑 reasoning 类型的 part,导致只有思考过程的消息被误删。
解决方案
1. parseMode 重构
将 parseMode 从 openai/anthropic 改为 openai/openai-compatible:
openai:使用@ai-sdk/openai的createOpenAI(原生 OpenAI API)openai-compatible:使用@ai-sdk/openai-compatible的createOpenAICompatible(兼容 API,如 SiliconFlow、DeepSeek)
2. 模型表增加 supportsTools 字段
llmModels 表新增 supportsTools 字段(integer("supports_tools").default(1).notNull()):
1(true):模型支持工具调用,请求时正常传 tools 参数0(false):模型不支持工具调用,请求时不传 tools 参数
3. 前端工具按钮禁用
不支持工具的模型,工具开关按钮自动禁用,tooltip 显示"当前模型不支持工具调用"。
4. 前端 validateAssistantContent 修复
增加 reasoning 类型检查,避免只有思考过程的消息被误删。
改动文件清单
数据库
| 文件 | 改动 |
|---|---|
packages/drizzle-pkg/lib/schema/llm.ts |
LlmParseModes 改为 ["openai", "openai-compatible"];llmModels 增加 supportsTools 字段 |
packages/drizzle-pkg/migrations/0018_colossal_barracuda.sql |
迁移文件:ALTER TABLE llm_models ADD supports_tools |
服务端 - resolveModel 实现
| 文件 | 改动 |
|---|---|
server/api/agent/chat/index.post.ts |
resolveModel:openai 用 createOpenAI,openai-compatible 用 createOpenAICompatible;streamText 中 supportsTools=false 时不传 tools |
server/api/llm/chat/index.post.ts |
同步 resolveModel 和 tools 逻辑 |
server/service/agent/title.ts |
同步 resolveModel |
服务端 - Service 层
| 文件 | 改动 |
|---|---|
server/service/llm/index.ts |
LlmModelRow 接口加 supportsTools;listSystemModels、listAllEnabledModelsForUser 查询加 supportsTools;createModel、createSystemModel、updateModel 加 supportsTools 字段 |
服务端 - API 接口
| 文件 | 改动 |
|---|---|
server/api/admin/llm/providers/index.post.ts |
parseMode 校验更新为 ["openai", "openai-compatible"] |
server/api/admin/llm/models/index.post.ts |
加 supportsTools 参数 |
server/api/llm/models/[providerId].post.ts |
加 supportsTools 参数 |
server/api/llm/models/detail/[id].put.ts |
加 supportsTools 参数 |
server/api/llm/models/index.get.ts |
返回值包含 supportsTools(通过 service 层) |
server/api/llm/chat/models.get.ts |
查询加 supportsTools 字段 |
server/api/agent/models/index.get.ts |
返回值加 supportsTools |
前端
| 文件 | 改动 |
|---|---|
app/pages/index.vue |
ModelOption 加 supportsTools;新增 currentModelSupportsTools computed;enableTools getter 不支持时返回 false;传 tools-disabled prop |
app/components/agent/AgentChatArea.vue |
加 toolsDisabled prop,传给 AgentInput |
app/components/agent/AgentInput.vue |
加 toolsDisabled prop;工具按钮禁用逻辑和样式 |
app/composables/useAgentChat.ts |
validateAssistantContent 增加 hasReasoning 检查 |
app/composables/useLlmChat.ts |
validateAssistantContent 增加 hasReasoning 检查 |
app/pages/settings/llm-config/index.vue |
provider 编辑页面 parseMode 选项更新;模型编辑表单加 supportsTools 下拉选项 |
app/pages/settings/llm-test/index.vue |
ModelOption 加 supportsTools;工具开关不支持时禁用 |
数据库现状
- 数据库路径:
packages/drizzle-pkg/db.sqlite - provider 配置:
- deepseek(id=2, parseMode=
openai-compatible) - siliconflow(id=3, parseMode=
openai-compatible)
- deepseek(id=2, parseMode=
- 模型配置:
- deepseek-v4-flash(id=2, supportsTools=1)
- Qwen3-VL-8B-Instruct(id=4, supportsTools=0)
关键技术决策
createOpenAI返回类型与LanguageModel不完全兼容:需用as unknown as LanguageModel转换enableThinking/enableTools改为请求体参数优先于 session 配置:更灵活的控制方式openai-compatible作为默认 parseMode:大多数第三方 API 都是 OpenAI 兼容协议
测试验证
- Qwen3-VL-8B-Instruct 发送消息正常返回内容(不再只有思考过程)
- Qwen3-VL-8B-Instruct 工具按钮禁用,tooltip 显示"当前模型不支持工具调用"
- deepseek-v4-flash 工具按钮正常启用,可开关工具
- deepseek-v4-flash 工具列表正常显示(fetch_html、calculator、uuid 等)
后续注意事项
server/api/llm/providers/[id].models.get.ts中仍有anthropic分支代码,但不会命中(parseMode 不再有 "anthropic"),走 else 分支app/pages/index.vue第 72 行硬编码enableThinking: () => false- 新增模型时默认
supportsTools=1,需在管理后台手动改为 0 如果模型不支持工具