业务智能体实战笔记:分层消除不确定性(五·终)|完全脱离 LLM 的确定性判定 + 评测闭环

系列导航:上一篇:业务智能体实战笔记(四):兜底修复——LLM 错了怎么救
阅读提示:本文为智能体准确率优化系列第五篇(收官篇),本篇是四层方法论的第四层——完全脱离 LLM 的确定性判定,同时复盘全系列核心教训:评测闭环搭建时机过晚。
四层方法论总览:1.前置拦截 → 2.收窄LLM决策空间 → 3.LLM决策后兜底修复 → 4.纯工程确定性判定(本文)


@


概述

前文三层方案仍会让LLM参与判断流程,存在概率性出错风险;第四层核心思路:把结构化运算、业务口径校验全部交由工程代码执行,LLM仅负责识别用户意图、编排工具调用参数,不参与任何数值、业务规则判定。
整套方案由三部分构成,存在明确依赖顺序:

  1. data_filter:通用结构化数据处理,解决算错、漏字段、图表错乱;
  2. 业务硬约束:兜底LLM无法识别的专属业务口径;
  3. 评测闭环:提供量化跑分能力,让所有优化动作可验证、可迭代。

全文最大复盘结论:如果重新落地业务智能体,第一件事搭建评测闭环,再做业务逻辑优化,能大幅缩短迭代成本。

一、什么算「完全脱离 LLM 」

本层与前三层核心差异:本层处理不依赖 LLM。LLM 仍负责意图识别与工具编排,但不再接触数据、不做数值运算、不判业务规则。四层路径核心区别汇总如下:

分层阶段 LLM参与形式 核心定位
前置拦截(第二篇) LLM不做决策,仅消费拦截结果 提前过滤无效/高危请求
收窄决策空间(第三篇) LLM主导决策,可选范围被压缩 降低模型选错概率
兜底修复(第四篇) LLM先输出结果,代码事后校验纠错 事后修复模型错误
确定性判定(本篇) LLM完全不进入判断链路 纯代码执行计算、口径校验

统一分工原则:LLM定「做什么」,工程侧定「怎么算」

举例:用户提问“统计6月工单完成量并生成柱状图”
LLM仅识别需求,输出data_filter工具调用参数;过滤、分组、计数、绘图全部由Java代码执行,模型全程不接触原始数据、不做任何数学运算。

二、data_filter:结构化数据从 LLM 侧完全搬到工程侧

背景痛点

LLM在文本流中处理结构化数据存在天然缺陷:数据量大易漏字段、分组统计串维度、排序逻辑混乱,仅靠提示词无法根治。
解决方案:新增纯Java工具data_filter,将所有结构化数据运算迁移至工程层;LLM仅负责发起工具调用、传递操作参数,过滤、聚合、排序、绘图等确定性计算全部由代码承载。

2.1 五大原子操作(ToolCallback)

对外仅暴露5类基础算子,支持自由链式组合,LLM无需在上下文内完整推演全链路,仅需分步下发指令:

操作 输入参数 输出 业务用途
filter 字段 + 条件表达式 过滤后数据子集 缩小数据集范围
group_count 分组维度字段 {分组值: 统计数量} 按维度聚合计数
sort 排序字段 + 升降序标识 完整有序数据集 数据排序
count 无(基于当前上下文数据集) 数据总行数 统计总量
to_chart 图表类型 + 字段映射关系 标准化图表JSON 生成可视化图表

组合调用示例

用户需求:筛选2026年6月工单,按工单状态分组统计,输出柱状图
执行链路:filter(创建时间=2026-06) → group_count(status) → to_chart(柱状图)

to_chart彻底解决前文图表JSON字段错位问题:固定映射规则由代码维护,不再依赖LLM拼接图表结构。

2.2 三条核心隔离约束

三条约束共同将数据、计算逻辑与LLM彻底隔离,保障结果稳定:

  1. 原始数据不经过LLM,统一从SessionContext读取
    SessionContext为会话级隔离存储,单用户单次查询的数据独立存放,多用户并发不会串数据。
    data_filter入参仅携带字段名、条件,不含原始业务数据:
    • 规避海量业务数据挤占上下文token;
    • 杜绝LLM转述数据时丢字段、篡改数值、丢失小数精度。
  2. 仅处理存量数据,不负责底层数据查询
    数据查询由MCP/Skill业务工具完成,查询结果写入SessionContext后,data_filter才可触发。
    实现关注点分离:业务工具负责“取数”,data_filter负责“加工数”,职责互不越界。
  3. 中间操作回写上下文,终态操作不落地
    • 中间操作filter/sort:处理完成后替换SessionContext当前数据集,支持连续链式调用,无需LLM记忆上一步结果;
    • 终态操作count/group_count/to_chart:输出结论供LLM组装回答,不更新上下文,不可作为后续计算原料。

