亚马逊 Alexa

amazon-alexa
分类通用
作者Agentic Awesome Skills 社区
许可MIT
评分4.40/5
使用13.1K

AMAZON ALEXA — 基于 Claude 的智能语音

概述

与 Amazon Alexa 的完整集成,用于创建智能语音技能,将 Alexa 转换为以 Claude 为大脑的助手(Auri 项目),并与 AWS 生态系统(Lambda, DynamoDB, Polly, Transcribe, Lex, Smart Home)集成。

何时使用此技能

  • 当你需要该领域的专业协助时

何时不要使用此技能

  • 任务与 Amazon Alexa 无关时
  • 更简单、更具体的工具可以处理该请求时
  • 用户需要无需领域专业知识的通用协助时

工作原理

> 你是 Alexa 和 AWS Voice 专家。使命:使用 Claude 作为 LLM 后端,结合神经语音、持久化记忆和智能家居控制,将任何 Alexa 设备转换为超智能助手。核心项目:AURI。

---

1. 生态系统概览

code
[Alexa 设备] → [Alexa 云] → [AWS Lambda] → [Claude API]
    语音          转录          逻辑          智能
      ↑               ↑               ↑                ↑
    用户           意图          处理器          Anthropic
                               + DynamoDB
                               + Polly TTS
                               + APL 视觉

Auri 架构组件

| 组件 | AWS 服务 | 功能 |
|-----------|-------------|--------|
| 语音 → 文本 | Alexa 原生 ASR | 语音识别 |
| NLU | ASK 交互模型 + Lex V2 | 提取意图 (Intent) 和槽位 (Slots) |
| 后端 | AWS Lambda (Python/Node.js) | 逻辑与编排 |
| LLM | Claude API (Anthropic) | 智能与响应 |
| 持久化 | Amazon DynamoDB | 历史记录与偏好 |
| 文本 → 语音 | Amazon Polly (neural) | Auri 的自然语音 |
| 视觉界面 | APL (Alexa Presentation Language) | Echo Show 屏幕显示 |
| 智能家居 | Alexa Smart Home API | 设备控制 |
| 自动化 | Alexa Routines API | 智能例程 |

---

2.1 前置条件

bash
## Ask Cli

npm install -g ask-cli
ask configure

Aws Cli

pip install awscli
aws configure

使用模板创建技能

ask new \
--template hello-world \
--skill-name auri \
--language pt-BR

└── .Ask/Ask-Resources.Json

code
## 2.3 配置调用名称 (Invocation Name)

models/pt-BR.json 文件中:

json
{
"interactionModel": {
"languageModel": {
"invocationName": "auri"
}
}
}
code
---

3.1 Auri 的核心意图 (Intents)

json { "interactionModel": { "languageModel": { "invocationName": "auri", "intents": [ {"name": "AMAZON.HelpIntent"}, {"name": "AMAZON.StopIntent"}, {"name": "AMAZON.CancelIntent"}, {"name": "AMAZON.FallbackIntent"}, { "name": "ChatIntent", "slots": [{"name": "query", "type": "AMAZON.SearchQuery"}], "samples": [ "{query}", "me ajuda com {query}", "quero saber sobre {query}", "o que voce sabe sobre {query}", "explique {query}", "pesqu"
code
ise {query}"
          ]
        },
        {
          "name": "SmartHomeIntent",
          "slots": [
            {"name": "device", "type": "AMAZON.Room"},
            {"name": "action", "type": "ActionType"}
          ],
          "samples": [
            "{action} a {device}",
            "controla {device}",
            "acende {device}",
            "apaga {device}"
          ]
        },
        {
          "name": "RoutineIntent",
          "slots": [{"name": "routine", "type": "RoutineType"}],
          "samples": [
            "ativa rotina {routine}",
            "executa {routine}",
            "modo {routine}"
          ]
        }
      ],
      "types": [
        {
          "name": "ActionType",
          "values": [
            {"name": {"value": "liga", "synonyms": ["acende", "ativa", "liga"]}},
            {"name": {"value": "desliga", "synonyms": ["apaga", "desativa", "desliga"]}}
          ]
        },
        {
          "name": "RoutineType",
          "values": [
            {"name": {"value": "bom dia", "synonyms": ["acordar", "manhã"]}},
            {"name": {"value": "boa noite", "synonyms": ["dormir", "descansar"]}},
            {"name": {"value": "trabalho", "synonyms": ["trabalhar", "foco"]}},
            {"name": {"value": "sair", "synonyms": ["saindo", "goodbye"]}}
          ]
        }
      ]
    }
  }
}

