上线只是起点

Data Agent 上线后,真实用户会问出测试集从未覆盖的问法:

  • 「销售收入和新增客户数能放一张图吗」
  • 「华北区留存率为什么和上周报表不一致」
  • 「有没有按产品线拆的收入」(元数据未配置)

若只靠一次性交付,系统会静态腐烂。需要运营闭环:发现缺口 → 分类工单 → 更新元数据/知识 → 验证回归 → 监控再发现

自进化闭环总览

1
2
3
4
5
6
7
8
9
10
11
12
flowchart LR
U[用户问数] --> Q[qa_history 记录]
Q --> F[qa_feedback 反馈]
Q --> M[质量监控]
M --> G[bi_metric_gap 口径缺口]
F --> G
G --> T[治理任务分派]
T --> META[更新 MySQL 元数据]
T --> KB[更新 Markdown 知识]
META --> RE[重建索引 / 回归测试]
KB --> RE
RE --> U

口径缺口:bi_metric_gap

表结构(虚构)

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE bi_metric_gap (
gap_id VARCHAR(64) PRIMARY KEY,
source ENUM('user_feedback', 'low_score_retrieve', 'sql_empty', 'manual'),
user_question TEXT,
session_id VARCHAR(64),
status ENUM('open', 'triaged', 'resolved', 'wontfix'),
assignee VARCHAR(64),
resolution TEXT,
created_at DATETIME,
resolved_at DATETIME
);

自动建单规则

触发条件 source 示例
检索最高分 < 3 low_score_retrieve 「客单价」未配置
SQL 执行空结果且宽表应有数 sql_empty 区域别名「华北」未映射
用户点「结果不对」 user_feedback 留存率口径质疑
连续 3 次澄清放弃 user_feedback 时间表述「上上个季度」
1
2
3
4
5
def maybe_create_gap(question: str, retrieve_score: float, row_count: int):
if retrieve_score < 3:
insert_gap(source="low_score_retrieve", question=question)
if row_count == 0 and should_have_data(question):
insert_gap(source="sql_empty", question=question)

用户反馈采集

前端反馈组件

1
2
3
4
5
6
7
<template>
<div class="feedback-bar" v-if="messageId">
<span>本条结果有帮助吗?</span>
<el-button size="small" @click="submit(1)">👍</el-button>
<el-button size="small" @click="openDislike">👎</el-button>
</div>
</template>

反馈表

1
2
3
4
5
6
7
8
9
CREATE TABLE qa_feedback (
feedback_id VARCHAR(64) PRIMARY KEY,
history_id BIGINT,
session_id VARCHAR(64),
rating TINYINT, -- 1 赞 / -1 踩
reason_code VARCHAR(32), -- wrong_number / wrong_metric / slow / other
comment TEXT,
created_at DATETIME
);

reason_code 枚举

代码 含义 典型处置
wrong_number 数字不对 核对 extract_logic、宽表 seed
wrong_metric 指标认错 补关键词或澄清规则
missing_dimension 缺维度 新增维度配置或 gap
口径不清 解释不足 补 Markdown 知识
slow 太慢 执行计划、索引优化

质量监控指标

指标 计算 周目标(虚构)
检索命中率 高分命中数 / 总问数 ≥ 85%
澄清率 需澄清数 / 总问数 ≤ 25%
一次答对率 首轮即成功 / 总问数 ≥ 60%
反馈差评率 踩 / 有反馈问数 ≤ 15%
gap 解决周期 resolved_at - created_at ≤ 5 工作日
SQL 校验失败率 校验失败 / 总执行 ≈ 0%
1
2
3
4
5
6
7
-- 周检索命中率(虚构)
SELECT
COUNT(*) AS total,
SUM(CASE WHEN retrieve_score >= 3 THEN 1 ELSE 0 END) AS hit,
SUM(CASE WHEN retrieve_score >= 3 THEN 1 ELSE 0 END) / COUNT(*) AS hit_rate
FROM qa_history
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY);

