综合

Qwen 已返回 `tool_calls`,为什么你的行情回答仍可能不可信?

作者: TickDB Research · 发布: 2026/5/27 · 阅读: 3

标签: C 类, 掘金, AI 工具

摘要:

Qwen 返回 tool_calls,不代表行情查询已经成功。本文从掘金开发者常见排错场景出发,拆解“触发工具、应用执行、结果校验、工具回填、最终回答”的最小可信链路,并给出未触发工具、查询失败或空结果、回填错误三个必须阻断价格回答的失败分支。TickDB 仅作为应用端只读行情数据路径示例出现。

你在日志里看到了这样的返回:

{
  "tool_calls": [
    {
      "function": {
        "name": "get_market_snapshot",
        "arguments": "{\"symbol\":\"AAPL.US\"}"
      }
    }
  ]
}

这只能说明一件事:模型提出了一个工具调用请求。

它不等于应用程序已经拿到行情,不等于返回内容有效,也不等于最终回答确实基于这次查询结果生成。对于“当前价格是多少”这类问题,只要工具链路没有完整闭环,模型就不应该继续输出确定价格。

tool_calls 不是行情结果

百炼官方文档给出的 Function Calling 流程,本质上由应用程序完成闭环:

步骤发生了什么能否证明行情可信
1应用把用户问题和工具定义发给 Qwen不能
2Qwen 返回工具名称与参数,即 tool_calls不能
3应用实际执行只读行情查询仍需检查结果
4应用把工具输出作为 role="tool" 消息回填形成回答依据
5应用再次请求 Qwen 生成自然语言答案仅在前面成功时可回答

容易忽略的是第 3、4 步:真正访问行情数据的是你的应用,而不是 tool_calls 本身。

最小可信调用链路

对于必须依赖当前行情的数据问题,可以把链路收紧为以下五步:

环节最小要求失败时的动作
识别问题判断请求是否必须读取当前行情不能把静态知识当当前价格
触发工具对已确认需要行情的分支要求工具调用未触发则停止报价格
执行查询应用调用只读行情适配器,例如接入 TickDB REST 查询快照请求失败或空结果则停止
回填证据将成功结果绑定原始 tool_call_id 回填给模型未正确回填则停止
生成回答仅基于工具返回组织自然语言不扩展为交易判断

这里 TickDB 的位置很简单:它可以是应用端行情适配器实际查询的数据路径之一。Qwen 负责决定要调用什么工具并整理回答,应用负责执行和校验查询,两者不能混写成“模型自己知道行情”。

核心代码片段:重点在阻断条件

以下为教学用核心片段,不是完整可运行代码。Qwen 的 OpenAI 兼容调用形式依据百炼官方文档;query_snapshot_via_readonly_adapter() 为故意省略的应用端执行器,可在审核后接入并核验 TickDB REST 请求、鉴权、字段与异常处理。

import json
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

tools = [{
    "type": "function",
    "function": {
        "name": "get_market_snapshot",
        "description": "读取指定标的的当前行情快照,只用于只读查询。",
        "parameters": {
            "type": "object",
            "properties": {"symbol": {"type": "string"}},
            "required": ["symbol"],
        },
    },
}]

messages = [{"role": "user", "content": "查询 AAPL.US 当前价格"}]
first = client.chat.completions.create(
    model="qwen3.6-plus",
    extra_body={"enable_thinking": False},
    messages=messages,
    tools=tools,
    tool_choice="required",  # 仅用于已确认必须查行情的分支
)

assistant_msg = first.choices[0].message
if not assistant_msg.tool_calls:
    raise RuntimeError("未触发行情工具,禁止输出当前价格")

messages.append(assistant_msg)
call = assistant_msg.tool_calls[0]
args = json.loads(call.function.arguments)

# 应用端只读数据适配器:可接 TickDB REST;此处省略真实网络实现。
result = query_snapshot_via_readonly_adapter(args)

if not result.get("ok") or not result.get("quote"):
    raise RuntimeError("查询失败或无可验证行情,禁止输出当前价格")

messages.append({
    "role": "tool",
    "tool_call_id": call.id,
    "content": json.dumps(result, ensure_ascii=False),
})

final = client.chat.completions.create(
    model="qwen3.6-plus",
    extra_body={"enable_thinking": False},
    messages=messages,
    tools=tools,
)  # 总结工具结果阶段,不继续强制工具调用
print(final.choices[0].message.content)

片段里的关键不是函数名,而是三条规则:

  1. 没有真实工具结果,就没有当前价格结论。
  2. 工具失败或结果为空,应该明确告诉用户“当前无法验证”,而不是让模型补写一个价格。
  3. 工具结果必须绑定正确的 tool_call_id 回填,之后的回答才有证据来源。

至少三个常见失败分支

失败分支你会看到什么为什么不可信正确处理
未触发工具模型直接返回一段价格回答,tool_calls 为空没有任何实时查询证据对行情查询分支要求调用工具;仍无调用则停止输出价格
工具请求失败或返回空结果超时、权限失败、适配器报错,或返回无可用行情有调用意图,但没有可消费的数据返回“行情暂不可验证”,记录错误,不进入价格总结
结果未被正确回填应用拿到了数据,却没有添加 role="tool" 消息,或绑定错 tool_call_id最终模型上下文里没有对应证据保留原始 assistant 工具调用消息,按调用 ID 回填结果后再请求总结
结果存在但回答越界工具只返回快照,模型却继续输出买卖判断或价格预测数据查询不等于决策依据限制回答范围,只描述查询结果与可验证边界

一个更实用的验收清单

上线前,不妨对行情工具调用链逐项检查:

  • 当前行情问题是否被路由到必须查询工具的分支。
  • tool_calls 是否只被视为请求,而不是查询成功标志。
  • 应用端查询是否为只读操作,并处理失败、超时和空结果。
  • 返回值是否作为工具消息正确回填到对应调用。
  • 最终回答是否只描述得到的数据,不补写不存在的结果。
  • 日志是否足以区分“模型没调工具”“工具没数据”“回填出错”三类问题。

边界说明

本文讨论的是工具调用链路的可信性设计,不提供交易建议,也不把一次行情快照扩展成趋势、收益或买卖判断。TickDB 在这里仅作为应用端可以接入的只读行情数据路径示例;实际接入时,仍应以当前接口文档和审核后的请求实现为准。

总结

看到 tool_calls,只能证明 Qwen 知道“该去查”。

只有应用成功执行查询、确认结果可用、正确回填工具输出,并让模型基于该结果回答,当前行情结论才拥有最基本的证据闭环。

对于行情类问答,最重要的工程规则不是“尽量回答”,而是:没有可验证工具结果时,明确停止报价格。

标签:

Qwen Function Calling tool_calls Python API 行情查询 排错

阿里云百炼 Function Calling 官方文档

通过 TickDB API 获取实时行情数据

一个 API 接入外汇、加密货币、美股、港股、A股、贵金属和全球指数的实时行情。支持 WebSocket 低延迟推送,免费开始使用。

免费领取 API Key查看 API 文档

相关文章