基于规则的决定模型与大型语言模型调用:边界处的延迟与稳定性
一项包含240次调用的实验,用于比较Jev所给出的固有概率与大型语言模型自我报告的概率,以及如何将这一差异转化为LangChain模型路由器。
来源: **Does Every AI Decision Need an LLM? Testing Jev with LangChain**
现代智能体代码中充斥着各种简单的“是”或“否”的判断:这张工单是否紧急、这个工具调用是否符合需求、这段数据是否值得获取。常见的处理方式是通过另一次生成式LLM调用来回答每个问题并解析结构化回复,虽然可行,但每一步都需要数秒时间,且会产生许多含义不明的结果。本演示通过专门设计的决策模型和通用LLM共进行了240次相同的有限判断,然后将得到的概率值接入LangChain路由器。学习完成后,你将了解如何公平地比较这两种方式,知晓延迟与稳定性方面的差异,以及为何要将路由策略写在普通代码中而非提示词里。
有限判断并非生成任务
看看典型的大语言模型应用中出现的各种决策,其中很多其实并非与生成语言相关:
- 这个服务请求是否应被视为紧急任务?
- 所推荐的工具功能真的符合用户的需求吗?
- 这份文档是否符合特定条件?
- 检索到的段落是否足够相关,可以纳入上下文中?
常见的实现方式是将当前状态传递给大语言模型,要求其给出结构化的答案,再将该答案转换为代码中的分支。从原理上讲这并没有问题。关键问题是:这些分支点是否每一个都值得使用完整的自回归模型来处理?
Jev是TypeSafe AI所谓“System One”系列中的首个模型,它采用了完全不同的处理方式——从不生成自由文本。用户只需提供一定的状态信息以及一组受限的查询,它就会以结构化的决策结果和概率值来回应。该厂商将其定位为软件开发的构建模块,而非聊天或推理模型的替代品。LangChain已发布了相关集成方案,可在智能体框架中利用Jev来完成选择模型、检查工具调用等任务。在撰写本文时,这两款产品都还处于新阶段,因此在基于它们进行开发之前请先确认当前的API接口情况。如果您主要关注这种架构的成本问题,关于在前沿大语言模型调用前使用结构化决策路由器的定价策略这篇文章会涉及相关内容;而本文的重点则在于其行为表现与延迟问题。
设计比较方案
两个系统都被要求回答同一个问题,具体表述为:该请求是否需要真正的多步骤推理,还是属于更简单的情况,比如直接查找、提取数值、进行基本计算、重新编写内容或进行少量本地编辑?
这些提示题刻意选择了较为模糊的案例。过于明显的极端情况并不能提供太多信息;路由器真正有趣的行为表现恰恰出现在“直接回答”与“仔细思考”之间的临界点。共使用了八条开发者提出的请求:
- 字典查找:为何在 Python 字典中查找键值通常的时间复杂度为 O(1)。
- 列表与集合:哪种数据结构更适合存储唯一的用户 ID。
POST /users/{id}/delete进行评估,探讨是否存在更简洁的REST实现方式。每个问题在三种不同的配置下各运行了十次:
- Jev,通过返回请求是否需要复杂推理概率的
Noul工具来提出问题。
调用预算的具体分配如下。
8 prompts
× 10 repetitions
× 3 conditions
= 240 calls
每次调用都会记录其决策结果、存在的概率值、模型名称以及往返延迟。需要明确的是,该实验并未试图解决以下问题:对于某个请求“真正”需要多少推理步骤,并不存在客观的基准标准,因此正确性并非评估目标。相反,该实验聚焦于三个更具体的问题:
- 决策模型与生成模型是否能得出相似的路由判断?
最重要的发现来自那些处于边界情况的提示词,而非明显复杂的提示词。
同一决策的三种实现方式
这三种方案均使用 LangChain 以 Python 编写。
带有一个 Noul 的 Jev
Noul 模型用于表示二元命题,但它不会直接给出真或假的结果,而是返回一个概率值。Jev 以开发者输入作为状态,并接收一个包含问题的 Noul 模型。该问题的定义大致如下:
Noul(
instructions="""
Does this request require substantial multi-step reasoning
rather than a direct lookup, extraction, simple calculation,
rewriting task, or small localized edit?
"""
)
响应仅是一个数字,例如:
0.86
该数值即表示该命题成立的概率:
P(requires substantial reasoning) = 0.86
为将Jev与二元大语言模型设置进行比较,概率值若达到0.5或更高则视为True。
GPT-5.6 Sol报告其自身概率
生成模型基于LangChain使用了ChatOpenAI,并通过Pydantic模型来约束输出格式。Field(ge=0.0, le=1.0)参数仅确保数值处于指定范围内,但并不能说明该数值是否具有实际意义。
class ReasoningProbability(BaseModel):
requires_reasoning: bool
probability: float = Field(ge=0.0, le=1.0)
此处模型需要同时给出判断结果以及“是”的概率估计值。这种区别值得重视。Jev的输出正是该模型被设计用来生成的;而大语言模型给出的数值只是因为它遵循架构要求而生成的浮点数,无法保证其反映了任何内部概率值。将这两个数值视为同一类型的量只是一种假设,并非事实。
GPT-5.6 Sol被迫采用布尔值形式
第三种设置去掉了所有与概率相关的元素,仅要求该模型输出一个数值:
class ReasoningBinary(BaseModel):
requires_reasoning: bool
这样就得到了三种不同的信号:一种为原生概率值,另外两种为生成型变体。
Jev
→ native probabilistic decision
GPT-5.6 Sol
→ generated probability + decisionGPT-5.6 Sol
→ forced binary decision
240次调用的结果
出现了三种模式:
- Jev更快地得出了有界决策结果。
- 对于明显需要推理的请求,各系统大多意见一致;在边界附近则出现分歧。
- 对于某个处于边缘状态的提示语,大语言模型在相同调用下的自我报告概率值波动很大。
延迟:数十毫秒对比数秒
以平均往返时间衡量,Jev 每次做决策的响应时间为 128.8 毫秒。GPT-5.6 Sol 在返回概率值时的耗时为 2,828.1 毫秒,而在仅输出二进制结果的模式下耗时则为 4,072.1 毫秒。也就是说,输出概率值的版本速度大约慢 22 倍,而仅输出布尔值的版本则慢 32 倍。
应将这些数值视为某一时刻的测试结果,而非基准标准。托管 API 的延迟会随服务提供商的负载、模型版本、所在地区以及网络路径而变化。其中数量级才是有用的信息:当任务仅需进行一次有限判断时,启动通用生成模型所带来的资源开销远远超过实际需求。
仅输出二进制结果这一现象值得注意。减少输出字段并未让调用速度加快,反而可能更慢。单次测试无法解释原因,但这提醒我们,端到端大语言模型的延迟主要受排队、预填充以及模型在回答前进行的任何隐性推理等因素影响,而非可见输出token的数量。
极端情况下一致,边缘情况出现分歧
对于那些明显较为复杂的提示语,无论是使用Redis替代方案还是将任务分配到多个微服务中处理,两种系统都认为需要进行推理,并给出了较高的评分。而在看似较简单的请求上则出现了差异:对于词典查询、列表与集合的比较以及REST设计相关问题,GPT-5.6 Sol给出的概率接近零,而Jev给出的概率则明显更接近中间值。
REST设计的评估是最明显的例子:
该请求要求对 POST /users/{id}/delete 进行分析,并提出更符合 RESTful 设计的替代方案。
Jev 的平均概率为 0.551,略高于 0.5 的阈值。GPT-5.6 Sol 的平均概率为 0.071。这并非处于阈值附近的随机波动:在所有十次测试中,Jev 都将此请求判定为需要大量推理,而两种大语言模型在所有十次测试中都将其判定为无需大量推理。
但这并不意味着 Jev 是正确的。在没有标注过的真实数据作为参考的情况下,无法判断哪种判定更优。可以确定的是,这两种信号不可互换,且它们在路由器对边界定义最为敏感的领域存在差异。如果用另一种决策源替代原有的决策源,那些你最不确定的请求的路由方式很可能会发生变化。
两个介于零与一之间但表现不同的数字
将每个提示重复10次后,稳定性变得明显。大多数提示都能让两个系统产生相当一致的输出。唯一的例外是要求在队列系统和发布/订阅系统之间选择用于订单通知的方式。
在10次完全相同的调用中,GPT-5.6 Sol自我报告的概率大致在0.28到0.90之间,而Jev的数值则始终集中在较窄范围内。这种二进制大型语言模型配置在10次测试中有9次给出了True的答案,因此尽管其声称的置信度并不稳定,但最终结果却相当稳定。
其解释基于结构差异。两种系统都会输出可表示为[0, 1]范围内数值的结果,但背后的处理机制不同。对于Jev模型而言,概率是该模型针对有限决策场景的固有输出;而对于大语言模型,则是因为提示词要求进行估算而生成的标记序列,且不同运行次数的采样结果可能差异很大。在当前任务中,大语言模型自我报告的概率并无法稳定地表现出与专为概率决策设计的模型相同的特性。如果你打算使用这类数值作为阈值,应在信任其结果之前先测量多次调用时的方差。
将概率转化为LangChain路由器
这一对比促使我们进行了实际测试:利用Jev模型的概率来在两个OpenAI模型之间路由真实请求。
- GPT-5.6 Luna用于处理那些无需复杂推理的请求。
Jev从不直接选择模型。它会回答实验中相同的Noul问题,即该请求是否需要复杂的多步骤推理,并返回一个概率值,如0.54,其含义为P(需要复杂推理) = 0.54。
随后,应用程序代码会将该值与用普通Python定义的阈值进行比较:
REASONING_THRESHOLD = 0.65
对应的判断逻辑也非常简单:
if reasoning_probability >= REASONING_THRESHOLD:
model = powerful_model
else:
model = fast_model
分工才是关键。Jev负责提供概率值,应用程序则决定如何使用这些概率。当阈值设为0.65时,得分0.54的任务会被分配给Luna,而得分0.86的任务则被分配给Sol。该策略明确、确定,且可通过代码差异对比进行审查,而语义判断则由模型负责。
整个流程如下:
User request
↓
Jev
↓
P(requires substantial reasoning)
↓
Python threshold = 0.65
↙ ↘
Luna Sol
关于该阈值的一点说明:0.65仅用于演示,并非经过优化设定。选择这个数值只是为了在简单的示例中,将明显较为简单的请求归为一类,而将得分较高的设计及架构相关问题归为另一类。在实际生产环境中,需要通过更大规模的标注数据集进行实证分析,并权衡两种不同的成本:要么在简单请求上使用性能较高的模型,要么将真正复杂的请求发送到性能较弱的模型。这两种成本往往不对称,因此最佳阈值也极少是0.5。
路由器的处理方式
共有六项请求经过了路由器处理,范围从简单的计算到多区域架构问题。大多数结果都与直觉相符:计算和重写任务得分很低,被分配给了Luna;而复杂的架构问题得分较高,则被分配给了Sol。
那些信息量适中的案例情况如下:
- 词典查询相关问题的得分为0.46
- REST API相关问题的得分为0.54
- 队列与发布/订阅模式相关问题的得分为0.86
由于Jev返回的是连续分数而非固定的“简单”或“困难”标签,因此路由策略的激进程度便成为一个可单独调整的决策因素。在0.65的分值时,REST API相关问题被分配给Luna处理,而队列与发布/订阅模式相关问题则由Sol处理。提高阈值可以减少发送给大型模型的请求数量,从而节省成本;降低阈值则能降低遗漏处理困难请求的风险。调整该阈值并不会改变模型的判断结果,这意味着即便动态调整策略,也无需重新提问。
本实验的局限性
需使各项表述保持适度:
- 八组提示词无法全面概括任意一种模型,且标注问题本身具有主观性。
- 并未对准确率与校准情况进行测量,该测试比较的是行为表现、一致性及延迟时间,而非正确性。
- Jev的概率值与大型语言模型自我报告的数值不应被认为具有相同的统计意义。
- 延迟时间取决于服务提供商以及测试时的具体条件。
更严谨的后续研究应使用规模更大的标注数据集,并对整个路由过程进行端到端评估:包括路由准确率、校准情况、下游答案质量、成本,以及对不同阈值的敏感度。
何时需要单独的决策模型
对于小型应用而言,让大语言模型负责路由通常完全可行;多一次调用几乎无关紧要。但当智能体需要处理越来越多的路由、检索、验证和工具检查步骤时,情况就会发生变化。这些步骤中的很多都属于有限范围的判断,如果每一步都变成需要数秒时间生成内容的调用,那么智能体的处理循环就会因与实际工作无关的原因而变得缓慢且成本高昂。
清晰的职责划分应如下所示:
- 决策模型负责处理有限范围的语义判断并返回概率值。
- 应用代码则负责设定阈值、策略及分支逻辑。
- 大语言模型则承担开放式思考与文本生成的任务。
一个功能强大的大型语言模型可以处理所有这些任务,但这并不意味着系统的每个部分都必须使用相同类型的模型,尤其是在延迟至关重要的情况下。关于根据任务需求选择合适模型规模的更多论述可见“结合路由、检索与评估功能合理选择大型语言模型规模”一文。
关键要点
- 在本次测试中,决策模型每次做出有限判断的平均耗时约为129毫秒,而生成式模型的耗时则为数秒。
- 对于接近模糊的输入,两种系统会持续出现分歧而非随机错误,因此用一种信号替代另一种信号会在最敏感的环节改变路由决策。
- 同一请求下,大型语言模型自我报告的概率可能差异很大(此处同一个提示语对应的概率大约在0.28到0.90之间);在对概率设置阈值之前应先检测其变化幅度。