最近在做一个内部AI编程助手,想用RAG把团队私有API文档接进去。文档是Markdown格式,有几十个模块,我按目录切块后embedding,用的bge-m3,存到Milvus。但实际提问时,比如问“怎么用XXX服务做流式调用”,召回的top5经常是无关的FAQ或者旧版本说明,把正确的那段反而排在后面。我试过调chunk_size和overlap,也加了HyDE,效果还是不稳定。是不是我预处理太粗暴了?还是说应该先用LLM生成摘要再存?有没有做过类似场景的老哥给点思路?现在处于一种能跑但不敢用的状态,挺焦虑的。
用RAG给AI编程工具加私有API文档,检索效果总是不理想怎么办?
全部回复
共 124 条我之前也遇到过类似问题,后来换了方案。
你这个问题我踩过类似的坑,按目录切块对API文档来说其实挺致命的,因为一个接口的说明经常横跨参数表、示例代码和注意事项,切完就散了,检索时自然拼不出完整语义。我建议你先别急着换模型,把切块逻辑改成按标题层级走,每个chunk带上模块名和接口名的上下文前缀再embedding,召回质量会明显不一样。另外top5里混进旧版本说明,很可能是元数据没做过滤,文档存的时候带上版本号和状态字段,检索时先筛掉废弃的。HyDE对API这种精确查询其实帮助有限,反而容易把语义带偏,你可以试试换成query改写,让LLM把“怎么流式调用”扩成具体的接口名和参数术语再检索。还有个思路是混合检索,bge-m3的稀疏向量那路别浪费,关键词匹配对接口名特别管用,跟稠密向量做融合排序。生成摘要再存我不太推荐,摘要会丢参数细节,API文档恰恰最吃细节,不如老老实实做好父子块,小块检索大块喂给模型。
你这个问题我太有共鸣了,我们团队之前做内部知识库检索也是这个状态,能跑但不敢用。感觉你卡住的地方可能不在chunk_size,而是切块的时候把语义结构切碎了,Markdown里的标题层级其实是很强的信号,按目录切完最好把父级标题和模块名拼进每个chunk里再embedding,不然“流式调用”这种词在多个模块里都出现,模型根本分不清是哪个服务的。另外旧版本说明和FAQ被排前面,很可能是它们表述更口语化、跟query的词汇重合度更高,你可以给文档加个版本或时效的metadata,检索时做个过滤或者加权,别让旧内容混进候选池。HyDE不是万能药,它更适合query太短的情况,你这个问法已经挺具体了,反而可能被它带偏。至于先让LLM生成摘要再存,我觉得要看情况,摘要会丢参数名和代码片段这类关键细节,编程场景里恰恰是这些细节最要命,不如保留原文但额外存一份“这段是讲什么的”短描述做双路召回。还有个容易忽略的点,top5里无关内容多,可以试试加个轻量的rerank模型过一遍,bge的reranker对中文技术文档效果还行,成本也不高。你们文档量几十个模块其实不算大,实在不行把模块名和接口名做成一个关键词索引做混合检索,纯向量在专有名词上确实容易翻车。
按模块+版本打标签过滤,再对API段落单独做小chunk,FAQ别混进去。