feat(pkb): Integrate pgvector and create Dify replacement plan

Summary:
- Migrate PostgreSQL to pgvector/pgvector:pg15 Docker image
- Successfully install and verify pgvector 0.8.1 extension
- Create comprehensive Dify-to-pgvector migration plan
- Update PKB module documentation with pgvector status
- Update system documentation with pgvector integration

Key changes:
- docker-compose.yml: Switch to pgvector/pgvector:pg15 image
- Add EkbDocument and EkbChunk data model design
- Design R-C-R-G hybrid retrieval architecture
- Add clinical data JSONB fields (pico, studyDesign, regimen, safety, criteria, endpoints)
- Create detailed 10-day implementation roadmap

Documentation updates:
- PKB module status: pgvector RAG infrastructure ready
- System status: pgvector 0.8.1 integrated
- New: Dify replacement development plan (01-Dify替换为pgvector开发计划.md)
- New: Enterprise medical knowledge base solution V2

Tested: PostgreSQL with pgvector verified, frontend and backend functionality confirmed
This commit is contained in:
2026-01-20 00:00:58 +08:00
parent 1ece9a4ae8
commit dfc0fe0b9a
289 changed files with 1897 additions and 41 deletions

View File

@@ -300,3 +300,4 @@ Level 3: 兜底Prompt缓存也失效

View File

@@ -486,3 +486,4 @@ const pageSize = Number(query.pageSize) || 20;

View File

@@ -220,3 +220,4 @@ ADMIN-运营管理端/

View File

@@ -319,3 +319,4 @@ INST-机构管理端/

View File

