# 知识库引擎数据模型设计 > **文档版本**: 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` JSONB:chunkSize, 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-L1–Positive Non–Small-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; // 结果数据 }; } ``` ### 8.2 典型病历 (case) ```typescript interface CaseData { // 诊断信息 diagnosis?: { primary: string; // 主诊断 secondary: string[]; // 合并诊断 staging: string; // 分期 pathology: string; // 病理类型 biomarkers: Record; // 生物标志物 }; // 治疗信息 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 字段 |