在这里插入图片描述

每日一句正能量

🔵 格局:从“是非”到“风景”的跃迁
“提升自己的格局,很多琐碎的烦恼自然会烟烟云散。”
当你的认知从“街头巷尾”升至“高空俯瞰”,那些曾令你纠结的人情往来、微小得失,便如地图上的褶皱,在更大的版图中自然舒展、不再刺眼。

前言

经营问答里最危险的问题,往往不是 SQL 写错,而是“指标说对了名字,却说错了口径”。

例如用户问:

“这个月 GMV 为什么下降?”

听起来只是一个经营分析问题,但系统真正需要先回答:

这里的 GMV 到底指什么?
是否含退款订单?
是否含取消订单?
按下单时间还是支付时间统计?
是否包含税费、运费?
跨境订单是否折算成人民币?
历史月份是否使用当时口径,还是当前口径回算?

如果这些定义没有统一,Agent 即使查出一个数字,也可能只是“算对了一个错误指标”。

因此,AI Agent 做经营问答时,不能只连接数据库,还需要一层结构化知识库保存指标口径;同时,真实数据查询仍要通过受控工具层执行。本文沿用前文的架构约定:KFS MCP Server 指面向 KFS/数据库能力的 MCP 工具服务层,用于向 Agent 暴露受控查询工具。公开资料中,KFS 官方产品是 Kingbase FlySync;MCP 官方规范则允许 Server 暴露带输入 Schema 的工具供模型调用。

核心思路可以概括成一句话:

知识库负责解释“指标是什么”,
MCP 工具负责查询“数据是多少”。

两者必须在同一个口径版本、时间范围和权限上下文中工作。


1. 背景与问题

企业里一个“销售额”可能有五种定义:

下单金额
支付金额
确认收货金额
扣除退款后的净额
财务入账金额

业务部门都可能简称:

销售额

这类语义冲突是经营问答最典型的问题。

假设用户问:

“华东区 7 月销售额同比增长多少?”

Agent 如果直接根据字段名猜:

SUM(order_amount)

很可能错误。

真正流程应该先确认:

当前用户所在业务域默认的“销售额”定义

例如:

metric_code = PAID_GMV
definition = 支付成功订单实付金额总和
time_basis = pay_time
refund_rule = 不扣除后续退款
currency_rule = 按支付时币种折算人民币

然后再去查数据库。

在这里插入图片描述

这意味着经营问答 Agent 的上下文至少由两类事实组成:

语义事实:
指标定义、公式、适用范围、版本。

数据事实:
某时间、某区域、某渠道的实际数值。

把两者混在 Prompt 里硬编码,很快会失控。


2. 环境与数据

示例环境:

JDK 21
Spring Boot 3.3+
KingbaseES / PostgreSQL 类数据库
KFS MCP Server
MyBatis / JDBC
Redis
Embedding / 全文检索
OpenTelemetry

支付订单表:

CREATE TABLE payment_order (
    id BIGINT PRIMARY KEY,
    order_no VARCHAR(64) NOT NULL,
    region_code VARCHAR(16) NOT NULL,
    channel_code VARCHAR(32) NOT NULL,
    order_amount NUMERIC(18,2) NOT NULL,
    pay_amount NUMERIC(18,2) NOT NULL,
    refund_amount NUMERIC(18,2) NOT NULL DEFAULT 0,
    pay_status VARCHAR(16) NOT NULL,
    order_time TIMESTAMP NOT NULL,
    pay_time TIMESTAMP NULL
);

指标定义表:

CREATE TABLE metric_definition (
    metric_code VARCHAR(64) PRIMARY KEY,
    metric_name VARCHAR(128) NOT NULL,
    metric_aliases TEXT,
    definition TEXT NOT NULL,
    formula_text TEXT NOT NULL,
    time_basis VARCHAR(32) NOT NULL,
    freshness VARCHAR(32) NOT NULL,
    owner_dept VARCHAR(128) NOT NULL,
    security_level VARCHAR(32) NOT NULL,
    enabled BOOLEAN NOT NULL
);

指标版本表:

CREATE TABLE metric_version (
    id BIGINT PRIMARY KEY,
    metric_code VARCHAR(64) NOT NULL,
    version_no VARCHAR(32) NOT NULL,
    effective_from TIMESTAMP NOT NULL,
    effective_to TIMESTAMP NULL,
    definition TEXT NOT NULL,
    formula_text TEXT NOT NULL,
    change_reason TEXT,
    approved_by VARCHAR(64) NOT NULL,

    UNIQUE(metric_code, version_no)
);

维度白名单:

