# AI 读规则，代码算价格：不能出错的业务系统里，模型和代码的分工线画在哪

> 发布日期：2026-09-01　作者：模界数智
> 原文链接：https://mojiedata.com/insights/ai-proposes-code-decides

---

有一类业务系统，AI 用起来特别难——不是因为任务复杂，而是因为**结果必须能被追问**。

报价就是其中之一。一张印刷订单上写着书名、数量、开本、印张、装订方式，还有一段自由填写的备注：「封面覆哑膜加烫金」「勒口 80mm」「配光盘一张」。这些要素组合起来，对应到报价表里可能是十几条规则的叠加。算错一个数字，是真金白银赔。

本文记录一个印刷订单计价系统里，模型和确定性代码的分工线是怎么画的。**客户身份已匿名；系统目前仍在开发中，报价精度尚未收敛，本文写的是设计与已验证的部分。**

## 关键结论

1. **业务系统要的不是一个答案，是一个可以被追问的答案。**
2. 模型负责**有歧义**的部分，确定性代码负责**有唯一正确答案**的部分。
3. **精确匹配，匹配不上就不计价并报警，不猜**——模糊匹配在错误代价高的场景是危险的便利。
4. **不要指望提示词把模型管住，要用代码检查模型的产出。**
5. 历史数据是**验证集**，不是规则来源——否则系统会学会复现历史上的错误。

## 一、两条走不通的路

**纯规则路线**：把报价表翻译成代码。问题是每接一家企业就要重写一遍规则，一百家就是一百套代码，且规则一变就要改代码上线。而报价表是业务人员维护的，改动频率远高于发版频率。

**纯模型路线**：把订单和报价表一起丢给大模型，让它直接算价格。这条路在 Demo 阶段效果惊人，在生产阶段过不了第一次对账——客户问「这个 3860 元是怎么来的」，系统答不出「用了哪条规则、哪个数量档位、哪几项工艺加价」。

第二条路失败的根因不是模型不够准，而是**它产出的是一个数字，而业务需要的是一条可回放的计算路径**。

## 二、那条分工线

系统的核心设计只有一句话：

> **模型应该像一个有经验的报价员那样工作，但系统不能是黑盒。**

展开成两组约束：

**模型可以做的：**
- 阅读并理解订单、备注、报价表规则
- 对缺失字段做合理推测
- 对规则无法直接匹配的情况提出候选路径
- 对最终结果做专业复核

**系统必须保证的：**
- 模型的结论要**结构化落地**，不能只是一段话
- 模型输出必须附带**理由、证据、置信度**
- **最终价格不能只来自模型一句话**
- 人工可以查看、确认、修改、覆盖

这两组约束共同决定了架构：模型的产出永远是「候选」，进入一个确定性的执行层之后才变成「结果」。

## 三、先统一结构，再谈识别率

一个容易走偏的地方：项目初期最诱人的目标是「提高 PDF 订单的识别准确率」。

但这个系统明确规定：**当前阶段的重点不是自动识别订单，而是先把后台结构化与计价流程跑通。** 而且加了一条硬约束——

> **不允许按单一企业建模。** 统一拆分结构必须同时覆盖两家样本企业才算成立。

这条约束的价值在第三家、第三十家企业接入时才显现。企业之间可以有不同的阶梯规则、乘数因子、部件计价方式、工艺加价方式、最低收费规则、另议规则，**但不应有不同的订单基础结构定义**。

所有订单先落到同一套结构——整书主表加部件表加工艺表。一本书可以拆成正文、封面、插页、环衬、扉页、护封、腰封、小册子、附件、包装等多个部件，每个部件挂各自的工艺。识别入口（PDF、粘贴、手工）只是这个统一结构的**数据来源之一**。

**先把结构做对，识别率是后面的事；结构错了，识别率再高也没用。**

## 四、术语表是唯一桥梁，且不做模糊匹配

订单上写「蒙肯纸」，报价表里写「轻型纸」，ERP 里又是另一个编码。同一种纸在三个系统里三个名字——这是这类项目最普遍也最隐蔽的失败点。

