ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

日志显示模型读取到了我写的tools但是并没实际调用?我使用的模型是千问3.5-397B-A17B,使用的langchain的ChatOpenAi,创建的deepagent,同时搭配了我的tools?

日志显示模型读取到了我写的tools但是并没实际调用?我使用的模型是千问3.5-397B-A17B,使用的langchain的ChatOpenAi,创建的deepagent,同时搭配了我的tools? 本文收录于 《全栈 Bug 调优实战版》 专栏。专栏聚焦真实项目中的各类疑难 Bug从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者还是负责复杂项目的资深工程师都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论助你稳步进阶、放大技术价值。特别说明文中问题案例来源于真实生产环境与公开技术社区并结合多位一线资深工程师与架构师的长期实践经验经过人工筛选与AI系统化智能整理后输出。文中的解决方案并非唯一“标准答案”而是兼顾可行性、可复现性与思路启发性的实践参考供你在实际项目中灵活运用与演进。欢迎订阅本专栏一次订阅后专栏内所有文章可永久免费阅读后续更新内容皆不用再次订阅持续更新中。 问题描述详细问题描述如下我的日志显示模型读取到了我写的tools但是并没实际调用遇到一个问题。我使用的模型也是千问3.5-397B-A17B。使用的是langchain的ChatOpenAi创建的deepagent同时搭配了我的tools。我的日志显示模型读取到了我写的tools但是并没实际调用这是什么原因全文目录 问题描述 请知悉如下方案不保证一定适配你的问题✅️问题理解✅️问题解决方案方案 A先确认是不是“模型自主选择不调用”这是最常见原因方案 B你可能只做了“把 tools 发给模型”但没有完成真正的“工具执行闭环”方案 C兼容层没完全跑通尤其是 ChatOpenAI OpenAI-compatible 服务的组合方案 DThinking / ReAct / 输出模板冲突导致“看起来像没调工具”方案 E工具 schema / 入参设计不利于调用模型“看得见但不愿意用”✅️问题延伸✅️问题预测✅️小结 结语 互动说明 文末福利技术成长加速包 Who am I? 请知悉如下方案不保证一定适配你的问题如下是针对上述问题进行专业角度剖析答疑不喜勿喷仅供参考✅️问题理解你这个问题本质上不等于“工具没注册成功”也不等于“LangChain 没把 tools 传给模型”。更准确地说它通常发生在下面这四层中的某一层工具确实已经传给模型了所以你在日志里看到了 tools。模型也看到了工具定义但它判断“当前问题不一定需要工具”于是直接自然语言回答没有返回tool_calls。模型其实返回了工具调用意图但你的代码路径没有进入真正的“工具执行闭环”。兼容层/推理服务/输出解析没有把工具调用结果按 OpenAI 规范稳定地返回给 LangChain导致你看到的是“读到了 tools但实际没调用”。LangChain 官方文档明确说明bind_tools只是把工具提供给模型是否调用默认由模型自己决定如果你不是用 agent而只是单独调用 model那么拿到tool_calls后还需要你自己执行工具并把ToolMessage再喂回模型。Deep Agents 本质上也是一个 tool-calling loop只是帮你把这个循环包装起来了同时它要求底层模型本身支持 tool calling。再说得更直白一点“日志里看到 tools” 只代表“工具被放进请求里了”不代表“模型决定调用了它”。阿里云百炼的 Function Calling 官方文档也明确写了当模型判断需要工具时会返回工具调用指令当模型判断不需要工具时会直接返回自然语言回复。并且tool_choice默认就是auto也就是让模型自己选。官方还特别提到即使你已经在tools里描述了工具在System Message里进一步强调“什么时候必须调用哪个工具”通常会明显提高工具调用准确率。另外你用的是ChatOpenAI。LangChain 官方也特别提醒ChatOpenAI面向的是官方 OpenAI API 规范如果你接的是第三方 OpenAI-compatible 服务非标准字段不会被它自动提取或保留。对于 Qwen 这类支持 OpenAI 兼容接口的模型这通常没问题但一旦你的底层服务在 tool calling、thinking 字段、message 格式、stream chunk 组装上有细微偏差就可能出现“模型端像是做了事但 LangChain 侧没收到规范化的tool_calls”这种假象。如果你想先建立一个最稳的心智模型可以把调用链路理解成这样你现在的问题大概率卡在E或G-H之间而不是卡在C-D。这就是为什么“看到 tools”但“没调用”的现象非常常见。LangChain、阿里云百炼和 Qwen 的官方资料三边机制是对得上的。✅️问题解决方案方案 A先确认是不是“模型自主选择不调用”这是最常见原因这是我认为命中率最高的原因。默认情况下LangChain 的bind_tools和阿里云百炼的 Function Calling 都不是“看到工具就一定调用”而是“模型自己决定要不要调用”。LangChain 文档写得很明确工具绑定后模型可以调用但不是必须调用如果你要强制它调用可以设置tool_choiceany或指定某个工具。阿里云百炼文档也写明tool_choice默认是auto模型会自主判断。这会出现几个非常典型的误区误区 1工具描述太弱比如你定义了一个search_db(query: str)description 只是 “search something”。这种描述对模型来说太模糊了。模型可能会觉得“我不一定非要调这个我直接答也行。”误区 2System Prompt 没明确工具策略阿里云百炼官方明确建议除了tools里的 schema最好在System Message里再强调一遍“什么场景必须调用工具”。这不是可有可无而是非常实用。误区 3用户问题本身允许模型直接胡诌/泛答如果你问的是“介绍一下你自己”“帮我分析一下这个问题”“你怎么看 LangChain”这类问题本身不强依赖工具模型当然可能直接回答。所以第一步不是先改 deepagent而是先做一个最小化实验fromlangchain_openaiimportChatOpenAIfromlangchain.toolsimporttooltooldefget_order_status(order_id:str)-str:Query the exact order status by order ID. Must be used whenever the user asks about order status, logistics, shipment, or delivery progress.returnforder{order_id}, statusshippedllmChatOpenAI(modelqwen3.5-397b-a17b,base_url你的兼容接口地址,api_key你的key,temperature0)msgllm.bind_tools([get_order_status],tool_choiceany# 关键先强制任意工具调用验证底层链路通不通).invoke(查询订单 A10086 的最新物流状态)print(content:,msg.content)print(tool_calls:,msg.tool_calls)print(additional_kwargs:,msg.additional_kwargs)如果这里都拿不到tool_calls那你就先别怀疑 deepagent问题基本在下面几类之一模型/服务端对 tool calling 支持不完整OpenAI-compatible 接口实现不标准LangChain / OpenAI SDK / 服务端版本不匹配你的工具 schema 被序列化后不符合预期。这一步非常关键因为它能把“deepagent 问题”和“底层 model/provider/tool-calling 问题”直接切开。如果这个最小实验可以稳定拿到tool_calls那说明底层模型调用链路是通的下一步再回去查 deepagent 配置。这一方案的核心修复动作把 tool description 写成“什么时候必须用”不是只写“它是什么”。在 system prompt 里明确哪些问题必须调用工具没有工具结果不得编造需要精确信息时优先使用工具。首轮排查时把temperature0。先用tool_choiceany或指定具体工具验证链路。等链路通了再恢复auto。这些做法和 LangChain 的工具调用机制、阿里云百炼的 Function Calling 建议是一致的。方案 B你可能只做了“把 tools 发给模型”但没有完成真正的“工具执行闭环”这个问题非常多而且特别隐蔽。LangChain 官方文档明确区分了两件事把工具绑定给模型执行模型返回的工具调用再把工具结果回传给模型如果你只是这样写msgllm.bind_tools(tools).invoke(messages)print(msg)那你只完成了第一阶段让模型产生工具调用意图。如果不用 agent你必须自己读取msg.tool_calls执行对应工具生成ToolMessage再次调用模型官方文档里这整个闭环写得很清楚。Qwen 官方的 function calling 文档也明确给出了同样的两阶段流程先拿到tool_calls再执行工具再把tool_call_id对应的tool消息追加回去再次请求模型得到最终答案。一个正确的最小闭环大概像这样fromlangchain_openaiimportChatOpenAIfromlangchain.toolsimporttooltooldefget_weather(city:str)-str:Get real-time weather for a city. Must be used for current weather questions.returnf{city}: 26C, sunnyllmChatOpenAI(modelqwen3.5-397b-a17b,base_url你的接口,api_key你的key,temperature0)modelllm.bind_tools([get_weather],tool_choiceany)messages[{role:user,content:上海现在天气怎么样}]# 1) 模型先返回 tool_callsai_msgmodel.invoke(messages)print(first tool_calls:,ai_msg.tool_calls)# 2) 执行工具messages.append(ai_msg)fortcinai_msg.tool_calls:resultget_weather.invoke(tc)messages.append(result)# 3) 再喂回模型拿最终答案final_msgmodel.invoke(messages)print(final_msg.content)如果你用的是deepagent / create_deep_agent理论上 agent loop 会帮你做这件事因为 Deep Agents 本质上就是 tool-calling loop。可一旦你实际代码里没有真正走 agent 的invoke路径中间自己截断了消息流用了自定义 middleware 改坏了 message或者你看的日志只是“模型层日志”不是“agent 执行层日志”你就会出现一种错觉“模型看到了 tools但没执行。”实际上可能是“模型返回了工具调用agent 没继续跑”或者“你只看到了第一跳”。所以你一定要检查这几个点检查点 1你到底调用的是deepagent.invoke(...)还是llm.invoke(...)如果是后者那就没有 agent loop。检查点 2日志里有没有tool_calls字段而不是只有 request payload 里的tools这两个不是一回事。检查点 3如果有tool_calls有没有后续roletool的消息被 append 回去没有这一步模型永远不会“完成实际调用后的总结”。检查点 4你看的 trace 是不是只截到了首个模型返回很多人只看第一段响应就误以为“没调用”。这类问题的定位方法非常简单在日志中分别打印下面三样print(REQUEST.tools ,tools)print(AI.tool_calls ,ai_msg.tool_calls)print(MESSAGES.after_tool ,messages)只要你把这三步的日志拆开问题基本当场就能现形。方案 C兼容层没完全跑通尤其是 ChatOpenAI OpenAI-compatible 服务的组合这是第二大类原因而且在 Qwen / 自建服务 / 第三方兼容接口里特别常见。LangChain 官方明确说明ChatOpenAI面向的是官方 OpenAI 规范。如果第三方服务存在非标准字段不同的 chunk 结构tool_calls 返回格式略有偏差reasoning / content / tool_call 混排stream 模式下 tool_call chunk 不完整那么 LangChain 这层未必能完美解析。阿里云百炼官方文档说明qwen3.5-397b-a17b是支持 OpenAI 兼容接口的也支持通过langchain_openai访问。也就是说如果你接的是百炼官方兼容接口链路理论上是可行的如果你接的是自建 OpenAI-compatible 服务就不能自动推定它的 tool calling 行为一定等价于百炼官方。所以这类问题一定要做分层验证第一层绕过 LangChain直接用官方 OpenAI Python SDK 调接口如果 SDK 直连都拿不到tool_calls那就不是 LangChain 的锅。第二层OpenAI SDK 正常但 LangChain 不正常那就重点查langchain-openai版本openaiSDK 版本stream/non-stream 差异provider 返回字段是否与 OpenAI 规范一致。第三层LangChain 普通 bind_tools 正常deepagent 不正常那就是 deepagent 这层配置或消息流问题而不是 provider 问题。建议你用下面这个顺序排查OpenAI SDK 直连 provider - LangChain ChatOpenAI bind_tools - create_agent / create_deep_agent谁先坏问题就在谁那一层。如果你接的是阿里云百炼官方接口先确认这些基础项base_url是否是官方兼容地址模型名是否正确langchain-openai是否升级到较新版本是否用非流式先验证是否把 provider 特有参数塞进了不兼容的位置。阿里云官方已经给出langchain_openai的接入方式和兼容地址先完全对齐官方示例再叠加 tool calling成功率最高。方案 DThinking / ReAct / 输出模板冲突导致“看起来像没调工具”你最后那句“system hint: start deep thinking, please always use the thinking mode”很值得注意。Qwen 官方关于 function calling 的文档里专门提到对于reasoning models不推荐使用依赖 stopwords 的 tool-call template比如某些 ReAct 风格解析因为模型可能会先输出 thought再输出工具调用而 stopword/解析器可能在 thought 段就误判或截断导致工具调用异常。官方还明确说了Qwen3 的 function calling 很大程度上依赖 prompt engineering / 模板不保证在任何场景都严格遵守协议。这意味着什么意味着如果你的 deepagent 或自定义 agent 流程里存在下面这些情况就很危险你在 system prompt 里强塞了很多“先思考、再分步输出”的格式要求你使用了自定义 ReAct parser你期待模型先输出一段可见思考再紧接着按固定格式 tool call你的服务端/中间件会清洗或截断 thought 段你在流式输出里按文本 token 解析工具调用而不是按tool_call_chunks/tool_calls结构解析。这种情况下实际发生的可能是模型内部已经进入“思考 - 工具调用”的意图路径但你的链路把它当普通文本了或者在 thought 段把后面的 tool_call 结构给“吃掉”了最终你只看到“它知道有 tools但没调用”。所以我会给你一个非常实际的建议排查阶段先关掉复杂思维模板先做纯工具调用验证。也就是temperature0system prompt 简短明确不加额外 ReAct 模板不做复杂输出约束非流式优先只保留一个极容易触发的工具等这条链路跑通以后再逐步恢复 thinking mode / 深度推理风格提示词。很多人一上来就“复杂 prompt 多工具 streaming reasoning deepagent 兼容接口”一起上最后根本不知道是哪层坏了。你现在最需要的是降维定位不是继续堆功能。方案 E工具 schema / 入参设计不利于调用模型“看得见但不愿意用”这个原因不如前几个高频但非常常见。工具调用本质上依赖三样东西namedescriptionparameters(JSON Schema)LangChain 官方对 tool calling 的定义里明确提到 schema 是核心组成部分Qwen 官方文档也强调 tool format / function format 里description和parameters都是模型理解工具用途的关键。从机制上可以推断出几个坑坑 1description 写得像开发者给开发者看的不像给模型看的差的写法query db好的写法Query the order database by exact order ID. Must be used when the user asks for exact order status, shipment progress, or delivery details. Do not guess order status without calling this tool.坑 2参数设计太复杂比如嵌套层级太深、可选字段太多、字段名太抽象。模型越难构造参数越可能直接放弃调用。坑 3一个工具包揽太多职责比如同一个工具既查用户、又查订单、又改状态、又发通知。模型会不知道什么时候该用它。坑 4多个工具职责边界重叠比如search_orderquery_order_statusfetch_order_info三个都像一个意思。模型很容易犹豫。最佳实践是一个工具只做一件事description 明确“适用场景”和“禁止直接猜测”参数字段名业务语义强required 字段尽量少但足够枚举值尽量明确多工具之间边界清晰。这类优化虽然看起来像“提示词工程”但对 function calling 的命中率影响非常大Qwen 官方也明确承认这件事高度依赖 prompt / template 设计。✅️问题延伸这个问题再往深一层其实是**“工具可见性”** 和“工具执行性”的区别。很多开发者的日志系统只记录了request payload 中的tools最终 assistant content但没有记录choices[0].message.tool_callsinvalid_tool_callsroletool消息再次调用模型前后的 messages 差异于是会产生非常严重的认知误差只要 tools 出现在请求里就以为 agent 已经“具备工具能力”。其实不是。真正决定是否调用工具的是下面这三段链路是否全部成立模型选择阶段模型是否产生tool_calls执行阶段你的框架是否真的执行了对应函数回灌阶段工具结果是否以正确的tool_call_id回传给模型任何一段断掉表象都会接近“工具没调用”。这个机制在 LangChain 官方 tool-calling loop、阿里云百炼 Function Calling 两阶段流程、以及 Qwen 官方 function calling 说明里都是一致的。再延伸一点说Deep Agent 不是魔法。它不是“把 tools 塞进去就自动百分百调用”它只是把 LangGraph/agent 的调度循环做了更强的封装。官方也明确说了 Deep Agents 依然是同一个 core tool calling loop只是多了规划、上下文管理、子代理等能力。所以如果你的底层模型 tool calling 行为本身不稳定Deep Agent 只会把问题放大不会替你掩盖。✅️问题预测基于你现在的描述我对你这个问题的高概率根因排序如下预测 1最高概率你现在只是把 tools 传入了模型但模型在auto模式下判断“可以直接答”所以没返回tool_calls。表现日志里有 tools请求发出去了回复是自然语言tool_calls[]。这和 LangChain、阿里云百炼的默认机制完全一致。预测 2你的 deepagent 路径没有真正执行到工具闭环或者你只看到了第一跳日志。表现首轮模型可能已经返回了工具意图但执行器没跑或者 messages 没追加roletool。这是 agent 工程里非常典型的接线错误。预测 3你使用了 Qwen 的 thinking mode / 自定义 ReAct 风格模板 / 流式解析导致工具调用被 thought 段干扰或解析失败。表现日志里有大量 reasoning/thinking 文本但没有稳定结构化tool_calls。Qwen 官方对 reasoning model 的 function calling 确实给过这类提醒。预测 4你接的不是百炼官方兼容接口而是某个自建或第三方 OpenAI-compatible 服务该服务“聊天能跑”但 tool calling 的 OpenAI 兼容度不够。表现普通问答正常工具调用时表现异常OpenAI SDK 和 LangChain 表现不一致。这时问题更多在 provider/serving 层而不是 LangChain 本身。预测 5你的工具 schema 不利于调用模型倾向规避。表现某些工具几乎从不被选中但换成简单工具或强制 tool_choice 后又能工作。这通常不是“模型坏了”而是 schema 设计太工程化、不够 agent-friendly。如果让我按实际工程经验给你一句最像“真相”的结论那就是八成不是“模型没读到 tools”而是“模型读到了但默认 auto 策略下没决定调或者你的执行闭环没接完整”。✅️小结我给你一个最终的、可执行的判断结论“日志显示模型读取到了 tools 但没实际调用”最常见的根因不是单点 bug而是下面这句工具注册成功 ≠ 模型一定调用 ≠ 框架一定执行 ≠ 最终链路闭环完成你现在应该按这个顺序排查最小化验证底层模型ChatOpenAI bind_tools tool_choiceany 非流式 temperature0看有没有tool_calls验证执行闭环如果不用 agent自己执行工具并追加ToolMessage如果用 deepagent确认真正走的是 agent invoke不是裸 llm invoke验证 provider 兼容性先用 OpenAI SDK 直连 provider再上 LangChain再上 deepagent收敛 prompt / schemasystem prompt 明确“哪些问题必须调用工具”tool description 写清适用场景与禁止臆测参数 schema 简化最后再恢复复杂能力thinking modestreaming多工具多代理这些建议都直接符合 LangChain、阿里云百炼、Qwen 官方资料给出的机制说明。一句话定性你这个问题大概率不是“tools 没传进去”而是下面三者之一模型在 auto 模式下没决定调你的 agent/tool loop 没闭环OpenAI-compatible 层把 tool calling 搞得不够标准 结语 互动说明希望以上分析与解决思路能为你当前的问题提供一些有效线索或直接可用的操作路径。若你按文中步骤执行后仍未解决不必焦虑或抱怨这很常见——复杂问题往往由多重因素叠加引起欢迎你将最新报错信息、关键代码片段、环境说明等补充到评论区我会在力所能及的范围内结合大家的反馈一起帮你继续定位 如果你有更优或更通用的解法非常欢迎在评论区分享你的实践经验或改进方案你的这份补充可能正好帮到更多正在被类似问题困扰的同学正所谓「赠人玫瑰手有余香」也算是为技术社区持续注入正向循环 文末福利技术成长加速包 文中部分问题来自本人项目实践部分来自读者反馈与公开社区案例也有少量经由全网社区与智能问答平台整理而来。若你尝试后仍没完全解决问题还请多一点理解、少一点苛责——技术问题本就复杂多变没有任何人能给出对所有场景都 100% 套用的方案。如果你已经找到更适合自己项目现场的做法非常建议你沉淀成文档或教程这不仅是对他人的帮助更是对自己认知的再升级。如果你还在持续查 Bug、找方案可以顺便逛逛我专门整理的 Bug 专栏《全栈 Bug 调优实战版》️这里收录的都是在真实场景中踩过的坑希望能帮你少走弯路节省更多宝贵时间。✍️如果这篇文章对你有一点点帮助欢迎给 bug菌 来个一键三连关注 点赞 收藏你的支持是我持续输出高质量实战内容的最大动力。同时也欢迎关注我的硬核公众号 「猿圈奇妙屋」获取第一时间更新的技术干货、BAT 等互联网公司最新面试真题、4000G 技术 PDF 电子书、简历 / PPT 模板、技术文章 Markdown 模板等资料通通免费领取。你能想到的绝大部分学习资料我都尽量帮你准备齐全剩下的只需要你愿意迈出那一步来拿。 Who am I?我是 bug菌热活跃于 CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等技术社区CSDN 博客之星 Top30、华为云多年度十佳博主/卓越贡献者、掘金多年度人气作者 Top40掘金、InfoQ、51CTO 等平台签约及优质作者全网粉丝累计30w。更多高质量技术内容及成长资料可查看这个合集入口 点击查看 ️硬核技术公众号「猿圈奇妙屋」期待你的加入一起进阶、一起打怪升级。- End -
返回列表