Files
group_fqcd_jr/docs/02-数据库建表设计.md
T
lzf_0626 36c7a9d8d2 文档:审查报告入库 + 全量校对补注
## 新入库(`docs/演示用/`)

- `代码库全面审查报告-2026-09-14.md`
- `代码修改方案-2026-09-14.md`
- `记忆系统排查报告-2026-09-14.md`
- `记忆系统修复文档-2026-09-14.md`
- `文档一致性审计报告-2026-09-14.md`
- `多Worker接入方案-2026-09-14.md`

## 全量校对(32 个既有文档 + `AGENTS.md`)

跨 39 个文件、**1125 insertions / 148 deletions**。

⚠️ **这批改动同样不是本次会话写的**。我抽样核对过性质:是**实质内容补充**而不是
格式/换行转换。例如 `docs/44-演示流程.md` 新增两条"2026-09-14 补注":

- `启动金融Agent平台.bat` 只在**桌面**上,仓库里只有 `启动平台.bat` 这一份
  (两份由同一个 `tools/make_launcher_bat.py` 产出,改完 `start.ps1` 重跑它一起更新);
- `advisor_t`(9020) 与 `offsite_t`(9006) **不在 `tools/seed_test_rbac.py` 的演示用户里**
  (那里只有 `cust_t`/`risk_t`/`admin_t`/`review_t` 四个),由 `grant_*.py` 系列创建,
  **重跑种子不会重建它们** —— 换机器时这两个账号登录失败,要先查 `sys_user` 有没有这两行,
  而不是查密码。

这两条都是对的地方,与我这一路踩到的现象一致(我确实用到了 `advisor_t`/`offsite_t`)。

**我没有逐字审阅全部 39 个文件**,只抽样确认了改动性质与规模。若其中有需要复核的段落,
请指明文件,我逐处核对。
2026-09-14 20:36:00 +08:00

44 KiB
Raw Blame History

数据库建表设计

版本:v3.1
修订日期:2026-09-09
演进原则:只允许新增表和新增字段,不修改已有表名、已有字段名、字段类型及既有业务含义

1. 文档目的

本文定义通用 Agent 平台、记忆系统和智能客服专项能力的数据库建设方案。数据库业务基线已固化为项目内的《00-新数据库基线设计.md》,本文只在该基线上补充字段、表、实施顺序和迁移规则。

2. 数据库范围

  • 数据库:MySQL 8.0。
  • 默认字符集:utf8mb4。
  • 默认排序规则:utf8mb4_0900_ai_ci。
  • 场内基线分项(本文 §4–§7 的覆盖范围):
    • 基础业务表:33 张。
    • 智能客服专项表:6 张。
    • 平台底座增量表:12 张(原设计 10 张、outbox_delivery、api_request_receipt)。
    • 场内小计:51 张(包含会话补表及公共 HTTP 写操作幂等回执)。
  • ⚠️ 全库当前口径(2026-09-14 更正):90 张表 = 89 张业务表 + alembic_version, 分域为 场内 51 + 场外/推广 17 + 投顾 21。 本文只定义场内 51 张;后 38 张属独立业务域,不进 docs/00 基线(AGENTS.md 规则 8), 其登记见 docs/28-场外与推广域数据表登记.md(场外/推广 17 张)、投顾 21 张的登记文档待补。 本文写作时的"总表数 51"是场内口径,不是全库总数——切勿据此判断库内表数。
  • 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 张表总览(场内口径)

⚠️ 本节只覆盖场内 51 张。全库当前共 89 张业务表(场内 51 + 场外/推广 17 + 投顾 21), 见文首说明。场外/推广登记在 docs/28,投顾 21 张登记文档待补。

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 未修改。 变更记录(2026-09-11 合并说明):两条并行分支各自补了一次撤约束迁移—— 20260910_drop_review_separation(风控线)与 20260911_drop_review_separation(yc 线), 两者都先查 information_schema 再决定是否 ALTER,重复执行不会报错,因此合并后全部保留。 chk_config_release_status、全部外键、唯一键与索引不变,表名与字段定义未做任何改动; 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 空库创建顺序

  1. 创建数据库和 Alembic 版本表。
  2. 创建 sys_user、角色、权限及用户角色关系。
  3. 创建客户画像、风险测评和客户归属。
  4. 创建产品、行情、账户、费用、委托、成交、资金和持仓。
  5. 创建预警、通知、风险工单、内容和审计表。
  6. 创建对话、知识、Episode 和记忆相关表。
  7. 创建 agent_negative_word 和 svc_handover_ticket。
  8. 创建 agent_faq_synonym 和 conversation_feedback。
  9. 创建 agent_reply_template 和 agent_intent_config。
  10. 创建会话、幂等、agent_run 和通用事件 Outbox 表。
  11. 创建配置发布、平台配置、模型端点、模型路由、路由备用端点和 Prompt 表。
  12. 写入初始角色、权限、意图、模板、模型路由和禁止表达。
  13. 建立 Milvus 集合、Neo4j 约束和 Redis Key 规范。

9.2 已有库升级

  1. 备份结构和关键表数据。
  2. 使用 Inspector 获取真实列、索引和外键。
  3. 只增加缺失字段,不重建或覆盖现有业务表。
  4. 新字段先允许兼容旧代码,再部署双版本兼容应用。
  5. 回填知识正文、审核状态和对话分类信息。
  6. 创建专项表和平台底座增量表。
  7. 发布首个完整配置快照。
  8. 部署新代码并验证双版本兼容读写。

content_text 在已有知识数据未回填前保持可空。即使回填完成,也不修改该已有字段定义;由应用校验和发布条件保证已发布知识正文非空。

10. 初始数据

10.1 内置角色

  • customer
  • advisor
  • operator
  • risk_operator
  • admin
  • super_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 张表的名称和已有字段定义保持不变。 注:此处 51 为场内口径(本清单覆盖范围);全库另有场外/推广 17 张与投顾 21 张,共 89 张业务表。
  • 主键、唯一键、外键和检查约束生效;唯一键必须与 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》,合并前必须逐字段比较;业务编号、状态枚举、审核流和外键语义不一致时,由数据库负责人组织评审,不允许两个定义同时进入迁移脚本。