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

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 重构

parseModeopenai/anthropic 改为 openai/openai-compatible

  • openai:使用 @ai-sdk/openaicreateOpenAI(原生 OpenAI API)
  • openai-compatible:使用 @ai-sdk/openai-compatiblecreateOpenAICompatible(兼容 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 resolveModelopenaicreateOpenAIopenai-compatiblecreateOpenAICompatiblestreamTextsupportsTools=false 时不传 tools
server/api/llm/chat/index.post.ts 同步 resolveModel 和 tools 逻辑
server/service/agent/title.ts 同步 resolveModel

服务端 - Service 层

文件 改动
server/service/llm/index.ts LlmModelRow 接口加 supportsToolslistSystemModelslistAllEnabledModelsForUser 查询加 supportsToolscreateModelcreateSystemModelupdateModelsupportsTools 字段

服务端 - 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 ModelOptionsupportsTools;新增 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 ModelOptionsupportsTools;工具开关不支持时禁用

数据库现状

  • 数据库路径:packages/drizzle-pkg/db.sqlite
  • provider 配置:
    • deepseek(id=2, parseMode=openai-compatible
    • siliconflow(id=3, parseMode=openai-compatible
  • 模型配置:
    • deepseek-v4-flash(id=2, supportsTools=1)
    • Qwen3-VL-8B-Instruct(id=4, supportsTools=0)

关键技术决策

  1. createOpenAI 返回类型与 LanguageModel 不完全兼容:需用 as unknown as LanguageModel 转换
  2. enableThinking/enableTools 改为请求体参数优先于 session 配置:更灵活的控制方式
  3. 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 如果模型不支持工具