2.3 LLM与工程侧完整协作流程

  1. 用户输入业务查询;
  2. PreprocessEngine 预处理:实体识别 + 消歧(有歧义则短路追问);
  3. LLM(ReactAgent ReAct 循环)识别意图,判断需要获取数据;
  4. LLM 发出 tool_call,调用 mcp_* 或 skill_* 工具获取原始业务数据;
  5. 工具执行完成后,结果经 ToolResultNormalizer 归一化为 {records, total, summary} 并写入 SessionContext(以 threadId 为 key);
  6. (可选)LLM 再次发出 tool_call,调用 data_filter 对 SessionContext 中的数据进行 filter → group_count → sort → to_chart 等二次加工;
  7. data_filter 的中间结果回写 SessionContext,支持链式调用;
  8. LLM 综合所有工具返回结果,生成最终自然语言回复。

2.4 收益说明

对照实验条件:200条结构化数值类测试用例,仅替换原生LLM计算逻辑、接入data_filter,模型、提示词、采样参数完全不变。
准确率提升Delta:+10~13pt
收益来源:一次性解决数值计算错误、字段遗漏、图表结构错乱三类高频问题,把结构化数据处理从概率系统转为100%稳定的确定性系统。

局限性data_filter 仅处理已加载至 SessionContext 内存的数据集,不连接数据库、不做 SQL 优化。超大数据集(万行级)需由上游 MCP / Skill 先做分页预取再写入上下文,data_filter 本身不解决数据量问题。

三、特定场景硬约束

data_filter解决通用数值运算问题,但仍存在大量业务专属口径场景无法通用化处理,必须在代码层硬编码约束兜底。本节围绕三点展开:硬编码必要性、低成本管理方案、暂缓落地规则引擎的理由。

3.1 必须硬编码的三类场景

核心矛盾:业务真值口径属于企业内部定义,无法通过通用语言语义让LLM稳定识别,这类场景存在三大共性:

  1. 业务口径与通用语义割裂
    例如工单场景“完成”,通用语义仅代表结束,但业务明确限定status=0;LLM无法自主推断业务状态定义,无天然语义映射通路。
  2. 错误无异常告警,隐蔽性极强
    工具调用流程正常、返回格式合规,仅业务数字错误;普通响应校验只能识别格式崩溃,无法判断业务口径对错,模型无法自主纠错。
  3. 容错代价严重不对称
    单次正确回答无正向感知,一次口径错误会直接丧失用户对产品数据可信度;软约束“大概率正确”无法抵御此类高风险场景。

3.2 硬编码的价值取舍

硬约束本质:将业务口径判断从概率LLM体系迁移至确定性代码。
优势:if-else规则100%稳定触发、无语义漂移、可单条单元测试、支持回归验证;
短板:新增业务规则需要服务发版,灵活性弱。
企业BI智能体场景下,“保证核心指标绝对准确”优先级高于快速迭代,该取舍具备工程合理性。

3.3 硬约束轻量化管理:记账法

不急于抽象、不直接上规则引擎,采用低成本文档记账管控硬约束持续膨胀,避免无边界补丁堆积。
新增任意一条硬约束,同步记录5项信息,Markdown表格即可落地:

硬约束 ID 业务口径 为什么 LLM 判断不了 理想解法 引入日期
HC-001 工单场景"完成"指 status=0 语料里"完成"的语义与业务状态无桥可通 BI 层暴露口径元数据,替代硬编码 2026-06-15
HC-002 "本月"以创建时间+完成时间双口径回答 LLM 无法可靠选择时间维度,业务上两者都可能是用户意图 需求侧规定统一表述,或在 BI 层拆成两个显式指标 2026-06-20

配套落地规范:

  1. 维护人:后端开发;
  2. 复盘周期:每2周统一梳理约束清单;
  3. 抽象触发阈值:同类约束累计≥8条,启动公共抽象层设计。

字段作用说明:

  • 硬约束ID:唯一编号,用于复盘、需求追溯;
  • 业务口径:清晰描述本条规则校验范围;
  • 为什么LLM判断不了:留存原始痛点,避免后续盲目回退软约束;
  • 理想解法:沉淀长期优化方向,积累多条后提炼公共抽象;
  • 引入日期:观察约束增长密度,密集新增代表需要顶层抽象。

3.4 暂缓落地规则引擎的原因