---

4.1 Python 主处理器

python
import os
import time
import anthropic
import boto3
from ask_sdk_core.skill_builder import SkillBuilder
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_intent_name, is_request_type
from ask_sdk_model import Response
from ask_sdk_dynamodb_persistence_adapter import DynamoDbPersistenceAdapter

============================================================

@sb.request_handler(can_handle_func=is_request_type("LaunchRequest"))
def launch_handler(handler_input: HandlerInput) -> Response:
attrs = handler_input.attributes_manager.persistent_attributes
name = attrs.get("name", "")
greeting = f"你好{', ' + name if name else ''}!我是 Auri。有什么我可以帮你的?"
return (handler_input.response_builder
.speak(greeting).ask("有什么我可以帮你的?").response)

@sb.request_handler(can_handle_func=is_intent_name("ChatIntent"))
def chat_handler(handler_input: HandlerInput) -> Response:
try:
# 获取查询内容
slots = handler_input.request_envelope.request.intent.slots
query = slots["query"].value if slots.get("query") else None
if not query:
return (handler_input.response_builder
.speak("能请你重复一遍吗?我没听清楚。").ask("能请你重复一遍吗?").response)

# 加载历史记录
attrs = handler_input.attributes_manager.persistent_attributes
history = attrs.get("history", [])

# 构建发送给 Claude 的消息
messages = history[-MAX_HISTORY:]
messages.append({"role": "user", "content": query})

# 调用 Claude
client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
response = client.messages.create(
model=CLAUDE_MODEL,
max_tokens=512,
system=AURI_SYSTEM_PROMPT,
messages=messages
)
reply = response.content[0].text

# 截断以避免超时
if len(reply) > MAX_RESPONSE_CHARS:
reply = reply[:MAX_RESPONSE_CHARS] + "... 需要我继续吗?"

# 保存历史记录


python
history.append({"role": "user", "content": query})
history.append({"role": "assistant", "content": reply})
attrs["history"] = history[-50:] # 保留最后 50 条
handler_input.attributes_manager.persistent_attributes = attrs
handler_input.attributes_manager.save_persist

4.2 Lambda 环境变量

code
ANTHROPIC_API_KEY=sk-...  (存储在 Secrets Manager 中)
DYNAMODB_TABLE=auri-users
AWS_REGION=us-east-1

4.3 Requirements.Txt

code
ask-sdk-core>=1.19.0
ask-sdk-dynamodb-persistence-adapter>=1.19.0
anthropic>=0.40.0
boto3>=1.34.0

---

5.1 创建表

bash
aws dynamodb create-table \
  --table-name auri-users \
  --attribute-definitions AttributeName=userId,AttributeType=S \
  --key-schema AttributeName=userId,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST \
  --region us-east-1

5.2 用户 Schema

json
{
  "userId": "amzn1.ask.account.XXXXX",
  "name": "Joao",
  "history": [
    {"role": "user", "content": "..."},
    {"role": "assistant", "content": "..."}
  ],
  "preferences": {
    "language": "pt-BR",
    "voice": "Vitoria",
    "personality": "assistente profissional"
  },
  "smartHome": {
    "devices": {},
    "routines": {}
  },
  "updatedAt": 1740960000,
  "ttl": 1748736000
}

5.3 自动 TTL (过期旧数据)

python
import time

保存时添加 180 天的 TTL

attrs["ttl"] = int(time.time()) + (180 * 24 * 3600)

---

6.1 可用语音 (葡萄牙语)

| 语音 | 语言 | 类型 | 推荐 |
|-------|--------|------|-------------|
| Vitoria | pt-BR | Neural | ✅ Auri PT-BR |
| Camila | pt-BR | Neural | 备选 |
| Ricardo | pt-BR | Standard | 男性 |
| Ines | pt-PT | Neural | 葡萄牙 |

6.2 在响应中集成 Polly

python
import boto3
import base64

def synthesize_polly(text: str, voice_id: str = "Vitoria") -> str:
"""返回用于 Alexa 的 Polly 音频 URL。"""
client = boto3.client("polly", region_name="us-east-1")
response = client.synthesize_speech(
Text=text,
OutputFormat="mp3",
VoiceId=voice_id,
Engine="neural"
)
# 保存到 S3 并返回 URL
# (在 Alexa 中使用自定义音频所必需)
return upload_to_s3(response["AudioStream"].read())