做法是三方通过同一张平台术语表对齐：

```
                 平台术语表（标准名 + 别名 + ERP 编码）
                /            |             \
        订单侧            ERP 侧            规则侧
      PDF → 解析        标准编码同步      报价表 → AI 提取
           ↓                 ↓                  ↓
        归一化  ═════ 精确匹配 ═════  归一化
```

关键规则：**精确匹配，匹配不上就不计价并产出警告，不猜。**

这一条经常被质疑——「加个模糊匹配不是更好用吗？」不是。「蒙肯纸」和「轻型纸」也许是一回事，但「128g 铜版」和「128g 哑粉」不是。**在错误代价高的场景，模糊匹配是危险的便利。**

还有一个细节值得记：**订单侧和规则侧的归一策略是不对称的。**

- 订单侧未命中 → 记入未知术语表，值不变继续；
- 规则侧未命中 → **保留原值**。

因为**规则的字面量是法律级的，不能擅自改**。订单是描述，规则是依据，两者的容错度不一样。

## 五、未知术语的人机闭环

匹配不上的术语不是错误，是待办：

```
原始值「蒙肯纸」
  → 归一化：未匹配
  → 模型建议：轻型纸（附理由与置信度 0.85）
  → 写入待确认队列
  → 界面显示「蒙肯纸 → 轻型纸？　[确认] [修改] [跳过]」
  → 人工确认后写入术语表，下次自动归一
```

**模型提效率，人管正确性，词典随使用增长。** 用得越久，需要人工确认的越少。

这个闭环的关键不在于模型建议得多准，而在于**人的每一次裁决都被沉淀下来了**。一个不沉淀的人机协同，本质上是把成本从模型转移给了人，而不是降低了总成本。

## 六、不要指望提示词把模型管住

报价表本身是自然语言：「内文 80g 双胶，5000 册以内每印张 X 元，超出部分 Y 元」。把它变成可执行规则，这一步只有模型做得了。

系统用七步提取把一份报价文档拆成结构化规则，每步都把已提取的内容和标准术语提示进去。但——

> **模型即便提示再充分，仍然会犯系统性错误。**

于是有了一层确定性校验器兜底。它检查 12 类问题，其中 10 类可以自动修复：

| 检查项 | 触发条件 | 处理 |
|---|---|---|
| 缺纸种限制 | 规则标签里含纸种关键词，但条件里没限制纸种 | ✅ 自动补上纸种条件（含同义词） |
| 缺装订限制 | 标签含精装关键词但无装订方式限制 | ✅ 自动补上 |
| 开本未展开 | 有「16 开」行但没有「大 16 开」行 | ✅ 自动补行 |
| 档位带单位 | 数量档位里含「册 / 本 / 张 / 套」 | ✅ 删除单位 |
| 档位写法不可解析 | 数量档位含「及以上」 | ✅ 转成可解析格式 |
| 漏乘数量 | 加价规则没乘印数但应该乘 | ✅ 自动追加 |
| 单值键字段 | 查表的某个键在所有行里值都一样 | ✅ 移到条件里 |
| 规则重复 | 不同规则实质上是同一条 | ✅ 保留第一条 |
| 乘数无基数 | 乘数规则没有可乘的前置值 | ⚠️ 仅警告，报人工 |
| 重复的克重调整 | 同一纸种多条克重调整 | ⚠️ 仅警告，报人工 |

界面上显示「**自动修复 7 项，剩余 2 项待人工确认**」。

> **这是整篇文章最实用的一条经验：不要指望提示词把模型管住，要用代码检查模型的产出。**
>
> 提示词是「倾向」，校验器是「保证」。你没法给提示词写单元测试，但可以给校验器写。

还有一层全局后处理也是确定性的：色数值归一（「双面」「全彩」「双面四色」统一成「四色」）、纸张同义词自动扩充（模型提取出「胶版纸」，自动扩为「胶版纸 / 高白胶 / 本白胶 / 双胶纸」）。

## 七、引擎不抛异常，所有问题都进对账

计价引擎的输出不只是一个价格：

