Files
ailine/backend/app/rag
root ef6fbc1521
Some checks failed
构建并部署 AI Agent 服务 / deploy (push) Failing after 6m36s
推理优化
2026-05-06 04:26:06 +08:00
..
2026-05-05 23:17:00 +08:00
2026-04-21 11:02:16 +08:00
2026-05-06 04:26:06 +08:00
2026-05-05 14:06:36 +08:00
2026-05-06 01:15:52 +08:00
2026-05-06 01:15:52 +08:00
2026-05-05 23:17:00 +08:00

在线 RAG 检索与生成系统 (Online RAG Retriever)

该模块负责 RAG 系统的阶段二:在线检索与生成。它接收用户提问,从知识库中检索出上下文,利用各种高级策略去噪、融合,并作为增强上下文输入给大语言模型 (LLM)。

🎯 核心架构

技术栈

组件 技术选型 说明
基础检索 Qdrant HNSW 稠密向量检索
混合检索 Qdrant + BM25 稠密 + 稀疏向量融合Qdrant 原生 RRF
查询改写 LangChain MultiQueryGenerator 多路改写
重排序 llama.cpp 本地服务OpenAI 兼容 Rerank API
编排框架 asyncio 异步并行检索
服务接入 model_services 统一获取嵌入、LLM、重排序服务

检索流水线

                    用户查询
                        ↓
              ┌───────────────────┐
              │  MultiQueryGenerator │ (可选)
              │  多路查询改写       │
              └─────────┬─────────┘
                        ↓
              ┌───────────────────┐
              │  并行检索         │
              │  (asyncio.gather) │
              └─────────┬─────────┘
                        ↓
              ┌───────────────────┐
              │  Qdrant 混合检索  │
              │  (dense + sparse) │
              └─────────┬─────────┘
                        ↓
              ┌───────────────────┐
              │  RRF 分数融合     │ (Qdrant 原生)
              └─────────┬─────────┘
                        ↓
              ┌───────────────────┐
              │  重排序 (可选)    │
              └─────────┬─────────┘
                        ↓
              ┌───────────────────┐
              │  父文档获取       │
              └─────────┬─────────┘
                        ↓
                    增强上下文

技术特性

  • Qdrant 原生混合检索:稠密向量 + BM25 稀疏向量,服务端 RRF 分数融合
  • 父子文档策略:子块精准检索,父块提供完整上下文
  • 多路查询改写:通过 LLM 将单一问题改写为多个不同角度的查询
  • 远程重排序:使用 llama.cpp 服务的 OpenAI 兼容 Rerank API
  • 完全异步化:检索、融合、重排序全链路 async / await
  • 统一服务接入:所有模型服务通过 model_services 获取

📂 架构与文件结构

backend/app/rag/
├── __init__.py
├── retriever.py           # Qdrant 混合检索器(含父子文档支持)
├── rerank.py              # llama.cpp 远程重排序器
├── query_transform.py     # 多路查询改写生成器
├── fusion.py              # RRF 融合算法(备用)
├── pipeline.py            # RAG 流水线编排
├── tools.py               # LangChain Tool 封装
├── evaluate.py            # 评估工具
└── README.md              # 本文档

backend/app/model_services/
├── embedding_services.py  # 嵌入服务
├── chat_services.py       # LLM 服务
└── rerank_services.py     # 重排序服务

backend/rag_core/
├── vector_store.py        # Qdrant 混合存储
├── sparse_embedder.py     # BM25 稀疏嵌入
├── doc_store.py           # PostgreSQL 文档存储
└── ...                    # 其他核心组件

🎯 演进路线与算法详解 (Roadmap)

  • 核心算法: 近似最近邻搜索 (ANN, 常用 HNSW 算法)。将用户问题转化为向量后,计算它与库中向量的余弦相似度 (Cosine Similarity),取距离最近的 K 个块。
  • 优缺点: 速度极快。但只能捕捉"语义相似",如果用户搜索特定专有名词、编号、订单号,纯向量检索往往会失效(产生"幻觉"匹配)。
  • 实现指南:
    • 使用 model_services.embedding_services 获取嵌入模型
    • 使用 app.rag.retriever 中的 create_base_retriever 创建基础检索器
    • 配置检索返回数量进行初步召回

