业务智能体实战笔记:分层消除不确定性(五·终)|完全脱离 LLM 的确定性判定 + 评测闭环
系列导航:上一篇:业务智能体实战笔记(四):兜底修复——LLM 错了怎么救
阅读提示:本文为智能体准确率优化系列第五篇(收官篇),本篇是四层方法论的第四层——完全脱离 LLM 的确定性判定,同时复盘全系列核心教训:评测闭环搭建时机过晚。
四层方法论总览:1.前置拦截 → 2.收窄LLM决策空间 → 3.LLM决策后兜底修复 → 4.纯工程确定性判定(本文)
@
概述
前文三层方案仍会让LLM参与判断流程,存在概率性出错风险;第四层核心思路:把结构化运算、业务口径校验全部交由工程代码执行,LLM仅负责识别用户意图、编排工具调用参数,不参与任何数值、业务规则判定。
整套方案由三部分构成,存在明确依赖顺序:
data_filter:通用结构化数据处理,解决算错、漏字段、图表错乱;- 业务硬约束:兜底LLM无法识别的专属业务口径;
- 评测闭环:提供量化跑分能力,让所有优化动作可验证、可迭代。
全文最大复盘结论:如果重新落地业务智能体,第一件事搭建评测闭环,再做业务逻辑优化,能大幅缩短迭代成本。
一、什么算「完全脱离 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彻底隔离,保障结果稳定:
- 原始数据不经过LLM,统一从SessionContext读取
SessionContext为会话级隔离存储,单用户单次查询的数据独立存放,多用户并发不会串数据。
data_filter入参仅携带字段名、条件,不含原始业务数据:- 规避海量业务数据挤占上下文token;
- 杜绝LLM转述数据时丢字段、篡改数值、丢失小数精度。
- 仅处理存量数据,不负责底层数据查询
数据查询由MCP/Skill业务工具完成,查询结果写入SessionContext后,data_filter才可触发。
实现关注点分离:业务工具负责“取数”,data_filter负责“加工数”,职责互不越界。 - 中间操作回写上下文,终态操作不落地
- 中间操作
filter/sort:处理完成后替换SessionContext当前数据集,支持连续链式调用,无需LLM记忆上一步结果; - 终态操作
count/group_count/to_chart:输出结论供LLM组装回答,不更新上下文,不可作为后续计算原料。
- 中间操作
2.3 LLM与工程侧完整协作流程
- 用户输入业务查询;
- PreprocessEngine 预处理:实体识别 + 消歧(有歧义则短路追问);
- LLM(ReactAgent ReAct 循环)识别意图,判断需要获取数据;
- LLM 发出 tool_call,调用 mcp_* 或 skill_* 工具获取原始业务数据;
- 工具执行完成后,结果经 ToolResultNormalizer 归一化为
{records, total, summary}并写入 SessionContext(以 threadId 为 key); - (可选)LLM 再次发出 tool_call,调用 data_filter 对 SessionContext 中的数据进行 filter → group_count → sort → to_chart 等二次加工;
- data_filter 的中间结果回写 SessionContext,支持链式调用;
- LLM 综合所有工具返回结果,生成最终自然语言回复。
2.4 收益说明
对照实验条件:200条结构化数值类测试用例,仅替换原生LLM计算逻辑、接入data_filter,模型、提示词、采样参数完全不变。
准确率提升Delta:+10~13pt
收益来源:一次性解决数值计算错误、字段遗漏、图表结构错乱三类高频问题,把结构化数据处理从概率系统转为100%稳定的确定性系统。
局限性:
data_filter仅处理已加载至 SessionContext 内存的数据集,不连接数据库、不做 SQL 优化。超大数据集(万行级)需由上游 MCP / Skill 先做分页预取再写入上下文,data_filter本身不解决数据量问题。
三、特定场景硬约束
data_filter解决通用数值运算问题,但仍存在大量业务专属口径场景无法通用化处理,必须在代码层硬编码约束兜底。本节围绕三点展开:硬编码必要性、低成本管理方案、暂缓落地规则引擎的理由。
3.1 必须硬编码的三类场景
核心矛盾:业务真值口径属于企业内部定义,无法通过通用语言语义让LLM稳定识别,这类场景存在三大共性:
- 业务口径与通用语义割裂
例如工单场景“完成”,通用语义仅代表结束,但业务明确限定status=0;LLM无法自主推断业务状态定义,无天然语义映射通路。 - 错误无异常告警,隐蔽性极强
工具调用流程正常、返回格式合规,仅业务数字错误;普通响应校验只能识别格式崩溃,无法判断业务口径对错,模型无法自主纠错。 - 容错代价严重不对称
单次正确回答无正向感知,一次口径错误会直接丧失用户对产品数据可信度;软约束“大概率正确”无法抵御此类高风险场景。
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 |
配套落地规范:
- 维护人:后端开发;
- 复盘周期:每2周统一梳理约束清单;
- 抽象触发阈值:同类约束累计≥8条,启动公共抽象层设计。
字段作用说明:
- 硬约束ID:唯一编号,用于复盘、需求追溯;
- 业务口径:清晰描述本条规则校验范围;
- 为什么LLM判断不了:留存原始痛点,避免后续盲目回退软约束;
- 理想解法:沉淀长期优化方向,积累多条后提炼公共抽象;
- 引入日期:观察约束增长密度,密集新增代表需要顶层抽象。
3.4 暂缓落地规则引擎的原因
当硬约束积累到一定数量,极易产生“配置化规则引擎”的想法,但现阶段不推荐优先落地:
- 规则引擎仅将代码补丁迁移至YAML配置,未解决“新增业务口径就要新增一条规则”的底层问题,系统复杂度无下降;
- 业务人员缺乏数据建模能力,自行配置极易产生口径冲突;
- 配置规则无配套单元测试,变更后无法自动回归校验;
- 多层规则解析增加查询链路开销,拖慢数值查询响应速度。
最优路径:先记账沉淀场景规律,待共性模式浮现后再做抽象层设计,而非提前搭建配置系统。
3.5 收益说明
对照实验条件:基于已上线data_filter能力,仅新增状态拦截、双时间补跑两类硬约束,其余逻辑不变。
准确率提升Delta:+2~4pt
分数提升幅度有限,但核心价值是拦截“一次错误就丢失用户信任”的高危业务场景,量化分数无法体现该隐性价值。
四、评测闭环:全系列最关键的经验教训
整套优化体系唯一后悔的决策:评测闭环搭得太晚。前期靠人工观察和感觉调参,浪费了大量时间。如果重新做一遍,我会先把评测搭起来,再动其他任何东西。
4.1 真值集共建机制(开发+测试协同)
真值集是评测体系核心基准,单一方独立搭建都会出现偏差,固定协作流程:
- 测试人员:输出全覆盖测试用例,定义每条用例标准期望结果,覆盖边缘、模糊、多维度组合查询;
- 开发人员:校验期望结果的工程可行性、业务口径正确性,与测试对齐标准;
- 双方达成共识后,结构化存储用例,支持自动化脚本批量读取跑分。
协作价值互补:测试保障场景覆盖度,开发规避无法稳定复现的无效用例。
真值集构建还需保证数据分布均衡:70% 来自线上真实用户 query,30% 为人工构造的边界与长尾 case,避免纯合成数据导致的离线高分、线上衰减。
4.2 多维度跑分判定口径
先统一准确率口径:准确率 = 判定通过的用例数 ÷ 评测用例总数 × 100%。单条用例「通过」指实际输出与期望值的偏差落在下述容差范围内。
查询分为数值型、分类型、聚合百分比三类,不能使用同一套判定标准,统一设计容差规则适配业务天然误差(时间戳精度、聚合窗口、四舍五入)。
- 单数字判定公式
∣expect−actual∣≤max(0.5, expect×0.5%)
逻辑说明:大数采用0.5%相对误差,小数采用0.5绝对差值兜底,兼顾两类场景合理性。- 示例1:预期值=10000,允许误差50,业务口径微调、四舍五入全部兼容;
- 示例2:预期值=3,允许误差0.5,不会因差值1误判小数量场景失败。
- 百分比合计校验:整体合计允许2%误差区间。
容差设计初衷:拒绝严格全等匹配,避免把业务无差异的正确结果判定为失败;容差区间经过业务侧确认,可吸收工程侧无关扰动。
4.3 选用外挂Python评测脚本的原因
内部Java框架仅支持LLM软评分,改造数值精确打分改造成本高、周期长;外挂Python是低成本落地方案,具备三大优势:
- 判定完全确定性:同一用例多次跑分结果一致,无随机波动;
- 零推理成本:无需调用裁判LLM,批量跑分无额外token开销;
- 问题可审计:直接输出「期望数值 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裁判存在三大硬缺陷:
- 结果不稳定:同一用例两次跑分得分不一致,评估误差叠加,无法区分是优化失效还是裁判模型波动;
- 运行成本高:每条用例额外发起一次LLM调用,大规模评测集成本成倍上涨;
- 不适合数值场景:数值对错是二元客观事实,LLM主观评判会引入模糊误差。
核心结论:能使用确定性基准判定的场景,绝不引入概率化LLM作为评判标准;数据库查询得到的真值具备唯一性,是最优评测基准。
4.5 真值集漂移自动化治理
业务迭代、底层数据表重构会导致历史期望结果失效,即真值漂移,完整处理链路:
- 漂移自动检测:每次跑分前置调度SQL,拉取当前真实指标,与历史期望数值比对,超出容差自动标记漂移用例;
- 人工修正校验:标记漂移条目后,重新走「开发+测试」协同流程,更新标准结果;
- 版本回滚兜底:真值集做多版本存档,修正出错时可一键回退至可信基线版本。
长期优化:将漂移检测作为评测流水线前置钩子,全流程自动化,不依赖人工记忆维护。
4.6 两类评测使用场景拆分
- 全量回归评测:完整跑一遍全部真值集,用于版本发布前校验,防止优化引发旧场景准确率回退;
- 单例调试评测:输入单条用户需求快速跑分,用于日常开发调优、定位单条错误案例。
4.7 评测闭环三大间接收益
评测脚本本身不直接提升准确率,但为所有优化动作提供量化基础:
- 优化效果可量化:各层优化收益不再依靠主观感受,统一跑分对比,精准归因每层贡献;
- 迭代周期大幅压缩:单次全量跑分仅需数分钟,替代人工逐条手动验证的数小时;
- 防止准确率退化:快速识别“优化A场景、破坏B场景”的隐性负向改动。
五、下一步演进方向
方向一:BI指标能力封装为标准化MCP工具
本思路延续「结构化计算交给确定性工程,LLM仅负责语义意图」核心逻辑,是当前方案的终极延伸,完整落地五步走:
- 底层数据库治理(前置基建,不属于AI项目):统一表名、字段类型、注释,清理废弃冗余数据表;
- BI层数据预处理:梳理主外键关联,过滤无数据、极少访问、仅审计用的无效表,减少AI认知负担;
- 绑定业务元数据:配置术语映射(如“完成率”对应指标字段)、时间口径注释、业务同义词;
- 高频查询固化参数化数据集:高频需求不实时生成SQL,复用经过验证的查询链路,降低出错概率;
- 封装MCP Server:将预处理后的标准化指标能力通过MCP协议对外提供,供智能体调用。
落地卡点与应对:
- 卡点1:底层脏数据多 → 分批治理高频查询表,无需一次性全量整改;
- 卡点2:业务口径频繁变动 → 搭建独立指标元数据表,替代代码硬编码。
最终效果:LLM不再直面海量数据表与SQL生成任务,仅操作经过口径标准化的工具,从根源减少口径理解错误。
方向二:硬约束记账沉淀 → 公共抽象层
遵循“先记账、找规律、再抽象”原则,不提前空想通用方案:
- 持续维护硬约束记账表,同类约束累计 ≥8 条后启动抽象;
- 从「为什么LLM判断不了」「理想解法」两列提取共性痛点;
- 针对统一痛点搭建公共抽象层。
示例:多条约束均为”时间维度口径识别混乱”,统一抽象时间维度元数据层,彻底消除同类硬编码补丁。
实施优先级:短期优先推硬约束记账(零成本、即时收益),中期搭评测流水线自动化(跑分前置钩子 + 漂移检测),长期推进 BI-MCP 封装(依赖数据治理基建,周期最长)。
六、系列整体收尾
整套四层工程优化方案,将业务智能体整体准确率从65%提升至85%以上,分层收益拆分:
- 前三篇(前置拦截+收窄决策空间+兜底修复):合计提升8~10pt;
data_filter结构化算子:提升10~13pt;- 业务硬约束兜底:提升2~4pt;
- 评测闭环:无直接分数提升,但让所有优化可量化、加速迭代,避免大量无效调参。
整体提升不靠模型升级、提示词魔法,而是分层逐层压缩系统不确定性,多层叠加实现稳定可靠的数据问答能力。
后续性能上限:完成BI-MCP封装、硬约束公共抽象层后,准确率仍有上行空间;再往上突破,则依赖大模型原生语义、逻辑能力进化。
复盘核心教训再强调一遍:评测闭环必须作为项目初期基建,延后搭建会浪费大量调优时间。
适用边界:本四层方案针对企业结构化数据查询类智能体(工单统计、BI 问数、报表生成)。通用闲聊、创意生成、非结构化文档问答等场景不适用——那些场景的准确性由模型能力本身决定,而非工程侧确定性判定。
互动交流
- 你的业务智能体采用LLM裁判还是真值集自动化评测?分别踩过哪些坑?
- 结构化数值类错误,团队选择提示词优化还是工程算子兜底?
- 业务口径频繁变更场景,你们是硬编码临时补丁,还是提前搭建指标元数据抽象层?
5 篇按四层方法论展开的实战笔记,从主线到全景、从前置拦截到确定性判定。感谢一路读到这里的你。
业务智能体准确率从 65% 提升至 85%+,靠的不是模型换代,而是逐层把不确定性从 LLM 手里移到工程侧。
本文是四层方法论的第四层"确定性判定"——data_filter 把结构化运算完全搬出 LLM、业务硬约束兜底口径错误、评测闭环让每一次改
动都有了量化依据。全系列核心教训只有一句:评测闭环应该第一步就搭起来,而不是调完参数再补。
浙公网安备 33010602011771号