没有银弹:先分清复杂度来自业务,还是来自实现
本文是 Agent 工程里的经典架构 系列的一篇。文中的业务场景和代码为讲解设计,产品能力以所链接的官方资料为准。
一个审批流程做得很慢,换了更强的模型后,邮件摘要从十秒降到两秒,订单却还是三天才能完成。不是模型没有价值,而是我们优化的环节没有决定整个流程的结果。架构讨论如果只盯着工具,很容易把可测量的局部改进当成最终收益。
Brooks 在《No Silver Bullet》中区分了本质复杂性与偶然复杂性。业务概念及其相互关系本身的困难,与语言、工具和实现方式引入的困难,不应混在一起讨论。这里借用这个区分分析 Agent 项目,不把它解读为对某一种新技术的预测。
比如采购审批里,接口字段不统一、失败后需要人工重新提交,可以通过适配层和持久执行改善。谁有权批准、超预算时怎么办、供应商违约由谁承担责任,则需要业务约定。系统可以帮助执行规则,不能因为模型更会生成文字,就认为责任边界已经自动解决。
我会先把流程拆成可观察的环节:资料收集、规则检查、人工判断、外部执行和结果确认。然后标记每一步的等待时间、人工投入、失败原因与可逆性。技术选型应该跟着最影响业务目标的环节走,而不只是跟着团队最熟悉或最想尝试的工具走。
下面是一组人为构造的小样本。模型调用平均耗时变短了,但任务是否正确完成、人工介入比例和每个完成任务的调用成本,都需要单独计算。它不是任何产品的实测结果,只用来说明指标的分母应该选择什么。
# 人为构造的数据,仅演示评估口径。
runs = [
{"completed": True, "human": False, "calls": 3},
{"completed": True, "human": True, "calls": 2},
{"completed": False, "human": True, "calls": 8},
{"completed": True, "human": False, "calls": 4},
]
def metrics(rows):
if not rows:
raise ValueError("没有样本")
done = sum(r["completed"] for r in rows)
calls = sum(r["calls"] for r in rows)
return {
"completion_rate": done / len(rows),
"human_rate": sum(r["human"] for r in rows) / len(rows),
"calls_per_completed_task": calls / done if done else None,
}
result = metrics(runs)
assert result["completion_rate"] == 0.75
assert result["human_rate"] == 0.5
assert result["calls_per_completed_task"] == 17 / 3
assert metrics([{"completed": False, "human": True, "calls": 1}])[
"calls_per_completed_task"] is None
print(result)
完整示例可下载,使用 Python 3.9 或以上版本运行:python3 example.py。只依赖标准库,不调用真实业务服务。
代码没有把“API 返回成功”当作任务成功。一个请求可能正常返回,却没有完成退款;一次任务可能经历两次失败重试,最后正确完成。只观察接口错误率,会遗漏这两种区别。完成标准应由业务定义,并尽可能通过账单、订单或用户确认等证据核验。
同样,人工介入也不必一律算失败。有些高影响决定本来就需要人判断,系统提前整理材料、检查缺项,可能已经节省大量时间。真正要比较的是整体处理成本和结果质量。为了追求零人工而增加高代价错误,未必改善 ROI。
这个思路也影响项目拆分。如果流程最常见的问题是审批消息没人看,可以先改善通知、超时升级和状态可见性;如果问题是信息来源分散,再考虑检索与摘要;如果步骤经常在重启后丢失,就先补恢复能力。每个改进都应该对应一个可验证的瓶颈。
软件架构里的取舍仍然存在。抽象层减少重复,也增加理解成本;更通用的工作流支持更多场景,也可能让简单流程难以配置;模型自主选择动作减少硬编码,却增加评估和约束需求。把这些成本写进方案,才能公平比较不同实现,而不是只对新方案算收益、对旧方案算成本。
我也会保留一个足够简单的基线。使用固定规则加人工处理,可能没有演示视频里那么惊艳,但能告诉我们新系统到底改善了什么。基线与新系统需要处理相同类型的任务,观察相同时间窗口,不能拿最容易成功的样本去证明整体效果。
上线后也要继续校验假设。如果人工介入率下降,却有更多用户重复提交,可能只是问题被推给了用户;如果平均成本下降,却只处理了更简单的任务,也不能直接说明整体效率提升。样本构成、重试与后续补救都应进入评估。
我更倾向于用一个明确周期比较相近任务,并保留失败样本的分类。这样下一次迭代可以针对真实瓶颈,而不必靠演示时最顺利的一条路径决定整个技术方向。
对于工程师,这个区分的价值是把讨论从“要不要上某个框架”拉回到“哪个问题值得解决”。代码生成、模型决策和自动恢复都可以降低一部分成本,但业务知识、异常判断和系统之间的真实约束仍然需要认真整理。能够清楚地指出技术改善了哪一段,往往比承诺一个全自动系统更有助于项目持续推进。