☰
AI Agent 30天速成|Day9 笔记:ReAct 循环里 Function 调用失败,把 endpoint 改到 TaoToken 的排查记录
2026/10/9 13:08:02 网站建设 项目流程

1. ReAct 循环里 Function 调用失败,先分清是鉴权还是路由

ReAct 循环跑通之后,最让人抓狂的不是模型不调用工具,而是它明明调了,结果返回一串报错。我这两天在 Chroma + Embedding 检索链路上就踩了这个坑:Agent 推理到rag_search这一步,工具调用直接失败,日志里躺着 401 和 local proxy failed 两种完全不同的错误。前者是鉴权问题,后者是路由问题,但表面看都像"接口挂了"。

先说清楚这套链路在干什么。ReAct 的核心是"推理—行动—观察"循环:模型根据用户问题决定调用哪个 Function,工具执行后把结果回填上下文,模型再判断信息够不够。我这条链路里有四个工具:calculator做数学计算、text_embedding把文本转成向量、vector_add把文档写进 Chroma 持久库、rag_search从 Chroma 里召回相关片段。其中vector_add和rag_search是嵌套调用——它们内部会自动调text_embedding生成向量,所以一次检索失败,可能是上层工具的问题,也可能是底层 Embedding 接口的问题。

为什么要把 endpoint 统一改到 TaoToken?因为原来我的 LLM 对话走一个地址、Embedding 走另一个地址,两套 Key、两套鉴权逻辑。ReAct 循环里工具嵌套调用时,底层 Embedding 请求用的是另一套配置,一旦那套配置的 Key 过期或者地址写错,报错就会从工具层冒出来,看起来像是 Function 调用失败,实际是 Embedding 接口 401。统一到一个通道之后,Base URL、Key、Model ID 三件套只有一份,排查路径立刻缩短一半。

这篇记录适合谁:正在用 ReAct 搭 Agent、工具调用报错但分不清是鉴权还是路由、用 Chroma 做本地持久向量库、Embedding 接口频繁 401 或超时的同学。我会把可复制的 endpoint 配置片段、一次完整的调用验证动作、以及 401 / local proxy failed / reading choices 这几类真实报错的对照排查都写出来。你跟着做一遍,基本能定位问题出在哪一层。

先给结论:ReAct 里 Function 调用失败,九成逃不出三种——Key 无效或没带上(401)、请求根本没发到目标地址(local proxy failed)、响应结构解析失败(reading choices)。下面按"先统一通道,再验证,再排障"的顺序走。

2. 把 LLM 和 Embedding 的 endpoint 统一到 TaoToken

在动手改配置之前,先理解为什么要统一。ReAct Agent 的工具调用有个特点:一次用户提问可能触发多次模型请求和多次 Embedding 请求。比如用户问"什么是 RAG",Agent 先调rag_search,rag_search内部调text_embedding生成查询向量,Chroma 召回后再把结果回填给模型做最终总结。这一轮下来,LLM 接口调了至少两次,Embedding 接口调了一次。如果 LLM 和 Embedding 走不同厂商、不同 Key,任何一套出问题都会让整个循环断掉,而且报错位置具有迷惑性。

TaoToken 在这里的作用是提供一个统一的 Key 和 API 通道。你只需要维护一份 Base URL 和一份 API Key,LLM 对话和 Embedding 请求都走这个通道。这样做的好处很直接:鉴权逻辑只有一套,Key 失效时所有请求一起报 401,不会出现"对话正常但检索失败"这种半死不活的状态;路由配置只有一份,不会出现 LLM 地址对、Embedding 地址写错的情况。

具体怎么拿 Key、怎么配,我按步骤说。先访问官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 了解通道能力,然后进控制台创建 API Key。控制台地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,API Keys 管理页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。创建完 Key 之后,API 的基础地址是 https://taotoken.net/api ,注意这个地址不带任何查询参数,配置时直接填。

