Natera 如何用 Amazon Bedrock AgentCore 构建低延迟语音预约智能体

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

让患者通过自然对话预约移动采血服务,看起来只是“语音识别加大模型”。真正进入生产环境后,系统却必须同时处理双向音频流、工具调用、身份验证、预约冲突和等待体验。Natera 基于 Amazon Bedrock AgentCore 构建的自动化语音智能体,将这些问题拆成双 WebSocket 桥接、事件驱动的延迟掩蔽和渐进式信任认证,并在其测试场景中实现了 100% 的工具调用准确率以及低于 7 秒的延迟。

这里值得关注的不只是模型选型,而是模型外围的工程控制面:什么事件可以立即反馈,什么操作必须经过验证,以及怎样让每一次工具调用都可检查、可拒绝、可追踪。

双 WebSocket:把实时音频与智能体执行解耦

语音预约涉及两个节奏不同的数据通道。一侧是电话或语音平台,它持续发送音频帧,也要求系统及时返回合成语音;另一侧是智能体运行时,它需要接收上下文、推理意图、调用预约工具并产生响应。

双 WebSocket 桥接可以把这两个边界隔开:

  • 面向语音平台的连接负责音频接入、打断检测和播放控制。
  • 面向 AgentCore 的连接负责智能体事件、工具调用结果和生成内容。
  • 桥接层维护会话 ID、事件顺序、背压和取消信号。
  • 结构化业务数据走工具接口,而不是混入音频传输逻辑。

关键点是不要把桥接器写成无状态的字节转发器。一次真实通话至少需要记录当前轮次、是否正在播放、患者是否打断、身份验证级别以及是否存在未完成的工具调用。否则,一句“等等,改到周五”可能在旧的预约请求已经提交之后才被处理。

下面是一个可以改造的最小 Python 桥接器。示例假设语音侧与上游智能体侧都使用 JSON WebSocket 消息;实际接入时,需要替换消息格式、鉴权头和 AgentCore 端点。

python -m venv .venv
source .venv/bin/activate
pip install websockets
export AGENT_WS_URL='wss://your-agent-runtime.example/ws'
python bridge.py
# bridge.py
import asyncio
import json
import os
import uuid

import websockets

AGENT_WS_URL = os.environ["AGENT_WS_URL"]


async def relay_voice_to_agent(voice_ws, agent_ws, session_id):
    async for raw in voice_ws:
        event = json.loads(raw)

        if event.get("type") == "audio":
            # 立即确认已收到音频,不必等待完整的模型响应。
            await voice_ws.send(json.dumps({
                "type": "activity",
                "state": "processing",
                "session_id": session_id,
            }))

        event["session_id"] = session_id
        await agent_ws.send(json.dumps(event))


async def relay_agent_to_voice(agent_ws, voice_ws):
    async for raw in agent_ws:
        event = json.loads(raw)

        # 工具参数不应直接播放给患者,也不应写入普通音频日志。
        if event.get("type") == "tool_call":
            continue

        await voice_ws.send(json.dumps(event))


async def handle_call(voice_ws):
    session_id = str(uuid.uuid4())
    async with websockets.connect(
        AGENT_WS_URL,
        additional_headers={"x-session-id": session_id},
        max_queue=32,
    ) as agent_ws:
        tasks = [
            asyncio.create_task(
                relay_voice_to_agent(voice_ws, agent_ws, session_id)
            ),
            asyncio.create_task(relay_agent_to_voice(agent_ws, voice_ws)),
        ]
        done, pending = await asyncio.wait(
            tasks, return_when=asyncio.FIRST_COMPLETED
        )
        for task in pending:
            task.cancel()
        await asyncio.gather(*pending, return_exceptions=True)
        for task in done:
            task.result()


async def main():
    async with websockets.serve(handle_call, "0.0.0.0", 8765):
        print("Voice bridge listening on ws://localhost:8765")
        await asyncio.Future()


if __name__ == "__main__":
    asyncio.run(main())

生产实现还要补上每轮超时、有限队列、断线重连策略和幂等键。不能无限缓存音频帧:下游变慢时,应明确丢弃过期的中间反馈或结束会话,而不是让患者听到几十秒前的内容。

延迟掩蔽不是伪造结果,而是尽早发出真实事件

低于 7 秒的延迟仍可能让电话另一端感到停顿。事件驱动的延迟掩蔽通过拆分响应阶段,避免让患者面对一段完全静默的等待:

  1. 语音活动事件表明系统已经听到用户说话。
  2. 意图初步确定后,可以播放“我正在查询可用时间”之类的过程反馈。
  3. 查询工具返回后,再播报真实的日期和时间段。
  4. 创建预约完成后,才给出明确的成功确认。

这里有一条重要边界:过程反馈可以提前,业务结论不能提前。“正在查询”是可验证的系统状态;“已经预约成功”必须等写操作返回并通过校验。若工具超时,智能体应该说明无法确认,而不是根据语言模型的推测补出预约编号。

