Files
ailine/app/rag/README.md
root 933d418d77
Some checks failed
构建并部署 AI Agent 服务 / deploy (push) Failing after 17m12s
检索器重构
2026-04-19 22:01:55 +08:00

172 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 在线 RAG 检索与生成系统 (Online RAG Retriever)
该模块负责 RAG 系统的阶段二:**在线检索与生成**。它接收用户提问,从知识库中检索出上下文,利用各种高级策略去噪、融合,并作为增强上下文输入给大语言模型 (LLM)。
## 🎯 演进路线与算法详解 (Roadmap)
### Level 1: 基础向量搜索 (Basic Similarity Search)
- **核心算法**: 近似最近邻搜索 (ANN, 常用 HNSW 算法)。将用户问题转化为向量后,计算它与库中向量的余弦相似度 (Cosine Similarity),取距离最近的 K 个块。
- **优缺点**: 速度极快。但只能捕捉“语义相似”,如果用户搜索特定专有名词、编号、订单号,纯向量检索往往会失效(产生“幻觉”匹配)。
- **实现指南**:
- 使用 `rag_indexer.embedders.LlamaCppEmbedder` 作为嵌入模型
- 使用 `app/rag/retriever.py` 中的 `create_base_retriever` 创建基础检索器
- 配置 `search_kwargs={"k": 20}` 进行初步召回
### Level 2: 混合检索与重排序 (Hybrid Search + Reranker)
混合检索旨在结合向量的“语义泛化”与关键词的“精准匹配”,随后利用重排序模型过滤噪声。
**1. 基础召回 (混合检索)**
- **核心原理**: 结合基于 HNSW 的 Dense Vector 相似度搜索与基于 TF-IDF 的 BM25 稀疏检索 (Sparse Vector)。
- **实现指南**: 使用 `app/rag/retriever.py` 中的 `create_hybrid_retriever` 函数,配置 `dense_k=10``sparse_k=10`,总召回 20 条结果。
**2. 二次精排 (Cross-Encoder)**
- **核心原理**: 不同于双塔模型(分别算向量再求距离),交叉编码器将“用户问题 + 检索到的单例文档”拼接后整体输入 Transformer 模型,由模型直接输出 0~1 的相关性得分,精度极高。
- **实现指南**:
- 使用 `app/rag/reranker.py` 中的 `CrossEncoderReranker` 类,加载 `BAAI/bge-reranker-base` 模型
- 设置 `top_n=5` 保留最相关的 5 条结果
- 使用 `ContextualCompressionRetriever` 组合基础检索器和重排序器
### Level 3: RAG-Fusion (多路改写与倒数排名融合)
RAG-Fusion 通过大模型发散思维,将单一问题改写为多个相似问题,扩大搜索面,再利用数学统计算法合并结果。
**1. 多路查询改写**
- **核心原理**: 克服用户初始提问词不达意或视角受限的问题。
- **实现指南**: 使用 `app/rag/query_transform.py` 中的 `MultiQueryTransformer` 类,配置 `num_queries=3` 生成 3 个不同角度的查询。
**2. 倒数排名融合 (RRF)**
- **核心原理**: RRF (Reciprocal Rank Fusion) 是一种无需评分归一化的融合算法。公式为 $RRF\_score(d) = \sum_{q \in Q} \frac{1}{k + rank_q(d)}$,有效避免某一极端检索结果主导全局。
- **实现指南**: 使用 `app/rag/retriever.py` 中的 `create_ensemble_retriever` 函数,配置 `search_type="rrf"` 实现倒数排名融合。
### Level 4: Agentic RAG / Self-RAG (智能体与自我反思)
- **核心原理**: 基于 LangGraph 的 ReAct (Reasoning and Acting) 状态机路由。大模型并非每次都去死板地执行检索,而是先判断问题:“这是闲聊?还是需要查知识库?”。如果是后者,模型输出一个 `ToolCall` 指令,触发检索。
- **实现指南**: 使用 `app/rag/tools.py` 中的 `search_knowledge_base` 工具,将其绑定到 LangGraph 状态机中。
- **示意图**:
```mermaid
sequenceDiagram
participant User
participant LangGraph Agent
participant RAG_Tool
participant Qdrant
User->>LangGraph Agent: "公司报销流程是什么?"
LangGraph Agent->>LangGraph Agent: 思考: 这是一个内部规章问题,需要查资料
LangGraph Agent->>RAG_Tool: ToolCall(search_knowledge_base, "公司报销流程")
RAG_Tool->>Qdrant: RAG-Fusion & 混合检索
Qdrant-->>RAG_Tool: 原始分块
RAG_Tool->>RAG_Tool: Cross-Encoder 重排过滤
RAG_Tool-->>LangGraph Agent: 返回最相关的5条报销规定
LangGraph Agent->>LangGraph Agent: 思考: 资料充分,开始撰写回答
LangGraph Agent-->>User: "根据知识库规定报销流程分为以下3步..."
```
### Level 5: GraphRAG 集成 (基于图和关系的 RAG)
- **核心原理**: 结合知识图谱的结构化关系和向量检索的语义相似度,解决跨文档复杂关系推理问题。
- **实现指南**:
- 使用 `langchain_community.graphs` 模块构建知识图谱
- 配置本地大模型(如 `Gemma-4-E2B`)用于实体关系抽取
- 实现混合检索逻辑,结合向量相似度和图路径分析
---
## 📦 所需依赖与安装
除了基础的 LangChain 包外,在线检索模块为了支持重排和稀疏检索,还需要安装:
```bash
# 用于 Cross-Encoder 重排序模型 (如 BAAI/bge-reranker-base)
pip install sentence-transformers
# 用于 BM25 关键词混合检索
pip install rank_bm25
# 基础框架
pip install langchain langchain-core langchain-openai langchain-qdrant
# 与 rag_indexer 共享的依赖
pip install qdrant-client httpx
```
---
## 📂 架构与文件结构设计
```
app/rag/
├── __init__.py
├── retriever.py # 负责 Qdrant 的基础召回与混合检索
├── reranker.py # 负责加载 sentence-transformers 交叉编码器
├── query_transform.py # 负责基于 MultiQueryRetriever 的改写逻辑
├── pipeline.py # 组合上述组件,暴露出核心的 retrieve() 方法
└── tools.py # 将 Pipeline 包装成 LangChain Tool 供 Agent 调用
```
---
## 🔄 与 rag_indexer 集成
### 数据结构兼容性
- **向量存储**: rag_indexer 使用 Qdrant 存储子块向量app/rag 直接从相同集合读取
- **文档存储**: rag_indexer 使用 PostgreSQL 存储父块app/rag 通过 `ParentDocumentRetriever` 关联
- **嵌入模型**: 共享 `LlamaCppEmbedder` 确保向量空间一致性
### 配置共享
- **环境变量**: QDRANT_URL、QDRANT_API_KEY、DB_URI 等配置在两个模块间共享
- **集合名称**: 默认使用 "rag_documents" 集合,确保数据一致性
---
## 🚀 与现有系统整合调用 (Agentic RAG 实现)
基于目前 LangGraph 系统的架构,我们将摒弃将代码堆砌在一起的旧方式,而是利用 **LangChain Tools** 的特性将 RAG 优雅地注入系统:
1. **封装检索工具 (Tool)**:
从 `langchain.tools` 导入 `@tool` 装饰器。定义一个名为 `search_knowledge_base(query: str)` 的函数。在函数内部,实例化并调用我们在 `pipeline.py` 中写好的多路召回与重排逻辑。
2. **模型绑定 (Bind)**:
在 `app/agent.py` 或 `app/nodes/tool_call.py` 中,将这个工具引入,并通过 `llm.bind_tools([search_knowledge_base])` 绑定到现有的本地大模型实例上。
3. **状态机路由 (Graph Routing)**:
你的 LangGraph 状态机会像处理普通对话一样自动接管:当模型判断需要调用查阅规章制度或专业资料时,它会输出 `ToolCall` 消息,流转到 `tool_node` 执行上述的 RAG 检索逻辑并返回上下文。
这让你无需修改任何前端 Streamlit 流式代码,就能平滑升级为具备超级知识库检索能力的智能体 (Agent)
---
## 🎯 快速开始
```python
# 1. 初始化嵌入模型
from rag_indexer.embedders import LlamaCppEmbedder
embeddings = LlamaCppEmbedder()
# 2. 初始化语言模型(用于 RAG-Fusion
from langchain_openai import OpenAI
llm = OpenAI(
openai_api_base="http://localhost:8000/v1",
openai_api_key="no-key-needed",
model_name="Qwen2.5-7B-Instruct",
temperature=0.3,
)
# 3. 创建 RAG 流水线
from app.rag.pipeline import RAGPipeline, RAGLevel
pipeline = RAGPipeline(
embeddings=embeddings,
llm=llm,
config={
"collection_name": "rag_documents",
"rag_level": RAGLevel.FUSION.value,
"num_queries": 3,
"rerank_top_n": 5,
},
)
# 4. 执行检索
result = pipeline.retrieve("如何申请项目资金?")
# 5. 格式化上下文
context = pipeline.format_context(result.documents)
print(context)
```