forked from fangtianchen/algonotes_rag
161 lines
4.1 KiB
Markdown
161 lines
4.1 KiB
Markdown
# 🤖 RAG 查询管线详解
|
||
|
||
> 本文档详细描述 AlgoNotes RAG 的 Agent 驱动查询流程,包括工具定义、路由逻辑与生成策略。
|
||
|
||
---
|
||
|
||
## 📊 总览
|
||
|
||
```mermaid
|
||
graph TD
|
||
Q[用户提问] --> Agent[RAG Agent<br/>内嵌查询理解 Prompt]
|
||
Agent -->|1. 分析查询| Agent
|
||
Agent -->|2. 路由工具| Tools[内部工具集]
|
||
|
||
Tools --> SN[search_notes<br/>向量语义检索]
|
||
Tools --> ST[search_by_tags<br/>SQL 标签匹配]
|
||
Tools --> GF[get_file_content<br/>获取文档全文]
|
||
|
||
SN --> Agent
|
||
ST --> Agent
|
||
GF --> Agent
|
||
|
||
Agent -->|3. 结果处理| G[rerank_results<br/>重排序 + 去重]
|
||
G -->|处理后结果| Agent
|
||
Agent -->|4. 生成答案| A[答案 + 📎 溯源引用]
|
||
```
|
||
|
||
---
|
||
|
||
## 🧠 RAG Agent(`src/rag/agent.py`)
|
||
|
||
### 职责
|
||
|
||
RAG Agent 是查询管线的核心,负责:
|
||
1. **查询理解**:通过 system prompt 解析用户意图
|
||
2. **工具路由**:根据查询内容选择调用哪些工具
|
||
3. **结果融合**:合并多个工具的返回结果
|
||
4. **去重处理**:消除重复的检索结果
|
||
|
||
### System Prompt
|
||
|
||
RAG Agent 的 system prompt 内嵌查询理解逻辑,引导 Agent:
|
||
- 将用户问题重写为适合检索的关键词
|
||
- 判断应该使用哪些检索工具
|
||
- 根据语义、关键词返回的文件来源、文件名列表调取笔记全文
|
||
|
||
---
|
||
|
||
## 🔧 内部工具
|
||
|
||
> **注意**:以下工具是 RAG Agent 的内部工具,**不暴露给 MCP**。
|
||
> MCP 工具(`src/mcp/tools.py`)是独立的对外接口。
|
||
|
||
### 1. search_notes(向量语义检索)
|
||
|
||
```python
|
||
@tool
|
||
def search_notes(query: str, top_k: int = 5) -> list[Document]:
|
||
"""通过语义相似度搜索个人算法笔记。
|
||
|
||
Args:
|
||
query: 检索词(重写后的关键词形式)
|
||
top_k: 返回结果数量
|
||
|
||
Returns:
|
||
相关笔记片段列表,含 metadata
|
||
"""
|
||
```
|
||
|
||
**实现**:调用 `vector_store.search(query, k=top_k)`
|
||
|
||
### 2. search_by_tags(SQL 标签匹配)
|
||
|
||
```python
|
||
@tool
|
||
def search_by_tags(keyword: str) -> list[str]:
|
||
"""通过关键词检索笔记标签,返回匹配的文件名列表。
|
||
|
||
Args:
|
||
keyword: 标签关键词(如 "并查集"、"线段树")
|
||
|
||
Returns:
|
||
匹配的文件名列表
|
||
"""
|
||
```
|
||
|
||
**实现**:调用 `sql_store.search_by_tags(keyword)`,返回 filename 列表
|
||
|
||
### 3. get_file_content(获取文档全文)
|
||
|
||
```python
|
||
@tool
|
||
def get_file_content(filename: str) -> str:
|
||
"""根据文件名获取笔记全文。
|
||
|
||
Args:
|
||
filename: 文件名(如 "fenwick.md")
|
||
|
||
Returns:
|
||
笔记全文内容
|
||
"""
|
||
```
|
||
|
||
**实现**:调用 `file_store.read(filename)`
|
||
|
||
---
|
||
|
||
## 🔄 查询流程
|
||
|
||
### 步骤 1:查询理解
|
||
|
||
Agent 通过 system prompt 分析用户问题:
|
||
- 提取核心关键词
|
||
- 判断是否涉及具体题目
|
||
- 决定检索策略
|
||
|
||
### 步骤 2:工具路由
|
||
|
||
Agent 根据分析结果选择工具:
|
||
|
||
| 场景 | 调用工具 |
|
||
|------|----------|
|
||
| 一般算法问题 | `search_notes` → `get_file_content` |
|
||
| 查找特定标签 | `search_by_tags` → `get_file_content` |
|
||
| 查询特定文件 | `get_file_content` |
|
||
|
||
### 步骤 3:结果处理
|
||
|
||
Agent 调用 `rerank_results` 工具,对检索结果进行后处理:
|
||
- 重排序(按相关性或时间)
|
||
- 截断(保留 top_k 个结果)
|
||
|
||
### 步骤 4:答案生成
|
||
|
||
Agent 根据 `rerank_results` 处理后的结果 + 用户原始问题,由 LLM 直接生成答案,并注入溯源引用。
|
||
|
||
---
|
||
|
||
## 📝 溯源引用格式
|
||
|
||
生成的答案包含溯源引用,格式如下:
|
||
|
||
| 来源 | 格式 | 示例 |
|
||
|------|------|------|
|
||
| 个人笔记 | `[个人: filename#header]` | `[个人: fenwick.md#树状数组]` |
|
||
| 公共题库(如 CPGraph) | `[公共: problem_id]` | `[公共: P3372]` |
|
||
|
||
> CPGraph 由前端工具调用,由SKILL指导生成带双源引用的答案。
|
||
|
||
---
|
||
|
||
## ⚙️ 配置依赖
|
||
|
||
```toml
|
||
[cp_graph]
|
||
enabled = false # 是否启用公共题库
|
||
url = "https://mcp.cpgraph.top/mcp" # CPGraph MCP 地址
|
||
```
|
||
|
||
- `enabled = true`:调用 CPGraph MCP 服务,后续可能添加用户知识体系分析等功能
|