用 Amazon Connect 构建餐厅电话点餐 AI 主持人

2026-08-25 34 预计阅读时间: 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 分钟

餐厅电话点餐不一定需要 App、网站或用户登录。通过 Amazon Connect、实时语音能力、Amazon Connect AI agent,以及经由 MCP 暴露后端工具的 Amazon Bedrock AgentCore Gateway,可以把一通电话串成完整流程:接听来电、理解自然语言、查询菜单、确认订单,并将结果交给餐厅后端系统。

这类系统的关键不只是“让模型会聊天”,而是把电话、实时语音、业务推理和可控工具调用组织成一条可靠链路。

一通电话背后的系统分工

可以把架构拆成四层,每层解决不同问题:

  • Amazon Connect:负责电话号码、呼入路由、队列、营业时间和通话生命周期。
  • Amazon Connect Agentic Voice:负责实时语音交互,让系统能够边听边说,而不是等整段录音结束后再处理。
  • Amazon Connect AI agent:负责理解顾客意图、维护点餐上下文、追问缺失信息,以及决定什么时候调用工具。
  • Amazon Bedrock AgentCore Gateway:把菜单查询、库存检查、价格计算和订单提交等后端能力以 MCP 工具形式提供给 AI agent。

典型调用路径可以表示为:

顾客电话
  -> Amazon Connect
  -> Agentic Voice 实时语音处理
  -> Amazon Connect AI agent
  -> AgentCore Gateway / MCP tools
  -> 菜单、库存、订单和支付后端

这里的边界很重要。模型可以负责理解“我要两个辣味鸡肉汉堡,其中一个不要洋葱”,但不应该直接拼接 SQL、修改订单数据库,或自行猜测价格。涉及业务事实和状态变更的动作,都应通过经过授权的工具完成。

把点餐对话设计成状态机

自然语言很灵活,订单状态却必须明确。一个可落地的电话流程通常包含这些状态:

  1. 欢迎与识别意图:确认顾客是点餐、查询营业时间,还是咨询配送范围。
  2. 收集商品:解析商品、数量、规格、配料和备注。
  3. 补齐必要信息:当商品缺少尺寸、套餐或取餐方式时,主动追问。
  4. 复述订单:逐项读回商品和数量,展示或播报价格。
  5. 确认履约信息:收集自取或配送所需的信息。
  6. 提交订单:调用后端工具创建订单,并取得订单号。
  7. 结束通话:确认总价、取餐时间或配送信息。

AI agent 可以自由理解表达方式,但流程中的关键节点应有明确约束。例如,订单提交工具只能在顾客明确确认后调用;库存不足时,系统必须回到商品选择环节,而不是继续创建订单。

可以给 agent 一条类似这样的系统指令:

你是餐厅电话点餐助手。

规则:
1. 用简短、自然的句子回应,适合电话语音播放。
2. 每次只询问一个缺失信息。
3. 不要猜测菜单、价格、库存或营业时间,必须调用对应工具查询。
4. 在提交订单前,逐项复述商品、数量、选项、取餐方式和总价。
5. 只有顾客明确说“确认”“就这样”或同义表达后,才能调用 create_order。
6. 工具报错时,用通俗语言说明暂时无法完成,并提供转人工选项。

这类提示词不能替代后端校验,但能减少对话偏离。真正的价格、库存、门店营业状态和订单状态仍应由工具返回,并在服务端再次验证。

用 MCP 工具连接真实业务

AgentCore Gateway 的价值在于把后端能力整理成 AI 可以发现和调用的工具。可以这样规划最小工具集:

工具 作用 是否改变状态
get_menu 查询当前门店菜单、规格和价格
check_item_availability 检查商品和选项是否有库存
calculate_order_total 根据订单草稿计算价格和税费
create_order 在顾客确认后创建订单
get_store_hours 查询营业时间和预计取餐时间

工具接口应使用结构化输入和输出,而不是让模型解析一段不稳定的自然语言。例如,订单提交接口可以采用这样的 JSON:

{
  "store_id": "store-001",
  "fulfillment": {
    "type": "pickup",
    "customer_name": "Alex"
  },
  "items": [
    {
      "menu_item_id": "burger-spicy",
      "quantity": 2,
      "options": ["no-onion"]
    }
  ],
  "customer_confirmation": true
}