当硬约束积累到一定数量,极易产生“配置化规则引擎”的想法,但现阶段不推荐优先落地:

  1. 规则引擎仅将代码补丁迁移至YAML配置,未解决“新增业务口径就要新增一条规则”的底层问题,系统复杂度无下降;
  2. 业务人员缺乏数据建模能力,自行配置极易产生口径冲突;
  3. 配置规则无配套单元测试,变更后无法自动回归校验;
  4. 多层规则解析增加查询链路开销,拖慢数值查询响应速度。
    最优路径:先记账沉淀场景规律,待共性模式浮现后再做抽象层设计,而非提前搭建配置系统。

3.5 收益说明

对照实验条件:基于已上线data_filter能力,仅新增状态拦截、双时间补跑两类硬约束,其余逻辑不变。
准确率提升Delta:+2~4pt
分数提升幅度有限,但核心价值是拦截“一次错误就丢失用户信任”的高危业务场景,量化分数无法体现该隐性价值。

四、评测闭环:全系列最关键的经验教训

整套优化体系唯一后悔的决策:评测闭环搭得太晚。前期靠人工观察和感觉调参,浪费了大量时间。如果重新做一遍,我会先把评测搭起来,再动其他任何东西。

4.1 真值集共建机制(开发+测试协同)

真值集是评测体系核心基准,单一方独立搭建都会出现偏差,固定协作流程:

  1. 测试人员:输出全覆盖测试用例,定义每条用例标准期望结果,覆盖边缘、模糊、多维度组合查询;
  2. 开发人员:校验期望结果的工程可行性、业务口径正确性,与测试对齐标准;
  3. 双方达成共识后,结构化存储用例,支持自动化脚本批量读取跑分。
    协作价值互补:测试保障场景覆盖度,开发规避无法稳定复现的无效用例。
    真值集构建还需保证数据分布均衡:70% 来自线上真实用户 query,30% 为人工构造的边界与长尾 case,避免纯合成数据导致的离线高分、线上衰减。

4.2 多维度跑分判定口径

先统一准确率口径:准确率 = 判定通过的用例数 ÷ 评测用例总数 × 100%。单条用例「通过」指实际输出与期望值的偏差落在下述容差范围内。
查询分为数值型、分类型、聚合百分比三类,不能使用同一套判定标准,统一设计容差规则适配业务天然误差(时间戳精度、聚合窗口、四舍五入)。

  1. 单数字判定公式
    ∣expect−actual∣≤max(0.5, expect×0.5%)
    逻辑说明:大数采用0.5%相对误差,小数采用0.5绝对差值兜底,兼顾两类场景合理性。
    • 示例1:预期值=10000,允许误差50,业务口径微调、四舍五入全部兼容;
    • 示例2:预期值=3,允许误差0.5,不会因差值1误判小数量场景失败。
  2. 百分比合计校验:整体合计允许2%误差区间。

容差设计初衷:拒绝严格全等匹配,避免把业务无差异的正确结果判定为失败;容差区间经过业务侧确认,可吸收工程侧无关扰动。

4.3 选用外挂Python评测脚本的原因

内部Java框架仅支持LLM软评分,改造数值精确打分改造成本高、周期长;外挂Python是低成本落地方案,具备三大优势:

  1. 判定完全确定性:同一用例多次跑分结果一致,无随机波动;
  2. 零推理成本:无需调用裁判LLM,批量跑分无额外token开销;
  3. 问题可审计:直接输出「期望数值 vs 实际数值」,快速定位口径错误。

极简脚本目录参考(可直接复制落地):

eval/
├── truth_dataset.json  # 真值测试用例库
├── run_eval.py         # 批量跑分主程序
├── judge_logic.py      # 数值容差判定函数
└── report_output.txt  # 跑分结果、失败用例日志

judge_logic.py 核心判定函数:

def is_match(expect: float, actual: float, tolerance_pct: float = 0.005) -> bool:
    """大数比例、小数绝对,一个阈值覆盖两端"""
    threshold = max(0.5, abs(expect) * tolerance_pct)
    return abs(expect - actual) <= threshold

4.4 放弃LLM裁判,选用真值集的核心理由

业界主流方案分为「LLM裁判打分」「真值基准打分」,本文选择后者,LLM裁判存在三大硬缺陷:

  1. 结果不稳定:同一用例两次跑分得分不一致,评估误差叠加,无法区分是优化失效还是裁判模型波动;
  2. 运行成本高:每条用例额外发起一次LLM调用,大规模评测集成本成倍上涨;
  3. 不适合数值场景:数值对错是二元客观事实,LLM主观评判会引入模糊误差。

核心结论:能使用确定性基准判定的场景,绝不引入概率化LLM作为评判标准;数据库查询得到的真值具备唯一性,是最优评测基准。

4.5 真值集漂移自动化治理

