目录RAG 工程的全流程一、知识的预处理1、为知识切片预生成问题Query-Answer 对齐2、对话知识沉淀让系统越用越聪明3、知识库健康度审查定期体检4、知识库版本管理把知识当产品迭代二、高效召回1、多查询召回2、索引扩展3、Rerank模型使用1BGE-Rerank2Cohere Rerank4、双向改写Query2Doc和Doc2Query5、Small to big策略RAG 工程的全流程很多人谈 RAG想到的第一个画面是向量数据库 大模型。但如果把 RAG 当作一个工程拆开看它至少包含以下环节阶段环节说明来源① 知识接入与解析文档解析PDF/网页/表格/OCR、清洗、格式统一原始数据往往很杂解析质量决定后续一切文档预处理:RAG多模态知识库② 知识切片Chunking按固定长度 / 语义边界 / 文档结构切块切片策略是检索质量的最高杠杆切片策略RAG搭建本地知识库③ 知识存储IndexEmbedding 向量化 → 写入向量数据库FAISS / ES / Milvus 等相当于给知识建索引目的是高效检索Embedding模型和向量数据库的选择④ 知识预处理预生成问题、打标签、生成摘要、健康度审查、版本管理、权限标签一次性投入持续受益 本文档重点⑤ 查询理解与改写Query Rewrite、多轮对话上下文补全用户的问题未必是好问题提示词的改写如何与大模型交互从提示词工程到RAG⑥ 检索Retrieve向量检索 关键词检索Hybrid 混合检索、BM25、元数据过滤生产级系统的标配 本文档⑦ 重排序RerankCross-Encoder 对候选集精排把对的证据排到最前 本文档⑧ 上下文组装版本过滤、去重、token 预算裁剪、Small-to-Big检索之后、生成之前的最后一道关 本文档⑨ 生成Generatechunk 用户问题 → LLM 生成回答有了背景知识回答才不会幻觉⑩ 评估与运营召回率/准确率评测、可观测性、对话知识沉淀、版本迭代、免责声明RAG 是持续运营的产品不是一锤子买卖 本文档在企业落地的真实场景中80%~90% 的 case 用 Native RAG原生 RAGRAG的工作流程与目标就能解决——即切片 → 向量化 → 检索 → 生成这条朴素的主链路。但如果想让系统从能跑走向好用从一次性项目走向持续运营的产品就必须把上面这十个环节当作一个整体工程来对待。部分内容我们已经写了我把文档的链接贴出来了。还有部分高级内容我将在本文介绍。一、知识的预处理1、为知识切片预生成问题Query-Answer 对齐我们的问题一般是疑问句而知识切片一般是陈述句。那么问题和知识转化成向量后在表达方向上有可能不完全一致导致用户问题和知识切片的相似度不是很高。我们可以为通过AI为知识切片生成一些可能性的问题然后将问题和问题之间来做个匹配以此来提高用户问题和知识切片的匹配度。思路让大模型扮演问答专家对每个知识切片预生成若干用户可能提问的问题检索时做问题与问题的匹配而非问题与陈述句的匹配。成本账预处理是一次性成本相当于给知识加外挂标签不需要随每次查询重复付费。建议用代码而非对话式工具来做——提示词固定后直接批量运行更省 token。def get_completion(prompt, modelqwen3.7-plus): messages [{role: user, content: prompt}] response client.chat.completions.create( modelmodel, messagesmessages, temperature0.7, ) return response.choices[0].message.content ....... def generate_questions_for_chunk(self, knowledge_chunk, num_questions5): 为单个知识切片生成多样化问题 instruction 你是一个专业的问答系统专家。给定的知识内容能回答哪些多样化的问题这些问题可以 1. 使用不同的问法直接问、间接问、对比问等 2. 避免重复和相似的问题 3. 确保问题不超出知识内容范围 请返回JSON格式 { questions: [ { question: 问题内容, question_type: 问题类型直接问/间接问/对比问/条件问等, difficulty: 难度等级简单/中等/困难 } ] } prompt f ### 指令 ### {instruction} ### 知识内容 ### {knowledge_chunk} ### 生成问题数量 ### {num_questions} ### 生成结果 ### response get_completion(prompt, self.model) # 预处理响应移除markdown代码块格式 response preprocess_json_response(response) try: result json.loads(response) return result.get(questions, []) except json.JSONDecodeError as e: print(fJSON解析失败: {e}) print(fAI返回内容: {response[:50]}...) # 如果JSON解析失败返回简单的问题列表 return [{question: f关于{knowledge_chunk[:50]}...的问题, question_type: 直接问, keywords: [], difficulty: 中等}]测试及结果要是想生成更多样化的问题修改提示词就可以了如instruction 你是一个专业的问答系统专家。请为给定的知识内容生成高度多样化的问题确保 1. 问题类型多样化直接问、间接问、对比问、条件问、假设问、推理问等 2. 表达方式多样化使用不同的句式、词汇、语气 3. 难度层次多样化简单、中等、困难的问题都要有 4. 角度多样化从不同角度和维度提问 5. 确保问题不超出知识内容范围 请返回JSON格式 { questions: [ { question: 问题内容, question_type: 问题类型, difficulty: 难度等级, perspective: 提问角度, is_answerable: 给出的知识能否回答该问题, answer: 基于该知识的回答 } ] } 2、对话知识沉淀让系统越用越聪明系统上线后会有大量的用户对话这些对话是非常有价值的把这些用户对话收集起来提取对话中用户反馈的问题表达的不满提出的新需求整理出来作为系统的下一次的迭代方向。核心• 使用AI模型从对话中提取结构化知识• 支持多种知识类型事实、问题、流程、注意事项等• 自动识别用户意图和对话摘要def extract_knowledge_from_conversation(self, conversation): 从单次对话中提取知识 instruction 你是一个专业的知识提取专家。请从给定的对话中提取有价值的知识点包括 1. 事实性信息地点、时间、价格、规则等 2. 用户需求和偏好 3. 常见问题和解答 4. 操作流程和步骤 5. 注意事项和提醒 请返回JSON格式 { extracted_knowledge: [ { knowledge_type: 知识类型事实/需求/问题/流程/注意, content: 知识内容, confidence: 置信度(0-1), source: 来源用户/AI/对话, keywords: [关键词1, 关键词2], category: 分类 } ], conversation_summary: 对话摘要, user_intent: 用户意图 } prompt f ### 指令 ### {instruction} ### 对话内容 ### {conversation} ### 提取结果 ### response get_completion(prompt, self.model) # 预处理响应移除markdown代码块格式 response preprocess_json_response(response) try: result json.loads(response) return result except json.JSONDecodeError as e: print(f对话知识提取JSON解析失败: {e}) print(fAI返回内容: {response[:200]}...) return { extracted_knowledge: [], conversation_summary: 无法解析对话, user_intent: 未知 }测试批量提取知识则上for循环def batch_extract_knowledge(self, conversations): 批量提取知识 all_knowledge [] for i, conversation in enumerate(conversations): print(f正在处理对话 {i1}/{len(conversations)}...) result self.extract_knowledge_from_conversation(conversation) all_knowledge.extend(result.get(extracted_knowledge, [])) # 更新频率统计 for knowledge in result.get(extracted_knowledge, []): key f{knowledge[knowledge_type]}:{knowledge[content][:50]} self.knowledge_frequency[key] 1 return all_knowledge知识合并按照类型把问题分类knowledge_by_type然后再用大模型扮演知识整理专家去重合并merge_knowledge_with_llmdef merge_similar_knowledge(self, knowledge_list): 使用LLM合并相似的知识点过滤掉需求和问题类型 # 过滤掉需求和问题类型的知识因为它们是临时的、个性化的 filtered_knowledge [ knowledge for knowledge in knowledge_list if knowledge.get(knowledge_type) not in [需求, 问题] ] print(f过滤前知识点数量: {len(knowledge_list)}) print(f过滤后知识点数量: {len(filtered_knowledge)}) print(f过滤掉的需求和问题类型知识点: {len(knowledge_list) - len(filtered_knowledge)}) # 按知识类型分组 knowledge_by_type {} for knowledge in filtered_knowledge: knowledge_type knowledge.get(knowledge_type, 其他) if knowledge_type not in knowledge_by_type: knowledge_by_type[knowledge_type] [] knowledge_by_type[knowledge_type].append(knowledge) merged_knowledge [] # 对每个知识类型分别进行LLM合并 for knowledge_type, knowledge_group in knowledge_by_type.items(): if len(knowledge_group) 1: # 只有一个知识点直接添加 merged_knowledge.append(knowledge_group[0]) else: # 多个知识点使用LLM合并 merged self.merge_knowledge_with_llm(knowledge_group, knowledge_type) merged_knowledge.append(merged) return merged_knowledgedef merge_knowledge_with_llm(self, knowledge_group, knowledge_type): 使用LLM合并同类型的知识组 # 准备知识内容列表 knowledge_contents [] all_keywords set() all_sources [] for i, knowledge in enumerate(knowledge_group, 1): content knowledge.get(content, ) confidence knowledge.get(confidence, 0.5) keywords knowledge.get(keywords, []) source knowledge.get(source, ) category knowledge.get(category, ) knowledge_contents.append(f{i}. 内容: {content}) knowledge_contents.append(f 置信度: {confidence}) knowledge_contents.append(f 分类: {category}) knowledge_contents.append(f 来源: {source}) knowledge_contents.append(f 关键词: {, .join(keywords)}) knowledge_contents.append() # 构建LLM合并提示 prompt f 你是一个专业的知识整理专家。请将以下{knowledge_type}类型的知识点进行智能合并生成一个更完整、准确的知识点。 ### 合并要求 1. 保留所有重要信息避免信息丢失 2. 消除重复内容整合相似表述 3. 提高内容的准确性和完整性 4. 保持逻辑清晰结构合理 5. 合并后的置信度取所有知识点中的最高值 ### 待合并的知识点 {chr(10).join(knowledge_contents)} ### 请返回JSON格式 {{ knowledge_type: {knowledge_type}, content: 合并后的知识内容, confidence: 最高置信度值, keywords: [合并后的关键词列表], category: 合并后的分类, sources: [所有来源], frequency: {len(knowledge_group)} }} ### 合并结果 response get_completion(prompt, self.model) # 预处理响应 response preprocess_json_response(response) try: result json.loads(response) return result except json.JSONDecodeError as e: print(f知识合并JSON解析失败: {e}) print(fAI返回内容: {response[:200]}...)关键技巧——置信度Confidence复杂任务不要让 AI直接干活要让它自我打分0~100。经验法则≥90 分可基本信任80~85 分说明方向对但不完整不能直接入库70 分以下要人工重点复核。类比考试估分 95 说明有把握估分 80 说明答案有欠缺。这个技巧可迁移到所有让 AI 做复杂决策的场景——比如让 AI 写代码时给出 A/B/C 多个方案并各自打分95 分的方案直接采纳70 分的推荐方案也要再调研。打分让人从逐条审查中解放出来只处理低分样本。测试3、知识库健康度审查定期体检知识库上线后不是一劳永逸的。需要定期对整个知识库进行健康度检查找出缺少的知识、过期的知识、冲突的知识确保知识库的质量和可靠性。核心内容• 完整性检查评估知识库是否覆盖用户的主要查询需求• 时效性检查识别过期或需要更新的知识内容• 一致性检查发现知识库中的冲突和矛盾信息• 综合评分提供量化的健康度评分和改进建议前三个检查都是让大模型来扮演相应的角色# 检查缺少的知识---------------------------------------- instruction 你是一个知识库完整性检查专家。请分析给定的测试查询和知识库内容判断知识库中是否缺少相关的知识。 检查标准 1. 查询是否能在知识库中找到相关答案 2. 知识是否完整、准确 3. 是否覆盖了用户的主要需求 4. 是否存在知识空白 请返回JSON格式 { missing_knowledge: [ { query: 测试查询, missing_aspect: 缺少的知识方面, importance: 重要性高/中/低, suggested_content: 建议的知识内容, category: 知识分类 } ], coverage_score: 覆盖率评分(0-1), completeness_analysis: 完整性分析 } # 检查过期的知识---------------------------------------- instruction 你是一个知识时效性检查专家。请分析给定的知识内容判断是否存在过期或需要更新的信息。 检查标准 1. 时间相关信息是否过期年份、日期、时间范围 2. 价格信息是否最新价格、费用、票价等 3. 政策规则是否更新政策、规定、规则等 4. 活动信息是否有效活动、节日、特殊安排等 5. 联系方式是否准确电话、地址、网址等 6. 技术信息是否过时版本、技术标准等 请返回JSON格式 { outdated_knowledge: [ { chunk_id: 知识切片ID, content: 知识内容, outdated_aspect: 过期方面, severity: 严重程度高/中/低, suggested_update: 建议更新内容, last_verified: 最后验证时间 } ], freshness_score: 新鲜度评分(0-1), update_recommendations: 更新建议 } # 检查冲突的知识---------------------------------------- instruction 你是一个知识一致性检查专家。请分析给定的知识库找出可能存在冲突或矛盾的信息。 检查标准 1. 同一主题的不同说法地点、名称、描述等 2. 价格信息的差异价格、费用、收费标准等 3. 时间信息的不一致营业时间、开放时间、活动时间等 4. 规则政策的冲突规定、政策、要求等 5. 操作流程的差异步骤、方法、流程等 6. 联系方式的差异地址、电话、网址等 请返回JSON格式 { conflicting_knowledge: [ { conflict_type: 冲突类型, chunk_ids: [相关切片ID], conflicting_content: [冲突内容], severity: 严重程度高/中/低, resolution_suggestion: 解决建议 } ], consistency_score: 一致性评分(0-1), conflict_analysis: 冲突分析 } 然后根据返回的内容生成健康度报告并打印出来示例系统的健康评分只有 0.57~0.6——说明大多数知识库都带病运行。审查只是提示问题在哪里补充和修正则是下一步的运营动作。4、知识库版本管理把知识当产品迭代知识库像代码和 Prompt 模板一样需要版本化V1、V2……核心功能• 版本创建为知识库创建带描述和统计信息的版本• 统计信息记录知识切片数量、内容长度、分类分布等• 版本比较比较两个版本的差异和变化向量数据库本身支持增删改查增量更新、局部更新完全可行不必每次全量重建索引。现在的公司里用的是哪些知识库管理工具有知道的吗二、高效召回我们原来是怎么用代码在Faiss数据库召回内容的呢?回忆一下for ... all_vectors.append(vector) #向量 metadata_store.append(metadata) #metadata # 创建FAISS索引 text_index faiss.IndexFlatL2(TEXT_EMBEDDING_DIM) #参数维度 text_index_map faiss.IndexIDMap(text_index) if all_vectors: text_ids [m[id] for m in metadata_store] text_index_map.add_with_ids(np.array(text_vectors).astype(float32), np.array(text_ids)) ...... # 获取查询的embedding query_vector np.array([get_text_embedding(query)]).astype(float32) # 使用faiss进行检索 distances, indices text_index_map.search(query_vector, k) for i, doc_id in enumerate(indices[0]): m metadata[idx] content_preview m[content][:45].replace(\n, ) ...... # 取top-k文本结果 top_results [r for r in results if r[metadata][type] text][:k]# 创建文本分割器用于将长文本分割成小块 text_splitter RecursiveCharacterTextSplitter( separators[\n\n, \n, ., , ], chunk_size1000, chunk_overlap200, length_functionlen, ) # 分割文本 chunks text_splitter.split_text(text) print(f文本被分割成 {len(chunks)} 个块。) # 创建嵌入模型 embeddings DashScopeEmbeddings( modeltext-embedding-v1, dashscope_api_keyDASHSCOPE_API_KEY, ) # 从文本块创建知识库 knowledgeBase FAISS.from_texts(chunks, embeddings) print(已从文本块创建知识库。) ...... query 客户经理被投诉了投诉一次扣多少分 if query: # 执行相似度搜索找到与查询相关的文档 docs knowledgeBase.similarity_search(query,k10) #K是召回多少个片段之前的召回我们想要回答质量更高我们的召回数量K一般5~10可以设置的高一点。然后给到大模型如果召回到不太相关的内容给到大模型是没关系的只要能召回到关键的信息大模型自己会做筛选组织推理等工作。1、多查询召回相似语义改写就是使用大模型将用户查询改写成多个语义相近的查询提升召回多样性。在LangChain旧版本中提供了MultiQueryRetriever支持多查询召回新版本需要自己编写。我们编写的也是用大模型来帮我们来改写使用LLM生成多个查询变体 prompt f你是一个AI助手负责生成多个不同视角的搜索查询。 给定一个用户问题生成{num_queries}个不同但相关的查询以帮助检索更全面的信息。 原始问题: {query} 请直接输出{num_queries}个查询每行一个不要编号和其他内容: response llm.invoke(prompt)我问一个问题客户经理的考核标准是什么生成结果如下遍历这些问题将向量库中匹配的内容去重后作为大模型的参考资料让大模型回答问题。2、索引扩展1离散索引扩展关键词的索引BM25使用关键词抽取、实体识别等技术生成离散索引与向量检索互补提升召回准确性。BM25是一种经典的文本检索算法它是TF-IDF词频-逆文档频率的改进版本通过更精细的词频饱和度和文档长度归一化提升了检索的相关性排序效果。计算方法用了TF * IDF以后我们再除上一个它的归一化的系数文档的长度越长分数越低。文档的长度越短价值越明显。BM25的值越高。实体识别从文档中识别出命名实体如人名、地点、组织等作为离散索引的一部分增强检索的精确性。2连续索引扩展向量索引结合多种向量模型如OpenAI的Ada、智源的BGE进行多路召回取长补短。3混合索引召回将BM25等离散索引与向量索引结合通过Ensemble Retriever实现混合召回提升召回多样性# ----------------------------BM25--------------------------------- # 构建BM25索引tokenize_chinese是用jieba分词器把chunk切分 tokenized_chunks [tokenize_chinese(chunk) for chunk in chunks] self.bm25 BM25Okapi(tokenized_chunks) ....... # BM25检索 tokenized_query tokenize_chinese(query) # 用jieba分词器query分词 bm25_scores self.bm25.get_scores(tokenized_query) #分词列表打分 # 归一化BM25分数归一化就是分数统一缩放到[0, 1] 区间 max_bm25 max(bm25_scores) if max(bm25_scores) 0 else 1 #获取最大的bm25打分 bm25_scores_normalized [s / max_bm25 for s in bm25_scores] #归一化计算 # ----------------------------向量--------------------------------- # 构建chunk到索引的映射 self.chunk_to_idx {chunk: idx for idx, chunk in enumerate(chunks)} ....... # 向量检索 (获取更多结果用于融合) vector_results self.vectorstore.similarity_search_with_score(query, klen(self.chunks)) # 构建向量分数字典 (距离越小越好转换为分数) vector_scores {} max_distance max(score for _, score in vector_results) if vector_results else 1 for doc, distance in vector_results: idx self.chunk_to_idx.get(doc.page_content) if idx is not None: # 距离转分数: 1 - (distance / max_distance) vector_scores[idx] 1 - (distance / max_distance) if max_distance 0 else 0 # ----------------------------融合--------------------------------- hybrid_scores [] for idx in range(len(self.chunks)): bm25_score bm25_scores_normalized[idx] vector_score vector_scores.get(idx, 0) # 加权融合 combined self.alpha * vector_score (1 - self.alpha) * bm25_score hybrid_scores.append((idx, combined)) # 排序并返回top-k hybrid_scores.sort(keylambda x: x[1], reverseTrue) top_k hybrid_scores[:k] results [] for idx, score in top_k: doc Document(page_contentself.chunks[idx], metadata{hybrid_score: score}) #将切片内容和分数转为LangChain Document 对象 results.append(doc) ...... # 大模型根据返回内容回答 context \n\n.join([doc.page_content for doc in docs]) prompt f根据以下上下文回答问题: {context} 问题: {query} response llm.invoke(prompt)离散索引其实指的就是关键词的索引我们会把关键词提取出来根据关键词来去做一些匹配得到关键词的分数。以上的代码用jieba来分词实际上抽取关键词有TF-IDF、TextRank等方法实体识别有SpaCy、BERT-based NER等方法。BM25检索比较精确而向量检索是模糊检索避免丢掉一些写法上不统一的内容。向量检索是一个粗筛他在给我们带来兜底的情况下也给我们带来了干扰。根据公式Score α ×Vector (1-α) ×BM25•专业术语多的文档- 降低alpha (偏BM25)•用户问题口语化- 提高alpha (偏向量)•不确定时- 从α 0.5 开始根据效果微调3、Rerank模型使用有时候我们经过粗筛召回的数量很多并且这些也并不都有价值反而给我们的检索带来干扰。这时候我们可以使用重排序Rerank在帮我们做一个筛选。重排序Rerank主要用于优化初步检索结果的排序提高最终输出的相关性或准确性。BGE-Rerank和Cohere Rerank是 两种广泛使用的重排序模型它们在检索增强生成RAG系统、搜索引擎优化和问答系统中表现优异。1BGE-Rerank由北京智源人工智能研究院BAAI开源发布属于FlagEmbedding项目的一部分。 基于Transformer的Cross-Encoder结构直接计算查询Query与文档Document的交互相关性得分。 训练数据支持多语言中、英等训练数据包括T2Ranking、MSMARCO、NLI等数据集。 提供bge-reranker-base和bge-reranker-large两个版本后者在精度上更优。部署方式可本地部署在魔搭社区可以检索到bge-rerank的模型本地部署Rerank模型# model_name: ModelScope上的模型名称 # - BAAI/bge-reranker-base (轻量级推荐) # - BAAI/bge-reranker-large (效果更好但更慢) model_dir snapshot_download(model_name, cache_dircache_dir) print(f模型已下载到: {model_dir}) self.tokenizer AutoTokenizer.from_pretrained(model_dir) self.model AutoModelForSequenceClassification.from_pretrained(model_dir) self.model.eval() # 使用GPU如果可用 self.device cuda if torch.cuda.is_available() else cpu self.model.to(self.device) print(fRerank模型已加载使用设备: {self.device})大家看下Rerank模型的下载和加载和我们前面介绍的其他模型一样呢。以下是使用Rerank模型召回文档刚好接上一个代码混合检索后召回docs再用rerank模型做一个二次排序reranked_docs rerank(query, docs, top_kfinal_k) def rerank(self, query: str, documents: List[Document], top_k: int None) - List[Document]: if not documents: return [] # 构建query-document对 pairs [[query, doc.page_content] for doc in documents] # 批量计算分数 with torch.no_grad(): inputs self.tokenizer( pairs, paddingTrue, truncationTrue, max_length512, return_tensorspt ).to(self.device) # 打分的重点 scores self.model(**inputs).logits.squeeze(-1).cpu().tolist() # 如果只有一个文档scores可能是float而不是list if isinstance(scores, float): scores [scores] # 为每个文档添加rerank分数 scored_docs list(zip(documents, scores)) scored_docs.sort(keylambda x: x[1], reverseTrue) # 更新metadata中的分数 results [] for doc, score in scored_docs: doc.metadata[rerank_score] score results.append(doc) if top_k: results results[:top_k] return resultsReRank属于轻量级的弱化版的大模型。他不能回答问题但是只能给你打分告诉两个之间的相关性。由于问题-答案对都要去计算分数实际他的速度不会很快。在BGE-Rerank模型中相关性分数scores是一个未归一化的对数几率logits值范围没有固定的上 限或下限不像某些模型限制在0-1。不过BGE-Rerank的分数通常落在以下范围高相关性3.0~10.0 中等相关性0.0~3.0低相关性/不相关负数如-5.0以下2Cohere Rerank由Cohere公司提供的商业API服务。 基于专有的深度学习模型支持多语言如rerank-multilingual-v3.0。 训练数据优化了语义匹配特别适用于混合检索如结合BM25和向量检索后的结果优化。 使用方式通过API调用集成到LangChain、LlamaIndex等框架中。优势• 简单易用适合快速集成到现有系统。• 在英文和多语言任务中表现优异如提升Hit Rate命中率和MRR平均倒数排名。import cohere co cohere.Client(api_keyYOUR_API_KEY) query What is the capital of France? docs [Paris is the capital of France., Berlin is the capital of Germany.] results co.rerank(queryquery, documentsdocs, top_n2, modelrerank-multilingual-v3.0) print(results) #Cohere Rerank的API返回的是归一化后的相关性分数如0-1更易解释。4、双向改写Query2Doc和Doc2Query核心是解决“用户怎么问”和“知识怎么写”不一致的问题。Query2Doc把用户问题先扩写成一段“预想答案”再用这段内容去匹配知识库。例用户问“怎么提高模型训练效率”先扩成“可从混合精度、分布式训练、数据预处理、学习率调整等方向优化”更容易命中知识库。Doc2Query建库时为每个知识片段预生成若干“它能回答什么问题”。检索时不只匹配原文也匹配这些预生成问题提高召回率。5、Small to big策略一种高效的检索方法特别适用于处理长文档或多文档场景。核心思想是通过小规模内容如摘要、关键句 或段落建立索引并链接到大规模内容主体中。这种策略的优势在于能够快速定位相关的小规模内容并通过链接获取更详细的上下文信息从而提高检索效率和答案的逻辑连贯性。Small-to-Big机制小规模内容检索用户输入查询后系统首先在小规模内容如摘要、关键句或段落中检索匹配的内容。小规模内容通常是通过摘要生成、关键句提取等技术从大规模内容中提取的并建立索引。链接到大规模内容当小规模内容匹配到用户的查询后系统会通过预定义的链接如文档ID、URL 或指针找到对应的大规模内容如完整的文档、文章。大规模内容包含更详细的上下文信息为RAG 提供丰富的背景知识。上下文补充将大规模内容作为RAG 系统的上下文输入结合用户查询和小规模内容生成更准确和连贯的答案。