Files
AIclinicalresearch/docs/02-通用能力层/03-RAG引擎/02-pgvector替换Dify计划.md
HaHafeng 40c2f8e148 feat(rag): Complete RAG engine implementation with pgvector
Major Features:
- Created ekb_schema (13th schema) with 3 tables: KB/Document/Chunk
- Implemented EmbeddingService (text-embedding-v4, 1024-dim vectors)
- Implemented ChunkService (smart Markdown chunking)
- Implemented VectorSearchService (multi-query + hybrid search)
- Implemented RerankService (qwen3-rerank)
- Integrated DeepSeek V3 QueryRewriter for cross-language search
- Python service: Added pymupdf4llm for PDF-to-Markdown conversion
- PKB: Dual-mode adapter (pgvector/dify/hybrid)

Architecture:
- Brain-Hand Model: Business layer (DeepSeek) + Engine layer (pgvector)
- Cross-language support: Chinese query matches English documents
- Small Embedding (1024) + Strong Reranker strategy

Performance:
- End-to-end latency: 2.5s
- Cost per query: 0.0025 RMB
- Accuracy improvement: +20.5% (cross-language)

Tests:
- test-embedding-service.ts: Vector embedding verified
- test-rag-e2e.ts: Full pipeline tested
- test-rerank.ts: Rerank quality validated
- test-query-rewrite.ts: Cross-language search verified
- test-pdf-ingest.ts: Real PDF document tested (Dongen 2003.pdf)

Documentation:
- Added 05-RAG-Engine-User-Guide.md
- Added 02-Document-Processing-User-Guide.md
- Updated system status documentation

Status: Production ready
2026-01-21 20:24:29 +08:00