延迟也应分段测量,而不是只记录整通电话的平均值。至少需要采集:语音结束到转写完成、转写完成到首个智能体事件、工具调用耗时、首个音频响应时间,以及预约确认总耗时。这样才能判断瓶颈来自网络、模型、合成语音还是排班系统。

渐进式信任:先帮用户查询,再逐步开放写操作

语音渠道不能默认“能说出姓名的人就是本人”。但如果在对话开始时要求患者一次性回答所有验证问题,又会增加放弃率。渐进式信任的做法是让权限随着验证状态提升:

  • 匿名状态可以解释服务流程和收集大致地区。
  • 基础识别后可以查询不含敏感信息的可用时间段。
  • 完成一次性验证码等强验证后,才允许创建、修改或取消预约。
  • 高风险操作可以增加二次确认,例如复述日期、地址和患者姓名后再提交。

可以这样实践一个独立于模型的工具授权层。即使模型错误地请求了 book_appointment,后端仍会拒绝未验证会话。

from dataclasses import dataclass
from enum import IntEnum


class Trust(IntEnum):
    ANONYMOUS = 0
    IDENTIFIED = 1
    VERIFIED = 2


REQUIRED_TRUST = {
    "search_slots": Trust.IDENTIFIED,
    "book_appointment": Trust.VERIFIED,
    "cancel_appointment": Trust.VERIFIED,
}


@dataclass
class Session:
    session_id: str
    trust: Trust = Trust.ANONYMOUS


def authorize_tool(session: Session, tool_name: str) -> None:
    required = REQUIRED_TRUST.get(tool_name)
    if required is None:
        raise ValueError(f"Unknown tool: {tool_name}")
    if session.trust < required:
        raise PermissionError(
            f"{tool_name} requires {required.name}; "
            f"session has {session.trust.name}"
        )


def invoke_tool(session: Session, tool_name: str, arguments: dict):
    authorize_tool(session, tool_name)
    return {
        "ok": True,
        "tool": tool_name,
        "arguments": arguments,
        "idempotency_key": f"{session.session_id}:{tool_name}:1",
    }


if __name__ == "__main__":
    call = Session("call-42", Trust.IDENTIFIED)

    print(invoke_tool(call, "search_slots", {"postal_code": "98101"}))

    try:
        invoke_tool(call, "book_appointment", {"slot_id": "slot-9"})
    except PermissionError as exc:
        print({"ok": False, "error": str(exc)})

    call.trust = Trust.VERIFIED
    print(invoke_tool(call, "book_appointment", {"slot_id": "slot-9"}))

这类控制必须位于服务端,而不是只写进系统提示词。提示词可以要求模型先验证身份,但它不是权限系统。工具网关还应验证参数模式、患者与会话的绑定关系、时段是否仍然有效,以及幂等键是否已被使用。

100% 工具调用准确率背后的工程含义

来源摘要提到的 100% 工具调用准确率,应理解为 Natera 在其定义的场景和评估集上取得的结果,而不是所有口音、噪声环境和异常输入下的普遍保证。要接近这样的稳定性,团队需要把“调用正确”拆成可测试的条件:

  • 在正确意图下选择正确工具。
  • 参数满足 JSON Schema,并完成日期、时区和地址规范化。
  • 缺少必填信息时继续询问,不猜测值。
  • 身份等级不足时不执行写操作。
  • 工具失败时不宣称成功。
  • 用户打断或修改要求时,取消旧轮次的待执行操作。

测试数据也不能只包含顺畅的预约对话。还要覆盖同音姓名、模糊日期、跨时区电话号码、重复验证码、已被占用的时段、上游超时,以及患者在确认前临时改口等情况。工具调用日志应保存决策结果和脱敏后的结构化参数,但不应记录原始验证码或不必要的医疗信息。

上线前的检查清单

采用这套架构时,可以按以下顺序控制风险:

  • 先开放只读的时段查询,再开放创建、修改和取消操作。
  • 将身份状态、工具授权和幂等控制放在确定性的服务端代码中。
  • 为双 WebSocket 通道设置队列上限、取消传播和超时预算。
  • 分别监控首事件延迟、首音频延迟、工具延迟和端到端确认延迟。
  • 用真实噪声、打断和表达歧义构建回归测试,而不只测试标准脚本。
  • 对敏感字段执行最小化采集、日志脱敏、传输加密和保留期限控制。
  • 让失败路径明确回退到人工服务,尤其是身份验证失败或预约状态不确定时。

Natera 的案例说明,可靠的语音预约智能体并不是把电话音频直接交给大模型。双 WebSocket 管住实时数据流,事件驱动反馈改善等待体验,渐进式信任限制工具权限;三者组合起来,模型才有机会在医疗预约这类高约束流程中稳定工作。


相关推荐