让补货自动闭环:用 MMF、Databricks Genie 和 Amazon Quick 把预测变成订单

2026-09-14 13 预计阅读时间: 1 分钟
来源: aws.amazon.com 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.

预计阅读时间:12 分钟

基础模型已经让“给整个商品目录做需求预测”变得相对容易,但预测本身不会让货架恢复库存。真正棘手的是下一步:识别需求激增、核对供应商的实时可供货量、决定补多少,并在条件满足时自动下单。

这篇文章讨论一种部署在 Databricks 和 Amazon Quick 上的闭环:检测需求变化,做出补货决策,执行采购动作;只有没有任何供应商能够覆盖需求时,才升级给人工处理。

从预测结果走向可执行决策

可以把补货流程拆成三类事实:

  • 需求事实:未来窗口内的预测需求、当前库存、已承诺订单和安全库存。
  • 供应事实:供应商当前可供数量、交期、最低起订量和价格。
  • 执行事实:是否已经创建采购订单、是否需要人工审批、异常是否已关闭。

预测模型只负责提供需求信号。后续系统还必须回答三个问题:

  1. 这次变化是不是足以构成需求激增?
  2. 哪个供应商能在目标交期内覆盖缺口?
  3. 这次动作可以无人值守执行,还是必须交给采购人员?

MMF 可以用于生成目录级预测,Databricks 负责组织数据、运行规则和保存决策结果,Genie 适合让业务人员用自然语言查询补货状态,Amazon Quick 则可以承载面向运营团队的分析和行动入口。关键不是把这些工具简单串联,而是让每个动作都能回溯到预测、库存和供应商数据。

一条可审计的 detect-decide-act 链路

一个实用的闭环可以按下面的顺序运行:

1. Detect:识别需求激增和库存缺口

将最新预测与基线预测或历史需求进行比较。例如,未来 14 天预测需求比基线高出 30%,并且可用库存低于需求加安全库存,就生成一个 replenishment event。

这里不要只看预测增幅。促销、季节性和数据延迟都可能造成假警报,因此事件中应保存预测版本、计算时间和输入数据时间窗。

2. Decide:把缺口与供应能力对齐

缺口可以用一个透明的公式计算:

replenishment_qty = max(
    forecast_demand + safety_stock - on_hand - inbound_confirmed,
    0
)

然后根据交期、可供数量、最低起订量和供应商优先级排序。若一个供应商无法覆盖全部缺口,可以按策略拆分订单;若所有合格供应商的总可供量仍然不足,就产生人工升级事件。

3. Act:创建订单或升级异常

自动动作必须具备幂等性。相同的事件重复执行时,不能创建两张采购订单。实践中可以使用 event_id 作为幂等键,并把 plannedorderedescalated 等状态写回 Delta 表或其他审计存储。

一个可以改造的补货决策示例

下面的 Python 示例是一个最小的服务端决策骨架。它不绑定具体供应商 API:/availability/purchase-orders 是示例接口,运行前需要替换成企业实际的供应商网关。预测和库存数据也可以改成从 Databricks SQL Warehouse 查询。

from dataclasses import dataclass
from typing import List, Optional
import os
import requests

SUPPLIER_API = os.environ.get("SUPPLIER_API", "https://supplier-gateway.example")
PURCHASE_API = os.environ.get("PURCHASE_API", "https://procurement.example")

@dataclass
class SupplierOffer:
    supplier_id: str
    available_qty: int
    lead_time_days: int
    unit_price: float


def required_qty(forecast_demand: int, safety_stock: int,
                 on_hand: int, inbound_confirmed: int) -> int:
    return max(forecast_demand + safety_stock - on_hand - inbound_confirmed, 0)


def get_offers(sku: str, needed_qty: int) -> List[SupplierOffer]:
    response = requests.get(
        f"{SUPPLIER_API}/availability",
        params={"sku": sku, "quantity": needed_qty, "max_lead_time_days": 14},
        timeout=10,
    )
    response.raise_for_status()
    return [SupplierOffer(**item) for item in response.json()["offers"]]


def create_order(event_id: str, sku: str, supplier_id: str, quantity: int) -> dict:
    response = requests.post(
        f"{PURCHASE_API}/purchase-orders",
        headers={"Idempotency-Key": event_id},
        json={
            "event_id": event_id,
            "sku": sku,
            "supplier_id": supplier_id,
            "quantity": quantity,
            "source": "automated-replenishment",
        },
        timeout=10,
    )
    response.raise_for_status()
    return response.json()


