Chapter9 图RAG系统架构与实现
第九章学习笔记:图RAG系统架构与实现
学习目标
- 了解图RAG系统的架构设计和环境配置
- 掌握图数据建模与Neo4j集成方法
- 学习Milvus索引构建的优化策略
- 理解智能查询路由与检索策略的设计
- 掌握图RAG系统的核心组件和工作流程
学习内容
一、图RAG系统架构与环境配置
1.1 项目背景与目标
从传统RAG到图RAG的演进: 上一章构建的传统RAG系统在处理复杂的关系推理和多跳查询时存在明显局限:
- 关系理解缺失:无法显式建模食材、菜谱、烹饪方法之间的语义关系
- 跨文档关联困难:难以发现不同菜谱之间的相似性、替代关系等隐含联系
- 推理能力有限:缺乏基于知识图谱的多跳推理能力
图RAG系统的核心优势:
- 结构化知识表达:以图的形式显式编码实体间的语义关系
- 增强推理能力:支持多跳推理和复杂关系查询
- 智能查询路由:根据查询复杂度自动选择最适合的检索策略
- 事实性与可解释性:基于图结构的推理路径提供可追溯的答案
1.2 环境配置
创建虚拟环境:
conda create -n graph-rag python=3.12.7
conda activate graph-rag安装核心依赖:
cd code/C9
pip install -r requirements.txtNeo4j数据库配置:
- 使用Docker Compose方式安装Neo4j
- 配置文件位于
data/C9/docker-compose.yml - 启动命令:
docker-compose up -d - Web界面访问:http://localhost:7474
- 用户名:neo4j,密码:all-in-rag
Milvus向量数据库配置:
- 使用Docker安装Milvus standalone版本
- 验证安装:
docker-compose ps
配置连接参数: 在项目根目录创建.env文件,配置Neo4j、Milvus和LLM API的连接参数。
1.3 系统架构设计
整体架构: 图RAG系统采用模块化设计,包含以下核心组件:
- 图数据准备模块 (GraphDataPreparationModule)
- 向量索引模块 (MilvusIndexConstructionModule)
- 混合检索模块 (HybridRetrievalModule)
- 图RAG检索模块 (GraphRAGRetrieval)
- 智能查询路由 (IntelligentQueryRouter)
- 生成集成模块 (GenerationIntegrationModule)
数据流程:
- 数据准备阶段:从Neo4j加载图数据,构建结构化菜谱文档,进行智能文档分块,构建Milvus向量索引
- 查询处理阶段:用户输入查询,智能查询路由器分析查询特征,根据分析结果选择检索策略,执行相应的检索操作
- 错误处理与降级:高级策略失败时自动降级到传统混合检索,支持流式输出中断时的自动重试机制
二、图数据建模与Neo4j集成
2.1 数据来源与转换
从Markdown到图数据的转换:
- 读取Markdown菜谱:从第八章的数据源加载菜谱文件
- LLM解析提取:使用大语言模型识别和提取实体及关系
- 结构化输出:生成nodes.csv和relationships.csv文件
- 图数据导入:通过Cypher脚本导入Neo4j数据库
图数据文件结构:
data/C9/cypher/
├── nodes.csv # 节点数据(菜谱、食材、步骤等)
├── relationships.csv # 关系数据(菜谱-食材、菜谱-步骤等)
└── neo4j_import.cypher # 数据导入脚本2.2 图数据模型设计
核心实体类型:
- Recipe (菜谱):具体的菜品,包含难度、菜系、时间等属性
- Ingredient (食材):制作菜品所需的原料,包含分类、用量、单位等
- CookingStep (烹饪步骤):详细的制作步骤,包含方法、工具、时间估计
- CookingMethod (烹饪方法):如炒、煮、蒸、炸等烹饪技法
- CookingTool (烹饪工具):如炒锅、蒸锅、刀具等
- DifficultyLevel (难度等级):一星到五星的难度分级
- RecipeCategory (菜谱分类):素菜、荤菜、水产、早餐等分类
关系类型:
| 关系编码 | 关系类型 | 说明 | 属性 |
|---|---|---|---|
| 801000001 | REQUIRES | 菜谱-食材关系 | relationshipId, amount, unit |
| 801000003 | CONTAINS_STEP | 菜谱-步骤关系 | relationshipId, step_order |
| 801000004 | HAS_DIFFICULTY_LEVEL | 菜谱-难度关系 | relationshipId |
| 801000005 | BELONGS_TO_CATEGORY | 菜谱-分类关系 | relationshipId |
2.3 图数据查询与检索
基础查询模式:
- 简单实体查询:查找特定分类的菜谱、包含特定食材的菜谱
- 多跳关系查询:查找某个难度等级的所有菜谱、菜谱的完整制作流程
- 全文搜索:使用全文索引查找菜谱
复杂推理查询:
- 基于约束的菜谱推荐:查找适合新手的简单菜谱、制作时间短的菜谱
- 菜谱组合推荐:查找同一分类下的不同菜谱、包含相同食材的不同菜谱
2.4 图数据到文档的转换
结构化文档构建:
def build_recipe_documents(self, graph_data: List[Dict]) -> List[Document]:
"""将图数据转换为结构化文档"""
# 构建结构化文档内容
content_parts = [
f"# {recipe['name']}",
f"分类: {', '.join([c['name'] for c in categories])}",
f"难度: {recipe['difficulty']}星",
"",
"## 所需食材"
]
# 添加食材列表和制作步骤
# 创建Document对象,包含丰富的元数据图RAG vs 传统RAG的分块对比:
| 特性 | 第八章 传统RAG | 第九章 图RAG |
|---|---|---|
| 数据来源 | 直接读取Markdown文件 | 从图数据库构建文档 |
| 上下文获取 | 父子文档映射 | 图关系遍历 |
| 关系信息 | 有限(仅父子关系) | 丰富(多种图关系) |
| 分块策略 | 按Markdown标题分块 | 按语义+长度智能分块 |
| 元数据来源 | 文件路径+内容推断 | 图节点结构化数据 |
三、Milvus索引构建
3.1 索引构建概述
索引构建流程: 图RAG的索引构建需要将从图数据库构建的结构化文档转换为向量表示,并存储到向量数据库中:
图数据库 → 文档构建 → 文档分块 → 向量化 → Milvus索引核心组件:
- 文档构建器:从图数据构建结构化文档
- 分块处理器:智能分块策略
- 向量化模型:文本转向量
- Milvus索引:高性能向量存储和检索
3.2 Milvus索引构建实现
索引构建器核心架构:
class MilvusIndexConstructionModule:
"""Milvus索引构建模块 - 负责向量化和Milvus索引构建"""
def __init__(self, host: str = "localhost", port: int = 19530,
collection_name: str = "cooking_knowledge",
dimension: int = 512,
model_name: str = "BAAI/bge-small-zh-v1.5"):
# 初始化配置和连接向量化处理:
- 使用BGE-small-zh-v1.5模型进行文本向量化
- 批量处理文档,提高效率
- 准备丰富的元数据,支持后续的复合检索
图RAG专用集合Schema设计:
- 专门为烹饪知识图谱设计的字段结构
- 包含菜谱名称、节点类型、菜系、难度等图谱特有信息
- 根据实际数据特点设置合理的字段长度限制
- 所有关键字段都可用于过滤和检索条件
3.3 索引优化策略
批量插入优化:
- 使用批量插入提高数据写入效率
- 设置合理的批次大小,平衡内存使用和性能
- 添加错误处理和日志记录
索引创建:
- 使用COSINE余弦相似度度量
- 选择IVF_FLAT索引类型,平衡查询速度和准确率
- 合理设置索引参数,如nlist=1024
索引验证:
- 检查集合状态和数据量
- 执行简单的检索测试,验证索引可用性
3.4 从FAISS切换到Milvus的优势
FAISS的局限性:
- 纯库模式:缺乏数据库的完整功能
- 无持久化:需要手动管理数据持久化和备份
- 单机限制:难以实现分布式部署和水平扩展
- 元数据支持有限:无法高效存储和查询复杂的结构化元数据
- 并发性能:在高并发场景下性能受限
Milvus的优势:
- 完整数据库功能:提供CRUD操作、事务支持、数据一致性保证
- 云原生架构:支持分布式部署、自动扩缩容、高可用性
- 丰富的元数据支持:支持复杂Schema设计,适合图RAG的多维度数据
- 生产级特性:监控、日志、备份恢复等企业级功能
四、智能查询路由与检索策略
4.1 智能查询路由器设计
查询路由的必要性: 不同类型的查询需要不同的检索策略:
- 简单查询:“川菜有哪些?”、“宫保鸡丁怎么做?”
- 复杂推理查询:“适合糖尿病人吃的低糖川菜有哪些,并且制作时间不超过30分钟?”
- 中等复杂查询:“家常菜中哪些适合新手制作?”
查询分析框架: 智能查询路由器通过四个维度分析查询特征:
- 查询复杂度 (0-1):简单信息查找、中等复杂度、高复杂度推理
- 关系密集度 (0-1):单一实体信息、实体间关系、复杂关系网络
- 推理需求:是否需要多跳推理、因果分析、对比分析
- 实体识别:查询中包含多少个明确实体
智能路由执行: 基于分析结果,路由到最适合的检索策略:
- 简单查询(复杂度 < 0.4)→ 传统混合检索
- 复杂推理查询(复杂度 > 0.7 或关系密集度 > 0.7)→ 图RAG检索
- 中等复杂查询(0.4 ≤ 复杂度 ≤ 0.7)→ 组合检索策略
4.2 三种检索策略详解
传统混合检索策略: 适用于简单查询,结合双层检索和向量检索:
- 双层检索:实体级+主题级检索
- 向量检索:语义相似度匹配
- Round-robin轮询合并:公平合并不同结果,确保多样性
图RAG检索策略: 适用于复杂推理查询,基于图结构进行多跳推理:
- 查询意图理解:分析查询类型(多跳推理、路径查找、子图提取、实体关系)
- 多跳遍历:最大深度3跳,发现隐含关联
- 知识子图提取:完整知识网络,最大100节点
- 图结构推理:推理链构建、可信度验证
多跳推理的价值:
- 知识发现:挖掘数据中的隐含关系
- 推荐增强:提供更丰富的搭配建议
- 语义理解:模拟人类的联想思维过程
- 数据利用:充分利用图结构的关系信息
组合检索策略: 适用于中等复杂查询,结合传统检索和图RAG的优势:
- 分配检索配额:traditional_k = top_k // 2, graph_k = top_k - traditional_k
- 并行执行检索:同时执行传统检索和图RAG检索
- Round-robin合并:交替添加结果,图RAG优先
- 去重和排序:基于内容哈希去重
4.3 Round-robin轮询合并机制
原理: Round-robin(轮询)是一种公平调度算法,在RAG系统中用于融合多个检索结果。其核心是按顺序轮流从不同的结果列表中选择文档,而不是基于分数权重进行合并。
优势:
- 确保了每种检索策略的结果都能得到公平的展示机会
- 避免了某种方法因排序靠前而被过度选择的问题
- 实现简单且稳定,无需调优权重参数
- 自然保持了结果的多样性
实现方式: 第1个位置选择传统检索的第1个结果,第2个位置选择图RAG的第1个结果,第3个位置选择传统检索的第2个结果,以此类推。
学习总结
本章介绍了图RAG系统的架构设计与实现,这是对传统RAG系统的重要升级。图RAG通过引入知识图谱,解决了传统RAG在复杂查询和关系推理方面的局限性。
系统架构采用了模块化设计,包含图数据准备、向量索引构建、混合检索、图RAG检索、智能查询路由和生成集成等核心模块。关键技术点包括:
- 图数据建模:使用Neo4j存储菜谱、食材、烹饪步骤等实体及其关系,支持复杂的多跳推理
- Milvus索引构建:从图数据构建结构化文档,使用BGE模型向量化,存储到Milvus向量数据库
- 智能查询路由:通过LLM分析查询的复杂度、关系密集度、推理需求和实体数量,自动选择最适合的检索策略
- 多检索策略:实现传统混合检索、图RAG检索和组合检索三种策略,满足不同复杂度查询的需求
- Round-robin轮询合并:公平合并不同检索结果,确保多样性和稳定性
图RAG系统的核心优势在于能够处理需要多跳推理的复杂查询,发现数据中的隐含关联,提供更准确、更可解释的答案。通过智能查询路由,系统能够根据查询特征自动选择最适合的检索策略,在保证效果的同时提高系统效率。
