feat(db): 启动本项目专属知识库容器并完成法规数据无损迁移与解耦

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
WeiCHEN
2026-09-07 23:40:23 +08:00
co-authored by Cursor
parent d8a7254c1b
commit 0f21060bce
4 changed files with 485 additions and 27 deletions
+83 -27
View File
@@ -1,34 +1,90 @@
-- 共享知识库 (Shared Knowledge Base) 初始化脚本
-- pgvector 扩展及基础条目库
-- =============================================================================
-- 共享知识库基础设施 (Shared Knowledge Base) 数据库初始化脚本
-- 适用于三套环境服务共享的 pgvector 向量数据库 (shuimu-kb-shared:5432)
-- 支持多领域知识中枢:法规标准 (Regulatory) + 项目数字资产 (ProjectAsset) + 员工能力模型 (StaffCapability)
-- =============================================================================
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE TABLE IF NOT EXISTS kb_documents (
id BIGSERIAL PRIMARY KEY,
title TEXT NOT NULL,
doc_no TEXT NOT NULL DEFAULT '',
category TEXT NOT NULL DEFAULT '',
content TEXT NOT NULL,
embedding vector(1024),
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
-- =============================================================================
-- 领域一:法规标准知识领域 (Domain: Regulatory)
-- 包含医疗器械法律法规、国家标准(GB/T)、行业标准(YY)及指导原则
-- 注:reg_* 系列表结构及 2,907 篇法规基线数据由流式迁移转储脚本导入
-- =============================================================================
-- =============================================================================
-- 领域二:项目数字资产知识领域 (Domain: ProjectAsset, 预留与扩展)
-- 沉淀已完成项目的可行性报告、CDO 报价模型、系统方案、BOM、踩坑避险记录
-- =============================================================================
CREATE TABLE IF NOT EXISTS asset_projects (
id BIGSERIAL PRIMARY KEY,
project_code TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
device_type TEXT NOT NULL DEFAULT '',
customer_name TEXT NOT NULL DEFAULT '',
stage_reached TEXT NOT NULL DEFAULT '',
summary TEXT NOT NULL DEFAULT '',
metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_kb_doc_title ON kb_documents USING gin (title gin_trgm_ops);
CREATE INDEX IF NOT EXISTS idx_kb_doc_no ON kb_documents(doc_no);
CREATE INDEX IF NOT EXISTS idx_kb_category ON kb_documents(category);
-- 共享法规/知识切片表
CREATE TABLE IF NOT EXISTS kb_chunks (
id BIGSERIAL PRIMARY KEY,
document_id BIGINT REFERENCES kb_documents(id) ON DELETE CASCADE,
chunk_index INT NOT NULL DEFAULT 0,
chunk_text TEXT NOT NULL,
embedding vector(1024),
tokens_count INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
CREATE TABLE IF NOT EXISTS asset_documents (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT REFERENCES asset_projects(id) ON DELETE CASCADE,
doc_type TEXT NOT NULL, -- feasibility, quote, cad, pcb, bom, testing
title TEXT NOT NULL,
file_path TEXT NOT NULL,
metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_kb_chunk_doc ON kb_chunks(document_id);
CREATE TABLE IF NOT EXISTS asset_chunks (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT REFERENCES asset_projects(id) ON DELETE CASCADE,
document_id BIGINT REFERENCES asset_documents(id) ON DELETE CASCADE,
chunk_title TEXT NOT NULL DEFAULT '',
content TEXT NOT NULL,
cite_key TEXT NOT NULL DEFAULT '',
embedding vector(1024),
tsv tsvector,
metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_asset_chunks_project ON asset_chunks(project_id);
CREATE INDEX IF NOT EXISTS idx_asset_chunks_doc ON asset_chunks(document_id);
CREATE INDEX IF NOT EXISTS idx_asset_chunks_tsv ON asset_chunks USING gin (tsv);
-- =============================================================================
-- 领域三:员工工作能力知识领域 (Domain: StaffCapability, 预留与扩展)
-- 沉淀研发工程师专长技能图谱、历史人效系数、工时评估模型,辅助智能排班与精准估算
-- =============================================================================
CREATE TABLE IF NOT EXISTS staff_profiles (
id BIGSERIAL PRIMARY KEY,
staff_code TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
role_category TEXT NOT NULL, -- optical, mechanical, hardware, firmware, algorithm, regulatory, qa
seniority_level TEXT NOT NULL DEFAULT 'senior',
skills TEXT[] NOT NULL DEFAULT '{}',
hourly_rate_cny NUMERIC(10,2) NOT NULL DEFAULT 0.00,
metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS staff_experience_records (
id BIGSERIAL PRIMARY KEY,
staff_id BIGINT REFERENCES staff_profiles(id) ON DELETE CASCADE,
project_code TEXT NOT NULL DEFAULT '',
task_type TEXT NOT NULL,
planned_hours NUMERIC(8,2) NOT NULL DEFAULT 0.00,
actual_hours NUMERIC(8,2) NOT NULL DEFAULT 0.00,
variance_ratio NUMERIC(5,2) NOT NULL DEFAULT 1.00,
learnings TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_staff_exp_staff ON staff_experience_records(staff_id);
CREATE INDEX IF NOT EXISTS idx_staff_exp_task ON staff_experience_records(task_type);
@@ -0,0 +1,134 @@
# 多领域知识中枢与专属法规知识库迁移集成实施计划 (Multi-Domain Knowledge Hub Plan)
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 启动本项目专有容器 `shuimu-kb-shared`,完成参考项目 2,907 篇法规数据的无损流式冷迁移与解耦,并在 `internal/kb` 构建支持法规、项目资产与员工能力的多领域知识中枢(Multi-Domain Knowledge Hub),实现 Hybrid RRF 检索与 Reranker 重排,最终在智能体小队工作区实现动态知识注入。
**Architecture:**
1. 基础设施层:基于 `docker-compose.shared.yml` 运行本项目独立的 `shuimu-kb-shared:5432`,使用流式 `pg_dump | psql` 完成零侵入数据迁移并更新配置,彻底与参考项目容器解耦;
2. 引擎服务层:在 `internal/kb` 中封装通用 Embedder、Reranker 与 PostgreSQL 存储层,提供支持 `regulatory`、`project_asset`、`staff_capability` 多命名空间路由的统一 `Hub` 接口;
3. 智能体集成层:在 `internal/bizdev` 与 `internal/squad` 中将项目事实转化为结构化检索词,检索法规知识并生成权威上下文注入智能体工作区,完成实测并输出标准化测试报告。
**Tech Stack:** Go 1.22+, PostgreSQL 16 + pgvector, bge-m3 (SiliconFlow/Local Embedding), bge-reranker-v2-m3 (Reranker), pgx/v5, Docker.
## Global Constraints
- **彻底解耦**:本阶段完成后严禁依赖参考项目的 `agent-regkb`,必须使用本项目独立的 `shuimu-kb-shared`。
- **只读零侵入**:迁移过程对 `agent-regkb` 仅执行流式只读导出,严禁修改参考项目任何数据。
- **架构可扩展**:数据契约与接口设计必须原生支持多领域(`regulatory`, `project_asset`, `staff_capability`)。
- **渐进式提交**:分层提交(`feat(db)` -> `feat(service)` -> `feat(agent)` -> `test(kb)` -> `docs(test)`)。
- **真实 Agent 交付铁律**:最终交付测试报告必须包含真实 Agent 实测输出,严禁以 stub 输出充当交付结果。
---
### Task 1: 基础设施专属容器启动、数据流式迁移与环境解耦
**Files:**
- Modify: `docker-compose.shared.yml`
- Modify: `.env`
- Script: `scripts/migrate_shared_kb.sh`
**Interfaces:**
- Input: `agent-regkb:55432` (只读源)
- Output: `shuimu-kb-shared:5432` (宿主机映射 5432,独立数据卷 `chat-agent-shared-kb-pgdata`)
- Verification: 验证 `reg_documents` = 2,907 行,`reg_chunks` >= 312,900 行,数据库大小 ~2.3GB
- [ ] **Step 1: 检查并启动本项目专属知识库容器 `shuimu-kb-shared`**
- [ ] **Step 2: 执行流式零侵入数据转储与恢复迁移**
- [ ] **Step 3: 校验专有容器内数据完整性与表索引结构**
- [ ] **Step 4: 更新 `.env` 中 `KB_DB_PORT=5432` 彻底与参考项目解耦**
- [ ] **Step 5: 提交 Git:`feat(db): 启动本项目专属知识库容器并完成法规数据无损迁移与解耦`**
---
### Task 2: 多领域知识中枢数据模型与核心接口定义
**Files:**
- Create: `internal/kb/types.go`
- Create: `internal/kb/hub.go`
**Interfaces:**
- Produces: `KnowledgeDomain`, `HitItem`, `SearchOptions`, `Hub` 接口
- Consumes: Go 标准库
- [ ] **Step 1: 定义领域枚举 `DomainRegulatory`, `DomainProjectAsset`, `DomainStaffCapability`**
- [ ] **Step 2: 定义跨领域通用命中模型 `HitItem` 与检索选项 `SearchOptions`**
- [ ] **Step 3: 定义多领域知识中枢 `Hub` 接口规范**
- [ ] **Step 4: 编写接口骨架并确保通过 `go vet`**
---
### Task 3: 向量化 (Embedder) 与语义重排 (Reranker) 引擎实现
**Files:**
- Create: `internal/kb/embed.go`
- Create: `internal/kb/rerank.go`
- Modify: `internal/config/config.go` (加载 RERANKER 与 EMBEDDING 配置)
**Interfaces:**
- Produces: `Embedder.Embed(ctx, text) ([]float32, error)`
- Produces: `Reranker.Rerank(ctx, query, docs) ([]RerankResult, error)`
- Consumes: `.env` 中的 `EMBEDDING_*` 和 `RERANKER_*`
- [ ] **Step 1: 在 `internal/config` 中增加 Reranker 与 Embedder 配置字段**
- [ ] **Step 2: 实现 `internal/kb/embed.go`,适配 BGE-M3 (1024维)**
- [ ] **Step 3: 实现 `internal/kb/rerank.go`,适配 BGE-Reranker-v2-m3**
- [ ] **Step 4: 编写单元测试验证真实/模拟 Embedder 与 Reranker 调用**
---
### Task 4: PostgreSQL/pgvector 存储与 RRF 混合检索实现
**Files:**
- Create: `internal/kb/store.go`
- Create: `internal/kb/retrieve.go`
- Create: `internal/kb/cite_lookup.go`
- Modify: `internal/kb/client.go` (实现 `Hub` 接口,替换原有 stub)
**Interfaces:**
- Produces: `client.Search(ctx, query, opts) ([]HitItem, error)`
- Produces: `client.LookupCite(ctx, citeKey) (string, bool)`
- Produces: `client.Stats(ctx) (map[KnowledgeDomain]any, error)`
- Consumes: `pgxpool.Pool`
- [ ] **Step 1: 引入 `github.com/jackc/pgx/v5` 依赖**
- [ ] **Step 2: 实现 `internal/kb/store.go`,管理与 `shuimu-kb-shared` 的连接池与状态统计**
- [ ] **Step 3: 实现 `internal/kb/retrieve.go`,实现向量余弦 + tsvector 全文 + RRF 混合排序**
- [ ] **Step 4: 实现 `internal/kb/cite_lookup.go`,支持根据标准号定位精准条款**
- [ ] **Step 5: 在 `internal/kb/client.go` 组装统一门面 `HubClient`**
- [ ] **Step 6: 编写检索集成测试验证对真实数据库中《GB 9706.1》等核心标准的召回**
- [ ] **Step 7: 提交 Git:`feat(service): 实现嵌入式多领域知识中枢与Hybrid RRF检索引擎`**
---
### Task 5: 业务工作区动态法规检索与上下文注入
**Files:**
- Modify: `internal/squad/workspace.go`
- Modify: `internal/bizdev/service.go`
**Interfaces:**
- Produces: 自动生成 `context/knowledge/hits.md` 注入智能体沙箱
- Consumes: `Hub.Search` 与 `BlackboardFacts`
- [ ] **Step 1: 在 `bizdev/service.go` 中解析任务黑板事实并组装精准查询**
- [ ] **Step 2: 调用知识中枢检索关键法规与指导原则**
- [ ] **Step 3: 格式化权威层级与引用规范写入 `context/knowledge/hits.md`**
- [ ] **Step 4: 提交 Git:`feat(agent): 智能体小队工作区动态法规检索与上下文注入`**
---
### Task 6: 全链路集成验证、真实 Agent 测试与测试报告归档
**Files:**
- Create: `internal/kb/integration_test.go`
- Create: `.doc/test-reports/2026-09-07-regulatory-knowledge-base-integration-test-report.md`
**Interfaces:**
- Input: 包含有源电气医疗器械/内窥镜业务事实的工作区任务
- Output: 真实 Agent 输出并引用法规条文,生成标准化交付测试报告
- [ ] **Step 1: 运行全量 `go test ./...` 确保所有既有与新增测试通过**
- [ ] **Step 2: 运行包含知识注入的端到端真实智能体任务**
- [ ] **Step 3: 检查智能体产出中对标准条文(如 GB 9706.1)的真实引用**
- [ ] **Step 4: 按照规范生成测试报告并归档至 `.doc/test-reports/`**
- [ ] **Step 5: 提交 Git:`test(kb): 补充知识库端到端测试用例` 与 `docs(test): 归档法规知识库集成测试报告`**
@@ -0,0 +1,172 @@
# 多领域知识中枢与专属法规知识库迁移集成规范 (Multi-Domain Knowledge Hub Spec)
> 日期:2026-09-07
> 状态:Approved by User
> 模式:解耦专有容器流式迁移 + 嵌入式多领域知识中枢 (Decoupled Dedicated Container + Multi-Domain Knowledge Hub)
---
## 1. 背景与目标
### 1.1 背景
在阶段一的端到端真实智能体业务验证中,系统成功跑通了商机接入与分流工序(`intake`)。但在深入到后续的立项论证(`V0.5 Feasibility`)、技术调研(`research`)和法规可行性研判(`feasibility_reg`)时,智能体必须依赖权威的医疗器械法律法规、国家标准(GB/GB-T)、医药行标(YY)及指导原则支撑。
此前参考项目 `.refs/agent-system/` 中已构建了一个拥有 2,907 篇法规、312,919 个 1024 维切片、全文倒排索引的 PostgreSQL/pgvector 数据库,运行在 `agent-regkb` (端口 55432) 容器中。
用户的明确指导如下:
1. **彻底解耦独立自立**:本阶段任务完成后,绝不再使用参考项目的容器,必须创建本项目自己的独立容器;
2. **完整无损复用**:整体无损复制+迁移现有 2,907 篇法规库全部数据,且严禁破坏和影响参考项目的原法规库;
3. **面向未来多知识库扩展**:后续将陆续建立“已完成项目数字资产知识库”、“员工工作能力知识库”等,系统底层必须支持多领域知识库的可插拔接入。
### 1.2 目标 (Goals)
1. **专有共享容器落地与冷迁移**:
- 运行本项目独立的共享基础设施服务 `shuimu-kb-shared`(网络端口映射 `5432`,专有数据卷 `chat-agent-shared-kb-pgdata`);
- 从 `agent-regkb` 执行单向流式逻辑转储并恢复,达成 100% 数据一致性,原库完全只读零侵入;
- 本项目 `.env` 正式切回 `KB_DB_PORT=5432`。
2. **多领域知识中枢抽象 (Multi-Domain Knowledge Hub)**:
- 抽象 `KnowledgeDomain` 枚举(`regulatory`、`project_asset`、`staff_capability`);
- 提供统一的 `Hub` 接口与 `SearchOptions`,支持跨领域检索与按领域定向路由;
- 命名空间表前缀隔离(法规库 `reg_*`,项目资产库 `asset_*`,员工能力库 `staff_*`)。
3. **高品质混合检索 (Hybrid RRF & Rerank)**:
- 向量检索(余弦距离) + 关键词倒排检索(tsvector simple 字典);
- RRF(Reciprocal Rank Fusion)倒数排名融合算法(k=60);
- Cross-Encoder `bge-reranker-v2-m3` 二次语义重排打分与截断。
4. **智能体工作区动态注入**:
- 在 `internal/bizdev` 与 `internal/squad` 工作区构建时,根据黑板关键事实(如设备类型、适用范围、目标市场)自动检索关联法规;
- 结构化注入到智能体沙箱 `context/knowledge/hits.md`,并在生成产出中强制引用标准条款。
5. **符合 Git 三分支与测试报告规范**:
- 遵循分层渐进式提交(`feat(db)` -> `feat(service)` -> `feat(agent)` -> `test(kb)` -> `docs(test)`);
- 输出标准化测试报告归档至 `.doc/test-reports/`。
---
## 2. 总体架构与数据流图
```mermaid
flowchart TD
subgraph S1_ContainerMigration ["一、 容器与数据流式迁移 (彻底解耦)"]
AgentRegKB["参考项目容器: agent-regkb :55432 (只读)"]
ShuimuShared["本项目专属容器: shuimu-kb-shared :5432 (独立卷)"]
AgentRegKB -- "pg_dump 流式管道 (零侵入)" --> ShuimuShared
end
subgraph S2_MultiDomainHub ["二、 internal/kb 多领域知识中枢"]
KBHub["KnowledgeHub (统一接入门面)"]
RegDomain["Domain: Regulatory (reg_* 表)"]
AssetDomain["Domain: ProjectAsset (asset_* 预留)"]
StaffDomain["Domain: StaffCapability (staff_* 预留)"]
KBHub --> RegDomain
KBHub --> AssetDomain
KBHub --> StaffDomain
RegDomain --> PGVector["PostgreSQL / pgvector 存储池"]
RegDomain --> Embedder["BGE-M3 Embedder (1024维)"]
RegDomain --> RRF["RRF 混合排序 (Vector + FullText)"]
RegDomain --> Reranker["BGE-Reranker-v2-m3 重排"]
end
subgraph S3_AgentInjection ["三、 智能体协同与上下文注入"]
BizDev["BizDev 阶段驱动 (research / feasibility_reg)"]
Workspace["Squad 工作区上下文构建"]
AgentSandbox["Agent 真实执行沙箱: context/knowledge/hits.md"]
BizDev --> KBHub
KBHub --> Workspace
Workspace --> AgentSandbox
end
```
---
## 3. 详细模块设计与规范
### 3.1 容器与数据持久化规范
- **Compose 服务名**:`shared-kb-db`,容器名:`shuimu-kb-shared`,镜像:`pgvector/pgvector:pg16`;
- **网络与端口**:宿主机 `127.0.0.1:5432`,桥接网络 `chat-agent-shared-net`;
- **数据卷持久化**:独立卷 `chat-agent-shared-kb-pgdata`,物理文件隔离于参考项目;
- **迁移验证基准**:
- `reg_documents` 总行数 = 2,907;
- `reg_chunks` 总行数 >= 312,900;
- `pg_database_size('regulations')` 约为 2.3 GB。
### 3.2 领域抽象与数据契约 (`internal/kb/types.go`)
```go
type KnowledgeDomain string
const (
DomainRegulatory KnowledgeDomain = "regulatory" // 医疗器械法规标准
DomainProjectAsset KnowledgeDomain = "project_asset" // 历史项目数字资产 (预留)
DomainStaffCapability KnowledgeDomain = "staff_capability" // 员工能力与工时模型 (预留)
)
type HitItem struct {
Domain KnowledgeDomain `json:"domain"`
Category string `json:"category"`
DocCode string `json:"doc_code"`
Title string `json:"title"`
Content string `json:"content"`
HeadingPath string `json:"heading_path"`
Score float64 `json:"score"`
CiteKey string `json:"cite_key"`
Source string `json:"source"`
Metadata map[string]any `json:"metadata,omitempty"`
}
type SearchOptions struct {
Domains []KnowledgeDomain `json:"domains"`
Limit int `json:"limit"`
IncludeRepealed bool `json:"include_repealed"`
FilterCategory string `json:"filter_category,omitempty"`
}
type Hub interface {
Search(ctx context.Context, query string, opts SearchOptions) ([]HitItem, error)
LookupCite(ctx context.Context, citeKey string) (string, bool)
Stats(ctx context.Context) (map[KnowledgeDomain]any, error)
Close()
}
```
### 3.3 检索流水线与重排评分机制 (`internal/kb/`)
1. **向量化 (Embedder)**:调用 `EMBEDDING_ENDPOINT_URL`(SiliconFlow / 本地),使用模型 `BAAI/bge-m3` 生成 1024 维 float32 向量;
2. **两路召回 (Dual Retrieval)**:
- **向量路**:执行 pgvector 余弦距离计算 `<=>`,召回 top 40;
- **关键词路**:执行 tsvector `to_tsquery('simple', ...)` 结合全文匹配,召回 top 40;
3. **RRF 融合 (Reciprocal Rank Fusion)**:
\[
\text{Score}_{\text{RRF}}(d) = \sum_{m \in \{\text{vec}, \text{txt}\}} \frac{1}{60 + \text{rank}_m(d)}
\]
4. **重排 (Reranker)**:
- 提取融合后的 Top 20 候选切片;
- 调用 `RERANKER_ENDPOINT_URL`,使用 `BAAI/bge-reranker-v2-m3` 计算跨注意力交互评分;
- 截断输出 Top K(默认 5~8 条),附带清晰的权威层级与引用 Key。
### 3.4 智能体知识注入规范 (`internal/squad/workspace.go`)
当任务类型为 `research` 或 `feasibility_reg` 时:
1. 从 `workspace.json` 及黑板事实中提取查询词(如:“三类 医用内窥镜 欧洲CE 有源医疗器械 电气安全 GB 9706.1”);
2. 检索法规中枢,格式化为权威上下文存入 `context/knowledge/hits.md`:
```markdown
# 权威法规与技术标准引用库 (Regulatory Knowledge Hits)
> 检索条件: [产品: 电子内窥镜 | 市场: 国内及欧洲CE | 分类: II/III类有源]
## 1. [GB 9706.1-2020] 医用电气设备 第1部分:基本安全和基本性能的通用要求
- **权威级别**: 国家强制性标准 (GB)
- **标准条文/章节**: 8.4 保护接地、功能接地和电位均衡
- **引用标记 (CiteKey)**: `[GB 9706.1-2020 §8.4]`
- **核心内容**: ...
```
3. 专员在输出交付物时,必须显式引用对应 `CiteKey`。
---
## 4. 实施阶段与渐进式提交矩阵
| 阶段 | 提交类型 | 说明 |
| :--- | :--- | :--- |
| **阶段 1** | `feat(db)` | 启动 `shuimu-kb-shared` 容器,流式完成数据冷迁移与校验,更新 `.env` |
| **阶段 2** | `feat(service)` | 在 `internal/kb/` 实现 Embedder、Reranker、Store 与 Multi-Domain Hub |
| **阶段 3** | `feat(agent)` | 在 `internal/bizdev` 与 `internal/squad` 中接入法规检索与上下文注入 |
| **阶段 4** | `test(kb)` | 编写单元测试与集成测试,覆盖向量+全文+重排+工作区生成链路 |
| **阶段 5** | `docs(test)` | 运行真实 Agent 执行法规论证任务,生成标准化测试报告归档 |
+96
View File
@@ -0,0 +1,96 @@
#!/usr/bin/env bash
# =============================================================================
# 共享法规知识库冷迁移脚本 (migrate_shared_kb.sh)
#
# 作用:
# 将参考项目容器 agent-regkb (端口 55432) 的 2,907 篇法规、31 万条切片
# 通过流式无损方式迁移至本项目专有基础设施容器 shuimu-kb-shared (端口 5432)
#
# 原则:
# 1. 源容器 agent-regkb 纯只读零侵入,严禁写操作;
# 2. 目标容器使用本项目专属数据卷 chat-agent-shared-kb-pgdata;
# 3. 迁移完成后执行数据基线校验。
# =============================================================================
set -eo pipefail
SOURCE_CONTAINER="agent-regkb"
TARGET_CONTAINER="shuimu-kb-shared"
DB_NAME="regulations"
DB_USER="regkb"
echo "============================================================"
echo ">>> 开始法规知识库流式数据迁移 (解耦自立)"
echo ">>> 源容器: ${SOURCE_CONTAINER} (只读)"
echo ">>> 目标容器: ${TARGET_CONTAINER} (本项目专有)"
echo "============================================================"
# 1. 检查源容器是否运行
if ! docker ps --format '{{.Names}}' | grep -q "^${SOURCE_CONTAINER}$"; then
echo "[错误] 源容器 ${SOURCE_CONTAINER} 未运行,无法执行数据读取!"
exit 1
fi
# 2. 检查目标容器是否运行
if ! docker ps --format '{{.Names}}' | grep -q "^${TARGET_CONTAINER}$"; then
echo "[提示] 目标容器 ${TARGET_CONTAINER} 未启动,尝试启动..."
docker compose -f docker-compose.shared.yml up -d
fi
# 3. 等待目标容器就绪
echo "[等待] 检查 ${TARGET_CONTAINER} 数据库就绪状态..."
for i in {1..30}; do
if docker exec -i "${TARGET_CONTAINER}" pg_isready -U "${DB_USER}" -d "${DB_NAME}" >/dev/null 2>&1; then
echo "[就绪] ${TARGET_CONTAINER} 已接受连接。"
break
fi
sleep 1
if [ "$i" -eq 30 ]; then
echo "[错误] 目标数据库连接超时!"
exit 1
fi
done
# 4. 执行流式无损导出与导入
echo "[迁移] 正在从 ${SOURCE_CONTAINER} 导出并流式导入到 ${TARGET_CONTAINER}..."
START_TIME=$(date +%s)
docker exec -i "${SOURCE_CONTAINER}" pg_dump -U "${DB_USER}" -d "${DB_NAME}" --clean --if-exists \
| sed -e '/DROP EXTENSION IF EXISTS vector/d' \
| docker exec -i "${TARGET_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" >/dev/null
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
echo "[完成] 数据流式导入完成,耗时: ${DURATION} 秒。"
# 5. 数据完整性比对校验
echo "============================================================"
echo ">>> 执行数据完整性基线校验"
echo "============================================================"
SRC_DOC_COUNT=$(docker exec -i "${SOURCE_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT count(*) FROM reg_documents;")
TGT_DOC_COUNT=$(docker exec -i "${TARGET_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT count(*) FROM reg_documents;")
SRC_CHUNK_COUNT=$(docker exec -i "${SOURCE_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT count(*) FROM reg_chunks;")
TGT_CHUNK_COUNT=$(docker exec -i "${TARGET_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT count(*) FROM reg_chunks;")
SRC_NODE_COUNT=$(docker exec -i "${SOURCE_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT count(*) FROM reg_nodes;")
TGT_NODE_COUNT=$(docker exec -i "${TARGET_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT count(*) FROM reg_nodes;")
TGT_DB_SIZE=$(docker exec -i "${TARGET_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT pg_size_pretty(pg_database_size('regulations'));")
echo "法规文档数 (reg_documents): 源=${SRC_DOC_COUNT} | 目标=${TGT_DOC_COUNT}"
echo "法规切片数 (reg_chunks): 源=${SRC_CHUNK_COUNT} | 目标=${TGT_CHUNK_COUNT}"
echo "法规节点数 (reg_nodes): 源=${SRC_NODE_COUNT} | 目标=${TGT_NODE_COUNT}"
echo "目标数据库大小: ${TGT_DB_SIZE}"
if [[ "${SRC_DOC_COUNT}" == "${TGT_DOC_COUNT}" && "${SRC_CHUNK_COUNT}" == "${TGT_CHUNK_COUNT}" && "${SRC_NODE_COUNT}" == "${TGT_NODE_COUNT}" ]]; then
echo "============================================================"
echo ">>> [PASS] 知识库数据无损迁移成功!数据 100% 一致!"
echo "============================================================"
else
echo "============================================================"
echo ">>> [FAIL] 数据校验不一致,请排查导入日志!"
echo "============================================================"
exit 1
fi