def decide_and_act(event: dict) -> dict:
    needed = required_qty(
        event["forecast_demand"],
        event["safety_stock"],
        event["on_hand"],
        event["inbound_confirmed"],
    )

    if needed == 0:
        return {"status": "no_action", "sku": event["sku"], "quantity": 0}

    offers = sorted(
        get_offers(event["sku"], needed),
        key=lambda x: (x.lead_time_days, x.unit_price),
    )

    remaining = needed
    orders = []
    for offer in offers:
        quantity = min(remaining, offer.available_qty)
        if quantity <= 0:
            continue
        order = create_order(
            event["event_id"], event["sku"], offer.supplier_id, quantity
        )
        orders.append(order)
        remaining -= quantity
        if remaining == 0:
            break

    if remaining > 0:
        return {
            "status": "escalated",
            "sku": event["sku"],
            "needed": needed,
            "covered": needed - remaining,
            "uncovered": remaining,
            "orders": orders,
            "reason": "no eligible supplier can cover the full surge",
        }

    return {
        "status": "ordered",
        "sku": event["sku"],
        "quantity": needed,
        "orders": orders,
    }


if __name__ == "__main__":
    sample_event = {
        "event_id": "surge-2025-001-ABC123",
        "sku": "ABC123",
        "forecast_demand": 1200,
        "safety_stock": 200,
        "on_hand": 350,
        "inbound_confirmed": 100,
    }
    print(decide_and_act(sample_event))

这个示例有几个值得保留的边界:

  • 供应商可供量来自实时接口,而不是预测快照。
  • 订单请求带有幂等键,避免重试造成重复采购。
  • 供应量不足时不会“猜测”一个供应商,而是明确返回 escalated
  • 每个事件都带有 event_id,便于在 Databricks 中追踪输入、决策和结果。

如果业务允许拆单,还需要在代码中加入最低起订量、包装倍数、预算上限和供应商配额等约束。示例中的逐家分配逻辑只是起点,不能直接替代企业采购策略。

用 Genie 和 Amazon Quick 让人看懂自动化结果

自动化并不意味着采购团队失去可见性。相反,系统应该把决策过程做成可以查询和解释的记录。

可以在 Databricks 中保存一张类似下面的决策表:

CREATE TABLE IF NOT EXISTS replenishment_decisions (
  event_id STRING,
  sku STRING,
  detected_at TIMESTAMP,
  forecast_demand INT,
  on_hand INT,
  inbound_confirmed INT,
  required_qty INT,
  supplier_coverage INT,
  status STRING,
  reason STRING,
  order_ids ARRAY<STRING>
) USING DELTA;

在这张表之上,可以让 Genie 回答类似问题:

过去 24 小时有哪些 SKU 因供应不足而升级?
按供应商汇总未覆盖数量,并列出预计缺货日期。
哪些自动采购订单的供应商交期超过了目标窗口?

Amazon Quick 的页面则可以围绕运营动作组织,而不是只展示一张预测折线图。例如展示:

  • 当前待处理的需求激增事件;
  • 已自动下单金额和订单数量;
  • 因供应不足而升级的 SKU;
  • 按供应商划分的覆盖率和交期;
  • 自动化动作的失败、重试和人工接管记录。

每一张图都应能跳转到事件明细。采购人员需要知道“为什么下了这张单”,而不仅是“系统下了一张单”。

不要把预测置信度当成采购授权

闭环自动化最容易踩的坑,是把高置信度预测直接等同于可以下单。两者不是一回事。

建议至少设置以下护栏:

  • 金额上限:超过预算的订单必须人工审批。
  • 供应商白名单:只允许合同有效且通过合规检查的供应商自动接单。
  • 交期约束:供应商能供货,但无法在需求窗口内交付时,不应算作有效覆盖。
  • 库存保护:关键 SKU 不允许因为一次异常预测而消耗全部安全库存。
  • 异常回滚:供应商接口超时、重复响应或返回不一致时,暂停自动下单并升级。
  • 审计记录:保留预测版本、规则版本、供应商响应和最终订单内容。

还应定期评估三类指标:预测误差、供应覆盖率和自动动作成功率。只看缺货率,可能会让系统过度补货;只看自动化率,又可能掩盖错误订单。

落地时的一份小清单

可以按以下顺序推进,而不是一开始就让整个目录无人值守:

  1. 先选择少量 SKU 和一个可控的供应商群组。
  2. 把预测、库存、在途和供应商可供量统一到同一个事件模型。
  3. 先只生成建议订单,验证缺口计算和供应商排序。
  4. 为事件和订单加入幂等键、状态机和审计表。
  5. 让自动化只覆盖低金额、规则清晰的场景。
  6. 将“无人供应可覆盖”的事件明确路由给采购人员。
  7. 用 Genie 和 Amazon Quick 检查结果,再逐步扩大自动下单范围。

真正有价值的系统不是“预测得更复杂”,而是能把预测转成受约束、可解释、可回滚的行动。MMF 提供需求信号,Databricks Genie 和 Amazon Quick 提供查询与运营入口,供应商接口和采购系统则完成动作。只有这几部分共同形成闭环,需求激增才不会停留在报表里。


相关推荐