Files
AIclinicalresearch/docs/02-通用能力层/03-RAG引擎/04-数据模型设计.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

945 lines
30 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.
# 知识库引擎数据模型设计
> **文档版本**: v2.0
> **最后更新**: 2026-01-21
> **状态**: ✅ 权威文档
> **说明**: 本文档是知识库引擎数据模型的唯一权威来源,其他文档应引用本文档,避免重复定义。
---
## 1. 设计原则
### 1.1 核心理念
> **即使没有任何结构化数据RAG 检索也必须能工作!**
>
> 结构化数据是"锦上添花",不是"必须有"。
### 1.2 四层架构
```
┌─────────────────────────────────────────────────────────────┐
│ Layer 0: RAG 核心层(必须有,检索基础) │
│ ───────────────────────────────────── │
│ extractedText → 全文 Markdown │
│ chunks[] → 文本切片 │
│ embeddings[] → 向量嵌入 │
│ │
│ ✅ 只要有这一层RAG 就能工作! │
├─────────────────────────────────────────────────────────────┤
│ Layer 1: 基础信息层(必须有,系统需要) │
│ ───────────────────────────────────── │
│ filename, fileType, fileSizeBytes, fileUrl │
│ status, errorMessage, createdAt, updatedAt │
│ │
│ ✅ 文件管理必需 │
├─────────────────────────────────────────────────────────────┤
│ Layer 2: 内容增强层(可选,提升体验) │
│ ───────────────────────────────────── │
│ summary → AI 生成摘要(快速预览) │
│ tokenCount → Token 数量(成本估算) │
│ pageCount → 页数 │
│ │
│ ✅ 有则更好,无也能用 │
├─────────────────────────────────────────────────────────────┤
│ Layer 3: 分类标签层(可选,用户自定义) │
│ ───────────────────────────────────── │
│ contentType → 内容类型(可 AI 自动识别) │
│ tags[] → 用户标签(用户自己打) │
│ category → 分类目录(用户自己选) │
│ │
│ ✅ 用户可以不管,系统也能运行 │
├─────────────────────────────────────────────────────────────┤
│ Layer 4: 结构化数据层(可选,精准查询) │
│ ───────────────────────────────────── │
│ metadata → 文献属性pmid, doi, journal...
│ structuredData → 类型特定数据pico, diagnosis...
│ │
│ ✅ 高级功能,专业用户/药企场景使用 │
└─────────────────────────────────────────────────────────────┘
```
### 1.3 设计目标
| 目标 | 实现方式 |
|------|----------|
| **最小可用** | Layer 0-1 必须有RAG 就能工作 |
| **渐进增强** | Layer 2-4 可选,有则更强 |
| **用户友好** | 什么都不填也能用 |
| **专业支持** | 专业用户可以填完整信息 |
| **AI 辅助** | contentType、summary 可 AI 自动生成 |
| **灵活扩展** | JSONB 支持任意结构化数据 |
### 1.4 ER 关系图
```
┌─────────────────────────────────────────────────────────────────┐
│ EkbKnowledgeBase │
│ ───────────────────────────────────────────── │
│ id, name, description │
│ type (USER | SYSTEM) │
│ ownerId (userId 或 moduleId) │
│ config (JSONB: chunkSize, topK, enableRerank...) │
├─────────────────────────────────────────────────────────────────┤
│ 1:N
┌─────────────────────────────────────────────────────────────────┐
│ EkbDocument │
│ ───────────────────────────────────────────── │
│ id, kbId(FK), userId │
│ filename, fileType, fileSizeBytes, fileUrl, fileHash │
│ extractedText, summary, tokenCount, pageCount │
│ contentType, tags[], category │
│ metadata(JSONB), structuredData(JSONB) │
├─────────────────────────────────────────────────────────────────┤
│ 1:N
┌─────────────────────────────────────────────────────────────────┐
│ EkbChunk │
│ ───────────────────────────────────────────── │
│ id, documentId(FK) │
│ content, chunkIndex │
│ embedding (vector 1024) │
│ pageNumber, sectionType │
│ metadata(JSONB) ← 新增:切片级元数据 │
└─────────────────────────────────────────────────────────────────┘
```
---
## 2. EkbKnowledgeBase 模型(容器表)
### 2.1 设计目的
| 痛点 | 解决方案 |
|------|----------|
| 无法区分用户私有库 vs 系统公共库 | `type` 字段USER / SYSTEM |
| 无法管理"谁拥有这个库" | `ownerId` 字段userId 或 moduleId |
| 无法为不同库配置不同 RAG 策略 | `config` JSONBchunkSize, topK 等 |
| 用户配额管理(最多 3 个库) | 通过 `type=USER` 计数 |
### 2.2 Prisma Schema
```prisma
model EkbKnowledgeBase {
id String @id @default(uuid())
name String // 知识库名称
description String? // 描述
// ===== 核心隔离字段 =====
type String @default("USER") // USER: 用户私有, SYSTEM: 系统公共
ownerId String // USER: userId, SYSTEM: moduleId (如 "ASL", "AIA")
// ===== 策略配置 (JSONB) =====
config Json? // { chunkSize, topK, enableRerank, embeddingModel }
// ===== 关联 =====
documents EkbDocument[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// ===== 索引 =====
@@index([ownerId])
@@index([type])
@@schema("ekb_schema")
}
```
### 2.3 字段说明
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `id` | String | ✅ | UUID 主键 |
| `name` | String | ✅ | 知识库名称(如"我的文献库"、"ASL 系统文献库" |
| `description` | String | ❌ | 知识库描述 |
| `type` | String | ✅ | 类型:`USER`(用户私有)或 `SYSTEM`(系统公共) |
| `ownerId` | String | ✅ | 所有者 ID用户库填 userId系统库填模块 ID |
| `config` | Json | ❌ | 策略配置 JSONB |
### 2.4 type 枚举
| 值 | 说明 | ownerId 含义 |
|------|------|-------------|
| `USER` | 用户私有知识库 | userId创建者 |
| `SYSTEM` | 系统公共知识库 | moduleId如 "ASL", "AIA", "IIT" |
### 2.5 config 结构
```typescript
interface KnowledgeBaseConfig {
// RAG 策略
chunkSize?: number; // 切片大小,默认 512
chunkOverlap?: number; // 切片重叠,默认 50
topK?: number; // 检索数量,默认 5
// 高级功能
enableRerank?: boolean; // 启用重排序
enableSummary?: boolean; // 自动生成摘要
enableClinicalExtraction?: boolean; // 临床数据提取
// 模型配置
embeddingModel?: string; // 嵌入模型版本
}
```
### 2.6 使用示例
```typescript
// 用户创建个人知识库
await prisma.ekbKnowledgeBase.create({
data: {
name: '我的肺癌文献库',
type: 'USER',
ownerId: 'user-123',
config: { chunkSize: 512, topK: 5 }
}
});
// 系统创建 ASL 模块知识库
await prisma.ekbKnowledgeBase.create({
data: {
name: 'ASL 系统文献库',
type: 'SYSTEM',
ownerId: 'ASL',
config: { enableClinicalExtraction: true }
}
});
// 查询用户所有知识库(配额检查)
const userKbs = await prisma.ekbKnowledgeBase.count({
where: { type: 'USER', ownerId: 'user-123' }
});
if (userKbs >= 3) throw new Error('知识库配额已满');
```
---
## 3. EkbDocument 模型
### 3.1 Prisma Schema
```prisma
model EkbDocument {
id String @id @default(uuid())
kbId String // 所属知识库
userId String // 上传者(冗余存储,方便快速查询)
// ===== Layer 1: 基础信息(必须)=====
filename String // 文件名
fileType String // pdf, docx, pptx, xlsx, md, txt
fileSizeBytes BigInt // 文件大小(字节)
fileUrl String // OSS 存储路径
fileHash String? // 文件 SHA256 哈希(用于秒传和去重)
status String @default("pending") // 处理状态
errorMessage String? @db.Text // 错误信息
// ===== Layer 0: RAG 核心(必须)=====
extractedText String? @db.Text // Markdown 全文
// ===== Layer 2: 内容增强(可选)=====
summary String? @db.Text // AI 摘要
tokenCount Int? // Token 数量
pageCount Int? // 页数
// ===== Layer 3: 分类标签(可选)=====
contentType String? // 内容类型
tags String[] // 用户标签
category String? // 分类目录
// ===== Layer 4: 结构化数据(可选)=====
metadata Json? // 文献属性 JSONB
structuredData Json? // 类型特定数据 JSONB
// ===== 关联 =====
knowledgeBase EkbKnowledgeBase @relation(fields: [kbId], references: [id], onDelete: Cascade)
chunks EkbChunk[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// ===== 索引 =====
@@index([kbId])
@@index([userId])
@@index([status])
@@index([contentType])
@@index([fileHash]) // 支持秒传查询
@@index([tags], type: Gin)
@@index([metadata], type: Gin)
@@index([structuredData], type: Gin)
@@schema("ekb_schema")
}
```
### 3.2 字段说明
#### Layer 1: 基础信息(必须)
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `id` | String | ✅ | UUID 主键 |
| `kbId` | String | ✅ | 所属知识库 ID外键 |
| `userId` | String | ✅ | 上传者用户 ID冗余存储便于快速查询 |
| `filename` | String | ✅ | 原始文件名 |
| `fileType` | String | ✅ | 文件类型pdf, docx, pptx, xlsx, md, txt, csv |
| `fileSizeBytes` | BigInt | ✅ | 文件大小(字节) |
| `fileUrl` | String | ✅ | OSS 存储路径 |
| `fileHash` | String | ❌ | 文件 SHA256 哈希(用于秒传和去重) |
| `status` | String | ✅ | 处理状态pending, processing, completed, failed |
| `errorMessage` | String | ❌ | 处理失败时的错误信息 |
#### Layer 0: RAG 核心(必须)
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `extractedText` | String | ❌* | Markdown 格式全文(处理完成后必须有) |
> *注:上传时为空,处理完成后必须有值
#### Layer 2: 内容增强(可选)
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `summary` | String | ❌ | AI 生成的摘要 |
| `tokenCount` | Int | ❌ | 全文 Token 数量(用于成本估算) |
| `pageCount` | Int | ❌ | 文档页数 |
#### Layer 3: 分类标签(可选)
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `contentType` | String | ❌ | 内容类型标识(见第 5 节) |
| `tags` | String[] | ❌ | 用户自定义标签 |
| `category` | String | ❌ | 分类目录路径,如 "肿瘤科/肺癌" |
#### Layer 4: 结构化数据(可选)
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `metadata` | Json | ❌ | 文献属性(见第 7 节) |
| `structuredData` | Json | ❌ | 类型特定数据(见第 8 节) |
### 3.3 status 状态枚举
| 状态 | 说明 |
|------|------|
| `pending` | 等待处理 |
| `processing` | 正在处理(解析、向量化) |
| `completed` | 处理完成 |
| `failed` | 处理失败 |
### 3.4 fileHash 使用示例
```typescript
// 计算文件哈希
import crypto from 'crypto';
function calculateFileHash(buffer: Buffer): string {
return crypto.createHash('sha256').update(buffer).digest('hex');
}
// 上传时检查是否已存在(秒传)
async function uploadWithDedup(kbId: string, file: Buffer, filename: string) {
const fileHash = calculateFileHash(file);
// 检查同一知识库内是否已存在相同文件
const existing = await prisma.ekbDocument.findFirst({
where: { kbId, fileHash }
});
if (existing) {
// 秒传:直接返回已存在的文档
return { type: 'duplicate', document: existing };
}
// 正常上传流程
const document = await prisma.ekbDocument.create({
data: { kbId, fileHash, filename, /* ... */ }
});
return { type: 'new', document };
}
```
---
## 4. EkbChunk 模型
### 4.1 Prisma Schema
```prisma
model EkbChunk {
id String @id @default(uuid())
documentId String // 所属文档
// ===== 核心内容 =====
content String @db.Text // 切片文本Markdown
chunkIndex Int // 切片序号(从 0 开始)
// ===== 向量 =====
embedding Unsupported("vector(1024)")? // 向量嵌入
// ===== 溯源信息(可选)=====
pageNumber Int? // 页码(用于 PDF 溯源)
sectionType String? // 章节类型
// ===== 扩展元数据(可选)=====
metadata Json? // 切片级元数据 JSONB
document EkbDocument @relation(fields: [documentId], references: [id], onDelete: Cascade)
@@index([documentId])
@@index([metadata], type: Gin) // JSONB 索引
@@schema("ekb_schema")
}
```
### 4.2 字段说明
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `id` | String | ✅ | UUID 主键 |
| `documentId` | String | ✅ | 所属文档 ID |
| `content` | String | ✅ | 切片文本Markdown 格式) |
| `chunkIndex` | Int | ✅ | 切片序号,从 0 开始 |
| `embedding` | vector(1024) | ❌* | 向量嵌入(向量化后必须有) |
| `pageNumber` | Int | ❌ | 来源页码PDF 溯源) |
| `sectionType` | String | ❌ | 章节类型标识 |
| `metadata` | Json | ❌ | 切片级扩展元数据(见 4.4 |
### 4.3 sectionType 枚举(可选)
| 值 | 说明 |
|------|------|
| `title` | 标题 |
| `abstract` | 摘要 |
| `introduction` | 引言 |
| `methods` | 方法 |
| `results` | 结果 |
| `discussion` | 讨论 |
| `conclusion` | 结论 |
| `references` | 参考文献 |
| `table` | 表格 |
| `figure` | 图片说明 |
### 4.4 metadata 结构(切片级元数据)
```typescript
interface ChunkMetadata {
// 考试题场景
isAnswer?: boolean; // 是否为答案切片
questionId?: number; // 所属题目 ID
chunkType?: 'question' | 'options' | 'answer' | 'explanation';
// 病历场景
section?: string; // 病历段落:主诉、现病史、检查结果等
// 通用
importance?: number; // 重要性权重 0-1
keywords?: string[]; // 关键词(用于加权检索)
}
```
**使用示例**
```typescript
// 考试题切片 - 题目
{
"content": "1. 关于帕博利珠单抗,下列说法正确的是?",
"metadata": { "chunkType": "question", "questionId": 1 }
}
// 考试题切片 - 选项
{
"content": "A. 派姆单抗 B. 纳武利尤单抗 C. 阿特珠单抗 D. 度伐利尤单抗",
"metadata": { "chunkType": "options", "questionId": 1 }
}
// 考试题切片 - 答案
{
"content": "正确答案A。派姆单抗是帕博利珠单抗的通用名...",
"metadata": { "chunkType": "answer", "questionId": 1, "isAnswer": true }
}
// 检索时降低纯答案切片的权重
const results = await vectorSearch(query);
const reranked = results.map(r => ({
...r,
score: r.metadata?.isAnswer ? r.score * 0.5 : r.score
}));
```
---
## 5. 索引设计
### 5.1 向量索引HNSW
```sql
-- 创建 HNSW 索引(高性能近似最近邻)
CREATE INDEX idx_ekb_chunk_embedding ON ekb_schema.ekb_chunk
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
```
**参数说明**
- `m = 16`: 每层最大连接数
- `ef_construction = 64`: 构建时搜索范围
### 5.2 关键词索引pg_bigm
```sql
-- 安装 pg_bigm 扩展
CREATE EXTENSION IF NOT EXISTS pg_bigm;
-- 全文内容索引
CREATE INDEX idx_ekb_chunk_content_bigm ON ekb_schema.ekb_chunk
USING gin (content gin_bigm_ops);
-- 文档摘要索引
CREATE INDEX idx_ekb_document_summary_bigm ON ekb_schema.ekb_document
USING gin (summary gin_bigm_ops);
-- 提取文本索引
CREATE INDEX idx_ekb_document_text_bigm ON ekb_schema.ekb_document
USING gin (extracted_text gin_bigm_ops);
```
**关键词查询示例**
```sql
-- 关键词搜索(支持中英文)
SELECT * FROM ekb_schema.ekb_chunk
WHERE content LIKE '%Pembrolizumab%'
ORDER BY likequery(content, 'Pembrolizumab') DESC;
-- 中文搜索
SELECT * FROM ekb_schema.ekb_chunk
WHERE content LIKE '%非小细胞肺癌%';
```
### 5.3 JSONB 索引GIN
```sql
-- 文献属性索引
CREATE INDEX idx_ekb_document_metadata ON ekb_schema.ekb_document
USING gin (metadata jsonb_path_ops);
-- 结构化数据索引
CREATE INDEX idx_ekb_document_structured ON ekb_schema.ekb_document
USING gin (structured_data jsonb_path_ops);
-- 标签数组索引
CREATE INDEX idx_ekb_document_tags ON ekb_schema.ekb_document
USING gin (tags);
```
**JSONB 查询示例**
```sql
-- 按影响因子筛选
SELECT * FROM ekb_schema.ekb_document
WHERE (metadata->>'ifScore')::float > 10;
-- 按 PICO 干预措施筛选
SELECT * FROM ekb_schema.ekb_document
WHERE structured_data->'pico'->>'I' ILIKE '%Pembrolizumab%';
-- 按标签筛选
SELECT * FROM ekb_schema.ekb_document
WHERE tags @> ARRAY['肺癌', '免疫治疗'];
```
---
## 6. contentType 枚举
| 值 | 说明 | 适用场景 |
|------|------|----------|
| `general` | 通用文档(默认) | 任意文档 |
| `literature` | 医学文献 | 论文、研究报告 |
| `case` | 典型病历 | MDT 病例、教学病例 |
| `exam` | 教学考试 | 试题、模拟题 |
| `drug` | 药品资料 | 说明书、处方信息 |
| `guideline` | 临床指南 | NCCN、CSCO 指南 |
| `note` | 个人笔记 | 学习笔记、会议记录 |
| `protocol` | 研究方案 | 临床试验方案 |
| `report` | 工作报告 | 汇报材料、分析报告 |
---
## 7. metadata 结构(文献属性)
### 7.1 JSON Schema
```typescript
interface Metadata {
// 基础信息
title?: string; // 文献标题
abstract?: string; // 原始摘要
// 标识符
pmid?: string; // PubMed ID
doi?: string; // DOI
nctId?: string; // ClinicalTrials.gov ID
// 来源信息
journal?: string; // 期刊名称
publisher?: string; // 出版商
authors?: string[]; // 作者列表
// 时间与评分
publishYear?: number; // 发表年份
publishDate?: string; // 发表日期 (YYYY-MM-DD)
ifScore?: number; // 影响因子
// 分类
docType?: string; // 文献类型RCT, Meta, Review, Case, Guideline
keywords?: string[]; // 关键词
meshTerms?: string[]; // MeSH 词表
// 语言
language?: string; // 语言en, zh, ...
}
```
### 7.2 示例
```json
{
"title": "Pembrolizumab versus Chemotherapy for PD-L1Positive NonSmall-Cell Lung Cancer",
"pmid": "27718847",
"doi": "10.1056/NEJMoa1606774",
"journal": "New England Journal of Medicine",
"authors": ["Reck M", "Rodriguez-Abreu D", "Robinson AG"],
"publishYear": 2016,
"ifScore": 176.079,
"docType": "RCT",
"keywords": ["NSCLC", "Pembrolizumab", "Immunotherapy"],
"language": "en"
}
```
---
## 8. structuredData 结构(类型特定数据)
### 8.1 医学文献 (literature)
```typescript
interface LiteratureData {
// PICO 要素
pico?: {
P: string; // Population
I: string; // Intervention
C: string; // Comparison
O: string; // Outcome
};
// 研究设计
studyDesign?: {
design: string; // Phase III RCT, Meta-analysis, etc.
sampleSize: number; // 样本量
blinding: string; // Double-blind, Open-label
duration: string; // 研究周期
};
// 用药方案
regimen?: Array<{
drug: string; // 药物名称
dose: string; // 剂量
freq: string; // 频率
route: string; // 给药途径
}>;
// 安全性数据
safety?: {
ae_all: string[]; // 所有不良反应
ae_grade34: string[]; // 3-4级不良反应
dropout_rate: string; // 脱落率
};
// 入排标准
criteria?: {
inclusion: string[]; // 入选标准
exclusion: string[]; // 排除标准
};
// 观察指标
endpoints?: {
primary: string[]; // 主要终点
secondary: string[]; // 次要终点
results: Record<string, any>; // 结果数据
};
}
```
### 8.2 典型病历 (case)
```typescript
interface CaseData {
// 诊断信息
diagnosis?: {
primary: string; // 主诊断
secondary: string[]; // 合并诊断
staging: string; // 分期
pathology: string; // 病理类型
biomarkers: Record<string, string>; // 生物标志物
};
// 治疗信息
treatment?: {
firstLine: string; // 一线治疗
secondLine: string; // 二线治疗
surgery: string; // 手术
radiation: string; // 放疗
response: string; // 疗效评价
duration: string; // 治疗周期
};
// 预后信息
prognosis?: {
pfs: string; // 无进展生存
os: string; // 总生存
status: string; // 当前状态
recurrence: string; // 复发情况
};
// 随访信息
followUp?: {
lastVisit: string; // 最后随访日期
nextPlan: string; // 下一步计划
notes: string; // 随访备注
};
}
```
### 8.3 教学考试 (exam)
```typescript
interface ExamData {
// 题目列表
questions?: Array<{
id: number;
type: 'single' | 'multiple' | 'essay'; // 题型
content: string; // 题目内容
options?: string[]; // 选项(选择题)
}>;
// 答案列表
answers?: Array<{
id: number;
answer: string; // 答案
explanation: string; // 解析
}>;
// 知识点
knowledgePoints?: string[];
// 难度
difficulty?: 'easy' | 'medium' | 'hard';
// 来源
source?: string; // 题目来源
}
```
### 8.4 药品资料 (drug)
```typescript
interface DrugData {
// 基础信息
genericName?: string; // 通用名
brandName?: string; // 商品名
manufacturer?: string; // 生产厂家
// 适应症
indication?: string[];
// 禁忌症
contraindication?: string[];
// 用法用量
dosage?: {
adult: string;
pediatric: string;
adjustment: string; // 剂量调整
};
// 药物相互作用
interaction?: string[];
// 警告
warnings?: string[];
// 不良反应
adverseReactions?: {
common: string[];
serious: string[];
};
}
```
### 8.5 临床指南 (guideline)
```typescript
interface GuidelineData {
// 推荐意见
recommendations?: Array<{
content: string; // 推荐内容
level: string; // 证据级别 (1A, 2B, etc.)
strength: string; // 推荐强度
}>;
// 适用人群
population?: string;
// 发布机构
organization?: string; // NCCN, CSCO, ESMO
// 版本
version?: string;
// 更新要点
updates?: string[];
}
```
### 8.6 个人笔记 (note)
```typescript
interface NoteData {
// 标签(与顶层 tags 字段可重复,这里可存更多)
tags?: string[];
// 分类
category?: string;
// 关联
relatedDocs?: string[]; // 关联文档 ID
// 提醒
reminder?: string; // 提醒日期
}
```
---
## 9. 使用示例
### 9.1 普通医生随手上传
```typescript
// 医生直接拖文件上传,什么都不填
await kbEngine.submitIngestTask({
kbId: 'kb-123',
file: pdfBuffer,
filename: '某篇论文.pdf',
// 其他字段都不填
});
// 系统自动完成:
// ✅ extractedText → 提取全文
// ✅ chunks → 切片
// ✅ embeddings → 向量化
// ✅ summary → AI 摘要(可选开启)
// ✅ contentType → AI 自动识别(可选开启)
// 结果RAG 检索完全可用!
```
### 9.2 医生想分类管理
```typescript
// 医生上传时选择分类、打标签
await kbEngine.submitIngestTask({
kbId: 'kb-123',
file: pdfBuffer,
filename: 'KEYNOTE-024.pdf',
contentType: 'literature',
tags: ['肺癌', '免疫治疗', 'RCT'],
category: '肿瘤科/肺癌',
});
// 结果:可以按分类、标签筛选
```
### 9.3 药企专业录入
```typescript
// 药企医学部专业人员完整填写
await kbEngine.submitIngestTask({
kbId: 'kb-456',
file: pdfBuffer,
filename: 'KEYNOTE-024.pdf',
contentType: 'literature',
tags: ['Pembrolizumab', 'NSCLC', 'Phase III'],
category: '临床研究/III期',
metadata: {
title: 'Pembrolizumab versus Chemotherapy...',
pmid: '27718847',
doi: '10.1056/NEJMoa1606774',
journal: 'NEJM',
authors: ['Reck M', 'Rodriguez-Abreu D'],
publishYear: 2016,
ifScore: 176.079,
docType: 'RCT',
},
options: { enableClinicalExtraction: true }
});
// AI 自动提取 structuredData
// {
// pico: { P: '晚期NSCLC, PD-L1≥50%', I: 'Pembrolizumab', ... },
// studyDesign: { design: 'Phase III RCT', sampleSize: 305 },
// ...
// }
```
### 9.4 典型病历录入
```typescript
await kbEngine.submitIngestTask({
kbId: 'kb-123',
file: docBuffer,
filename: '肺癌MDT病例.docx',
contentType: 'case',
tags: ['MDT', '肺癌', 'IVA期'],
category: '病例库/肺癌',
options: { enableClinicalExtraction: true }
});
// AI 自动提取 structuredData
// {
// diagnosis: { primary: '非小细胞肺癌 IVA期', ... },
// treatment: { firstLine: '帕博利珠单抗 + 化疗', ... },
// ...
// }
```
---
## 10. 功能可用性矩阵
| 功能 | 只有 Layer 0-1 | + Layer 2 | + Layer 3 | + Layer 4 |
|------|----------------|-----------|-----------|-----------|
| **向量检索** | ✅ | ✅ | ✅ | ✅ |
| **关键词检索** | ✅ | ✅ | ✅ | ✅ |
| **混合检索** | ✅ | ✅ | ✅ | ✅ |
| **快速预览** | ❌ | ✅ 有摘要 | ✅ | ✅ |
| **分类筛选** | ❌ | ❌ | ✅ | ✅ |
| **标签筛选** | ❌ | ❌ | ✅ | ✅ |
| **年份筛选** | ❌ | ❌ | ❌ | ✅ |
| **IF 筛选** | ❌ | ❌ | ❌ | ✅ |
| **PICO 查询** | ❌ | ❌ | ❌ | ✅ |
---
## 11. 版本历史
| 版本 | 日期 | 变更内容 |
|------|------|----------|
| v1.0 | 2026-01-20 | 初版:四层架构设计,支持多内容类型 |
| v2.0 | 2026-01-21 | 整合审查建议:增加 EkbKnowledgeBase 容器表、EkbDocument.fileHash 字段、EkbChunk.metadata 字段 |