Files
AIclinicalresearch/docs/02-通用能力层/03-RAG引擎/01-知识库引擎架构设计.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

726 lines
36 KiB
Markdown
Raw Permalink 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.
# 知识库引擎架构设计
> **文档版本:** v1.2
> **创建日期:** 2026-01-20
> **最后更新:** 2026-01-20
> **能力定位:** 通用能力层
> **状态:** 🔄 升级中Dify → PostgreSQL + pgvector
> **核心原则:** 提供基础能力(乐高积木),不做策略选择
---
## 📋 概述
### 能力定位
知识库引擎是平台的**核心通用能力**,提供知识库相关的**基础能力(乐高积木)**,供业务模块根据场景自由组合。
### ⭐ 核心设计原则
```
┌─────────────────────────────────────────────────────────────┐
│ │
│ ✅ 提供基础能力(乐高积木) │
│ ❌ 不做策略选择(组装方案由业务模块决定) │
│ ⚡️ 入库必须异步(防止 HTTP 超时) │
│ 💰 提取按需开启(控制 LLM 调用成本) │
│ │
│ 原因: │
│ • 不同业务场景需要不同的知识库使用策略 │
│ • 小知识库10个文件可能直接全文塞给 LLM 更好 │
│ • 大知识库1000+文件)必须用 RAG 向量检索 │
│ • 有的场景需要 摘要筛选 → Top-K 全文 的两阶段策略 │
│ • 策略选择是业务逻辑,不是基础设施 │
│ │
└─────────────────────────────────────────────────────────────┘
```
### 基础能力清单
| 能力分类 | 基础能力 | 说明 |
|----------|----------|------|
| **文档入库** | `submitIngestTask()` | ⚡️ 异步入库,返回 taskId |
| | `getIngestStatus()` | 获取入库任务状态和进度 |
| **全文获取** | `getDocumentFullText()` | 获取单个文档全文 |
| | `getAllDocumentsText()` | 获取知识库所有文档全文 |
| **摘要获取** | `getDocumentSummary()` | 获取单个文档摘要 |
| | `getAllDocumentsSummaries()` | 获取知识库所有文档摘要 |
| **向量检索** | `vectorSearch()` | 基于 pgvector 的语义检索 |
| **关键词检索** | `keywordSearch()` | 基于 pg_bigm 的中文精确检索 |
| **混合检索** | `hybridSearch()` | 向量 + 关键词 + RRF 融合 |
| **重排序** | `rerank()` | 🆕 基于 Qwen-Rerank 的精排序 |
| **管理操作** | `deleteDocument()` | 删除文档 |
| | `clearKnowledgeBase()` | 清空知识库 |
> ⚠️ **注意**:不提供 `chat()` 方法!问答策略由业务模块根据场景决定。
---
## 🎯 业务模块策略选择
知识库引擎提供基础能力,业务模块根据场景自由组合:
### 策略示例
```
┌─────────────────────────────────────────────────────────────┐
│ 业务模块层(策略选择) │
├─────────────────────────────────────────────────────────────┤
│ │
│ PKB 个人知识库 │
│ ├─ 小知识库(< 20 文档)→ 全文模式 │
│ │ getAllDocumentsText() → 直接塞给 LLM │
│ └─ 大知识库100+ 文档)→ RAG 模式 │
│ hybridSearch() → 检索 Top-K → LLM 回答 │
│ │
│ AIA AI智能问答 │
│ └─ 摘要筛选 + Top-K 全文 │
│ getAllDocumentsSummaries() → LLM 筛选 Top 5 │
│ → getDocumentFullText() × 5 → LLM 回答 │
│ │
│ ASL 智能文献 │
│ └─ 向量检索 + Rerank │
│ vectorSearch(topK=50) → Rerank(topK=10) → 返回 │
│ │
│ RVW 稿件审查 │
│ └─ 全文比对查重 │
│ getAllDocumentsText() → 逐篇相似度计算 │
│ │
├─────────────────────────────────────────────────────────────┤
│ 通用能力层(提供积木) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 全文获取 │ │ 摘要获取 │ │ 向量检索 │ │ 关键词检索│ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 文档入库 │ │ 混合检索 │ │ 文档删除 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────┘
```
### 代码示例
#### 场景 1PKB 小知识库10个文件→ 全文模式
```typescript
// PKB 模块:小知识库直接全文
async function pkbSmallKbChat(kbId: string, query: string) {
const kbEngine = new KnowledgeBaseEngine(prisma);
// 获取所有文档全文
const docs = await kbEngine.getAllDocumentsText(kbId);
// 直接塞给 LLM
const context = docs.map(d => `## ${d.filename}\n${d.extractedText}`).join('\n\n---\n\n');
const systemPrompt = `你是医学专家。以下是知识库的完整内容:\n\n${context}`;
return llmChat(systemPrompt, query);
}
```
#### 场景 2AIA 摘要筛选 + Top-K 全文
```typescript
// AIA 模块:摘要筛选 + 全文精读
async function aiaSmartChat(kbIds: string[], query: string) {
const kbEngine = new KnowledgeBaseEngine(prisma);
// 1. 获取所有文档摘要
const summaries = await kbEngine.getAllDocumentsSummaries(kbIds);
// 2. LLM 筛选最相关的 Top 5 文档
const topDocIds = await llmSelectTopK(summaries, query, 5);
// 3. 获取 Top 5 文档全文
const fullTexts = await Promise.all(
topDocIds.map(id => kbEngine.getDocumentFullText(id))
);
// 4. 基于全文回答
const context = fullTexts.map(d => `## ${d.filename}\n${d.text}`).join('\n\n');
return llmChat(context, query);
}
```
#### 场景 3ASL 大规模文献检索
```typescript
// ASL 模块:向量检索 + Rerank
async function aslLiteratureSearch(kbIds: string[], query: string) {
const kbEngine = new KnowledgeBaseEngine(prisma);
// 1. 向量检索 Top 50
const candidates = await kbEngine.vectorSearch(kbIds, query, 50);
// 2. Rerank 精排 Top 10
const reranked = await rerankService.rerank(candidates, query, 10);
// 3. 返回带引用的结果
return reranked.map(r => ({
content: r.content,
source: r.documentName,
score: r.score,
}));
}
```
#### 场景 4RVW 稿件查重
```typescript
// RVW 模块:全文比对
async function rvwPlagiarismCheck(manuscriptText: string, kbId: string) {
const kbEngine = new KnowledgeBaseEngine(prisma);
// 获取所有文献全文
const docs = await kbEngine.getAllDocumentsText(kbId);
// 逐篇比对相似度
const similarities = docs.map(d => ({
document: d,
similarity: calculateTextSimilarity(manuscriptText, d.extractedText),
}));
// 返回可疑重复段落
return similarities
.filter(s => s.similarity > 0.3)
.sort((a, b) => b.similarity - a.similarity);
}
```
---
## 🏗️ 整体架构
### 架构图
```
┌─────────────────────────────────────────────────────────────────┐
│ 业务模块层(策略选择) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ PKB │ │ AIA │ │ ASL │ │ RVW │ │
│ │ 全文/RAG │ │摘要+全文 │ │向量+Rerank│ │ 全文比对 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │
│ │ 根据场景自由组合基础能力 │ │
│ └────────────┴────────────┴────────────┘ │
│ │ │
│ ▼ │
├─────────────────────────────────────────────────────────────────┤
│ 知识库引擎(通用能力层 - 提供积木) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ KnowledgeBaseEngine │ │
│ │ 提供基础能力,不做策略选择 │ │
│ ├─────────────────────────────────────────────────────────┤ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────┐ │ │
│ │ │ 文档入库能力 │ │ │
│ │ │ ingestDocument() / ingestBatch() │ │ │
│ │ └────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────┐ │ │
│ │ │ 内容获取能力 │ │ │
│ │ │ getDocumentFullText() / getAllDocumentsText() │ │ │
│ │ │ getDocumentSummary() / getAllDocumentsSummaries()│ │ │
│ │ └────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────┐ │ │
│ │ │ 检索能力 │ │ │
│ │ │ vectorSearch() / keywordSearch() / hybridSearch()│ │ │
│ │ └────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 文档处理引擎(独立通用能力) │ │
│ │ PDF/Word/Excel/PPT → Markdown │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ 数据存储层 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ PostgreSQL + pgvector (Postgres-Only) │ │
│ │ ┌───────────────┐ ┌───────────────────────────┐ │ │
│ │ │ EkbDocument │ │ EkbChunk │ │ │
│ │ │ (文档 + JSONB)│───>│ (切片 + vector(1024)) │ │ │
│ │ └───────────────┘ └───────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 🏗️ 关键技术决策
### 1. ⚡️ 入库异步化Postgres-Only 架构)
文档入库是耗时操作10-60秒**必须异步处理**以避免 HTTP 超时。
```typescript
// 提交入库任务(立即返回 taskId
const { taskId } = await kbEngine.submitIngestTask({
kbId: 'kb-123',
file: pdfBuffer,
filename: 'research.pdf',
});
// 轮询任务状态
const status = await kbEngine.getIngestStatus(taskId);
// { status: 'processing', progress: 45, error: null }
```
**技术实现**:基于 pg-boss 队列,详见 [Postgres-Only异步任务处理指南](../Postgres-Only异步任务处理指南.md)
### 2. 💰 成本控制策略
| 行为 | 默认 | LLM 调用 | 成本 |
|------|------|----------|------|
| 解析 + 切片 + 向量化 | ✅ 开启 | ❌ 无 | 低(仅 Embedding API |
| 摘要生成 | ❌ 关闭 | ✅ 有 | 中 |
| 临床要素提取PICO | ❌ 关闭 | ✅ 有 | 高 |
```typescript
// 默认行为:只做向量化(零 LLM 成本)
await kbEngine.submitIngestTask({ kbId, file, filename });
// ASL 智能文献场景:开启完整提取
await kbEngine.submitIngestTask({
kbId, file, filename,
options: {
enableSummary: true, // 💰 可选
enableClinicalExtraction: true // 💰 可选
}
});
```
### 3. 🔧 中文关键词检索方案
PostgreSQL 默认分词对中文支持不佳,采用 **pg_bigmBigram** 方案:
| 方案 | 原理 | 中文效果 | 说明 |
|------|------|----------|------|
| `tsvector` | 分词 | 差 | 需额外中文分词插件 |
| `pg_trgm` | 3-gram | 一般 | 英文为主 |
| **`pg_bigm`** ✅ | 2-gram | **优秀** | 专为 CJK 文字优化 |
```sql
-- 开启插件
CREATE EXTENSION IF NOT EXISTS pg_bigm;
-- 创建索引
CREATE INDEX bigm_idx ON "ekb_schema"."EkbChunk"
USING gin (content gin_bigm_ops);
-- 查询(支持中文精确匹配)
SELECT * FROM "EkbChunk" WHERE content LIKE '%帕博利珠%';
-- 可匹配:"帕博利珠单抗"、"帕博利珠注射液" 等
-- 相似度查询
SELECT *, bigm_similarity(content, '帕博利珠单抗') as score
FROM "EkbChunk"
WHERE content LIKE '%帕博利珠%'
ORDER BY score DESC;
```
**优势**
- 对医学专有名词召回率高
- 不需要复杂语义评分(向量检索已做语义互补)
- 追求"查全率"和"精确匹配"
---
## 📦 代码结构
### 目录规划
```
backend/src/common/rag/
├── index.ts # 统一导出
├── KnowledgeBaseEngine.ts # 统一入口类(基础能力)
├── services/
│ ├── ChunkService.ts # 文档切片服务
│ ├── EmbeddingService.ts # 向量化服务(阿里云 DashScope
│ ├── SummaryService.ts # 摘要生成服务(💰 可选)
│ ├── ClinicalExtractionService.ts # 临床要素提取(💰 可选)
│ ├── VectorSearchService.ts # 向量检索服务pgvector
│ ├── KeywordSearchService.ts # 关键词检索服务pg_trgm
│ ├── HybridSearchService.ts # 混合检索服务RRF 融合)
│ └── RerankService.ts # 🆕 重排序服务Qwen-Rerank
├── workers/
│ └── ingestWorker.ts # ⚡️ 异步入库 Workerpg-boss
├── types/
│ ├── index.ts # 类型定义
│ ├── chunk.types.ts
│ ├── search.types.ts
│ └── document.types.ts
├── utils/
│ ├── rrfFusion.ts # RRF 算法
│ └── jsonParser.ts # JSON 容错解析
└── __tests__/ # 单元测试
├── embedding.test.ts
├── chunk.test.ts
└── search.test.ts
```
### 基础能力 API
```typescript
// KnowledgeBaseEngine.ts
export class KnowledgeBaseEngine {
constructor(private prisma: PrismaClient) {}
// ==================== 文档入库(异步) ====================
/**
* ⚡️ 提交入库任务(立即返回 taskId
* 详见Postgres-Only异步任务处理指南
*/
async submitIngestTask(params: {
kbId: string;
userId: string;
file: Buffer;
filename: string;
options?: {
enableSummary?: boolean; // 💰 默认 false
enableClinicalExtraction?: boolean; // 💰 默认 false
chunkSize?: number;
chunkOverlap?: number;
};
}): Promise<{ taskId: string; documentId: string }>;
/**
* 获取入库任务状态
*/
async getIngestStatus(taskId: string): Promise<{
status: 'pending' | 'processing' | 'completed' | 'failed';
progress: number; // 0-100
error?: string;
}>;
// ==================== 内容获取(全文) ====================
/**
* 获取单个文档全文
*/
async getDocumentFullText(documentId: string): Promise<DocumentText>;
/**
* 获取知识库所有文档全文
*/
async getAllDocumentsText(kbId: string): Promise<DocumentText[]>;
/**
* 批量获取多个知识库的所有文档全文
*/
async getAllDocumentsTextBatch(kbIds: string[]): Promise<DocumentText[]>;
// ==================== 内容获取(摘要) ====================
/**
* 获取单个文档摘要
*/
async getDocumentSummary(documentId: string): Promise<DocumentSummary>;
/**
* 获取知识库所有文档摘要
*/
async getAllDocumentsSummaries(kbId: string): Promise<DocumentSummary[]>;
/**
* 批量获取多个知识库的所有文档摘要
*/
async getAllDocumentsSummariesBatch(kbIds: string[]): Promise<DocumentSummary[]>;
// ==================== 检索能力 ====================
/**
* 向量检索(语义搜索)
*/
async vectorSearch(
kbIds: string[],
query: string,
topK?: number
): Promise<SearchResult[]>;
/**
* 关键词检索pg_bigm 中文精确匹配)
*/
async keywordSearch(
kbIds: string[],
query: string,
topK?: number
): Promise<SearchResult[]>;
/**
* 混合检索(向量 + 关键词 + RRF 融合)
*/
async hybridSearch(
kbIds: string[],
query: string,
topK?: number,
options?: {
vectorWeight?: number;
keywordWeight?: number;
filters?: SearchFilters;
}
): Promise<SearchResult[]>;
/**
* 🆕 重排序Qwen-Rerank API
*/
async rerank(
documents: SearchResult[],
query: string,
topK?: number
): Promise<SearchResult[]>;
// ==================== 管理操作 ====================
/**
* 删除文档(级联删除切片和向量)
*/
async deleteDocument(documentId: string): Promise<void>;
/**
* 删除知识库所有文档
*/
async clearKnowledgeBase(kbId: string): Promise<void>;
/**
* 获取知识库统计信息
*/
async getKnowledgeBaseStats(kbId: string): Promise<{
documentCount: number;
chunkCount: number;
totalTokens: number;
}>;
// ==================== ❌ 不提供 chat() 方法 ====================
// 策略由业务模块根据场景决定
}
```
---
## 🔄 核心流程
### 文档入库流程Ingest
```
用户上传 PDF/Word/...
┌─────────────────────────────────────────────────────────────┐
│ Step 1: 文档处理引擎 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ DocumentProcessor.toMarkdown(file) │ │
│ │ • PDF → pymupdf4llm │ │
│ │ • Word → mammoth │ │
│ │ • Excel → pandas │ │
│ │ 输出Markdown 文本 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Step 2: 文本切片 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ChunkService.split(markdown) │ │
│ │ • 递归字符切分 │ │
│ │ • chunkSize: 512, overlap: 50 │ │
│ │ 输出Chunk[] │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Step 3: 摘要生成(可选) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ SummaryService.generate(fullText) │ │
│ │ • LLM 生成 200-500 字摘要 │ │
│ │ 输出summary 字段 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Step 4: 临床要素提取(可选) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ClinicalExtractionService.extract(fullText) │ │
│ │ • PICO、用药方案、安全性数据等 │ │
│ │ • LLM 提取 + JSON 容错解析 │ │
│ │ 输出ClinicalData (JSONB) │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Step 5: 向量化 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ EmbeddingService.embedBatch(chunks.map(c => c.text))│ │
│ │ • 阿里云 text-embedding-v3 │ │
│ │ • 1024 维向量 │ │
│ │ 输出number[][] │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Step 6: 存储 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ PostgreSQL + pgvector │ │
│ │ • EkbDocument: 文档元数据 + 摘要 + 临床数据 (JSONB) │ │
│ │ • EkbChunk: 切片文本 + 向量 (vector(1024)) │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
---
## 🗄️ 数据模型
> 📌 **数据模型详见**[04-数据模型设计.md](./04-数据模型设计.md)
>
> 本文档不再重复定义数据模型,请以上述文档为准。该文档包含:
> - 四层架构设计原则
> - EkbDocument / EkbChunk 完整 Prisma Schema
> - 索引设计HNSW、pg_bigm、GIN
> - contentType 枚举定义
> - metadata / structuredData JSONB 结构
> - 各类型使用示例
---
## 📊 策略选择指南
### 根据知识库规模选择策略
| 知识库规模 | 文档数量 | 估算 Tokens | 推荐策略 | 基础能力组合 |
|-----------|---------|-------------|----------|-------------|
| **微型** | 1-10 | < 30K | 全文塞给 LLM | `getAllDocumentsText()` |
| **小型** | 10-30 | 30K-80K | 全文 + 长上下文模型 | `getAllDocumentsText()` + Qwen-Long |
| **中型** | 30-100 | 80K-300K | 摘要筛选 + Top-K 全文 | `getAllDocumentsSummaries()` + `getDocumentFullText()` |
| **大型** | 100+ | > 300K | RAG 向量检索 | `hybridSearch()` |
### 根据场景选择策略
| 场景 | 推荐策略 | 原因 |
|------|----------|------|
| 精准问答 | 全文模式 | 无信息丢失 |
| 快速检索 | 向量检索 | 速度快 |
| 综合分析 | 摘要筛选 + 全文 | 兼顾广度和深度 |
| 文献综述 | 混合检索 + Rerank | 召回率高 |
| 查重对比 | 全文比对 | 精确匹配 |
---
## 🔗 与其他通用能力的关系
### 依赖关系图
```
┌─────────────────────────────────────────────────────────────┐
│ 知识库引擎 (本模块) │
│ │
│ 平台依赖: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ⚡️ 异步任务处理pg-boss │ │
│ │ • 入库任务队列 │ │
│ │ • 详见Postgres-Only异步任务处理指南 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 文档处理引擎 │ │
│ │ • 调用 DocumentProcessor.toMarkdown() │ │
│ │ • 获取 PDF/Word/Excel 的 Markdown 文本 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ LLM 网关(💰 可选调用) │ │
│ │ • 摘要生成enableSummary: true │ │
│ │ • 临床要素提取enableClinicalExtraction: true │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 存储服务 │ │
│ │ • 调用 storage.upload() / storage.download() │ │
│ │ • 存储原始文档到 OSS │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 外部依赖: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 阿里云 DashScope API │ │
│ │ • text-embedding-v3 (向量化) │ │
│ │ • qwen-rerank (重排序) │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
---
## 📅 开发计划
### 分阶段实施(推荐)
详见:[03-分阶段实施方案.md](./03-分阶段实施方案.md)
| 阶段 | 内容 | 工期 | 状态 |
|------|------|------|------|
| **Phase 1 MVP** | 入库 + 向量检索 + 全文获取 | 3 天 | 🔜 待开始 |
| **Phase 2 增强** | + 关键词检索 + 混合检索 + rerank | 2 天 | 📋 规划中 |
| **Phase 3 完整** | + 异步入库 + 摘要 + PICO | 3 天 | 📋 规划中 |
**核心原则**:先跑通 MVP让业务走起来再逐步完善。
### 技术实现参考
详见:[02-pgvector替换Dify计划.md](./02-pgvector替换Dify计划.md)
---
## 📚 相关文档
- [分阶段实施方案](./03-分阶段实施方案.md) - 🆕 MVP → 增强 → 完整
- [pgvector 替换 Dify 技术方案](./02-pgvector替换Dify计划.md) - 详细技术实现
- [Postgres-Only异步任务处理指南](../Postgres-Only异步任务处理指南.md) - 异步架构参考
- [文档处理引擎设计方案](../02-文档处理引擎/01-文档处理引擎设计方案.md)
- [LLM 网关](../01-LLM大模型网关/README.md)
- [通用能力层总览](../README.md)
---
## 📅 更新日志
### v1.2 (2026-01-20)
**架构审核优化:**
- ⚡️ **入库异步化**`ingestDocument()``submitIngestTask()` + `getIngestStatus()`,基于 pg-boss 队列
- 💰 **成本控制**:摘要生成、临床要素提取默认关闭,按需开启
- 🔧 **中文检索**:关键词检索从 `tsvector` 改为 `pg_bigm`,专为 CJK 文字优化
- 🆕 **新增能力**:独立暴露 `rerank()` 重排序能力Qwen-Rerank API
- 📦 **代码结构**:新增 `workers/ingestWorker.ts``RerankService.ts`
- 📋 **分阶段实施**:新增 MVP → 增强 → 完整 三阶段方案
### v1.1 (2026-01-20)
**设计原则重大更新:**
- ✅ 明确"提供基础能力,不做策略选择"原则
- ❌ 移除 `chat()` 方法,策略由业务模块决定
- 🆕 新增 `getDocumentFullText()` / `getAllDocumentsText()` 全文获取
- 🆕 新增 `getDocumentSummary()` / `getAllDocumentsSummaries()` 摘要获取
- 🆕 新增业务模块策略选择示例PKB/AIA/ASL/RVW
- 🆕 新增策略选择指南(按规模、按场景)
- 📝 数据模型添加 `summary``tokenCount` 字段
### v1.0 (2026-01-20)
- 初始版本
---
**维护人:** 技术架构师
**最后更新:** 2026-01-20