@@ -886,3 +886,4 @@ export interface SlashCommand {

View File

@@ -191,3 +191,4 @@ export type AgentStage = 'topic' | 'design' | 'review' | 'data' | 'writing';
本次开发遵循了现有 PromptService 的设计模式,与 RVW 模块集成方式保持一致。

View File

@@ -1298,5 +1298,6 @@ interface FulltextScreeningResult {

View File

@@ -412,5 +412,6 @@ GET /api/v1/asl/fulltext-screening/tasks/:taskId/export

View File

@@ -514,5 +514,6 @@ Failed to open file '\\tmp\\extraction_service\\temp_10000_test.pdf'

View File

@@ -172,3 +172,4 @@ UNIFUNCS_API_KEY=sk-xxxx
- [Postgres-Only 异步任务处理指南](../../02-通用能力层/Postgres-Only异步任务处理指南.md)
- [数据库开发规范](../../04-开发规范/09-数据库开发规范.md)

View File

@@ -580,5 +580,6 @@ df['creatinine'] = pd.to_numeric(df['creatinine'], errors='coerce')

View File

@@ -995,5 +995,6 @@ export const aiController = new AIController();

View File

@@ -1329,5 +1329,6 @@ npm install react-markdown

View File

@@ -237,5 +237,6 @@ FMA___基线 | FMA___1个月 | FMA___2个月

View File

@@ -395,5 +395,6 @@ formula = "FMA总分0-100 / 100"

View File

@@ -229,5 +229,6 @@ async handleFillnaMice(request, reply) {

View File

@@ -201,5 +201,6 @@ method: 'mean' | 'median' | 'mode' | 'constant' | 'ffill' | 'bfill'

View File

@@ -652,5 +652,6 @@ import { logger } from '../../../../common/logging/index.js';

View File

@@ -455,5 +455,6 @@ import { ChatContainer } from '@/shared/components/Chat';

View File

@@ -365,5 +365,6 @@ const initialMessages = defaultMessages.length > 0 ? defaultMessages : [{

View File

@@ -653,5 +653,6 @@ http://localhost:5173/data-cleaning/tool-c

View File

@@ -441,5 +441,6 @@ Docs: docs/03-业务模块/DC-数据清洗整理/06-开发记录/DC模块重建

View File

@@ -314,5 +314,6 @@ ConflictDetectionService // 冲突检测(字段级对比)

View File

@@ -478,5 +478,6 @@ Tool B后端代码**100%复用**了平台通用能力层,无任何重复开发

View File

@@ -255,5 +255,6 @@ $ node scripts/check-dc-tables.mjs

View File

@@ -488,5 +488,6 @@ ${fields.map((f, i) => `${i + 1}. ${f.name}${f.desc}`).join('\n')}

View File

@@ -694,4 +694,5 @@ private async processMessageAsync(xmlData: any) {

View File

@@ -1087,5 +1087,6 @@ async function testIntegration() {

View File

@@ -228,5 +228,6 @@ Content-Type: application/json

View File

@@ -649,4 +649,5 @@ REDCap API: exportRecords success { recordCount: 1 }

View File

@@ -654,5 +654,6 @@ backend/src/modules/iit-manager/

View File

@@ -804,5 +804,6 @@ CREATE TABLE iit_schema.wechat_tokens (

View File

@@ -561,5 +561,6 @@ Day 3 的开发工作虽然遇到了多个技术问题,但最终成功完成

View File

@@ -328,5 +328,6 @@ AI: "出生日期2017-01-04

View File

@@ -272,5 +272,6 @@ Day 4: REDCap EMWebhook推送← 作为增强,而非核心

View File

@@ -687,4 +687,5 @@ const answer = `根据研究方案[1]和CRF表格[2],纳入标准包括:

View File

@@ -445,3 +445,4 @@ export const calculateAvailableQuota = async (tenantId: string) => {

View File

@@ -318,3 +318,4 @@ https://platform.example.com/t/pharma-abc/login

View File

@@ -1,10 +1,11 @@
# PKB个人知识库模块 - 当前状态与开发指南
> **文档版本:** v2.0
> **文档版本:** v2.1
> **创建日期:** 2026-01-07
> **维护者:** PKB模块开发团队
> **最后更新:** 2026-01-07
> **重大进展:** 🎉 **PKB模块核心功能全部实现具备生产可用性**
> **最后更新:** 2026-01-19
> **重大进展:** 🎉 **PKB模块核心功能全部实现pgvector向量数据库已集成**
> **基础设施:** ✅ pgvector 0.8.1 已安装RAG检索模式基础设施就绪
> **文档目的:** 反映模块真实状态,记录开发历程
---
@@ -65,10 +66,11 @@ UI组件: Ant Design v6 + Ant Design X
```
框架: Fastify v4 (Node.js 22)
数据库: PostgreSQL 15 + Prisma 6
数据库: PostgreSQL 15 + Prisma 6 + pgvector 0.8.1
Schema: pkb_schema (独立隔离)
向量存储: pgvector (PostgreSQL原生向量扩展) ✅ 2026-01-19 已集成
LLM: DeepSeek-V3, Qwen-Max (通过LLMFactory)
RAG: Dify知识库集成
RAG: Dify知识库集成 → 计划迁移到 pgvector 原生RAG
存储: OSS对象存储
```
@@ -210,30 +212,41 @@ frontend-v2/src/modules/pkb/
**当前状态**:🔧 API执行待调试
### 4. RAG检索模式待开发
### 4. RAG检索模式基础设施就绪
**功能说明**
- 基于向量检索
- 精准定位相关段落
- 适合快速查找
**当前状态**❌ 后端待实现
**当前状态**🟡 基础设施已就绪pgvector 0.8.1 已安装),后端业务逻辑待实现
**技术基础**2026-01-19 完成):
- ✅ pgvector 扩展已安装(版本 0.8.1
- ✅ 支持 HNSW 和 IVFFlat 索引
- ✅ 与阿里云 RDS pgvector 0.8.0 兼容
- ⏳ 向量表设计待实现
- ⏳ Embedding 服务集成待实现
- ⏳ 相似度检索 API 待实现
---
## ⚠️ 已知问题
### 1. RAG检索模式未实现 🟡 中优先级
### 1. RAG检索模式业务逻辑未实现 🟡 中优先级
**问题描述**
- RAG检索模式暂未实现
- pgvector 基础设施已就绪2026-01-19
- RAG检索业务逻辑待实现
- 当前优先全文阅读和逐篇精读模式
**影响**:工作模式选择有限
**解决方案**
- v2.1版本实现RAG检索
- 集成Dify知识库检索能力
- v2.1版本实现RAG检索基于pgvector不再依赖Dify
- 设计向量表结构pkb_schema.document_embeddings
- 集成 Embedding 服务OpenAI/智谱)
- 实现相似度检索 API
### 2. 批处理模板有限 🟢 低优先级
@@ -265,8 +278,11 @@ frontend-v2/src/modules/pkb/
### v2.1 版本(短期)
1. **RAG检索模式** 🟡
- 实现基于Dify的知识库检索
1. **RAG检索模式** 🟡 (基础设施已就绪 ✅)
- ✅ pgvector 0.8.1 已安装
- 设计向量表结构pkb_schema.document_embeddings
- 集成 Embedding 服务(文本向量化)
- 实现相似度检索 API
- 添加工作模式选择器
- 测试检索准确度
@@ -394,7 +410,32 @@ frontend-v2/src/modules/pkb/
---
**最后更新:** 2026-01-07
---
## 📝 更新日志
### 2026-01-19 pgvector 向量数据库集成
**重大变更**
- ✅ **pgvector 0.8.1 安装成功**Docker 环境已迁移到 `pgvector/pgvector:pg15` 镜像
- ✅ **兼容性验证**:与阿里云 RDS pgvector 0.8.0 完全兼容
- ✅ **功能验证**:前后端服务重启后功能正常
- ✅ **数据完整性**用户数据、知识库数据、pg-boss 队列函数全部正常
**技术细节**
- 镜像:`pgvector/pgvector:pg15`
- 扩展版本0.8.1
- 支持索引类型HNSW、IVFFlat
- 向量维度:最高支持 16000 维
**下一步**
- 设计 `pkb_schema.document_embeddings` 表
- 集成 Embedding 服务
- 实现 RAG 检索 API
---
**最后更新:** 2026-01-19
**文档维护:** PKB模块开发团队
**联系方式:** 项目Issues

View File

@@ -0,0 +1,191 @@
# **企业级医学知识库 (EKB) 综合技术解决方案**
版本: v2.0 (增强版:临床数据全要素结构化)
核心目标: 构建高精度、可追溯、基于医学证据的企业级知识库
技术栈: Node.js, Python, PostgreSQL (pgvector), DeepSeek, pymupdf4llm
设计范式: R-C-R-G (Router \- Concurrent \- Rerank \- Generate)
## **1\. 总体架构设计**
本方案采用 **"Postgres-Only"** 极简架构,利用 Node.js 进行业务编排Python 进行文档解析,外部 API 提供 AI 算力。
### **1.1 核心组件**
1. **解析层 (Python Microservice)**
* **核心工具**pymupdf4llm
* **作用**:将 PDF含复杂表格转换为 **Markdown** 格式,保留结构化语义。
2. **存储层 (PostgreSQL 15+)**
* **三维信息架构**
1. **文献属性信息** (Metadata)PMID、IF分、期刊等。
2. **文献关键内容信息** (Clinical Data)PICO、用药方案、不良反应、入排标准、终点指标等JSONB存储
3. **向量信息** (Vector):全文切片的语义向量。
3. **计算层 (Node.js \+ External APIs)**
* **Embedding**:调用 text-embedding-v4 或 BGE-M3 API。
* **Rerank**:调用 qwen-rerank API。
* **Reasoning**:调用 DeepSeek V3 进行全要素提取和答案生成。
4. **文件层 (OSS)**
* 存储原始 PDF 和生成的 Markdown 文件。
## **2\. 数据模型设计 (存储方案)**
利用 PostgreSQL 的强大扩展性,我们在单库中实现多种数据类型的融合存储,构建**健壮的临床数据库**。
### **2.1 数据库 Schema (Prisma 描述)**
// 1\. 文档主表:承载 "属性信息" 与 "关键内容信息"
model EkbDocument {
id String @id @default(uuid())
projectId String // 业务隔离
// \--- A. 文档属性信息 (Metadata) \- 用于基础筛选 \---
title String
abstract String? @db.Text // 原始摘要
pmid String? @unique
doi String?
journal String?
authors String\[\]
publishYear Int // 用于 "2024年最新" 筛选
ifScore Float? // 用于 "高分文献" 筛选
docType String // 指南/RCT/综述/病例报告
// \--- B. 文档关键内容信息 (Clinical Data) \- AI 提取的结构化金矿 \---
// 使用 JSONB 存储,支持 GIN 索引,实现 "SQL 级" 的精准查询
// 1\. PICO 要素
// { "P": "晚期NSCLC", "I": "Keytruda", "C": "化疗", "O": "OS, PFS" }
pico Json?
// 2\. 研究设计与样本
// { "design": "Phase III RCT", "sampleSize": 500, "blinding": "Double-blind" }
studyDesign Json?
// 3\. 药物与剂量 (Regimen)
// \[ { "drug": "Pembrolizumab", "dose": "200mg", "freq": "Q3W" } \]
regimen Json?
// 4\. 安全性与不良反应 (Safety)
// { "ae\_all": \["Rash", "Fatigue"\], "ae\_grade34": \["Pneumonitis"\], "dropout\_rate": "5%" }
safety Json?
// 5\. 入排标准 (Criteria)
// { "inclusion": \["Age \>= 18", "EGFR \-"\], "exclusion": \["Autoimmune disease"\] }
criteria Json?
// 6\. 观察指标 (Endpoints)
// { "primary": \["PFS"\], "secondary": \["OS", "ORR"\], "results": {"PFS\_HR": 0.5} }
endpoints Json?
// \--- C. 系统信息 \---
fileKey String // PDF OSS 路径
mdKey String? // Markdown OSS 路径
status String // PENDING, PROCESSED, FAILED
chunks EkbChunk\[\]
// \--- 索引优化 \---
@@index(\[projectId\])
@@index(\[publishYear\])
@@index(\[ifScore\])
// GIN 索引:让 JSON 字段支持高速查询 (e.g. 搜特定不良反应)
@@index(\[pico\], type: Gin)
@@index(\[regimen\], type: Gin)
@@index(\[safety\], type: Gin)
}
// 2\. 切片表:向量信息 \+ 文本内容
model EkbChunk {
id String @id @default(uuid())
documentId String
// \--- D. 切片内容 \---
content String @db.Text // Markdown 格式的切片文本
pageNumber Int // 溯源锚点
sectionType String? // 标记切片来源Title, Abstract, Methods, Results, Discussion
// \--- E. 向量信息 \---
// 使用 Unsupported 类型支持 pgvector
embedding Unsupported("vector(1024)")?
document EkbDocument @relation(fields: \[documentId\], references: \[id\], onDelete: Cascade)
}
## **3\. 数据处理流水线 (Ingestion Pipeline)**
此流程负责将非结构化的 PDF 转化为结构化的数据库记录。
### **步骤一:解析与转换 (Python)**
* **工具**pymupdf4llm
* **输入**PDF 文件流。
* **输出**Markdown 文本(保留表格结构)。
### **步骤二:全要素智能提取 (DeepSeek)**
这是构建健壮数据库的关键一步。
* **操作**:将全文 Markdown或前 10k token丢给 DeepSeek V3。
* **Prompt**"你是一个医学数据专家。请阅读这篇文献,严格按照以下 JSON 格式提取关键信息。如果文中未提及,字段留空。
1. **pico**: { P, I, C, O }
2. **studyDesign**: { design (如RCT), sampleSize (数字), blinding }
3. **regimen**: 提取主要药物名称、剂量、给药频率。
4. **safety**: 提取主要不良反应Adverse Events及严重不良反应。
5. **criteria**: 简要概括核心入选和排除标准。
6. **endpoints**: 主要和次要观察指标。
输出必须是纯 JSON。"
* **存储**:解析返回的 JSON分别填入 EkbDocument 的对应字段。
### **步骤三:切片与向量化 (Node.js)**
* **切片器**RecursiveCharacterTextSplitter。
* **增强策略**:在切片 content 前面加上元数据头。例如:\[Design: RCT\] \[Sample: 500\] ...原文...。这能显著增加向量检索的召回率。
* **存储**:存入 EkbChunk。
## **4\. 检索与问答策略 (增强版 R-C-R-G)**
有了结构化数据,我们的检索策略从“模糊搜”升级为“精准筛 \+ 模糊搜”。
### **4.1 Router (意图路由)**
用户提问后,调用 LLM 判断意图并提取**结构化参数**
1. **安全性查询** \-\> 提取不良反应关键词 (e.g., "Rash")。
2. **方案对比** \-\> 提取药物名称 (e.g., "Keytruda")。
3. **高质筛选** \-\> 提取样本量阈值 (e.g., "n \> 100")。
### **4.2 Concurrent Retrieval (并发混合召回)**
Node.js 并行执行以下查询,最后取并集:
* 路径 A (SQL 精准筛选 \- 新增杀手锏)
利用 JSONB 字段进行逻辑过滤。
* *Query*: SELECT id FROM EkbDocument WHERE safety-\>\>'ae\_all' ILIKE '%Pneumonitis%' (找提到肺炎副作用的)
* *Query*: SELECT id FROM EkbDocument WHERE (studyDesign-\>\>'sampleSize')::int \> 100 (找大样本研究)
* 路径 B (向量检索)
在路径 A 圈定的 ID 范围内,执行 ORDER BY embedding \<=\> query\_vec。
* 路径 C (关键词检索)
使用 ts\_rank 捕捉专有名词。
### **4.3 Rerank (重排序)**
* **工具**qwen-rerank API。
* **策略**:输入用户问题 \+ 混合召回的 Top 50 切片。
### **4.4 Generate (生成与溯源)**
* **模型**DeepSeek V3/R1。
* **优势**:此时 LLM 拿到的 Context 不仅有文本切片还可以注入该文档的结构化信息如样本量、PICO使得回答更加立体。
## **5\. 实施关键检查点**
1. **JSONB 性能**PostgreSQL 的 JSONB 查询非常快,但务必建立 GIN 索引(如 @@index(\[safety\], type: Gin)),否则全表扫描会很慢。
2. **提取成本**:全要素提取会消耗更多 Input Token。按 1000 篇文献算DeepSeek V3 成本约为 20-30 元人民币,完全可接受。
3. **数据清洗**AI 提取的 JSON 可能会有格式错误Node.js 端需要加一层 try-catch 和简单的格式校验(如 JSON.parse 失败重试)。
## **6\. 总结**
这套升级后的方案,不仅是一个**知识库**,更是一个**轻量级的 RWE (真实世界证据) 数据库**。
* **查询能力质变**:从只能问“文章说了什么”,升级为能问“有哪些文章是用 200mg 剂量的”或“有哪些三期临床涉及了亚洲人”。
* **应用场景扩展**:支持自动生成 **Meta 分析草稿**、**竞品安全性对比表**、**指南用药推荐汇总** 等高级应用。

View File

@@ -0,0 +1,602 @@
# **医疗科研AI系统架构评估报告PostgreSQL与pgvector在RAG及知识库中的深度应用分析**
## **1\. 执行摘要**
本报告旨在为一家中国的医疗科研创业AI公司提供关于技术选型及其架构决策的深度分析重点评估利用PostgreSQL数据库的扩展插件pgvector构建检索增强生成RAG系统及医疗知识库的可行性、性能表现及行业最佳实践。
经过对技术架构、医疗领域需求及当前中国云服务生态的详尽调研,本报告得出以下核心结论:
1. **战略契合度极高Reliability & Fit**对于一家处于创业阶段且数据规模在“数千至数百万”篇文献量级的医疗AI公司采用PostgreSQL集成pgvector不仅是“靠谱”的方案更是**最优的架构决策**。它避免了引入专用向量数据库带来的运维复杂性和数据一致性风险,完全契合创业团队对开发效率和系统稳定性的要求。
2. **医疗场景的独特优势Unique Capabilities**PostgreSQL最大的竞争壁垒在于其原生支持**混合检索Hybrid Search**。医疗科研对查准率要求极高如区分“5mg”与“50mg”的剂量差异或精准匹配特定药物名称单纯的向量语义检索往往难以满足。pgvector与PostgreSQL内置的全文检索tsvector结合能够通过互惠排名融合RRF算法在单一ACID事务中同时实现语义理解与关键词精准匹配这是大多数独立向量数据库难以企及的能力。
3. **容量与扩展性Capacity & Scalability**针对用户关心的“几千还是几万篇文献”的容量问题pgvector的处理能力远超此量级。在标准硬件配置下它可以轻松承载**数千万级**的向量数据对应数十万篇全长医学文献的切片。只有在数据量突破亿级100M+ vectors才需考虑分片或迁移至分布式专用向量引擎。
4. **国产化与合规Ecosystem**阿里云、腾讯云及华为云的RDS PostgreSQL服务均已全面支持pgvector包括最新的HNSW索引这为医疗数据的本地化部署与合规性提供了坚实的基础设施保障。
本报告将从技术原理、架构对比、医疗场景实战、局限性分析及落地实施指南五个维度展开长达15,000字的深度论述。
## ---
**2\. 技术背景与架构演进**
### **2.1 医疗科研AI面临的“检索”挑战**
在构建医疗垂直领域的RAG系统时核心痛点并非在于大模型LLM的生成能力而在于**检索Retrieval的精准度**。医疗数据具有以下显著特征:
* **术语严谨性**:医学术语(如“心肌梗死”与“心绞痛”)在语义上相近,但在临床路径上截然不同。向量模型有时会因语义泛化而混淆两者。
* **多模态信息**科研文献中包含大量图表、剂量数值、分子式等非结构化文本这些信息难以通过单一的文本嵌入Embedding完美表达。
* **数据一致性**临床指南或药物说明书的更新必须实时反映在系统中。如果数据库与向量库分离极易出现“幻觉”——即LLM基于旧版本的检索结果生成错误的医疗建议。
### **2.2 向量数据库的“分久必合”**
过去三年AI技术栈经历了从“分离式架构”向“融合式架构”的演进。
* **第一阶段2022-2023**应用通常采用“PostgreSQL存储元数据 \+ Pinecone/Milvus存储向量”的双库架构。这种架构虽然性能强劲但带来了双倍的运维成本、网络延迟及数据同步难题Data Consistency Drift
* **第二阶段2024-2026**随着pgvector、pg\_embedding等插件的成熟PostgreSQL具备了原生向量处理能力。对于95%的企业级应用数据量在1亿向量以下“全能型数据库”Converged Database成为主流选择。它允许开发者在一条SQL语句中同时完成关系型筛选如“筛选2024年后的论文”和语义检索如“查找关于免疫疗法的研究”1。
对于初创公司而言选择pgvector意味着将技术栈复杂度降低了50%,这是在激烈的市场竞争中保持迭代速度的关键优势。
## ---
**3\. 深度解析PostgreSQL \+ pgvector 的核心能力(回应问题 1 & 2**
### **3.1 什么是 pgvector**
pgvector 是一个基于PostgreSQL的开源扩展插件它赋予了PostgreSQL存储、索引和查询高维向量数据的能力。它不是一个独立的数据库而是作为一种新的数据类型Data Type和索引方法Index Access Method嵌入在PostgreSQL内核中。
#### **3.1.1 核心数据结构**
pgvector 并非简单的存储工具它针对AI场景引入了多种专用数据类型极大地丰富了应用场景
* **vector (Dense Vector)**
* **描述**标准的稠密向量类型支持最高16,000维默认编译配置通常为2,000维可调整
* **医疗应用**:完美适配**BioBERT**768维、**PubMedBERT**或OpenAI text-embedding-31536/3072维生成的嵌入向量。这是构建医疗文献语义索引的基础 3。
* **halfvec (Half-Precision Vector)**
* **描述**在pgvector 0.7.0版本中引入使用16位浮点数FP16代替标准的32位浮点数FP32存储维度数据。
* **价值**这一特性对医疗初创公司至关重要。它将索引占用的内存RAM直接**减半**。基准测试显示在医疗文献检索任务中FP16相比FP32的检索精度损失Recall Loss通常小于1%但能够让原本需要64GB内存的服务器承载两倍的数据量极大地降低了云资源成本 5。
* **sparsevec (Sparse Vector)**
* **描述**:稀疏向量支持,仅存储非零元素。
* **医疗应用**:这是实现**SPLADE**Sparse Lexical and Expansion等高级检索模型的关键。在医疗领域许多文档特征是稀疏的例如在数万种药物中一篇论文可能只提及了“阿司匹林”和“氯吡格雷”。使用稀疏向量可以比稠密向量更精准地捕捉这些关键词特征避免语义漂移 6。
* **bit (Binary Vector)**
* **描述**支持二进制向量及海明距离Hamming Distance、杰卡德相似系数Jaccard Distance
* **医疗应用**:这是**化学信息学**的神器。在药物研发中分子指纹Molecular Fingerprints通常表示为二进制串如MACCS Keys。利用pgvector的位运算索引科研人员可以毫秒级在数百万分子库中检索结构相似的化合物这是通用文本向量库如OpenAI Embeddings无法直接做到的 6。
### **3.2 索引机制HNSW 与 IVFFlat 的抉择**
PostgreSQL 的查询优化器极其强大而pgvector为向量数据提供了两种核心索引算法。理解它们的差异对于系统调优至关重要。
#### **3.2.1 HNSW (Hierarchical Navigable Small World)**
* **原理**这是一种基于图Graph-based的索引算法。它构建了一个分层的“小世界”网络搜索过程类似于在地图上从洲际公路高层逐级导航到街道底层
* **性能**HNSW是目前业界的**性能金标准**State-of-the-Art。它提供了极高的查询速度低延迟和召回率Recall
* **pgvector实战**自0.5.0版本引入HNSW以来pgvector的查询性能已能与Milvus、Qdrant等专用库媲美。对于医疗科研系统**强烈推荐默认使用HNSW索引**。尽管其构建速度较慢且内存占用较高,但它能保证医生在查询“罕见病治疗方案”时,不会因为索引精度问题而漏掉关键文献 9。
#### **3.2.2 IVFFlat (Inverted File with Flat Compression)**
* **原理**基于聚类Clustering的倒排索引。它将向量空间划分为多个区域Lists查询时先找到最近的区域中心再遍历该区域内的向量。
* **局限**如果查询向量位于区域边界极易漏掉相邻区域的最近邻Recall较低。且当新增数据导致数据分布改变时IVFFlat索引的性能会急剧下降需要定期重建。
* **适用场景**仅在内存极度受限如在边缘设备或极低配云主机上运行时考虑。对于追求精准的医疗AI应尽量避免使用 12。
### **3.3 距离度量算法**
pgvector 支持多种度量方式,且可以在同一列上创建不同度量的索引:
* **余弦相似度Cosine Similarity \<=\>**最适合归一化的文本嵌入如BioBERT衡量向量的方向一致性。
* **欧氏距离L2 Distance \<-\>**:适合未归一化的数据或空间坐标数据。
* **内积Inner Product \<\#\>**:常用于推荐系统中的矩阵分解场景。
## ---
**4\. 核心竞争力PostgreSQL 独有的“必杀技”(回应问题 3**
用户问到“PostgreSQL的插件pgvector与PostgreSQL 有哪些特殊的技能,或者能力,是其他向量库所不具备的?”
这是一个非常关键的问题。pgvector的真正威力不在于它作为一个向量库有多快而在于它依然是PostgreSQL。
### **4.1 真正的“混合检索”Hybrid Search能力**
在医疗RAG系统中纯向量检索往往存在致命缺陷——**“精确性丢失”**。
* *案例*:用户查询“\*\*依鲁替尼Ibrutinib\*\*的副作用”。
* *纯向量检索的问题*向量模型可能认为“泽布替尼Zanubrutinib”在语义上与“依鲁替尼”极度相似都是BTK抑制剂因此检索结果可能混杂了大量关于泽布替尼的文献。这在临床上是不可接受的噪音。
* PostgreSQL的解法
利用PostgreSQL内置的全文检索Full-Text Search, FTS组件tsvector结合pgvector可以在一条SQL语句中同时执行
1. **语义检索**找到关于“BTK抑制剂副作用”的相关文献高召回
2. **关键词检索**强制要求文档中必须包含“Ibrutinib”这个词高精确
3. **重排序Reranking**:使用\*\*互惠排名融合Reciprocal Rank Fusion, RRF\*\*算法,将两者的评分融合。
**技术实现代码SQL**
SQL
WITH semantic\_search AS (
SELECT id, RANK() OVER (ORDER BY embedding \<=\> query\_embedding) as rank
FROM medical\_docs
ORDER BY embedding \<=\> query\_embedding LIMIT 50
),
keyword\_search AS (
SELECT id, RANK() OVER (ORDER BY ts\_rank\_cd(to\_tsvector('english', content), plainto\_tsquery('Ibrutinib side effects'))) as rank
FROM medical\_docs
WHERE to\_tsvector('english', content) @@ plainto\_tsquery('Ibrutinib side effects')
LIMIT 50
)
SELECT
COALESCE(s.id, k.id) as doc\_id,
COALESCE(s.rank, 0) \+ COALESCE(k.rank, 0) as combined\_score
FROM semantic\_search s
FULL OUTER JOIN keyword\_search k ON s.id \= k.id
ORDER BY combined\_score ASC
LIMIT 10;
这种\*\*“原生SQL级融合”\*\*是Milvus或Pinecone无法做到的。后者通常需要你在应用层Python代码分别请求两个系统Elasticsearch \+ Milvus然后在内存中极其痛苦地合并结果不仅增加了延迟还引入了系统复杂性 14。
### **4.2 ACID 事务一致性Transactional Consistency**
医疗数据容不得“最终一致性”。
* *场景*某篇科研论文被撤稿Retracted或者某位患者撤回了隐私授权。
* *专用向量库的痛点*你需要在MySQL中删除记录然后异步调用API去Pinecone中删除向量。如果中间网络抖动Pinecone删除失败系统就会出现“幽灵数据”——AI依然能检索到这篇已被撤稿的文章并据此生成建议引发严重的医疗伦理事故。
* *PostgreSQL的能力*
SQL
BEGIN;
DELETE FROM medical\_docs WHERE id \= 1001; \-- 向量数据随行记录一同物理删除
COMMIT;
在PostgreSQL中向量只是表的一列。删除操作是**原子性Atomic的。一旦提交任何查询无论是SQL还是向量搜索都绝不会再看到这条数据。这种强一致性**是医疗级系统的刚需 2。
### **4.3 复杂的元数据过滤Pre-Filtering**
医疗查询往往伴随着极其复杂的筛选条件。
* *查询*:“查找**2020年以后**发表的、由**北京协和医院**作者撰写的、关于**肺结节**的**随机对照试验RCT**。”
* PostgreSQL的优势
PostgreSQL拥有几十年历史的查询优化器Query Planner。它能智能地分析统计信息
* 如果“2020年以后”的数据很少它会先利用B-Tree索引筛选出这些记录然后对剩下的几条数据进行暴力向量计算速度极快
* 如果筛选条件很宽泛它会先走HNSW向量索引再过滤属性。
这种\*\*基于成本的优化Cost-Based Optimization\*\*是其核心壁垒。专用向量库在处理复杂的布尔逻辑AND/OR/NOT嵌套和关系型Join如关联作者表、医院表性能往往大幅下降甚至不支持 17。
## ---
**5\. 局限性与不足分析(回应问题 4**
尽管pgvector在架构上优势明显但在某些维度上它确实不如专用向量数据库。我们需要客观地认清这些差距以判断它们是否会成为贵公司的瓶颈。
### **5.1 规模天花板The Scale Wall**
* **现象**PostgreSQL是单机垂直扩展Scale-up架构。
* **局限**:当向量数据量达到\*\*1亿100 Million\*\*级别以上时单机内存RAM和磁盘I/O将成为瓶颈。虽然可以通过分区表Partitioning缓解但在十亿级规模下Milvus或Weaviate这种天生分布式、支持水平分片Sharding的系统会更有优势。
* **医疗场景评估**PubMed所有文献摘要加起来约为3500万篇。即使切分成块Chunking总量可能在2-3亿向量。如果贵公司的目标是索引全人类所有语种的医疗文献PostgreSQL可能会吃力需要引入Citus分布式插件或极高配置的服务器。但如果仅针对特定领域如肿瘤学、心血管或中文医疗文献数据量通常在百万至千万级pgvector完全在舒适区 19。
### **5.2 资源争抢Resource Contention**
* **现象**向量搜索是计算密集型CPU密集和内存密集型任务。
* **局限**在同一个PostgreSQL实例中构建HNSW索引或执行高并发向量查询会占用大量CPU资源。如果数据库同时还承载着用户登录、订单支付等OLTP业务可能会导致由于CPU飙升而拖慢常规业务的响应速度。
* **解决方案**:架构分离。
* **主库Primary**:负责写入和常规业务。
* **只读副本Read Replica**专门用于承载向量搜索流量。阿里云和腾讯云的RDS都支持创建只读实例这是标准的规避方案。
### **5.3 缺乏GPU加速**
* **局限**目前的pgvector主要依赖CPU指令集如AVX-512进行加速。相比之下Milvus和FAISS对GPUNVIDIA CUDA有深度优化在大批量Batch查询或超大规模索引构建时GPU的速度是CPU的几十倍。
* **影响**对于实时RAG系统通常是单条查询CPU的延迟毫秒级已经足够低GPU的吞吐优势体现不明显。但如果需要离线大规模聚类分析pgvector会慢很多 20。
## ---
**6\. 医疗科研领域的RAG应用实战回应问题 5 & 6**
### **6.1 典型应用场景**
1. **循证医学问答Evidence-Based QA**
* 医生提问“针对EGFR突变的非小细胞肺癌三代TKI耐药后的后续治疗方案有哪些
* 系统利用pgvector检索最新的临床指南和Case Report结合RAG生成包含引用来源的建议。
2. **临床试验匹配Clinical Trial Matching**
* 将患者的病历(非结构化文本)转化为向量。
* 利用向量相似度搜索在数据库中匹配入排标准Inclusion/Exclusion Criteria相似的临床试验项目。
3. **药物重定位Drug Repurposing**
* 利用二进制向量bit类型存储药物分子指纹。
* 通过杰卡德距离计算,发现老药与新靶点在分子结构上的潜在关联 6。
### **6.2 知识库容量评估**
用户问:“能够承载多大容量?几千篇还是几万篇?”
* **结论****“几千、几万篇”对PostgreSQL来说属于微量数据**。
* **数据推算**
* 假设一篇医疗文献平均5,000字切分为10个Chunk。
* **5万篇文献** \= 50万个向量。
* **50万个768维向量**BioBERT的原始数据大小约为 **1.5 GB**
* 加上HNSW索引总内存占用可能在 **2-3 GB** 左右。
* **性能预期**在任何一台现代笔记本电脑或入门级云服务器2核 4G检索50万向量的耗时都在 **5毫秒ms** 以内。
* **上限**pgvector 在单机(如阿里云 32GB 内存实例)上,可以流畅处理 **1000万至2000万** 个向量对应约100万-200万篇全长文献。因此贵公司的需求完全在覆盖范围内且留有百倍的增长空间 10。
### **6.3 医疗文献处理的最佳范式**
在医疗领域,直接将整段文本向量化往往效果不佳。推荐采用\*\*分层索引Hierarchical Indexing\*\*策略:
| 处理步骤 | 方法 | PostgreSQL实现 |
| :---- | :---- | :---- |
| **1\. 图表处理** | 医疗文献包含大量图表Table 1, Figure 2。直接丢弃会丢失关键数据。 | 将表格转化为Markdown或JSON格式利用LLM生成“表格摘要文本”。对**摘要**进行Embedding存入vector列原表格存入jsonb列。 |
| **2\. 切片策略** | 避免机械切分如每500字一切。采用语义切分。 | 建立父子文档结构。父文档Parent是整章“Result”子文档Child是具体发现。检索时匹配子文档向量但在Prompt中提供父文档全文上下文。PostgreSQL的JOIN查询天然支持这种操作。 |
| **3\. 引用溯源** | 医疗回答必须有据可查。 | 建立citations表。RAG生成答案后利用SQL关联查询出对应的文献DOI、发表年份和期刊影响因子作为可信度背书。 |
## ---
**7\. 实施指南与生态资源(回应问题 7**
### **7.1 开发教程与易用性**
pgvector 的学习曲线极低特别是对于熟悉SQL的开发者。
**极简开发流程:**
1. **启用插件**
SQL
CREATE EXTENSION vector;
2. **创建表**
SQL
CREATE TABLE papers (
id bigserial PRIMARY KEY,
content text,
embedding vector(768) \-- BioBERT dimensions
);
3. **插入数据**
SQL
INSERT INTO papers (content, embedding) VALUES ('Aspirin inhibits...', '\[0.1, \-0.2,...\]');
4. **查询(最近邻搜索)**
SQL
SELECT content FROM papers ORDER BY embedding \<=\> '\[0.1, \-0.2,...\]' LIMIT 5;
**开发框架支持**
* **LangChain**Python库langchain-postgres提供了开箱即用的PGVector类完全封装了底层SQL 21。
* **LlamaIndex**原生支持Postgres向量存储并能自动将LlamaIndex的高级过滤器转换为SQL WHERE子句 23。
### **7.2 中国云服务商支持情况**
由于贵公司在中国,云服务商的兼容性至关重要:
* **阿里云Aliyun RDS**
* PostgreSQL 14及以上版本全面支持pgvector。
* **注意**需在控制台确认插件版本。建议升级到支持HNSW的0.5.0以上版本。最新的0.7.0版本支持稀疏向量可能需要最新的内核小版本20240530以后请在购买前查看RDS发布说明 24。
* **腾讯云TencentDB**
* PostgreSQL 13/14/15 均支持pgvector。腾讯云对内核进行了深度优化支持向量化指令加速。
* 最新版本已支持pgvector 0.7.0,且支持在控制台管理插件升级 26。
* **华为云GaussDB / RDS**
* 华为云RDS for PostgreSQL 12+ 支持该插件。
* GaussDB分布式版也有自己的向量检索引擎但标准RDS PostgreSQL更适合初创期的轻量级部署 28。
## ---
**8\. 总结与建议**
经过全面评估,我们认为**PostgreSQL \+ pgvector 是贵公司构建医疗AI知识库的首选方案**。
**核心理由总结**
1. **架构极简**:无需维护第二套数据库,降低了创业初期的运维与人力成本。
2. **能力全面**独有的混合检索Hybrid Search能力完美解决医疗领域对“精准实体匹配”的刚需。
3. **完全合规**:数据完全私有化,依托成熟的国产云数据库底座,规避数据出境风险。
4. **容量充足**轻松应对千万级文献足以支撑公司未来3-5年的业务增长。
**落地建议**
* **模型选择**:务必使用针对生物医学微调的**BioBERT**或**PubMedBERT**作为Embedding模型而非通用的OpenAI模型以提升专业术语的理解能力。
* **索引策略**:生产环境务必创建**HNSW索引**不要使用默认的IVFFlat。
* **硬件配置**向量索引常驻内存。建议数据库服务器内存RAM配置充足例如每100万个768维向量预留约2-3GB内存
此方案不仅是一个技术上的“可行解”,更是一个商业上的“最优解”,它以最低的复杂度提供了最符合医疗严肃场景需求的核心能力。
---
*以下为报告详细正文涵盖上述章节的深度展开包含具体SQL代码、性能调优参数及详细的架构设计图解描述。*
# **详细研究报告基于PostgreSQL与pgvector构建医疗科研AI系统的深度评估**
## **1\. 引言**
随着大语言模型LLM在医疗领域的应用深化\*\*检索增强生成RAG\*\*已成为解决模型幻觉、赋予模型实时专业知识的关键架构。对于一家中国的医疗科研创业公司而言,选择何种技术栈来构建底层的“知识库”与“向量检索引擎”,直接决定了产品的检索质量、响应速度以及后续数年的运维成本。
本报告针对用户提出的核心疑问,对利用现有的 **PostgreSQL** 数据库集成 **pgvector** 插件这一技术路线进行了全方位的可行性研究。报告将结合医疗行业的特殊需求(如高精度、多模态数据、数据隐私)及中国本土的云基础设施环境,提供客观、详实的技术分析。
## **2\. 技术路线评估:为什么选择 pgvectorReliability & Architectural Fit**
### **2.1 从“专用”到“通用”的范式转移**
在RAG技术出现的早期2022年左右由于传统关系型数据库对向量支持的缺失开发者往往被迫采用“多库架构”使用MySQL/PostgreSQL存储业务数据同时引入Milvus、Pinecone或Weaviate存储向量数据。
然而,对于医疗科研系统,这种分离架构带来了巨大的痛点:
1. **数据一致性风险Data Consistency Risk**医疗数据要求极高的严谨性。如果一篇临床指南被修订了PostgreSQL中的文本更新了但向量库中的索引未能毫秒级同步AI就可能引用旧版指南给出错误的医疗建议。这种“同步延迟”在医疗领域是不可接受的风险。
2. **元数据过滤的复杂性Metadata Filtering Complexity**科研人员常需要进行复杂的组合查询例如“查找2023年IF\>10的期刊中关于PD-1抑制剂的论文”。在分离架构中这需要在两个数据库间传输大量ID进行“交集”运算效率极低。
pgvector 的出现解决了这一核心矛盾。
作为PostgreSQL的一个扩展pgvector 让向量Vector成为数据库中的一种原生数据类型。这意味着
* **单一数据源Single Source of Truth**:文本、元数据、向量存储在同一张表中。
* **ACID 事务保障**:更新文献和更新向量在同一个事务中完成,要么全成功,要么全失败,彻底消除了数据不一致的隐患。
* **运维极简**初创团队无需学习和维护一套全新的分布式向量数据库系统只需维护现有的PostgreSQL即可。备份、恢复、高可用HA方案完全复用。
### **2.2 中国医疗环境下的合规性优势**
在中国医疗数据属于强监管范畴如《数据安全法》。使用SaaS类的向量数据库如Pinecone通常涉及数据传输到公有云API这在合规上存在灰色地带。
相比之下PostgreSQL可以完全私有化部署Self-hosted。无论是在医院内网的物理机上还是在阿里云/腾讯云的私有网络VPC企业都能对数据拥有100%的掌控权。各大国产数据库如华为GaussDB、腾讯TDSQL大多基于PostgreSQL生态这也为未来的信创迁移留出了空间。
## ---
**3\. 功能详解pgvector 能做什么Capabilities & Features**
pgvector 的功能迭代极快特别是0.5.0版本之后的HNSW索引支持使其真正具备了生产级能力。
### **3.1 向量数据类型与存储**
在PostgreSQL中启用插件后即可使用 vector 类型:
SQL
CREATE EXTENSION vector;
CREATE TABLE documents (
id bigserial PRIMARY KEY,
content text,
embedding vector(768) \-- 对应BioBERT模型的维度
);
#### **3.1.1 维度支持**
pgvector 支持高达16,000维的向量。对于医疗领域常用的Embedding模型
* **BioBERT / PubMedBERT**输出768维向量。
* **BGE-M3 (BAAI)**输出1024维向量。
* OpenAI text-embedding-3-large输出3072维向量。
以上模型均能被完美支持。
#### **3.1.2 半精度向量Halfvec—— 降本增效利器**
在pgvector 0.7.0版本中,引入了 halfvec 类型。它将维度的存储精度从32位浮点数降为16位。
* **原理**:深度学习模型的输出往往不需要极高的浮点精度来维持检索排序。
* **收益**存储空间减少50%内存占用减少50%。
* **实测**对于千万级的文献库这意味着原本需要128GB内存的服务器现在只需64GB即可全内存加载索引大幅节省了云服务器成本 5。
#### **3.1.3 稀疏向量Sparsevec—— 专治“关键词遗漏”**
传统的稠密向量Dense Vector是将一段文本压缩成一个实数数组这会导致信息压缩损失。例如一篇长论文中只出现了一次“TP53基因突变”在稠密向量中这个特征可能被淹没。
sparsevec 允许存储稀疏向量如SPLADE模型的输出。它仅记录非零维度的值能够精准捕捉稀缺关键词。这对于医疗科研中的精准术语检索价值巨大 7。
### **3.2 索引算法:性能的核心**
#### **3.2.1 HNSW推荐**
pgvector 实现了完整的HNSW索引。
* **性能**:查询时间复杂度为 $O(\\log N)$。在百万级数据下单次查询通常在2ms-10ms之间。
* **参数可调**
* m节点最大连接数。医疗场景建议设为16-32以保证高召回。
* ef\_construction构建时的搜索深度。设为64-128可提升索引质量虽然构建变慢但查询更准 9。
* **构建速度**支持并行构建Parallel Build。利用多核CPU构建速度比早期版本提升了数倍。
#### **3.2.2 IVFFlat**
这是早期的索引算法。除非您的服务器内存极小例如只有2GB内存却要跑数百万数据否则不建议使用。它的召回率不稳定且维护成本高需要定期Reindex
## ---
**4\. 独家绝技PostgreSQL \+ pgvector 的不可替代性Unique Skills**
用户特别关心“有什么是别人做不到的”。除了前文提到的ACID事务最大的杀手锏是**混合检索Hybrid Search**。
### **4.1 医疗场景下的“语义”与“符号”之争**
在医疗RAG中我们经常面临两难
* \*\*语义检索Vector\*\*擅长理解概念。例如搜“免疫检查点抑制剂”它能找到“PD-1”、“CTLA-4”相关的文章。
* \*\*符号检索Keyword\*\*擅长精确匹配。例如搜“NCT04826348”临床试验号或者搜“5mg/kg”这需要字符级的精确匹配。
如果只用向量库,很难搜到具体的临床试验号,因为向量模型无法精确编码一串随机数字。
如果只用全文检索,搜“癌症治疗”可能会漏掉“肿瘤疗法”的文章。
### **4.2 完美的结合pgvector \+ tsvector**
PostgreSQL 是世界上最强大的开源关系型数据库,它内置了企业级的全文检索引擎 tsvector基于BM25算法
利用 pgvector我们可以在数据库内部实现\*\*“语义+关键词”的双路召回\*\*,并使用\*\*RRF互惠排名融合\*\*算法合并结果。
实战案例:
假设我们要找“阿司匹林在心血管疾病中的应用,且必须提及出血风险”。
SQL
WITH vector\_search AS (
\-- 路径1语义检索找前50个语义最相关的
SELECT id, RANK() OVER (ORDER BY embedding \<=\> query\_embedding) as rank
FROM papers
ORDER BY embedding \<=\> query\_embedding LIMIT 50
),
keyword\_search AS (
\-- 路径2关键词检索找前50个包含'bleeding'和'risk'的
SELECT id, RANK() OVER (ORDER BY ts\_rank\_cd(to\_tsvector('english', content), plainto\_tsquery('bleeding risk'))) as rank
FROM papers
WHERE to\_tsvector('english', content) @@ plainto\_tsquery('bleeding risk')
LIMIT 50
)
\-- 融合计算RRF得分
SELECT
COALESCE(v.id, k.id) as id,
(1.0 / (60 \+ COALESCE(v.rank, 0))) \+ (1.0 / (60 \+ COALESCE(k.rank, 0))) as rrf\_score
FROM vector\_search v
FULL OUTER JOIN keyword\_search k ON v.id \= k.id
ORDER BY rrf\_score DESC
LIMIT 10;
这一能力是**PostgreSQL独有**的。它不需要外部的Elasticsearch不需要复杂的ETL不需要在应用层写代码合并列表。它极其高效、稳定是构建高精度医疗RAG的最佳范式 14。
## ---
**5\. 局限性与不足理性看待差距Limitations**
虽然pgvector对于99%的场景都足够好但在某些极端场景下它确实不如Milvus或Pinecone。
### **5.1 亿级以上规模的挑战**
* **索引构建时间**当数据量达到1亿100M以上时PostgreSQL构建HNSW索引可能会非常慢数小时甚至数天因为它是基于磁盘的数据库且主要依赖CPU计算。而Milvus支持GPU加速索引构建速度快10倍以上 20。
* **内存瓶颈**HNSW索引非常吃内存。虽然PostgreSQL支持将索引存放在磁盘上利用OS Page Cache但如果内存不足以容纳大部分索引层查询会出现大量磁盘IO导致延迟从2ms飙升到200ms。专用向量库通常有更复杂的内存管理机制如Mmap优化来缓解这个问题。
### **5.2 资源隔离问题**
* PostgreSQL是单进程多线程或多进程模型。如果一个巨大的向量查询占满了CPU可能会影响到数据库中其他简单的SQL查询如用户登录
* **对策**:在生产环境中,强烈建议配置**读写分离**。主库处理写入和元数据更新配置一个只读节点Read Replica专门处理向量查询请求。阿里云和腾讯云的RDS都能一键实现这个架构。
### **5.3 高级量化技术缺失**
* 目前pgvector支持halfvecFP16和简单的二进制量化。但业界领先的向量库如Qdrant支持积量化Product Quantization, PQ能将向量压缩到原始大小的1/64。如果您的数据量极其庞大且预算极其有限pgvector的存储成本会显得较高。
## ---
**6\. 容量与性能几千还是几万Capacity Analysis**
用户问:“能够承载多大容量的知识库?几千篇文献,还是几万篇文献?”
### **6.1 容量评估:绰绰有余**
对于pgvector而言“几万篇文献”属于微型数据集。
让我们做一下量化计算:
* **场景**:假设您有**10万篇**医疗文献。
* **切片Chunking**每篇文献平均切分为20个段落Chunks
* **总量**$100,000 \\times 20 \= 2,000,000$ 200万个向量。
* **存储需求**
* BioBERT向量768维大小$2,000,000 \\times 768 \\times 4 \\text{ bytes} \\approx 6 \\text{ GB}$。
* HNSW索引大小约为数据大小的50%-80%,即约 **4 GB**
* **总内存需求**:约 **10 GB**
结论:一台标准的 16GB内存 的云服务器如阿里云ECS g7型就足以将这10万篇文献的索引全部加载进内存实现毫秒级查询。
PostgreSQL的舒适区在 1000万至5000万 向量之间。因此贵公司的业务即使增长100倍这套架构依然撑得住。
### **6.2 性能实测数据**
根据由于Google Cloud和AWS进行的基准测试基于10
* **数据集**100万条 768维向量。
* **索引**HNSW (m=16, ef=64)。
* **查询延迟Latency**\< 5ms 在t3.medium这种低配机器上
* **每秒查询数QPS**单机可达数千QPS。对于医疗科研系统通常是医生或研究员使用并发不高这性能完全溢出。
## ---
**7\. 医疗科研领域的特殊应用与最佳范式Medical Best Practices**
### **7.1 嵌入模型的选择**
不要直接使用OpenAI的通用模型。在医疗领域专有模型效果更好。
* **推荐**
* 英文文献:**BioBERT** 或 **PubMedBERT**
* 中文文献:**Text2Vec-Base-Chinese-Paraphrase** 或针对中医/西医微调过的BERT模型。
* **注意**pgvector 只是存储容器检索质量的70%取决于Embedding模型本身的质量。
### **7.2 表格与图表的处理**
科研文献中的精华往往在图表Table/Figure里。
* **错误做法**:直接把表格转成文本字符串切片。这会丢失行列对应关系。
* **最佳范式**
1. 使用OCR或PDF解析工具如Unstructured.io提取表格。
2. 将表格转化为Markdown格式或JSON。
3. 利用大模型如GPT-4o或Qwen-Max生成一段\*\*“表格摘要”\*\*例如“表1显示实验组的生存期中位数为12个月显著高于对照组的8个月...”)。
4. 对这段**摘要**进行Embedding存入vector列。
5. 将原始表格Markdown存入PostgreSQL的jsonb列。
6. 检索时匹配摘要但将原始表格Markdown作为上下文喂给LLM 30。
### **7.3 引文溯源Citations**
医疗RAG必须解决“幻觉”问题。
* **设计**在documents表中增加metadata列JSONB类型存储DOI、作者、期刊名、发表日期。
* **查询**在RAG生成回答时利用PostgreSQL查出的元数据强制LLM在回答中标注引用来源例如“根据2023年JAMA的研究...”)。
## ---
**8\. 实施指南与云服务支持Implementation Guide**
### **8.1 云平台支持详情**
鉴于贵公司在中国,以下是三大云厂商的具体支持情况:
* **阿里云Aliyun RDS PostgreSQL**
* **版本**PostgreSQL 14/15/16 均支持。
* **操作**在RDS控制台“插件管理”页面点击安装vector插件即可。
* **注意**确保内核小版本是最新的以获取HNSW索引支持。
* **腾讯云TencentDB for PostgreSQL**
* **版本**:全面支持。腾讯云在内核层面做了向量指令加速。
* **教程**腾讯云官方文档中有详细的“使用pgvector构建向量检索系统”的教程 26。
* **华为云RDS for PostgreSQL**
* 支持pgvector。华为云通常用于政企项目如果贵公司服务于公立医院华为云的合规属性会有加分 28。
### **8.2 开发教程资源**
* **教程丰富度**pgvector 是目前GitHub上Star增长最快的PostgreSQL插件之一社区资源极其丰富。
* **推荐库**
* **Python**: psycopg3 或 SQLAlchemy配合pgvector-python库
* **AI框架**: **LangChain** (langchain\_postgres) 和 **LlamaIndex** 都内置了对pgvector的完美支持。你甚至不需要写SQL只需要几行Python代码即可完成知识库的构建和检索 21。
**LangChain 极简示例:**
Python
from langchain\_postgres import PGVector
from langchain\_huggingface import HuggingFaceEmbeddings
\# 1\. 定义连接字符串 (阿里云RDS地址)
connection \= "postgresql+psycopg://user:pass@rm-xxx.pg.rds.aliyuncs.com:5432/med\_db"
\# 2\. 初始化向量库 (自动使用pgvector)
vector\_store \= PGVector(
embeddings=HuggingFaceEmbeddings(model\_name="shibing624/text2vec-base-chinese"),
collection\_name="clinical\_guidelines",
connection=connection,
use\_jsonb=True,
)
\# 3\. 添加文档
vector\_store.add\_documents(documents)
\# 4\. 检索 (RAG)
results \= vector\_store.similarity\_search("高血压的首选药物", k=5)
## **9\. 结论**
综上所述对于贵公司——一家专注于医疗科研的AI创业公司而言**集成PostgreSQL的pgvector插件不仅是“靠谱”的而且是目前阶段最具性价比、最稳健的技术选型。**
它利用PostgreSQL强大的生态解决了医疗领域最棘手的**混合检索**和**数据一致性**问题同时完全满足从数千篇到数千万篇文献的扩展需求。相比于盲目引入复杂的专用向量数据库基于PostgreSQL构建“全栈式”医疗知识库将让贵公司的技术架构更加简洁、高效且合规。
#### **引用的著作**
1. Load vector embeddings up to 67x faster with pgvector and Amazon Aurora \- AWS, 访问时间为 一月 14, 2026 [https://aws.amazon.com/blogs/database/load-vector-embeddings-up-to-67x-faster-with-pgvector-and-amazon-aurora/](https://aws.amazon.com/blogs/database/load-vector-embeddings-up-to-67x-faster-with-pgvector-and-amazon-aurora/)
2. Ditch the Extra Database: Simplify Your AI Stack with Managed PostgreSQL and pgvector, 访问时间为 一月 14, 2026 [https://render.com/articles/simplify-ai-stack-managed-postgresql-pgvector](https://render.com/articles/simplify-ai-stack-managed-postgresql-pgvector)
3. Postgres Vector Search with pgvector: Benchmarks, Costs, and Reality Check \- Medium, 访问时间为 一月 14, 2026 [https://medium.com/@DataCraft-Innovations/postgres-vector-search-with-pgvector-benchmarks-costs-and-reality-check-f839a4d2b66f](https://medium.com/@DataCraft-Innovations/postgres-vector-search-with-pgvector-benchmarks-costs-and-reality-check-f839a4d2b66f)
4. Overfitter/biobert\_embedding: Token and Sentence level embeddings from BioBERT model, 访问时间为 一月 14, 2026 [https://github.com/Overfitter/biobert\_embedding](https://github.com/Overfitter/biobert_embedding)
5. What's new in pgvector v0.7.0 \- Supabase, 访问时间为 一月 14, 2026 [https://supabase.com/blog/pgvector-0-7-0](https://supabase.com/blog/pgvector-0-7-0)
6. vector 0.7.0: Open-source vector similarity search for Postgres / PostgreSQL Extension Network \- PGXN, 访问时间为 一月 14, 2026 [https://pgxn.org/dist/vector/0.7.0/](https://pgxn.org/dist/vector/0.7.0/)
7. The pgvector extension \- Neon Docs, 访问时间为 一月 14, 2026 [https://neon.com/docs/extensions/pgvector](https://neon.com/docs/extensions/pgvector)
8. pgvector 0.7.0 Released\! \- PostgreSQL, 访问时间为 一月 14, 2026 [https://www.postgresql.org/about/news/pgvector-070-released-2852/](https://www.postgresql.org/about/news/pgvector-070-released-2852/)
9. An early look at HNSW performance with pgvector | Jonathan Katz, 访问时间为 一月 14, 2026 [https://jkatz05.com/post/postgres/pgvector-hnsw-performance/](https://jkatz05.com/post/postgres/pgvector-hnsw-performance/)
10. Faster similarity search performance with pgvector indexes | Google Cloud Blog, 访问时间为 一月 14, 2026 [https://cloud.google.com/blog/products/databases/faster-similarity-search-performance-with-pgvector-indexes](https://cloud.google.com/blog/products/databases/faster-similarity-search-performance-with-pgvector-indexes)
11. How to calculate amount of RAM required for serving X N-dimensional vectors with pgvector (HNSW)? \- Stack Overflow, 访问时间为 一月 14, 2026 [https://stackoverflow.com/questions/77401874/how-to-calculate-amount-of-ram-required-for-serving-x-n-dimensional-vectors-with](https://stackoverflow.com/questions/77401874/how-to-calculate-amount-of-ram-required-for-serving-x-n-dimensional-vectors-with)
12. pgvector/pgvector: Open-source vector similarity search for Postgres \- GitHub, 访问时间为 一月 14, 2026 [https://github.com/pgvector/pgvector](https://github.com/pgvector/pgvector)
13. Optimize generative AI applications with pgvector indexing: A deep dive into IVFFlat and HNSW techniques | AWS Database Blog, 访问时间为 一月 14, 2026 [https://aws.amazon.com/blogs/database/optimize-generative-ai-applications-with-pgvector-indexing-a-deep-dive-into-ivfflat-and-hnsw-techniques/](https://aws.amazon.com/blogs/database/optimize-generative-ai-applications-with-pgvector-indexing-a-deep-dive-into-ivfflat-and-hnsw-techniques/)
14. Hybrid Search in PostgreSQL: The Missing Manual | ParadeDB, 访问时间为 一月 14, 2026 [https://www.paradedb.com/blog/hybrid-search-in-postgresql-the-missing-manual](https://www.paradedb.com/blog/hybrid-search-in-postgresql-the-missing-manual)
15. Hybrid search with PostgreSQL and pgvector \- Jonathan Katz, 访问时间为 一月 14, 2026 [https://jkatz05.com/post/postgres/hybrid-search-postgres-pgvector/](https://jkatz05.com/post/postgres/hybrid-search-postgres-pgvector/)
16. Vector Databases vs. PostgreSQL with pg\_vector for RAG Setups \- DEV Community, 访问时间为 一月 14, 2026 [https://dev.to/simplr\_sh/vector-databases-vs-postgresql-with-pgvector-for-rag-setups-1lg2](https://dev.to/simplr_sh/vector-databases-vs-postgresql-with-pgvector-for-rag-setups-1lg2)
17. The Case Against pgvector | Alex Jacobs, 访问时间为 一月 14, 2026 [https://alex-jacobs.com/posts/the-case-against-pgvector/](https://alex-jacobs.com/posts/the-case-against-pgvector/)
18. Supercharging vector search performance and relevance with pgvector 0.8.0 on Amazon Aurora PostgreSQL | AWS Database Blog, 访问时间为 一月 14, 2026 [https://aws.amazon.com/blogs/database/supercharging-vector-search-performance-and-relevance-with-pgvector-0-8-0-on-amazon-aurora-postgresql/](https://aws.amazon.com/blogs/database/supercharging-vector-search-performance-and-relevance-with-pgvector-0-8-0-on-amazon-aurora-postgresql/)
19. 访问时间为 一月 14, 2026 [https://www.instaclustr.com/education/vector-database/pgvector-key-features-tutorial-and-pros-and-cons-2026-guide/\#:\~:text=pgvector%20inherits%20PostgreSQL's%20scalability%20limits,strategies%20or%20external%20vector%20systems.](https://www.instaclustr.com/education/vector-database/pgvector-key-features-tutorial-and-pros-and-cons-2026-guide/#:~:text=pgvector%20inherits%20PostgreSQL's%20scalability%20limits,strategies%20or%20external%20vector%20systems.)
20. Beyond PGVector: When Your Vector Database Needs a Formula 1 Upgrade \- Zilliz blog, 访问时间为 一月 14, 2026 [https://zilliz.com/blog/beyond-pgvector-when-your-vectordb-need-a-formula-one-upgrade](https://zilliz.com/blog/beyond-pgvector-when-your-vectordb-need-a-formula-one-upgrade)
21. PGVector \- Docs by LangChain, 访问时间为 一月 14, 2026 [https://python.langchain.com/docs/integrations/vectorstores/pgvector/](https://python.langchain.com/docs/integrations/vectorstores/pgvector/)
22. PGVectorStore \- Docs by LangChain, 访问时间为 一月 14, 2026 [https://docs.langchain.com/oss/javascript/integrations/vectorstores/pgvector](https://docs.langchain.com/oss/javascript/integrations/vectorstores/pgvector)
23. Postgres Vector Store | LlamaIndex Python Documentation, 访问时间为 一月 14, 2026 [https://developers.llamaindex.ai/python/examples/vector\_stores/postgres/](https://developers.llamaindex.ai/python/examples/vector_stores/postgres/)
24. How do I use the pgvector extension to perform vector similarity searches? \- ApsaraDB RDS \- Alibaba Cloud Documentation Center, 访问时间为 一月 14, 2026 [https://www.alibabacloud.com/help/en/rds/apsaradb-rds-for-postgresql/pgvector-use-guide](https://www.alibabacloud.com/help/en/rds/apsaradb-rds-for-postgresql/pgvector-use-guide)
25. ApsaraDB RDS:AliPG minor engine version release notes (PostgreSQL 1418) \- Alibaba Cloud, 访问时间为 一月 14, 2026 [https://www.alibabacloud.com/help/en/rds/apsaradb-rds-for-postgresql/release-notes-for-alipg](https://www.alibabacloud.com/help/en/rds/apsaradb-rds-for-postgresql/release-notes-for-alipg)
26. Overview \- Tencent Cloud, 访问时间为 一月 14, 2026 [https://www.tencentcloud.com/document/product/409/47734](https://www.tencentcloud.com/document/product/409/47734)
27. Kernel Version Release Notes \- Tencent Cloud, 访问时间为 一月 14, 2026 [https://www.tencentcloud.com/document/product/409/44365](https://www.tencentcloud.com/document/product/409/44365)
28. pgvector \- Cloud Service Help Center \- Huawei, 访问时间为 一月 14, 2026 [https://doc.hcs.huawei.com/usermanual/rds/rds\_09\_0062.html](https://doc.hcs.huawei.com/usermanual/rds/rds_09_0062.html)
29. pgvector\_Extension Management\_User Guide\_Relational Database Service\_RDS for PostgreSQL-Huawei Cloud, 访问时间为 一月 14, 2026 [https://support.huaweicloud.com/intl/en-us/usermanual-rds-pg/rds\_09\_0062.html](https://support.huaweicloud.com/intl/en-us/usermanual-rds-pg/rds_09_0062.html)
30. Mastering RAG: Precision techniques for table-heavy documents \- Kx Systems, 访问时间为 一月 14, 2026 [https://kx.com/blog/mastering-rag-precision-techniques-for-table-heavy-documents/](https://kx.com/blog/mastering-rag-precision-techniques-for-table-heavy-documents/)
31. Knowledge Table — Multi-Document RAG (Extraction & Memory) | by Chia Jeng Yang, 访问时间为 一月 14, 2026 [https://medium.com/enterprise-rag/knowledge-table-multi-document-rag-extraction-memory-ec08450e858f](https://medium.com/enterprise-rag/knowledge-table-multi-document-rag-extraction-memory-ec08450e858f)
32. Accelerate HNSW indexing and searching with pgvector on Amazon Aurora PostgreSQL-compatible edition and Amazon RDS for PostgreSQL | AWS Database Blog, 访问时间为 一月 14, 2026 [https://aws.amazon.com/blogs/database/accelerate-hnsw-indexing-and-searching-with-pgvector-on-amazon-aurora-postgresql-compatible-edition-and-amazon-rds-for-postgresql/](https://aws.amazon.com/blogs/database/accelerate-hnsw-indexing-and-searching-with-pgvector-on-amazon-aurora-postgresql-compatible-edition-and-amazon-rds-for-postgresql/)

View File

@@ -0,0 +1,672 @@
# PKB 模块Dify 替换为 pgvector 开发计划
> **文档版本:** v1.0
> **创建日期:** 2026-01-19
> **预计工期:** 2 周10个工作日
> **前置条件:** ✅ pgvector 0.8.1 已安装
> **目标:** 用 PostgreSQL + pgvector 原生 RAG 替代 Dify实现 R-C-R-G 混合检索架构
---
## 📊 整体难度评估
### 总体评估:⭐⭐⭐ 中等难度
| 评估维度 | 难度 | 说明 |
|----------|------|------|
| **数据库设计** | ⭐⭐ 低 | Prisma schema 直接写pgvector 已就绪 |
| **Embedding 服务** | ⭐⭐ 低 | 调用阿里云 API简单封装 |
| **文档切片** | ⭐⭐ 低 | 成熟方案RecursiveCharacterTextSplitter |
| **全要素提取** | ⭐⭐⭐ 中 | 需要调优 Prompt处理 JSON 异常 |
| **向量检索** | ⭐⭐⭐ 中 | pgvector SQL 语法需要学习 |
| **混合检索RRF** | ⭐⭐⭐ 中 | 核心算法,需要调优 |
| **服务替换** | ⭐⭐⭐⭐ 中高 | 需要保持 API 兼容,测试覆盖 |
| **数据迁移** | ⭐⭐⭐ 中 | 现有文档需重新向量化 |
**综合评估**:技术上完全可行,主要挑战在于**服务替换的平滑过渡**和**检索效果调优**。
---
## 🔥 核心挑战分析
### 挑战 1混合检索效果调优 🔴 高风险
**问题描述**
- 替换 Dify 后,检索效果可能下降
- 需要调优向量检索 + 关键词检索的权重
- RRF 参数k 值)需要实验确定
**应对策略**
- 准备测试数据集100+ 查询)
- 建立效果评估指标Recall@K, MRR
- 先用小批量数据验证,再全量迁移
**预留时间**2 天专门用于调优
---
### 挑战 2全要素提取的准确性 🟡 中风险
**问题描述**
- LLM 提取的 JSON 可能格式错误
- PICO、用药方案等字段提取不完整
- 不同类型文献RCT/综述/病例)提取策略不同
**应对策略**
- 三层 JSON 解析容错(直接解析 → 提取代码块 → LLM修复
- 字段级校验(必填字段、类型校验)
- 分文献类型设计 Prompt
**预留时间**1 天用于 Prompt 调优
---
### 挑战 3服务替换的兼容性 🟡 中风险
**问题描述**
- 需要保持 API 接口不变(前端零修改)
- `searchKnowledgeBase()` 返回格式需兼容
- 文档上传流程需要无缝切换
**应对策略**
- 定义适配层,转换返回格式
- 新旧服务并行运行,灰度切换
- 充分测试所有使用场景
**预留时间**1 天专门用于兼容性测试
---
### 挑战 4向量数据的批量处理 🟢 低风险
**问题描述**
- 批量 Embedding 调用需要控制并发
- 阿里云 API 有 QPS 限制
- 大文档切片后向量较多
**应对策略**
- 使用 p-queue 控制并发(固定 3 并发)
- 批量 Embedding每次最多 25 条)
- 增量处理,支持断点续传
---
## 📅 详细开发计划
### 总览时间线
```
Week 1: 基础设施 + 核心服务开发
├── Day 1: 数据库设计 + Prisma 迁移
├── Day 2: Embedding 服务 + 切片服务
├── Day 3: 全要素提取服务Prompt 调优)
├── Day 4: 向量检索服务pgvector SQL
├── Day 5: 混合检索 + RRF 融合
Week 2: 服务替换 + 测试 + 迁移
├── Day 6: 修改 knowledgeBaseService检索替换
├── Day 7: 修改 documentService上传替换
├── Day 8: 集成测试 + 效果调优
├── Day 9: 数据迁移(现有文档向量化)
├── Day 10: 清理 + 文档 + 上线
```
---
### Day 1数据库设计 + Prisma 迁移
**目标**:创建向量存储的数据表
**任务清单**
- [ ] 设计 `EkbDocument` 表(增强文档,含临床数据 JSONB 字段)
- [ ] 设计 `EkbChunk` 表(向量切片,含 pgvector 字段)
- [ ] 编写 Prisma schema
- [ ] 运行 `prisma migrate dev`
- [ ] 创建 HNSW 索引(手动 SQL
- [ ] 验证向量插入和查询
**交付物**
- `prisma/schema.prisma` 更新
- `migrations/xxx_add_ekb_tables.sql`
- 索引创建脚本
**预计工时**4-6 小时
**关键代码**
```prisma
// schema.prisma
model EkbDocument {
id String @id @default(uuid())
kbId String
userId String
// 基础信息
filename String
fileType String
fileSizeBytes BigInt
fileUrl String // 原始 PDF 的 OSS 地址
extractedText String? @db.Text // 解析后的 Markdown/文本
// 临床数据JSONB
pico Json?
studyDesign Json?
regimen Json?
safety Json?
criteria Json?
endpoints Json?
// 状态
status String @default("pending")
errorMessage String? @db.Text
chunks EkbChunk[]
knowledgeBase KnowledgeBase @relation(fields: [kbId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([kbId])
@@index([status])
@@schema("pkb_schema")
}
model EkbChunk {
id String @id @default(uuid())
documentId String
content String @db.Text
pageNumber Int?
sectionType String?
// pgvector 字段(需要手动创建)
embedding Unsupported("vector(1024)")?
document EkbDocument @relation(fields: [documentId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
@@index([documentId])
@@schema("pkb_schema")
}
```
**手动 SQL创建索引**
```sql
-- 创建 HNSW 索引
CREATE INDEX IF NOT EXISTS ekb_chunk_embedding_idx
ON "pkb_schema"."EkbChunk"
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- 创建全文检索索引
CREATE INDEX IF NOT EXISTS ekb_chunk_content_idx
ON "pkb_schema"."EkbChunk"
USING gin (to_tsvector('simple', content));
-- 创建 JSONB GIN 索引(用于临床数据查询)
CREATE INDEX IF NOT EXISTS ekb_document_pico_idx
ON "pkb_schema"."EkbDocument"
USING gin (pico);
CREATE INDEX IF NOT EXISTS ekb_document_safety_idx
ON "pkb_schema"."EkbDocument"
USING gin (safety);
```
---
### Day 2Embedding 服务 + 切片服务
**目标**:实现文本向量化和文档切片
**任务清单**
- [ ] 创建 `EmbeddingService.ts`(阿里云 text-embedding-v3
- [ ] 创建 `ChunkService.ts`RecursiveCharacterTextSplitter
- [ ] 单元测试Embedding API 调用
- [ ] 单元测试:切片效果验证
- [ ] 环境变量配置DASHSCOPE_API_KEY
**交付物**
- `backend/src/common/rag/EmbeddingService.ts`
- `backend/src/common/rag/ChunkService.ts`
- 单元测试文件
**预计工时**4-6 小时
**关键代码**
```typescript
// 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[]> { ... }
}
// ChunkService.ts
export class ChunkService {
splitDocument(
text: string,
options: { chunkSize: number; chunkOverlap: number }
): Chunk[] { ... }
detectSections(text: string): Section[] { ... }
}
```
---
### Day 3全要素提取服务
**目标**:实现 PICO、用药方案等临床数据的 AI 提取
**任务清单**
- [ ] 创建 `ClinicalExtractionService.ts`
- [ ] 设计提取 Prompt参考 EKB 方案)
- [ ] 实现三层 JSON 解析容错
- [ ] 测试不同类型文献RCT、综述、病例
- [ ] Prompt 调优(提高提取准确率)
**交付物**
- `backend/src/modules/pkb/services/ClinicalExtractionService.ts`
- `backend/prompts/clinical_extraction.txt`
- 测试用例
**预计工时**6-8 小时(含 Prompt 调优)
**关键 Prompt**
```
你是一个医学数据专家。请阅读这篇文献,严格按照以下 JSON 格式提取关键信息。
如果文中未提及字段留空null
提取字段:
1. pico: { "P": "患者人群", "I": "干预措施", "C": "对照", "O": "结局指标" }
2. studyDesign: { "design": "研究类型", "sampleSize": 数字, "blinding": "盲法" }
3. regimen: [{ "drug": "药物名", "dose": "剂量", "frequency": "频率" }]
4. safety: { "ae_all": ["不良反应列表"], "ae_grade34": ["严重不良反应"] }
5. criteria: { "inclusion": ["纳入标准"], "exclusion": ["排除标准"] }
6. endpoints: { "primary": ["主要终点"], "secondary": ["次要终点"] }
输出必须是纯 JSON不要有任何前言或后缀。
---
文献内容:
{{fullText}}
```
---
### Day 4向量检索服务pgvector SQL
**目标**:实现基于 pgvector 的向量检索
**任务清单**
- [ ] 创建 `VectorSearchService.ts`
- [ ] 实现向量检索(余弦相似度)
- [ ] 实现关键词检索PostgreSQL FTS
- [ ] 测试检索性能1000+ 向量)
- [ ] 优化查询(索引使用验证)
**交付物**
- `backend/src/common/rag/VectorSearchService.ts`
- 性能测试报告
**预计工时**6 小时
**关键 SQL**
```sql
-- 向量检索
SELECT
c.id,
c.content,
d.filename,
1 - (c.embedding <=> $1::vector) as score
FROM "pkb_schema"."EkbChunk" c
JOIN "pkb_schema"."EkbDocument" d ON c."documentId" = d.id
WHERE d."kbId" = $2
ORDER BY c.embedding <=> $1::vector
LIMIT $3;
-- 关键词检索
SELECT
c.id,
c.content,
d.filename,
ts_rank_cd(to_tsvector('simple', c.content), plainto_tsquery('simple', $1)) as score
FROM "pkb_schema"."EkbChunk" c
JOIN "pkb_schema"."EkbDocument" d ON c."documentId" = d.id
WHERE d."kbId" = $2
AND to_tsvector('simple', c.content) @@ plainto_tsquery('simple', $1)
ORDER BY score DESC
LIMIT $3;
```
---
### Day 5混合检索 + RRF 融合
**目标**:实现 R-C-R-G 架构中的混合检索
**任务清单**
- [ ] 实现 RRFReciprocal Rank Fusion算法
- [ ] 实现并发三路检索(向量 + 关键词 + SQL 筛选)
- [ ] 集成 Rerank API可选qwen-rerank
- [ ] 效果评估(对比 Dify 检索)
- [ ] 参数调优k 值、权重)
**交付物**
- RRF 融合模块
- 效果评估报告
**预计工时**6-8 小时
**RRF 算法**
```typescript
function rrfFusion(
vectorResults: Result[],
keywordResults: Result[],
k: number = 60 // RRF 常数,通常取 60
): Result[] {
const scoreMap = new Map<string, number>();
// 计算 RRF 分数
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 }));
}
```
---
### Day 6修改 knowledgeBaseService检索替换
**目标**:替换 Dify 检索为 pgvector 检索
**任务清单**
- [ ] 修改 `searchKnowledgeBase()` 函数
- [ ] 移除 `difyClient.retrieveKnowledge()` 调用
- [ ] 使用 `vectorSearchService.hybridSearch()`
- [ ] 保持返回格式兼容(前端零修改)
- [ ] 单元测试
**交付物**
- 更新后的 `knowledgeBaseService.ts`
**预计工时**4 小时
**关键修改**
```typescript
// 修改前
const results = await difyClient.retrieveKnowledge(
knowledgeBase.difyDatasetId,
query,
{ retrieval_model: { search_method: 'semantic_search', top_k: topK } }
);
// 修改后
const searchResults = await vectorSearchService.hybridSearch(kbId, query, topK);
// 格式转换(保持兼容)
return {
query: { content: query },
records: searchResults.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 7修改 documentService上传替换
**目标**:替换 Dify 上传流程为本地向量化流程
**任务清单**
- [ ] 修改 `uploadDocument()` 函数
- [ ] 移除 `difyClient.uploadDocumentDirectly()` 调用
- [ ] 实现本地处理流程(提取 → 切片 → 向量化)
- [ ] 移除 Dify 状态轮询逻辑
- [ ] 实现自己的异步处理和状态更新
- [ ] 单元测试
**交付物**
- 更新后的 `documentService.ts`
**预计工时**6 小时
---
### Day 8集成测试 + 效果调优
**目标**:端到端测试,确保功能正常
**任务清单**
- [ ] 前端测试:创建知识库
- [ ] 前端测试:上传文档
- [ ] 前端测试RAG 检索问答
- [ ] 效果对比Dify vs pgvector 检索质量
- [ ] 性能测试:检索延迟
- [ ] Bug 修复
**交付物**
- 测试报告
- Bug 修复记录
**预计工时**8 小时
---
### Day 9数据迁移现有文档向量化
**目标**:将现有知识库文档迁移到新表并向量化
**任务清单**
- [ ] 编写迁移脚本Document → EkbDocument
- [ ] 批量向量化现有文档
- [ ] 验证迁移完整性
- [ ] 验证检索效果
**交付物**
- `scripts/migrate-to-ekb.ts`
- 迁移日志
**预计工时**6 小时
**迁移脚本**
```typescript
// scripts/migrate-to-ekb.ts
async function migrateDocuments() {
// 1. 获取所有现有文档
const documents = await prisma.document.findMany({
where: { status: 'completed', extractedText: { not: null } },
});
console.log(`Found ${documents.length} documents to migrate`);
// 2. 逐个迁移
for (const doc of documents) {
try {
// 创建 EkbDocument
const ekbDoc = await prisma.ekbDocument.create({
data: {
kbId: doc.kbId,
userId: doc.userId,
filename: doc.filename,
fileType: doc.fileType,
fileSizeBytes: doc.fileSizeBytes,
extractedText: doc.extractedText,
status: 'embedding',
},
});
// 切片
const chunks = chunkService.splitDocument(doc.extractedText!);
// 向量化
const embeddings = await embeddingService.embedBatch(
chunks.map(c => c.content)
);
// 存入数据库
// ...
console.log(`✅ Migrated: ${doc.filename}`);
} catch (error) {
console.error(`❌ Failed: ${doc.filename}`, error);
}
}
}
```
---
### Day 10清理 + 文档 + 上线
**目标**:清理遗留代码,更新文档,正式上线
**任务清单**
- [ ] 删除 `DifyClient.ts`
- [ ] 删除 `difyDatasetId` 字段(可选,下个版本)
- [ ] 删除 `difyDocumentId` 字段(可选,下个版本)
- [ ] 更新 `00-模块当前状态与开发指南.md`
- [ ] 更新环境变量文档
- [ ] 代码 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 |
---
## ✅ 验收标准
### 功能验收
- [ ] 创建知识库:不依赖 Dify直接创建
- [ ] 上传文档:本地处理 + 向量化
- [ ] RAG 检索:混合检索效果 ≥ Dify
- [ ] 全文阅读模式:正常工作
- [ ] 批处理模式:正常工作
### 性能验收
- [ ] 检索延迟:< 500ms95 分位)
- [ ] 上传处理:< 60s/文档(平均)
- [ ] 向量化吞吐:> 100 文档/小时
### 质量验收
- [ ] 检索召回率:≥ 80%(测试集)
- [ ] 无 Dify 相关代码残留
- [ ] 文档更新完整
---
## 📝 附录
### A. 相关文档
- [企业级医学知识库综合技术解决方案 V2](../00-系统设计/企业级医学知识库_综合技术解决方案%20V2.md)
- [PostgreSQL与pgvector深度应用分析](../00-系统设计/医疗科研AI系统架构评估报告PostgreSQL与pgvector在RAG及知识库中的深度应用分析.md)
- [PKB模块当前状态](../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": {
// 新增
"langchain": "^0.1.0", // 可选,用于切片
"p-queue": "^8.0.0" // 并发控制
}
}
```
---
**文档维护**PKB 模块开发团队
**最后更新**2026-01-19
**下次更新**:开发完成后更新进度

View File

@@ -368,3 +368,4 @@ const newResults = resultsData.map((docResult: any) => ({

View File

@@ -776,5 +776,6 @@ docker exec redcap-apache php /tmp/create-redcap-password.php

View File

@@ -158,5 +158,6 @@ AIclinicalresearch/redcap-docker-dev/