accounts/docs/rag-system-design.md

163 lines
5.9 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.

# 基于 Go 的 RAG 系统设计
本文档描述一个使用 Go 实现的 Retrieval Augmented Generation (RAG) 系统方案满足多仓库文档同步、Markdown 解析与分块、向量化存储以及问答检索的需求。
## 1. 数据源同步
- **多仓库配置**:支持在配置文件中声明多个 GitHub 仓库及其关注路径,例如:
- `repoA/docs/`
- `repoB/guides/`
- `repoC/tutorials/`
- **同步方式**:使用 `git clone` / `git pull` 将远程仓库同步到本地,定时任务或 Webhook 触发。
- **增量更新**:检测新增或修改的 Markdown 文档,触发后续嵌入流程。
## 2. Markdown 处理与分块
- 使用 `goldmark``blackfriday` 将 Markdown 渲染为纯文本。
- 对文档按照 500~1000 tokens 分块,保存每块的顺序和位置信息。
- 每个分块生成唯一 `chunk_id` 以便回溯源文档位置。
## 3. 向量化
- 默认嵌入模型:
- [bge-m3](https://github.com/BAAI-bge/): 本地部署HTTP 服务返回 1024 维向量。
- [OpenAI `text-embedding-3-large`](https://platform.openai.com/docs/guides/embeddings): 通过 OpenAI API 获取 1024 维向量。
- 统一的 `Embed(text string) ([]float32, error)` 接口屏蔽具体实现,可在配置中切换模型。
## 4. 数据库设计
使用 PostgreSQL + [pgvector](https://github.com/pgvector/pgvector)。初始化步骤:
1. 在目标数据库中启用扩展:
```sql
CREATE EXTENSION IF NOT EXISTS vector;
```
2. 按以下 SQL 创建存储向量的表及索引:
```sql
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
repo TEXT NOT NULL, -- 来源仓库
path TEXT NOT NULL, -- 文件路径
chunk_id INT NOT NULL,
content TEXT NOT NULL,
embedding VECTOR(1024), -- 向量
metadata JSONB -- 额外信息:标签/更新时间等
);
-- 向量索引
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);
-- 元数据索引
CREATE INDEX idx_documents_metadata ON documents USING gin (metadata);
```
连接字符串示例:`postgres://user:password@127.0.0.1:5432`。
## 5. 检索与问答流程
1. 用户提出问题,服务端调用 `Embed()` 对问题生成向量。
2.`documents` 表中通过 `cosine` 相似度检索 Top K 的分块。
3. 将检索结果拼装为 Prompt调用 GPT/Claude 等大模型生成回答。
4. 返回答案并附带来源文档信息以便追溯。
### 5.1 前端 AskAIDialog 调用流程
1. 用户在 `AskAIDialog` 中输入问题,`handleAsk` 会先做去空格、去尾标点等规整并使用防抖避免短时间内重复发送。
2. 若 10 秒内命中过去问题的缓存,则直接返回缓存答案;否则把规整后的问题与最近对话历史组合为 `history`POST 到 `/api/rag/query`,请求设置超时并以流式方式返回结果。
3. 流式结果会实时更新聊天记录,若返回 `answer``chunks`,则通过 `SourceHint` 展示检索到的来源。
4.`answer` 为空或没有检索结果时,会在控制台记录回退原因,并调用 `/api/askai` 获取普通 AI 回答,同样带有超时限制。
5. 最终的回答写入缓存并通过 `ChatBubble` 组件显示给用户,形成完整的 RAG 聊天流程。
## 6. Go 代码模块划分
```
rag-server/internal/rag/
├── config/ # 仓库与模型配置
├── sync/ # GitHub 同步逻辑
├── ingest/ # Markdown 解析与分块
├── embed/ # 向量化接口实现
├── store/ # PostgreSQL + pgvector 操作封装
└── api/ # REST/gRPC 接口,提供问答与同步触发
```
各模块通过 `go-pg`/`pgx`、`go-git` 等库实现,协程与通道用于提升并行处理能力。
## 7. 未来扩展
- 支持更多文件格式,如 PDF、HTML。
- 嵌入向量批量写入以提升效率。
- 引入缓存与摘要生成,进一步优化响应速度。
以上设计为后续实现提供结构化指导,可在项目中逐步落地。
## 8. 同步与查询测试
### 8.1 启动依赖服务
```bash
docker run -d --name pgvector \
-e POSTGRES_PASSWORD=password \
-p 5432:5432 \
ankane/pgvector:latest
docker run -d --name redis -p 6379:6379 redis
```
### 8.2 配置 rag.yaml
```yaml
redis:
addr: "127.0.0.1:6379"
password: ""
module: "moonshotai/Kimi-K2-Instruct"
vectordb:
pgurl: "postgres://user:password@127.0.0.1:5432"
datasources:
- name: Xstream
repo: https://github.com/svc-design/Xstream
path: docs
- name: XControl
repo: https://github.com/svc-design/XControl
path: docs
- name: documents
repo: https://github.com/svc-design/documents
```
### 8.3 运行同步
```bash
# 同步并处理所有 Markdown 文件
./xcontrol-cli --config rag.yaml
```
该命令会克隆或更新数据源仓库,扫描 Markdown 文件,并逐个解析、分块、调用 BGE Embed 并通过 `/api/rag/upsert` 写入数据库。
### 8.4 手动测试 Upsert 接口
在同步流程之外,也可以通过 `curl` 手动向 `/api/rag/upsert` 写入一条记录:
> 默认情况下RAG 服务监听 `127.0.0.1:8090`,因此以下示例均以
> `http://localhost:8090` 为基础地址。
```bash
curl -X POST http://localhost:8090/api/rag/upsert \
-H "Content-Type: application/json" \
-d '{"docs":[{"repo":"example","path":"doc.md","chunk_id":1,"content":"hello","embedding":[0.1,0.2],"metadata":{},"content_sha":"abc"}]}'
```
若向量数据库未就绪,接口会返回 `error` 字段提示连接问题。
### 8.5 查询接口
同步完成后,可通过 curl 测试 `/api/rag/query`
```bash
curl -X POST http://localhost:8090/api/rag/query \
-H "Content-Type: application/json" \
-d '{"question": "What is XControl?"}'
```
请求体必须包含 `question` 字段。若数据写入成功,将返回相关的 `chunks` 列表;若返回 `{"chunks":null}`,请检查同步日志、数据库连接与配置文件是否正确。