chore: 文档与 IDE 配置整理
- .kiro/specs/ → docs/specs/(41 个历史需求 spec 迁移,移除 .config.kiro) - CLAUDE.md 三层拆分:根文件精简 + apps/backend/CLAUDE.md + .claude/commands/ - 新增 /spec-close、/pre-change 两个工作流命令 - DDL 基线刷新(从测试库重新导出 11 个文件,dws 35→38 表,biz 18→21 表) - BD_Manual → BD_manual 命名统一(48 个文件) - 修复 3 处文档与数据库不一致(auth.users.status 默认值、scheduled_tasks 字段、RLS 视图数) - 新增 BD_manual_public_rbac_tables.md(public schema 8 张 RBAC/工作流表) - 合并 biz.trigger_jobs 文档(10→12 字段,归档独立文档) - docs/database/README.md 索引更新 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,22 +1,26 @@
|
||||
# BD_Manual:biz Schema AI 表(对话记录 + 消息 + 缓存)
|
||||
# BD_Manual:biz Schema AI 表(对话记录 + 消息 + 缓存 + 运行日志 + 调度记录)
|
||||
|
||||
> 目标库:`test_zqyy_app`(通过 `APP_DB_DSN` 连接)
|
||||
> 迁移脚本:
|
||||
> - `db/zqyy_app/migrations/2026-03-08__create_ai_tables.sql`(初始建表)
|
||||
> - `db/zqyy_app/migrations/2026-03-20__rns14_chat_module_extend.sql`(RNS1.4 CHAT 扩展)
|
||||
> 关联 SPEC:`05-miniapp-ai-integration`(P5 AI 集成层)、`rns1-chat-integration`(RNS1.4 CHAT 对齐与联调收尾)
|
||||
> - `db/zqyy_app/migrations/2026-03-22__p14_ai_module.sql`(P14 DashScope 迁移 + 调度器完善)
|
||||
> - `db/zqyy_app/migrations/2026-03-23__p15_ai_monitoring.sql`(P15 AI 监控后台 — alert_status + BRIN 索引)
|
||||
> 关联 SPEC:`05-miniapp-ai-integration`(P5 AI 集成层)、`rns1-chat-integration`(RNS1.4 CHAT 对齐与联调收尾)、`P14-ai-dashscope-migration`(P14 DashScope 迁移)、`ai-monitoring-testing`(P15 AI 监控后台)
|
||||
|
||||
---
|
||||
|
||||
## 1. 变更说明
|
||||
|
||||
### 新增表(3 张,P5 初始建表)
|
||||
### 新增表(5 张)
|
||||
|
||||
| # | 表名 | 用途 | 字段数(初始→当前) |
|
||||
|---|------|------|---------------------|
|
||||
| 1 | `biz.ai_conversations` | AI 对话记录:每次 AI 调用(用户主动或系统自动)创建一条 | 8 → 13 |
|
||||
| 2 | `biz.ai_messages` | AI 消息记录:对话中的每条消息(输入/输出/系统) | 6 → 7 |
|
||||
| 3 | `biz.ai_cache` | AI 应用缓存:各应用的结构化输出结果 | 9 |
|
||||
| # | 表名 | 用途 | 字段数(初始→当前) | 来源 |
|
||||
|---|------|------|---------------------|------|
|
||||
| 1 | `biz.ai_conversations` | AI 对话记录:每次 AI 调用(用户主动或系统自动)创建一条 | 8 → 14 | P5 |
|
||||
| 2 | `biz.ai_messages` | AI 消息记录:对话中的每条消息(输入/输出/系统) | 6 → 7 | P5 |
|
||||
| 3 | `biz.ai_cache` | AI 应用缓存:各应用的结构化输出结果 | 9 → 10 | P5 |
|
||||
| 4 | `biz.ai_run_logs` | **P14 新增** — AI 运行记录:每次 DashScope API 调用的详细日志 | 14 → 15 | P14, P15 |
|
||||
| 5 | `biz.ai_trigger_jobs` | **P14 新增** — 调度运行记录:每次 AI 事件触发的编排执行记录 | 13 | P14 |
|
||||
|
||||
### RNS1.4 CHAT 模块扩展字段(2026-03-20)
|
||||
|
||||
@@ -25,9 +29,26 @@
|
||||
| 1 | `biz.ai_conversations` | `context_type`, `context_id`, `title`, `last_message`, `last_message_at` | 多入口对话复用 + 历史列表展示与排序 |
|
||||
| 2 | `biz.ai_messages` | `reference_card` | 引用卡片 JSON(客户概览等结构化上下文数据) |
|
||||
|
||||
### P14 DashScope 迁移扩展字段(2026-03-22)
|
||||
|
||||
| # | 表名 | 新增字段 | 用途 |
|
||||
|---|------|---------|------|
|
||||
| 1 | `biz.ai_conversations` | `session_id` | 百炼 session_id(格式 `conv_{id}_{ts}`),仅 App1 使用 |
|
||||
| 2 | `biz.ai_cache` | `status` | 缓存状态:valid / expired / invalidated / generating |
|
||||
|
||||
### P15 AI 监控后台扩展(2026-03-23)
|
||||
|
||||
| # | 表名 | 变更类型 | 说明 |
|
||||
|---|------|---------|------|
|
||||
| 1 | `biz.ai_run_logs` | 新增字段 `alert_status` | 告警处理状态:NULL / pending / acknowledged / ignored |
|
||||
| 2 | `biz.ai_run_logs` | 新增约束 `chk_ai_run_logs_alert_status` | CHECK (alert_status IS NULL OR alert_status IN ('pending', 'acknowledged', 'ignored')) |
|
||||
| 3 | `biz.ai_run_logs` | 新增部分索引 `idx_ai_run_logs_alert` | (alert_status, created_at DESC) WHERE status IN ('failed', 'timeout', 'circuit_open') — 告警列表查询 |
|
||||
| 4 | `biz.ai_run_logs` | 新增 BRIN 索引 `idx_ai_run_logs_created_brin` | BRIN (created_at) WITH (pages_per_range = 32) — Dashboard 聚合优化 |
|
||||
| 5 | `biz.ai_run_logs` | 回填 | 已有 status IN ('failed','timeout','circuit_open') 的记录 alert_status 设为 'pending' |
|
||||
|
||||
### 表字段明细
|
||||
|
||||
#### biz.ai_conversations(13 字段)
|
||||
#### biz.ai_conversations(14 字段)
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
@@ -39,11 +60,12 @@
|
||||
| `source_page` | VARCHAR(100) | 可空 | 来源页面标识 |
|
||||
| `source_context` | JSONB | 可空 | 页面上下文 JSON |
|
||||
| `created_at` | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | 创建时间 |
|
||||
| `context_type` | VARCHAR(20) | 可空 | **RNS1.4 新增** — 对话关联上下文类型:task(任务)/ customer(客户)/ coach(助教)/ general(通用) |
|
||||
| `context_id` | VARCHAR(50) | 可空 | **RNS1.4 新增** — 关联上下文 ID:task 入口为 taskId,customer 入口为 customerId,coach 入口为 coachId,general 为 NULL |
|
||||
| `title` | VARCHAR(200) | 可空 | **RNS1.4 新增** — 对话标题:自定义 > 上下文名称 > 首条消息前20字 |
|
||||
| `context_type` | VARCHAR(20) | 可空 | **RNS1.4 新增** — 对话关联上下文类型:task / customer / coach / general |
|
||||
| `context_id` | VARCHAR(50) | 可空 | **RNS1.4 新增** — 关联上下文 ID |
|
||||
| `title` | VARCHAR(200) | 可空 | **RNS1.4 新增** — 对话标题 |
|
||||
| `last_message` | TEXT | 可空 | **RNS1.4 新增** — 最后一条消息内容摘要(截断至100字) |
|
||||
| `last_message_at` | TIMESTAMPTZ | 可空 | **RNS1.4 新增** — 最后消息时间,用于历史列表排序和对话复用时限判断 |
|
||||
| `last_message_at` | TIMESTAMPTZ | 可空 | **RNS1.4 新增** — 最后消息时间 |
|
||||
| `session_id` | VARCHAR(100) | 可空 | **P14 新增** — 百炼 session_id,格式 `conv_{conversation_id}_{created_timestamp}`,仅 App1 使用 |
|
||||
|
||||
#### biz.ai_messages(7 字段)
|
||||
|
||||
@@ -57,7 +79,7 @@
|
||||
| `created_at` | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | 创建时间 |
|
||||
| `reference_card` | JSONB | 可空 | **RNS1.4 新增** — 引用卡片 JSON:`{type, title, summary, data}`,用于展示客户概览等结构化上下文数据 |
|
||||
|
||||
#### biz.ai_cache(9 字段)
|
||||
#### biz.ai_cache(10 字段)
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
@@ -70,6 +92,7 @@
|
||||
| `triggered_by` | VARCHAR(100) | 可空 | 触发来源标识 |
|
||||
| `created_at` | TIMESTAMPTZ | NOT NULL DEFAULT NOW() | 创建时间 |
|
||||
| `expires_at` | TIMESTAMPTZ | 可空 | 可选过期时间 |
|
||||
| `status` | VARCHAR(20) | DEFAULT 'valid', CHECK | **P14 新增** — 缓存状态:valid(有效)/ expired(已过期)/ invalidated(手动失效)/ generating(生成中) |
|
||||
|
||||
### cache_type 枚举值与 target_id 约定
|
||||
|
||||
@@ -89,14 +112,62 @@
|
||||
|----|-----------|------|------|
|
||||
| `ai_conversations` | `idx_ai_conv_user_site` | INDEX | `(user_id, site_id, created_at DESC)` — 用户历史对话列表查询 |
|
||||
| `ai_conversations` | `idx_ai_conv_app_site` | INDEX | `(app_id, site_id, created_at DESC)` — 按应用查询对话 |
|
||||
| `ai_conversations` | `idx_ai_conv_context` | INDEX(条件) | **RNS1.4** — `(user_id, site_id, context_type, context_id, last_message_at DESC) WHERE context_type IS NOT NULL` |
|
||||
| `ai_conversations` | `idx_ai_conv_last_msg` | INDEX | **RNS1.4** — `(user_id, site_id, last_message_at DESC NULLS LAST)` |
|
||||
| `ai_messages` | FK `conversation_id` | FK | → `biz.ai_conversations(id)` ON DELETE CASCADE |
|
||||
| `ai_messages` | `chk_ai_msg_role` | CHECK | `role IN ('user', 'assistant', 'system')` |
|
||||
| `ai_messages` | `idx_ai_msg_conv` | INDEX | `(conversation_id, created_at)` — 对话消息列表 |
|
||||
| `ai_cache` | `chk_ai_cache_type` | CHECK | 7 个枚举值 |
|
||||
| `ai_cache` | `chk_ai_cache_status` | CHECK | **P14** — `status IN ('valid', 'expired', 'invalidated', 'generating')` |
|
||||
| `ai_cache` | `idx_ai_cache_lookup` | INDEX | `(cache_type, site_id, target_id, created_at DESC)` — 查询最新缓存 |
|
||||
| `ai_cache` | `idx_ai_cache_cleanup` | INDEX | `(cache_type, site_id, target_id, created_at)` — 清理超限记录(ASC 排序便于删除最旧) |
|
||||
| `ai_conversations` | `idx_ai_conv_context` | INDEX(条件) | **RNS1.4 新增** — `(user_id, site_id, context_type, context_id, last_message_at DESC NULLS LAST) WHERE context_type IS NOT NULL` — 上下文对话查找(多入口复用) |
|
||||
| `ai_conversations` | `idx_ai_conv_last_msg` | INDEX | **RNS1.4 新增** — `(user_id, site_id, last_message_at DESC NULLS LAST)` — 历史列表排序优化(CHAT-1 倒序) |
|
||||
| `ai_cache` | `idx_ai_cache_cleanup` | INDEX | `(cache_type, site_id, target_id, created_at)` — 清理超限记录 |
|
||||
| `ai_run_logs` | `idx_ai_run_logs_site_app` | INDEX | **P14** — `(site_id, app_type)` |
|
||||
| `ai_run_logs` | `idx_ai_run_logs_created` | INDEX | **P14** — `(created_at)` — Token 预算聚合 |
|
||||
| `ai_run_logs` | `idx_ai_run_logs_status` | INDEX | **P14** — `(status)` |
|
||||
| `ai_run_logs` | `chk_ai_run_logs_alert_status` | CHECK | **P15** — `alert_status IS NULL OR alert_status IN ('pending', 'acknowledged', 'ignored')` |
|
||||
| `ai_run_logs` | `idx_ai_run_logs_alert` | INDEX(部分) | **P15** — `(alert_status, created_at DESC) WHERE status IN ('failed', 'timeout', 'circuit_open')` — 告警列表查询优化 |
|
||||
| `ai_run_logs` | `idx_ai_run_logs_created_brin` | BRIN INDEX | **P15** — `BRIN (created_at) WITH (pages_per_range = 32)` — Dashboard 聚合查询优化,适合按时间顺序插入的表 |
|
||||
| `ai_trigger_jobs` | `idx_ai_trigger_jobs_site` | INDEX | **P14** — `(site_id, event_type)` |
|
||||
| `ai_trigger_jobs` | `idx_ai_trigger_jobs_dedup` | INDEX(条件) | **P14** — `(event_type, member_id, site_id, created_at) WHERE status NOT IN ('skipped_duplicate')` — 去重 |
|
||||
| `ai_trigger_jobs` | `idx_ai_trigger_jobs_status` | INDEX | **P14** — `(status)` |
|
||||
|
||||
#### biz.ai_run_logs(15 字段,P14 新增 + P15 扩展)
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGSERIAL | PK | 自增主键 |
|
||||
| `site_id` | BIGINT | NOT NULL | 门店 ID |
|
||||
| `app_type` | VARCHAR(30) | NOT NULL | 应用类型:app1_chat / app2_finance / ... / app8_consolidate |
|
||||
| `trigger_type` | VARCHAR(20) | NOT NULL | 触发类型:user / scheduled / event / forced |
|
||||
| `member_id` | BIGINT | 可空 | 会员 ID |
|
||||
| `request_prompt` | TEXT | 可空 | 请求 prompt(截断前 2000 字符) |
|
||||
| `response_text` | TEXT | 可空 | 响应文本 |
|
||||
| `tokens_used` | INTEGER | DEFAULT 0 | 消耗 token 数 |
|
||||
| `latency_ms` | INTEGER | 可空 | 调用延迟(毫秒) |
|
||||
| `status` | VARCHAR(20) | NOT NULL DEFAULT 'pending' | 状态:pending / running / success / failed / timeout / budget_exceeded |
|
||||
| `error_message` | TEXT | 可空 | 错误信息 |
|
||||
| `session_id` | VARCHAR(100) | 可空 | 百炼 session_id(仅 App1) |
|
||||
| `alert_status` | VARCHAR(20) | DEFAULT NULL, CHECK | **P15 新增** — 告警处理状态:NULL(非告警记录)/ pending(待处理)/ acknowledged(已确认)/ ignored(已忽略)。仅 status IN ('failed','timeout','circuit_open') 的记录才设置此字段 |
|
||||
| `created_at` | TIMESTAMPTZ | NOT NULL DEFAULT now() | 创建时间 |
|
||||
| `finished_at` | TIMESTAMPTZ | 可空 | 完成时间 |
|
||||
|
||||
#### biz.ai_trigger_jobs(13 字段,P14 新增)
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | BIGSERIAL | PK | 自增主键 |
|
||||
| `site_id` | BIGINT | NOT NULL | 门店 ID |
|
||||
| `event_type` | VARCHAR(30) | NOT NULL | 事件类型:consumption / dws_completed / note_created / task_assigned |
|
||||
| `connector_type` | VARCHAR(30) | DEFAULT 'feiqiu' | 连接器类型 |
|
||||
| `member_id` | BIGINT | 可空 | 会员 ID |
|
||||
| `payload` | JSONB | 可空 | 附加数据 |
|
||||
| `status` | VARCHAR(20) | NOT NULL DEFAULT 'pending' | 状态:pending / running / completed / failed / skipped_duplicate / budget_exceeded |
|
||||
| `is_forced` | BOOLEAN | DEFAULT false | 是否强制执行(跳过去重检查) |
|
||||
| `app_chain` | VARCHAR(100) | 可空 | 调用链描述,如 `app3→app8→app7` |
|
||||
| `started_at` | TIMESTAMPTZ | 可空 | 开始时间 |
|
||||
| `finished_at` | TIMESTAMPTZ | 可空 | 完成时间 |
|
||||
| `error_message` | TEXT | 可空 | 错误信息 |
|
||||
| `created_at` | TIMESTAMPTZ | NOT NULL DEFAULT now() | 创建时间 |
|
||||
|
||||
---
|
||||
|
||||
@@ -104,19 +175,56 @@
|
||||
|
||||
| 组件 | 影响 |
|
||||
|------|------|
|
||||
| ETL 任务 | 无影响。AI 表属于 `biz` Schema,不参与 ETL 流程 |
|
||||
| 后端 API | 直接依赖。P5 AI 模块(`apps/backend/app/ai/`)将基于这三张表实现对话持久化、缓存读写、SSE 流式对话等功能 |
|
||||
| 后端 API(RNS1.4) | **直接依赖**。CHAT 模块(`apps/backend/app/routers/xcx_chat.py`、`apps/backend/app/services/chat_service.py`)依赖 `ai_conversations` 的 5 个新字段(`context_type`/`context_id`/`title`/`last_message`/`last_message_at`)实现多入口对话复用、历史列表展示与排序;依赖 `ai_messages.reference_card` 存储引用卡片 JSON |
|
||||
| ETL 任务 | **P14 新增**:DWS 任务完成后通过 `utils/ai_trigger.py` 发送 HTTP 触发事件到后端 `ai_trigger_jobs`,失败不中断 ETL 流程 |
|
||||
| 后端 API | 直接依赖。P5 AI 模块(`apps/backend/app/ai/`)基于这些表实现对话持久化、缓存读写、SSE 流式对话等功能 |
|
||||
| 后端 API(RNS1.4) | **直接依赖**。CHAT 模块依赖 `ai_conversations` 的 5 个 RNS1.4 字段实现多入口对话复用 |
|
||||
| 后端 API(P14) | **直接依赖**。`ai_run_logs` 用于 Token 预算聚合(BudgetTracker);`ai_trigger_jobs` 用于事件去重和调度记录;`ai_conversations.session_id` 用于百炼会话管理;`ai_cache.status` 用于缓存状态控制 |
|
||||
| 小程序 | 间接依赖。小程序通过后端 AI API 间接使用对话和缓存数据 |
|
||||
| 小程序(RNS1.4) | **间接依赖**。`pages/chat/chat.ts` 和 `pages/chat-history/chat-history.ts` 通过 CHAT-1/2/3/4 端点间接依赖新字段(`title`→对话标题、`lastMessage`→摘要、`timestamp`→排序、`referenceCard`→引用卡片渲染) |
|
||||
| 管理后台 | 暂无影响。后续可能增加 AI 调用统计和缓存管理界面 |
|
||||
| `member_retention_clue` | 间接关联。App8(维客线索整理)的结果同时写入 `ai_cache` 和 `member_retention_clue` 表 |
|
||||
| 现有 `biz` Schema | 兼容。P5 新增 3 张表;RNS1.4 仅在已有表上 ADD COLUMN / CREATE INDEX,不修改已有字段或约束 |
|
||||
| 管理后台 | **P15 直接依赖**。admin-web AI 监控后台(4 个页面)依赖 `ai_run_logs.alert_status` 实现告警管理(确认/忽略),依赖 BRIN 索引优化 Dashboard 聚合查询性能 |
|
||||
| `member_retention_clue` | 间接关联。App8 结果同时写入 `ai_cache` 和 `member_retention_clue` 表(P14 实现幂等 DELETE+INSERT) |
|
||||
|
||||
---
|
||||
|
||||
## 3. 回滚策略
|
||||
|
||||
### 3d. 回滚 P15 AI 监控后台(2026-03-23 迁移)
|
||||
|
||||
按逆序 DROP 新增索引、约束和字段:
|
||||
|
||||
```sql
|
||||
BEGIN;
|
||||
DROP INDEX IF EXISTS biz.idx_ai_run_logs_created_brin;
|
||||
DROP INDEX IF EXISTS biz.idx_ai_run_logs_alert;
|
||||
ALTER TABLE biz.ai_run_logs DROP CONSTRAINT IF EXISTS chk_ai_run_logs_alert_status;
|
||||
ALTER TABLE biz.ai_run_logs DROP COLUMN IF EXISTS alert_status;
|
||||
COMMIT;
|
||||
```
|
||||
|
||||
注意:
|
||||
- 回滚后 admin-web AI 监控后台的告警管理功能将不可用
|
||||
- Dashboard 聚合查询性能可能下降(失去 BRIN 索引)
|
||||
- 回滚不影响 P14 的核心功能(调度器、预算追踪等)
|
||||
|
||||
### 3c. 回滚 P14 DashScope 迁移(2026-03-22 迁移)
|
||||
|
||||
按逆序 DROP 新增表和字段:
|
||||
|
||||
```sql
|
||||
-- 删除 P14 新增约束和字段
|
||||
ALTER TABLE biz.ai_cache DROP CONSTRAINT IF EXISTS chk_ai_cache_status;
|
||||
ALTER TABLE biz.ai_cache DROP COLUMN IF EXISTS status;
|
||||
ALTER TABLE biz.ai_conversations DROP COLUMN IF EXISTS session_id;
|
||||
|
||||
-- 删除 P14 新增表
|
||||
DROP TABLE IF EXISTS biz.ai_trigger_jobs;
|
||||
DROP TABLE IF EXISTS biz.ai_run_logs;
|
||||
```
|
||||
|
||||
注意:
|
||||
- 回滚后 P14 AI 调度器(dispatcher)、Token 预算追踪(BudgetTracker)将无法正常工作
|
||||
- `ai_run_logs` 和 `ai_trigger_jobs` 中的数据将丢失,需先备份
|
||||
- 回滚不影响 P5 和 RNS1.4 的功能
|
||||
|
||||
### 3a. 回滚 RNS1.4 CHAT 扩展(2026-03-20 迁移)
|
||||
|
||||
按逆序 DROP 新增索引和字段:
|
||||
@@ -185,7 +293,7 @@ SELECT column_name, data_type, is_nullable
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'biz' AND table_name = 'ai_conversations'
|
||||
ORDER BY ordinal_position;
|
||||
-- 预期:返回 13 行(P5 原始 8 字段 + RNS1.4 新增 5 字段)
|
||||
-- 预期:返回 14 行(P5 原始 8 + RNS1.4 新增 5 + P14 session_id = 14)
|
||||
|
||||
-- 3. 验证 ai_messages 的外键和 CHECK 约束
|
||||
SELECT conname, contype, pg_get_constraintdef(oid) AS constraint_def
|
||||
@@ -198,7 +306,7 @@ ORDER BY conname;
|
||||
SELECT conname, pg_get_constraintdef(oid) AS constraint_def
|
||||
FROM pg_constraint
|
||||
WHERE conrelid = 'biz.ai_cache'::regclass AND contype = 'c';
|
||||
-- 预期:返回 1 行 chk_ai_cache_type,包含 7 个枚举值
|
||||
-- 预期:返回 2 行(chk_ai_cache_type 含 7 个枚举值,chk_ai_cache_status 含 4 个状态值)
|
||||
|
||||
-- 5. 验证 P5 初始索引全部存在(5 个)
|
||||
SELECT indexname
|
||||
@@ -244,3 +352,101 @@ WHERE schemaname = 'biz' AND tablename = 'ai_conversations'
|
||||
-- idx_ai_conv_context — 含 WHERE context_type IS NOT NULL 条件
|
||||
-- idx_ai_conv_last_msg — (user_id, site_id, last_message_at DESC NULLS LAST)
|
||||
```
|
||||
|
||||
### 4c. P14 DashScope 迁移验证
|
||||
|
||||
```sql
|
||||
-- 9. 验证 ai_run_logs 表存在且字段正确
|
||||
SELECT column_name, data_type, character_maximum_length
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'biz' AND table_name = 'ai_run_logs'
|
||||
ORDER BY ordinal_position;
|
||||
-- 预期:返回 15 行
|
||||
|
||||
-- 10. 验证 ai_trigger_jobs 表存在且字段正确
|
||||
SELECT column_name, data_type, character_maximum_length
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'biz' AND table_name = 'ai_trigger_jobs'
|
||||
ORDER BY ordinal_position;
|
||||
-- 预期:返回 13 行
|
||||
|
||||
-- 11. 验证 ai_run_logs 索引(含 PK)
|
||||
SELECT indexname FROM pg_indexes
|
||||
WHERE schemaname = 'biz' AND tablename = 'ai_run_logs';
|
||||
-- 预期:6 行(PK + 3 P14 索引 + 2 P15 索引)
|
||||
|
||||
-- 12. 验证 ai_trigger_jobs 索引(含去重部分索引)
|
||||
SELECT indexname FROM pg_indexes
|
||||
WHERE schemaname = 'biz' AND tablename = 'ai_trigger_jobs';
|
||||
-- 预期:4 行(PK + 3 个索引)
|
||||
|
||||
-- 13. 验证 ai_conversations.session_id 字段
|
||||
SELECT column_name, data_type, character_maximum_length
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'biz' AND table_name = 'ai_conversations'
|
||||
AND column_name = 'session_id';
|
||||
-- 预期:1 行,varchar(100)
|
||||
|
||||
-- 14. 验证 ai_cache.status 字段 + CHECK 约束
|
||||
SELECT column_name, data_type, column_default
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'biz' AND table_name = 'ai_cache'
|
||||
AND column_name = 'status';
|
||||
-- 预期:1 行,varchar(20),default 'valid'
|
||||
|
||||
SELECT conname FROM pg_constraint
|
||||
WHERE conrelid = 'biz.ai_cache'::regclass AND conname = 'chk_ai_cache_status';
|
||||
-- 预期:1 行
|
||||
```
|
||||
|
||||
### 4d. P15 AI 监控后台验证
|
||||
|
||||
```sql
|
||||
-- 15. 验证 ai_run_logs.alert_status 字段存在
|
||||
SELECT column_name, data_type, character_maximum_length, column_default
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'biz' AND table_name = 'ai_run_logs'
|
||||
AND column_name = 'alert_status';
|
||||
-- 预期:1 行,varchar(20),default NULL
|
||||
|
||||
-- 16. 验证 alert_status CHECK 约束
|
||||
SELECT conname, pg_get_constraintdef(oid) AS constraint_def
|
||||
FROM pg_constraint
|
||||
WHERE conrelid = 'biz.ai_run_logs'::regclass
|
||||
AND conname = 'chk_ai_run_logs_alert_status';
|
||||
-- 预期:1 行,CHECK (alert_status IS NULL OR alert_status IN ('pending', 'acknowledged', 'ignored'))
|
||||
|
||||
-- 17. 验证 P15 新增索引(部分索引 + BRIN 索引)
|
||||
SELECT indexname, indexdef
|
||||
FROM pg_indexes
|
||||
WHERE schemaname = 'biz' AND tablename = 'ai_run_logs'
|
||||
AND indexname IN ('idx_ai_run_logs_alert', 'idx_ai_run_logs_created_brin');
|
||||
-- 预期:2 行
|
||||
-- idx_ai_run_logs_alert — 含 WHERE status IN ('failed', 'timeout', 'circuit_open')
|
||||
-- idx_ai_run_logs_created_brin — USING brin
|
||||
|
||||
-- 18. 验证 ai_run_logs 总索引数(P14 3个 + P15 2个 + PK = 6)
|
||||
SELECT indexname FROM pg_indexes
|
||||
WHERE schemaname = 'biz' AND tablename = 'ai_run_logs';
|
||||
-- 预期:6 行
|
||||
|
||||
-- 19. 验证回填结果:失败/超时/熔断记录的 alert_status 应为 'pending'
|
||||
SELECT COUNT(*) AS unset_alerts
|
||||
FROM biz.ai_run_logs
|
||||
WHERE status IN ('failed', 'timeout', 'circuit_open')
|
||||
AND alert_status IS NULL;
|
||||
-- 预期:0(所有失败记录已回填为 'pending')
|
||||
```
|
||||
|
||||
### P15 admin API 查询模式说明
|
||||
|
||||
P15 admin-web AI 监控后台引入以下典型查询模式:
|
||||
|
||||
| 查询场景 | SQL 模式 | 使用索引 |
|
||||
|---------|---------|---------|
|
||||
| Dashboard 今日统计 | `SELECT COUNT(*), AVG(latency_ms) FROM ai_run_logs WHERE created_at >= 今日零点` | `idx_ai_run_logs_created_brin` |
|
||||
| Dashboard 7天趋势 | `SELECT date_trunc('day', created_at), COUNT(*) FROM ai_run_logs WHERE created_at >= 7天前 GROUP BY 1` | `idx_ai_run_logs_created_brin` |
|
||||
| 告警列表 | `SELECT * FROM ai_run_logs WHERE status IN ('failed','timeout','circuit_open') AND alert_status = 'pending' ORDER BY created_at DESC` | `idx_ai_run_logs_alert` |
|
||||
| 告警确认/忽略 | `UPDATE ai_run_logs SET alert_status = 'acknowledged' WHERE id = ?` | PK |
|
||||
| 调用记录分页 | `SELECT * FROM ai_run_logs WHERE site_id = ? AND app_type = ? ORDER BY created_at DESC LIMIT ? OFFSET ?` | `idx_ai_run_logs_site_app` |
|
||||
| Token 预算聚合 | `SELECT SUM(tokens_used) FROM ai_run_logs WHERE created_at >= 今日零点 AND status = 'success'` | `idx_ai_run_logs_created` (B-tree) |
|
||||
|
||||
Reference in New Issue
Block a user