def speak_with_polly(handler_input, text, voice_id="Vitoria"):
"""通过 SSML 使用自定义 Polly 语音返回响应。"""
audio_url = synthesize_polly(text, voice_id)
ssml = f'<speak><audio src="{audio_url}"/></speak>'
return handler_input.response_builder.speak(ssml)

6.3 用于语音控制的 SSML

xml
<speak>
  <prosody rate="90%" pitch="+5%">
    Oi! Eu sou a Auri.
  </prosody>
  <break time="0.5s"/>
  <emphasis level="moderate">Como posso ajudar?</emphasis>
</speak>

---

7.1 聊天模板

json
{
  "type": "APL",
  "version": "2023.3",
  "theme": "dark",
  "mainTemplate": {
    "parameters": ["payload"],
    "items": [{
      "type": "Container",
      "width": "100%",
      "height": "100%",
      "backgroundColor": "#1a1a2e",
      "items": [
        {
          "type": "Text",
          "text": "AURI",
          "fontSize": "32px",
          "color": "#e94560",
          "textAlign": "center",
          "paddingTop": "20px"
        },
        {
          "type": "Text",
          "text": "${payload.lastResponse}",
          "fontSize": "24px",
          "color": "#ffffff",
          "padding": "20px",
          "maxLine
s": 8, "grow": 1 }, { "type": "Text", "text": "说点什么继续...", "fontSize": "18px", "color": "#888888", "textAlign": "center", "paddingBottom": "20px" } ] }] } }
code
### 7.2 在响应中添加 APL
python @sb.request_handler(can_handle_func=is_intent_name("ChatIntent")) def chat_with_apl(handler_input: HandlerInput) -> Response: # ... 获取 Claude 的回复 ...

# 检查设备是否支持 APL
supported = handler_input.request_envelope.context.system.device.supported_interfaces
has_apl = getattr(supported, "alexa_presentation_apl", None) is not None

if has_apl:
apl_directive = {
"type": "Alexa.Presentation.APL.RenderDocument",
"token": "auri-chat",
"document": CHAT_APL_DOCUMENT,
"datasources": {"payload": {"lastResponse": reply}}
}
handler_input.response_builder.add_directive(apl_directive)

return handler_input.response_builder.speak(reply).ask("还有其他需要帮忙的吗?").response

code
---

8.1 激活智能家居 Skill

skill.json 中添加:

json
{
"apis": {
"smartHome": {
"endpoint": {
"uri": "arn:aws:lambda:us-east-1:123456789:function:auri-smart-home"
}
}
}
}
code
### 8.2 智能家居 Handler
python
def handle_smart_home_directive(event, context):
namespace = event["directive"]["header"]["namespace"]
name = event["directive"]["header"]["name"]
endpoint_id = event["directive"]["endpoint"]["endpointId"]

if namespace == "Alexa.PowerController":
state = "ON" if name == "TurnOn" else "OFF"
# 调用你的智能家居 API
control_device(endpoint_id, {"power": state})
return build_smart_home_response(endpoint_id, "powerState", state)

elif namespace == "Alexa.BrightnessController":
brightness = event["directive"]["payload"]["brightness"]
control_device(endpoint_id, {"brightness": brightness})
return build_smart_home_response(endpoint_id, "brightness", brightness)

code
### 8.3 设备发现 (Discovery)
python
def handle_discovery(event, context):
return {
"event": {
"header": {
"namespace": "Alexa.Discovery",
"name": "Discover.Response",
"payloadVersion": "3"
},
"payload": {
"endpoints": [
{
"endpointId": "light-sala-001",
"friendlyName": "客厅灯",
"displayCategories": ["LIGHT"],
"capabilities": [
{
"type": "AlexaInterface",
"interface": "Alexa.PowerController",
"version": "3"
},
{
"type": "AlexaInterface",
"interface": "Alexa.BrightnessController",
"version": "3"
}
]
}
]
}
}
}
code
---

完整部署 (Skill + Lambda)

cd auri/
ask deploy

检查状态

ask status

在模拟器中测试

ask dialog --locale pt-BR

特定 Intent 测试

ask simulate \
--text "abrir aur
i" \
--locale pt-BR \
--skill-id amzn1.ask.skill.YOUR-SKILL-ID

手动创建 Lambda

aws lambda create-function \
--function-name auri-skill \
--runtime python3.11 \
--role arn:aws:iam::ACCOUNT:role/auri-lambda-role \
--handler lambda_function.handler \
--timeout 8 \
--memory-size 512 \
--zip-file fileb://function.zip

添加 Alexa 触发器

aws lambda add-permission \
--function-name auri-skill \
--statement-id alexa-skill-trigger \
--action lambda:InvokeFunction \
--principal alexa-appkit.amazon.com \
--event-source-token amzn1.ask.skill.YOUR-SKILL-ID

code
## 使用 Secrets Manager

aws secretsmanager create-secret \
--name auri/anthropic-key \
--secret-string '{"ANTHROPIC_API_KEY": "sk-..."}'

Lambda 通过 SDK 访问:

import boto3, json
def get_secret(secret_name):
client = boto3.client('secretsmanager')
response = client.get_secret_value(SecretId=secret_name)
return json.loads(response['SecretString'])

---

第一阶段 — 环境搭建 (第 1 天)

code
[ ] 创建 Amazon Developer 账号
[ ] 配置 AWS 账号 (免费套餐)
[ ] 安装并配置 ASK CLI
[ ] 创建具有 Lambda, DynamoDB, Polly, Logs 权限的 IAM Role
[ ] 将 Anthropic API 密钥存储在 Secrets Manager 中

第二阶段 — 技能基础 (第 2-3 天)

code
[ ] ask new --template hello-world --skill-name auri
[ ] 定义交互模型 (pt-BR.json)
[ ] LaunchRequest 处理程序运行正常
[ ] 集成 Claude 的 ChatIntent 处理程序运行正常
[ ] ask deploy 部署成功
[ ] 在 ASK 模拟器中进行基础测试

第三阶段 — 数据持久化 (第 4 天)

code
[ ] 创建 DynamoDB 表
[ ] 历史记录持久化功能运行正常
[ ] 配置 TTL (生存时间)
[ ] 保存用户偏好设置

第四阶段 — Polly + APL (第 5-6 天)

code
[ ] 集成 Polly 语音 Vitoria (neural)
[ ] 创建 APL 聊天模板
[ ] 在 Echo Show 模拟器中渲染 APL

第五阶段 — 智能家居 (可选)

code
[ ] 启用智能家居技能
[ ] 设备发现功能运行正常
[ ] 实现 PowerController
[ ] 使用真实设备测试

第六阶段 — 发布

code
[ ] 完成所有功能的全面测试
[ ] 性能达标 (超时 < 8s)
[ ] 提交 Amazon 认证
[ ] 在 Alexa Skills Store 发布

---

11. 快速命令

| 操作 | 命令 |
|------|---------|
| 创建技能 | ask new --template hello-world |
| 部署 | ask deploy |
| 模拟 | ask simulate --text "abre a auri" |
| 交互对话 | ask dialog --locale pt-BR |
| 查看日志 | ask smapi get-skill-simulation |
| 验证模型 | ask validate --locales pt-BR |
| 导出技能 | ask smapi export-package --skill-id ID |
| 列出技能 | ask list skills |

---

12. 参考资料

  • 完整 Python 模板: assets/boilerplate/lambda_function.py
  • PT-BR 交互模型: assets/interaction-models/pt-BR.json
  • APL 聊天模板: assets/apl-templates/chat-interface.json
  • 智能家居示例: references/smart-home-api.md
  • ASK SDK Python 文档: https://github.com/alexa/alexa-skills-kit-sdk-for-python
  • Claude + Alexa 指南: https://www.anthropic.com/news/claude-and-alexa-plus

最佳实践

  • 提供关于项目和需求的清晰、具体的上下文
  • 在将建议应用于生产代码之前,请审查所有建议
  • 结合其他互补技能进行全面分析

常见陷阱

  • 将此技能用于其专业领域之外的任务
  • 在不了解具体上下文的情况下直接应用建议
  • 未提供
足够的项目上下文以进行准确分析

局限性

  • 仅在任务明确符合上述范围时使用此技能。
  • 不要将输出结果视为针对特定环境的验证、测试或专家评审的替代方案。
  • 如果缺少必要的输入、权限、安全边界或验收标准,请停止操作并请求澄清。