Level 2: 混合检索与重排序Hybrid Search + Reranker

混合检索旨在结合向量的"语义泛化"与关键词的"精确匹配",随后利用重排序模型过滤噪声。

当前状态

  • 混合检索已完全实现,使用 Qdrant 原生双向量存储 + RRF 分数融合
  • Qdrant 集合已配置稀疏向量字段,支持 dense + sparse 同步检索
  • 重排序器使用 llama.cpp 服务的 OpenAI 兼容 Rerank API

1. 混合检索(核心)

  • 核心原理: 结合基于 HNSW 的 Dense Vector 相似度检索与基于 TF-IDF 的 BM25 稀疏检索 (Sparse Vector)
  • 实现指南: 使用 app.rag.retriever 中的 create_hybrid_retrievercreate_parent_hybrid_retriever 函数
  • 技术优势: Qdrant 原生支持,无需客户端后处理,性能更优

2. 二次精排 (Cross-Encoder)

  • 核心原理: 不同于双塔模型(分别算向量再求距离),交叉编码器将"用户问题 + 检索到的单例文档"拼接后整体输入 Transformer 模型,由模型直接输出 0~1 的相关性得分,精度极高
  • 实现指南: 使用 app.rag.rerank 中的 LLaMaCPPReranker 类,设置 top_n 保留最相关结果

Level 3: RAG-Fusion (多路改写与倒数排名融合)

RAG-Fusion 通过大模型发散思维,将单一问题改写为多个相似问题,扩大搜索面,再利用数学统计算法合并结果。

1. 多路查询改写

  • 核心原理: 克服用户初始提问词不达意或视角受限的问题
  • 实现指南: 使用 app.rag.query_transform 中的 MultiQueryGenerator 类,配置 num_queries 生成不同角度的查询

2. 倒数排名融合 (RRF)

  • 核心原理: RRF (Reciprocal Rank Fusion) 是一种无需评分归一化的融合算法。公式为 RRF_score(d) = Σ 1/(k + rank_q(d)),有效避免某一极端检索结果主导全局
  • 当前实现: 使用 Qdrant 原生 FusionQuery 进行服务端 RRF 融合,性能更优

Level 4: Agentic RAG / Self-RAG (智能体与自我反思)

  • 核心原理: 基于 LangGraph 的 ReAct (Reasoning and Acting) 状态机路由。大模型并非每次都去死板地执行检索,而是先判断问题:"这是闲聊?还是需要查知识库?"。如果是后者,模型输出一个 ToolCall 指令,触发检索。

  • 实现指南: 使用 app/rag/tools.py 中的 search_knowledge_base 工具,将其绑定到 LangGraph 状态机中。

  • 示意图:

┌──────────┐     ┌──────────────┐     ┌──────────┐     ┌────────
│   User   │────>│ LangGraph    │────>│ RAG_Tool │────>│ Qdrant │
│          │     │ Agent        │     │          │     │        │
│ "公司报  │     │ 思考: 这是   │     │ ToolCall │     │ RAG-   │
│ 销流程?"│     │ 内部规章问题 │     │ search_  │     │ Fusion │
│          │     │ 需要查资料   │     │ knowledge│     │ & 混合 │
│          │<────│ 资料充分,   │<────│ 返回最相 │<────│ 检索   │
│ "根据知  │     │ 开始撰写回答 │     │ 关5条规定 │     │ Cross- │
│ 识库规定 │     │              │     │          │     │ Encoder│
│ ..."     │     │              │     │          │     │ 重排   │
└──────────     └──────────────     └──────────┘     └────────┘

Level 5: GraphRAG 集成 (基于图和关系的 RAG)

  • 核心原理: 结合知识图谱的结构化关系和向量检索的语义相似度,解决跨文档复杂关系推理问题
  • 实现指南:
    • 使用 langchain_community.graphs 模块构建知识图谱
    • 配置本地大模型(如 Gemma-4-E4B)用于实体关系抽取
    • 实现混合检索逻辑,结合向量相似度和图路径分析

🔧 核心组件详解

1. 检索器 (retriever.py)