工单处理流程

1
2
3
4
5
6
7
stateDiagram-v2
[*] --> open: 自动/手动建单
open --> triaged: 产品/BI 分诊
triaged --> resolved: 更新元数据或知识
triaged --> wontfix: 超出范围
resolved --> [*]: 回归通过
wontfix --> [*]

resolved 标准

  • MySQL 元数据已更新且 validate_data_pipeline 通过
  • 若动知识库,Chroma 索引已重建
  • 原问法加入 golden test
  • 关联 gap 单填写 resolution

虚构 resolution 示例

新增指标别名「营收」→ 销售收入;补充 bi_metric.alias;重建索引;golden 加 1 条。

元数据与知识协同更新

变更类型 MySQL Markdown 向量索引
新指标 bi_metric + extract_logic 新建指标文档 重建
口径修正 更新 extract_logic 更新规则章节 重建
区域别名 domain_keywords 区域口径说明 重建
纯 FAQ 可选 faq 文档 重建

原则:能进结构化元数据的,优先 MySQL;解释性、争议性内容进 Markdown。

低分问法分析例会

每周导出 TOP 20 低分问法:

1
2
3
4
5
6
7
SELECT user_question, retrieve_score, COUNT(*) AS cnt
FROM qa_history
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
AND retrieve_score < 3
GROUP BY user_question, retrieve_score
ORDER BY cnt DESC
LIMIT 20;

例会产出:

  1. 立即可配置项(别名、关键词)→ 当周 resolved
  2. 需业务确认口径 → triaged + 指派
  3. 超出 Agent 能力 → wontfix 或产品 backlog

Agent 模式演进占位

Direct 管道稳定后,可对复杂多步问题试点 ReAct Agent,例如:

「比较华东区与华北区 Q1 销售收入同比,哪个更高?」

需多步:两次查询 + 比较 + 解释。此类问法失败也应进入 gap,而非强行单 SQL。

1
2
3
4
5
6
flowchart TB
D[Direct 管道 80% 问法]
A[Agent 多步 20% 问法]
D --> MON[统一监控]
A --> MON
MON --> GAP[gap 池]

与组织协作

角色 职责
业务专家 口径确认、差评复核
BI 工程师 extract_logic、宽表质量
平台开发 管道、校验、前端反馈
产品经理 gap 分诊、优先级

建议双周问数运营会:过监控指标 + 清 gap 积压。

回归与发布

1
2
3
4
# gap 修复后的最小回归
python scripts/validate_data_pipeline.py --env staging
pytest tests/test_golden_questions.py -v
python scripts/rebuild_chroma_index.py --source knowledge/

发布检查:

  • golden test 全绿
  • 本周新增 gap 已 triaged
  • 差评工单 48h 内有回应(可先自动回复「已记录」)

虚构案例:华北区别名

现象:用户问「华北 2026Q1 销售收入」,空结果。

根因:宽表为 华北区,解析未归一化。

修复

1
2
3
UPDATE bi_domain
SET domain_keywords = CONCAT(domain_keywords, ',华北')
WHERE domain_code = 'SALES_OPS';

并在维度解析增加别名映射 华北 → 华北区。gap 单关单,golden 加问法。

本章小结

  • 落地后靠 gap + 反馈 + 监控 驱动自进化,不是一锤子买卖
  • 自动建单规则覆盖低分检索、空结果、用户差评
  • 元数据与 Markdown 分工明确,变更后必须回归与重建索引
  • Direct 管道与未来 Agent 多步共用同一套运营闭环

思考题

  1. 差评率突然上升,你会先查数据、模型还是前端?
  2. wontfix 的 gap 要不要对用户可见?如何设定预期?
  3. 如何防止「为冲命中率」乱加关键词导致指标误命中?

系列导航

主题
01 架构全景
02 Text-to-SQL
03 RAG 指标库
04 多轮澄清
05 安全校验
06 Vue3 工作台
07 演示验证
08 本篇

← 返回专题首页