ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Agentic RAG工作流架构与落地实践:打造可靠的智能体系统!

Agentic RAG工作流架构与落地实践:打造可靠的智能体系统! 1. 从原型到生产Agentic RAG 工作流到底难在哪Agentic RAG 工作流架构说白了就是让大模型不再只是“检索一次、拼上下文、生成答案”这么一条直线而是变成一个会自己判断该查文档还是查数据库、会调用工具、会反思答案是否靠谱的智能体系统。它适合谁适合那些已经跑通基础 RAG demo却发现线上回答经常答非所问、数据对不上、SQL 查错表的开发者。原型阶段你喂几篇 PDF 就能出效果可一旦接入真实业务库、真实用户提问检索命中率和工具调用成功率就会断崖式下跌。我见过太多团队卡在同一个地方向量检索召回了一堆语义相近但事实无关的片段LLM 拿着这些片段一本正经地编。或者用户问“上个月华东区退货率最高的三个 SKU”系统却去文档库里翻产品手册。这类问题的根子不在模型能力而在工作流编排——检索、规划、工具调用、反思这四个环节没有被拆开设计也没有可验证的成功指标。所以这篇内容聚焦一件事把 Agentic RAG 工作流从原型推到生产拆解每个环节的编排方式给出可复制的节点配置和验证动作。技术栈上我会用 LlamaIndex 做编排、Milvus 做自托管向量库、TaoToken 做模型接入层再配一个回答验证环节。整条链路你都能跟着配下来最后我会给出检索命中率和工具调用成功率的实测验证方法。先明确一个判断标准一个可靠的 Agentic RAG 系统必须能回答三个问题——这次查询走了哪条路径工具调用返回了什么最终答案的置信度是多少如果这三个问题你的系统答不上来那它还停留在原型阶段。下面从模型接入开始一步步把这条链路搭起来。2. TaoToken 前置模型接入层与工具调用能力准备在搭工作流之前得先把模型接入层定下来。Agentic RAG 对模型的要求比普通 RAG 高一个档次它必须支持 function calling / tool use否则智能体没法自主选择工具。我试过用不支持工具调用的模型硬做路由结果只能靠 prompt 里写死规则查询一复杂就崩。这里用 TaoToken 作为统一接入层好处是它兼容 OpenAI 风格的接口LlamaIndex 的 OpenAILike 可以直接对接切换模型时不用改工作流代码。你需要准备三样东西Base URL、API Key、Model ID。这三件套在后面的配置里会反复出现先记牢。Base URL 用https://taotoken.net/api注意这个地址不带任何查询参数。API Key 去控制台创建路径是 API Keys 页面。Model ID 选一个支持工具调用的比如 Qwen 系列或 Claude 系列具体以你账号下可用的为准。创建 Key 的入口在这里https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite如果你还没想好选哪个模型可以先去模型对话页面试一下工具调用是否正常https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite为什么要单独强调接入层因为 Agentic 工作流里模型会被调用多次——规划一次、工具选择一次、答案生成一次、反思验证可能再一次。如果每次调用都走不同的 SDK、不同的鉴权方式排障时你会疯掉。统一走 TaoToken 之后所有请求的日志、计费、模型切换都在一个地方看出问题能快速定位是模型侧还是工作流侧。还有一个实际考量工具调用成功率跟模型的指令遵循能力直接相关。同一个工作流换个模型可能工具选择准确率差 20 个百分点。所以接入层要支持快速换模型做 A/B 对比这也是我用统一 Base URL 的原因。配置好之后先写一个最小请求验证连通性再往下搭工作流。3. 可复制配置LlamaIndex Milvus 工具路由的节点编排这一节是核心给出可直接复制的配置片段。整个工作流分四层模型层、检索层、工具层、编排层。我按文件路径组织你照着建目录就行。先建项目结构agentic_rag/ ├── config/ │ └── settings.toml ├── engines/ │ ├── sql_engine.py │ └── rag_engine.py ├── tools/ │ └── registry.py └── workflow/ └── router.py模型层配置写在config/settings.toml把三件套集中管理[llm] base_url https://taotoken.net/api api_key sk-your-key-here model_id qwen3-235b temperature 0.1 supports_tool_call true [embedding] model_id text-embedding-v3 base_url https://taotoken.net/api api_key sk-your-key-here [milvus] uri http://localhost:19530 collection agentic_docs dim 1024注意 temperature 设成 0.1Agentic 场景下规划环节需要稳定输出温度高了工具选择会飘。embedding 也走同一个 Base URL省得维护两套鉴权。检索层分两个引擎。engines/rag_engine.py负责文档检索用 Milvus 做向量存储from llama_index.core import VectorStoreIndex, StorageContext from llama_index.vector_stores.milvus import MilvusVectorStore from llama_index.embeddings.openai import OpenAIEmbedding vector_store MilvusVectorStore( urihttp://localhost:19530, collection_nameagentic_docs, dim1024, overwriteFalse, ) embed_model OpenAIEmbedding( modeltext-embedding-v3, api_basehttps://taotoken.net/api, api_keysk-your-key-here, ) index VectorStoreIndex.from_vector_store( vector_store, embed_modelembed_model ) rag_query_engine index.as_query_engine(similarity_top_k5)engines/sql_engine.py负责自然语言转 SQL用 LlamaIndex 的 NLSQLTableQueryEnginefrom llama_index.core.query_engine import NLSQLTableQueryEngine from llama_index.core import SQLDatabase from sqlalchemy import create_engine sql_engine create_engine(postgresql://user:passlocalhost:5432/biz) sql_database SQLDatabase(sql_engine, include_tables[orders, skus]) sql_query_engine NLSQLTableQueryEngine( sql_databasesql_database, llmllm, verboseTrue, )工具层把两个引擎注册成工具tools/registry.pyfrom llama_index.core.tools import QueryEngineTool, ToolMetadata doc_tool QueryEngineTool( query_enginerag_query_engine, metadataToolMetadata( namedocument_search, description用于查询产品文档、政策说明、操作手册等非结构化内容, ), ) sql_tool QueryEngineTool( query_enginesql_query_engine, metadataToolMetadata( namesql_query, description用于查询订单、库存、销售等结构化业务数据支持聚合统计, ), ) tools [doc_tool, sql_tool]工具描述description是路由准确率的关键。我踩过的坑是描述写得太笼统模型分不清该用哪个。后来把“非结构化内容”和“结构化业务数据”这两个边界写清楚工具选择准确率明显提升。编排层用 LlamaIndex 的 AgentWorkflowworkflow/router.pyfrom llama_index.core.agent import AgentWorkflow agent AgentWorkflow.from_tools_or_functions( tools, llmllm, system_prompt( 你是一个业务智能体。先判断用户问题需要文档检索还是数据查询 再调用对应工具。拿到结果后检查是否回答了问题不确定就换工具重试。 ), verboseTrue, )这套配置跑起来后模型会自己决定走 document_search 还是 sql_query。但光有路由还不够生产环境需要验证答案可靠性下一节讲怎么加反思环节和验证请求。4. 验证请求与成功结果检索命中率、工具调用成功率实测配置写完不代表能用得用真实请求验证。我设计了三组测试用例分别验证检索命中率、工具调用成功率和端到端答案质量。第一组验证工具路由。准备 10 个问题5 个该走文档检索5 个该走 SQL 查询test_cases [ {q: 退货政策里七天无理由怎么算, expect: document_search}, {q: 上个月华东区销售额是多少, expect: sql_query}, {q: 产品保修期多久, expect: document_search}, {q: 退货率最高的三个SKU, expect: sql_query}, # ... 补足10条 ] correct 0 for case in test_cases: resp agent.run(case[q]) used resp.tool_calls[0].tool_name if resp.tool_calls else none if used case[expect]: correct 1 print(f工具调用成功率: {correct}/{len(test_cases)})实测下来工具描述写清楚边界后10 条能对 9 条。错的那条是“退货政策里七天无理由怎么算”模型一开始走了 SQL因为“退货”这个词在订单表里也有。后来在文档工具描述里补了“政策、规则、条款类问题优先走此工具”就修正了。第二组验证检索命中率。这个需要标注数据给每个问题标出应该命中的文档片段 IDdef hit_rate(queries, ground_truth_ids, top_k5): hits 0 for q, gt_ids in zip(queries, ground_truth_ids): nodes rag_query_engine.retrieve(q)[:top_k] retrieved_ids {n.node_id for n in nodes} if retrieved_ids set(gt_ids): hits 1 return hits / len(queries)命中率低于 0.8 就要调 chunk 大小或换 embedding 模型。我一般先把 chunk 从 512 调到 256 试再不行才换模型。第三组验证端到端答案。这里加一个反思节点让模型自己检查答案是否基于工具返回结果def reflect(query, answer, context): prompt f问题{query}\n答案{answer}\n依据{context}\n prompt 答案是否完全基于依据有无编造只回答 是 或 否。 return llm.complete(prompt).text.strip()成功结果长这样工具调用返回sql_querySQL 语句正确答案里带具体数字反思节点返回“是”。如果反思返回“否”工作流应该重新检索或降级回复“暂无法确认”。这套验证跑通你的 Agentic RAG 才算有了生产可用的基础。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth搭这套工作流时报错基本集中在几个地方。我按真实遇到的顺序列出来对照着查。401 Unauthorized。最常见九成是 API Key 没配对。检查settings.toml里的api_key是否和 TaoToken 控制台创建的一致注意别把sk-前缀漏了。还有一种情况是 Key 创建后没复制全尾部字符被截断。如果确认 Key 没问题还是 401检查 Base URL 是不是写成了带路径的形式正确写法就是https://taotoken.net/api不要在后面加/v1之类。local proxy failed。这个报错通常出现在你本地配了环境变量代理但请求走不通。先检查HTTP_PROXY/HTTPS_PROXY环境变量临时清掉再试unset HTTP_PROXY HTTPS_PROXY如果清了还报检查 Milvus 服务是否启动docker ps看容器状态。Milvus 没起来时检索层初始化会失败报错信息有时会伪装成网络问题。reading choices 相关报错。典型信息是Error reading choices或choices field missing。这说明模型返回体格式和 SDK 预期不一致。原因通常是 Model ID 写错了或者用了一个不支持 OpenAI 兼容格式的模型。去模型对话页面确认该 Model ID 能正常返回再检查settings.toml里的model_id拼写。还有一种可能是流式和非流式混用AgentWorkflow 默认走非流式如果你在别处开了 stream返回结构会变。OAuth 相关报错。如果你用了 Claude Code 或 Codex 这类工具接入可能会碰到 OAuth token 过期。这类工具的三件套配置要写全Base URL、API Key、Model ID。以 Codex 的auth.json为例{ base_url: https://taotoken.net/api, api_key: sk-your-key-here, model: qwen3-235b }三个字段缺一不可只填 Key 不填 Base URL 会走默认端点直接 OAuth 失败。Claude Code 的配置类似在 settings 里把 Base URL 指向同一个地址。如果你用 CC Switch 或 Cline MCP 管理多个模型同样确保每个 profile 里三件套完整。排障顺序建议先验证模型连通性单独发一个 chat 请求再验证检索层单独跑一次 retrieve最后验证工作流编排。分层排查比一上来就 debug 整个链路快得多。6. 语义一致 CTA把工作流跑起来之后工作流跑通、验证指标达标之后下一步是把它接到真实业务里。这时候模型调用量会上来建议去控制台把用量监控开起来顺便确认计费方式符合预期https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite如果你还在选模型阶段想对比不同模型在工具调用上的表现可以直接在模型对话里用同一组测试用例跑一遍https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite长期做编码类 Agent 或者需要稳定跑工作流的可以看下 Coding Plan适合高频调用场景https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite接入细节和参数说明都在文档里配置遇到卡点先翻这里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite最后给一个实用建议Agentic RAG 的调优是个持续过程别指望一次配置就完美。把工具调用成功率和检索命中率做成日常监控指标每周看一次趋势发现下降就回查最近的文档更新或模型切换记录。这套工作流的价值不在于一次搭好而在于你能持续知道它哪里在退化。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进