这里有个容易踩的坑:很多人把官网地址当成 API 地址填进去,结果请求发到了网页服务器而不是 API 网关,返回一堆 HTML,解析时报 reading choices 错误。记住官网是给人看的,API 是给程序调的,两者不是一回事。

统一通道之后,你的.env里 LLM 和 Embedding 的配置应该指向同一个 Base URL,只是路径不同。下面是我改完之后的配置结构,你可以直接对照自己的项目调整。注意 Model ID 要填你实际开通的模型,不要照抄示例里的名字。

配置改完之后,先别急着跑整个 Agent。ReAct 循环涉及工具嵌套,出错时调用栈很深。正确做法是先单独验证 LLM 接口通不通,再单独验证 Embedding 接口通不通,两个都通了再跑完整循环。下一节给可复制的配置片段和验证命令。

3. 可复制的 endpoint 配置片段(.env + settings)

这一节给两份配置:一份是.env环境变量,适合 Python 项目用python-dotenv加载;一份是 JSON 格式的 settings,适合需要结构化配置的场景。两份配置的核心都是把 LLM 和 Embedding 指向 TaoToken 统一通道,Base URL 用 https://taotoken.net/api ,Key 用你在控制台创建的那一个。

先看.env。我保留了原来项目里的变量名,只改了地址和 Key,这样你不用动代码里的os.getenv调用:

# LLM 对话接口(ReAct 推理用) LLM_BASE_URL=https://taotoken.net/api/v1/chat/completions LLM_API_KEY=sk-你的TaoToken密钥 # Embedding 接口(Chroma 向量化用) LLM_EMBED_URL=https://taotoken.net/api/v1/embeddings LLM_EMBED_KEY=sk-你的TaoToken密钥 # 模型 ID(按你实际开通的填) LLM_MODEL_ID=你的对话模型ID EMBED_MODEL_ID=你的向量模型ID # Chroma 持久化 CHROMA_PERSIST_PATH=./chroma_kb CHROMA_COLLECTION_NAME=agent_kb # 超时与重试 LLM_TIMEOUT=60 EMBED_TIMEOUT=15 MAX_RETRY=3

注意LLM_API_KEY和LLM_EMBED_KEY填的是同一个 Key。统一通道的意义就在这里:一份 Key 管所有请求,Key 失效时一起失效,不会出现部分接口能用的迷惑状态。如果你原来的代码里 Embedding 用的是单独的 Key 变量,现在把它改成和 LLM 一样即可。

再看 JSON 格式的 settings,适合 FastAPI 项目或者需要动态加载配置的场景:

{ "llm": { "base_url": "https://taotoken.net/api/v1/chat/completions", "api_key": "sk-你的TaoToken密钥", "model_id": "你的对话模型ID", "timeout": 60 }, "embedding": { "base_url": "https://taotoken.net/api/v1/embeddings", "api_key": "sk-你的TaoToken密钥", "model_id": "你的向量模型ID", "timeout": 15 }, "chroma": { "persist_path": "./chroma_kb", "collection_name": "agent_kb" } }

如果你用的是 Claude Code 或者类似的编码工具,配置方式略有不同。Claude Code 的 settings 文件通常在项目根目录的.claude/settings.json,你需要把 Base URL、Key、Model ID 三件套都写进去。Base URL 填 https://taotoken.net/api ,Key 填控制台创建的 Key,Model ID 填你开通的模型。这三者缺一不可,少填一个就会出现 401 或者模型找不到的错误。

Cline 或者带 MCP 的工具也是同样的逻辑:Base URL、Key、Model ID 三件套。MCP 配置里如果涉及远程服务地址,同样指向 TaoToken 的 API 地址。Codex 的auth.json里需要填 API Key 和 Base URL,格式是 JSON,Key 字段名通常是api_key或openai_api_key,具体看你用的版本。