CREATE TABLE metric_dimension (
    metric_code VARCHAR(64) NOT NULL,
    dimension_code VARCHAR(64) NOT NULL,
    dimension_name VARCHAR(128) NOT NULL,
    allowed BOOLEAN NOT NULL,
    PRIMARY KEY(metric_code, dimension_code)
);

3. 复现过程

3.1 只靠模型记忆指标定义

最简单实现:

系统 Prompt:
GMV 就是成交总额。

这几乎没有工程价值。

因为:

口径会变
部门间定义不同
历史问答需要旧版本
Prompt 无法审计

一旦财务部门把 GMV 改为:

扣除全额退款

旧 Prompt 就过期了。

3.2 直接让模型查指标表也不够

可以暴露:

SELECT * FROM metric_definition

让 Agent 自己查。

问题是模型可能:

查错别名
忽略历史版本
忽略权限
一次拉回全部口径

指标解释需要一个专门的知识检索层,而不是“随便查数据库”。

3.3 同名指标跨部门冲突

例如:

运营 GMV:
支付成功金额

财务 GMV:
确认收入金额

用户只说:

GMV

Agent 必须结合:

用户部门
工作空间
默认业务域
问题上下文

选择正确口径。

否则数据查询即使准确,也是在回答另一个部门的问题。

3.4 历史口径问题

用户问:

“2025 年 12 月和 2026 年 1 月 GMV 为什么跳变?”

假设:

2026-01-01

开始 GMV 改口径。

如果系统永远读取当前定义,就会错误地把 2025 年数据按新口径解释。

所以知识库必须支持:

effective_from
effective_to

4. 方案实施

4.1 指标知识库必须结构化

在这里插入图片描述

每个指标至少应包含:

metric_code
metric_name
aliases
definition
formula
time_basis
dimensions
freshness
owner
security_level
effective period

不要只存一段 Markdown。

结构化后才能:

版本控制
权限过滤
自动校验
SQL 模板关联

4.2 稳定标识使用 metric_code

名称可以变:

成交额
支付成交额
实付GMV

但内部主键:

PAID_GMV

应该稳定。

Agent 最终工具调用也应传:

metricCode

而不是自然语言名称。

4.3 指标别名

例如:

{
  "metricCode": "PAID_GMV",
  "metricName": "支付GMV",
  "aliases": [
    "成交额",
    "支付成交额",
    "实付金额"
  ]
}

但别名并不意味着完全等价。

如果某别名在另一个业务域代表其他指标,应在检索阶段加入:

domain
department
tenant

约束。

4.4 知识检索工具

MCP Tool:

{
  "name": "resolve_metric",
  "inputSchema": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string"
      },
      "businessDomain": {
        "type": "string"
      },
      "asOfTime": {
        "type": "string"
      }
    },
    "required": [
      "query",
      "businessDomain"
    ]
  }
}

输出:

{
  "metricCode": "PAID_GMV",
  "metricName": "支付GMV",
  "version": "v3",
  "definition": "支付成功订单的实付金额总和",
  "timeBasis": "pay_time",
  "freshness": "near_realtime",
  "allowedDimensions": [
    "region",
    "channel"
  ]
}

4.5 版本必须由时间选择

SQL:

SELECT
    mv.metric_code,
    mv.version_no,
    mv.definition,
    mv.formula_text
FROM metric_version mv
WHERE mv.metric_code = ?
  AND mv.effective_from <= ?
  AND (
      mv.effective_to IS NULL
      OR mv.effective_to > ?
  )
ORDER BY mv.effective_from DESC
LIMIT 1;

这样问历史月份时能自动取当时口径。

4.6 指标定义与 SQL 模板关联

不要让模型根据自然语言定义临时猜 SQL。

可以增加:

CREATE TABLE metric_query_template (
    metric_code VARCHAR(64) NOT NULL,
    version_no VARCHAR(32) NOT NULL,
    template_code VARCHAR(64) NOT NULL,
    sql_template TEXT NOT NULL,
    PRIMARY KEY(
        metric_code,
        version_no,
        template_code
    )
);

例如:

SELECT
    SUM(pay_amount)
FROM payment_order
WHERE pay_status = 'SUCCESS'
  AND pay_time >= ?
  AND pay_time < ?;

当口径版本变化时:

定义
公式
SQL模板

一起版本化。

4.7 KFS MCP Server 不暴露任意 SQL

经营问答场景更适合:

query_metric
compare_metric
breakdown_metric

而不是:

execute_sql

工具:

{
  "name": "query_metric",
  "inputSchema": {
    "type": "object",
    "properties": {
      "metricCode": {
        "type": "string"
      },
      "metricVersion": {
        "type": "string"
      },
      "startTime": {
        "type": "string"
      },
      "endTime": {
        "type": "string"
      },
      "dimensions": {
        "type": "array"
      },
      "filters": {
        "type": "object"
      }
    },
    "required": [
      "metricCode",
      "metricVersion",
      "startTime",
      "endTime"
    ]
  }
}