提供基于 Qdrant 的向量检索能力。

基础检索器

  • 功能:纯稠密向量检索
  • 配置:集合名称、检索数量

混合检索器

  • 功能:稠密 + 稀疏向量混合检索Qdrant 原生 RRF 融合
  • 配置:集合名称、检索数量、分数阈值(可选)

父子文档混合检索器

  • 功能:子块检索 → 父块获取,提供完整上下文
  • 配置:集合名称、检索数量

2. 多路查询改写 (query_transform.py)

通过 LLM 将用户问题改写为多个不同版本,扩大搜索面。

配置

  • LLM 服务:从 model_services.chat_services 获取
  • 查询数量:默认 3 个

3. RRF 融合算法 (fusion.py)

Reciprocal Rank Fusion 算法,公式:RRF_score(d) = Σ 1/(k + rank_q(d))

当前状态

  • 主要使用 Qdrant 原生 FusionQuery 进行服务端融合
  • 本模块为备用实现,用于特殊场景

4. 重排序器 (rerank.py)

使用 llama.cpp 服务的 OpenAI 兼容 Rerank API 对检索结果重排序。

配置

  • 服务地址:从环境变量或配置获取
  • API Key从环境变量或配置获取
  • Top N返回最相关的 N 个结果

5. RAG 流水线 (pipeline.py)

组合上述组件的完整检索流水线。

主要功能

  • 多路查询改写(可选)
  • 混合检索(支持父子文档)
  • 重排序(可选)
  • 上下文格式化

配置选项

  • 集合名称
  • LLM 服务
  • 是否使用多路改写
  • 是否使用重排序
  • 检索/重排序数量

🔄 与 Agent 系统集成

封装为 LangChain Tool

  • 创建工具函数,用于搜索知识库获取相关信息
  • 工具描述要清晰,说明功能和用途

绑定到 LangGraph

  • 将 RAG 工具添加到 Agent 可用工具列表
  • 构建 LangGraph 图时传入工具列表
  • 配置检查点(可选)用于状态持久化

⚙️ 环境配置

变量名 说明 默认值
QDRANT_URL Qdrant 向量数据库地址 http://115.190.121.151:6333
QDRANT_API_KEY Qdrant API 密钥 -
DB_HOST PostgreSQL 主机 115.190.121.151
DB_PORT PostgreSQL 端口 5432
DB_USER PostgreSQL 用户 postgres
DB_PASSWORD PostgreSQL 密码 postgres
DB_NAME PostgreSQL 数据库 rag_db
LLAMACPP_EMBEDDING_URL llama.cpp 嵌入服务地址 http://127.0.0.1:18001
LLAMACPP_RERANK_URL llama.cpp 重排序服务地址 http://127.0.0.1:18002
LLAMACPP_CHAT_URL llama.cpp 聊天服务地址 http://127.0.0.1:18000
LLAMACPP_API_KEY llama.cpp API 密钥 huang1998

🚀 快速开始

步骤概览

  1. 初始化模型服务:从 model_services 获取嵌入、LLM、重排序服务
  2. 创建检索器:选择 create_base_retrievercreate_hybrid_retrievercreate_parent_hybrid_retriever
  3. 创建 RAG 流水线:配置是否使用多路改写、是否使用重排序等
  4. 执行检索:调用 aretrieve 进行异步检索
  5. 格式化上下文:调用 format_context 整理为 LLM 可用格式

📊 检索策略对比

策略 优点 缺点 适用场景
基础向量检索 速度快,语义理解好 专有名词匹配差 通用问答
混合检索 语义 + 关键词匹配 - 专业术语查询
父子文档混合检索 检索精准 + 上下文完整 - 生产环境通用
多路改写 + RRF 搜索面广,结果稳定 延迟略高 复杂问题
重排序 精度高 依赖额外模型 最终精排

🤝 与 rag_indexer 集成

  • 向量存储:共享 Qdrant 集合,确保嵌入模型一致
  • 文档存储:使用 PostgreSQL 存储父块,通过 UUID 映射
  • 集合名称:默认使用 rag_documents 集合
  • 服务接入:统一使用 model_services 获取模型服务

详见 rag_indexer/README.md