ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

生产级Agentic RAG实战:从知识库选型到Mac搭建

生产级Agentic RAG实战:从知识库选型到Mac搭建 看到“production-agentic-rag-course”这个标题你可能会想这不过是把 RAG 和 Agent 两个热词缝在一起的课程包装。我的看法不太一样。作为正在维护生产环境 Agentic RAG 系统的人我深知“production”代表的是一整套评测、监控、成本控制而不是能在本地跑通 demo 就算数。“Agentic”意味着检索不再是一锤子买卖而是由模型自己决定查什么、用什么工具、要不要再查一次。这篇内容就是我在反复“building for production 卡住”之后沉淀出的实战经验整理成一套课程式的拆解。我会把知识库选型、Agent 架构、生产指标、Mac 本地搭建、常见问题都讲清楚。适合从 demo 走向线上的开发者也适合还在 RAG 知识库、知识图谱和结构化数据库之间犹豫的人。1. 先搞明白传统 RAG 的瓶颈到底在哪1.1 大家常说的“卡住”是指什么很多团队在 demo 阶段的路线基本一致找一批 PDF 或 Markdown切开、向量化、存进向量库然后用一个 Prompt 把“检索到的上下文 问题”扔给大模型。演示的时候感觉很好一旦放进生产环境就会碰到一堆奇怪问题明明文档里有答案检索却拿不回来用户换一种问法结果完全不对涉及数字统计的问题模型开始胡编文档一更新回答的还是旧内容。这种“卡住”不是运维问题而是架构问题。普通 RAG 的流程是固定的——先召回 top-k 片段再拼接上下文生成答案。这个过程没有反馈没有分支没有跨多个数据源协同的能力。它本质上是一个“单次语义匹配器”不是“任务求解器”。只要用户需求变成“有几个条件要同时满足”或者“需要从两个不同文档里拼出答案”单次检索就必然漏。另外还有一类需求是普通 RAG 完全处理不了的精确计算和结构化查询。比如“华东区前三季度销售额同比增幅是多少”文档库里只有叙述性文本没有计算能力。向量检索擅长的是语义相似度而不是执行 SUM、GROUP BY、关联关系。这时候答案只能靠猜。所以我在课程里第一件事就是让大家承认RAG 不只是一个“向量检索 Prompt”的组合它需要根据问题类型去路由到不同的工具。1.2 Agentic RAG 不是玄学是流程重构Agentic RAG 的核心并不复杂用一个 LLM 作为调度中枢把检索工具暴露给它由它自己决定先调用哪个工具、如何改写检索词、是否要继续第二轮、最后如何综合信息。这就是经典的“感知—行动—观察”循环只不过感知是调用工具后的返回结果行动是工具调用观察是 LLM 读取这些结果后的下一步判断。举例用户问“我们去年在华东区的销售额和华北区相比差多少”。传统 RAG 可能会去文档里搜索“华东区销售额”“华北区销售额”相关的片段结果找到一堆营销文案没有任何精确数字。Agentic RAG 的做法是先识别这是结构化查询意图路由到 SQL 工具如果 SQL 里缺少“华东区包含哪些省市”的定义再去向量库检索组织架构说明然后带同续查询。这个过程需要多次往返但每一步都是受控的。这里要强调一点Agent 只是实现手段不是目的。我见过不少项目为了“有 Agent”而强行把检索链路拆成 Step1、Step2结果延迟从 800ms 变成 5s回答并没有更好。真正值得 Agentic 化的场景是查询有多跳、组合、歧义或者需要跨文档/SQL/知识图谱的混合回答。否则普通 RAG 的固定管道反而更适合生产。2. 知识库选型RAG知识库、知识图谱和结构化数据库的区别2.1 三种知识库的本质差异和应用场景搜“rag知识库和结构知识库区分以及应用场景”的人越来越多说明很多人已经意识到不能把所有东西都塞进向量库。我按生产实践把知识载体分成三类每一类解决不同的问题。类型核心存储单位擅长解决典型问题实现示例RAG 知识库向量库文本块/chunk 向量语义相似检索、非结构化文档问答、叫“有哪些内容提到 xx”精确数值、多跳关系、版本一致性Chroma、FAISS、Milvus、pgvector知识图谱KG实体和关系“A 和 B 是什么关系”“谁是 X 的负责人”“某类实体的子集”冷启动建模成本高、数据抽取难Neo4j、RDF/SPARQL、TigerGraph结构化数据库记录/字段/表聚合统计、精确过滤、事务一致性、复杂报表非结构化语义检索、跨表语义模糊匹配PostgreSQL、MySQL、ClickHouse从应用场景看文档知识问答优先用向量库涉及复杂的实体关系和权限推导比如“哪些订单涉及未完成的验收条款”优先用知识图谱而财务、运营报表这类精确计算应该直接走 SQL。生产环境里真正稳定的系统绝大多数都是混合路由——Agent 先判断类型再把请求转发到对应工具。这就是我在课程里安排的第二个模块让用户学会给知识分家。2.2 Ontology 在 RAG 里的价值“ontology rag”这个词越来越热原因是知识图谱在实践中最大的坑就是“查出来不会用”。我们知道实体之间的关系但让 LLM 直接生成 Cypher/SPARQL 时经常因为属性名、关系名不一致而报错。Ontology本体就是知识图谱的模式层定义了实体的类型、属性、关系约束。它相当于给模型一张“地图”模型根据本体生成查询语句时而不是靠猜。我在知识库设计中加入了一层轻量级 Ontology比如“销售区域”包含“华东区、华北区、华南区”“华东区”下面的省份有哪些“合同”有属性“状态、签署日期、相对方”状态枚举是“进行中、已履约、逾期”。当 Agent 接到“华东区上半年逾期合同金额”时会先读取 Ontology 摘要知道“逾期”对应状态枚举华东区映射到具体省份然后生成查询。这个做法大幅减少 SQL/Cypher 生成的试错次数。普通 RAG 不会教你这个但生产级系统这一步几乎能决定上限。2.3 知识库能不能存图片“rag知识库能存储图片嘛”是个高频搜索答案是可以但不要直接把图片二进制扔给向量库。我在生产环境里的做法是“图文分仓、元数据关联”图片原图放对象存储S3/OSS/MinIO用 CLIP/SigLIP 这类多模态模型把图片转换成向量存进向量库同时在 metadata 里记录图片 URL、识别出的标签、周围文字的摘要。用户提问时文本查询可以先去向量库匹配到图片向量返回路径和注解生成阶段再交给多模态模型看图作答。对于 Mac 本地实验你可以用pip install clip或直接调用 Ollama 的多模态模型比如llava给图片生成描述再把描述向量化。本质上图片问题可以被转成“文本描述 图片引用”。别把图片本身塞进 Prompt除非你的模型确实是多模态否则普通 LLM 看到一段 base64 只会浪费 token。3. 生产级 Agentic RAG 架构别只堆 Agent3.1 核心组件必须分工生产级 Agentic RAG 不是简单的 ReAct 循环而是多个组件各司其职。我一般至少分成六块路由层识别问题意图决定走向量检索、SQL、图谱还是拒绝回答。查询理解层处理指代、同义词、缺失条件必要时拆成多个子问题。工具执行层将 LLM 输出的结构化调用参数映射到真实数据源限制超时和返回行数。记忆层保存对话历史、跨轮指代、用户偏好会话级别的短期记忆足以覆盖多数场景。终止与控制层设定最大步数、无进展判定、结果置信度检查。生成与引用层强制要求答案附带来源 ID限制“编造未检索信息”。这套模块化设计的好处是每一层都可以单独观测和回滚。比如路由判断错了我只需要看路由日志就能修正而不是去翻整段对话。线上排查时日志要记录“为什么选这个工具”“检索命中了哪些 chunk”“Agent 决定下一步的依据”这些信息比最终答案文本值钱得多。3.2 生产化不能只盯准确率很多人以为上了 Agent 以后评测只看“回答对不对”。实际上生产环境需要同时可观测以下六个指标端到端延迟P95 尽量在 3 秒内。Agent 多轮调用会把延迟放大 35 倍所以必须限制步数并把无状态查询的向量检索做成并行。检索质量用 Recallk、MRR 看是否真的找出正确片段不是看模型最终说得好不好。工具调用成功率SQL 语法错误率、图谱查询的超时率这些是 Agent 系统的“基建错误”。幻觉率生成内容是否严格落在检索片段和工具返回值范围内。可以抽样让评估模型打分。成本Agentic RAG 的 token 消耗可能是普通 RAG 的 510 倍。建议给每一步设预算上限对高成本查询做缓存。监控与追溯每一次对话都有 trace_id记录完整的决策链。这能让你在用户投诉时快速定位。我在课程里专门留了一节“生产卡住的真相”百分之八十的问题不是模型能力不够而是没有评测集、没有 trace、没有回归测试。你在 notebook 里怎么改都行但生产环境每次升级都要跑同一个测试集对比前后指标。没有这套机制Agent 改着改着就会失控。3.3 框架选型别被热门框架绑架搜“rag框架”的人最多我直接给结论LangChain、LlamaIndex、Haystack 都是可选方案但生产环境的选择标准不是“功能多”而是“可控、可测试、可升级”。我自己维护的那套系统核心代码是自己封装的通过 LLM 输出 JSON 指令来调用工具没有用某个重框架的 Agent 编排层。原因很简单生产环境出问题时你需要能打断点、看中间变量、精确知道是哪一步抛异常。框架的抽象层越厚排障成本越高。但如果团队刚起步用 LangChain 或 LlamaIndex 快速验证思路完全可行。框架优势生产中的坑适合场景LangChain生态最大、工具集成多、Agent 链模板成熟升级 API 频繁、隐式抽象多、调试成本高快速原型、需要大量现成工具LlamaIndex对 RAG 数据管线支持细腻索引/检索组合灵活Agent 组件相对更新慢、社区偏向文档问答以文档为中心的 RAG 项目Haystack管道定义严谨、有完整评测工具、生产部署友好Agent 能力不如前两者自定义工具要额外封装已明确检索管道、重视测评工程自研轻量编排代码少、行为透明、容易 pin 点和优化要自己解决重试、并发、模型调用失败生产稳定优先、中小团队一句话框架只是脚手架真正决定系统质量的是数据质量和评测机制。4. 实操在 Mac 上搭一个可运行的 Agentic RAG4.1 环境准备Ollama ChromaMac 本地搭建 RAG 知识库并不复杂选对工具后半小时能跑通。我在课程里的默认配置是 Ollama启动本地模型 Chroma本地向量库 Python。Mac 上安装 Ollama 用 Homebrew 最省事brew install ollama # 拉取问答模型和 Embedding 模型 ollama pull qwen2.5:7b ollama pull nomic-embed-textqwen2.5 负责 Agent 的推理和工具决策nomic-embed-text 负责把文档切成向量。如果你的 Mac 是 M1/M2/M3 芯片Ollama 会自动使用 Metal 加速跑 7B 模型的中等并发没问题。然后是安装 Python 依赖pip install chromadb ollama pandasChroma 是嵌入式向量库和 SQLite 一样本地运行非常适合实验和中等规模生产原型。生产环境如果并发高建议后面换 Milvus 或 pgvector但只要接口不变替换成本可控。4.2 核心代码Agent 循环 两个工具下面这段代码是个可运行的骨架我故意把工具限制成两个一个检索文档一个查询销售 CSV。完整跑通后你可以按同样的方式加图谱查询工具。import json import chromadb from chromadb.utils.embedding_functions import OllamaEmbeddingFunction from ollama import Client ollama Client() EMBED OllamaEmbeddingFunction(model_namenomic-embed-text) # 准备一个简单文档库 client chromadb.PersistentClient(path./demo_db) col client.get_or_create_collection(docs, embedding_functionEMBED) def search_docs(query, top_k3): 向量检索工具从文档库返回相关片段 res col.query(query_texts[query], n_resultstop_k) return \n.join(res[documents][0]) def query_sales(question): SQL/表格工具这里用 pandas 简单模拟精确查询 import pandas as pd df pd.read_csv(sales.csv) # 生产环境应该用 Text2SQL 或参数化查询这里只做演示 if total in question: return str(df[amount].sum()) return no exact answer TOOLS { search_docs: search_docs, query_sales: query_sales, } SYSTEM_PROMPT 你是客服助手必须按以下 JSON 格式响应 {thought: 你的判断, action: search_docs|query_sales|finish, action_input: 参数} 如果信息已经足够回答用户请使用 actionfinish 并给出 final_answer。 最多不超过 4 步。 def agent_run(question, max_steps4): messages [{role: system, content: SYSTEM_PROMPT}] messages.append({role: user, content: question}) for _ in range(max_steps): resp ollama.chat(modelqwen2.5:7b, messagesmessages) content resp[message][content] # 生产环境建议用正则/JSON修复这里假设模型输出合法 JSON try: decision json.loads(content) except json.JSONDecodeError: continue if decision.get(action) finish: return decision.get(final_answer) tool TOOLS.get(decision.get(action)) if tool: observation tool(decision.get(action_input, )) messages.append({role: assistant, content: content}) messages.append({role: user, content: f工具返回: {observation}}) return 超过最大步数无法确定答案。 if __name__ __main__: print(agent_run(文档库里提到了哪些产品特性)) print(agent_run(销售总额是多少))这段代码把 Agent 的核心逻辑压到了十行里生成 JSON 决策、根据 action 调用工具、把 observation 回填到上下文、再让模型继续。生产环境里你要做的最大改动是给工具调用加超时、重试和权限控制并把中间过程全部打日志。代码本身完全可以跑本地模型如果输出 JSON 不稳定可以在 Prompt 后面加一句“只输出 JSON不要解释”。4.3 用 30 个问题验证 Agent 行为很多人止步于“能跑”但课程必须教“怎么验证”。我建议自己做一套最小评测集至少覆盖四类问题文档检索类答案能从向量库里找到验证 search_docs 的召回。精确计算类需要 query_sales验证路由是否正确。多跳组合类如“文档里提到的产品去年销售额是多少”需要先搜文档再查表格验证 Agent 的连续调用。拒答类无关问题应该直接拒绝不要硬编。每一条记录三个维度最终答案是否正确、工具调用序列是否合理、总步数是否小于上限。用这套小集做回归每次改 Prompt 或换模型都跑一遍。你会在 30 个问题上立刻暴露本地小模型的短板比如路由不稳定、JSON 格式偶尔跑飞。这是好事因为生产环境只会更残酷。另一个建议让一个更强的模型当裁判把问题、答案、工具过程喂给它打 15 分能省大量人工评审时间。5. 常见问题与排查记录5.1 症状、原因和对策速查表下面这份速查表是从我自己的维护日志里归纳的直接可参考症状常见原因解决思路明明有答案却检索不到chunk 过大导致语义稀释embedding 模型不合适没有 metadata 过滤调整 chunk 为 256512 token换领域匹配的 embedding加日期/类型过滤回答和引用对不上生成阶段没有约束必须基于来源Prompt 强制“只能使用检索片段和工具返回值中的事实”加引用 ID延迟过高Agent 串行调用太多步上下文过长限制 max_steps3并行调用多个工具只保留最近两轮对话Agent 陷入死循环没有终止条件模型不知道“不知道”加“如果无法继续调用 finish”检测连续重复动作并强制终止SQL 工具频繁报错LLM 生成 SQL 缺乏表结构约束把 schema 摘要、字段枚举、SQL few-shot 放进 Prompt或改用 HITL图片查不到只有文本 embedding没有多模态向量用 CLIP/SigLIP 生成图片向量在元数据中记录对象存储路径知识更新后回答旧数据索引没有增量更新缓存未失效给每个 chunk 标记源文件版本ETL 定时重建查询增加时间过滤这里要特别提醒不要迷信“加一个大模型就能解决一切”。大多数 Agent 系统的失败核心是数据和工具设计不合理。工具返回的字段名含糊不清模型自然不知道要不要调用。5.2 独家避坑技巧从生产环境学到的两点第一个技巧在 Agent 的 system prompt 里永远加上一句“如果工具返回不够充分直接说不知道不要猜测”。这听起来太简单但它对生产环境的幻觉率抑制效果比任何后置事实核查都便宜。第二句把所有工具调用的输入输出都记录下来尤其是查询改写前后的文本。我发现 60% 的检索失败不是向量库的问题而是 Agent 把“华东区销售额”改写成了“华东区销售区域数据”导致语义漂移。有了 trace你才能发现是这一步错的而不是盲目换 embedding 模型。第二个技巧给每个工具设定“可观察返回值”的格式。比如 search_docs 返回的每个 chunk 都要带来源 IDquery_sales 返回时带 SQL 或 pandas 执行条件。不要返回大段文本让模型慢慢读要在工具层做精简和摘要。我在生产里用过一个很朴素的方法让工具返回最多 10 行有效结果多出来的部分在元数据里说明——模型需要更多细节时再发一次调用。这样既保住上下文长度也逼着 Agent 学会拆解问题。5.3 生产上线前的最后检查清单课程最后一节我会给一张检查清单这里提前分享核心项评测集大于 50 条包含 4 类问题且每条有标准答案。记录每一次 Agent 运行的 trace_id线上出错能溯源。对工具调用设有超时建议 3 秒和重试一次。明确 token 成本上限比如每次会话不超过 10 万 token。对话历史缓存设置过期时间避免长期会话无限膨胀。知识库更新后有版本号和强制刷新机制不依赖进程重启。多用户并发时持久化连接池管理防止 Chroma/SQLite 锁冲突。我在实际使用中还有一点体会生产环境中“少即是多”。你的 Agent 工具集如果能控制在 35 个系统稳定性会远高于挂了 20 个工具的“全能系统”。工具越多路由错误的概率越大。先跑通最小闭环再慢慢加这是我最想对“building for production 卡住”的朋友们说的话。最后一个建议无论你最后选 LangChain、LlamaIndex 还是自研都先把课程里的“最小评测集 trace 日志”落地再谈 Agent 能力扩展。这比我之前调各种 Prompt 参数有用得多。
返回列表