feat(db): 部署专属记忆与多级上下文数据库容器与pgvector初始化Schema
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
committed by
weichen
co-authored by
Cursor
parent
07a5e999b8
commit
f769f8da4c
@@ -0,0 +1,167 @@
|
||||
-- =============================================================================
|
||||
-- 医疗器械商务与研发智能参谋系统 - 专属记忆与多级上下文数据库初始化脚本
|
||||
-- 运行环境:开发环境 (5433:5432) | 镜像:pgvector/pgvector:pg16
|
||||
-- 涵盖范围:
|
||||
-- 1. 单用户偏好记忆 (User Preferences & Habits)
|
||||
-- 2. 多用户与项目级单一事实黑板 (Project Blackboards & Decision Audit)
|
||||
-- 3. 会话与多轮交互日志 (Chat Sessions & Multi-Turn Messages)
|
||||
-- 4. CAS 内容寻址文件存储与引用去重 (Storage Blobs & File References)
|
||||
-- 5. 动态向量化记忆切片 (Context Memory Chunks with Vector 1024 & Full-Text)
|
||||
-- =============================================================================
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 1. 用户与工作习惯偏好表 (User Profiles & Habits)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
account_id TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL DEFAULT '',
|
||||
role TEXT NOT NULL DEFAULT 'engineer', -- pm, director, regulatory, engineer, sales
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_preferences (
|
||||
user_id BIGINT PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
||||
communication_style TEXT NOT NULL DEFAULT 'concise_structured', -- concise_structured, detailed_analytical, executive_summary
|
||||
focus_areas TEXT[] NOT NULL DEFAULT '{}', -- 例如: {"cost_budget", "reg_compliance", "timeline"}
|
||||
output_format_pref TEXT NOT NULL DEFAULT 'standard_report', -- standard_report, bilingual_brief, ppt_bullet
|
||||
custom_instructions TEXT NOT NULL DEFAULT '', -- 用户明确要求的定制化引导
|
||||
memory_facts JSONB NOT NULL DEFAULT '{}'::jsonb, -- 异步蒸馏出的长期偏好画像事实
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 2. 项目与统一事实黑板表 (Projects & Blackboard SSOT)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS projects (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
code TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
customer_name TEXT NOT NULL DEFAULT '',
|
||||
device_type TEXT NOT NULL DEFAULT '',
|
||||
intended_use TEXT NOT NULL DEFAULT '',
|
||||
target_market TEXT NOT NULL DEFAULT '',
|
||||
current_stage TEXT NOT NULL DEFAULT 'V0.1_triage',
|
||||
environment TEXT NOT NULL DEFAULT 'dev',
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
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 project_blackboards (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
project_id BIGINT NOT NULL UNIQUE REFERENCES projects(id) ON DELETE CASCADE,
|
||||
facts JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
version INT NOT NULL DEFAULT 1,
|
||||
last_updated_by TEXT NOT NULL DEFAULT 'system',
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 3. 多用户协同活动流与决策审计表 (Project Activities & Decisions)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS project_activities (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
project_id BIGINT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
user_id BIGINT REFERENCES users(id) ON DELETE SET NULL,
|
||||
user_name TEXT NOT NULL DEFAULT '',
|
||||
activity_type TEXT NOT NULL, -- chat, decision, operation, upload, download, stage_advance
|
||||
title TEXT NOT NULL,
|
||||
detail JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
weight NUMERIC(4,2) NOT NULL DEFAULT 1.00, -- 初始重要度权重 (决策为 1.0,闲聊为 0.2)
|
||||
is_milestone BOOLEAN NOT NULL DEFAULT FALSE, -- 里程碑事件不衰减
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_project_activities_pid_time ON project_activities(project_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_project_activities_uid ON project_activities(user_id);
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 4. 会话与多轮交互日志表 (Chat Sessions & Messages)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS chat_sessions (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
session_id TEXT NOT NULL UNIQUE,
|
||||
project_id BIGINT REFERENCES projects(id) ON DELETE CASCADE,
|
||||
user_id BIGINT REFERENCES users(id) ON DELETE SET NULL,
|
||||
title TEXT NOT NULL DEFAULT '新对话',
|
||||
current_stage TEXT NOT NULL DEFAULT '',
|
||||
pending_exp JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_chat_sessions_pid ON chat_sessions(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_chat_sessions_uid ON chat_sessions(user_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS chat_messages (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
session_id TEXT NOT NULL REFERENCES chat_sessions(session_id) ON DELETE CASCADE,
|
||||
user_id BIGINT REFERENCES users(id) ON DELETE SET NULL,
|
||||
role TEXT NOT NULL, -- user, assistant, system
|
||||
content TEXT NOT NULL,
|
||||
intent TEXT NOT NULL DEFAULT '',
|
||||
branch TEXT NOT NULL DEFAULT '',
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_chat_messages_sid_time ON chat_messages(session_id, created_at ASC);
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 5. CAS 物理文件寻址与引用去重表 (Storage Blobs & File References)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS storage_blobs (
|
||||
sha256 TEXT PRIMARY KEY, -- 文件 SHA-256 哈希值
|
||||
size_bytes BIGINT NOT NULL, -- 物理字节数
|
||||
mime_type TEXT NOT NULL DEFAULT 'application/octet-stream',
|
||||
storage_path TEXT NOT NULL, -- 宿主机相对物理路径 (如 storage/blobs/ab/cd/xxx.bin)
|
||||
ref_count INT NOT NULL DEFAULT 1, -- 被引用次数
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS file_references (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
project_id BIGINT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
user_id BIGINT REFERENCES users(id) ON DELETE SET NULL,
|
||||
blob_sha256 TEXT NOT NULL REFERENCES storage_blobs(sha256) ON DELETE RESTRICT,
|
||||
file_name TEXT NOT NULL, -- 用户原文件名
|
||||
file_category TEXT NOT NULL DEFAULT 'material', -- material, standard, cad, quote, deliverable
|
||||
summary TEXT NOT NULL DEFAULT '', -- 自动提取的文档摘要
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_file_references_proj ON file_references(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_file_references_blob ON file_references(blob_sha256);
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 6. 动态向量化记忆切片表 (Context Memory Chunks: User / Project / Agent)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS context_memory_chunks (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
domain TEXT NOT NULL, -- user_memory, project_doc, project_activity, chat_summary
|
||||
project_id BIGINT REFERENCES projects(id) ON DELETE CASCADE,
|
||||
user_id BIGINT REFERENCES users(id) ON DELETE SET NULL,
|
||||
reference_id TEXT NOT NULL DEFAULT '', -- 关联的外键标识 (如 file_id, session_id, activity_id)
|
||||
title TEXT NOT NULL DEFAULT '',
|
||||
content TEXT NOT NULL,
|
||||
chunk_hash TEXT NOT NULL DEFAULT '', -- 文本哈希防重复向量化
|
||||
embedding vector(1024), -- bge-m3 1024 维向量
|
||||
tsv tsvector, -- 中文/英文全文检索分词
|
||||
importance_weight NUMERIC(4,2) NOT NULL DEFAULT 1.00,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_mem_chunks_domain_proj ON context_memory_chunks(domain, project_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_mem_chunks_user ON context_memory_chunks(user_id, domain);
|
||||
CREATE INDEX IF NOT EXISTS idx_mem_chunks_hash ON context_memory_chunks(chunk_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_mem_chunks_tsv ON context_memory_chunks USING gin (tsv);
|
||||
CREATE INDEX IF NOT EXISTS idx_mem_chunks_vec ON context_memory_chunks USING hnsw (embedding vector_cosine_ops);
|
||||
+11
-11
@@ -9,20 +9,20 @@ name: agent-dev
|
||||
|
||||
services:
|
||||
system-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: shuimu-system-pg-dev
|
||||
image: pgvector/pgvector:pg16
|
||||
container_name: shuimu-context-pg-dev
|
||||
command: ["postgres", "-c", "shared_buffers=256MB", "-c", "max_connections=100"]
|
||||
environment:
|
||||
POSTGRES_USER: ${SYSTEM_DB_USER:-app}
|
||||
POSTGRES_PASSWORD: ${SYSTEM_DB_PASSWORD:-dev_secret_db_pass}
|
||||
POSTGRES_DB: ${SYSTEM_DB_NAME:-agent_system_dev}
|
||||
POSTGRES_USER: ${CONTEXT_DB_USER:-${SYSTEM_DB_USER:-app}}
|
||||
POSTGRES_PASSWORD: ${CONTEXT_DB_PASSWORD:-${SYSTEM_DB_PASSWORD:-dev_secret_db_pass}}
|
||||
POSTGRES_DB: ${CONTEXT_DB_NAME:-${SYSTEM_DB_NAME:-agent_system_dev}}
|
||||
ports:
|
||||
- "127.0.0.1:${SYSTEM_DB_PUBLISH_PORT:-5433}:5432"
|
||||
- "127.0.0.1:${CONTEXT_DB_PUBLISH_PORT:-${SYSTEM_DB_PUBLISH_PORT:-5433}}:5432"
|
||||
volumes:
|
||||
- dev-system-pgdata:/var/lib/postgresql/data
|
||||
- ./deploy/postgres/system_init.sql:/docker-entrypoint-initdb.d/01-init.sql:ro
|
||||
- dev-context-pgdata:/var/lib/postgresql/data
|
||||
- ./deploy/postgres/context_init.sql:/docker-entrypoint-initdb.d/01-init.sql:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${SYSTEM_DB_USER:-app} -d ${SYSTEM_DB_NAME:-agent_system_dev}"]
|
||||
test: ["CMD-SHELL", "pg_isready -U ${CONTEXT_DB_USER:-${SYSTEM_DB_USER:-app}} -d ${CONTEXT_DB_NAME:-${SYSTEM_DB_NAME:-agent_system_dev}}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
@@ -115,7 +115,7 @@ networks:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
dev-system-pgdata:
|
||||
name: agent-dev-system-pgdata
|
||||
dev-context-pgdata:
|
||||
name: agent-dev-context-pgdata
|
||||
dev-aux-sqlite-data:
|
||||
name: agent-dev-aux-sqlite-data
|
||||
|
||||
@@ -30,6 +30,13 @@ type Config struct {
|
||||
KbDbPassword string `json:"kb_db_password"`
|
||||
KbDbName string `json:"kb_db_name"`
|
||||
|
||||
// 专属记忆与多级上下文数据库配置
|
||||
ContextDbHost string `json:"context_db_host"`
|
||||
ContextDbPort int `json:"context_db_port"`
|
||||
ContextDbUser string `json:"context_db_user"`
|
||||
ContextDbPassword string `json:"context_db_password"`
|
||||
ContextDbName string `json:"context_db_name"`
|
||||
|
||||
// 向量化 Embedding 服务配置
|
||||
EmbeddingEndpointURL string `json:"embedding_endpoint_url"`
|
||||
EmbeddingProvider string `json:"embedding_provider"`
|
||||
@@ -64,6 +71,12 @@ func Load(path string) (*Config, error) {
|
||||
KbDbPassword: "shared_kb_secret_pass",
|
||||
KbDbName: "regulations",
|
||||
|
||||
ContextDbHost: "127.0.0.1",
|
||||
ContextDbPort: 5433,
|
||||
ContextDbUser: "app",
|
||||
ContextDbPassword: "dev_secret_db_pass",
|
||||
ContextDbName: "agent_system_dev",
|
||||
|
||||
EmbeddingEndpointURL: "https://www.dmxapi.cn/v1/embeddings",
|
||||
EmbeddingProvider: "openai_compatible",
|
||||
EmbeddingModel: "bge-m3",
|
||||
@@ -148,6 +161,18 @@ func Load(path string) (*Config, error) {
|
||||
cfg.KbDbPassword = val
|
||||
case "KB_DB_NAME":
|
||||
cfg.KbDbName = val
|
||||
case "CONTEXT_DB_HOST":
|
||||
cfg.ContextDbHost = val
|
||||
case "CONTEXT_DB_PORT":
|
||||
if p, err := strconv.Atoi(val); err == nil {
|
||||
cfg.ContextDbPort = p
|
||||
}
|
||||
case "CONTEXT_DB_USER":
|
||||
cfg.ContextDbUser = val
|
||||
case "CONTEXT_DB_PASSWORD":
|
||||
cfg.ContextDbPassword = val
|
||||
case "CONTEXT_DB_NAME":
|
||||
cfg.ContextDbName = val
|
||||
case "EMBEDDING_ENDPOINT_URL":
|
||||
cfg.EmbeddingEndpointURL = val
|
||||
case "EMBEDDING_PROVIDER":
|
||||
@@ -214,6 +239,23 @@ func Load(path string) (*Config, error) {
|
||||
if v := os.Getenv("KB_DB_NAME"); v != "" {
|
||||
cfg.KbDbName = v
|
||||
}
|
||||
if v := os.Getenv("CONTEXT_DB_HOST"); v != "" {
|
||||
cfg.ContextDbHost = v
|
||||
}
|
||||
if v := os.Getenv("CONTEXT_DB_PORT"); v != "" {
|
||||
if p, err := strconv.Atoi(v); err == nil {
|
||||
cfg.ContextDbPort = p
|
||||
}
|
||||
}
|
||||
if v := os.Getenv("CONTEXT_DB_USER"); v != "" {
|
||||
cfg.ContextDbUser = v
|
||||
}
|
||||
if v := os.Getenv("CONTEXT_DB_PASSWORD"); v != "" {
|
||||
cfg.ContextDbPassword = v
|
||||
}
|
||||
if v := os.Getenv("CONTEXT_DB_NAME"); v != "" {
|
||||
cfg.ContextDbName = v
|
||||
}
|
||||
if v := os.Getenv("EMBEDDING_ENDPOINT_URL"); v != "" {
|
||||
cfg.EmbeddingEndpointURL = v
|
||||
}
|
||||
@@ -240,3 +282,9 @@ func Load(path string) (*Config, error) {
|
||||
func (c *Config) KbDSN() string {
|
||||
return "postgres://" + c.KbDbUser + ":" + c.KbDbPassword + "@" + c.KbDbHost + ":" + strconv.Itoa(c.KbDbPort) + "/" + c.KbDbName + "?sslmode=disable"
|
||||
}
|
||||
|
||||
// ContextDSN 返回专属记忆与多级上下文 PostgreSQL 连接字符串
|
||||
func (c *Config) ContextDSN() string {
|
||||
return "postgres://" + c.ContextDbUser + ":" + c.ContextDbPassword + "@" + c.ContextDbHost + ":" + strconv.Itoa(c.ContextDbPort) + "/" + c.ContextDbName + "?sslmode=disable"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user