尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

千亿级AI知识库实战:腾讯云ES混合检索与RAG链路优化

千亿级AI知识库实战:腾讯云ES混合检索与RAG链路优化 1. 千亿级AI知识库到底难在哪第一次听到千亿级AI知识库这个量级的时候我脑子里第一反应不是兴奋而是这得烧多少钱。后来真正参与到类似规模的项目里才发现钱只是一方面更麻烦的是数据规模、检索延迟、召回质量这三者之间的三角博弈。ima这个产品做的是AI知识库底层依托腾讯云ESElasticsearch来承载千亿级的向量和文本混合检索这个架构选择本身就值得好好拆一拆。先说清楚这个项目解决的是什么问题。传统的企业知识库本质上就是存文档关键词搜索用户搜报销流程它给你返回一堆包含报销两个字的文档至于哪篇真正回答了问题得你自己翻。而AI知识库要干的事情是用户用自然语言提问系统理解意图从千亿级的知识片段里精准捞出最相关的那几条喂给大模型让大模型生成一个直接可用的答案。这中间涉及**RAG检索增强生成**的完整链路而检索这一环就是整个链路的瓶颈所在。为什么说是瓶颈因为大模型本身的能力再强如果检索回来的内容是错的、不全的、或者排序不对那生成的答案就是一本正经地胡说八道。行业里有个说法叫RAG的hit rate决定了天花板检索命中率上不去后面所有的优化都是白搭。ima要面对的是千亿级的数据量这意味着单靠一个向量库或者单靠关键词检索都撑不住必须做向量检索全文检索的混合召回还要在毫秒级完成排序返回。这套架构适合谁来参考我觉着有三类人值得细看一是正在做RAG项目、卡在检索质量上的工程师二是负责企业知识库建设、需要做技术选型的架构师三是对AI知识库底层原理好奇、想搞清楚为什么我的知识库答不准的产品经理。不管你用的是LangChain4j、Spring AI还是自己手搓的RAG框架底层的检索逻辑是相通的。2. 架构选型的核心逻辑拆解2.1 为什么是腾讯云ES而不是纯向量数据库很多人一上来就问做AI知识库不是应该用专门的向量数据库吗Milvus、Qdrant、Weaviate这些不香吗我一开始也这么想但实际做过几个项目之后发现事情没那么简单。纯向量数据库的优势在于向量检索的性能和召回率调优空间大但它有个致命短板不支持复杂的标量过滤和全文检索。举个实际场景用户问2024年第三季度的销售政策里关于返点的规定这里面既有语义检索的需求返点规定又有精确过滤的需求2024年第三季度还有全文匹配的需求销售政策。如果你只用向量库那个时间过滤就得在应用层做数据量一大性能直接崩。腾讯云ES的好处在于它是向量检索和全文检索的统一引擎。ES从7.x版本开始支持dense_vector字段类型到8.x已经支持kNN检索同时它本身就是一个成熟的全文搜索引擎倒排索引、BM25打分、聚合分析这些都是看家本领。一个查询请求里你可以同时做向量相似度匹配和关键词匹配然后用RRFReciprocal Rank Fusion或者自定义的加权策略把两路结果融合排序。这就省掉了在应用层做多路召回合并的复杂度。还有一个很现实的原因运维成本。单独维护一套向量数据库加一套全文搜索引擎意味着两套集群、两套监控、两套备份策略、两套扩容逻辑。用ES统一承载至少运维层面少一半工作量。当然这不是说ES就是万能的后面我会讲到它在向量检索上的一些坑。2.2 千亿级数据的分片策略怎么定千亿级数据量这个规模下分片策略直接决定了集群能不能稳住。我见过太多项目一开始随便设了个默认的5个分片数据涨到几十亿就开始各种超时。ES的分片设计有个经验公式单个分片的大小控制在30GB到50GB之间。假设千亿级数据每条记录平均1KB包含向量、原文、元数据那就是大约10TB的原始数据。算上副本和索引开销实际存储可能在20TB到30TB。按每个分片40GB算大概需要500到750个主分片。这个数量听起来吓人但分布到几十个数据节点上每个节点承担十几个分片是可以接受的。但分片不是越多越好。每个分片本质上是一个Lucene索引分片太多会导致集群状态管理开销增大master节点压力大查询时需要合并的分片结果增多协调节点压力大每个分片的段合并segment merge消耗更多资源所以实际做法是按时间或者按业务维度做索引分层。比如热数据最近3个月放在高配节点上分片数多一些保证查询性能冷数据3个月以前做索引合并减少分片数甚至用可搜索快照searchable snapshot降到对象存储里。ima这种知识库场景大部分查询集中在近期文档上冷热分离能省下大量成本。2.3 向量维度和索引类型的选择向量检索的核心参数就两个维度和索引类型。维度取决于你用的embedding模型。常见的比如OpenAI的text-embedding-3-large是3072维BGE-large是1024维m3e-base是768维。维度越高语义表达能力越强但存储和计算成本也线性增长。千亿级数据下3072维的向量光存储就是一大笔开销。我的建议是除非你的场景对语义精度要求极高否则768到1024维足够用了。实测下来1024维和3072维在大部分知识库问答场景下的召回率差异不到3个百分点但存储成本差了3倍。索引类型方面ES支持两种kNN检索方式近似kNNANN基于HNSW算法查询快但召回率不是100%精确kNNexact暴力计算召回率100%但速度慢千亿级数据下精确kNN基本不可用必须用近似kNN。HNSW的关键参数是m每个节点的连接数和ef_construction构建时的候选队列大小。m越大索引越大召回率越高ef_construction越大构建越慢但索引质量越好。经验值是m16到m32ef_construction100到200。查询时的ef_search参数可以动态调整牺牲延迟换召回率。3. 混合检索与RAG链路的实操细节3.1 向量检索和全文检索怎么融合这是整个架构里最核心的部分。ima的做法是双路召回融合排序具体流程是这样的第一路向量检索。用户query经过embedding模型转成向量在ES里做kNN检索返回top-K个语义最相似的文档片段。这一路擅长处理意思相近但用词不同的情况比如用户问怎么请假能召回休假申请流程。第二路全文检索。用户query经过分词后在ES里做BM25检索返回top-K个关键词匹配度最高的文档片段。这一路擅长处理精确术语和专有名词比如用户问P0级故障处理流程向量检索可能召回一堆故障处理的文档但全文检索能精准命中P0这个关键词。两路各返回比如50条结果然后用RRF算法融合。RRF的公式很简单score sum(1 / (k rank))其中k是一个常数通常取60rank是文档在每一路结果里的排名。这个算法的好处是不需要归一化不同路的分数直接基于排名融合工程上很好实现。但RRF也不是万能的。如果两路召回的质量差异很大比如向量检索明显更准那RRF会把两路平等对待反而拉低了整体效果。这时候可以给两路加权重比如向量路权重0.7全文路权重0.3。权重的调参没有理论最优解只能靠A/B测试和人工评估。3.2 Chunk策略决定了检索的上限很多人把精力全花在检索算法上却忽略了**文档切分chunking**这个前置环节。我可以负责任地说chunk策略没做好后面怎么调都是白费。千亿级知识库的文档来源五花八门PDF、Word、网页、数据库记录、聊天记录。不同来源的文档结构差异巨大用一套固定的chunk大小比如512个token去切所有文档效果一定好不了。我的实操经验是分层chunk第一层按文档的自然结构切分。比如Markdown按标题层级切PDF按段落切表格单独处理。第二层对过长的段落做滑动窗口切分窗口大小512 token重叠128 token。重叠是为了避免关键信息被切断。第三层对每个chunk生成一个摘要向量和一个原文向量。摘要向量用于粗筛原文向量用于精排。为什么要生成摘要向量因为有些chunk很长直接embedding会丢失细节。先用摘要做粗筛把候选范围从千亿级降到百万级再用原文向量精排这样兼顾了速度和精度。还有一个细节chunk的元数据要保留完整。每个chunk必须带上来源文档ID、章节路径、创建时间、权限标签。权限标签尤其重要企业知识库里不同部门的文档访问权限不同检索时必须做权限过滤否则会出现员工搜到了不该看的文档这种严重问题。3.3 写入性能优化怎么判断是磁盘瓶颈还是其他问题千亿级数据不是一次性灌进去的而是持续增量写入。写入性能直接决定了知识库的时效性。ES写入慢的原因有很多我整理了一个排查思路现象可能原因排查方法解决方向写入延迟高但CPU不高磁盘IO瓶颈看iostat的%util和await换SSD或增加节点写入延迟高且CPU高段合并频繁看thread_pool的merge队列调大refresh_interval写入延迟周期性飙升GC压力看JVM的GC日志调大堆内存或换G1写入吞吐上不去分片数不足看每个分片的写入速率增加主分片数批量写入超时bulk队列满看thread_pool的write队列减小bulk批次或增加节点判断磁盘是否是瓶颈最直接的指标是iostat的%util。如果%util持续超过80%同时await平均等待时间超过20ms那基本可以确定是磁盘扛不住了。这时候要么换NVMe SSD要么增加数据节点分摊压力。另一个容易被忽略的指标是ES的refresh_interval。默认是1秒意味着每秒都会生成一个新的segment写入量大时会产生大量小segment段合并压力巨大。对于知识库这种场景实时性要求没那么高把refresh_interval调到30秒甚至60秒写入吞吐能提升好几倍。3.4 RAG链路中检索结果怎么喂给大模型检索回来top-N个chunk之后不能直接一股脑塞给大模型。这里有几个坑第一上下文长度限制。大模型的context window是有限的比如32K token。如果每个chunk 512 token那最多塞60个chunk。但实际不能塞满因为还要留空间给系统prompt和用户query。一般控制在top-10到top-20之间。第二chunk排序。检索返回的结果是按相关性排序的但喂给大模型时最相关的应该放在最前面还是最后面实测下来放在最前面和最后面效果最好中间的位置容易被大模型忽略。这叫lost in the middle现象。所以可以做一个重排把最相关的几条放在开头和结尾。第三去重和压缩。检索回来的chunk之间可能有大量重复内容直接喂给大模型会浪费context window。可以做一层去重或者用一个小模型对chunk做压缩只保留和query最相关的句子。第四引用标注。生成答案时要让大模型标注每个结论来自哪个chunk这样用户能溯源。实现方式是在prompt里给每个chunk编号要求大模型在生成时带上编号引用。4. 常见问题与排查技巧实录4.1 检索命中率上不去怎么办这是被问得最多的问题。检索命中率低原因可能出在链路的任何一个环节。我的排查顺序是先看query本身。用户的query是不是太短比如只输入报销两个字这种query的语义信息太少embedding出来的向量区分度很低。解决办法是做query改写用大模型把短query扩展成完整的问句再做检索。再看embedding模型。你用的embedding模型是不是适合中文是不是适合你的领域通用embedding模型在专业领域比如医疗、法律的表现可能很差。解决办法是用领域数据做微调或者换一个在该领域表现更好的模型。然后看chunk质量。随机抽几个检索失败的case看看对应的chunk内容是不是完整、是不是包含了答案。如果chunk本身就不包含答案那检索算法再牛也没用。最后看融合策略。向量检索和全文检索的权重是不是合理RRF的k值是不是合适这些参数需要根据实际数据调优。4.2 向量检索的召回率怎么评估很多人不知道怎么评估向量检索的效果。我的做法是构建一个评测集人工标注100到200个query每个query标注哪些文档是相关的。然后计算RecallK和MRRMean Reciprocal Rank。RecallK衡量的是top-K结果里包含多少相关文档MRR衡量的是第一个相关文档出现的位置。这两个指标结合起来能比较全面地反映检索质量。评测集的建设是个体力活但非常值得。没有评测集所有的优化都是盲调。我见过团队花了几个月调参数结果因为没有评测集根本不知道有没有变好。4.3 集群稳定性怎么保障千亿级集群稳定性是生命线。几个关键措施监控要全。除了ES自带的监控指标还要监控JVM的GC、磁盘IO、网络延迟。特别是GC长时间的Full GC会导致节点短暂失联触发分片重新分配引发雪崩。熔断要配。ES有circuit breaker机制当内存使用超过阈值时会拒绝请求。这个阈值要合理设置太小会导致正常请求被拒太大会导致OOM。降级要有。当向量检索超时或者不可用时能不能自动降级到纯全文检索这个降级逻辑要在应用层实现保证核心功能可用。压测要定期做。不要等到大促或者流量高峰才发现集群扛不住。定期做全链路压测找到瓶颈点。4.4 成本怎么控制千亿级数据成本是个绕不开的话题。几个省钱的方向冷热分离。前面提过冷数据用可搜索快照降到对象存储成本能降70%以上。向量维度压缩。用PCA或者量化技术把向量维度从1024降到256存储成本降75%召回率损失控制在5%以内。副本数调整。不是所有索引都需要多副本。冷数据索引可以设0副本靠快照恢复。实例类型选择。计算密集型的节点用高主频CPU存储密集型的节点用大容量SSD不要一刀切。5. 一些踩过的坑和实操心得5.1 关于ES版本选择ES 8.x对向量检索的支持比7.x好很多特别是kNN的性能优化。如果新项目直接上8.x。但要注意8.x默认开启了安全认证配置起来比7.x麻烦一些。另外8.x的Java API Client和7.x的RestHighLevelClient差异很大迁移成本不低。5.2 关于embedding模型的部署embedding模型推理是CPU密集型的千亿级数据下如果每次查询都实时推理延迟会很高。我的做法是query embedding实时做doc embedding离线做。离线做的时候可以用GPU批量推理速度快很多。另外embedding模型最好和ES集群部署在同一个内网减少网络延迟。5.3 关于权限过滤的性能权限过滤是在检索时做的如果权限规则很复杂会严重影响检索性能。优化方式是把权限规则预处理成位图bitmap检索时用位运算做过滤比逐条判断快几个数量级。5.4 关于RAG的评估RAG系统的评估不能只看检索指标还要看最终生成的答案质量。我一般用两个维度忠实度faithfulness和相关性relevance。忠实度衡量答案是不是基于检索到的内容生成的有没有胡编相关性衡量答案是不是回答了用户的问题。这两个维度可以用大模型做自动评估也可以人工抽检。5.5 关于Agentic RAG的演进传统的RAG是一次检索一次生成但复杂问题往往需要多轮检索。Agentic RAG的思路是让大模型自己决定什么时候检索、检索什么、要不要追问。这对检索层提出了更高要求不仅要快还要支持复杂的查询计划。ES的DSL本身就很灵活可以支持这种多轮检索的需求但需要在应用层做好编排。6. 从千亿级实践中提炼的几条硬经验做千亿级AI知识库技术选型只是起点真正的功夫在细节里。我总结几条我认为最重要的经验第一检索质量是RAG的生命线。不要指望大模型能化腐朽为神奇检索回来的内容不对大模型只会错得更离谱。把70%的精力花在检索优化上不过分。第二评测集是优化的指南针。没有评测集所有的调参都是玄学。哪怕只有100条标注数据也比没有强。第三chunk策略比检索算法更重要。我见过太多团队在检索算法上死磕却忽略了chunk切分这个上游环节。chunk切得好简单的BM25都能有不错的效果。第四成本控制要从架构设计阶段就开始。冷热分离、向量压缩、副本策略这些如果等到账单爆炸了再想就来不及了。第五稳定性是1其他都是0。千亿级集群任何一个小故障都可能被放大。监控、熔断、降级、压测一个都不能少。最后分享一个我个人的小技巧在做检索调优的时候我会把每次查询的召回结果和最终答案都记录下来定期做bad case分析。很多时候问题不是出在检索算法上而是出在数据质量上——比如某个文档的chunk切分错了导致关键信息丢失。这种问题只有通过持续的bad case分析才能发现。
返回列表