All-in-RAG | 大模型应用开发实战:RAG技术全栈指南
🔍 检索增强生成 (RAG) 技术全栈指南
从理论到实践,从基础到进阶,构建你的RAG技术体系
项目简介
All-in-RAG 是一个综合性的检索增强生成(RAG)技术全栈指南与实践项目。它从最基础的文档加载、文本分割出发,逐步深入到复杂的多模态检索、图数据库集成、智能路由与高级评估,为开发者提供了一套从入门到精通的完整学习路径和可复用的代码实现。
功能特性
- 📚 系统化学习路径:从基础的文档加载与分块到高级的图RAG与智能路由,提供完整的知识体系。
- 🔧 全栈实践代码:包含大量可直接运行的示例代码,涵盖 LangChain、LlamaIndex、FAISS、Milvus 等主流框架和工具。
- 🖼️ 多模态支持:集成 Visualized-BGE 等模型,实现文本与图像的联合检索与编码。
- 🗺️ 图数据库增强:深入整合 Neo4j,展示如何利用图结构进行复杂的关系推理和多跳查询。
- 🚦 智能查询路由:实现基于查询复杂度的智能路由,自动选择传统检索或图RAG策略。
- 📊 全面评估体系:提供基于忠实度(Faithfulness)和相关性(Relevancy)的RAG系统评估方案。
- 🍳 领域应用示例:包含完整的“智能烹饪助手”应用案例,展示RAG技术在垂直领域的落地。
安装指南
环境要求
- Python: 3.12.7 或更高版本
- 主要依赖:LangChain, LlamaIndex, PyTorch, Transformers, Milvus, Neo4j 等
基础安装与配置
克隆项目:
gitclone https://github.com/datawhalechina/all-in-rag.gitcdall-in-rag安装Python依赖(建议使用虚拟环境):
pipinstall-r requirements.txt配置环境变量:
创建.env文件,并配置必要的API密钥和服务地址,例如:# 大模型API(如DeepSeek, Moonshot)DEEPSEEK_API_KEY=your_deepseek_api_key_hereMOONSHOT_API_KEY=your_moonshot_api_key_here# 向量数据库(如Milvus)MILVUS_URI=http://localhost:19530# 图数据库(如Neo4j)NEO4J_URI=bolt://localhost:7687NEO4J_USER=neo4jNEO4J_PASSWORD=your_password_here下载必要模型:
部分示例需要预训练模型,如中文嵌入模型BAAI/bge-small-zh-v1.5和 Visual-BGE 模型。运行提供的下载脚本或根据提示手动下载。# 示例:运行模型下载脚本python scripts/download_model.py
平台说明
- Linux/macOS:支持良好。
- Windows:建议使用 WSL2 以获得最佳体验,特别是运行 Milvus、Neo4j 等服务时。
- GPU 加速:如需使用GPU进行嵌入计算或模型推理,请确保安装对应版本的 PyTorch 和 CUDA。
使用说明
快速开始:基础RAG流水线
以下是一个使用 LangChain 构建基础RAG系统的最小示例,它完成了从加载Markdown文档到生成答案的完整流程。
# 基础RAG示例 (基于代码文件3)importosfromdotenvimportload_dotenvfromlangchain_community.document_loadersimportUnstructuredMarkdownLoaderfromlangchain_text_splittersimportRecursiveCharacterTextSplitterfromlangchain_huggingfaceimportHuggingFaceEmbeddingsfromlangchain_core.vectorstoresimportInMemoryVectorStorefromlangchain_core.promptsimportChatPromptTemplatefromlangchain_deepseekimportChatDeepSeek load_dotenv()# 1. 加载文档markdown_path=“your_document.md” loader=UnstructuredMarkdownLoader(markdown_path)docs=loader.load()# 2. 文本分块text_splitter=RecursiveCharacterTextSplitter()chunks=text_splitter.split_documents(docs)# 3. 向量化与存储embeddings=HuggingFaceEmbeddings(model_name=“BAAI/bge-small-zh-v1.5”)vectorstore=InMemoryVectorStore(embeddings)vectorstore.add_documents(chunks)# 4. 配置大模型llm=ChatDeepSeek(model=“deepseek-chat”,api_key=os.getenv(“DEEPSEEK_API_KEY”))# 5. 构建提示模板prompt=ChatPromptTemplate.from_template(“”“请根据上下文回答问题。 上下文:{context}问题:{question}回答:”“”)# 6. 检索与生成question=“你的问题是什么?” retrieved_docs=vectorstore.similarity_search(question,k=3)context=“\n\n”.join(doc.page_contentfordocinretrieved_docs)answer=llm.invoke(prompt.format(question=question,context=context))print(answer)核心模块与进阶使用
项目代码展示了多个核心进阶场景的实现:
- 多模态检索:使用 Visual-BGE 模型进行图文联合编码与检索(见代码文件10)。
- 混合检索与重排:结合向量检索(FAISS)和 BM25,并使用 RRF 算法进行结果重排(见代码文件62)。
- 图RAG检索:基于 Neo4j 图数据库进行多跳查询和子图提取,实现复杂关系推理(见代码文件75)。
- 智能查询路由:分析查询意图,自动路由至传统检索或图RAG引擎(见代码文件77)。
- 系统评估:使用 FaithfulnessEvaluator 和 RelevancyEvaluator 对RAG系统的回答质量进行量化评估(见代码文件56)。
典型应用场景:智能烹饪助手
项目包含一个完整的“智能烹饪助手”案例(见代码文件58等),它集成了:
- 知识图谱构建:从菜谱Markdown文件自动解析并构建烹饪知识图谱(Neo4j)。
- 混合检索:在Milvus中存储向量,并结合图关系进行检索。
- 智能问答:根据用户查询(如“推荐一道简单的川菜”),检索相关信息并生成详细回答。
你可以通过运行主程序来启动该系统:
python main_advanced_graph_rag.py核心代码解析
以下是项目中最能体现其设计思想和技术深度的几个核心模块代码段。
1. 图RAG检索引擎 (GraphRAGRetrieval)
此模块实现了真正的基于图结构的检索与推理,超越了简单的关键词匹配。
# 代码文件75 节选 - 图RAG检索核心类classGraphRAGRetrieval:"""真正的图RAG检索系统,核心特点:查询意图理解、多跳图遍历、子图提取、图结构推理、动态查询规划。"""def__init__(self,config,llm_client):self.config=config self.llm_client=llm_client self.driver=None# Neo4j驱动self.entity_cache={}self.relation_cache={}defmulti_hop_query(self,start_entity:str,relation_types:List[str],max_depth:int=2)->KnowledgeSubgraph:"""执行多跳图查询,探索实体间的深层关系。 Args: start_entity: 起始实体名称。 relation_types: 关注的关系类型列表。 max_depth: 图遍历的最大深度。 Returns: KnowledgeSubgraph: 包含中心节点、关联节点、关系及推理链的知识子图。 """# 1. 初始查询:获取起始实体的直接邻居initial_query=“”“ MATCH(start{name:$entity_name})-[r]->(neighbor)WHEREtype(r)IN $relation_types RETURN start,r,neighbor LIMIT20”“”withself.driver.session()assession:result=session.run(initial_query,entity_name=start_entity,relation_types=relation_types)initial_nodes=[]initial_rels=[]forrecordinresult:initial_nodes.extend([record[“start”],record[“neighbor”]])initial_rels.append(record[“r”])# 2. 多跳扩展:基于初始结果进行广度优先遍历expanded_data=self._bfs_traverse(initial_nodes,relation_types,max_depth)# 3. 构建知识子图并提取推理链subgraph=self._build_knowledge_subgraph(initial_nodes,expanded_data)reasoning_chains=self._extract_reasoning_chains(subgraph,start_entity)subgraph.reasoning_chains=reasoning_chainsreturnsubgraphdef_extract_reasoning_chains(self,subgraph:KnowledgeSubgraph,start_entity:str)->List[List[str]]:"""从子图中提取有意义的推理路径(链)。 例如:`‘红烧肉’ -> (‘属于菜系’)-> ‘川菜’ -> (‘使用技法’)-> ‘红烧’` """chains=[]# 实现基于图拓扑结构和节点/关系类型的路径发现逻辑# ... (具体路径发现算法)returnchains代码解读:
- 意图理解与规划:该类设计的起点是将用户查询转化为图查询模式(如多跳查询),而非直接进行向量相似度计算。
- 多跳遍历 (
multi_hop_query):利用 Neo4j 的 Cypher 查询语言,从起始实体开始,沿特定关系类型进行深度探索,捕获实体间的间接关联。 - 推理链生成 (
_extract_reasoning_chains):这是图RAG的核心价值。它从检索到的子图中提取出连贯的推理路径,为后续生成步骤提供“为什么是这些信息”的解释性结构,使大模型的回答更具逻辑性和可信度。 - 知识封装 (
KnowledgeSubgraph):将检索结果封装为包含节点、关系、图指标和推理链的结构化对象,便于后续处理和解释。
2. 智能查询路由器 (IntelligentQueryRouter)
该模块实现了根据查询复杂度自动选择最优检索策略的智能路由机制。
# 代码文件77 节选 - 智能查询路由核心分析函数classIntelligentQueryRouter:"""智能查询路由器,根据查询特点自动选择最适合的检索策略。"""defanalyze_query(self,query:str)->QueryAnalysis:"""深度分析查询特征,决定最佳检索策略。"""# 使用LLM进行智能分析analysis_prompt=f“”“作为RAG系统的查询分析专家,请深度分析以下查询的特征: 查询:{query}请从以下维度分析:1.查询复杂度(0-1):简单信息查找(如‘红烧肉怎么做?’)为低,高复杂度推理(如‘为什么川菜用花椒而粤菜不用?’)为高。2.关系密集度(0-1):查询中隐含的实体间关系多少。3.是否需要多步推理。 请以JSON格式返回分析结果,包含 `query_complexity`,`relationship_intensity`,`reasoning_required`,`recommended_strategy` 等字段。 ”“” llm_response=self.llm_client.chat.completions.create(model=“deepseek-chat”,messages=[{“role”:“user”,“content”:analysis_prompt}],response_format={“type”:“json_object”})analysis_dict=json.loads(llm_response.choices[0].message.content)# 基于分析结果推荐策略ifanalysis_dict[‘reasoning_required’]andanalysis_dict[‘relationship_intensity’]>0.6:strategy=SearchStrategy.GRAPH_RAG reason=“查询涉及复杂关系推理,图RAG在探索关联关系方面具有优势。”elifanalysis_dict[‘query_complexity’]<0.4:strategy=SearchStrategy.HYBRID_TRADITIONAL reason=“查询为简单事实查找,传统混合检索效率更高。”else:strategy=SearchStrategy.COMBINED reason=“查询复杂度中等,建议组合使用两种检索策略以平衡精度与广度。”returnQueryAnalysis(query_complexity=analysis_dict[‘query_complexity’],relationship_intensity=analysis_dict[‘relationship_intensity’],reasoning_required=analysis_dict[‘reasoning_required’],recommended_strategy=strategy,confidence=0.85,# 可根据历史反馈动态调整reasoning=reason)defroute_and_retrieve(self,query:str)->List[Document]:"""执行路由并检索。"""analysis=self.analyze_query(query)print(f“查询分析:{analysis.reasoning}”)ifanalysis.recommended_strategy==SearchStrategy.GRAPH_RAG:results=self.graph_rag_retrieval.retrieve(query)elifanalysis.recommended_strategy==SearchStrategy.HYBRID_TRADITIONAL:results=self.traditional_retrieval.hybrid_search(query)else:# COMBINEDtraditional_results=self.traditional_retrieval.hybrid_search(query)graph_results=self.graph_rag_retrieval.retrieve(query)results=self._merge_results(traditional_results,graph_results)self.route_stats[f“{analysis.recommended_strategy.value}_count”]+=1self.route_stats[“total_queries”]+=1returnresults代码解读:
- LLM驱动的查询分析 (
analyze_query):利用大模型本身的能力来理解用户查询的潜在需求,判断其属于简单查找还是复杂推理。这避免了依赖固定的关键词规则,更具泛化能力。 - 策略决策逻辑:根据分析结果(复杂度、关系密集度、是否需要推理)映射到三种检索策略:简单查询用传统混合检索(快),复杂推理用图RAG检索(准),中等复杂度用组合策略(平衡)。
- 自适应学习潜力:类中维护的
route_stats可用于后续收集反馈,优化路由决策的置信度,使系统越用越智能。 - 系统设计价值:此路由器是构建高效、经济RAG系统的关键。它避免了图检索(计算开销大)在所有查询上的滥用,实现了资源的最优调配。
3. 混合检索与重排模块 (HybridRetrievalModule)
此模块展示了经典的双检索器(Dense + Sparse)融合与重排技术。
# 代码文件62 节选 - 混合检索与RRF重排classHybridRetrievalModule:"""混合检索模块,结合向量检索和BM25检索,使用RRF重排。"""defhybrid_search(self,query:str,top_k:int=3)->List[Document]:"""混合检索 - 结合向量检索和BM25检索,使用RRF重排。"""# 分别获取向量检索和BM25检索结果vector_docs=self.vector_retriever.invoke(query)# Dense Retrievalbm25_docs=self.bm25_retriever.invoke(query)# Sparse Retrieval# 使用RRF重排reranked_docs=self._rrf_rerank(vector_docs,bm25_docs)returnreranked_docs[:top_k]def_rrf_rerank(self,vector_docs:List[Document],bm25_docs:List[Document],k:int=60)->List[Document]:"""使用RRF (Reciprocal Rank Fusion) 算法重排文档。"""doc_scores={}doc_objects={}# 计算向量检索结果的RRF分数forrank,docinenumerate(vector_docs):doc_id=hash(doc.page_content)# 以内容哈希为IDdoc_objects[doc_id]=doc# RRF公式: 1 / (k + rank)rrf_score=1.0/(k+rank+1)doc_scores[doc_id]=doc_scores.get(doc_id,0)+rrf_score# 计算BM25检索结果的RRF分数forrank,docinenumerate(bm25_docs):doc_id=hash(doc.page_content)doc_objects[doc_id]=doc rrf_score=1.0/(k+rank+1)doc_scores[doc_id]=doc_scores.get(doc_id,0)+rrf_score# 按最终RRF分数排序sorted_docs=sorted(doc_scores.items(),key=lambdax:x[1],reverse=True)# 构建最终结果reranked_docs=[]fordoc_id,final_scoreinsorted_docs:ifdoc_idindoc_objects:doc=doc_objects[doc_id]doc.metadata[‘rrf_score’]=final_score# 分数存入元数据reranked_docs.append(doc)logger.info(f“RRF重排完成:向量检索{len(vector_docs)}个文档,BM25检索{len(bm25_docs)}个文档,合并后{len(reranked_docs)}个文档”)returnreranked_docs代码解读:
- 双路检索 (
hybrid_search):同时调用密集检索器(如基于BERT的向量模型,擅长语义匹配)和稀疏检索器(如BM25,擅长精确关键词匹配),取长补短。 - RRF重排算法 (
_rrf_rerank):- 原理:为每个检索器结果列表中的文档分配一个排名分数,公式为
1 / (k + rank)。k是一个常数(通常设为60),用于平滑低排名的影响。 - 过程:分别计算两个来源的分数,然后对同一文档的分数进行求和。最后根据总分进行全局重排。
- 优点:无需对两个检索器的原始分数进行归一化或校准,简单有效,是融合异质检索结果的经典方法。
- 输出:将最终RRF分数存入文档元数据,便于调试和解释排序原因。
- 原理:为每个检索器结果列表中的文档分配一个排名分数,公式为
- 工程意义:这是构建生产级RAG系统的基石技术,能显著提升检索结果的召回率和鲁棒性。
通过以上三个核心模块的代码解析,可以清晰地看到 All-in-RAG 项目如何将前沿的学术思想(如图推理、智能路由)与成熟的工程实践(如混合检索、RRF重排)相结合,为开发者提供了一个兼具深度和广度的RAG技术蓝图。
KL98CKKrbpl5M1Z+J7nDl9hV6GeCOZLSTxbWWoiOH1g=
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)