配置写完,先做一次语法检查。.env文件里不要有多余空格,Key 不要加引号(除非你的加载库要求),地址末尾不要多斜杠。这些细节看起来小,但 401 和 404 经常就是这些地方引起的。下一节用一条 curl 命令验证配置是否生效。

4. 验证请求:一条 curl 打通 LLM 和 Embedding

配置改完,最忌讳直接跑整个 ReAct 循环。循环里工具嵌套,报错信息会被层层包装,你看到的"Function 调用失败"可能只是底层 Embedding 401 的二次包装。正确做法是分层验证:先验证 LLM 接口,再验证 Embedding 接口,最后跑完整循环。

先验证 LLM 对话接口。用 curl 发一条最简单的请求,确认鉴权和路由都通:

curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的TaoToken密钥" \ -H "Content-Type: application/json" \ -d '{ "model": "你的对话模型ID", "messages": [{"role": "user", "content": "回复ok两个字"}], "temperature": 0.1 }'

如果返回的 JSON 里有choices字段,且choices[0].message.content是"ok",说明 LLM 通道正常。如果返回 401,检查 Key 是否填对、是否带了Bearer前缀。如果返回 404,检查 Base URL 路径是否正确,/v1/chat/completions不能少。如果返回的是一段 HTML,说明地址填成了官网而不是 API 地址。

再验证 Embedding 接口。这一步是 Chroma 检索链路的关键,因为rag_search和vector_add都依赖它:

curl -X POST https://taotoken.net/api/v1/embeddings \ -H "Authorization: Bearer sk-你的TaoToken密钥" \ -H "Content-Type: application/json" \ -d '{ "model": "你的向量模型ID", "input": ["RAG 是检索增强生成"] }'

正常返回的 JSON 里data[0].embedding是一个浮点数数组,长度取决于你的向量模型(常见 1024 或 1536 维)。如果这里报 401,说明 Embedding 的 Key 没配对;如果报模型不存在,说明 Model ID 填错了;如果超时,检查网络和超时设置。

两个接口都通了之后,跑一次完整的 ReAct 调用验证。用你项目里的 FastAPI 入口,发一条会触发rag_search的请求:

curl "http://127.0.0.1:8000/agent/chat?session_id=test001&user_role=user&prompt=什么是RAG"

预期返回的 JSON 里应该有trace_id、tool_record和answer三个字段。tool_record里能看到rag_search的执行结果,answer是模型基于检索结果生成的最终回答。如果tool_record里rag_search的值是"知识库未匹配到相关内容",说明 Chroma 里还没数据,先调vector_add入库再检索。

验证通过的标准很简单:LLM 返回 choices、Embedding 返回向量数组、完整循环返回 answer。三个都满足,说明 endpoint 改到 TaoToken 的动作完成。接下来如果还有报错,就是代码逻辑或者参数问题,不是通道问题。下一节把常见报错和排查路径列清楚。

5. 常见报错对照排查:401、local proxy failed、reading choices

这一节是排查手册。ReAct 循环里 Function 调用失败,报错信息往往经过多层包装,你需要对照原始错误定位根因。下面按报错类型逐一拆解,每条都给现象、原因、排查动作。

401 Unauthorized。现象是工具执行返回"鉴权失败"或者直接抛 401。原因通常是三种:Key 没填、Key 填错、Key 没带上Bearer前缀。排查动作:先看.env里LLM_API_KEY和LLM_EMBED_KEY是否都填了,再确认代码里请求头是不是Authorization: Bearer sk-xxx。特别注意 Embedding 请求——很多人只改了 LLM 的 Key,忘了 Embedding 还在用旧 Key,结果对话正常但检索 401。统一到 TaoToken 之后,两个 Key 应该完全一样。