4.8 服务端二次校验指标版本

不能完全相信模型传入:

metricVersion

服务端应再次校验:

该版本是否存在
时间是否匹配
用户是否有权限
维度是否合法

模型只是调用方,不是信任边界。

4.9 MyBatis 参数化实现

<select id="queryPaidGmv"
        resultType="MetricValue">
    SELECT
        SUM(pay_amount) AS metric_value
    FROM payment_order
    WHERE pay_status = 'SUCCESS'
      AND pay_time >= #{startTime}
      AND pay_time < #{endTime}
      <if test="regionCode != null">
        AND region_code = #{regionCode}
      </if>
</select>

这里所有值参数都用:

#{}

维度字段本身如果需要动态选择,则必须经过服务端白名单。

4.10 动态维度白名单

错误:

GROUP BY ${dimension}

如果 dimension 直接来自 Agent,不安全。

服务端:

String column =
    switch (dimension) {
        case "region" -> "region_code";
        case "channel" -> "channel_code";
        default ->
            throw new InvalidDimensionException();
    };

只有固定映射后的列名才能进入 SQL。

4.11 知识库权限和数据权限是两回事

用户可能:

能知道“利润率”的定义
但不能查看利润率真实数值。

也可能:

只能知道本部门指标定义。

所以要分别维护:

knowledge ACL
data ACL

不能因为能检索指标解释,就自动获得数据库查询权限。

4.12 多租户隔离

所有知识库检索都带:

tenant_id

所有 MCP Tool 同样带租户上下文,但该上下文最好从鉴权会话注入,而不是让模型自由填写。

4.13 数据库最小权限

Agent 查询账号:

agent_metric_reader

只访问指标视图:

GRANT SELECT
ON v_metric_payment
TO agent_metric_reader;

不要直接开放所有原始明细表。

4.14 结果脱敏

经营指标一般是聚合数据,但下钻时可能出现:

客户名称
手机号
订单号

MCP Server 应根据:

role
securityLevel

决定是否返回。

4.15 数据时效必须进入答案

如果指标定义:

freshness = T+1

用户问:

“今天利润率是多少?”

Agent 不应该把昨天最后一次数据装成实时值。

回答应该明确:

当前该指标为 T+1,
最新可用数据截至昨日。

4.16 工具调用流程

一个标准问题:

“昨天华东 GMV 比上周同一天低多少?”

建议:

Tool 1:
resolve_metric(
  query="GMV",
  domain="operation",
  asOfTime="yesterday"
)

Tool 2:
query_metric(
  metricCode="PAID_GMV",
  version="v3",
  period="yesterday",
  region="east"
)

Tool 3:
query_metric(
  metricCode="PAID_GMV",
  version="v3",
  period="last_week_same_day",
  region="east"
)

然后模型做比较。

不要先猜 SQL,再回头解释口径。

4.17 独立查询可以并行

两个时期的数据:

昨天
上周同日

如果口径版本相同,可以并行 Tool Call。

但如果跨越口径切换日,必须先分别解析:

asOfTime

对应版本。

4.18 缓存指标知识

指标定义变化频率低,可以缓存:

metricCode + version

TTL:

5~30 分钟

更重要的是:

审批发布新版本时主动失效。

4.19 数据结果缓存

例如昨天 GMV:

已经封账

可缓存较久。

今天实时 GMV:

TTL 很短

缓存策略应跟:

freshness

绑定,而不是所有指标固定 5 分钟。

4.20 缓存 Key 必须包含口径版本

错误:

gmv:east:2026-07-01

正确:

metric:PAID_GMV:v3:east:2026-07-01

否则口径升级后可能命中旧定义下的数据。

4.21 回答模板

一个可信回答至少包含:

1. 数值
2. 变化
3. 指标口径
4. 时间范围
5. 数据时效

例如:

昨日华东区支付GMV为 1.82 亿元,
较上周同日下降 7.4%。

这里“支付GMV”按支付成功订单的实付金额统计,
以 pay_time 作为归属时间,不扣除后续退款。
当前数据为近实时口径。

不要只回答:

下降 7.4%。

4.22 为什么要在回答里显示口径

经营指标本身具有歧义。

用户如果看到:

口径说明

更容易判断答案是否符合自己的业务语境。

而且这也减少:

“AI 编了一个数字”

的信任问题。

4.23 知识库变更流程

指标修改不应该让开发人员直接改数据库。

建议:

提出变更
-> 指标 Owner 审核
-> 数据团队验证公式
-> 生效时间确认
-> 发布新版本
-> 刷新缓存
-> Agent 测试集回归

