使用 Strands 构建下一代语音助理

发布: (2026年1月8日 GMT+8 19:35)
12 min read
原文: Dev.to

Source: Dev.to

简介

在当今节奏极快的技术环境中,新框架几乎每天都有发布。真正的挑战不仅是跟上步伐——而是决定哪些工具真的值得你投入 深度探索 的时间。

如果你已经听说过 Strands Agents 以及它们的新双向流(BidiAgent),那么本指南适合你。我会用通俗的语言拆解这个特性,探讨实时语音助手等真实案例,并客观评估其缺点。阅读完后,你将清楚它是否适合你的下一个高并发项目。

Voice‑controlled concierge

Strands Agents

Strands Agents 是由 AWS 开发的开源 SDK,简化了可扩展 AI 代理的构建。虽然它起源于 AWS 生态系统,但并非“围墙花园”。你并不局限于 Amazon Bedrock;该框架完全 model‑agnostic,意味着你可以将其与其他云提供商集成,甚至使用 Ollama 在本地运行。

Strands Agents 双向流式 (实验)

通常我们通过“乒乓”式的文字交互与 AI 沟通:你发送一条信息,等待,然后代理回复。全新的 Bidirectional Streaming 功能(目前为实验性)颠覆了这种模式。

想象一下像…好吧,人类般的对话。通过利用全双工通信,你现在可以实时通过语音与代理进行交互 实时

  • 与传统的将 Speech‑to‑Text 与 Text‑to‑Speech 模型链(常常感觉延迟)不同,Strands 使用原生 speech‑to‑speech 模型,如 Amazon Nova Sonic。
  • 这降低了延迟和成本,使代理能够 倾听说话 同时进行。
  • 结果是?你终于可以像在自然对话中打断朋友一样,打断你的 AI 助手(此功能称为 “barge‑in”)。

用例

双向流从“酷炫技术”何时转变为必备工具?下面列举了两个高影响场景,Strands BidiAgent 将令人沮丧的任务转化为流畅的对话。

用例 1 – 停车位助理

问题 – “机器界面”障碍
我们都有过这种经历:在巨大的多层停车场里徘徊,完全忘记把车停在哪里了。有些高端商场设有数字自助终端,但体验往往令人沮丧。你必须找到机器,操作笨拙的触摸屏界面,还要手动输入车牌号。这种冷冰冰的机械交互迫使你停下来,用机器的方式“与之对话”。

解决方案 – 对话式环境
借助双向流,你只需像有一位贴心礼宾站在身旁一样对系统说话。交互流畅、实时——最重要的是,它不会让人感觉像在与机器进行交易。

示例对话

User: “我完全找不到车了——能帮我找一下吗?”
System: “当然可以!请告诉我你的车牌号码。”
User: “是 EHU 62E。”
System: “好的。你其实在商场的另一侧,还需要走一段路。先往右边的电梯走,然后——”
User (打断): “等一下,是星巴克旁边的电梯吗?”
System: “没错!穿过星巴克,左转到出口,你的车就在右手边的第五辆。”

为何这是一场变革 – 在传统 AI 设置中,系统必须先完整输出一段指示,你才能提出澄清。使用 Strands BidiAgent 时,系统会即时“听到”你的打断并转向对话,将僵硬的数据库查询转变为类似人类的帮助。

如何将这段对话实现——无论是通过实体装置、集成音频,还是定制硬件——才是创新的真正所在。

用例 2 – 互动式商场导览

问题 – “静态迷宫”
大多数商场仍依赖静态或半互动的“您所在位置”指示牌。使用这些指示牌就像在期待 GPS 的世界里翻看纸质地图。你必须先确定方向,浏览约 200 家店铺的列表,然后在脑中规划路线。摩擦感强,常常导致更大的困惑。

解决方案 – 用 BidiAgent 升级边缘
我们不必更换整个指示牌,而是为 2026 年“升级”。只需在指示牌上安装 Jetson Nano 等系统级芯片(SoC),并加装简易的麦克风/扬声器阵列,就能把静态指示牌转变为由 Strands BidiAgent 驱动的语音优先助理。

示例对话

User: “我在找星巴克……好像在三层?”
System (在用户停顿时即时响应): “其实你很走运!它更近,就在右边的电梯到二层。”
User: “等一下,是靠近喷泉的那家吗?”
System: “没错。你出来后左转,星巴克就在你面前。”

