OSPF 与 LLM 融合:业务路径
本页介绍问题、决策过程与能力生命周期;技术路径介绍组件、类型化 IR、编译执行和计划恢复。原页面地址保持不变,已有链接仍可使用。
本教程从一个完整的小型生产计划问题出发,说明如何让用户通过自然语言查询、调整和比较 OSPF 优化模型。无需了解任何外部业务系统。LLM 负责生成候选请求;示例应用负责校验与确认;OSPF 和求解器负责数学建模与求解。
这里的集成协议是应用层设计,不是 OSPF 内置的聊天或 JSON 编译 API。文中的模型可独立于 LLM 求解;真实 LLM 接入是可替换的边界,不应成为确定性回归测试的依赖。
本教程的终点是 LLM as Runtime(LLM 参与运行时能力形成):用户不只是得到一次回答,而是在使用过程中表达新的查询、规则和操作组合;应用将这些表达转为受控中间表示,验证后执行,并根据真实使用记录决定哪些值得沉淀为专用能力。LLM 是语义前端,不是取代 OSPF 或应用执行器的运行环境。
阅读路径分为两个闭环:第 1~5 节建立“表达意图—校验—试算—比较—选择”的决策闭环;第 6 节建立“采集运行事实—识别稳定模式—专门化—验证发布—失效回退”的能力形成闭环。后者不能省略成“保存一份提示词或模板”。以下注册表、查询计划、流程和状态名称均是教程的应用层设计,未声称 OSPF 已内置完整实现。
1. 生产计划领域模型
1.1 概述与依赖上下文
工厂生产 A、B 两种产品,希望在一天的材料和加工时间限制内最大化收益。本例只有一个生产计划上下文,无上游上下文依赖。假设全部产品均可销售,不考虑库存、换产、设备排序或固定成本;加工时间是可累加的资源工时,而不是任务在日历上的开始、结束时间。
1.2 概念与实体
产品具有以下属性,所有数值均为本教程给定的确定性输入:
| 产品 | 单位收益 | 材料系数 | 工时系数 |
|---|---|---|---|
| A | 30 | 2 | 1 |
| B | 50 | 3 | 2 |
1.3 变量
决策变量
辅助变量:本模型不需要额外辅助变量;以下中间值和松弛量直接由决策变量求值。
1.4 谓词
MinimumRequired:产品被本轮已确认的最低产量规则选中。该谓词决定哪些产品加入最低产量约束,不改变产品本身的属性。
1.5 集合
1.6 中间值
材料消耗
加工时间
总收益
剩余资源
1.7 断言
输入必须满足以下性质,缺失值不得默认为零:
输入还必须是有限值、产品标识唯一、单位兼容;最低产量
1.8 约束
Material capacity [材料容量]:计划消耗不能超过当天材料供应。
Processing capacity [加工容量]:计划工时不能超过当天可用工时。
Minimum production [最低产量]:只对本轮已确认的规则生成硬约束。
本例没有软约束;用户不能通过调整罚系数绕过材料容量或已确认的最低产量要求。
1.9 目标函数与求解器实际模型
最大化总收益。基准模型传入求解器的完整形式为:
中间值是表达式,不额外生成等式或辅助列。确认最低产量要求后追加对应约束行;试算增加工时时,只修改试算副本中的工时右端值。
1.10 算法引用
本模型是整数线性规划,不依赖额外领域算法。下文使用有限枚举独立核对该小实例;正式求解仍由配置的 OSPF 求解器适配器执行。
1.11 统一语言
| 术语 | 含义 |
|---|---|
| 候选请求 | LLM 生成、尚未经应用接受的操作描述 |
| 方案 | 在某个冻结输入与规则版本上得到的生产计划 |
| 试算 | 在独立副本中调整参数或规则,不修改原方案 |
| 证据 | 可追溯到方案、模型元素和实际求解结果的数据 |
1.12 设计决策
使用整数产量,避免出现半件产品;使用单日、两产品实例,使所有结果均可独立复算。只允许白名单操作,避免执行模型生成的任意源码。语义目录和权限由应用管理,不进入求解器数学模型。
1.13 变更记录
| 版本 | 变更 | 原因 |
|---|---|---|
| 1 | 建立基准模型和受控对话流程 | 展示独立、可验证的 OSPF 与 LLM 集成 |
2. 从求解到交互
用户请求 + 已授权的模型目录与方案快照
→ LLM:生成结构化候选
→ 应用:解析、语义检查、回述确认、版本与权限检查
→ OSPF:构建模型并调用求解器
→ 应用:解析结果,计算中间值与方案差异
→ LLM:引用证据组织说明2
3
4
5
6
LLM 不决定一个方案是否最优,也不直接写入生产状态。即使输出符合 JSON 格式,仍可能误解“至少”“新增”或“今天”。应用必须确认业务含义;求解可行不能证明翻译忠实。
建议按顺序展示以下会话:
| 步骤 | 用户意图 | 明确的上下文 |
|---|---|---|
| S0 | 怎样生产收益最高? | 基准模型,70 小时,无最低产量 |
| S1 | A 至少生产 20 件 | 在 S0 上增加 |
| S2 | 增加 10 小时会怎样? | 从 S1 派生试算, |
| S3 | B 也至少生产 30 件 | 从 S1 派生, |
3. 向 LLM 提供模型语义
应用提供精简目录,而不是让 LLM 猜测代码中的变量下标:
| 稳定标识 | 含义与单位 | 允许操作 |
|---|---|---|
production[A], production[B] | 当天计划产量,整数件 | 查询、设置最低产量候选 |
material.used | 查询 | |
processing.used | 查询 | |
profit | 查询 | |
processing.capacity | 在试算副本中修改 |
目录同时绑定业务日期、时区、输入版本、目录版本和已确认规则。只有得到授权的字段与方案才进入 LLM 上下文;日志不应保存密钥或未脱敏的完整业务输入。
例如,“至少生产 20”缺少产品,应要求澄清;“A 至少 20 kg”不能直接当成 20 件。固定枚举只支持 A、B,不允许通过用户文本访问任意属性或执行函数。
3.1 字段目录是类型契约,不只是提示词词典
以 production[A] 为例,目录记录稳定字段标识 production.quantity、产品维度 A、整数类型、单位 piece、状态角色 planned、业务日和 query/minimumConstraint 能力。A、B 在本例中就是稳定产品 ID;展示名称可以翻译,ID 不随语言变化。
目录快照回答“字段当时是什么意思”,输入快照回答“当时有哪些数据”,权限投影回答“这个操作者现在可以访问什么”。三者必须分别保存或引用,不能用一个版本号代替。字段支持某项能力,不代表当前操作者获得了权限。
同一材料表达式
3.2 查询与约束是不同的中间表示
用户问“查看 S1 的材料和工时使用量”时,不需要重新求解。应用先把 S1 解析为固定的成功运行引用,再读取结果数据集。最小查询候选可为:
{
"schemaVersion": 1,
"operation": "queryResult",
"sourceRunId": "run-S1-1",
"catalogVersion": "production-v1",
"select": ["material.used", "processing.used"],
"maxRows": 1
}2
3
4
5
6
7
8
run-S1-1 是本教程的示意标识,实际由应用分配。执行时核对运行归属、结果快照及目录版本,并把用户预算与服务上限取更严格者。授权过滤同时覆盖投影、过滤、排序和聚合字段,不能只隐藏返回列。
查询谓词判断已有记录是否入选;数学约束限定未来可行解。material.used <= 120 作为查询过滤不会改变优化模型,作为约束则必须绑定到本轮符号表达式。不可行运行没有可行方案值,不能用零行或零值冒充“消耗为零”;合法空结果、缺失结果和未知值分别表达。历史来源缺失时明确失败,不读取当前结果补齐。
4. 从自然语言到约束
“A 产品至少生产 20 件”对应的命题为:
这里
以下 JSON 是本教程建议的应用层候选契约,不是可直接传给 OSPF 的参数:
{
"schemaVersion": 1,
"baseScenarioId": "S0",
"catalogVersion": "production-v1",
"operation": "minimumProduction",
"product": "A",
"quantity": 20,
"unit": "piece"
}2
3
4
5
6
7
8
9
应用负责:严格解析并拒绝未知字段;检查产品、整数范围、单位和版本;核对操作者权限;回述“在 S0 上增加当天 A 至少 20 件”;确认后生成不可变的已验证请求。审批状态、操作者身份和执行权限不得由 LLM 自行填写或授予。
编译规则是有限映射:minimumProduction(A,q) 生成 whatIfProcessingHours(delta) 在明确基准副本上计算 queryResult(field) 只能读取指定方案中已有的证据。应用应限制请求大小、数值范围、候选次数和求解预算。
4.1 技术实现入口
字段注册、类型化 IR、约束编译及 Kotlin/Rust 原生建模片段已移至技术路径。本页保留业务规则和完整数学定义;技术页继续说明每轮模型绑定、求解报告、参数化计划、发布与失效恢复。
5. 求解与可复算的结果
以下结果由有限整数枚举独立核对,是示例的验收基准,不冒充某次实际求解器运行的日志:
| 方案 | 收益(元) | 材料消耗 / 剩余(kg) | 工时消耗 / 剩余(小时) | ||
|---|---|---|---|---|---|
| S0 | 30 | 20 | 1900 | 120 / 0 | 70 / 0 |
| S1 | 30 | 20 | 1900 | 120 / 0 | 70 / 0 |
| S2 | 21 | 26 | 1930 | 120 / 0 | 73 / 7 |
| S3 | — | — | — | 不可行 | 不可行 |
S1 的最低产量没有改变最优方案。S2 新增 10 小时但实际仅多使用 3 小时,收益增加 30 元;不能据此声称每增加一小时都能获得固定收益。
这些最优值也可直接证明。S0/S1 有
若用户在 S1 问“为什么材料没有用完?”,应先纠正前提:“该方案使用了全部 120 kg 材料。”在 S2 问“为什么有 7 小时没用完?”,可以说明材料已用满,并引用重新求解的结果;单凭某条约束紧绑定不能宣称已经证明因果关系或得到整数模型的影子价格。
5.1 不可行性与状态
S3 中,由已确认最低产量可直接推导:
这是本例可独立检查的矛盾证据,不称为求解器返回的 IIS。可以建议用户考虑调整最低产量或授权修改资源条件,但不能自动删除硬约束。即使把工时增加到 80 小时,材料矛盾仍然存在。
实际集成应分别保存问题状态、终止原因与解是否存在。有可行解但未证明最优时,显示可用的界与 gap;超时未找到解不等于不可行。诊断能力不支持或证据缺失时,明确报告缺失,不通过解析自然语言日志补造证据。
5.2 解释用证据契约
应用可向 LLM 提供 scenarioId、输入与规则版本、实际求解状态、变量值、目标分项和约束 lhs/rhs/slack。为每一项分配稳定证据标识,例如 S1/material.capacity。每条定量说明引用证据标识;缺失结果不得补零。只有真实求解后才能填写求解器版本、终止原因与 gap。
5.3 候选、运行与正式方案不能混为一谈
S0~S3 是便于阅读的场景标识,不是四个已经发布的正式版本。为例子引入以下应用记录:
| 记录 | 示例 | 生命周期 |
|---|---|---|
| 正式方案 | plan-v1 引用 S1 的已选运行 | 只有选择与审批成功才产生新正式版本 |
| 迭代 | iteration-1 固定 plan-v1 的内容哈希 | 容纳 S2、S3 两个候选 |
| 候选 | candidate-S2、candidate-S3 | 保存基线引用和不可变变更集,不占正式版本号 |
| 运行 | run-S2-1、run-S2-2 | 一次求解一次 ID;重试不覆盖旧报告 |
| 能力版本 | compare-hours-v1 | 第 6 节发布的可复用操作,不是生产方案 |
“确认 A 至少 20 件的含义”“授权试算”“采用试算结果”“发布可复用能力”是不同决定,不得共享一个 LLM 可写的 approved 布尔值。
例如 S2 和 S3 从同一个 plan-v1 并行试算。选择 S2 后,应用重新校验基线是否仍有效、选中运行是否匹配候选哈希、可行性与审批是否满足要求,再以预期版本和幂等键创建唯一的 plan-v2。S3 保留为不可行的历史候选。并发选择发生版本冲突时重新比较,不能让两个候选同时覆盖正式当前态。此处只描述方案登记,不实现生产下发。
5.4 先形成影响分析,再生成修正候选
S3 的确定性证据已经证明最低材料需求为 130 kg。应用可以生成结构化影响结果:对象 A/B、原因 MINIMUM_EXCEEDS_MATERIAL、证据引用、待确认事项、允许动作 ASK_CLARIFICATION/CREATE_WHAT_IF。LLM 可以解释并组合候选,但不能把“可能增加材料”改写为“现场材料已经增加”。
字段拼写错误只能在映射无歧义时按规则纠正;语义不明确则追问。求解超时可以在授权预算内形成新的运行尝试,硬约束变化必须成为新的候选并重新确认。为修正轮次、总时间、模型调用和求解次数设置上限,超限转人工。多数 LLM 回答赞成某个修改,不构成数学证明或审批。
保存原始结构化候选、上下文哈希、父候选/父运行、修正原因和新报告,才能复盘每一步。回放确定性候选不需要重新询问 LLM;重新生成自然语言说明不保证文本逐字相同,也不能以文本差异推断数学结果不一致。
6. 从交互求解走向 LLM as Runtime
6.1 为什么一次成功的对话还不够
前面的应用能回答一次问题,却仍可能为每次相似请求重复调用模型、解析意图和组织试算。现在把使用过程也纳入设计:用户多次询问“材料和工时还剩多少”,多次指定不同产品的最低数量,或多次比较增加不同工时后的收益。变化的是参数,稳定的是操作结构。
本节让同一例子形成第二个闭环:
自然语言 → 结构化候选 → 验证 → 通用执行 → 运行事实
↑ ↓
安全回退 识别稳定语义形状
↑ ↓
失效/撤销 ← 专用能力 ← 验证/发布
↓
后续请求绑定新参数并执行2
3
4
5
6
7
这里的“编译”首先是把语义转为可复用的执行计划,而非生成机器码。LLM 帮助表达过去需要开发者逐一实现的请求;应用运行时决定哪些已验证的组合可以留下来。未知公式仍需领域开发,不能凭自然语言自动变成正确的新能力。
6.2 三类可沉淀产物
| 重复请求 | 参数化中间表示 | 专用产物 | 仍需执行的工作 |
|---|---|---|---|
| 查看某次运行的资源余量 | 固定数据集、字段与结果映射,runId 为参数 | 只读查询计划 | 新运行的授权、快照读取与预算检查 |
| 某产品至少生产某数量 | MinimumProduction(product,q,date) | 约束模板与已验证编译规则 | 参数、单位、作用域检查,重新绑定本轮 OSPF 变量 |
| 比较增加不同工时的收益 | CompareHours(base,deltaList) | 查询—候选—求解—比较流程计划 | 每个候选重新求解,结果比较与审批 |
查询计划缓存的是“怎样取数”,不是某次查询结果;约束模板缓存的是“怎样生成约束”,不是跨模型复用运行时变量;流程计划缓存的是“怎样组织操作”,不是既有最优解。任何一次缓存命中都不能证明新输入可行或最优。
本例查询可直接读取内存中的结果快照,不要求数据库。若扩展到数据库,只能由适配器将已验证查询编译为参数化计划,不能让 LLM 返回 SQL。是否进一步生成代码制品,需要额外性能证据、隔离与发布治理,不是本教程的前提。
6.3 区分请求、形状与执行证据
“A 至少 20 件”和“A 至少 25 件”是两个具体请求,但可以共享 MinimumProduction(product:ProductId,q:Integer[piece]) 形状;若 A、B 的字段能力和权限适用规则相同,产品也可以成为类型化参数。不能抹掉不同算法放置位置、单位、时间语义或授权策略的差异来提高命中率。
| 标识 | 包含内容 | 不可代替 |
|---|---|---|
requestHash | 规范化的具体请求、参数和基线引用 | 不能用形状哈希替代历史请求 |
shapeHash | 操作、字段、类型、参数位置、单位、时间及结果语义 | 不含具体敏感参数,不证明两个请求结果相同 |
dependencyKey | 目录、策略、编译器、适配器、模型语义版本 | 不等同于输入数据哈希 |
runId/resultHash | 单次执行及其规范化结果 | 不等同于计划版本 |
使用确定性的结构化序列化计算哈希,不使用自然语言文本或对象 toString()。只在已证明语义可交换的节点上排序。计划与指标不记录参数原值;具体请求的审计数据另行受权限和保留策略管理。空结果有明确的规范表示,不能与缺失结果混同。
每次运行追加所用路径、形状、计划版本(若命中)、来源快照、耗时、返回量、错误、结果哈希和可用的资源成本。首次尚未规范化的请求允许没有形状记录,不能捏造命中。数值求解的运行事实还保留求解器实际报告;指标日志不替代这些报告。
6.4 从运行事实决定是否专门化
假设真实记录显示某类比较操作反复发生,先区分时间消耗在 LLM、语义校验、模型构建还是求解阶段。缓存候选编排只可能减少前几项开销,不能宣称已经加速整数求解。
提升策略同时考察频率、语义稳定性、错误率、人工修正、尾延迟、构建成本和预期复用量。可用以下估算帮助判断,而不是作为已测量结果:
其中
6.5 验证与发布专用能力
应用层注册表保存不可变计划版本:planId/version、参数化 IR、参数 schema、结果映射、依赖版本、内容摘要、验证证据、适用范围、发布者和回退引用。生命周期可设计为:
CANDIDATE → COMPILING → VERIFYING → ACTIVE
└────────┴──────→ FAILED
ACTIVE → STALE / REVOKED2
3
状态变化追加事件;重建产生新版本,不覆盖失效版本。只有验证通过的版本才能原子切换为 ACTIVE。验证至少包括:
- 查询:同一冻结数据上的行、顺序、空值、分页、权限和预算错误一致。
- 约束:通用与模板路径的变量绑定、系数、关系、右端值和定义域一致,并检查边界与单位反例。
- 流程:相同节点契约、基线与参数产生语义一致的候选及比较,沙箱不产生正式写入。
- 性能:记录两条路径的真实耗时与资源成本,预先确定收益门槛,不能只展示平均值。
先影子运行:仍返回通用路径结果,专用路径只用于比对。正确性、失败语义和收益达标后再小范围启用,并监测 p95/p99、错误率和回退次数。有限测试不能证明所有输入上的等价;受限语法的确定性编译规则、声明的适用域与性质测试共同限定信任边界。
6.6 下次请求如何执行,以及何时回退
对新的“比较增加 5、10、15 小时”,LLM 可继续完成参数提取,也可由用户直接调用已发布的结构化操作。应用重新检查权限、参数与基线,然后按 shapeHash + dependencyKey 查找有效计划。命中才使用专用路径;未命中则走仍受完整校验的通用路径,异步构建不能阻塞当前请求。
目录字段被移除、单位含义改变、权限策略升级或编译器不兼容时,相关计划标为 STALE;重启时重新校验依赖与摘要,弥补遗漏的失效事件。若通用路径也无法理解新字段,返回能力缺口,而不是无条件“回退成功”。回退只能选择仍兼容且未被撤销的版本。
例如工时单位从小时改为分钟,旧计划不能继续把参数 10 解释为 10 小时;需显式单位换算或新版本验证。相反,每天
6.7 将多个已治理能力组合成流程
为“批量比较工时变化”登记以下节点契约,而不是暴露任意函数名:
| 节点 | 类型化输入 → 输出 | 执行边界 |
|---|---|---|
| ReadBaseline | 方案版本引用 → 冻结快照 | 授权只读 |
| CreateHoursCandidates | 快照、小时增量列表 → 候选列表 | 独立副本、数量上限 |
| SolveCandidates | 已验证候选 → 运行报告列表 | 求解预算、取消、保留失败 |
| CompareResults | 基线报告、候选报告 → 差异表 | 按实际可行性与 KPI 比较 |
流程图验证输入输出类型、单位、节点版本、可达性和执行预算。比较前必须等待所需报告,超时或无解行保留状态,不以零收益参与排名。沙箱中的求解可以是真的,但审批、正式方案发布和生产下发不在 Agent 可编排节点集合内。
把上述流程版本、最低产量模板版本、字段目录依赖、参数边界和验证记录引用式组合,可以形成一个“最低产量下的工时试算”适配包。它允许新参数使用已有能力,不需要为每种措辞新增接口。包发布与方案采用仍独立审批;任一依赖变化使联合验证失效,不能只发布一半依赖。
6.8 从例子理解能力演进的边界
| 新请求 | 处理方式 |
|---|---|
| 换成 B 至少 15 件 | 已有字段与编译规则,校验新参数 |
| 先查余量,再比较多个工时增量 | 组合已注册查询、求解与比较节点 |
| 引入随产量变化的良率曲线 | 当前模型未定义该公式,返回能力缺口并进入建模开发 |
| 忽略材料限制并直接下发 | 越权或不安全,拒绝,不伪装成待优化配置 |
因此 LLM as Runtime 的价值不是无限扩大模型权限,而是让开放意图进入受限领域语言,在实际使用中形成可执行、可复用、可撤销的能力。一次性请求可以保持临时状态;稳定重复的规则再成为模板或适配包,充分验证的共性最终可进入正常维护的产品功能。这是从“软件回答问题”到“软件在使用中受控形成能力”的完整链条。
6.9 一条可以逐步验收的运行轨迹
下面是应用实现应当产生的验收轨迹,不是已经运行的日志。使用同一个生产模型即可验证,不需要引入订单、设备或其它业务系统。
| 步骤 | 输入与动作 | 应保存的输出或事实 |
|---|---|---|
| 1. 首次请求 | 从 S1 比较增加 10 小时,目录为 production-v1 | 候选、输入快照、通用路径运行及 S2 比较结果;正式方案不变 |
| 2. 重复使用 | 多次提交不同工时增量,仍保留最低产量规则 | 不同请求哈希、相同适用形状、每次独立运行;次数不足则不提升 |
| 3. 产生能力候选 | 运行统计满足预先定义的提升策略 | compare-hours-v1 的参数契约、依赖、构建任务与原因 |
| 4. 验证 | 在相同历史输入上运行通用和专用路径 | 比较证据、失败反例、成本记录;不一致则 FAILED |
| 5. 发布 | 验证与发布授权通过 | 不可变能力版本与 ACTIVE 发布事件,不生成新的生产方案 |
| 6. 再次调用 | 在 S1 上比较增加 5、10、15 小时 | 重新授权、绑定参数、执行已发布流程;每个候选仍真实求解 |
| 7. 采用方案 | 用户选择某个成功且符合采用策略的候选 | 独立审批并创建正式方案版本;不修改能力版本 |
| 8. 依赖变化 | 工时字段的单位契约变更 | 旧能力 STALE;兼容通用路径或能力错误;新版本异步验证 |
| 9. 重启与回放 | 恢复注册表并读取历史运行 | 当前执行重新校验依赖;历史记录仍引用原版本,不篡改旧结果 |
若第 1 步已完成而第 3~9 步没有对应执行证据,只能称为“LLM 辅助试算”;若只是手工写好模板并调用,称为“参数化能力复用”。只有运行事实参与能力选择、验证、发布和失效治理,才具备本教程所讨论的 LLM as Runtime 闭环。通用求解报告及数学证据由 OSPF 提供,能力注册表和上述生命周期由示例应用承担,二者不能混淆。
7. 测试、复现与扩展
下面是仅依赖语言标准库的完整数值验证程序,不代替 OSPF 建模与求解适配器。将所选代码保存为 Main.kt 或 main.rs;断言全部通过时没有输出。
data class Plan(val a: Int, val b: Int) {
val material get() = 2 * a + 3 * b
val hours get() = a + 2 * b
val profit get() = 30 * a + 50 * b
}
// Independent oracle for this fixed 120 kg instance only.
fun oracle(minA: Int, minB: Int, hours: Int): Plan? {
require(minA >= 0 && minB >= 0 && hours >= 0)
return (0..60).flatMap { a -> (0..40).map { b -> Plan(a, b) } }
.filter { it.a >= minA && it.b >= minB &&
it.material <= 120 && it.hours <= hours }
.maxByOrNull { it.profit }
}
fun main() {
check(oracle(0, 0, 70) == Plan(30, 20))
check(oracle(20, 0, 70) == Plan(30, 20))
check(oracle(20, 0, 80) == Plan(21, 26))
check(oracle(20, 30, 70) == null)
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#[derive(Debug, PartialEq, Eq)]
struct Plan { a: u32, b: u32 }
impl Plan {
fn material(&self) -> u32 { 2 * self.a + 3 * self.b }
fn hours(&self) -> u32 { self.a + 2 * self.b }
fn profit(&self) -> u32 { 30 * self.a + 50 * self.b }
}
// Independent oracle for this fixed 120 kg instance only.
fn oracle(min_a: u32, min_b: u32, hours: u32) -> Option<Plan> {
(0..=60)
.flat_map(|a| (0..=40).map(move |b| Plan { a, b }))
.filter(|p| p.a >= min_a && p.b >= min_b
&& p.material() <= 120 && p.hours() <= hours)
.max_by_key(Plan::profit)
}
fn main() {
assert_eq!(oracle(0, 0, 70), Some(Plan { a: 30, b: 20 }));
assert_eq!(oracle(20, 0, 70), Some(Plan { a: 30, b: 20 }));
assert_eq!(oracle(20, 0, 80), Some(Plan { a: 21, b: 26 }));
assert_eq!(oracle(20, 30, 70), None);
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
确定性测试不调用真实 LLM。对固定候选输入验证解析、校验和约束映射,再用真实求解器检查结果;LLM 的语义测试单独评估正确理解、澄清和拒绝行为。
| 测试 | 预期 |
|---|---|
| 基准与 S1 | 可行,最优收益 1900 |
| S2 保留 A 最低产量 | 最优收益 1930,不错误返回不带最低产量的 2000 |
| S3 | 不可行,保留三条矛盾约束的来源 |
| 未知产品、负数、小数件数、错误单位 | 建模前拒绝 |
| 过期基准、未授权修改、伪造确认字段 | 执行前拒绝 |
| 重复请求 | 幂等处理,不重复累加工时 |
| 模拟超时且无解 | 不描述为已证明不可行 |
| 模板与通用路径 | 相同约束与目标语义 |
7.1 LLM as Runtime 的额外验收
以下是应用运行时的验收要求,不表示本文已实现注册表、数据库或发布服务:
| 场景 | 必须证明的行为 |
|---|---|
| 最低产量 20 改为 25 | 形状可复用,具体请求哈希不同,新参数重新校验 |
| 只读查询改为最低产量约束 | 不合并为同一执行形状 |
| 专用路径影子结果错误 | 不发布,保留通用响应与差异证据 |
| 字段单位或权限策略变化 | 旧计划执行前失效,不因缓存命中绕过检查 |
| 服务重启、丢失失效事件 | 重新核对依赖和摘要,不盲目恢复 ACTIVE |
| 两个 worker 同时发布 | 预期版本/CAS 保证只有一个有效发布事实 |
| 相同参数但不同历史输入 | 不错误复用结果;读取相应快照并重新求解 |
| 编译失败、计划被撤销 | 使用仍兼容的通用路径或明确能力错误 |
| 选择候选与发布模板 | 分别授权、记录版本,不互相隐式触发 |
| 沙箱流程 | 可运行求解,不发生正式方案或外部写入 |
记录候选合法率、解释证据覆盖、未经批准修改硬约束次数、计划命中与回退次数、通用/专用 p95/p99、构建成本和 LLM 调用成本。数值 fixture 通过,只证明小模型的数值结果;要声称形成了运行时能力闭环,还必须有注册表持久化、状态转换、真实路径比对、失效与恢复的执行证据。
该小模型可枚举
真实 LLM 接入只需实现“授权上下文和请求 → 候选”的接口,密钥从运行环境读取,并设置超时与重试预算。无需绑定特定厂商、SDK 或工具协议。通过固定候选的回放即可先验证完整的确定性流程。
本教程不实现生产下发、长期记忆或自动学习目标权重。进一步采用领域驱动设计时,可参考使用领域驱动设计架构;约束翻译的正确性可结合数学模型的演绎逻辑表达和形式化设计与形式化验证继续展开。