一个测连通的按钮,把 reasoning 模型挡在了门外
如果你用过开源 AI 平台,肯定见过这样的设计——配置一个新模型时,UI 上有个"测试连接"按钮:你填好 base_url、api_key、模型名,点一下,平台后端发个最小成本的请求验证它能不能跑。
通常这个请求长这样:
awaitllm.chat([{"role":"user","content":"Hello"}],max_tokens=1)为什么max_tokens=1?因为只是要"验证连通性"——只要 API 返回 200、能拿到一个 token,就算连上。便宜、快、对模型供应商也友好。
这套设计在传统 chat 模型上工作了多年。直到 reasoning 模型登场。
最近 Xagent 通过两个连续合并的 PR 修复了这个问题:
- PR #625:fix(xinference): handle reasoning models in chat response and test-connection(
d8794f2已 merge) - PR #626:fix(openai): fall back to reasoning_content when content is empty(
3ca54bb已 merge)
这两个 PR 看起来在修同一件事,但合在一起读,能讲清楚一个非常微妙的兼容性故事——以及一段关于 PR review 的好示范。
故事开始:用户连不上 qwen3.6_27b
具体复现:用户在 Xagent UI 上配置一个 Xinference 服务上的 reasoning 模型qwen3.6_27b,点"测试连接",前端报错:
Invalid Xinference response: { 'id': 'chat...', 'choices': [{ 'message': { 'role': 'assistant', 'content': '', 'reasoning_content': 'Here' }, 'finish_reason': 'length' }], 'usage': {'prompt_tokens': 11, 'completion_tokens': 1} }看起来响应是好的——HTTP 200、有 choices、有 usage。问题在content=''和reasoning_content='Here'。
Reasoning 模型的"脑内独白"机制
Reasoning 模型(qwen3-thinking、deepseek-r1、qwen3.x_*、openai o1/o3 等)在生成最终答案之前,会先在reasoning_content字段里做"思考"——这部分是模型的草稿、推理链、自我对话;最终答案才放到content里。
正常完成时,响应是这样:
{"content":"答案是 42","reasoning_content":"需要计算 6×7..."}但当max_tokens=1时,模型刚开始 reasoning 就被截断——reasoning_content="Here"(thinking 的第一个 token),content=""(还没开始写最终答案),finish_reason="length"