```
QuoteResult {
  total_price           最终价格
  breakdown[]           每一笔的来源：用了哪条规则、哪个档位、算式是什么
  warnings[]            规则与订单对不上的地方
  profile_content_hash  计价档案的内容哈希 —— 用于回放
  dsl_version           规则版本
}
```

**引擎不抛异常，所有问题都进 warnings。** 两类最常见：

- **查表未命中**——订单的开本是规则没列的（规则只有 16 开和 32 开，订单是 24 开），或数量落在所有档位之外，或多维键缺一个；
- **部件无规则**——所有规则跑完后，某个部件类型压根没被任何规则覆盖。

这两个警告是报价精度收敛的**主要排查工具**。它们的价值在于：**把「算不出来」和「算错了」区分开**。一个抛异常的引擎只告诉你失败了；一个产出对账信息的引擎告诉你差在哪。

那个 `profile_content_hash` 也值得一提——它让任何一笔历史报价都可以用当时的规则原样复算。**可回放不是附加功能，是审计的前提。**

## 八、历史数据是验证集，不是规则来源

客户提供了历史订单的最终成交价。最诱人的用法是把它当作训练或规则来源——毕竟那是「正确答案」。

这个系统明确把它定位为**验证集**：规则从报价表提取，历史价格用于回归。规则改动后跑一遍样本回归，看价格是否仍然对得上。

原因是：**如果把历史价格当规则来源，系统会学会复现历史上的错误报价。** 而这类错误极难发现——它和「正确」在数据上长得一模一样，只有回到报价表逐条核对才能分辨。

这条区分在很多企业 AI 项目里都成立：**历史数据记录的是「过去发生了什么」，不是「什么是对的」。** 把两者混为一谈，系统会把历史上的偏差固化成规范。

## 九、当前状态与边界

**已跑通：**

| 能力 | 状态 |
|---|---|
| 三种订单入口（PDF 上传、文本粘贴、手工录入） | ✅ |
| 统一订单结构（整书 + 部件 + 工艺） | ✅ |
| 规则 DSL（5 类规则）+ 计价引擎 + 数量分档 | ✅ |
| 计价档案与报价版本链、内容哈希可回放 | ✅ |
| 样本回归验证 | ✅ |
| 平台 / 租户两级术语表 + 未知术语闭环 | ✅ |
| 多租户数据库行级隔离 | ✅ |
| ERP 单向推送（签名 + 发件箱 + 重试） | ✅ |

**尚未完成：**

- **报价精度仍在收敛**——引擎乘数、工艺过滤、默认工艺三处仍在调整，这是当前的主要风险
- 订单识别目前只支持 PDF，图片、Word、Excel、邮件入口未做
- ERP 只有单向推送，无双向同步
- 「约一百家企业」是设计目标，目前只在两家样本上验证过统一结构的成立性

## 十、可迁移的部分

这个案例的技术细节是印刷行业的，但那条分工线不是。

在企业 AI 项目里，「让模型端到端做完」几乎总是最省事的方案，也几乎总是过不了生产验收的方案。真正可落地的分工是：

| 谁 | 负责什么 | 例子 |
|---|---|---|
| **模型** | 有歧义的、需要理解的、规则写不全的 | 读懂自由文本备注、把自然语言规则提取成结构、对缺项提候选 |
| **确定性代码** | 有唯一正确答案的 | 最终计算、精确匹配、权限判断、审计留痕、对模型产出做校验 |
| **人** | 模型不确定时的裁决 | 确认术语归一、处理无法自动修复的规则问题——**且裁决要沉淀** |

判断一件事该归谁，问一个问题就够了：

> **这件事有没有唯一正确答案？**

有——交给代码，并且**为它写测试**。
没有——交给模型，但**它的产出必须经过代码检查，且以候选而非结论的形式落地**。

这条判断在知识库的权限过滤、Agent 的工具授权、数据的分类分级里同样成立。模型让系统变得能理解模糊输入，确定性代码让系统仍然值得被信任——**两者缺一个，都不构成一个能上生产的企业 AI 应用。**

—— 模界数智