为何这能取胜 – 在边缘运行 speech‑to‑speech (S2S) 模型或低延迟流式处理后,“地图”变成了主动的向导。它消除了触摸屏的需求(更卫生、更易访问),在机器主导的环境中提供以人为本的交互界面。

我已经实际构建了一个原型来展示真实场景的效果。下面就是该用例的可运行示例。

商场助理实战 – 利用 Strands 与双向音频循环

实用示例:店铺位置助理

import asyncio
from strands.experimental.bidi import BidiAgent, BidiAudioIO
from strands.experimental.bidi.io import BidiTextIO
from strands.experimental.bidi.models import BidiNovaSonicModel
from strands import tool
from strands_tools import calculator, current_time

# Create a bidirectional streaming model
model = BidiNovaSonicModel()

# Define a custom tool
@tool
def get_shop_location(shop: str) -> str:
    """
    Get the shop location for a given shop name.

    Args:
        shop: Name of the shop to locate

    Returns:
        A string with the directions to find the shop.
    """
    print("get_shop_location called with shop:", shop)
    # In a real application, call the location API that returns these instructions
    locations = {
        "starbucks": (
            "Take the elevator at your right, go to the second floor and turn left "
            "in that hall – you will find it on the right."
        ),
        "apple store": (
            "Go straight ahead from the main entrance, take the escalator to the "
            "first floor, and it's on your left."
        ),
        "food court": (
            "Head to the centre of the mall, take the stairs to the third floor, "
            "and you'll see it right in front of you."
        ),
        "bookstore": (
            "From the main entrance, turn right and walk past the clothing stores; "
            "it's next to the toy store."
        ),
    }
    if shop.lower() in locations:
        print("Found location for shop:", shop)
        return locations[shop.lower()]
    else:
        return "Sorry, we don't have that shop in the mall."

# Create the agent
agent = BidiAgent(
    model=model,
    tools=[calculator, current_time, get_shop_location],
    system_prompt=(
        "You are a mall assistant that helps people find any shop in a mall. "
        "Keep responses concise and natural."
    ),
)

# Set up audio I/O for microphone and speakers
audio_io = BidiAudioIO()
text_io = BidiTextIO()

# Run the conversation
async def main():
    await agent.run(
        inputs=[audio_io.input()],
        outputs=[audio_io.output(), text_io.output()],
    )

asyncio.run(main())

注意: 店铺位置在工具内部是硬编码的。在此使用场景中,这是一种刻意的选择:商场的地图是静态的,硬编码可以实现 100 % 的准确率几乎为零的延迟。虽然也可以接入外部 API,或使用带有数字地图的检索增强生成(RAG)方法,但这些方式会增加成本并提升模型“幻觉”出错误指引的风险。对于客流量大的商场而言,简单的本地“真相来源”往往是最稳健的解决方案。

演示视频: (在此嵌入或链接视频)

挑战:应对环境噪声

没有任何实验性功能是没有成长痛苦的。在测试过程中,我遇到了一个重大障碍:白噪声敏感性

双向流式传输旨在实现自然对话,并且会持续监听“抢话”(即用户打断 AI)。如果电脑风扇启动,内置麦克风会把那种嗡嗡声当作抢话,导致代理在句子中途停止。

关于 Nova Sonic 版本的技术说明

  • 当前状态: 在撰写本文时,Strands 集成主要针对 nova‑sonic‑v1 进行优化。该版本缺少细粒度设置来调整“抢话阈值”。
  • 未来计划: 即将推出的 nova‑sonic‑v2 将提供更好的噪声抑制和灵敏度配置。

实际部署(例如我们的商场助理)该怎么做:

  1. 使用高质量的指向性麦克风,
  2. 等待 Nova Sonic v2 更广泛的集成,
  3. 切换到已经提供可调灵敏度的供应商(例如 OpenAI 的实时语音模型)。

Source:

结论:未来是对话式的

我们正从点击按钮转向自然对话。虽然双向流式仍属实验阶段——尤其在敏感度方面——但让技术具有人性化的潜力是巨大的。从更智能的商场导览到交互式工业助理,这一从“文本输入/文本输出”到“实时对话”的转变是下一个前沿。

这些实现的复杂性——尤其是涉及 Jetson Nano 等硬件或调节模型敏感度时——才是真正的工作起点。如果你对将这种“人类体验”带入你的硬件或项目感兴趣,欢迎交流。我正积极探索这些架构,愿意帮助你理清构建下一个智能代理的细节。

Back to Blog

相关文章

阅读更多 »