4.24 版本不可覆盖

不要把:

v3

原地改掉。

应该:

v4

新增。

历史问答才能复现。

4.25 异常结构化

指标不存在:

{
  "code": "METRIC_NOT_FOUND",
  "retryable": false
}

口径歧义:

{
  "code": "METRIC_AMBIGUOUS",
  "candidates": [
    "PAID_GMV",
    "REVENUE_GMV"
  ]
}

权限不足:

{
  "code": "METRIC_FORBIDDEN",
  "retryable": false
}

数据库超时:

{
  "code": "METRIC_QUERY_TIMEOUT",
  "retryable": true
}

模型可以根据错误类型采取不同动作。

4.26 事务边界

指标解释:

只读

指标查询:

只读

可以使用:

@Transactional(readOnly = true)
public MetricResult query(...) {
    ...
}

Agent 不应该拥有:

BEGIN / COMMIT / ROLLBACK

工具。

4.27 如果需要修改指标口径

这是管理操作,不能让普通经营问答 Agent 直接完成。

应使用独立:

metric_admin

工具,并要求:

管理员角色
审批号
版本号
生效时间
审计

4.28 效果评估

在这里插入图片描述

至少评估:

Metric Match Accuracy
Numeric Accuracy
Tool Calls / Request
Unauthorized Access
Freshness Match
Definition Coverage

4.29 构造评测集

例如 200 条:

简单指标
同义词
跨部门同名指标
历史口径
实时/T+1冲突
权限不足
多维度下钻
不存在指标

每条都标注:

正确 metric_code
正确 version
正确 SQL 结果
期望安全行为

4.30 一个示例对比实验

基线:

只给模型指标名称 + 数据库工具

优化后:

结构化指标知识库
+
版本解析
+
受控 MCP Tool

示例结果:

指标基线优化后
指标匹配准确率78%96%
数值正确率84%98%
平均 Tool Call4.12.6
口径说明覆盖率41%97%
越权访问2 次0 次

以上数字是实验模板,正式参赛时应替换为实际测试结果。


5. 结果对比

改造前

流程:

用户问指标
-> 模型猜指标含义
-> 模型直接调用数据库
-> 返回数字

问题:

同名指标易混淆
历史口径无法复现
工具调用多
答案缺少口径
权限控制粗

改造后

流程:

问题
-> 知识库解析 metric_code
-> 解析时间对应版本
-> 校验维度和权限
-> KFS MCP Server 查询真实数据
-> 结果校验
-> 回答中附带口径与时效

这样“解释”与“取数”不再混为一谈。

最重要的变化是:

Agent 不再自己发明指标定义。

6. 风险与复盘

6.1 知识库错误比模型错误更隐蔽

如果指标库本身写错:

所有 Agent 都会稳定地答错。

所以知识库必须有 Owner 和审批流程。

6.2 指标版本管理不能省

经营指标会变化。

没有版本:

历史分析不可复现。

6.3 同名指标要允许歧义,而不是强猜

如果上下文不足:

GMV

同时匹配两个指标,系统应该返回候选,而不是擅自选择。

6.4 权限不只是数据库权限

知识定义本身也可能敏感。

例如:

风控命中率
客户流失风险
成本利润率

可能只允许部分角色查看。

6.5 缓存必须携带 metric version

否则口径升级后最容易出现:

解释是新口径,
数据却来自旧缓存。

6.6 数据时效必须显式

T+1 指标不能包装成实时指标。

Agent 必须把:

数据截止时间

告诉用户。

6.7 模型不能成为授权系统

无论模型是否“理解用户有权限”,真正权限判断都必须在:

知识检索
MCP Server
数据库

执行。

6.8 效果评估必须同时看数字与解释

一个数字正确但口径错误的答案,仍然是错误答案。

所以:

Numeric Accuracy
+
Definition Accuracy

必须一起评估。


结语

经营问答真正难的地方不是把 SQL 交给 AI,而是建立:

指标语言

和:

数据库事实

之间稳定、可审计的映射。

成熟架构应该是:

指标知识库
-> 解析 metric_code 和 version
-> Agent 规划
-> KFS MCP Server 受控工具
-> 数据库查询
-> 口径与数据联合校验
-> 生成经营回答

可以把全文总结为一句话:

经营问答先解释“怎么算”,
再查询“是多少”,
最后才讨论“为什么”。

当指标定义、公式、版本、权限和真实查询结果全部成为可治理的数据资产后,AI Agent 才不会只是一个会“猜指标”的聊天机器人,而能真正成为可信的经营分析入口。


转载自:https://blog.csdn.net/u014727709/article/details/165357427
欢迎 👍点赞✍评论⭐收藏,欢迎指正

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