下面是一个可以直接运行或改造成 Lambda、容器服务处理器的 Python 示例。它演示了服务端必须做的两件事:重新计算订单金额,以及拒绝没有明确确认的订单。示例数据仅用于本地验证,生产环境应替换为菜单数据库和订单服务。

from decimal import Decimal
from typing import Any

MENU = {
    "burger-spicy": {"name": "Spicy Chicken Burger", "price": Decimal("8.50")},
    "fries": {"name": "Fries", "price": Decimal("3.00")},
}


def create_order(payload: dict[str, Any]) -> dict[str, Any]:
    if payload.get("customer_confirmation") is not True:
        raise ValueError("customer_confirmation must be true")

    total = Decimal("0")
    normalized_items = []
    for item in payload.get("items", []):
        menu_item_id = item["menu_item_id"]
        quantity = int(item["quantity"])
        if quantity < 1 or menu_item_id not in MENU:
            raise ValueError("invalid menu item or quantity")

        menu_item = MENU[menu_item_id]
        total += menu_item["price"] * quantity
        normalized_items.append({
            "menu_item_id": menu_item_id,
            "name": menu_item["name"],
            "quantity": quantity,
            "options": item.get("options", []),
            "unit_price": str(menu_item["price"]),
        })

    if not normalized_items:
        raise ValueError("order must contain at least one item")

    return {
        "order_id": "demo-order-1001",
        "store_id": payload["store_id"],
        "items": normalized_items,
        "total": str(total),
        "status": "accepted",
    }


if __name__ == "__main__":
    sample = {
        "store_id": "store-001",
        "fulfillment": {"type": "pickup", "customer_name": "Alex"},
        "items": [
            {"menu_item_id": "burger-spicy", "quantity": 2, "options": ["no-onion"]}
        ],
        "customer_confirmation": True,
    }
    print(create_order(sample))

运行方式:

python order_tool.py

在真实系统中,工具还应验证门店标识、顾客输入、幂等键、库存和权限。create_order 最好接收一个通话会话或请求 ID,避免电话重试、网络重放或模型重复调用造成重复订单。

语音体验比文本聊天更苛刻

电话交互没有屏幕,顾客无法回看购物车。因此,语音层需要控制信息密度和节奏:

  • 一次只读出有限数量的信息,长订单可以分组确认。
  • 商品名称、数量和选项使用固定表达,避免同音词造成误解。
  • 金额和订单号需要重复一次,必要时按数字分组播报。
  • 对沉默、打断、重复询问和背景噪声设置明确策略。
  • 识别失败或工具不可用时,提供转人工或回拨路径。

实时语音能力适合处理用户的打断和自然停顿,但它不应成为业务逻辑的唯一控制点。通话记录、工具调用、订单草稿和最终提交结果都应写入可观测系统,便于客服处理争议和定位失败原因。

建议至少记录以下事件:

{
  "call_id": "call-abc123",
  "event": "tool_call",
  "tool": "calculate_order_total",
  "request_id": "req-789",
  "latency_ms": 420,
  "result": "success"
}

日志中要注意脱敏。姓名、电话号码、地址和支付相关信息不应以不受控的明文形式长期保存;同时需要按门店、环境和角色限制工具访问权限。

上线前的检查清单

这套方案适合从窄场景开始,例如只支持单门店、固定菜单、自取订单和少量常见修改。验证稳定后,再逐步加入配送、优惠券、多个门店和支付流程。

上线前可以检查:

  • Connect 呼入流程是否能正确处理营业时间、排队和转人工。
  • 语音 agent 是否能处理打断、沉默、口音和重复确认。
  • AI agent 是否绝不绕过工具猜测价格或库存。
  • MCP 工具是否有输入校验、权限、超时、幂等和审计日志。
  • 订单提交前是否强制顾客确认,提交后是否播报订单号。
  • 工具失败、菜单为空和库存变化时,是否有可理解的降级路径。
  • 是否用真实通话脚本测试高频订单、复杂备注和边界输入。

Amazon Connect 解决了电话入口,Agentic Voice 解决了实时语音交互,AI agent 负责对话推理,而 AgentCore Gateway 把推理连接到可控业务工具。把这些组件组合起来时,最值得优先设计的不是更长的提示词,而是清晰的订单状态、严格的工具契约和可追踪的失败处理。这样,餐厅得到的才是一条可以运营的电话点餐链路,而不只是一个会说话的演示程序。


相关推荐