首页 / 资讯中心 / 文章详情

RAG终极实战:搞定大模型幻觉,搭建企业知识库问答系统

RAG终极实战:搞定大模型幻觉,搭建企业知识库问答系统 ★ FEATURED ARTICLE
1. 先看一个真实问题为什么大模型会一本正经地胡说八道过去大半年我一直在帮某企业做内部知识库问答系统中间踩了不少坑也把RAG从理论到落地完整走了一遍。今天想把这套东西彻底聊透包括它到底解决什么问题、怎么搭一条最小可用链路、以及那些文档里不写但你一定会遇到的细节。先说一个高频场景。你拿着一份内部刚发布的季度管理制度去问某个通用大模型“新报销流程的审批额度是多少”它可能给你一个流畅但错误的答案——因为它训练时根本没见过这份文件。更麻烦的是如果你让它基于一份PDF内容回答但它没有真正“读”PDF的能力只能靠你手动粘贴几千字进去超了上下文窗口就开始丢信息回答质量断崖式下跌。模型的回复语气越是自信错误越隐蔽这就是常说的“幻觉”。幻觉的来源其实不复杂本质是生成模型的训练目标和事实约束不一致。在预训练阶段模型学的是“给定前文预测下一个词”的概率分布它优化的是语言流畅度、语义连贯性而不是“这句话是否符合数据库里的某条记录”。所以只要一个知识点在训练语料里出现频率低、或者以互相矛盾的表述出现模型就有很大概率在“补全”时编出看起来合理的答案。而RAG解决这个问题的思路很直接在生成之前先到外部知识库里去把真实资料检索出来让模型基于证据回答而不是凭记忆编造。这也是我把这篇文章标题定为“终极方案”的原因。写这篇文章之前我专门和几个做推荐系统和问答系统的朋友确认过当下的工程实践结论高度一致生产环境里想要LLM输出可控、可溯源、知识及时更新RAG是最稳妥、最省成本的路径。它不需要重新训练模型不需要动底层权重只需要把数据管好、把检索做好。下面我会从原理到实战一步步拆开讲适合两类人一类是想给自己的产品接入大模型能力、但被幻觉问题困扰的开发者另一类是已经跑通基础RAG、想进一步优化检索质量和评估效果的工程师。2. RAG到底在“增强”什么两个痛点、两条解决路径要理解RAG为什么有效得先把它想解决的问题掰开看。大模型接入业务场景时最常碰到的两个问题分别是知识时效性和领域知识覆盖不足。2.1 知识时效性模型只活在“训练快照”里一个大模型的知识截止日期是固定的比如某个模型的知识停留在2023年初那它对2024年以后发生的事天然没有感知。你可以把模型想象成一个只读到某年某月出版物的学生你再怎么问它也答不出之后发生的事。更麻烦的是企业内部的新制度、产品的新参数、技术的新规范这些内容在互联网上压根不存在通用模型根本没机会学过。你如果硬让它回答它只能靠“常识”猜猜错了就是幻觉。解决时效性问题有两个传统思路一个是定期微调Fine-tuning把新资料混进训练集重新训练另一个是直接更换参数更大的模型。但这两个方案的成本都高得离谱——微调一次动辄几百张显卡几十小时模型上线后数据又很快过期陷入“越调越跟不上”的循环。RAG把问题从根本上换了个角度与其让模型记住所有知识不如让模型学会“查资料”。资料放在外部数据库里随时更新模型每次回答前先去查查到什么就基于什么答。知识库的更新成本就是一次数据写入几秒钟的事和重新训练完全不是一个量级。2.2 领域知识覆盖不足长尾问题才是幻觉重灾区即便模型训练数据截止到最新长尾领域知识仍然是它最薄弱的地方。通用语料里“某企业内部系统的接口文档”“某型号设备的维修手册”出现频率极低模型连见都没见过几次。当用户问到这类问题时模型只能从相似领域“迁移”一个答案出来——迁移对了是惊喜迁移错了就是幻觉。这里要强调一个经常被误解的点RAG不负责“教会”模型新知识它负责“告诉”模型答案在哪里。整个过程分为两段第一段是检索模型或系统先从外部知识库中找到与问题相关的若干片段第二段是生成大语言模型根据这些片段和原始问题组织答案。检索如果准生成不会偏到哪里去检索如果烂生成能力再强也只能在错误的上下文里“戴着镣铐跳舞”。所以后来业内普遍形成了共识RAG的上限由生成模型决定下限由检索质量决定。而在实际工程项目里大家花时间最多的往往不是调大模型而是调检索链路——怎么切文档、怎么算向量、怎么排序、怎么过滤噪声。2.3 为什么要从“记忆模式”切换成“考试带资料模式”我习惯把LLM的两种使用方式比喻成两种考试直接回答问题是“闭卷考试”模型只能靠脑子里记的东西RAG是“开卷考试”模型可以翻资料。闭卷考的是记忆力开卷考的是理解力和信息组织能力。对于知识密集型的业务场景——客服问答、法律条文检索、技术文档问答——开卷几乎总是更靠谱。有朋友问过我“那我直接给模型塞一个超大上下文把几千页文档都拼进去是不是就不用RAG了”理论上可以但实际工程上很难。第一上下文窗口再大也有限几千页文档超窗口只是时间问题第二生成模型对超长上下文里远距离的信息关注度会衰减找起来也容易漏第三每轮请求都带上全部文档令牌消耗极高成本受不了。RAG的核心价值就是通过“先检索缩小范围”让模型每次都只读和当前问题最相关的几百上千字既省窗口、又提准确率。3. 一条最小可用的RAG流水线从文档入库到答案生成聊完原理直接上干货。我用当前社区里最流行的开源组件搭了一条完整流水线在本地机器上就能跑通。整个过程分四步文档加载与清洗、切片与向量化、检索召回、生成回答。3.1 技术选型为什么是这四个组件先说我用的组合文档加载和拆分用LangChain或LlamaIndex两者选一向量化Embedding模型我用的是开源模型如BGE系列或M3E本地部署不走API方便反复实验向量存储Chroma或FAISS都是轻量级方案社区资料多生成模型Qwen或DeepSeek的本地版本也可以接云厂商API取决于你的算力和成本预算这套组合的好处是每个环节都可替换。RAG是一条流水线任何一环坏了都可以单独换不必推倒重来。如果你用到的文档是PDF需要加一层PDF解析如果是网页需要加爬虫和清洗。选型时不必追求“最强”而应该追求“好排查”——因为接下来你一定会遇到各种问题每个环节能否单独验证决定了排错效率。3.2 核心代码跑通全流程下面是我在模拟项目X一个企业内部文档问答系统里跑通的第一版代码。为了演示我简化了部分细节但主干逻辑完整。# rag_basic_pipeline.py # 依赖pip install langchain langchain-community chromadb sentence-transformers from langchain_community.document_loaders import TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.embeddings import HuggingFaceEmbeddings from langchain_community.vectorstores import Chroma from langchain_community.llms import Ollama from langchain.chains import RetrievalQA # 第1步加载文档 loader TextLoader(knowledge_base.txt, encodingutf-8) documents loader.load() print(f加载完成共 {len(documents)} 个文档对象) # 第2步切分文档 text_splitter RecursiveCharacterTextSplitter( chunk_size512, # 每块最大字符数 chunk_overlap64, # 相邻块的重叠字符数 separators[\n\n, \n, 。, , , , ] ) chunks text_splitter.split_documents(documents) print(f切分完成共 {len(chunks)} 个文本块) # 第3步向量化并写入向量库 embeddings HuggingFaceEmbeddings(model_nameBAAI/bge-small-zh-v1.5) vectorstore Chroma.from_documents( documentschunks, embeddingembeddings, persist_directory./chroma_db ) print(向量库写入完成) # 第4步构建检索问答链 llm Ollama(modelqwen2.5:7b, temperature0.1) qa_chain RetrievalQA.from_chain_type( llmllm, retrievervectorstore.as_retriever(search_kwargs{k: 4}), return_source_documentsTrue ) # 第5步提问并打印答案与来源 query 新报销流程的审批额度是多少 result qa_chain.invoke({query: query}) print(答案:, result[result]) print(参考来源:) for i, doc in enumerate(result[source_documents]): print(f--- 片段{i1} ---) print(doc.page_content[:200])这段代码跑通之后你已经有了一个“能回答”的系统。但我要泼一盆冷水能回答和答得对是两回事。第一版系统大概率会在几个地方翻车——分块切坏了语义、检索召回了不相关内容、模型没严格按照资料回答。接下来的几个部分就是把这三块逐个抠精的过程。3.3 为什么第一版一定会“看起来能用、用起来飘”我自己的经历是第一版demo给同事演示时问了好几个业务问题它能答上来而且引用了我放在知识库里的原文片段看起来很厉害。但换一个稍偏门的问题它就答错了而且答错时依然自信满满。事后复盘问题出在三个地方一是文档切分时一个完整表格被切成了两半检索只召回了表头那一半模型只能瞎猜数值二是embedding模型是通用领域预训练的对内部业务术语的语义区分度不够“审批额度”和“审批流程”在向量空间里被模型当成相近内容召回了错误的片段三是生成阶段prompt里没有强调“只能依据给定资料回答”导致模型在资料不足时“发挥想象力”。这三个问题恰好覆盖了RAG链路里的检索、召回、生成三个环节我后面会逐一展开。4. 分块策略与Embedding模型选型检索质量的下限由它们决定如果说生成模型是RAG的天花板那分块Chunking和向量化Embedding就是RAG的地基。地基打不牢后面的重排序、调prompt都是白费劲。4.1 分块为什么这么重要语义完整性和粒度之间的平衡文档切分看起来是最没技术含量的一步实际却是最容易翻车的一步。切多了——比如把整个段落硬切成512字符的碎片——一个完整的意思被拦腰截断检索到的片段可能只有半句话模型根本读不出上下文。切少了——比如把几个完全不同主题的段落粘成一个大块——检索召回了这个块但真正相关的只有其中一句话模型还得从噪声里淘金。以我做的模拟项目X为例最初的配置是固定512字符切块overlap设了0结果检索到的问题片段经常是“该流程需要经过”这样没头没尾的内容。后来我改成按语义边界递归切分也就是先按段落符号换行、句号、分号切再对超出长度的大段落做二次细分配合64字符的overlap召回完整度明显改善。分块参数的选择没有绝对标准但有两条经验可以参考块大小中文场景下建议256到512字符之间。太短语义承载不够太长向量表示的语义容易被稀释且生成阶段占用上下文窗口过大。如果文档本身结构清晰如制度条款可以按条款切不做字数限制再对超长条款二次切分。Overlap中文场景建议设为块大小的10%到15%。Overlap的作用是保留边界处的上下文连贯性防止一个完整句子被切成两半后前后块各不知道上下文。另一个经验是如果你的知识文档本身有结构目录、章节、表格优先按结构切而不是按字数切。结构本身就是最好的语义边界。4.2 Embedding模型选型开源还是API维度怎么选Embedding模型负责把文本变成向量。它的质量直接决定“语义相近”的判断准不准。这一块有几个关键判断第一选中文效果好的开源模型。中文场景不要直接拿英文的通用Embedding模型硬套中文语义理解和英文差异很大。实测下来BGE系列如bge-small-zh、bge-large-zh在中文检索里性价比很高M3E针对中文场景做了专门优化。如果预算充足、追求上限还可以对比OpenAI的text-embedding-3-small但注意API调用有成本和数据出境问题。第二向量维度不是越高越好。维度高意味着对语义的刻画更精细但同时检索耗时和存储开销上涨。我的经验是中等规模知识库几十万片段以下用中小模型完全够只要检索top_k能召回正确答案维度精度带来的差异没那么明显。第三Embedding模型的“领域适配”问题。通用Embedding模型对“财务”“报销”“审批”这类词有一定理解但对你的业务里特殊缩写、内部黑话效果就不好。比如某企业内部叫“BPM流程”通用模型可能把它当作一个普通英文缩写来处理。遇到这种情况有两个解决手段一是对文档做同义词扩充把业务缩写和全称、俗称写进同一条文档里二是对Embedding模型做领域微调。后者的成本高一些一般知识库项目先用前者扛住即可。4.3 分块和Embedding的联动一个容易被忽略的组合拳分块策略和Embedding模型是配合关系不是孤立的两件事。不同Embedding模型对小块文本和大块文本的表示能力不同。有的模型在512字符内表现优秀超过512就退化明显有的模型因为训练时见过超长句子对长文本也能保持语义稳定。所以当你调整chunk_size时一定要同步回测Embedding模型的效果不能只调一个变量。我实测过的一个场景用M3E模型在chunk_size256时检索准确率92%chunk_size1024时准确率掉到83%换成另一个模型chunk_size1024时反而更好。这说明没有万能参数组合必须在你的数据集上做小规模回归测试。5. 检索策略的硬核调参top_k、混合检索与重排序RAG链路里检索策略是最值得花时间的部分。同样的知识库、同样的生成模型检索策略不同答案质量可能天差地别。这一节我用自己的实测数据说话。5.1 top_k怎么选不是越大越好top_k决定了每次回答最多引用几个知识片段。k值太小可能漏掉正确答案k值太大无关噪声混进去模型容易被带偏。我的建议分场景事实型问答查额度、查日期、查参数top_k3到5即可答案通常集中在某个文档的某一段综述型问答总结某个制度的要点、归纳某类问题的处理流程top_k可以调到6到8让模型看到更多相关片段再做归纳开放型问答“给我几个优化建议”top_k看资料丰富程度通常5到10。最重要的一点top_k和分块大小是联动关系。如果你的块切得细比如256字符top_k5相当于给模型看约1280字符的上下文如果块切得粗比如1024字符top_k5给模型看约5120字符。不要在调整top_k时忘记换算实际注入生成模型的上下文量。5.2 混合检索向量检索不是万能药纯向量检索有一个典型短板对专有名词和精确匹配不敏感。比如用户搜索“CVE-2024-1234”这样一个漏洞编号向量会把“编号”理解成语义相近的内容召回一堆其他漏洞而传统的关键词检索BM25能精确命中编号。反过来用户搜索“报销流程怎么走”关键词检索对同义表达无能为力向量检索却能理解语义。所以生产环境里我更推荐混合检索向量检索和BM25并行跑各自召回一批候选再合并去重。LangChain里用EnsembleRetriever就能实现。# 混合检索示例向量检索 BM25 from langchain.retrievers import EnsembleRetriever from langchain_community.retrievers import BM25Retriever bm25_retriever BM25Retriever.from_documents(chunks) bm25_retriever.k 3 vector_retriever vectorstore.as_retriever(search_kwargs{k: 3}) ensemble_retriever EnsembleRetriever( retrievers[bm25_retriever, vector_retriever], weights[0.3, 0.7] # 权重可以根据验证集调优 ) qa_chain RetrievalQA.from_chain_type( llmllm, retrieverensemble_retriever, return_source_documentsTrue )混合检索实测下来对“含编号、含专业术语”的问题召回准确率能提升15到25个百分点。代价是多一层检索耗时和排序逻辑但对生产系统来说完全值得。5.3 重排序Rerank最后一公里的质量保障混合检索把两类候选拉到一起之后排序质量不一定好。向量检索返回的相关性分数和BM25的分数不在同一尺度上直接合并排序会不公。这里就需要重排序模型把候选片段和原始问题一起交给一个交叉编码器重新计算相关性得到更准确的排序。我用的方案是BGE-reranker系列模型用法很简单from sentence_transformers import CrossEncoder reranker CrossEncoder(BAAI/bge-reranker-base) def rerank(query, candidates, top_n3): pairs [[query, doc.page_content] for doc in candidates] scores reranker.predict(pairs) ranked sorted(zip(candidates, scores), keylambda x: x[1], reverseTrue) return [doc for doc, _ in ranked[:top_n]] # 用法先拿ensemble_retriever召回10个候选再用reranker选前3 candidates ensemble_retriever.invoke(query) final_docs rerank(query, candidates, top_n3)重排序的收益在知识库内容相似度高时尤其明显。比如制度文档里十几条都提到“报销”但只有一条提到“事业部审批”向量检索可能把“报销”相关的片段排在最前面而正确的那条排在第五、第六位。没有重排序top_k4就会错过正确答案有了重排序正确片段被拉到前三位答案质量直接改善。5.4 检索相关性阈值宁可说“不知道”也不要硬答RAG里有一条重要哲学不是所有问题都强制回答。当检索结果的相关性分数普遍很低时说明知识库里很可能没有这个问题的答案。这时候与其让模型硬编不如让它明确说“根据现有资料我无法回答这个问题”。实现方式对重排序后的最高分设一个阈值比如0.5低于阈值就不进入生成环节直接返回兜底话术。阈值怎么定在验证集上跑一遍统计“正确答案被跳过”和“错误答案被放行”的分数分布取两者谷值。我在模拟项目X里把阈值设为0.45后大幅降低了“强答”带来的负面体验虽然回答覆盖率略有下降但用户反馈的信任感提升明显。5.5 实测对比同一问题三种检索策略的效果差异我在模拟项目X里用同一批测试问题跑了一组对比结果很有代表性检索策略top_k4 准确率响应耗时问题类型覆盖纯向量检索78%0.6s语义近似好精确匹配差纯BM2571%0.4s精确匹配好同义表达差混合检索86%0.8s两类问题都能覆盖混合检索重排序91%1.1s排序精度明显提升这组数据说明重排序增加约0.3秒耗时但准确率提升5个百分点性价比极高。如果对延迟特别敏感可以考虑对重排序输入做预筛选比如只对top_k10的候选做重排序而不是对所有候选这样能把耗时控制在可接受范围内。6. 用RAGAS做量化评估别再用“肉眼感觉”判断效果很多项目组评估RAG效果靠的是“问几个问题用人眼判断答得好不好”。这种评估方式有两个致命问题一是主观性强换个测试人结论就变了二是无法定位问题环节——答得不好到底是检索没召回还是生成没用好这一节我讲怎么用RAGAS框架做系统化评估。6.1 RAG的四个核心指标从“答得好”到“链路每个环节都好”RAGAS是目前社区里最常用的RAG评估框架它提供四个关键指标忠实度Faithfulness生成的答案是否严格基于检索到的上下文有没有出现“资料里没有的内容”。这是衡量幻觉的核心指标。答案相关性Answer Relevancy生成的答案是否切题有没有答非所问。它会同时检查答案内容本身和答案的完整性。上下文相关性Context Relevancy检索到的片段和问题的相关程度。这个指标高说明检索环节没问题低说明召回阶段出问题了。上下文精确度Context Precision检索结果里相关片段是不是排在前面。如果正确答案排在第五位而top_k只取了3位就是精确度不够需要调整排序或重排序。这四个指标把RAG链路拆成了两段前两个指标评估“生成端”后两个指标评估“检索端”。当整体效果不好时先看后两个指标定位检索再看前两个指标定位生成。6.2 快速上手在测数据集上跑RAGAS评估测试数据集不需要太大我的习惯是准备50到100条问题覆盖正常问答、边缘问答、无答案问答三类。RAGAS评估的代码大概长这样# ragas_eval.py from ragas.metrics import ( faithfulness, answer_relevancy, context_relevancy, context_precision ) from ragas.llms import LangchainLLMWrapper from langchain_community.llms import Ollama from datasets import Dataset # 准备测试集questions是问题answers是系统答案contexts是检索到的片段 eval_dataset Dataset.from_dict({ question: questions, answer: answers, contexts: contexts, }) llm LangchainLLMWrapper(Ollama(modelqwen2.5:7b, temperature0)) result evaluate( eval_dataset, metrics[faithfulness, answer_relevancy, context_relevancy, context_precision], llmllm ) df result.to_pandas() print(df[[question, faithfulness, answer_relevancy, context_relevancy, context_precision]].mean())有一点要提醒RAGAS在计算这些指标时本身也要调用一个LLM来做判断所以你的评估LLM的质量会影响指标可靠度。建议用强一点的模型做评估判官。6.3 指标怎么解读什么算“合格”以我的经验首次跑通RAG时各项指标大概在0.5到0.7之间不必太慌。逐步优化后目标可以定在忠实度≥0.9幻觉问题基本消除答案相关性≥0.8上下文相关性≥0.85上下文精确度≥0.75。如果忠实度一直上不去优先检查prompt里有没有明确“只能基于给定资料回答”如果上下文相关性低回头调分块和Embedding如果上下文精确度低上重排序。这个评估体系最大的价值是让你在迭代优化时有数据支撑而不是“拍脑袋”。比如你改了分块参数跑一遍RAGAS看上下文相关性有没有变好改了prompt看忠实度有没有提升。每次改动都能量化项目汇报时也更有底气。7. 三类高发问题与完整排查链路查不全、查不准、答不对就算你把基础链路搭好了、评估体系建起来了生产环境里依然会遇到各种幺蛾子。这一节把我实际踩过的坑归类成三类每一类给出根因定位和解决思路。7.1 查不全知识库里有正确答案但检索没召回症状答案答非所问或者直接说“知识库里没有该内容”但你自己去向量库检索明明能查到相关文档。根因大概率是分块或Embedding的问题。常见细分原因有三种文档里相关内容和用户问题的表达差异太大。比如文档写“差旅费补贴标准”用户问“出差一天补助多少钱”。语义上有重叠但句子结构差异大embedding可能算不出足够高的相似度。解决对文档做同义扩充把口语化表达、缩写、俗称都补进文档里。分块把那块内容切碎了。一个完整定义被切到两个块里检索时只命中了一半。解决检查chunk边界调整分割符或减小chunk_size。Embedding模型本身对该领域语义理解弱。解决换专业领域的Embedding模型或者做领域微调。排查思路先手动取用户问题去向量库里做一次相似度搜索看看相关文档排在第几位。如果排在十几名开外说明是语义匹配弱如果排在第一位但内容不完整说明是切块问题。7.2 查不准检索回来了但答案被无关内容带偏症状答案里夹杂了明显不正确的内容或者引用了不相干的资料。打开source_documents一看检索结果里混入了大量噪声。根因知识库里相似内容太多且彼此之间存在细微差异。比如制度文档里“请假审批流程”“采购审批流程”“报销审批流程”都是同一套模板只在个别字段不同。向量检索容易把三类流程都当成“相关”模型面对多份小差异片段时可能挑错信息。解决思路按优先级排列加混合检索和重排序让精确相关的片段排在前面调整top_k减少噪声输入从5降到3优化分块策略确保同一流程的内容集中在同一块内而不是被切散在prompt里明确“如果资料之间冲突以时间最近的资料为准”或“优先采用被引用次数最多的内容”。7.3 答不对检索没问题但生成阶段没用好资料症状context_relevancy指标很高结果也正确但最终答案就是不好——要么长篇大论答非所问要么丢了解答核心的关键句。根因生成模型的prompt约束不够或者模型本身能力不足以从多个片段中提取整合信息。排查方式把检索到的片段和系统最终答案投喂给一个更强的模型比如云端的大参数量模型让它判断“这段上下文里包含答案吗为什么没答出来”如果强模型能答对说明你的生成模型能力需要升级或者在prompt里要提供更明确的“答案组织模板”。我在模拟项目X里遇到过一例知识库里明确写了“5000元以上需分管领导审批”模型答成了“5000元以下由部门经理审批”——也就是说资料对但模型读反了。这就是典型的生成阶段理解偏差。解决手段有两个一是换一个更强的生成模型二是把prompt改得更细——“严格依据资料不要自行推断特别关注金额和审批层级等具体数值”。实测发现这类问题换成更强模型后基本消失。7.4 完整排查链路先把“检索”和“生成”解耦排查RAG问题最重要的一步是解耦。很多人一上来就调prompt结果改半天没有用因为问题根本在检索环节。我总结了一个排查顺序先把检索结果单独拉出来看——查出来的片段和问题相关吗如果片段本身不相关问题在检索端去做分块和Embedding优化如果片段相关但答案不对问题在生成端去调prompt和模型参数。如果片段相关但“相关得很勉强”比如关键信息缺失了一半问题可能在分块切割上回去看chunk边界。这个链路走一遍花不了十分钟但能精准定位80%的问题方向。我从这套方法里最大的收获是别让模型背黑锅之前先确认它手里有没有正确资料。8. 一些从实战里沉淀下来的优化细节最后分享几个我在多次迭代里总结的经验不一定能写进教程但实战中很管用。第一知识库的去重比想象中重要。我最初实验时同一份制度文档被上传了三个版本内容有细微差别。结果检索时三个版本都命中了模型整合时把新旧版本混在一起给出了自相矛盾的答案。后来我加了sha256指纹去重并对同一文档的多版本按修改时间做优先级问题立刻缓解。第二温度参数别调太高。生成阶段我把temperature设在0.1到0.2之间这能显著提高忠实度因为模型在低温度下更倾向于“照抄”资料里的原文。如果你的业务允许一点发散性比如营销文案再考虑调高。第三文档更新后要重建索引而且要先删后建。有一次我直接往向量库里追加新文档结果旧版本和新版本同时存在检索结果里出现冲突内容。后来我改成“按文档ID先删除旧向量再写入新向量”并在写入后重新跑一遍小批量回归测试确认检索质量没有回退。第四日志记录检索结果。每一轮问答把检索到的片段ID、相关性分数、重排序结果、最终答案都打日志。这样出了问题能回放整个链路。我曾经靠一份日志花了十分钟定位到某个Pad上的文档解析器把表格读成了乱码这是任何测试集都发现不了的问题。第五评估集要持续积累。上线后把用户实际问到的、系统答错的问题沉淀下来每周补充进测试集。随着测试集越来越贴近真实场景RAGAS指标的说服力才会越来越强。
阅读完成 · 觉得有帮助?
咨询建站