# xep-rag-agent **Repository Path**: xep/xep-rag-agent ## Basic Information - **Project Name**: xep-rag-agent - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-21 - **Last Updated**: 2026-10-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # xep-rag-agent · 企业级 RAG 知识库平台(Demo) 基于 **Java 生态**的检索增强生成(RAG, Retrieval-Augmented Generation)知识库实战项目: 上传企业文档 → 自动解析切片 → 向量化存入 pgvector → 基于语义检索 + DeepSeek 生成可信回答(带原文出处)。 > 适合用来系统学习 RAG 工程落地:文档解析、切片策略、Embedding、向量检索、Prompt 组装、SSE 流式输出、多轮会话。 --- ## 一、技术架构 ``` ┌──────────────────────────────────────────────────────────────┐ │ Vue 3 + Element Plus │ │ 知识库管理 │ 文档管理(上传) │ 流式问答(引用溯源) │ └────────────────────────────┬─────────────────────────────────┘ │ HTTP / SSE ┌────────────────────────────▼─────────────────────────────────┐ │ Spring Boot 3 (Java 17) │ │ ┌──────────┐ ┌──────────┐ ┌───────────┐ ┌──────────────┐ │ │ │ 文档解析 │→│ 文本切片 │→│ Embedding │→│ 向量检索 │ │ │ │ Tika │ │重叠窗口 │ │ 豆包 2048 │ │ pgvector HNSW│ │ │ └──────────┘ └──────────┘ └───────────┘ └──────┬───────┘ │ │ │ │ │ Prompt 组装(资料+历史) ──→ DeepSeek(火山方舟) ──→ SSE 流式返回 │ └────────────────────────────┬─────────────────────────────────┘ │ ┌──────────────▼──────────────┐ │ PostgreSQL 16 + pgvector │ │ 业务表 / 向量列 / HNSW 索引 │ └─────────────────────────────┘ ``` | 层次 | 技术选型 | |---|---| | 前端 | Vue 3、Vite、Vue Router、Element Plus、Axios | | 后端 | Spring Boot 3.2、MyBatis-Plus 3.5、Lombok、Bean Validation | | 大模型 | 火山引擎方舟 SDK `volcengine-java-sdk-ark-runtime:2.0.28`(OpenAI 兼容协议) | | 对话模型 | DeepSeek(`deepseek-v4-pro-ga-260813`) | | 向量模型 | 豆包 Embedding(`doubao-embedding-vision-251215`,2048 维) | | 向量数据库 | PostgreSQL 16 + pgvector(HNSW 索引 + 余弦距离) | | 文档解析 | Apache Tika 3.3(统一封装 PDFBox 3 / POI 5,自动嗅探,支持上千种格式) | --- ## 二、RAG 核心流程(学习重点) ### 离线:文档入库(Indexing) 1. **文档解析**:Tika `AutoDetectParser` 按文件内容自动嗅探类型,PDF / Office / Markdown / 邮件等统一提取为纯文本,并支持内嵌文档递归解析([DocumentParser.java](rag-backend/src/main/java/com/xep/rag/rag/DocumentParser.java)) 2. **文本切片**:按段落拆分、贪心聚合约 500 字、相邻切片保留 100 字重叠,避免答案落在切片边界被截断([TextChunker.java](rag-backend/src/main/java/com/xep/rag/rag/TextChunker.java)) 3. **向量化**:按批(batch-size=10)调用豆包 Embedding,文本 → 2048 维向量([EmbeddingClient.java](rag-backend/src/main/java/com/xep/rag/llm/EmbeddingClient.java)) 4. **写入 pgvector**:向量列原生 **`vector(2048)`**。2048 维超过 pgvector HNSW/IVFFLAT 索引 2000 维上限,而 Demo/中小知识库切片行数有限,因此**不建 ANN 索引**,检索走 `ORDER BY embedding <=> ?` 全表精确扫描(召回率 100%);未来切片量到数十万级时,可将列改为 `halfvec(2048)` + HNSW(`halfvec_cosine_ops`)([DocumentChunkMapper.java](rag-backend/src/main/java/com/xep/rag/mapper/DocumentChunkMapper.java)) > 全过程在线程池中异步执行(`@Async("indexingExecutor")`),文档状态机:`PENDING → PROCESSING → SUCCESS / FAILED`。 ### 在线:问答生成(Retrieval + Generation) 1. **问题向量化**:用户问题调用同一个 Embedding 模型 2. **语义检索**:pgvector 余弦距离算子 `<=>` 取 TopK 相似切片,`score = 1 - distance`,按阈值(默认 0.30)过滤 3. **Prompt 组装**:系统提示词(含检索到的参考资料并编号)+ 最近 N 轮历史对话 + 当前问题([PromptBuilder.java](rag-backend/src/main/java/com/xep/rag/rag/PromptBuilder.java)) 4. **流式生成**:调用 DeepSeek,token 逐块通过 **SSE** 推给前端;约束模型只能用资料作答并标注 `[序号]` 引用,缓解幻觉 5. **引用溯源**:生成结束后把命中的文档名、片段、相似度返回前端展示 ```sql -- pgvector 相似度检索的核心 SQL SELECT id, doc_id, content, 1 - (embedding <=> cast(? AS vector)) AS score FROM rag_document_chunk WHERE kb_id = ? ORDER BY embedding <=> cast(? AS vector) LIMIT 5; ``` --- ## 三、数据库表 | 表 | 说明 | |---|---| | `rag_knowledge_base` | 知识库(多个知识库互相隔离) | | `rag_document` | 文档元数据 + 索引状态 | | `rag_document_chunk` | 切片内容 + 向量(核心表,HNSW 索引) | | `rag_chat_session` / `rag_chat_message` | 问答会话与消息(多轮历史) | 完整 DDL(按编号拆分,容器按文件名顺序执行):[docker/postgres/init/](docker/postgres/init/)(`00-init-schemas.sql` 建 schema/扩展,`01-rag-schema.sql` 建表) --- ## 四、快速开始 数据库结构:**数据库 `xep_agent` / Schema `rag_db`**(多项目可共用一个 PG 实例,按 schema 隔离)。 **方式 A:已有 pgvector 实例(本 Demo 采用,最省事)** ```bash # 确认 xep_agent 库存在(不存在则先 createdb xep_agent),然后按顺序执行: psql -d xep_agent -f docker/postgres/init/00-init-schemas.sql psql -d xep_agent -f docker/postgres/init/01-rag-schema.sql # 脚本会创建 rag_db schema、把 vector 扩展装进该 schema、建全部表 ``` > 本仓库开发时复用了本地另一个 pgvector 容器(:5432)。若你的 5432 已被占用,**不要再启动本项目 compose 的 postgres**(端口冲突),按上面方式手动初始化即可。 **方式 B:Docker 全新启动** ```bash docker compose up -d # 仅启动 pgvector(自动建库 xep_agent + 按顺序执行 docker/postgres/init 下脚本) ``` ### 2. 启动后端 确认 [application.yml](rag-backend/src/main/resources/application.yml) 中方舟 API Key(建议通过环境变量注入,避免硬编码): ```bash export ARK_API_KEY="你的方舟 API Key" cd rag-backend mvn spring-boot:run # 后端地址 http://localhost:8080 ``` 数据库连接可用环境变量覆盖:`PG_HOST / PG_PORT / PG_DB / PG_USER / PG_PASSWORD`。 ### 3. 启动前端 ```bash cd rag-frontend npm install npm run dev # 打开 http://localhost:5173 ``` ### 4. 体验 1. **知识库管理**:新建一个知识库(如「员工手册库」) 2. **文档管理**:选择知识库,上传 PDF / Word / Markdown 文件,等待状态变为「已完成」 3. **知识库问答**:提问后可看到流式回答与「参考资料」来源;支持多轮对话与历史会话切换 --- ## 五、主要 HTTP 接口 | 方法 | 路径 | 说明 | |---|---|---| | GET/POST/DELETE | `/api/kb` | 知识库增删改查 | | POST | `/api/documents/upload` | 上传文档(multipart,异步索引) | | GET | `/api/documents?kbId=` | 文档列表 | | POST | `/api/documents/{id}/reindex` | 重新索引 | | DELETE | `/api/documents/{id}` | 删除文档(含向量) | | POST | `/api/chat/stream` | RAG 流式问答(SSE) | | GET/POST | `/api/sessions` | 会话管理 | | GET | `/api/sessions/{id}/messages` | 会话历史消息 | SSE 事件:`token`(增量 token)、`references`(引用来源)、`session`(会话 ID)、`done`、`error`。 --- ## 六、从 Demo 到生产:进阶演进路线 本项目聚焦 RAG 主干,企业级落地还可逐步加入: 1. **检索质量** - Query 改写 / 多查询(Multi-Query)、HyDE - 混合检索:向量 + 全文(pgvector + tsvector / 倒排),RRF 融合 - Rerank 重排序模型(如豆包/CoHere reranker) - 父子切片、语义切片(按句子/标题层级) 2. **工程化** - 原文件与权限接入对象存储(TOS/OSS/MinIO) - 文档权限隔离、多租户、行级权限 - Embedding 失败重试、限流、幂等、分布式任务队列 - 知识库增量更新、向量与原文一致性校验 3. **Agent 化**:Function Calling / Tool Use、多知识库路由、联网检索、SQL 问答 4. **可观测**:检索命中率、引用准确率、回答点赞点踩反馈、LLM 调用链路追踪 5. **高并发**:连接池调优、读写分离、HNSW 参数调优、召回结果缓存 --- ## 七、常见问题 - **向量维度不匹配**:`vector(2048)` 必须与 Embedding 模型输出维度一致;更换模型需重建切片或新建知识库。 - **2048 维想建 HNSW 索引怎么办**:pgvector 的 HNSW/IVFFLAT 对 `vector` 类型上限 2000 维;切片量不大时无需建索引(全表精确扫描,召回率 100%),数据量大时把列改为 `halfvec(2048)`(上限 4000 维)再建 `halfvec_cosine_ops` 索引。 - **报 type "vector" does not exist**:扩展装在了别的 schema,而 JDBC `currentSchema=rag_db` 会把 search_path 限定为 rag_db;需把扩展装到 rag_db(`CREATE EXTENSION vector SCHEMA rag_db`)。 - **相似度阈值怎么调**:阈值过高容易"答不上来",过低引入噪声。可先看前端返回的命中 score 分布,再调整 `rag.retrieval.score-threshold`。 - **中文切片**:本 Demo 按字符而非 token 切片,参数在 `rag.chunk` 中调整。 - **API Key 安全**:不要把真实 Key 提交到代码仓库,生产环境统一走环境变量/配置中心。