local proxy failed。现象是请求根本没发出去,报错里带 local proxy 字样。原因通常是 Base URL 写错、地址不可达、或者本地网络配置有问题。排查动作:先用 curl 直接请求 https://taotoken.net/api 看能不能通,如果 curl 也失败,说明是网络层问题;如果 curl 通但代码不通,检查代码里的 Base URL 是不是被环境变量覆盖了,或者有没有多余的斜杠、空格。还有一种情况是地址填成了官网域名而不是 API 域名,请求发到了网页服务器,自然失败。

reading choices 报错。现象是解析响应时抛异常,提示读取 choices 字段失败。原因通常是响应结构不是预期的 JSON,可能是返回了 HTML 错误页、可能是返回了错误 JSON(比如{"error": "..."}),也可能是流式响应没处理完就解析。排查动作:先把原始响应打印出来看,不要直接取choices[0]。如果是 HTML,说明地址错了;如果是 error JSON,看 error 内容定位;如果是流式,检查你的解析逻辑有没有等[DONE]标记。

OAuth 相关报错。现象是提示 token 过期或 OAuth 流程失败。原因通常是用了需要 OAuth 的接口但没走授权流程,或者 token 缓存过期。排查动作:确认你用的是 API Key 鉴权而不是 OAuth,TaoToken 的 API 通道用 Key 即可。如果代码里残留了 OAuth 逻辑,把它去掉,统一改成 Bearer Key。

模型不存在或 Model ID 错误。现象是返回 404 或提示 model not found。原因就是 Model ID 填错了。排查动作:对照控制台里开通的模型列表,把 Model ID 原样复制到配置里,不要自己拼写。LLM 和 Embedding 的 Model ID 通常不一样,别混用。

超时。现象是请求挂起很久然后失败。原因可能是网络慢、模型响应慢、或者超时设置太短。排查动作:LLM 超时设 60s,Embedding 超时设 15s,这是比较合理的值。如果还是超时,先用 curl 测单次请求耗时,确认是通道问题还是模型本身慢。

排查顺序建议:先 curl 验证通道,再看代码配置,最后看参数和逻辑。不要一上来就改代码,很多时候问题在配置层。把上面这几类报错对照一遍,基本能覆盖 ReAct 循环里 Function 调用失败的常见情况。

6. 后续怎么用:模型对话、Coding Plan 和接入文档

通道打通之后,日常使用分几个场景。如果你只是想验证模型能不能正常对话、Embedding 能不能正常返回向量,用模型对话页面最直接:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。在这里可以快速试不同模型的响应,确认通道和模型都正常,再去跑 Agent 循环。

如果你要长期做编码类 Agent,比如让 Agent 自动写代码、跑测试、调工具,那 Coding Plan 更合适:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。它针对编码场景做了优化,适合 ReAct 循环里频繁调用工具的负载。我实测下来,编码类任务用 Coding Plan 的响应稳定性比按次调用好一些,尤其是工具嵌套多、请求密集的时候。

接入过程中遇到配置问题,先查接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。文档里有各语言的接入示例和参数说明,比在代码里猜要快。Key 管理在 API Keys 页面:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,可以创建多个 Key 做环境隔离,比如开发用一个、生产用一个。

最后说一个实用技巧:ReAct 循环里给每次工具调用都带上 trace_id,日志里记录工具名、参数、耗时、异常。这样一旦 Function 调用失败,你能直接从日志定位是哪个工具、哪次请求、什么错误,而不是在一堆包装过的报错里猜。我踩过的坑就是没加 trace_id,结果 401 和 local proxy failed 混在一起,排查花了半天。加上之后,一眼就能看出是 Embedding 的 Key 没配对,改完立刻通。

Claude Code 用户如果要把 endpoint 改到 TaoToken,记住三件套:Base URL 填 https://taotoken.net/api ,Key 填控制台创建的 Key,Model ID 填开通的模型。三个都写进 settings 文件,缺一个都会报错。改完先跑一条简单对话验证,再跑工具调用,分层验证比一次性跑完整循环高效得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询