ARTICLE DETAIL

资讯详情

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

Agent驱动RAG知识库面试全链路:从文档切分到pgvector选型与Agent调度

Agent驱动RAG知识库面试全链路:从文档切分到pgvector选型与Agent调度 1. 面试官问的不是术语是你有没有真的跑过链路DocResearch 这个项目名字听起来像个文档问答工具但真正面过这类岗位的人都知道面试官关心的从来不是你能不能背出 RAG 的全称而是你能不能把一条完整的链路讲清楚文档进来之后怎么切、切完存哪里、检索的时候怎么召回、召回之后怎么重排、重排完怎么喂给 Agent、Agent 又怎么决定要不要再查一轮。这条链路上任何一个环节含糊面试官三句话就能把你问穿。我面过也带过人面过见过太多候选人把“我用了 pgvector 做向量检索”挂在嘴边结果一问“为什么选 pgvector 而不是 FAISS 或者 Milvus”就开始说“因为它是 PostgreSQL 的扩展比较方便”。这个回答不算错但太浅了。面试官想听的是你的数据量级多大、写入和查询的比例是多少、有没有事务需求、运维成本能不能接受、团队里有没有人熟悉 Postgres。这些才是选型的真实理由术语只是结果。DocResearch 这类项目的核心其实是一个Agent 驱动的检索增强系统。它和普通的 RAG 问答最大的区别在于普通 RAG 是“一次检索、一次生成”而 DocResearch 里的 Agent 会自己判断“这次检索够不够”“要不要换个关键词再查”“要不要拆成多个子问题分别查”。这个判断能力才是 Agent 和普通 RAG 的分水岭也是面试里最能拉开差距的地方。这篇文章我想按面试的真实节奏来写不是给你一份标准答案让你背而是把每个模块“为什么这么设计”“我当时怎么想的”“踩过什么坑”讲透。你看完之后应该能做到面试官随便挑一个模块你都能从需求、选型、实现、坑点四个层面讲出十分钟不带重复的内容。适合谁看如果你正在准备 DocResearch 或类似 Agent RAG 项目的面试或者你手上正在搭一个知识库问答系统但总觉得哪里不对劲这篇内容应该能帮你把思路理顺。我会尽量用大白话把那些看起来高大上的概念拆成你能直接上手的东西。2. 文档切分最不起眼却最容易翻车的环节2.1 为什么固定长度切分是个陷阱几乎所有人做 RAG 的第一步都是“把文档切成块”。很多人上来就写chunk_size500, overlap50然后就开始调检索效果。我一开始也这么干后来发现检索出来的内容经常“缺头少尾”——一个完整的段落被从中间切断前半段在一个 chunk 里后半段在另一个 chunk 里检索到哪个都答不全。固定长度切分的问题在于它假设“文本的价值均匀分布”但真实文档不是这样的。一份技术文档里一个标题下面的内容是一个完整语义单元一份合同里一个条款是一个完整单元。你按字符数硬切等于把语义单元打碎了。DocResearch 里我最后采用的是结构化切分 语义切分结合的策略。具体做法是先按文档的天然结构切比如 Markdown 按标题层级切PDF 按段落和表格边界切代码文件按函数和类切。对于超长的结构块再用语义切分做二次处理判断相邻句子之间的语义相似度相似度骤降的地方就是切分点。最后给每个 chunk 补上“上下文头”也就是它所属的章节标题路径比如[第三章 3.2 检索策略 3.2.1 向量召回]。这个上下文头非常关键。面试的时候如果你能主动提到这一点面试官会觉得你真的调过效果。因为检索的时候用户问“向量召回怎么做的”如果 chunk 里只有正文没有标题模型可能不知道这段在讲什么加上标题路径之后召回准确率会有肉眼可见的提升。2.2 chunk 大小到底怎么定这个问题没有标准答案但有一个思考框架。chunk 太大检索精度下降因为一个 chunk 里混了太多主题chunk 太小上下文不足模型答不全。我的经验值是文档类型建议 chunk 大小overlap理由技术文档300-500 token50-80段落短语义密度高法律合同500-800 token100条款完整性强不能切碎会议纪要200-400 token30话题切换频繁代码文件按函数切不适用函数是天然语义单元注意这里说的是 token 不是字符。中文里一个 token 大约对应 1.5 到 2 个汉字英文里一个 token 大约 0.75 个单词。很多人用字符数来设 chunk_size结果中文文档切出来特别碎因为中文字符信息密度高。还有一个实操细节overlap 不是越大越好。我见过有人设 overlap200结果检索出来的内容大量重复反而干扰了重排。overlap 的作用是防止切分点正好落在关键句中间一般设 chunk 大小的 10% 到 20% 就够了。2.3 表格和图片怎么处理这是面试里经常被追问的点因为热词里就有“rag知识库能存储图片嘛”。答案是能但不是你想的那种存法。图片本身不能直接做向量检索你需要把它转成文本描述或者向量。DocResearch 里的做法是表格用解析库把表格转成 Markdown 格式保留行列结构然后作为一个独立 chunk 存储。表格的检索往往靠关键词匹配更有效所以我会给表格 chunk 同时建向量索引和全文索引。图片用多模态模型生成图片描述把描述文本作为 chunk 内容同时保留图片的原始路径。检索到描述之后前端可以根据路径把原图展示出来。图表如果图表里有数据尽量用 OCR 或者结构化解析把数据抽出来转成文字描述。提示图片描述的质量直接决定检索效果。我试过用通用描述“这是一张架构图”结果完全检索不到后来改成“这是 DocResearch 的检索链路架构图包含文档解析、向量化、pgvector 存储、Agent 调度四个模块”效果立刻不一样。描述要包含“这张图在讲什么主题”而不只是“这张图长什么样”。3. 向量存储选型pgvector 到底适合什么场景3.1 pgvector 的真实定位热词里有“pgvector windows precompiled下载”说明很多人卡在安装这一步。但面试官不会问你安装他会问你“为什么用 pgvector”。这个问题的答案取决于你的项目规模和团队情况。pgvector 的本质是给 PostgreSQL 加了一个向量类型和向量索引。它的优势不是性能最强而是你不需要额外维护一套数据库。如果你的项目已经在用 Postgres 存业务数据那向量数据放在同一个库里可以用 SQL 直接 join事务也能保证一致性。这对中小规模项目来说运维成本低得不是一点半点。但它的边界也很清楚数据量超过千万级向量查询延迟会明显上升这时候要考虑专用向量库。需要极致的召回性能比如毫秒级、亿级向量pgvector 不是最优解。如果你的团队完全没用过 Postgres那“省一套数据库”的优势就不存在了。我在 DocResearch 里选 pgvector就是因为项目本身用 Postgres 存文档元数据向量放同一个库检索的时候一条 SQL 就能把“向量相似度 元数据过滤”一起做完不用在应用层做两次查询再合并。这个设计在面试里讲出来比单纯说“pgvector 方便”有说服力得多。3.2 索引类型的选择逻辑pgvector 支持两种索引IVFFlat 和 HNSW。很多人建索引的时候随便选一个结果查询慢得离谱。这两个索引的区别用大白话讲IVFFlat把向量空间划分成若干个簇查询的时候只查最近的几个簇。建索引快内存占用小但召回率依赖簇的数量需要调参。HNSW建一个多层图查询的时候在图上走。查询快召回率高但建索引慢内存占用大。我的选择逻辑是数据量小、写入频繁、对召回率要求不是极致 → IVFFlat数据量中等、查询频繁、召回率要求高 → HNSW。DocResearch 里文档更新不频繁但查询很频繁所以我选了 HNSW。建索引的时候有个坑HNSW 的m和ef_construction参数直接影响索引质量和构建时间。m是每个节点的连接数越大召回率越高但内存越大ef_construction是构建时的候选集大小越大索引质量越好但构建越慢。我一般从m16, ef_construction64开始调数据量大的时候会加到m32, ef_construction128。查询的时候还有一个ef_search参数控制查询时的候选集大小。这个参数可以在查询时动态调整不需要重建索引。如果发现召回不够先调这个别急着重建。3.3 元数据过滤和向量检索怎么配合这是 pgvector 相比专用向量库的一个隐藏优势。假设你要查“2023 年之后的、关于检索策略的文档”用专用向量库你可能需要先做向量检索拿到一堆结果再在应用层过滤年份效率很低。用 pgvector 可以直接写SELECT content, 1 - (embedding query_embedding) AS similarity FROM doc_chunks WHERE doc_date 2023-01-01 ORDER BY embedding query_embedding LIMIT 10;这条 SQL 里是向量距离操作符WHERE是元数据过滤Postgres 的查询优化器会决定先过滤还是先算距离。这个能力在面试里讲出来面试官会觉得你确实用过而不是只看过文档。注意元数据过滤的字段最好建 B-tree 索引否则全表扫描会拖慢查询。另外如果过滤后的结果集太小向量索引可能反而不如全表扫描快这时候查询优化器会自动切换你不用手动干预。4. 检索策略从单路召回走向多路融合4.1 纯向量检索的瓶颈在哪向量检索的本质是“语义相似”它擅长找“意思相近”的内容但不擅长找“精确匹配”的内容。比如用户问“DocResearch 里 pgvector 的索引参数怎么设”向量检索可能召回一堆讲向量数据库的文章但真正包含“pgvector 索引参数”这个精确短语的 chunk 反而排不到前面。这就是热词里说的“rag瓶颈”之一单一检索方式无法覆盖所有查询意图。用户的问题有时候是语义型的“怎么提高检索准确率”有时候是精确型的“HNSW 的 m 参数默认值是多少”有时候是混合型的。DocResearch 里的解决方案是多路召回 融合重排向量召回负责语义匹配用 embedding 相似度。全文召回负责精确匹配用 PostgreSQL 的全文检索或者 BM25。关键词召回负责专有名词匹配用倒排索引。三路召回各自拿一批候选然后用 RRFReciprocal Rank Fusion做融合。RRF 的公式很简单每个文档的得分是1 / (k rank)k 一般取 60。这个方法的妙处在于它不需要知道每路召回的分数分布只看排名所以不同检索方式的结果可以直接融合。4.2 重排模型值不值得上多路召回之后候选集可能有几十上百个直接喂给大模型会超上下文而且噪声太多。这时候需要重排。重排模型Reranker和 embedding 模型的区别是embedding 是“双塔”结构query 和 document 分别编码再算相似度快但精度有限Reranker 是“交叉编码”结构query 和 document 拼在一起过模型精度高但慢。所以典型流程是向量召回拿 top 100Reranker 精排拿 top 5。面试里经常被问“Reranker 值不值得上”。我的回答是看你的场景对准确率的敏感程度。如果答错一个问题的代价很高比如法律、医疗那 Reranker 必须上如果是闲聊型问答Reranker 的收益可能抵不上它带来的延迟。DocResearch 里我上了 Reranker因为文档问答的场景下用户对答案准确性的期望很高。实测下来加了 Reranker 之后top 5 的命中率从 60% 左右提升到了 80% 以上。这个提升在面试里是可以量化的比说“效果变好了”有说服力。4.3 查询改写让 Agent 决定怎么查这是 DocResearch 区别于普通 RAG 的核心模块。普通 RAG 是用户问什么就查什么但用户的问法往往和文档的写法不一致。比如用户问“怎么让检索更准”文档里写的是“提升召回率的策略”直接拿用户问题去检索效果可能不好。Agent 在这里的作用是查询改写把口语化的问题改写成文档里可能出现的表述。把复杂问题拆成多个子问题分别检索再合并。根据第一轮检索的结果判断要不要换关键词再查一轮。这个“判断要不要再查”的能力就是 Agent 和固定流程的区别。实现上我会给 Agent 一个工具集search(query)、rerank(results)、read(chunk_id)然后让它自己决定调用顺序。Agent 的 prompt 里会明确告诉它“如果第一轮检索的结果和问题不相关尝试用不同的关键词再查一次。”提示Agent 的查询改写不要过度。我见过有人让 Agent 把每个问题都拆成五个子问题结果检索次数暴涨延迟从 2 秒变成 10 秒效果还没提升多少。拆分的粒度要控制一般一个问题拆成 2 到 3 个子问题就够了。5. Agent 调度DocResearch 真正的技术分水岭5.1 Agent 和普通 RAG 的本质区别热词里有“harness和agent区别”“agent架构”“ai agent搭建”说明大家对 Agent 的理解还比较模糊。用一句话讲清楚普通 RAG 是“检索一次、生成一次”的固定流程Agent 是“自己决定下一步做什么”的动态流程。在 DocResearch 里Agent 要做的决策包括这个问题需不需要检索有些问题比如“你好”根本不需要查文档。检索几轮第一轮结果不够好要不要再查用哪个检索工具向量检索、全文检索、还是两个都用检索到的内容够不够回答问题不够的话要不要换个角度再查什么时候停止不能无限查下去。这些决策串起来就是一个 Agent 的“思考-行动-观察”循环。面试的时候如果你能把这个循环画出来口头描述也行并且说清楚每一步的输入输出面试官基本就能判断你真的实现过。5.2 工具设计Agent 的手和眼Agent 的能力边界取决于你给它什么工具。DocResearch 里我设计了四个核心工具工具名输入输出用途search_vectorquery, top_kchunk 列表语义检索search_fulltextquery, top_kchunk 列表精确检索rerankquery, chunks重排后 chunks精排read_chunkchunk_idchunk 全文读取完整内容工具设计的原则是每个工具只做一件事输入输出明确错误处理清晰。不要设计一个“万能检索工具”让 Agent 自己选检索方式那样 Agent 反而容易懵。把选择权交给 Agent但把每个选项做简单。还有一个细节工具的返回结果要包含足够的元信息比如 chunk 的来源文档、章节路径、相似度分数。Agent 根据这些信息判断“这个结果可不可靠”。如果只返回一段文本Agent 没法判断质量。5.3 怎么防止 Agent 陷入死循环这是 Agent 开发里最实际的问题。Agent 可能会一直觉得“检索结果不够好”然后无限查下去。防护措施有三层最大轮次限制硬性限制 Agent 最多查 3 轮超过就强制生成答案。结果去重如果新一轮检索的结果和上一轮高度重叠说明再查也没用直接停止。超时控制整个 Agent 流程设置总超时比如 15 秒超时就用已有结果生成。这三层防护在面试里讲出来面试官会觉得你考虑过生产环境的问题而不是只跑通了 demo。5.4 Agent 的并发问题热词里有“ai agent 怎么扛并发”这是个好问题。Agent 的并发瓶颈通常不在 Agent 本身而在它调用的工具上。向量检索、Reranker、大模型生成每一个都是耗时操作。DocResearch 里的做法是向量检索和全文检索可以并行发起用异步 IO 同时查减少等待时间。Reranker 是 CPU/GPU 密集型用批处理一次重排多个 query 的候选集。大模型生成用流式输出用户不用等全部生成完才看到内容。Agent 的会话状态存在 Redis 里支持多实例水平扩展。这些优化手段面试的时候不用全讲但至少要能说出“瓶颈在哪、怎么定位、怎么优化”的思路。6. 面试里怎么把模块讲成故事6.1 用“问题-方案-结果”结构组织回答面试官问“你这个检索模块怎么做的”最忌讳的回答是“我用了向量检索和全文检索然后做了融合”。这是陈述不是故事。好的回答结构是问题一开始只用向量检索发现精确匹配的查询召回不好比如用户问某个具体参数名向量检索召回的都是泛泛而谈的文章。方案加了全文检索做多路召回用 RRF 融合又加了 Reranker 精排。结果top 5 命中率从 60% 提升到 80%延迟从 1.5 秒增加到 2.2 秒在可接受范围内。这个结构的好处是面试官能听到你的思考过程而不只是最终方案。而且“结果”部分有数据可信度立刻上来了。6.2 主动暴露一个坑比完美回答更加分面试里最加分的时刻往往是你主动说“这里我踩过一个坑”。比如“切分的时候我一开始用固定长度结果检索出来的内容经常缺上下文。后来改成按结构切分并且给每个 chunk 加上章节标题路径召回准确率明显提升。这个改动看起来小但效果比换 embedding 模型还明显。”这段话里有问题、有方案、有对比、有量化面试官会觉得你是真的做过而不是背的。6.3 被问到不会的怎么办DocResearch 涉及的技术栈很广面试官可能会问到你没用过的部分比如“你们有没有考虑过用知识图谱”。这时候不要硬编可以说“知识图谱这块我们评估过但当时的数据量级和查询类型用向量检索加全文检索已经能覆盖引入图谱会增加不少复杂度。如果要做的话我会从实体抽取和关系抽取入手把图谱作为一路召回和现有的多路召回融合。”这个回答承认了没做但展示了你知道怎么做以及为什么当时没做。面试官通常能接受这种回答。7. 几个容易被忽略但面试常问的细节7.1 embedding 模型怎么选热词里有“rag框架”“rag教程”但很少有人讲 embedding 模型的选择。DocResearch 里我对比过几个模型选择逻辑是中文为主选中文语料训练充分的模型不要直接用英文模型。维度维度越高表达能力越强但存储和检索成本也越高。768 维和 1024 维在实际效果上差距不大但存储差 30%。推理速度如果文档量大embedding 的生成速度直接影响入库时间。是否支持长文本有些模型只支持 512 token超过就截断这对长 chunk 不友好。面试的时候如果你能说出“我对比过 A 模型和 B 模型在中文技术文档上 A 的召回率高 5 个百分点”这比说“我用了某某模型”有说服力得多。7.2 怎么评估检索效果这是很多人忽略的环节。你改了切分策略、换了 embedding 模型、加了 Reranker怎么知道效果变好了靠感觉是不行的。DocResearch 里我建了一个小规模的评估集人工标注了 100 个问题和对应的正确 chunk。每次改动之后跑一遍评估集看 top 5 命中率、MRR平均倒数排名这些指标。这个评估集不用很大100 条就能看出趋势。面试的时候提到“我建了评估集来量化效果”面试官会觉得你有工程思维而不是只会调参。7.3 成本控制Agent RAG 的成本主要来自三块embedding 生成、向量存储、大模型调用。DocResearch 里的控制手段embedding 只在文档入库时生成一次查询时复用。向量存储用 pgvector省了一套数据库的运维成本。大模型调用做缓存相同或相似的问题直接返回缓存结果。Agent 的轮次限制避免无限调用大模型。这些在面试里不用全讲但至少要知道成本花在哪以及怎么控制。8. 我踩过的几个真实坑第一个坑是chunk 的元数据丢失。一开始我只存了 chunk 内容和向量没存来源文档和章节路径。后来发现检索出来的内容没法溯源用户问“这个答案从哪来的”答不上来。加上元数据之后不仅溯源方便了检索时还能按文档类型过滤。第二个坑是Reranker 的输入长度超限。Reranker 模型通常有最大输入长度限制query 加 document 超过限制会被截断。我一开始没注意长文档的 chunk 被截断后重排效果很差。后来在切分阶段就控制了 chunk 大小确保 query 加 chunk 不超过 Reranker 的限制。第三个坑是Agent 的 prompt 太长导致指令遵循下降。Agent 的 system prompt 里塞了太多工具说明和规则结果 Agent 经常忽略某些规则。后来我把 prompt 精简到只保留核心指令把详细说明放到工具描述里效果反而更好。第四个坑是pgvector 的索引在数据量小的时候反而拖慢查询。数据量低于一万条的时候全表扫描比走索引还快因为索引本身有开销。Postgres 的查询优化器有时候会选错需要手动分析执行计划。这个坑在面试里讲出来面试官会觉得你真的在生产环境跑过。9. 如果重新做一遍我会怎么调整如果让我重新搭一遍 DocResearch我会在几个地方做得不一样。第一评估集先行。一开始就建好评估集而不是做到一半才想起来要量化效果。有了评估集每次改动都能快速验证不用靠感觉。第二切分策略做成可配置。不同文档类型用不同的切分参数而不是一套参数打天下。配置化之后调优不用改代码。第三Agent 的工具设计更克制。工具不是越多越好每个工具都要有明确的适用场景。工具太多Agent 的选择成本反而高。第四日志和可观测性从第一天就加上。Agent 的每一步决策、每次检索的结果、每个工具的耗时都要有日志。出了问题能快速定位而不是靠猜。这些调整看起来是工程细节但面试的时候如果你能说出“如果重做我会怎么改”面试官会觉得你有反思能力而不是只会执行。10. 面试前最后检查清单面 DocResearch 这类项目之前我会建议你对着下面这些问题自测一遍。每个问题都要能用“问题-方案-结果”的结构讲出来而不是一句话带过。文档切分为什么不用固定长度你的切分策略是什么为什么选 pgvector它的边界在哪向量索引选的哪种参数怎么定的检索用了几路怎么融合的Reranker 上了没有效果提升多少Agent 在流程里做了什么决策怎么防止死循环检索效果怎么评估的有没有量化数据整个链路的延迟是多少瓶颈在哪踩过最大的坑是什么怎么解决的如果重新做你会改什么这十个问题如果能答清楚面试基本就稳了。答不清楚的地方就是你需要补的地方。面试不是考你背了多少术语而是考你有没有真的把一条链路跑通、跑好、跑出数据。术语谁都能背但踩过的坑和量化过的效果只有真正做过的人才有。
返回列表