ORBIT:让企业级 AI 从“会推理”走向“可靠执行”

2026-08-06 47 预计阅读时间: 1 分钟
来源: postgr.es AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:15 分钟

企业 AI 最危险的故障,不一定是模型给出了错误答案,而是系统做出了一个重要决定,却没人能在事后解释它是如何发生的。模型可能检索正确、推理合理、选择了正确动作,但外围系统仍会因为超时、重启、重复投递或状态记录丢失而产生错误结果。

这意味着,AI 可靠性不能只靠更强的模型解决。只要 AI 开始修改业务数据、调用外部 API、发送消息或触发审批,它就进入了分布式系统的世界。ORBIT 提出的五项执行原则,关注的正是模型之外的那一层:如何让决定持久化、让多 worker 协调、让任务脱离请求生命周期、让重试不会制造重复结果,并让每个重要决策留下证据。

从一次成功调用到可恢复的业务流程

Demo 只需要证明一次调用能够成功。生产系统却要面对持续发生的网络超时、服务重启、队列重复投递、消息乱序和用户关闭浏览器等情况。

因此,生产 AI 工作流的目标不是“只执行一次”,而是即使被中断、重复执行或延迟执行,也能最终得到正确的业务结果。一个文档处理流程可能包含文本抽取、摘要、分类、向量化、索引、通知和人工审批。把它们塞进一个 HTTP 请求,等于让浏览器连接、请求超时和单个进程承担整个业务流程的生存责任。

更稳妥的设计是:请求只负责创建工作,工作流本身拥有独立的状态、重试记录和执行历史。

ORBIT 的五个执行支点

O:Outbox First,先持久化行动意图

业务事务与外部副作用之间存在一个天然间隙。应用先更新数据库,再调用支付、消息或通知服务时,进程可能正好在两步之间崩溃。数据库会认为动作已经完成,但外部动作根本没有发生。

反过来,外部调用已经成功,进程却在记录结果前崩溃,重试又可能造成重复扣款或重复发信。

Outbox 模式把“准备执行什么”写入与业务状态变更相同的数据库事务。提交成功后,独立 worker 再读取 outbox 表并执行外部动作;只有确认动作成功,才把记录标记为完成。这样,崩溃最多留下一个待处理意图,而不是让意图直接消失。

下面是一个可改造的 PostgreSQL 示例。ordersoutbox_events 必须在同一个事务中提交,worker 则负责异步投递事件:

CREATE TABLE orders (
    id UUID PRIMARY KEY,
    status TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE outbox_events (
    id UUID PRIMARY KEY,
    event_type TEXT NOT NULL,
    aggregate_id UUID NOT NULL,
    payload JSONB NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending',
    attempts INTEGER NOT NULL DEFAULT 0,
    available_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    sent_at TIMESTAMPTZ
);

BEGIN;

INSERT INTO orders (id, status)
VALUES ('00000000-0000-0000-0000-000000000001', 'created');

INSERT INTO outbox_events (id, event_type, aggregate_id, payload)
VALUES (
    '00000000-0000-0000-0000-000000000010',
    'order.created',
    '00000000-0000-0000-0000-000000000001',
    '{"order_id":"00000000-0000-0000-0000-000000000001"}'::jsonb
);

COMMIT;

-- worker 获取待处理事件;SKIP LOCKED 允许多个 worker 并行消费
SELECT id, event_type, aggregate_id, payload
FROM outbox_events
WHERE status = 'pending'
  AND available_at <= now()
ORDER BY available_at
FOR UPDATE SKIP LOCKED
LIMIT 1;

真实 worker 还需要在同一事务中增加 attempts、设置退避时间,并在外部服务成功后更新 status = 'sent'。对于无法提供 exactly-once 的外部 API,仍需配合幂等键。

R:Rate & Shared State,限流与共享状态必须协调

当多个 worker、agent 或后台任务可以同时处理同一资源时,本地内存状态就不再可靠。两个 worker 可能同时领取同一任务,五个 agent 可能各自认为还有 API 配额,两个工作流也可能同时修改同一客户记录。

可行的基础做法包括:

  • SELECT ... FOR UPDATE SKIP LOCKED 或 PostgreSQL advisory lock 独占领取任务。
  • 把限流计数写入共享表,而不是写在每个进程自己的内存里。
  • 对同一个业务实体设置明确的并发策略,例如按客户 ID 串行化。
  • 把“谁拥有下一步动作”作为可查询的持久状态记录下来。

共享状态不是为了让系统更复杂,而是为了让每个执行者看到同一个事实来源。只要多个进程能够操作同一件事,它们就不能只依赖自己的局部判断。

B:Background Is the Unit of Execution,让工作活过请求

用户上传文档后,系统可能需要抽取、总结、分类、生成 embedding、写入索引并发送通知。这类流程可能持续数秒甚至数分钟,浏览器连接却可能在几百毫秒后就断开。

请求应该启动工作,而不应该拥有工作的完成责任。典型实现是:

  1. HTTP 接口创建 workflow_run 记录,状态设为 queued
  2. 同一个事务写入 outbox 事件。
  3. worker 根据工作流状态执行单个步骤。
  4. 每个步骤成功后持久化结果和下一步状态。
  5. 失败时只重试失败步骤,而不是从头运行整条链路。
  6. 前端通过轮询、SSE 或 webhook 查询进度。

这种结构还能让服务重启后从上一个已确认的步骤恢复,而不是因为请求连接断开而丢失全部工作。

I:Idempotency from Day One,让重试不会产生新业务结果

分布式系统无法可靠地假设消息只会到达一次。网络可能在服务端成功后超时,队列可能重复投递,worker 也可能在提交结果后立刻重启。

幂等性并不意味着操作只运行一次,而是同一逻辑操作运行多次,业务结果仍然只出现一次。通常可以组合使用:

  • 为每个逻辑操作生成稳定的幂等键。
  • 用唯一约束拒绝重复业务记录。
  • 通过条件更新确保状态只能向前推进。
  • 外部 API 调用携带幂等键。
  • worker 执行前检查当前工作流状态。
CREATE TABLE payments (
    id UUID PRIMARY KEY,
    idempotency_key TEXT NOT NULL UNIQUE,
    order_id UUID NOT NULL,
    amount_cents INTEGER NOT NULL,
    status TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- 重试同一个逻辑请求时,唯一键保证不会创建第二笔业务支付
INSERT INTO payments (id, idempotency_key, order_id, amount_cents, status)
VALUES (
    gen_random_uuid(),
    'pay-order-0001-v1',
    '00000000-0000-0000-0000-000000000001',
    1299,
    'pending'
)
ON CONFLICT (idempotency_key) DO NOTHING;

目标不是消灭重试,而是让重试只恢复未完成的工作,不制造新的订单、支付、工单或发货动作。

T:Trace Everything,让每个重要决定留下证据

三天后,客户询问一次 AI 决定为什么发生。系统至少应该能够回答:使用了哪个模型版本、检索了哪些文档、实际发送了什么 prompt、当时工作流处于什么状态、谁批准了动作,以及外部系统返回了什么结果。

建议为每个工作流建立可关联的 trace_id,并记录:

  • 输入和关键业务标识。
  • 模型名称、版本与参数。
  • 检索到的文档 ID、版本和排序信息。
  • 实际使用的 prompt 模板版本。
  • 每一步的开始时间、结束时间、状态和重试次数。
  • 外部调用、幂等键和返回结果摘要。
  • 人工审批者以及最终业务结果。

需要注意数据治理边界。完整保存 prompt、文档内容或模型输出可能包含个人信息和商业机密,生产系统应按敏感等级脱敏、加密、设置保留期限,并限制审计数据访问权限。可观测性必须同时满足可追溯性和合规性。

ORBIT 与 OWNS、CALM 的关系

ORBIT 关注的是执行层,但它并不是孤立的方法论。

  • OWNS 解决战略选择:是否应该基于某个平台构建,成本、生态、议价风险和监管风险是否可控。
  • CALM 解决平台准备度:平台在可变更性、保障能力、杠杆能力和可度量性方面,是否能承载生产 AI。
  • ORBIT 解决日常执行:真正运行在平台上的工作流,能否在失败、重试和并发条件下可靠完成,并且事后可解释。

三者对应三个不同问题:是否应该在这里构建,平台是否已经准备好,以及运行中的动作是否值得信任。平台正确、战略选择合理,并不自动意味着工作流可靠;执行层仍需要单独设计和验证。

用五个问题做一次评估

可以把 ORBIT 转成一张工程和管理团队都能使用的检查表:

原则 评估问题
Outbox First 事务提交后,业务意图是否可能丢失?
Rate & Shared State 多个 worker 是否可能争抢或重复拥有下一步动作?
Background 用户断开连接或服务重启后,工作能否继续?
Idempotency 重试是否可能产生重复业务结果?
Trace Everything 六个月后,是否仍能解释一次重要 AI 决策?

一个“否”通常对应一项明确的工程投资。多个“否”则说明执行层需要重新设计,继续增加模型能力可能只会扩大故障影响面。

不要把 ORBIT 变成过度工程

并不是所有 AI 功能都需要五项原则达到同等强度。一个只给单个用户生成摘要、没有外部副作用、重复运行成本很低的内部工具,通常不需要完整的 outbox 和幂等体系。

应用 ORBIT 时,可以根据两个维度判断投入:

  • 工作流对外部世界的作用有多强:只读展示、修改记录、发送通信、扣款或触发其他系统,风险逐步上升。
  • 结果持续时间和纠错成本有多高:容易发现且容易撤销的错误,风险低于数天后才被发现的重复扣款或静默丢单。

对每条工作流逐项问“它会遭遇哪一种失败”,再针对实际风险建设机制,通常比所有系统统一套用完整框架更合理。

结语:可靠 AI 是可靠结果,而不只是好模型

组织最终信任的不是模型本身,而是可验证、可恢复、可解释的业务结果。一个推理质量很高的模型,如果运行在会丢失意图、重复扣款、依赖浏览器连接且无法解释决策的执行层上,它仍然不是可靠的生产 AI。

ORBIT 的核心提醒很具体:先持久化行动意图,协调共享状态,让后台工作流成为真正的执行单元,从第一天开始设计幂等重试,并为重要决定保留完整证据。模型负责提出决定,执行系统负责把决定可靠地变成结果,并在很久以后仍然说明结果为何发生。


相关推荐