相对第一版 46fc976 的完整变更。组员迁移对照表见 docs/20。
一、对外契约对齐 docs/05(破坏性,共 4 处,组员需按 docs/20 调整)
1) 配置发布端点改为文档规定的复数资源名:submit→validations、
approve→reviews(需 body decision)、activate→activations、
rollback→rollbacks;第一版这 4 个动词式路径 docs/05 从未定义过。
2) 错误码由 8 个笼统码改为 15 个具体语义码(FORBIDDEN→AGENT_PERMISSION_DENIED、
UNAUTHORIZED→AUTHENTICATION_REQUIRED、CONFLICT→RESOURCE_VERSION_CONFLICT、
RESOURCE_NOT_FOUND→RUN_NOT_FOUND/SESSION_NOT_FOUND 等),
输入类错误状态码 400→422。
3) POST /api/v1/agent-runs 与 GET /api/v1/agent-runs/{run_id} 统一为
{data, meta} 信封(data 内字段名与语义未变)。
4) 错误响应体统一为 {error:{code,message,retryable,field_errors}, meta:{trace_id}},
不再返回 FastAPI 默认的 {"detail": ...}。
二、数据库基线与约束
新增 39 张表的基线迁移(链根)与联合唯一键纠偏(4 张表、删 8 增 4,幂等收敛);
撤下 config_release 的双人复核 CHECK(应用层已允许自审,审核节点保留,
自审如实写入 reviewer_id);记忆 active key 生成列与唯一键;
activate 开始记录 supersedes_release_id 使版本链可追溯。
docs/00 基线未修改,未重命名或删除任何表与字段。
三、修复会静默出错或无报错的缺陷
- 跑完集成测试后平台会静默失去生效配置:清理只删自己创建的版本,却没有恢复被它
顶成 superseded 的原生效版本,且审计一并删除因而完全无痕,表现为所有工具被拒
但没有任何报错。已修清理逻辑并加恢复。
- Worker 单轮异常导致进程退出;记忆抽取调用方的“事务已开始”异常;
召回缓存丢失 degraded 标记;连接时区未生效导致 created_at/updated_at 差 8 小时;
.env 与 os.getenv 密钥来源分裂导致“没有可用的已批准模型端点”。
- 记忆信号识别漏判与跨键误命中;SSE 未带 Accept 的协商行为。
四、功能补齐
记忆链路 P1/P2/P3(抽取、受控词表、召回与缓存、生命周期级联及投影事件)、
fin_* 场内交易只读 ORM 层、agent_intent_config 状态流转并在运行期真正生效、
限流(Redis 固定窗口、故障一律放行)、游标校验、trace_id 中间件、
示例业务 Agent fund_query_demo 与一键端到端验证脚本,以及审计/指纹/迁移状态工具。
五、文档与验证
新增 docs/19(业务 Agent 接入实操)、docs/20(第一版迁移指南)与 docs/evidence 证据;
docs/01/02/06/08/09/17 同步实现现状。
验证结果:ruff 通过、mypy 103 文件无错、unit+contract 447 passed、
integration 29 passed、acceptance_check --production 7 PASS、
demo_agent_e2e 9/9 PASS(含失败关闭反证)。
42 KiB
数据库建表设计
版本:v3.1
修订日期:2026-09-09
演进原则:只允许新增表和新增字段,不修改已有表名、已有字段名、字段类型及既有业务含义
1. 文档目的
本文定义通用 Agent 平台、记忆系统和智能客服专项能力的数据库建设方案。数据库业务基线已固化为项目内的《00-新数据库基线设计.md》,本文只在该基线上补充字段、表、实施顺序和迁移规则。
2. 数据库范围
- 数据库:MySQL 8.0。
- 默认字符集:
utf8mb4。 - 默认排序规则:
utf8mb4_0900_ai_ci。 - 基础业务表:33 张。
- 智能客服专项表:6 张。
- 平台底座增量表:12 张(原设计 10 张、outbox_delivery、api_request_receipt)。
- 建成后总表数:51 张(包含会话补表及公共 HTTP 写操作幂等回执)。
- Redis、Milvus 和 Neo4j 不计入 MySQL 表数量。
当前交易范围是场内基金模拟交易。数据库不建设充值、提现、银行流水匹配或场外基金申购赎回交易表。
2.1 不可变基线规则
新版《00-新数据库基线设计.md》中的表名和已有字段是不可变基线。后续迁移只能创建新表、在已有表中增加新字段,或为新增字段增加索引和约束。禁止重命名表,禁止删除、重命名或复用已有字段,禁止改变已有字段的类型、可空性和既有业务含义。历史问题无法兼容解决时,新增语义明确的字段或新表,并由应用执行双读、回填和切换。
3. 通用建表约定
数据库实体和迁移属于 MVC+S 的 Model 层。Controller 不访问 ORM;Service 通过 Repository 读写 Model。Alembic 迁移是表结构变更的唯一入口,运行时业务代码不执行 CREATE TABLE 或 ALTER TABLE。
| 项目 | 约定 |
|---|---|
| 主键 | BIGINT UNSIGNED AUTO_INCREMENT |
| 业务编号 | 单独字段并建立唯一索引 |
| 时间 | 使用 DATETIME(6),统一以 _at 结尾 |
| 金额 | DECIMAL(18,2) |
| 价格 | DECIMAL(18,6) |
| 数量 | DECIMAL(18,4) |
| 置信度 | DECIMAL(5,4),范围 0 至 1 |
| JSON | 使用 MySQL 原生 JSON,禁止用逗号字符串代替数组 |
| 删除 | 交易、预警、审计、对话和通知不物理删除 |
| 审计 | 关键状态变化追加写入 interaction_audit |
| 外键 | MySQL 核心实体使用外键;Milvus/Neo4j 关系由应用校验 |
| 时间基准 | 应用和数据库统一使用 UTC,展示层转换时区 |
4. 51 张表总览
4.1 基础业务表
| 域 | 表 | 主要职责 | Agent 访问边界 |
|---|---|---|---|
| 身份 | sys_user |
客户与员工统一身份 | 按字段策略读取 |
| 权限 | sys_role |
角色定义 | 只读 |
| 权限 | sys_permission |
资源、动作、数据范围 | 只读 |
| 权限 | sys_user_role |
用户角色关系 | 只读 |
| 权限 | sys_role_permission |
角色权限关系 | 只读 |
| 归属 | sys_customer_assignment |
客户与投顾/运营归属 | 只读 |
| 客户 | fin_customer_profile |
客户金融画像 | 只读 |
| 客户 | fin_risk_assessment |
正式风险测评历史 | 只读、权威事实 |
| 软事实 | user_facts |
现有代码兼容软事实 | 只读 |
| 产品 | fin_product |
场内产品及适当性信息 | 只读 |
| 行情 | fin_market_price |
场内日线行情 | 只读 |
| 净值 | fin_nav_history |
基金净值兼容数据 | 只读 |
| 账户 | fin_sim_account |
虚拟资金账户 | 只读 |
| 资金 | fin_cash_ledger |
虚拟资金明细 | 只读 |
| 资金 | fin_capital_flow |
风控兼容标准化流水 | 只读 |
| 费用 | fin_fee_rule |
模拟交易费率 | 只读 |
| 委托 | fin_sim_order |
场内模拟委托 | 交易服务写,Agent 只读 |
| 成交 | fin_transaction |
模拟成交 | 交易服务写,Agent 只读 |
| 持仓 | fin_holding |
当前持仓汇总 | 交易服务写,Agent 只读 |
| 登录 | sys_login_record |
逐次登录结果 | 只读 |
| 工单 | biz_work_order |
风险调查和处置工单 | 风控流程读写 |
| 风控 | fin_risk_alert |
规则命中与人工处置 | 风控服务读写 |
| 通知 | fin_risk_notification |
站内和邮件通知 | 风控服务读写 |
| 会话 | conversation_message |
完整对话留存 | 公共基础层写 |
| 知识 | fin_knowledge_meta |
知识元数据及正文镜像 | 知识服务写、Agent 只读 |
| Episode | episodes |
会话片段摘要 | 记忆服务写 |
| 记忆 | memory_unit |
中期记忆单元 | 记忆服务写 |
| 证据 | memory_evidence |
记忆来源证据 | 记忆服务写 |
| 冲突 | memory_conflict |
新旧记忆冲突 | 记忆服务写 |
| 画像 | profile_snapshots |
长期画像版本投影 | 画像服务写 |
| 同步 | memory_sync_outbox |
Milvus/Neo4j 同步事件 | 记忆服务写、消费者更新状态 |
| 审计 | interaction_audit |
全系统追加审计 | 公共基础层追加写 |
| 内容 | client_facing_content |
对客内容审核发布 | 投顾流程读写 |
4.2 智能客服专项表
| 表 | 优先级 | 主要职责 |
|---|---|---|
agent_negative_word |
P0 | 禁止表达与变体规则配置 |
svc_handover_ticket |
P0 | 客服转人工工单 |
agent_faq_synonym |
P1 | FAQ 同义问法和口语表达 |
conversation_feedback |
P1 | 用户对回复的反馈 |
agent_reply_template |
Phase 2 | 兜底、拒答、免责声明等模板 |
agent_intent_config |
Phase 2 | 意图、阈值、路由和工具配置 |
4.3 平台底座增量表
| 表 | 主要职责 | 写入方 |
|---|---|---|
svc_conversation_session |
会话状态、澄清轮次和配置快照 | 会话服务 |
outbox_delivery |
已有 Outbox 消费幂等记录 | Outbox Worker |
api_request_receipt |
公共 HTTP 写操作幂等回执 | ApiTransactionService |
api_request_receipt 是独立新增表,不复用只用于 Agent 运行的 request_idempotency。
其字段为 id BIGINT UNSIGNED 自增主键、user_id BIGINT UNSIGNED 非空、scope_hash CHAR(64)
非空、idempotency_key VARCHAR(128) 非空、request_hash CHAR(64) 非空、response_json JSON
可空、created_at DATETIME(6) 非空默认 CURRENT_TIMESTAMP(6),唯一键
(user_id, scope_hash, idempotency_key)。操作结果、业务状态和审计在同一事务完成;失败整体回滚。
迁移 20260909_api_receipt 仅 CREATE TABLE;既有 49 表字段指纹比对未变化,会话表保持 §8.1。
| domain_event_outbox | 通用领域事件可靠投递 | 事务内事件发布器 |
| request_idempotency | 请求占位、结果定位和并发防重 | AgentService |
| agent_run | 可恢复 Agent 运行状态、租约和结果定位 | AgentRunService/Worker |
| config_release | 配置发布、审核、激活和回滚批次 | 配置中心 |
| platform_config_item | 记忆、关系及运行参数的版本化配置项 | 配置中心 |
| model_endpoint_config | 模型端点能力、限制和密钥引用 | 模型平台管理员 |
| model_routing_rule | 按 Agent 和任务类型选择模型及备用链 | 模型路由服务 |
| model_routing_fallback | 路由规则的有序备用端点及可重试错误 | 模型路由服务 |
| prompt_template_version | 分类、生成、摘要和提取 Prompt 版本 | Prompt 管理服务 |
5. 核心关系
sys_user 1 --- 1 fin_customer_profile
sys_user 1 --- N fin_risk_assessment
sys_user 1 --- N conversation_message
sys_user 1 --- N svc_handover_ticket
sys_user 1 --- N svc_conversation_session
conversation_message N --- 1 session_id(逻辑会话)
conversation_message 1 --- N conversation_feedback
fin_knowledge_meta 1 --- N agent_faq_synonym
fin_knowledge_meta -- 正文和向量镜像 --> Milvus 知识集合
episodes 1 --- N memory_unit
memory_unit 1 --- N memory_evidence
memory_unit N --- N memory_unit(通过 memory_conflict)
memory_unit/profile_snapshots 1 --- N memory_sync_outbox
svc_conversation_session 1 --- N conversation_message
svc_conversation_session 1 --- N request_idempotency
svc_conversation_session 1 --- N agent_run
request_idempotency 1 --- 1 agent_run
conversation_message 1 --- N agent_run(用户消息)
conversation_message 1 --- N agent_run(助手结果)
conversation_message/interaction_audit 1 --- N domain_event_outbox
config_release 1 --- N platform_config_item
config_release 1 --- N model_routing_rule
config_release 1 --- N prompt_template_version
model_endpoint_config 1 --- N model_routing_rule
model_routing_rule 1 --- N model_routing_fallback
model_endpoint_config 1 --- N model_routing_fallback
fin_risk_alert 1 --- N biz_work_order
fin_risk_alert 1 --- N fin_risk_notification
svc_handover_ticket 与 biz_work_order 相互独立
6. 现有表字段增补
6.1 conversation_message
新版基线已经包含 tool_calls JSON,保持其名称和定义不变。本次只新增以下三个字段:
| 字段 | 类型 | 约束 | 用途 |
|---|---|---|---|
intent |
VARCHAR(32) | 可空、索引 | 助手消息的意图结果 |
confidence |
DECIMAL(5,4) | 可空、索引、0 至 1 | 意图置信度 |
source_references |
JSON | 可空 | RAG 来源集合与文档 ID |
用户原始消息的三个新增字段可以为空;助手最终消息记录实际采用的意图、置信度和来源。既有 tool_calls 字段继续保存脱敏后的工具调用;未使用知识或工具时对应 JSON 字段使用 NULL。
迁移示例:
ALTER TABLE conversation_message
ADD COLUMN intent VARCHAR(32) NULL COMMENT '识别的意图' AFTER trace_id,
ADD COLUMN confidence DECIMAL(5,4) NULL COMMENT '意图置信度' AFTER intent,
ADD COLUMN source_references JSON NULL COMMENT '检索来源' AFTER confidence,
ADD CONSTRAINT chk_conversation_confidence
CHECK (confidence IS NULL OR confidence BETWEEN 0 AND 1),
ADD INDEX idx_conversation_intent (intent),
ADD INDEX idx_conversation_confidence (confidence);
6.2 fin_knowledge_meta
最终结构以新版表定义为准,必须包含 content_text、tags、effective_date、expire_date、version、reviewer_id 和 review_status。
实际迁移前使用 Alembic Inspector 检查现库。若 version、effective_date、expire_date 已存在,只新增以下四个缺失字段:
ALTER TABLE fin_knowledge_meta
ADD COLUMN content_text MEDIUMTEXT NULL COMMENT 'Milvus知识正文MySQL镜像,保持可空兼容旧数据',
ADD COLUMN tags JSON NULL COMMENT '知识标签数组',
ADD COLUMN reviewer_id BIGINT UNSIGNED NULL COMMENT '审校人ID',
ADD COLUMN review_status VARCHAR(16) NOT NULL DEFAULT 'pending'
COMMENT 'pending/approved/published/archived',
ADD CONSTRAINT fk_knowledge_reviewer
FOREIGN KEY (reviewer_id) REFERENCES sys_user(id),
ADD INDEX idx_knowledge_review_status (review_status),
ADD INDEX idx_knowledge_reviewer (reviewer_id);
content_text 保持新增时的可空定义,后续不得更改已有字段约束。应用通过发布校验保证 published 知识必须存在正文。
有效知识的统一过滤条件为:
review_status = 'published'
AND status = 'active'
AND (effective_date IS NULL OR effective_date <= UTC_DATE())
AND (expire_date IS NULL OR expire_date > UTC_DATE())
7. 智能客服专项表 DDL
以下 DDL 面向全新数据库。若应用于已有数据库,必须通过 Alembic 生成版本迁移并在测试库演练。
7.1 agent_negative_word
禁止表达不写死在业务 Agent 中。规则变更必须经过审核并保留版本。
CREATE TABLE agent_negative_word (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
rule_code VARCHAR(64) NOT NULL,
word_pattern VARCHAR(256) NOT NULL,
match_type VARCHAR(16) NOT NULL DEFAULT 'contains',
category VARCHAR(32) NOT NULL,
severity VARCHAR(16) NOT NULL DEFAULT 'block',
applicable_agents JSON NULL,
safe_reply_template_code VARCHAR(64) NULL,
status VARCHAR(16) NOT NULL DEFAULT 'draft',
version INT UNSIGNED NOT NULL DEFAULT 1,
created_by BIGINT UNSIGNED NOT NULL,
reviewer_id BIGINT UNSIGNED NULL,
reviewed_at DATETIME(6) NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_negative_rule_code (rule_code),
KEY idx_negative_status_category (status, category),
KEY idx_negative_reviewer (reviewer_id),
CONSTRAINT fk_negative_created_by FOREIGN KEY (created_by) REFERENCES sys_user(id),
CONSTRAINT fk_negative_reviewer FOREIGN KEY (reviewer_id) REFERENCES sys_user(id),
CONSTRAINT chk_negative_match_type
CHECK (match_type IN ('exact', 'contains', 'regex')),
CONSTRAINT chk_negative_severity
CHECK (severity IN ('warn', 'regenerate', 'block')),
CONSTRAINT chk_negative_status
CHECK (status IN ('draft', 'active', 'disabled', 'archived'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='Agent禁止表达配置';
7.2 svc_handover_ticket
本表只表示客服会话向人工坐席的转接,不替代风险预警处置工单 biz_work_order。
CREATE TABLE svc_handover_ticket (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
ticket_no VARCHAR(32) NOT NULL,
session_id VARCHAR(64) NOT NULL,
customer_id BIGINT UNSIGNED NULL,
source_agent VARCHAR(32) NOT NULL DEFAULT 'customer_service',
source_message_id BIGINT UNSIGNED NULL,
intent VARCHAR(32) NULL,
confidence DECIMAL(5,4) NULL,
priority VARCHAR(8) NOT NULL DEFAULT 'P1',
reason_code VARCHAR(64) NOT NULL,
reason_detail VARCHAR(500) NULL,
conversation_summary MEDIUMTEXT NULL,
source_references JSON NULL,
status VARCHAR(16) NOT NULL DEFAULT 'pending',
assigned_to BIGINT UNSIGNED NULL,
assigned_at DATETIME(6) NULL,
accepted_at DATETIME(6) NULL,
resolved_at DATETIME(6) NULL,
closed_at DATETIME(6) NULL,
resolution TEXT NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_handoff_ticket_no (ticket_no),
KEY idx_handoff_session (session_id, created_at),
KEY idx_handoff_customer (customer_id, created_at),
KEY idx_handoff_queue (status, priority, created_at),
KEY idx_handoff_assignee (assigned_to, status),
CONSTRAINT fk_handoff_customer FOREIGN KEY (customer_id) REFERENCES sys_user(id),
CONSTRAINT fk_handoff_source_message
FOREIGN KEY (source_message_id) REFERENCES conversation_message(id),
CONSTRAINT fk_handoff_assignee FOREIGN KEY (assigned_to) REFERENCES sys_user(id),
CONSTRAINT chk_handoff_confidence
CHECK (confidence IS NULL OR confidence BETWEEN 0 AND 1),
CONSTRAINT chk_handoff_priority CHECK (priority IN ('P0', 'P1', 'P2')),
CONSTRAINT chk_handoff_status
CHECK (status IN ('pending', 'assigned', 'processing', 'resolved', 'closed', 'cancelled'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='客服转人工工单';
状态流转:
pending -> assigned -> processing -> resolved -> closed
| | |
`----------+-------------+-> cancelled
cancelled 只允许在未解决状态进入。每次分配、接单、解决、关闭或取消都要写入 interaction_audit。
7.3 agent_faq_synonym
CREATE TABLE agent_faq_synonym (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
knowledge_id BIGINT UNSIGNED NOT NULL,
phrase VARCHAR(500) NOT NULL,
normalized_phrase VARCHAR(500) NOT NULL,
phrase_hash CHAR(64) NOT NULL,
language_code VARCHAR(16) NOT NULL DEFAULT 'zh-CN',
source_type VARCHAR(24) NOT NULL DEFAULT 'manual',
hit_count BIGINT UNSIGNED NOT NULL DEFAULT 0,
status VARCHAR(16) NOT NULL DEFAULT 'pending',
created_by BIGINT UNSIGNED NOT NULL,
reviewer_id BIGINT UNSIGNED NULL,
reviewed_at DATETIME(6) NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_faq_synonym (knowledge_id, phrase_hash),
KEY idx_faq_synonym_status (status),
KEY idx_faq_synonym_normalized (normalized_phrase(191)),
CONSTRAINT fk_synonym_knowledge FOREIGN KEY (knowledge_id) REFERENCES fin_knowledge_meta(id),
CONSTRAINT fk_synonym_created_by FOREIGN KEY (created_by) REFERENCES sys_user(id),
CONSTRAINT fk_synonym_reviewer FOREIGN KEY (reviewer_id) REFERENCES sys_user(id),
CONSTRAINT chk_synonym_source
CHECK (source_type IN ('manual', 'conversation', 'ticket', 'import')),
CONSTRAINT chk_synonym_status
CHECK (status IN ('pending', 'approved', 'disabled', 'archived'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='FAQ同义问法';
只有 approved 的同义问法参与意图识别和检索扩展。会话自动提取内容必须先进入 pending。
phrase_hash 由应用对完整 normalized_phrase 计算 SHA-256,防止仅使用索引前缀时不同长文本被误判为重复。
7.4 conversation_feedback
CREATE TABLE conversation_feedback (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
feedback_no VARCHAR(32) NOT NULL,
session_id VARCHAR(64) NOT NULL,
message_id BIGINT UNSIGNED NOT NULL,
customer_id BIGINT UNSIGNED NULL,
rating TINYINT NOT NULL,
feedback_type VARCHAR(32) NULL,
feedback_content VARCHAR(1000) NULL,
status VARCHAR(16) NOT NULL DEFAULT 'open',
handler_id BIGINT UNSIGNED NULL,
handled_at DATETIME(6) NULL,
handling_note VARCHAR(1000) NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_feedback_no (feedback_no),
UNIQUE KEY uk_feedback_message_customer (message_id, customer_id),
KEY idx_feedback_session (session_id, created_at),
KEY idx_feedback_status_type (status, feedback_type),
CONSTRAINT fk_feedback_message FOREIGN KEY (message_id) REFERENCES conversation_message(id),
CONSTRAINT fk_feedback_customer FOREIGN KEY (customer_id) REFERENCES sys_user(id),
CONSTRAINT fk_feedback_handler FOREIGN KEY (handler_id) REFERENCES sys_user(id),
CONSTRAINT chk_feedback_rating CHECK (rating IN (-1, 1)),
CONSTRAINT chk_feedback_status CHECK (status IN ('open', 'reviewed', 'resolved', 'ignored'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='对话回复反馈';
匿名或未登录反馈的 customer_id 可以为空,但必须由 API 限流并保存安全审计信息,防止重复刷票。
7.5 agent_reply_template
CREATE TABLE agent_reply_template (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
template_code VARCHAR(64) NOT NULL,
scene VARCHAR(32) NOT NULL,
title VARCHAR(128) NOT NULL,
content_text MEDIUMTEXT NOT NULL,
variables JSON NULL,
locale VARCHAR(16) NOT NULL DEFAULT 'zh-CN',
version INT UNSIGNED NOT NULL DEFAULT 1,
status VARCHAR(16) NOT NULL DEFAULT 'draft',
active_key VARCHAR(128) GENERATED ALWAYS AS
(IF(status = 'active', CONCAT(template_code, ':', locale), NULL)) STORED,
effective_at DATETIME(6) NULL,
expire_at DATETIME(6) NULL,
created_by BIGINT UNSIGNED NOT NULL,
reviewer_id BIGINT UNSIGNED NULL,
reviewed_at DATETIME(6) NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_reply_template_version (template_code, version),
UNIQUE KEY uk_reply_template_active_one (active_key),
KEY idx_reply_template_active (scene, status, effective_at, expire_at),
CONSTRAINT fk_template_created_by FOREIGN KEY (created_by) REFERENCES sys_user(id),
CONSTRAINT fk_template_reviewer FOREIGN KEY (reviewer_id) REFERENCES sys_user(id),
CONSTRAINT chk_template_scene
CHECK (scene IN ('disclaimer', 'low_confidence', 'compliance_block',
'transfer', 'model_failure', 'system_busy', 'clarification')),
CONSTRAINT chk_template_status
CHECK (status IN ('draft', 'approved', 'active', 'archived')),
CONSTRAINT chk_template_window
CHECK (expire_at IS NULL OR effective_at IS NULL OR expire_at > effective_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='Agent回复模板';
相同 template_code + locale 可以有多个历史版本,但数据库通过 active_key 唯一索引保证同一组合最多一个 active 版本。发布服务仍须在事务中完成状态切换并写入审计记录。
7.6 agent_intent_config
CREATE TABLE agent_intent_config (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
agent_type VARCHAR(32) NOT NULL,
intent_code VARCHAR(64) NOT NULL,
intent_name VARCHAR(128) NOT NULL,
description VARCHAR(500) NULL,
examples JSON NOT NULL,
classifier_instruction TEXT NULL,
confidence_threshold DECIMAL(5,4) NOT NULL DEFAULT 0.6000,
max_clarification_rounds TINYINT UNSIGNED NOT NULL DEFAULT 2,
transfer_on_failure TINYINT(1) NOT NULL DEFAULT 1,
collection_routes JSON NULL,
allowed_tools JSON NULL,
priority INT NOT NULL DEFAULT 100,
version INT UNSIGNED NOT NULL DEFAULT 1,
status VARCHAR(16) NOT NULL DEFAULT 'draft',
active_key VARCHAR(128) GENERATED ALWAYS AS
(IF(status = 'active', CONCAT(agent_type, ':', intent_code), NULL)) STORED,
effective_at DATETIME(6) NULL,
expire_at DATETIME(6) NULL,
created_by BIGINT UNSIGNED NOT NULL,
reviewer_id BIGINT UNSIGNED NULL,
reviewed_at DATETIME(6) NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_intent_config_version (agent_type, intent_code, version),
UNIQUE KEY uk_intent_config_active_one (active_key),
KEY idx_intent_config_active (agent_type, status, priority),
CONSTRAINT fk_intent_created_by FOREIGN KEY (created_by) REFERENCES sys_user(id),
CONSTRAINT fk_intent_reviewer FOREIGN KEY (reviewer_id) REFERENCES sys_user(id),
CONSTRAINT chk_intent_confidence
CHECK (confidence_threshold BETWEEN 0 AND 1),
CONSTRAINT chk_intent_status
CHECK (status IN ('draft', 'approved', 'active', 'archived')),
CONSTRAINT chk_intent_window
CHECK (expire_at IS NULL OR effective_at IS NULL OR expire_at > effective_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='Agent意图路由配置';
客服初始意图至少包含:faq、product_inquiry、policy_explain、chitchat 和 transfer_human。
8. 平台底座增量表 DDL
本节所有对象均为新增表,不替换、不重命名原有表。
8.1 svc_conversation_session
CREATE TABLE svc_conversation_session (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
session_id VARCHAR(64) NOT NULL,
user_id BIGINT UNSIGNED NOT NULL,
portal VARCHAR(32) NOT NULL,
agent_type VARCHAR(32) NULL,
status VARCHAR(16) NOT NULL DEFAULT 'active',
clarification_round TINYINT UNSIGNED NOT NULL DEFAULT 0,
message_count INT UNSIGNED NOT NULL DEFAULT 0,
last_intent VARCHAR(32) NULL,
config_version VARCHAR(64) NULL,
started_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
last_active_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
ended_at DATETIME(6) NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_session_id (session_id),
KEY idx_session_user_active (user_id, last_active_at),
KEY idx_session_status_active (status, last_active_at),
CONSTRAINT fk_session_user FOREIGN KEY (user_id) REFERENCES sys_user(id),
CONSTRAINT chk_session_status
CHECK (status IN ('active', 'ended', 'transferred', 'expired')),
CONSTRAINT chk_session_clarification CHECK (clarification_round <= 10)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='Agent会话状态与澄清轮次';
澄清次数使用带旧值条件的原子更新;Redis 只缓存该记录,MySQL 是权威来源。会话结束、转人工和过期必须写明确状态。
8.2 domain_event_outbox
CREATE TABLE domain_event_outbox (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
event_id CHAR(36) NOT NULL,
event_type VARCHAR(64) NOT NULL,
aggregate_type VARCHAR(32) NOT NULL,
aggregate_id VARCHAR(64) NOT NULL,
trace_id VARCHAR(64) NOT NULL,
payload JSON NOT NULL,
status VARCHAR(16) NOT NULL DEFAULT 'pending',
retry_count INT UNSIGNED NOT NULL DEFAULT 0,
next_retry_at DATETIME(6) NULL,
last_error VARCHAR(500) NULL,
occurred_at DATETIME(6) NOT NULL,
published_at DATETIME(6) NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_domain_event_id (event_id),
KEY idx_domain_outbox_pending (status, next_retry_at, id),
KEY idx_domain_outbox_aggregate (aggregate_type, aggregate_id),
KEY idx_domain_outbox_trace (trace_id),
CONSTRAINT chk_domain_outbox_status
CHECK (status IN ('pending', 'published', 'failed', 'dead'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='通用领域事件Outbox';
8.3 request_idempotency
CREATE TABLE request_idempotency (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL,
session_id VARCHAR(64) NOT NULL,
agent_type VARCHAR(32) NOT NULL,
idempotency_key VARCHAR(64) NOT NULL,
request_hash CHAR(64) NOT NULL,
trace_id VARCHAR(64) NOT NULL,
status VARCHAR(16) NOT NULL DEFAULT 'processing',
result_message_id BIGINT UNSIGNED NULL,
error_code VARCHAR(64) NULL,
locked_until DATETIME(6) NULL,
expire_at DATETIME(6) NOT NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_idempotency_scope (user_id, agent_type, idempotency_key),
KEY idx_idempotency_expire (expire_at),
KEY idx_idempotency_trace (trace_id),
KEY idx_idempotency_session (session_id, created_at),
CONSTRAINT fk_idempotency_user FOREIGN KEY (user_id) REFERENCES sys_user(id),
CONSTRAINT fk_idempotency_session
FOREIGN KEY (session_id) REFERENCES svc_conversation_session(session_id),
CONSTRAINT fk_idempotency_result
FOREIGN KEY (result_message_id) REFERENCES conversation_message(id),
CONSTRAINT chk_idempotency_status
CHECK (status IN ('processing', 'completed', 'failed'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='Agent请求幂等记录';
相同幂等键但 request_hash 不同必须返回冲突;processing 未过租约返回处理中,completed 返回原结果,只有租约超时后才能由新请求接管。
8.4 agent_run
CREATE TABLE agent_run (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
run_id CHAR(36) NOT NULL,
idempotency_id BIGINT UNSIGNED NOT NULL,
session_id VARCHAR(64) NOT NULL,
user_id BIGINT UNSIGNED NOT NULL,
agent_type VARCHAR(32) NOT NULL,
trace_id VARCHAR(64) NOT NULL,
request_message_id BIGINT UNSIGNED NOT NULL,
result_message_id BIGINT UNSIGNED NULL,
status VARCHAR(24) NOT NULL DEFAULT 'queued',
attempt_count INT UNSIGNED NOT NULL DEFAULT 0,
worker_id VARCHAR(128) NULL,
locked_until DATETIME(6) NULL,
result_version INT UNSIGNED NULL,
error_code VARCHAR(64) NULL,
cancel_requested_at DATETIME(6) NULL,
started_at DATETIME(6) NULL,
completed_at DATETIME(6) NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_agent_run_id (run_id),
UNIQUE KEY uk_agent_run_idempotency (idempotency_id),
UNIQUE KEY uk_agent_run_trace (trace_id),
KEY idx_agent_run_session (session_id, created_at),
KEY idx_agent_run_user (user_id, created_at),
KEY idx_agent_run_worker_lease (status, locked_until),
CONSTRAINT fk_agent_run_idempotency
FOREIGN KEY (idempotency_id) REFERENCES request_idempotency(id),
CONSTRAINT fk_agent_run_session
FOREIGN KEY (session_id) REFERENCES svc_conversation_session(session_id),
CONSTRAINT fk_agent_run_user FOREIGN KEY (user_id) REFERENCES sys_user(id),
CONSTRAINT fk_agent_run_request_message
FOREIGN KEY (request_message_id) REFERENCES conversation_message(id),
CONSTRAINT fk_agent_run_result_message
FOREIGN KEY (result_message_id) REFERENCES conversation_message(id),
CONSTRAINT chk_agent_run_status CHECK
(status IN ('queued', 'running', 'succeeded', 'failed',
'cancel_requested', 'cancelled'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='可恢复Agent运行状态';
run_id 是对外运行主键,trace_id 只用于可观测性。Worker 通过 locked_until 租约接管过期运行;同一 run_id 安全重试,不承诺从模型中间 Token 续写。最终消息、审计、幂等完成状态和 Outbox 必须与运行成功状态同一事务提交。
8.5 config_release
CREATE TABLE config_release (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
release_no VARCHAR(64) NOT NULL,
title VARCHAR(128) NOT NULL,
change_summary VARCHAR(1000) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'draft',
created_by BIGINT UNSIGNED NOT NULL,
reviewer_id BIGINT UNSIGNED NULL,
reviewed_at DATETIME(6) NULL,
activated_at DATETIME(6) NULL,
supersedes_release_id BIGINT UNSIGNED NULL,
rollback_of_release_id BIGINT UNSIGNED NULL,
active_slot TINYINT GENERATED ALWAYS AS
(IF(status = 'active', 1, NULL)) STORED,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_config_release_no (release_no),
UNIQUE KEY uk_config_release_active_one (active_slot),
KEY idx_config_release_status (status, created_at),
CONSTRAINT fk_config_release_creator FOREIGN KEY (created_by) REFERENCES sys_user(id),
CONSTRAINT fk_config_release_reviewer FOREIGN KEY (reviewer_id) REFERENCES sys_user(id),
CONSTRAINT fk_config_release_supersedes
FOREIGN KEY (supersedes_release_id) REFERENCES config_release(id),
CONSTRAINT fk_config_release_rollback
FOREIGN KEY (rollback_of_release_id) REFERENCES config_release(id),
CONSTRAINT chk_config_release_status
CHECK (status IN ('draft', 'validating', 'pending_review', 'approved',
'active', 'superseded', 'rejected', 'rolled_back'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='平台配置发布批次';
变更记录:原
CONSTRAINT chk_config_release_separation CHECK (reviewer_id IS NULL OR reviewer_id <> created_by)(双人复核)已于迁移20260910_drop_review_separation撤下。原因是本平台为单管理员部署, 该约束使配置发布在数据库层永远无法完成(错误 3819)。撤下的只是"审核人必须不同于创建人"这一 身份限制:状态机仍要求pending_review→approved经审核接口并写入reviewer_id/reviewed_at,reviewer_id列本身的类型、可空性与业务含义均未改变。docs/00-新数据库基线设计.md未修改。
8.6 platform_config_item
CREATE TABLE platform_config_item (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
release_id BIGINT UNSIGNED NOT NULL,
namespace VARCHAR(64) NOT NULL,
config_key VARCHAR(128) NOT NULL,
value_json JSON NOT NULL,
schema_version VARCHAR(32) NOT NULL,
checksum CHAR(64) NOT NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_config_item_release (release_id, namespace, config_key),
KEY idx_config_item_lookup (namespace, config_key, release_id),
CONSTRAINT fk_config_item_release
FOREIGN KEY (release_id) REFERENCES config_release(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='版本化平台配置项';
namespace 首版限定为 agent_runtime、memory_policy、relationship_view、compliance_policy 和 tool_policy;value_json 必须先通过对应 Pydantic Schema 校验。
8.7 model_endpoint_config
CREATE TABLE model_endpoint_config (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
endpoint_code VARCHAR(64) NOT NULL,
provider VARCHAR(32) NOT NULL,
model_name VARCHAR(128) NOT NULL,
base_url VARCHAR(500) NOT NULL,
secret_ref VARCHAR(256) NOT NULL,
capabilities JSON NOT NULL,
allowed_data_levels JSON NOT NULL,
context_window INT UNSIGNED NOT NULL,
timeout_ms INT UNSIGNED NOT NULL DEFAULT 15000,
cost_input_per_1k DECIMAL(12,6) NULL,
cost_output_per_1k DECIMAL(12,6) NULL,
status VARCHAR(16) NOT NULL DEFAULT 'disabled',
created_by BIGINT UNSIGNED NOT NULL,
reviewer_id BIGINT UNSIGNED NULL,
reviewed_at DATETIME(6) NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)
ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_model_endpoint_code (endpoint_code),
KEY idx_model_endpoint_status (status, provider),
CONSTRAINT fk_model_endpoint_creator FOREIGN KEY (created_by) REFERENCES sys_user(id),
CONSTRAINT fk_model_endpoint_reviewer FOREIGN KEY (reviewer_id) REFERENCES sys_user(id),
CONSTRAINT chk_model_endpoint_status
CHECK (status IN ('draft', 'approved', 'active', 'disabled', 'archived'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='模型端点配置';
secret_ref 只保存环境变量名或密钥服务路径,禁止保存明文密钥。
8.8 model_routing_rule
CREATE TABLE model_routing_rule (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
release_id BIGINT UNSIGNED NOT NULL,
rule_code VARCHAR(64) NOT NULL,
agent_type VARCHAR(32) NOT NULL,
task_type VARCHAR(48) NOT NULL,
model_policy VARCHAR(32) NOT NULL,
primary_endpoint_id BIGINT UNSIGNED NOT NULL,
fallback_endpoint_ids JSON NULL,
condition_json JSON NULL,
max_attempts TINYINT UNSIGNED NOT NULL DEFAULT 2,
latency_budget_ms INT UNSIGNED NOT NULL DEFAULT 15000,
cost_budget DECIMAL(12,6) NULL,
priority INT NOT NULL DEFAULT 100,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_model_route_release (release_id, rule_code),
KEY idx_model_route_match
(release_id, agent_type, task_type, model_policy, priority),
CONSTRAINT fk_model_route_release FOREIGN KEY (release_id) REFERENCES config_release(id),
CONSTRAINT fk_model_route_primary
FOREIGN KEY (primary_endpoint_id) REFERENCES model_endpoint_config(id),
CONSTRAINT chk_model_route_attempts CHECK (max_attempts BETWEEN 1 AND 3)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='多模型路由规则';
fallback_endpoint_ids 是为旧版读取方保留的兼容字段,可为空;它不再作为备用链权威来源。若迁移期继续填充该字段,其端点顺序必须与 model_routing_fallback 按 fallback_order 排序后的结果完全一致,发布服务在同一配置发布事务中校验。
8.9 model_routing_fallback
CREATE TABLE model_routing_fallback (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
routing_rule_id BIGINT UNSIGNED NOT NULL,
endpoint_id BIGINT UNSIGNED NOT NULL,
fallback_order TINYINT UNSIGNED NOT NULL,
retryable_error_codes JSON NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_model_fallback_order (routing_rule_id, fallback_order),
UNIQUE KEY uk_model_fallback_endpoint (routing_rule_id, endpoint_id),
KEY idx_model_fallback_endpoint (endpoint_id),
CONSTRAINT fk_model_fallback_rule
FOREIGN KEY (routing_rule_id) REFERENCES model_routing_rule(id),
CONSTRAINT fk_model_fallback_endpoint
FOREIGN KEY (endpoint_id) REFERENCES model_endpoint_config(id),
CONSTRAINT chk_model_fallback_order CHECK (fallback_order BETWEEN 1 AND 2)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='模型路由有序备用端点';
model_routing_fallback 是备用链的权威关系表。发布服务必须校验主端点不出现在备用链中、每条路由的总端点数不超过 3,且 retryable_error_codes 只能包含平台登记的错误码。
8.10 prompt_template_version
CREATE TABLE prompt_template_version (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
release_id BIGINT UNSIGNED NOT NULL,
prompt_code VARCHAR(64) NOT NULL,
task_type VARCHAR(48) NOT NULL,
agent_type VARCHAR(32) NULL,
version INT UNSIGNED NOT NULL,
system_prompt MEDIUMTEXT NOT NULL,
user_prompt_template MEDIUMTEXT NOT NULL,
input_schema JSON NULL,
output_schema JSON NULL,
checksum CHAR(64) NOT NULL,
created_by BIGINT UNSIGNED NOT NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
UNIQUE KEY uk_prompt_version (prompt_code, version),
KEY idx_prompt_release_task (release_id, task_type, agent_type),
CONSTRAINT fk_prompt_release FOREIGN KEY (release_id) REFERENCES config_release(id),
CONSTRAINT fk_prompt_creator FOREIGN KEY (created_by) REFERENCES sys_user(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
COMMENT='Prompt不可变版本';
9. 创建与迁移顺序
9.1 空库创建顺序
- 创建数据库和 Alembic 版本表。
- 创建
sys_user、角色、权限及用户角色关系。 - 创建客户画像、风险测评和客户归属。
- 创建产品、行情、账户、费用、委托、成交、资金和持仓。
- 创建预警、通知、风险工单、内容和审计表。
- 创建对话、知识、Episode 和记忆相关表。
- 创建
agent_negative_word和svc_handover_ticket。 - 创建
agent_faq_synonym和conversation_feedback。 - 创建
agent_reply_template和agent_intent_config。 - 创建会话、幂等、
agent_run和通用事件 Outbox 表。 - 创建配置发布、平台配置、模型端点、模型路由、路由备用端点和 Prompt 表。
- 写入初始角色、权限、意图、模板、模型路由和禁止表达。
- 建立 Milvus 集合、Neo4j 约束和 Redis Key 规范。
9.2 已有库升级
- 备份结构和关键表数据。
- 使用 Inspector 获取真实列、索引和外键。
- 只增加缺失字段,不重建或覆盖现有业务表。
- 新字段先允许兼容旧代码,再部署双版本兼容应用。
- 回填知识正文、审核状态和对话分类信息。
- 创建专项表和平台底座增量表。
- 发布首个完整配置快照。
- 部署新代码并验证双版本兼容读写。
content_text 在已有知识数据未回填前保持可空。即使回填完成,也不修改该已有字段定义;由应用校验和发布条件保证已发布知识正文非空。
10. 初始数据
10.1 内置角色
customeradvisoroperatorrisk_operatoradminsuper_admin
10.2 客服初始禁止表达
至少录入:保本、稳赚、无风险、保证收益、预期收益率、年化收益率、安全,以及经合规确认的变体。初始状态必须经过审核后才可以设置为 active。
10.3 客服初始模板
- 固定免责声明。
- AI 生成标识。
- 低置信兜底。
- 合规拒答。
- 转人工提示。
- 模型故障和系统繁忙提示。
11. 事务和并发要求
- 模拟成交、账户余额、资金明细和持仓必须在一个事务内提交。
- 工单状态更新采用乐观锁或条件更新,禁止重复接单覆盖。
- 画像版本和 Outbox 事件在同一事务提交。
- 助手消息、执行审计和
domain_event_outbox在同一短事务提交。 - 幂等记录通过唯一键抢占,完成状态与结果消息在同一事务更新。
- 配置发布批次和全部配置项校验通过后才能原子激活。
- 模板和意图新版本发布时,旧版本失效与新版本生效必须原子完成。
- 审计记录与受监管的业务状态变更应在同一事务写入。
- 外部模型、邮件、Milvus 和 Neo4j 调用不得放入 MySQL 长事务。
12. 数据安全
password_hash不向 Agent、风控或 NL2SQL 开放。- 身份证、手机号、银行卡号和精确账户余额不得写入 Milvus 或 Neo4j。
source_references只保存必要的来源标识,不复制整份文档。- SQL 查询必须应用
data_scope和客户归属过滤。 interaction_audit仅追加,不允许普通业务接口更新或删除。- 生产备份、迁移导出和错误日志均执行敏感字段保护。
- 模型端点表只保存
secret_ref,不得保存 API 明文密钥。
13. 验证清单
- 51 张业务表全部存在(另有
alembic_version),原 39 张表的名称和已有字段定义保持不变。 - 主键、唯一键、外键和检查约束生效;唯一键必须与
docs/00声明一致,由tools/audit_constraints.py逐表比对。 - 2026-09-09 约束纠偏:
fin_market_price、fin_nav_history、fin_holding、sys_customer_assignment四张表的联合唯一键曾被基线生成器错误拆成单列唯一键,已由迁移20260909_constraint_fix修正(删 8 个错误唯一键、加 4 个联合唯一键),docs/00未做修改。证据见docs/evidence/与docs/08。 conversation_message三个 Agent 增量字段和既有tool_calls字段可正常读写。- 知识检索只命中已发布且在有效期内的条目。
- Milvus 故障时 MySQL 正文降级检索可用。
- 客服转人工工单与风险工单完全独立。
- 同义问法只有审核通过后参与检索。
- 一个客户对同一回复不能重复反馈。
- 模板和意图配置可版本化发布和回滚。
- 每个模板或意图组合最多一个
active版本,备用模型端点均受外键约束且顺序唯一。 - 越权客户查询被数据库访问层和服务层共同拒绝。
- Redis 丢失可以从 MySQL 恢复必要记忆。
- Milvus 或 Neo4j 单边失败不会丢失 Outbox 事件。
- 重复请求不会重复生成消息、工单或领域事件。
- 配置发布失败时旧版本继续有效,回滚不修改历史版本。
- 模型路由最多尝试三个已审核端点,并完整记录采用版本。
- 所有迁移在空库、旧版本库和回滚路径各执行一次。
14. 已知实施前提
6 张专项表的字段由本文补全并作为建议实施结构。若团队已有《智能客服Agent新增表详细设计.md》,合并前必须逐字段比较;业务编号、状态枚举、审核流和外键语义不一致时,由数据库负责人组织评审,不允许两个定义同时进入迁移脚本。