543 lines
14 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.
# 通用能力层:知识库引擎 pgvector 实现计划
> **文档版本:** v2.0
> **创建日期:** 2026-01-19
> **重构日期:** 2026-01-20从 PKB 模块提升为通用能力层)
> **预计工期:** 2 周10个工作日
> **前置条件:** ✅ pgvector 0.8.1 已安装
> **目标:** 构建通用知识库引擎,用 PostgreSQL + pgvector 原生 RAG 替代 Dify服务全平台业务模块
---
## 🎯 项目定位变更
### 从业务模块到通用能力层
| 维度 | 原方案PKB 模块) | 新方案(通用能力层) |
|------|-------------------|---------------------|
| **定位** | PKB 模块内部改造 | 平台级通用能力 |
| **代码位置** | `modules/pkb/services/` | `common/rag/` |
| **使用范围** | 仅 PKB 模块 | PKB、AIA、ASL、RVW 等 |
| **扩展性** | 有限 | 高度可扩展 |
### 受益模块
| 模块 | 使用场景 | 优先级 |
|------|----------|--------|
| **PKB** 个人知识库 | 知识库管理、RAG 问答 | P0首个接入 |
| **AIA** AI智能问答 | @知识库 问答、附件理解 | P0 |
| **ASL** AI智能文献 | 文献库检索、智能综述 | P1 |
| **RVW** 稿件审查 | 稿件与文献对比、查重 | P1 |
---
## 📊 整体难度评估
### 总体评估:⭐⭐⭐ 中等难度
| 评估维度 | 难度 | 说明 |
|----------|------|------|
| **数据库设计** | ⭐⭐ 低 | Prisma schema 直接写pgvector 已就绪 |
| **Embedding 服务** | ⭐⭐ 低 | 调用阿里云 API简单封装 |
| **文档切片** | ⭐⭐ 低 | 成熟方案RecursiveCharacterTextSplitter |
| **临床要素提取** | ⭐⭐⭐ 中 | 需要调优 Prompt处理 JSON 异常 |
| **向量检索** | ⭐⭐⭐ 中 | pgvector SQL 语法需要学习 |
| **混合检索RRF** | ⭐⭐⭐ 中 | 核心算法,需要调优 |
| **通用 API 设计** | ⭐⭐⭐ 中 | 需要考虑多模块复用 |
| **服务替换** | ⭐⭐⭐⭐ 中高 | 需要保持 API 兼容,测试覆盖 |
| **数据迁移** | ⭐⭐⭐ 中 | 现有文档需重新向量化 |
**综合评估**:技术上完全可行,主要挑战在于**通用 API 设计**、**服务替换的平滑过渡**和**检索效果调优**。
---
## 🔥 核心挑战分析
### 挑战 1通用 API 设计 🔴 高优先级
**问题描述**
- 需要设计一套通用 API满足多模块需求
- 不同模块可能有不同的检索策略
- 需要支持多知识库联合检索
**应对策略**
- 设计 `KnowledgeBaseEngine` 统一入口类
- 提供灵活的配置选项chunkSize、topK、filters 等)
- 支持 `kbIds: string[]` 多知识库检索
**关键代码**
```typescript
// common/rag/KnowledgeBaseEngine.ts
export class KnowledgeBaseEngine {
// 文档入库
async ingestDocument(params: IngestParams): Promise<IngestResult>;
// 混合检索(通用)
async search(params: SearchParams): Promise<SearchResult[]>;
// RAG 问答(通用)
async chat(params: ChatParams): Promise<ChatResult>;
}
```
---
### 挑战 2混合检索效果调优 🔴 高风险
**问题描述**
- 替换 Dify 后,检索效果可能下降
- 需要调优向量检索 + 关键词检索的权重
- RRF 参数k 值)需要实验确定
**应对策略**
- 准备测试数据集100+ 查询)
- 建立效果评估指标Recall@K, MRR
- 先用小批量数据验证,再全量迁移
**预留时间**2 天专门用于调优
---
### 挑战 3临床要素提取的准确性 🟡 中风险
**问题描述**
- LLM 提取的 JSON 可能格式错误
- PICO、用药方案等字段提取不完整
- 不同类型文献RCT/综述/病例)提取策略不同
**应对策略**
- 三层 JSON 解析容错(直接解析 → 提取代码块 → LLM修复
- 字段级校验(必填字段、类型校验)
- 分文献类型设计 Prompt
**预留时间**1 天用于 Prompt 调优
---
### 挑战 4服务替换的兼容性 🟡 中风险
**问题描述**
- PKB 模块需要保持 API 接口不变(前端零修改)
- `searchKnowledgeBase()` 返回格式需兼容
- 文档上传流程需要无缝切换
**应对策略**
- 定义适配层,转换返回格式
- 新旧服务并行运行,灰度切换
- 充分测试所有使用场景
**预留时间**1 天专门用于兼容性测试
---
## 📅 详细开发计划
### 总览时间线
```
Week 1: 通用能力层核心开发
├── Day 1: 数据库设计 + Prisma 迁移
├── Day 2: Embedding 服务 + 切片服务
├── Day 3: 临床要素提取服务Prompt 调优)
├── Day 4: 向量检索服务pgvector SQL
├── Day 5: 混合检索 + RRF 融合 + 统一入口
Week 2: PKB 模块接入 + 测试 + 迁移
├── Day 6: PKB knowledgeBaseService 改造
├── Day 7: PKB documentService 改造
├── Day 8: 集成测试 + 效果调优
├── Day 9: 数据迁移(现有文档向量化)
├── Day 10: 清理 + 文档 + 上线
```
---
### Day 1数据库设计 + Prisma 迁移
**目标**:创建向量存储的数据表(通用 schema
**任务清单**
- [ ] 创建 `ekb_schema`Enterprise Knowledge Base
- [ ] 设计 `EkbDocument` 表(通用文档,含临床数据 JSONB
- [ ] 设计 `EkbChunk` 表(通用切片,含 pgvector 字段)
- [ ] 编写 Prisma schema
- [ ] 运行 `prisma migrate dev`
- [ ] 创建 HNSW 索引(手动 SQL
- [ ] 验证向量插入和查询
**交付物**
- `prisma/schema.prisma` 更新
- `migrations/xxx_add_ekb_tables.sql`
- 索引创建脚本
**预计工时**4-6 小时
**关键代码**
> 📌 **数据模型详见**[04-数据模型设计.md](./04-数据模型设计.md)
>
> 包含完整的 EkbDocument / EkbChunk Prisma Schema 和索引设计。
---
### Day 2Embedding 服务 + 切片服务
**目标**:实现通用的文本向量化和文档切片服务
**任务清单**
- [ ] 创建 `common/rag/services/EmbeddingService.ts`
- [ ] 创建 `common/rag/services/ChunkService.ts`
- [ ] 单元测试Embedding API 调用
- [ ] 单元测试:切片效果验证
- [ ] 环境变量配置DASHSCOPE_API_KEY
**交付物**
- `backend/src/common/rag/services/EmbeddingService.ts`
- `backend/src/common/rag/services/ChunkService.ts`
- 单元测试文件
**预计工时**4-6 小时
**关键代码**
```typescript
// common/rag/services/EmbeddingService.ts
export class EmbeddingService {
private apiKey: string;
private baseUrl = 'https://dashscope.aliyuncs.com/api/v1/services/embeddings/text-embedding/text-embedding';
async embed(text: string): Promise<number[]> { ... }
async embedBatch(texts: string[]): Promise<number[][]> { ... }
async embedQuery(query: string): Promise<number[]> { ... }
}
// common/rag/services/ChunkService.ts
export class ChunkService {
splitDocument(
text: string,
options: { chunkSize: number; chunkOverlap: number }
): Chunk[] { ... }
detectSections(text: string): Section[] { ... }
}
```
---
### Day 3临床要素提取服务
**目标**:实现 PICO、用药方案等临床数据的 AI 提取(可选功能)
**任务清单**
- [ ] 创建 `common/rag/services/ClinicalExtractionService.ts`
- [ ] 设计提取 Prompt
- [ ] 实现三层 JSON 解析容错
- [ ] 测试不同类型文献
- [ ] Prompt 调优
**交付物**
- `backend/src/common/rag/services/ClinicalExtractionService.ts`
- 测试用例
**预计工时**6-8 小时(含 Prompt 调优)
---
### Day 4向量检索服务
**目标**:实现基于 pgvector 的向量检索
**任务清单**
- [ ] 创建 `common/rag/services/VectorSearchService.ts`
- [ ] 实现向量检索(余弦相似度)
- [ ] 实现关键词检索PostgreSQL FTS
- [ ] 测试检索性能
- [ ] 优化查询(索引使用验证)
**交付物**
- `backend/src/common/rag/services/VectorSearchService.ts`
- 性能测试报告
**预计工时**6 小时
**关键 SQL**
```sql
-- 向量检索(支持多知识库)
SELECT
c.id,
c.content,
d.filename,
d."kbId",
1 - (c.embedding <=> $1::vector) as score
FROM "ekb_schema"."EkbChunk" c
JOIN "ekb_schema"."EkbDocument" d ON c."documentId" = d.id
WHERE d."kbId" = ANY($2::text[]) -- 支持多知识库
ORDER BY c.embedding <=> $1::vector
LIMIT $3;
```
---
### Day 5混合检索 + RRF 融合 + 统一入口
**目标**:实现完整的混合检索和统一入口类
**任务清单**
- [ ] 实现 RRFReciprocal Rank Fusion算法
- [ ] 实现并发三路检索
- [ ] 创建 `KnowledgeBaseEngine` 统一入口类
- [ ] 导出通用 API
- [ ] 效果评估
**交付物**
- `backend/src/common/rag/KnowledgeBaseEngine.ts`
- `backend/src/common/rag/index.ts`
- 效果评估报告
**预计工时**6-8 小时
**RRF 算法**
```typescript
// common/rag/utils/rrfFusion.ts
export function rrfFusion(
vectorResults: SearchResult[],
keywordResults: SearchResult[],
k: number = 60
): SearchResult[] {
const scoreMap = new Map<string, number>();
vectorResults.forEach((r, idx) => {
const rrfScore = 1 / (k + idx + 1);
scoreMap.set(r.id, (scoreMap.get(r.id) || 0) + rrfScore);
});
keywordResults.forEach((r, idx) => {
const rrfScore = 1 / (k + idx + 1);
scoreMap.set(r.id, (scoreMap.get(r.id) || 0) + rrfScore);
});
return Array.from(scoreMap.entries())
.sort((a, b) => b[1] - a[1])
.map(([id, score]) => ({ id, score, ...getResultById(id) }));
}
```
---
### Day 6-7PKB 模块接入(服务替换)
**目标**PKB 模块作为首个业务模块接入通用知识库引擎
**Day 6 任务**
- [ ] 修改 `knowledgeBaseService.ts` - 检索替换
- [ ] 移除 `difyClient.retrieveKnowledge()` 调用
- [ ] 使用 `KnowledgeBaseEngine.search()`
- [ ] 保持返回格式兼容
**Day 7 任务**
- [ ] 修改 `documentService.ts` - 上传替换
- [ ] 移除 `difyClient.uploadDocumentDirectly()` 调用
- [ ] 使用 `KnowledgeBaseEngine.ingestDocument()`
- [ ] 移除 Dify 状态轮询逻辑
**关键修改**
```typescript
// modules/pkb/services/knowledgeBaseService.ts
// 修改前Dify
const results = await difyClient.retrieveKnowledge(
knowledgeBase.difyDatasetId,
query,
{ retrieval_model: { search_method: 'semantic_search', top_k: topK } }
);
// 修改后(通用知识库引擎)
import { KnowledgeBaseEngine } from '@/common/rag';
const kbEngine = new KnowledgeBaseEngine(prisma);
const results = await kbEngine.search({
kbIds: [kbId],
query,
topK
});
// 格式转换(保持前端兼容)
return {
query: { content: query },
records: results.map((r, idx) => ({
segment_id: r.id,
document_id: r.documentId,
document_name: r.documentName,
position: idx + 1,
score: r.score,
content: r.content,
})),
};
```
---
### Day 8集成测试 + 效果调优
**目标**:端到端测试,确保功能正常
**任务清单**
- [ ] 前端测试:创建知识库
- [ ] 前端测试:上传文档
- [ ] 前端测试RAG 检索问答
- [ ] 效果对比Dify vs pgvector 检索质量
- [ ] 性能测试:检索延迟
- [ ] Bug 修复
**交付物**
- 测试报告
- Bug 修复记录
**预计工时**8 小时
---
### Day 9数据迁移
**目标**:将现有知识库文档迁移到新表并向量化
**任务清单**
- [ ] 编写迁移脚本
- [ ] 批量向量化现有文档
- [ ] 验证迁移完整性
- [ ] 验证检索效果
**交付物**
- `scripts/migrate-to-ekb.ts`
- 迁移日志
**预计工时**6 小时
---
### Day 10清理 + 文档 + 上线
**目标**:清理遗留代码,更新文档,正式上线
**任务清单**
- [ ] 标记 `DifyClient.ts` 为废弃(暂不删除,保留回滚能力)
- [ ] 更新通用能力层文档
- [ ] 更新 PKB 模块文档
- [ ] 更新环境变量文档
- [ ] 代码 Review
- [ ] 合并到主分支
**交付物**
- 更新后的文档
- 清理后的代码
**预计工时**4 小时
---
## ⚠️ 风险评估与应对
### 风险矩阵
| 风险 | 概率 | 影响 | 等级 | 应对措施 |
|------|------|------|------|----------|
| 检索效果下降 | 中 | 高 | 🔴 | 效果评估 + 参数调优 + 回滚方案 |
| API 兼容性问题 | 低 | 高 | 🟡 | 格式转换层 + 充分测试 |
| Embedding API 限流 | 中 | 中 | 🟡 | 并发控制 + 重试机制 |
| 迁移数据丢失 | 低 | 高 | 🟡 | 备份 + 验证 + 回滚 |
| 性能下降 | 低 | 中 | 🟢 | 索引优化 + 缓存 |
### 回滚方案
如果新方案效果不理想:
1. 保留 `difyDatasetId` 字段,随时切回 Dify
2. 新旧服务通过 Feature Flag 切换
3. 灰度发布:先 10% 用户使用 pgvector
---
## 📊 资源需求
### 人力资源
| 角色 | 工作量 | 说明 |
|------|--------|------|
| 后端开发 | 10 人天 | 核心开发 |
| 测试 | 2 人天 | 集成测试 + 效果评估 |
| **总计** | **12 人天** | 约 2 周 |
### 技术资源
| 资源 | 用途 | 成本 |
|------|------|------|
| 阿里云 DashScope | Embedding API | ~¥50/月 |
| 阿里云 DashScope | Rerank API可选 | ~¥20/月 |
| PostgreSQL | 已有 | ¥0 |
---
## ✅ 验收标准
### 功能验收
- [ ] 通用 API`KnowledgeBaseEngine` 正常工作
- [ ] PKB 接入:创建知识库不依赖 Dify
- [ ] PKB 接入:上传文档本地处理 + 向量化
- [ ] PKB 接入RAG 检索效果 ≥ Dify
- [ ] PKB 接入:全文阅读模式正常
- [ ] PKB 接入:批处理模式正常
### 性能验收
- [ ] 检索延迟:< 500ms95 分位)
- [ ] 上传处理:< 60s/文档(平均)
- [ ] 向量化吞吐:> 100 文档/小时
### 质量验收
- [ ] 检索召回率:≥ 80%(测试集)
- [ ] 通用能力层代码独立,无业务耦合
- [ ] 文档更新完整
---
## 📝 附录
### A. 相关文档
- [知识库引擎架构设计](./01-知识库引擎架构设计.md)
- [文档处理引擎设计方案](../02-文档处理引擎/01-文档处理引擎设计方案.md)
- [通用能力层清单](../00-通用能力层清单.md)
### B. 环境变量配置
```bash
# .env 新增
DASHSCOPE_API_KEY=sk-xxx # 阿里云 DashScope API Key
EMBEDDING_MODEL=text-embedding-v3 # Embedding 模型
EMBEDDING_DIMENSION=1024 # 向量维度
RERANK_MODEL=gte-rerank # Rerank 模型(可选)
```
### C. 依赖更新
```json
// package.json
{
"dependencies": {
"p-queue": "^8.0.0" // 并发控制
}
}
```
---
**文档维护**:技术架构师
**原文档**`03-业务模块/PKB-个人知识库/04-开发计划/01-Dify替换为pgvector开发计划.md`
**最后更新**2026-01-20