
使用 TensorZero 构建简单 Agentic RAG基于 Wikipedia 的多跳检索问答智能体实战【免费下载链接】tensorzeroTensorZero is an open-source LLMOps platform that unifies an LLM gateway, observability, evaluation, optimization, and experimentation.项目地址: https://gitcode.com/GitHub_Trending/te/tensorzero导读本文基于 TensorZero 官方示例simple-agentic-rag完整讲解如何用 TensorZero 构建一个多跳multi-hop检索问答智能体它通过反复搜索 Wikipedia、加载页面内容来逐步收集证据并在信息足够时给出带引用的最终答案。读完本文你将掌握 TensorZero 的函数function与工具tool配置方法、tool_choice与并行工具调用等关键参数的作用以及用 Python 客户端AsyncTensorZeroGateway驱动工具调用循环的完整实战写法。示例完整代码位于 examples/rag-retrieval-augmented-generation/simple-agentic-rag。背景为什么需要多跳检索普通的 RAG检索增强生成通常只做一次检索 → 一次生成而许多真实问题无法通过单次检索回答需要把多个事实链式拼接起来。例如示例中的经典问题What is a common dish in the hometown of the scientist that won the Nobel Prize for the discovery of the positron?发现正电子的诺奖科学家的家乡有什么常见菜肴要回答它模型必须依次完成正电子发现者是谁 → 他的家乡在哪 → 那个地方有什么特色菜每个环节都依赖上一步的检索结果这就是典型的多跳推理。本示例展示了一个极简却有效的思路让智能体迭代地使用搜索工具由模型自己决定何时收集够了信息、何时给出最终答案而不是预先设计固定的检索流水线。智能体工具设计示例为智能体配备了四个工具定义见 config/tools 目录下的四个 JSON Schema 文件工具参数作用thinkthought思考问题与已收集信息规划下一步行动search_wikipediaquery搜索 Wikipedia返回相关页面标题列表load_wikipedia_pagetitle加载指定 Wikipedia 页面的内容answer_questionanswer结束检索流程并给出最终答案每个工具的 JSON Schema 都遵循 JSON Schema draft-07并统一使用additionalProperties: false约束与strict true配合实现严格模式。以search_wikipedia为例search_wikipedia.json 定义如下{ $schema: http://json-schema.org/draft-07/schema#, type: object, description: Search Wikipedia for pages that match the query. Returns a list of page titles., properties: { query: { type: string, description: The query to search Wikipedia for (e.g. \machine learning\). } }, required: [query], additionalProperties: false }think工具值得特别说明它没有任何外部副作用纯粹用于让模型先规划再行动。Anthropic 的相关工程实践表明这类思考工具往往能显著提升 Agent 工作流的回答质量——它把模型的推理过程显式化为工具调用既能让推理可见、可观测也避免模型在不充分的信息下贸然作答。在 Python 客户端中think没有真实实现只回传一个空字符串作为工具结果因为 OpenAI 等部分提供商要求每个工具调用都必须有对应结果。函数与变体配置智能体的核心配置位于 config/tensorzero.toml# ────────────────────────────────────────────────────────────────────────────── # GENERAL # ────────────────────────────────────────────────────────────────────────────── # To keep things minimal in this example, we dont set up observability with ClickHouse. [gateway] observability.enabled false # ────────────────────────────────────────────────────────────────────────────── # FUNCTIONS # ────────────────────────────────────────────────────────────────────────────── [functions.multi_hop_rag_agent] type chat tools [think, search_wikipedia, load_wikipedia_page, answer_question] tool_choice required parallel_tool_calls true [functions.multi_hop_rag_agent.variants.baseline] type chat_completion model openai::gpt-4o-mini system_template functions/multi_hop_rag_agent/baseline/system_template.txt # ────────────────────────────────────────────────────────────────────────────── # TOOLS # ────────────────────────────────────────────────────────────────────────────── [tools.think] description Think about the question and the information you have gathered so far. This is a good time to plan your next steps. parameters tools/think.json strict true [tools.search_wikipedia] description Search Wikipedia for pages that match the query. Returns a list of page titles. parameters tools/search_wikipedia.json strict true [tools.load_wikipedia_page] description Load a Wikipedia page. Returns the page content, or an error if the page does not exist. parameters tools/load_wikipedia_page.json strict true [tools.answer_question] description End the search process and answer a question. Returns the answer to the question. parameters tools/answer_question.json strict true几个关键配置点需要重点理解type chat函数类型为对话式聊天输入输出均为消息序列。tools [...]为函数声明可用工具集合。注意answer_question也被声明为一个工具这是本示例的精妙之处——结束检索本身也是一个模型可选择的动作模型调用它即表示认为信息已足够。tool_choice required强制模型每次推理都必须发起工具调用。由于answer_question是唯一能终止循环的路径这个设置保证了流程不会以普通文本结束从而让循环逻辑简单可靠。parallel_tool_calls true允许模型在一次响应中并行发起多个工具调用例如同时加载多个 Wikipedia 页面显著加速多源信息收集。变体baseline使用openai::gpt-4o-mini模型系统提示词模板指向 system_template.txt。observability.enabled false示例刻意关闭 ClickHouse 观测保持最小化生产环境建议参考 部署文档 启用可观测性来追踪每次推理与工具调用。系统提示词的设计要点system_template.txt 是整个 Agent 行为调优的核心README 明确鼓励读者随意编辑它以微调智能体行为。它传达了几个关键策略搜索优先于记忆即使模型觉得自己知道答案也要先用工具核实强调宁可搜索、思考、验证。深度使用think每个问题开始前、每次搜索之间、加载页面前后、面对矛盾信息时、定稿答案前都要先think。这是把链式思维chain-of-thought显式化到工具循环中的实现方式。系统性验证避免基于不完整信息仓促下结论尽量跨多个页面交叉验证事实。透明与引用最终答案必须说明查阅了哪些 Wikipedia 页面、区分Wikipedia 来源信息与补充知识、标注不确定之处并要求附上具体引用。强制以工具收尾明确要求绝不直接向用户返回文本最终必须通过answer_question输出。这份提示词展示了如何仅用文本引导就塑造出一个谨慎、带引用、可追溯的检索型 Agent是提示工程层面的最佳实践范本。运行环境与前置条件前置条件Python 3.10安装 Python 依赖推荐使用uvuv sync依赖清单见 pyproject.toml核心依赖包括tensorzeroPython 客户端、wikipediaWikipedia 访问库、markdownify将 HTML 页面转为 Markdown 以节省 token、jupyter/ipykernel运行 notebook。一个 OpenAI API Key示例默认使用openai::gpt-4o-mini。启动步骤设置环境变量export OPENAI_API_KEY...启动 TensorZero Gatewaydocker compose updocker-compose.yml 使用官方tensorzero/gateway镜像将本地./config目录只读挂载为/app/config以--config-file /app/config/tensorzero.toml启动并把宿主机的OPENAI_API_KEY注入容器缺失时启动会报错提示Gateway 监听3000端口。注意该文件顶部明确标注这是仅供学习的最小化示例生产部署请参考 tensorzero-gateway 部署文档。运行main.ipynbJupyter notebook示例运行代码全部在 notebook 中。驱动 Agent 循环客户端代码逐段拆解notebook main.ipynb 中的代码展示了完整的 Agent 循环实现。它使用 TensorZero Python 客户端的AsyncTensorZeroGateway、ToolCall、ToolResult类型。建立 Gateway 连接from tensorzero import AsyncTensorZeroGateway, ToolCall, ToolResult t0 await AsyncTensorZeroGateway.build_http( gateway_urlhttp://localhost:3000, )build_http以 HTTP 方式连接上一步启动的本地 Gateway。实现真实工具函数def search_wikipedia(tool_call: ToolCall) - ToolResult: search_wikipedia_result \n.join(wikipedia.search(tool_call.arguments[query])) return ToolResult( namesearch_wikipedia, idtool_call.id, resultsearch_wikipedia_result, )load_wikipedia_page的实现有几个值得学习的工程细节调用wikipedia.page(title)获取页面再用markdownify把 HTML 转为Markdown 以压缩 token 用量返回内容统一组织为# URL\n\n{url}\n\n# CONTENT\n\n{markdown}的结构化格式便于模型解析对PageError页面不存在与DisambiguationError消歧义错误做异常处理返回带ERROR:前缀的结果字符串让模型能感知检索失败并调整策略。主循环ask_questionMAX_INFERENCES 20 async def ask_question(question: str, verbose: bool False): messages [{role: user, content: question}] episode_id None for _ in range(MAX_INFERENCES): response await t0.inference( function_namemulti_hop_rag_agent, input{messages: messages}, episode_idepisode_id, ) messages.append({role: assistant, content: response.content}) episode_id response.episode_id output_content_blocks [] for content_block in response.content: if isinstance(content_block, ToolCall): if verbose: print(f[Tool Call] {content_block.name}: {content_block.arguments}) # 分发到具体工具实现search / load / think / answer ... messages.append({role: user, content: output_content_blocks})循环的关键机制MAX_INFERENCES 20硬性上限防止模型无限循环检索是 Agent 循环必备的安全阀。episode_id追踪首次推理时传None之后用响应返回的episode_id回传TensorZero 会把整轮多跳检索关联为同一个 episode便于统一观测与评估。消息累积每一轮把 assistant 的响应与工具结果依次追加到messages形成完整的多轮对话上下文工具结果以{role: user, content: [ToolResult...]}形式回填。工具分发根据content_block.name分发到对应的 Python 工具函数think只返回空字符串结果无真实副作用当检测到answer_question时直接return content_block.arguments[answer]终止循环。无效调用防护对name或arguments为空的调用返回ERROR: invalid tool call保证循环健壮性。兜底策略循环耗尽仍未回答时抛出异常notebook 注释也指出生产场景中可以让模型基于已有信息尽力作答。示例问题与预期答案notebook 内置了三个验证智能体能力的多跳问题及推理链路What is a common dish in the hometown of the scientist that won the Nobel Prize for the discovery of the positron?→ 正电子发现 → Carl D. Anderson → 纽约市 → 纽约特色菜如 bagel。What company developed the popular Chinese video game voiced by the same voice actor that voiced a wizard in the anime Konosuba?→ Konosuba 的 wizardMegumin→ 声优 Rie Takahashi → 中文游戏《原神》→ 开发公司 HoYoversemiHoYo。What is the national flower of the country where the mathematician who proved Fermats Last Theorem was born?→ 费马大定理 → Andrew Wiles → 英国 → 国花 Tudor rose红玫瑰。这些用例恰好展示了多跳检索的核心价值每个问题都需要跨 23 个知识跳转任何一跳缺失都无法作答。一次完整的多跳检索轨迹以正电子诺奖科学家的家乡菜肴为例README 给出了真实的工具调用轨迹可以直观看到智能体如何思考 → 搜索 → 阅读 → 再思考 → 再搜索 → 阅读 → 定稿[Tool Call] think: {thought: To answer the question, I need to first identify the scientist who won the Nobel Prize for the discovery of the positron. After that, I will determine his hometown and look for a common dish associated with that place.} [Tool Call] search_wikipedia: {query: Nobel Prize positron discovery} [Tool Call] load_wikipedia_page: {title: Carl David Anderson} [Tool Call] think: {thought: Carl David Anderson, the scientist who discovered the positron, was born in New York City. I need to find common dishes that are characteristic of New York City.} [Tool Call] search_wikipedia: {query: Cuisine of New York City} [Tool Call] load_wikipedia_page: {title: Cuisine of New York City} [Tool Call] think: {thought: I have established that Carl David Anderson, who won the Nobel Prize for discovering the positron, was born in New York City. Based on the information from the cuisine of New York City, some iconic dishes include New York-style pizza, bagels with lox, and pastrami on rye. I need to decide on one common dish to summarize.} [Tool Call] answer_question: {answer: The scientist who discovered the positron was Carl David Anderson, born in New York City. A common dish associated with New York City is the New York-style bagel, often served with cream cheese and lox. ...}注意轨迹呈现的规律每个搜索/阅读动作之间都穿插着think调用——模型先规划下一步检索目标再执行工具最终答案明确区分了 Wikipedia 来源信息并附上引用。这正是系统提示词设计意图的直接体现也是tool_choice required保证每个推理步骤都有工具动作的必然结果。扩展思路如何调优与改造基于该示例README 与代码结构共同指向了清晰的扩展方向调优行为直接编辑 system_template.txt——例如调整检索策略、强化引用格式、改变终止条件何时该调用answer_question。更换模型或增加变体在 tensorzero.toml 的[functions.multi_hop_rag_agent.variants]下增加新变体即可做 A/B 对比TensorZero 的变体机制天然支持同函数多模型/多提示词并存。替换检索源把wikipedia库替换为你的私有知识库、向量数据库或企业搜索 API只需重写search_wikipedia/load_wikipedia_page两个工具函数Agent 循环与配置完全复用。接入观测与评估将observability.enabled打开并连接 ClickHouse配合 episode 机制即可追踪每一次多跳推理的完整工具调用链再结合 评估文档 对答案质量进行系统化评测与优化。小结本示例用约一个配置文件、一份提示词和一百余行客户端代码就构建出一个能在 Wikipedia 上自主完成多跳推理、带引用作答的检索智能体。它的设计方法论——工具即动作、思考显式化、强制工具收尾、上限防死循环、episode 全程追踪——可平滑迁移到任何工具调用型 Agent 项目中。深入研读 config/tensorzero.toml、系统提示词 与 main.ipynb 三个文件即可完整掌握这套模式。【免费下载链接】tensorzeroTensorZero is an open-source LLMOps platform that unifies an LLM gateway, observability, evaluation, optimization, and experimentation.项目地址: https://gitcode.com/GitHub_Trending/te/tensorzero创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考