Files
AIclinicalresearch/docs/09-架构实施/07-架构决策-新增EKB独立Schema.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

151 lines
7.0 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.
# **架构决策记录 (ADR-013):关于新增第 13 个 Schema (ekb\_schema) 的提案**
状态: 🟢 提议中 (Proposed)
日期: 2026-01-20
决策者: 架构师 & 开发团队
涉及模块: 知识库引擎 (EKB), 个人知识库 (PKB), 智能文献 (ASL), 智能问答 (AIA)
## **1\. 背景与问题**
目前我们的 Postgres-Only 架构已成功实施了 12 个 Schema 的隔离策略platform, common, pkb, asl 等)。
随着 **知识库引擎 (Knowledge Base Engine)** 的引入我们需要存储海量的向量切片数据EkbChunk 表和多模态文档数据EkbDocument 表)。
**当前面临的问题是:这些数据应该存放在哪里?**
我们面临三个选项:
1. **选项 A**:放在 pkb Schema 中(因为 PKB 是第一个使用者)。
2. **选项 B**:放在 common 或 capability Schema 中(因为它是通用能力)。
3. **选项 C**:新建第 13 个独立 Schema —— **ekb\_schema**
## **2\. 决策结论**
**我们决定采用【选项 C】创建独立的 ekb\_schema。**
这意味着我们的 Prisma datasource 配置将包含 13 个 Schema
schemas \= \[..., "ekb\_schema"\]
## **3\. 决策详细理由**
### **3.1 架构分层:避免依赖倒置 (Dependency Inversion)**
知识库引擎是**底层基础设施Infrastructure Layer**,类似于“图书馆大楼”;而 PKB、ASL、AIA 是**上层业务应用Application Layer**,类似于“租户”。
* 如果将引擎表放在 pkb Schema 中会导致逻辑上的“ASL 依赖 PKB”这是错误的依赖关系。
* 通过独立 ekb\_schema所有业务模块PKB, ASL, AIA都平等地依赖 EKB架构层次清晰。
### **3.2 运维隔离:重型数据的特殊需求**
向量表 (EkbChunk) 具有显著的\*\*“重数据”\*\*特征:
* **数据量大**:可能迅速增长到百万/千万行级别。
* **索引特殊**:使用 HNSW 向量索引,构建和维护成本高。
* **维护频繁**:向量表对 UPDATE/DELETE 敏感,需要更激进的 VACUUM (垃圾回收) 策略。
将其隔离在独立 Schema 中,允许 DBA 未来针对该 Schema 进行独立的性能调优(如分配特定的 Tablespace 或调整内存参数),而不影响 users 或 orders 等轻量级业务表。
### **3.3 业务边界清晰**
* common存放纯技术组件Log, Storage 记录)。
* capability存放轻量级业务配置Prompt 模板)。
* ekb\_schema存放核心知识资产和向量数据。
混在一起会导致 common 变得极其臃肿,增加后续拆分微服务的难度。
## **4\. 性能影响评估 (Performance Review)**
团队可能担心“13 个 Schema 会不会太多?会不会拖慢速度?”
**技术评估结论对性能几乎无负面影响Zero Overhead**
| 关注点 | 技术事实 | 结论 |
| :---- | :---- | :---- |
| **查询速度** | PostgreSQL 内部使用 OID 查找表Schema 只是逻辑命名空间。跨 Schema Join (JOIN ekb.Chunk) 与同 Schema Join 性能完全一致。 | ✅ 无损耗 |
| **连接资源** | 我们使用的是 Prisma 单一连接池。所有 Schema 复用同一个 TCP 连接,不增加数据库连接数。 | ✅ 无损耗 |
| **内存占用** | Schema 本身只占用极少的元数据空间。Postgres 支持单库数千个 Schema 毫无压力。 | ✅ 可忽略 |
| **维护效率** | 独立的 Schema 让 pg\_dump 备份和 VACUUM 维护更灵活(可只备份业务数据,单独备份向量数据)。 | ✅ 正向收益 |
## **5\. 潜在风险与应对 (Risks & Mitigation)**
虽然性能无忧,但在多 Schema 开发中存在以下“坑”,需提前规避:
### **🔧 坑 1Prisma 的跨 Schema 关联**
* **问题**:跨 Schema 定义外键(如 EkbDocument 关联 User容易因缺少标记报错。
* **解决方案**
1. **显式标记**:关联的两个 Model 必须都带有 @@schema("...") 标记。
2. **双向定义**:在两边都定义 @relation 字段,确保 Prisma Client 能正确生成跨 Schema 的 Join 查询。
3. **弱关联推荐**:对于非强一致性业务,建议仅存储 ID 字符串(如 userId减少数据库层面的硬外键约束提升灵活性。
### **🔧 坑 2原生 SQL 的写法复杂度**
* **问题**:在使用 prisma.$queryRaw 进行向量检索时,很容易忘记加 Schema 前缀,导致 Relation "EkbChunk" does not exist 错误。
* **解决方案**
* **强制带前缀**:在写 SQL 时必须使用双引号包裹 Schema 和表名,例如 FROM "ekb\_schema"."EkbChunk"。
* **封装服务**:禁止在 Controller 层写 SQL所有向量检索逻辑必须封装在 KnowledgeBaseEngine 类中,屏蔽底层细节。
### **🔧 坑 3迁移文件管理 (Migration Clutter)**
* **问题**Prisma 将所有 Schema 的变更都放在同一个 prisma/migrations 文件夹下,文件多了容易混乱。
* **解决方案**
* **命名规范**:执行迁移时强制加前缀。
* ✅ npx prisma migrate dev \--name ekb\_init\_vector\_table
* ✅ npx prisma migrate dev \--name aia\_update\_agents
* 这样在排查问题时,能一眼看出该 Migration 属于哪个模块。
## **6\. 实施计划 (Implementation)**
### **步骤 1: 更新 Prisma 配置**
在 prisma/schema.prisma 中:
generator client {
provider \= "prisma-client-js"
previewFeatures \= \["multiSchema", "postgresqlExtensions"\]
}
datasource db {
provider \= "postgresql"
url \= env("DATABASE\_URL")
extensions \= \[vector, pg\_bigm\] // 确保启用插件
// 添加新的 schema
schemas \= \[..., "capability", "ekb\_schema"\]
}
### **步骤 2: 定义模型**
将 04-数据模型设计.md 中的模型放入:
model EkbKnowledgeBase {
// ... 字段定义
@@schema("ekb\_schema") // 👈 关键点
}
model EkbDocument {
// ... 字段定义
kbId String
kb EkbKnowledgeBase @relation(fields: \[kbId\], references: \[id\])
@@schema("ekb\_schema")
}
// ... EkbChunk 同理
### **步骤 3: 跨 Schema 关联 (注意事项)**
如果业务表(如 pkb\_schema.UserPkbConfig需要关联知识库
// 在 pkb\_schema 中
model UserPkbConfig {
id String @id
kbId String
kb EkbKnowledgeBase @relation(fields: \[kbId\], references: \[id\]) // 👈 跨 Schema 关联支持良好
@@schema("pkb")
}
## **7\. 常见问题 (FAQ)**
Q: 以后如果要把 EKB 拆成独立微服务怎么办?
A: 正因为我们现在用了独立的 Schema拆分微服务时只需要把这个 Schema 导出,部署到新数据库即可。如果混在 pkb 里,拆分反而极其痛苦。
Q: 为什么不放在 capability Schema
A: capability 目前主要存 Prompt 模板,数据量极小。而 ekb 未来会有大量向量数据,体量差异过大,建议物理上保持逻辑距离。
**结论:** 创建第 13 个 Schema 是符合我们“Postgres-Only \+ 模块化”架构原则的最佳实践,既保证了性能,又为未来的运维和扩展留足了空间。