ARTICLE DETAIL

资讯详情

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

RAG进阶实战:从检索增强到智能体工程化落地

RAG进阶实战:从检索增强到智能体工程化落地 1. 为什么现在还要聊RAG进阶RAG这个词从2023年火到现在已经不算新鲜了。但凡做过LLM应用的人几乎都搭过一个文档切块→向量化→检索→拼prompt的demo。问题也恰恰出在这里demo能跑通不代表系统能用。我见过太多团队第一版RAG上线时效果惊艳三个月后用户量一上来检索质量断崖式下跌回答开始胡编运维成本飙升最后整个项目被砍掉。《RAG进阶实战》这个专栏策划案核心要解决的就是这个断层——从能跑到能扛之间的那段路。它面向的不是刚听说RAG的新手而是已经踩过基础坑、准备把系统推向生产环境的开发者。专栏会围绕RAG、LLM、Agent、pgvector、Milvus这几个关键词展开把检索增强这件事从单点技巧升级成一套工程方法论。我个人的判断是2024年之后RAG的竞争点已经不在会不会用向量库而在能不能把检索、记忆、推理、工具调用这几件事编排成一个稳定的系统。这也是为什么Agent会频繁出现在RAG的讨论里——单纯的检索已经不够了用户要的是能查、能算、能记住、能行动的智能体。这个专栏的策划思路就是沿着这条主线往下拆。2. 专栏整体设计与内容主线拆解2.1 从检索增强到检索增强智能体的定位升级传统RAG的定义很窄给LLM外挂一个知识库让它回答时有据可依。但实际项目里你会发现用户的问题往往不是帮我查一段资料这么简单。他可能先问我上个月那份合同里付款条款怎么写的接着问那按这个条款我这次该付多少再问帮我生成一封催款邮件。这三个问题分别对应检索、计算、生成单一RAG链路根本接不住。所以专栏的定位从一开始就定在进阶两个字上不是教你怎么调LangChain的RetrievalQA而是教你怎么把RAG当成一个可编排的组件嵌进更大的Agent架构里。检索负责找事实LLM负责做推理Agent负责决定下一步做什么三者各司其职。这个定位决定了专栏的内容不会停留在API调用层面而会深入到路由策略、记忆管理、工具编排这些真正影响效果的地方。2.2 技术选型背后的取舍逻辑专栏里会重点讲pgvector和Milvus这两个向量库不是随便选的。pgvector适合什么场景你的业务数据本来就在Postgres里量级在百万级以下团队不想再维护一套独立服务那pgvector就是最优解——一个数据库搞定关系数据和向量数据事务一致性还天然有保障。Milvus适合什么场景向量规模上千万甚至上亿需要分布式、需要多种索引类型、需要高并发检索那Milvus的独立架构就值得那份额外的运维成本。我在实际项目里两种都用过。小团队做内部知识库pgvector从零到上线两天搞定做面向C端的产品日活几十万Milvus standalone模式先扛着量再涨就上集群。专栏会把这两种路径的决策依据、迁移成本、性能拐点都讲清楚而不是简单说Milvus更强。2.3 内容模块的编排思路整个专栏我规划成四条主线并行推进。第一条是检索质量线从切块策略、embedding选型、混合检索到重排序解决找不准的问题。第二条是架构线讲pgvector和Milvus的部署、索引、调优解决扛不住的问题。第三条是Agent线讲工具调用、记忆管理、多步推理解决不够用的问题。第四条是评测线讲怎么用LLM as judge、怎么建评测集、怎么定位badcase解决说不清哪里坏了的问题。这四条线不是割裂的每一章都会交叉。比如讲重排序的时候会顺带讲它在Agent多轮检索里怎么用讲Milvus调优的时候会讲它怎么影响Agent的响应延迟。这种编排方式更贴近真实项目的复杂度读者学完能直接迁移到自己的系统里。3. 核心细节解析与实操要点3.1 切块策略RAG效果的第一道分水岭很多人做RAG效果差根子就在切块上。固定长度512字符一切看起来整齐实际上把一句话从中间劈开检索出来的片段语义残缺LLM拿到手里也拼不出完整意思。我的经验是切块要跟着文档结构走而不是跟着字符数走。具体怎么做Markdown文档按标题层级切代码文档按函数边界切合同按条款切论文按章节切。切完之后再做一层语义合并如果相邻两个块合起来不超过阈值就合并如果某个块明显是标题或页眉就丢掉。这套逻辑用LangChain的RecursiveCharacterTextSplitter配合自定义分隔符就能实现不需要多复杂的代码。注意切块大小没有万能值。中文技术文档我一般用300到500字英文用500到800 token法律合同这种需要精确引用的场景块要更小200字左右保证检索出来的片段能直接作为证据。还有一个容易被忽略的点元数据。每个块除了文本内容还要带上来源文件、章节路径、页码、更新时间。这些元数据在后续做过滤检索、引用溯源、增量更新时都是刚需。我见过太多项目上线后想加只搜最近三个月文档的功能结果发现元数据根本没存只能重跑全量。3.2 Embedding选型别只看榜单排名Open LLM Leaderboard这类公开榜单可以参考但不能照搬。榜单测的是通用语义相似度你的业务场景可能是法律、医疗、工业设备手册通用模型未必最优。我的做法是先选两三个候选模型用自己业务里的真实query-doc对做小规模评测看召回率再决定用哪个。中文场景下BGE系列和M3E系列是稳妥选择维度768或1024都够用。如果预算充足可以用API型的embedding服务省去部署和GPU成本但要注意数据出境和调用延迟问题。本地部署的话一张消费级显卡就能跑BGE-large吞吐量对中小规模知识库完全够。提示embedding模型换了整个向量库必须重建。所以选型阶段多花两天做评测比上线后返工划算得多。另外query和doc最好用同一个模型编码混用不同模型会导致向量空间不对齐检索质量直接崩。3.3 混合检索与重排序把召回率拉满纯向量检索有个天然短板对精确匹配不敏感。用户搜GB/T 19001向量检索可能返回一堆语义相近但标准号不对的文档。这时候就需要混合检索——向量检索负责语义召回BM25负责关键词召回两路结果融合后再重排序。融合策略我常用RRFReciprocal Rank Fusion简单有效不需要调权重。重排序用Cross-Encoder模型比如BGE-reranker把粗排的top50精排到top5效果提升非常明显。代价是延迟增加所以重排序一般只对top50做不要对全量做。检索方式优势短板适用场景纯向量语义理解强精确匹配弱开放问答BM25关键词精确无同义扩展编号、术语检索混合重排兼顾两者延迟略高生产环境推荐3.4 Agent记忆管理token的三个点怎么理解热词里有个说法很形象LLM的token三个点——key是我是谁query是我在找什么value是我能提供什么。这其实是在讲记忆的检索逻辑。Agent在多轮对话里不能把所有历史都塞进context那样token爆炸且噪声大。正确做法是把历史对话也做成可检索的记忆库每轮根据当前query去检索相关记忆。短期记忆放context里保留最近几轮长期记忆存向量库按需检索。key用对话主题或实体value用对话内容摘要query用当前用户输入。这样Agent既能记住用户上周提过预算有限又不会把整段历史都拖着走。这个设计在客服、助理类Agent里特别关键直接决定用户体验。4. 实操过程与核心环节实现4.1 用pgvector搭一个最小可用RAG先讲pgvector这条路适合快速验证。环境准备很简单Postgres 14以上装个vector扩展就行。# 安装pgvector扩展 CREATE EXTENSION vector; # 建表embedding维度按模型定BGE-large是1024 CREATE TABLE documents ( id SERIAL PRIMARY KEY, content TEXT, metadata JSONB, embedding vector(1024) ); # 建HNSW索引比IVFFlat更适合动态数据 CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);检索的时候用余弦距离pgvector的操作符就是余弦距离。查询语句大概长这样SELECT content, metadata, 1 - (embedding $1) AS similarity FROM documents WHERE metadata-source contract ORDER BY embedding $1 LIMIT 5;这套方案我从零搭到能跑半天时间。优点是事务一致插入文档和插入向量在同一个事务里不会出现数据不一致。缺点是向量规模超过500万后查询延迟开始明显上升这时候就该考虑Milvus了。4.2 Milvus standalone模式部署与踩坑Milvus standalone模式适合单机部署用Docker Compose拉起最省事。在Mac上装的话注意Docker Desktop的内存要调到至少8G否则Milvus的etcd和minio容易OOM。# 下载官方compose文件 wget https://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-standalone-docker-compose.yml -O docker-compose.yml # 启动 docker-compose up -d # 验证 docker-compose ps连接的时候有个坑milvus_uri如果写成./data/milvus.db这种本地路径那是Milvus Lite的用法standalone模式必须用http://localhost:19530。我见过有人本地加载提示连接失败排查半天发现是URI写错了。建collection的时候索引类型选HNSWmetric_type选COSINE。Milvus的余弦值计算和pgvector略有差异Milvus返回的是相似度分数越大越相似pgvector返回的是距离越小越相似写代码时别搞反了。from pymilvus import Collection, CollectionSchema, FieldSchema, DataType fields [ FieldSchema(nameid, dtypeDataType.INT64, is_primaryTrue, auto_idTrue), FieldSchema(nameembedding, dtypeDataType.FLOAT_VECTOR, dim1024), FieldSchema(namecontent, dtypeDataType.VARCHAR, max_length65535), ] schema CollectionSchema(fields) collection Collection(namerag_docs, schemaschema) collection.create_index(embedding, { index_type: HNSW, metric_type: COSINE, params: {M: 16, efConstruction: 200} })M和efConstruction这两个参数M控制图的连接度越大召回越高但内存占用越大efConstruction控制建索引时的搜索范围越大索引质量越好但建索引越慢。生产环境我一般M16efConstruction200平衡效果和成本。4.3 检索链路串起来从query到answer完整链路是这样的用户query进来先做query改写把口语化问题转成检索友好的表达然后并行走向量检索和BM25检索结果用RRF融合取top50送重排序重排序取top5拼进prompt最后LLM生成答案。query改写这一步很多人省了但效果差异很大。用户问那个啥来着就是上次说的付款的事直接检索基本废掉。用一个小模型做改写输出付款条款 付款时间 付款方式检索质量立刻上来。改写模型可以用本地小模型也可以用API成本很低。prompt拼装也有讲究。不要简单把5个片段堆进去要带上来源标注让LLM知道每段话出自哪里。生成答案时要求LLM引用来源编号这样用户能溯源也方便后续做评测。4.4 Agent工具调用的最小实现Agent的核心是决定调用哪个工具。最简单的实现是ReAct模式LLM输出思考过程决定调用检索工具还是计算工具还是直接回答。检索工具就是上面那套RAG链路计算工具可以是Python执行器回答工具就是直接生成。tools [ {name: search_knowledge, description: 检索知识库, func: rag_search}, {name: calculate, description: 执行数学计算, func: python_calc}, ]LLM根据用户问题选择工具拿到工具返回结果后再决定下一步。这个循环跑几轮直到LLM认为可以给出最终答案。关键点是工具描述要写清楚LLM才能选对。描述模糊是工具调用失败的头号原因。注意Agent循环一定要设最大轮数否则LLM可能陷入死循环反复调用同一个工具。我一般设5轮上限超过就强制返回当前最优答案。5. 常见问题与排查技巧实录5.1 检索质量突然下降怎么排查这是最高频的问题。排查顺序我总结成一张表现象可能原因排查方法召回内容不相关embedding模型换了检查模型版本是否一致精确匹配失效索引未重建确认新数据是否已建索引结果重复切块重叠过大检查chunk_overlap参数延迟飙升索引参数不当检查HNSW的ef参数部分文档搜不到元数据过滤错误检查filter条件我遇到过一次诡异的情况检索结果突然全是旧文档。排查半天发现是增量更新时新文档的embedding用了新模型旧文档还是老模型向量空间不一致。解决办法就是全量重建没有捷径。5.2 Milvus连接与性能问题速查Milvus standalone最常见的三个问题连接超时、内存不足、索引加载慢。连接超时一般是端口没通检查19530和9091端口。内存不足调Docker内存上限。索引加载慢是正常的HNSW索引加载到内存需要时间collection.load()之后要等一会儿才能查。还有个坑Milvus的collection删除后数据不会立即释放要等GC。频繁建删collection会导致内存泄漏。生产环境建议复用collection用分区或字段过滤来隔离数据。5.3 Agent调用失败的典型场景Agent调用工具失败八成是这几个原因工具描述不清、参数格式不对、返回值太大。参数格式问题最常见LLM生成的JSON有时候多一个逗号就解析失败。解决办法是用结构化输出约束或者加一层容错解析。返回值太大也是个坑。检索工具返回5个长文档塞进context直接爆token。要在工具内部做截断只返回最相关的片段控制在2000 token以内。5.4 评测怎么做才靠谱没有评测的RAG系统就是盲人摸象。我的做法是建一个200条左右的评测集覆盖常见问题类型每条标注标准答案和应召回的文档。每次改动后跑一遍看召回率和答案准确率的变化。LLM as judge可以辅助评测但不能全信。我一般用LLM做初筛人工复核争议case。judge的prompt要写清楚评分标准否则LLM打分很随意。评测集要持续更新把线上badcase加进去这样评测才越来越贴近真实场景。6. 从专栏到落地我的一些实操体会做RAG进阶这件事最大的体会是没有银弹只有权衡。pgvector和Milvus没有绝对优劣切块大小没有标准答案Agent轮数没有固定值一切都要看你的数据规模、延迟要求、团队能力。专栏能做的是把这些权衡的维度和依据讲清楚让你在做决策时有据可依而不是拍脑袋。另一个体会是评测要趁早。很多人把评测放到最后做结果发现系统已经烂到没法救。正确的顺序是先建评测集再搭系统每改一处就跑评测。这样你能清楚知道每一步改动是正向还是负向不会越改越乱。最后分享一个小技巧把线上用户的query都存下来定期抽样分析。你会发现很多你没想到的问法这些才是真正驱动系统迭代的燃料。我负责的一个项目就是靠分析query日志发现用户大量在问表格数据于是专门加了表格检索链路效果提升立竿见影。RAG进阶的路说到底就是被真实需求推着往前走。
返回列表