业务迭代、底层数据表重构会导致历史期望结果失效,即真值漂移,完整处理链路:

  1. 漂移自动检测:每次跑分前置调度SQL,拉取当前真实指标,与历史期望数值比对,超出容差自动标记漂移用例;
  2. 人工修正校验:标记漂移条目后,重新走「开发+测试」协同流程,更新标准结果;
  3. 版本回滚兜底:真值集做多版本存档,修正出错时可一键回退至可信基线版本。

长期优化:将漂移检测作为评测流水线前置钩子,全流程自动化,不依赖人工记忆维护。

4.6 两类评测使用场景拆分

  1. 全量回归评测:完整跑一遍全部真值集,用于版本发布前校验,防止优化引发旧场景准确率回退;
  2. 单例调试评测:输入单条用户需求快速跑分,用于日常开发调优、定位单条错误案例。

4.7 评测闭环三大间接收益

评测脚本本身不直接提升准确率,但为所有优化动作提供量化基础:

  1. 优化效果可量化:各层优化收益不再依靠主观感受,统一跑分对比,精准归因每层贡献;
  2. 迭代周期大幅压缩:单次全量跑分仅需数分钟,替代人工逐条手动验证的数小时;
  3. 防止准确率退化:快速识别“优化A场景、破坏B场景”的隐性负向改动。

五、下一步演进方向

方向一:BI指标能力封装为标准化MCP工具

本思路延续「结构化计算交给确定性工程,LLM仅负责语义意图」核心逻辑,是当前方案的终极延伸,完整落地五步走:

  1. 底层数据库治理(前置基建,不属于AI项目):统一表名、字段类型、注释,清理废弃冗余数据表;
  2. BI层数据预处理:梳理主外键关联,过滤无数据、极少访问、仅审计用的无效表,减少AI认知负担;
  3. 绑定业务元数据:配置术语映射(如“完成率”对应指标字段)、时间口径注释、业务同义词;
  4. 高频查询固化参数化数据集:高频需求不实时生成SQL,复用经过验证的查询链路,降低出错概率;
  5. 封装MCP Server:将预处理后的标准化指标能力通过MCP协议对外提供,供智能体调用。

落地卡点与应对:

  • 卡点1:底层脏数据多 → 分批治理高频查询表,无需一次性全量整改;
  • 卡点2:业务口径频繁变动 → 搭建独立指标元数据表,替代代码硬编码。

最终效果:LLM不再直面海量数据表与SQL生成任务,仅操作经过口径标准化的工具,从根源减少口径理解错误。

方向二:硬约束记账沉淀 → 公共抽象层

遵循“先记账、找规律、再抽象”原则,不提前空想通用方案:

  1. 持续维护硬约束记账表,同类约束累计 ≥8 条后启动抽象;
  2. 从「为什么LLM判断不了」「理想解法」两列提取共性痛点;
  3. 针对统一痛点搭建公共抽象层。

示例:多条约束均为”时间维度口径识别混乱”,统一抽象时间维度元数据层,彻底消除同类硬编码补丁。

实施优先级:短期优先推硬约束记账(零成本、即时收益),中期搭评测流水线自动化(跑分前置钩子 + 漂移检测),长期推进 BI-MCP 封装(依赖数据治理基建,周期最长)。

六、系列整体收尾

整套四层工程优化方案,将业务智能体整体准确率从65%提升至85%以上,分层收益拆分:

  1. 前三篇(前置拦截+收窄决策空间+兜底修复):合计提升8~10pt;
  2. data_filter结构化算子:提升10~13pt;
  3. 业务硬约束兜底:提升2~4pt;
  4. 评测闭环:无直接分数提升,但让所有优化可量化、加速迭代,避免大量无效调参。

整体提升不靠模型升级、提示词魔法,而是分层逐层压缩系统不确定性,多层叠加实现稳定可靠的数据问答能力。

后续性能上限:完成BI-MCP封装、硬约束公共抽象层后,准确率仍有上行空间;再往上突破,则依赖大模型原生语义、逻辑能力进化。

复盘核心教训再强调一遍:评测闭环必须作为项目初期基建,延后搭建会浪费大量调优时间。

适用边界:本四层方案针对企业结构化数据查询类智能体(工单统计、BI 问数、报表生成)。通用闲聊、创意生成、非结构化文档问答等场景不适用——那些场景的准确性由模型能力本身决定,而非工程侧确定性判定。

互动交流

  1. 你的业务智能体采用LLM裁判还是真值集自动化评测?分别踩过哪些坑?
  2. 结构化数值类错误,团队选择提示词优化还是工程算子兜底?
  3. 业务口径频繁变更场景,你们是硬编码临时补丁,还是提前搭建指标元数据抽象层?

5 篇按四层方法论展开的实战笔记,从主线到全景、从前置拦截到确定性判定。感谢一路读到这里的你。

posted @ 2026-07-22 09:55  荣--  阅读(60)  评论(0)    收藏  举报