Skip to Content

14d - 语音 Agent 用例

本文是《AI Agent 实战手册》第 14 章第 4 节。 上一节:14c-AI电话Agent构建 | 下一节:14e-延迟优化与多语言

概述

语音 Agent 正在重塑企业与用户的交互方式——从 7×24 小时智能客服到自动化销售外呼,从语音驱动的开发工具到医疗预约管理,语音 AI 的落地场景远比想象中丰富。本文通过 4 个完整的实战案例(智能客服、销售外呼 Agent、语音控制开发工具、医疗预约 Agent),深入剖析每个场景的架构设计、技术选型、代码实现和成本分析,帮助你找到最适合自己业务的语音 Agent 方案。


1. 语音 Agent 用例全景

1.1 行业应用地图

语音 Agent 的应用已覆盖几乎所有需要电话或语音交互的行业:

┌─────────────────────────────────────────────────────────────────┐ │ 语音 Agent 行业应用地图 │ ├──────────────┬──────────────┬──────────────┬───────────────────┤ │ 客户服务 │ 销售营销 │ 医疗健康 │ 开发者工具 │ ├──────────────┼──────────────┼──────────────┼───────────────────┤ │ · 智能客服热线│ · 外呼销售 │ · 预约挂号 │ · 语音编程 │ │ · 订单查询 │ · 线索筛选 │ · 用药提醒 │ · 语音 DevOps │ │ · 投诉处理 │ · 预约确认 │ · 随访回访 │ · 语音数据查询 │ │ · 技术支持 │ · 满意度调查 │ · 健康咨询 │ · 语音代码审查 │ │ · FAQ 自动应答│ · 催收提醒 │ · 报告解读 │ · 语音 CI/CD 触发 │ ├──────────────┼──────────────┼──────────────┼───────────────────┤ │ 金融保险 │ 房地产 │ 教育培训 │ 餐饮零售 │ ├──────────────┼──────────────┼──────────────┼───────────────────┤ │ · 账户查询 │ · 房源推荐 │ · 课程咨询 │ · 订餐/外卖 │ │ · 理赔报案 │ · 看房预约 │ · 学习辅导 │ · 预订管理 │ │ · 贷款咨询 │ · 租约提醒 │ · 考试提醒 │ · 会员服务 │ │ · 风险提醒 │ · 客户跟进 │ · 家长沟通 │ · 库存查询 │ └──────────────┴──────────────┴──────────────┴───────────────────┘

1.2 用例选型决策矩阵

用例类型技术复杂度ROI 周期推荐平台月均成本适合团队
智能客服(呼入)⭐⭐⭐1-2 月Vapi.ai / Retell AI$200-2,000中小企业
销售外呼⭐⭐⭐⭐2-3 月Bland.ai / Vapi.ai$500-5,000销售团队
医疗预约⭐⭐⭐⭐1-3 月Retell AI / 自建$300-3,000医疗机构
语音开发工具⭐⭐⭐⭐⭐即时Wispr Flow + IDE$10-30开发者个人
催收提醒⭐⭐⭐1 月Bland.ai$500-3,000金融机构
满意度调查⭐⭐即时Vapi.ai$100-500运营团队

工具推荐

工具用途价格适用场景
Vapi.ai全托管语音 Agent 平台$0.05/分钟起 + 组件费客服、销售、通用场景
Bland.ai大规模外呼 Agent$0.09/分钟起销售外呼、催收、调查
Retell AI低延迟企业语音 Agent$0.07/分钟起企业客服、医疗
Twilio ConversationRelay电话 + AI 深度集成$0.004/分钟 + STT/TTS 费需要深度定制的企业
Wispr Flow语音驱动开发工具$10/月(个人)开发者语音编程
Home Assistant + Whisper本地语音控制免费(开源)智能家居、IoT 控制
ElevenLabs Conversational AI语音对话 Agent$0.10/分钟起高质量语音交互
OpenAI Realtime API原生语音到语音$0.06/分钟(输入)+ $0.24/分钟(输出)实时语音对话

实战案例一:智能客服语音 Agent

场景描述

一家电商公司每天接到 500+ 通客服电话,其中 70% 是重复性问题(订单查询、退换货、物流追踪)。目标:用 AI 语音 Agent 自动处理这些常见问题,将人工客服的工作量减少 60%,同时保持 90%+ 的客户满意度。

架构设计

┌─────────────────────────────────────────────────────────────────────┐ │ 智能客服语音 Agent 架构 │ │ │ │ ┌──────────┐ ┌──────────────────────────────────────────────┐ │ │ │ 客户来电 │───→│ Vapi.ai 编排层 │ │ │ │ (PSTN) │ │ │ │ │ └──────────┘ │ ┌────────┐ ┌────────┐ ┌────────────────┐ │ │ │ │ │Deepgram│→ │GPT-4o │→ │ ElevenLabs │ │ │ │ │ │Nova-3 │ │/Claude │ │ Flash v2.5 │ │ │ │ │ │(STT) │ │(LLM) │ │ (TTS) │ │ │ │ │ └────────┘ └───┬────┘ └────────────────┘ │ │ │ │ │ Function Calling │ │ │ └──────────────────┼───────────────────────────┘ │ │ │ │ │ ┌────────────────┼────────────────┐ │ │ ↓ ↓ ↓ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 订单系统 │ │ 物流 API │ │ 知识库 │ │ │ │ (CRM/ERP)│ │ (快递100) │ │ (RAG) │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ │ ┌────────────────┼────────────────┐ │ │ ↓ ↓ ↓ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 人工转接 │ │ 工单系统 │ │ 数据分析 │ │ │ │ (Twilio) │ │ (Zendesk)│ │ (日报表) │ │ │ └──────────┘ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────────────────────────┘

技术选型

组件选择理由
编排平台Vapi.ai开箱即用,快速上线
STTDeepgram Nova-3中文识别准确率高,延迟 <200ms
LLMGPT-4o工具调用能力强,响应快
TTSElevenLabs Flash v2.5自然度高,支持中文
电话Twilio稳定可靠,全球覆盖
知识库Pinecone + OpenAI Embeddings产品 FAQ 检索

代码实现

1. 创建客服 Assistant

import requests import os VAPI_API_KEY = os.getenv("VAPI_API_KEY") def create_customer_service_agent(): """创建电商客服语音 Agent""" response = requests.post( "https://api.vapi.ai/assistant", headers={ "Authorization": f"Bearer {VAPI_API_KEY}", "Content-Type": "application/json" }, json={ "name": "电商智能客服", "model": { "provider": "openai", "model": "gpt-4o", "messages": [ { "role": "system", "content": CUSTOMER_SERVICE_PROMPT } ], "tools": [ { "type": "function", "function": { "name": "query_order", "description": "根据订单号或手机号查询订单状态", "parameters": { "type": "object", "properties": { "order_id": { "type": "string", "description": "订单号" }, "phone": { "type": "string", "description": "手机号后四位" } } } }, "server": { "url": "https://your-api.com/vapi/tools" } }, { "type": "function", "function": { "name": "track_logistics", "description": "查询物流信息", "parameters": { "type": "object", "properties": { "tracking_number": { "type": "string", "description": "快递单号" } }, "required": ["tracking_number"] } }, "server": { "url": "https://your-api.com/vapi/tools" } }, { "type": "function", "function": { "name": "create_return_request", "description": "创建退换货申请", "parameters": { "type": "object", "properties": { "order_id": { "type": "string", "description": "订单号" }, "reason": { "type": "string", "description": "退换货原因" }, "type": { "type": "string", "enum": ["refund", "exchange"], "description": "退款或换货" } }, "required": ["order_id", "reason", "type"] } }, "server": { "url": "https://your-api.com/vapi/tools" } }, { "type": "function", "function": { "name": "transfer_to_human", "description": "转接人工客服", "parameters": { "type": "object", "properties": { "reason": { "type": "string", "description": "转接原因" }, "department": { "type": "string", "enum": ["general", "refund", "complaint", "vip"], "description": "转接部门" } }, "required": ["reason"] } } }, { "type": "function", "function": { "name": "search_knowledge_base", "description": "搜索产品知识库回答常见问题", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "用户的问题" } }, "required": ["query"] } }, "server": { "url": "https://your-api.com/vapi/tools" } } ] }, "voice": { "provider": "11labs", "voiceId": "21m00Tcm4TlvDq8ikWAM", "stability": 0.5, "similarityBoost": 0.75 }, "firstMessage": "您好,欢迎致电星辰商城客服中心,我是智能客服小星。请问有什么可以帮您的?", "endCallMessage": "感谢您的来电,祝您购物愉快,再见!", "transcriber": { "provider": "deepgram", "model": "nova-3", "language": "zh" }, "silenceTimeoutSeconds": 20, "maxDurationSeconds": 600, "endCallFunctionEnabled": True, "hipaaEnabled": False } ) return response.json() # 客服 Agent 系统提示词 CUSTOMER_SERVICE_PROMPT = """你是星辰商城的 AI 电话客服"小星"。 ## 身份与风格 - 语气:温暖专业,像一位耐心的客服老手 - 语速:适中偏慢,确保客户听清 - 每次回复:控制在 2-3 句话 - 语言:简洁口语化中文,避免书面语 ## 核心能力 1. 订单查询:根据订单号或手机号查询订单状态 2. 物流追踪:查询快递物流信息 3. 退换货:协助创建退换货申请(需二次确认) 4. 常见问题:通过知识库回答产品相关问题 5. 人工转接:无法解决时转接人工客服 ## 对话规则 - 先确认客户身份(手机尾号或订单号) - 敏感操作(退款、取消)必须二次确认:"您确认要申请退款吗?" - 不确定的信息说"我帮您查一下",不要编造 - 客户情绪激动时先安抚:"非常理解您的心情,我来帮您解决" - 连续 2 次无法理解时主动转人工 ## 电话特殊规则 - 不使用 Markdown 格式、表情符号 - 数字用口语("一百二十三" 而非 "123") - 金额明确说"元"("三百五十元") - 需要列举时分多轮说明 """

2. 工具处理服务器

# tools_server.py — 客服工具处理服务器 from fastapi import FastAPI, Request from pinecone import Pinecone from openai import OpenAI import json import httpx app = FastAPI() openai_client = OpenAI() pc = Pinecone(api_key="your-pinecone-key") index = pc.Index("product-knowledge") @app.post("/vapi/tools") async def handle_tool_call(request: Request): """处理 Vapi 工具调用""" body = await request.json() tool_call = body["message"]["toolCalls"][0] func_name = tool_call["function"]["name"] args = json.loads(tool_call["function"]["arguments"]) result = "" if func_name == "query_order": result = await query_order(args) elif func_name == "track_logistics": result = await track_logistics(args) elif func_name == "create_return_request": result = await create_return(args) elif func_name == "search_knowledge_base": result = await search_kb(args) return { "results": [{ "toolCallId": tool_call["id"], "result": result }] } async def query_order(args: dict) -> str: """查询订单状态(对接 ERP 系统)""" order_id = args.get("order_id") phone = args.get("phone") # 实际项目中对接你的 ERP/CRM API async with httpx.AsyncClient() as client: resp = await client.get( "https://your-erp.com/api/orders", params={"order_id": order_id, "phone_last4": phone} ) if resp.status_code == 200: order = resp.json() return ( f"订单 {order['id']} 状态:{order['status']}。" f"商品:{order['product_name']}," f"金额:{order['amount']} 元。" f"{'预计 ' + order['eta'] + ' 送达。' if order.get('eta') else ''}" ) return "抱歉,没有找到该订单,请确认订单号是否正确。" async def track_logistics(args: dict) -> str: """查询物流信息""" tracking = args["tracking_number"] async with httpx.AsyncClient() as client: resp = await client.get( f"https://api.kuaidi100.com/query", params={"num": tracking} ) if resp.status_code == 200: data = resp.json() latest = data["data"][0] if data.get("data") else None if latest: return f"最新物流:{latest['time']}{latest['context']}" return "暂时查不到物流信息,可能快递刚发出,请稍后再查。" async def create_return(args: dict) -> str: """创建退换货申请""" async with httpx.AsyncClient() as client: resp = await client.post( "https://your-erp.com/api/returns", json={ "order_id": args["order_id"], "reason": args["reason"], "type": args["type"] } ) if resp.status_code == 201: ret = resp.json() type_text = "退款" if args["type"] == "refund" else "换货" return ( f"{type_text}申请已提交,申请编号 {ret['return_id']}。" f"预计 1 到 3 个工作日内处理完成,届时会短信通知您。" ) return "申请提交失败,我帮您转接人工客服处理。" async def search_kb(args: dict) -> str: """RAG 知识库检索""" query = args["query"] # 生成查询向量 embedding = openai_client.embeddings.create( model="text-embedding-3-small", input=query ).data[0].embedding # Pinecone 检索 results = index.query( vector=embedding, top_k=3, include_metadata=True ) if results["matches"]: contexts = [m["metadata"]["text"] for m in results["matches"]] return "根据我们的产品资料:" + " ".join(contexts[:2]) return "这个问题我不太确定,我帮您转接专业同事来解答。"

3. 通话数据分析仪表板

# analytics.py — 通话数据收集与分析 from fastapi import FastAPI, Request from datetime import datetime import json app = FastAPI() # Vapi 通话结束 Webhook @app.post("/vapi/call-ended") async def handle_call_ended(request: Request): """收集通话数据用于分析""" body = await request.json() call = body.get("message", {}).get("call", {}) analytics_data = { "call_id": call.get("id"), "duration_seconds": call.get("duration"), "ended_reason": call.get("endedReason"), "cost": call.get("cost"), "transcript": call.get("transcript"), "timestamp": datetime.now().isoformat(), # 从转录中提取关键指标 "intent": extract_intent(call.get("transcript", "")), "resolved": not call.get("transferredTo"), "sentiment": analyze_sentiment(call.get("transcript", "")) } # 存入数据库(示例用 print) print(f"通话分析: {json.dumps(analytics_data, ensure_ascii=False)}") # 实际项目:写入 PostgreSQL / BigQuery / ClickHouse return {"status": "ok"} def extract_intent(transcript: str) -> str: """从转录文本提取用户意图""" intent_keywords = { "订单查询": ["订单", "查询", "到哪了", "发货"], "退换货": ["退货", "换货", "退款", "不想要"], "物流追踪": ["快递", "物流", "送到", "配送"], "产品咨询": ["怎么用", "功能", "区别", "推荐"], "投诉": ["投诉", "不满意", "差评", "态度"] } for intent, keywords in intent_keywords.items(): if any(kw in transcript for kw in keywords): return intent return "其他" def analyze_sentiment(transcript: str) -> str: """简单情绪分析""" negative = ["生气", "投诉", "差评", "不满", "垃圾", "骗子"] positive = ["谢谢", "满意", "不错", "很好", "感谢"] if any(w in transcript for w in negative): return "negative" if any(w in transcript for w in positive): return "positive" return "neutral"

成本分析

以日均 500 通电话、平均通话 3 分钟计算:

成本项人工客服AI 语音 Agent节省
人力成本¥30,000/月(5 人)¥0¥30,000
Vapi 平台费¥1,500/月($0.05×1500 分钟×30 天÷2)
STT (Deepgram)包含在 Vapi 费用中
LLM (GPT-4o)¥2,000/月
TTS (ElevenLabs)包含在 Vapi 费用中
电话线路 (Twilio)¥3,000/月¥1,500/月¥1,500
月总成本¥33,000¥5,000¥28,000(85%)

注:AI Agent 处理 70% 的来电(350 通/天),剩余 30% 转人工,仍需保留 2 名人工客服。实际节省约 60%。

案例分析

关键决策点:

  1. 选择 Vapi.ai 而非自建——开发时间从 4 周缩短到 2 天
  2. 使用 RAG 知识库而非纯 LLM——避免 AI 编造产品信息
  3. 设置 3 次澄清上限——超过自动转人工,避免客户体验恶化
  4. 保留人工兜底——AI 处理不了的问题无缝转接,客户无感知

效果指标(上线 3 个月后):

  • AI 自主解决率:72%
  • 平均通话时长:从 4.5 分钟降至 2.8 分钟
  • 客户满意度:91%(人工客服为 88%)
  • 月度成本节省:约 ¥28,000

实战案例二:销售外呼 Agent

场景描述

一家 SaaS 公司有 2,000 条潜在客户线索需要跟进。传统方式需要 5 名 SDR(销售开发代表)花 2 周时间逐一拨打。目标:用 AI 语音 Agent 在 3 天内完成全部外呼,筛选出高意向客户交给销售团队跟进。

架构设计

┌─────────────────────────────────────────────────────────────────────┐ │ 销售外呼 Agent 架构 │ │ │ │ ┌──────────┐ ┌──────────────────────────────────────────────┐ │ │ │ CRM 线索 │───→│ Bland.ai 外呼引擎 │ │ │ │ 数据库 │ │ │ │ │ └──────────┘ │ ┌─────────────────────────────────────────┐ │ │ │ ↑ │ │ 批量外呼调度器 │ │ │ │ │ │ │ · 并发控制(50 路同时拨打) │ │ │ │ │ │ │ · 时段管理(9:00-12:00, 14:00-18:00) │ │ │ │ │ │ │ · 重试策略(未接听最多重试 2 次) │ │ │ │ │ │ └─────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ │ ┌────────┐ ┌────────┐ ┌────────────────┐ │ │ │ │ │ │Deepgram│→ │Claude │→ │ ElevenLabs │ │ │ │ │ │ │(STT) │ │Sonnet │ │ (TTS) │ │ │ │ │ │ └────────┘ └───┬────┘ └────────────────┘ │ │ │ │ └──────────────────┼───────────────────────────┘ │ │ │ │ │ │ │ ┌────────────────┼────────────────┐ │ │ │ ↓ ↓ ↓ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ │ 线索评分 │ │ 日程预约 │ │ 通话录音 │ │ │ │ │ (AI 打分) │ │ (Calendly)│ │ (分析) │ │ │ │ └─────┬────┘ └──────────┘ └──────────┘ │ │ │ │ │ │ └────────────┘ 回写 CRM(线索状态 + 评分 + 摘要) │ │ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ 结果处理流水线 │ │ │ │ 高意向(A级) → Slack 通知销售 → 自动创建跟进任务 │ │ │ │ 中意向(B级) → 加入培育序列 → 3天后再次外呼 │ │ │ │ 低意向(C级) → 标记归档 → 30天后重新评估 │ │ │ │ 未接听 → 24小时后重试 → 最多重试2次 │ │ │ └──────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘

技术选型

组件选择理由
外呼平台Bland.ai批量外呼能力强,$0.09/分钟成本低
LLMClaude Sonnet对话自然度高,不容易”机器感”
TTSElevenLabs语音自然,支持语音克隆
CRMHubSpot / Salesforce线索管理和自动化工作流
日程预约Calendly API自动预约 Demo 时间
通知Slack Webhook高意向线索实时通知销售

代码实现

1. 批量外呼调度器

# outbound_dialer.py — 批量外呼调度 import requests import asyncio import csv from datetime import datetime, time from typing import List, Dict import os BLAND_API_KEY = os.getenv("BLAND_API_KEY") SALES_PROMPT = """你是 CloudFlow(一家 SaaS 公司)的销售代表"小李"。 你正在给潜在客户打电话,介绍我们的项目管理工具。 ## 你的目标 1. 确认对方身份和职位 2. 了解他们当前的项目管理痛点 3. 简要介绍 CloudFlow 的核心价值 4. 如果对方有兴趣,预约一次 15 分钟的产品演示 5. 如果对方不感兴趣,礼貌结束并记录原因 ## 对话策略 - 开场白要简短有力,30 秒内说明来意 - 多问开放式问题,让客户说话 - 不要硬推销,重点是了解需求 - 提到具体数据:"帮助 500+ 团队提升 30% 效率" - 如果客户说忙,主动提出换个时间再聊 ## 关键话术 - 开场:"您好,请问是 [客户姓名] 吗?我是 CloudFlow 的小李, 注意到您之前在我们官网留过信息,想花两分钟跟您聊聊。" - 痛点挖掘:"您团队现在用什么工具管理项目?有没有遇到什么不方便的地方?" - 价值传递:"我们的客户平均节省了 30% 的项目沟通时间" - 预约:"要不我们约个 15 分钟的线上演示,我给您看看具体怎么用?" - 拒绝处理:"完全理解,那我先把资料发到您邮箱,您有空看看?" ## 电话规则 - 不使用 Markdown 格式 - 每次说话不超过 3 句 - 语气自然友好,不要像念稿 """ async def load_leads(csv_path: str) -> List[Dict]: """从 CSV 加载线索数据""" leads = [] with open(csv_path, "r", encoding="utf-8") as f: reader = csv.DictReader(f) for row in reader: leads.append({ "name": row["name"], "phone": row["phone"], "company": row["company"], "title": row.get("title", ""), "source": row.get("source", "website") }) return leads def is_calling_hours() -> bool: """检查是否在允许拨打的时间段""" now = datetime.now().time() morning = (time(9, 0), time(12, 0)) afternoon = (time(14, 0), time(18, 0)) return (morning[0] <= now <= morning[1] or afternoon[0] <= now <= afternoon[1]) async def make_call(lead: Dict) -> Dict: """发起单通外呼""" response = requests.post( "https://api.bland.ai/v1/calls", headers={ "Authorization": BLAND_API_KEY, "Content-Type": "application/json" }, json={ "phone_number": lead["phone"], "task": SALES_PROMPT.replace( "[客户姓名]", lead["name"] ), "voice": "mason", # 自然男声 "first_sentence": ( f"您好,请问是{lead['name']}吗?" f"我是 CloudFlow 的小李。" ), "wait_for_greeting": True, "max_duration": 300, # 最长 5 分钟 "language": "zh", "tools": [ { "name": "book_demo", "description": "当客户同意预约产品演示时调用", "input_schema": { "type": "object", "properties": { "preferred_time": { "type": "string", "description": "客户偏好的时间" }, "email": { "type": "string", "description": "客户邮箱" } } }, "url": "https://your-api.com/bland/book-demo" }, { "name": "score_lead", "description": "通话结束时对线索进行评分", "input_schema": { "type": "object", "properties": { "interest_level": { "type": "string", "enum": ["high", "medium", "low", "not_interested"], "description": "客户兴趣程度" }, "pain_points": { "type": "string", "description": "客户提到的痛点" }, "next_action": { "type": "string", "description": "建议的下一步动作" } } }, "url": "https://your-api.com/bland/score-lead" } ], "metadata": { "lead_name": lead["name"], "company": lead["company"], "source": lead["source"] } } ) return response.json()

2. 批量调度执行器

# batch_executor.py — 批量外呼执行 import asyncio from typing import List, Dict async def batch_dial( leads: List[Dict], concurrency: int = 50, delay_between: float = 1.0 ) -> List[Dict]: """批量外呼,控制并发数""" semaphore = asyncio.Semaphore(concurrency) results = [] async def dial_with_limit(lead): async with semaphore: if not is_calling_hours(): print("当前不在拨打时段,等待...") while not is_calling_hours(): await asyncio.sleep(60) result = await make_call(lead) results.append({ "lead": lead, "call_id": result.get("call_id"), "status": result.get("status") }) await asyncio.sleep(delay_between) tasks = [dial_with_limit(lead) for lead in leads] await asyncio.gather(*tasks) return results # 主执行流程 async def run_campaign(): """执行外呼活动""" leads = await load_leads("leads.csv") print(f"共 {len(leads)} 条线索,开始外呼...") results = await batch_dial(leads, concurrency=50) # 统计结果 connected = [r for r in results if r["status"] == "completed"] no_answer = [r for r in results if r["status"] == "no-answer"] print(f"接通: {len(connected)}, 未接: {len(no_answer)}") if __name__ == "__main__": asyncio.run(run_campaign())

3. 线索评分与 CRM 回写

# lead_scoring.py — 线索评分与 CRM 集成 from fastapi import FastAPI, Request import httpx import os app = FastAPI() HUBSPOT_TOKEN = os.getenv("HUBSPOT_TOKEN") SLACK_WEBHOOK = os.getenv("SLACK_WEBHOOK_URL") @app.post("/bland/score-lead") async def score_lead(request: Request): """接收 Bland.ai 的线索评分回调""" body = await request.json() interest = body.get("interest_level", "low") pain_points = body.get("pain_points", "") next_action = body.get("next_action", "") metadata = body.get("metadata", {}) # 评分映射 score_map = {"high": 90, "medium": 60, "low": 30, "not_interested": 10} score = score_map.get(interest, 0) # 回写 HubSpot CRM await update_hubspot_contact( name=metadata.get("lead_name"), company=metadata.get("company"), score=score, notes=f"痛点: {pain_points}\n下一步: {next_action}" ) # 高意向线索实时通知销售 if interest == "high": await notify_sales_team( lead_name=metadata.get("lead_name"), company=metadata.get("company"), pain_points=pain_points ) return {"status": "scored", "score": score} async def update_hubspot_contact( name: str, company: str, score: int, notes: str ): """更新 HubSpot 联系人""" async with httpx.AsyncClient() as client: # 搜索联系人 search = await client.post( "https://api.hubapi.com/crm/v3/objects/contacts/search", headers={"Authorization": f"Bearer {HUBSPOT_TOKEN}"}, json={ "filterGroups": [{ "filters": [{ "propertyName": "company", "operator": "EQ", "value": company }] }] } ) contacts = search.json().get("results", []) if contacts: contact_id = contacts[0]["id"] await client.patch( f"https://api.hubapi.com/crm/v3/objects/contacts/{contact_id}", headers={"Authorization": f"Bearer {HUBSPOT_TOKEN}"}, json={ "properties": { "lead_score": str(score), "ai_call_notes": notes, "ai_call_status": "completed" } } ) async def notify_sales_team( lead_name: str, company: str, pain_points: str ): """Slack 通知销售团队""" async with httpx.AsyncClient() as client: await client.post(SLACK_WEBHOOK, json={ "text": ( f"🔥 *高意向线索*\n" f"姓名: {lead_name}\n" f"公司: {company}\n" f"痛点: {pain_points}\n" f"请尽快跟进!" ) }) @app.post("/bland/book-demo") async def book_demo(request: Request): """处理预约 Demo 请求""" body = await request.json() preferred_time = body.get("preferred_time", "") email = body.get("email", "") # 调用 Calendly API 创建预约 async with httpx.AsyncClient() as client: resp = await client.post( "https://api.calendly.com/scheduling_links", headers={ "Authorization": f"Bearer {os.getenv('CALENDLY_TOKEN')}", "Content-Type": "application/json" }, json={ "max_event_count": 1, "owner": "https://api.calendly.com/event_types/YOUR_EVENT_TYPE", "owner_type": "EventType" } ) link = resp.json().get("resource", {}).get("booking_url", "") # 发送预约邮件(简化示例) print(f"发送预约链接 {link}{email}") return { "status": "booked", "message": f"好的,我已经把预约链接发到您的邮箱 {email} 了," f"您可以选择方便的时间。" }

成本分析

以 2,000 条线索、平均通话 2 分钟、接通率 60% 计算:

成本项人工 SDRAI 外呼 Agent节省
人力成本¥50,000/月(5 名 SDR)¥0¥50,000
Bland.ai 通话费¥2,160(2000×60%×2min×$0.09×7.2)
LLM 费用¥500
CRM 工具¥2,000/月¥2,000/月¥0
Calendly¥200/月
单次活动总成本¥52,000¥4,860¥47,140(91%)
每条线索成本¥26¥2.4390% 降低

注:AI 外呼的接通率和人工相当(约 60%),但 AI 可以同时拨打 50 路,2,000 条线索 3 天内完成,人工需要 2 周。

案例分析

关键决策点:

  1. 选择 Bland.ai 而非 Vapi.ai——Bland 的批量外呼 API 更成熟,$0.09/分钟成本更低
  2. 使用 Claude Sonnet 而非 GPT-4o——销售对话需要更自然的语气,Claude 表现更好
  3. 设置 5 分钟通话上限——避免 AI 陷入无效闲聊,控制成本
  4. 三级线索分类——高/中/低意向分别处理,最大化转化率

效果指标:

  • 2,000 条线索 3 天完成(人工需 2 周)
  • 高意向线索识别率:18%(360 条)
  • Demo 预约转化率:8%(160 个预约)
  • 销售团队效率提升:300%(只跟进高意向线索)

销售外呼提示词模板

你是 [公司名称] 的销售代表 [Agent名称],正在给潜在客户打电话。 ## 目标 1. 确认对方身份(30 秒内) 2. 了解当前痛点(1 分钟) 3. 传递产品价值(30 秒) 4. 推动下一步行动(预约 Demo / 发送资料) ## 开场白策略 - 直接说明来意,不要绕弯子 - 提到客户的公司名或行业,显示你做了功课 - 用一句话说明为什么打这个电话 ## 异议处理 - "没时间" → "完全理解,我只占用您两分钟" - "不需要" → "请问您目前用什么方案解决 [痛点]?" - "发资料" → "好的,您方便告诉我邮箱吗?" - "多少钱" → "根据团队规模不同,我们有灵活的方案, 预约个 Demo 我给您详细介绍" ## 禁止行为 - 不要过度推销或施压 - 不要贬低竞品 - 不要承诺无法兑现的优惠 - 不要在客户明确拒绝后继续纠缠

实战案例三:语音控制开发工具

场景描述

开发者每天花大量时间在键盘上打字——写代码、写 prompt、写文档、查日志。语音控制开发工具让开发者可以用说话代替打字,将思维速度(150 词/分钟)直接转化为代码和操作,比打字(40-80 词/分钟)快 2-3 倍。这个案例展示如何搭建一套语音驱动的开发工作流。

架构设计

┌─────────────────────────────────────────────────────────────────────┐ │ 语音控制开发工具架构 │ │ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ 开发者语音输入 │ │ │ │ "创建一个 React 组件,接收 name 和 age 两个 props" │ │ │ └──────────────────────┬───────────────────────────────────────┘ │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ Wispr Flow / SuperWhisper │ │ │ │ (本地 AI 语音转文本,理解开发者上下文) │ │ │ │ │ │ │ │ · 识别 camelCase、snake_case 等命名规范 │ │ │ │ · 理解编程术语("括号"→()、"花括号"→{}) │ │ │ │ · 自动格式化为结构化 prompt │ │ │ └──────────────────────┬───────────────────────────────────────┘ │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ AI 编码助手 (IDE 集成) │ │ │ │ │ │ │ │ ┌────────────┐ ┌────────────┐ ┌────────────────────────┐ │ │ │ │ │ Cursor │ │ Kiro │ │ Claude Code (CLI) │ │ │ │ │ │ (AI IDE) │ │ (AI IDE) │ │ (终端) │ │ │ │ │ └──────┬─────┘ └──────┬─────┘ └──────────┬────────────┘ │ │ │ │ │ │ │ │ │ │ │ └───────────────┼────────────────────┘ │ │ │ │ ↓ │ │ │ │ LLM (Claude / GPT-4o / Gemini) │ │ │ │ ↓ │ │ │ │ 代码生成 / 修改 / 审查 / 解释 │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ 扩展能力 (MCP / 工具) │ │ │ │ │ │ │ │ "查一下生产环境的错误日志" → MCP → Datadog API │ │ │ │ "部署到 staging" → MCP → GitHub Actions │ │ │ │ "这个 PR 有什么问题" → MCP → GitHub PR Review │ │ │ │ "数据库里有多少活跃用户" → MCP → PostgreSQL Query │ │ │ └──────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘

技术选型

组件选择理由
语音转文本Wispr Flow专为开发者设计,理解代码术语
AI IDECursor / Kiro深度 AI 集成,支持语音 prompt
CLI 助手Claude Code终端中的 AI 编程助手
本地 STT 备选SuperWhisper隐私优先,本地处理
工具连接MCP Server连接数据库、CI/CD、监控等

工具推荐

工具用途价格适用场景
Wispr FlowAI 语音转文本(开发者专用)$10/月(个人)、$24/月(Pro)语音编程、prompt 口述
SuperWhisper本地 AI 语音转文本$8/月隐私敏感场景
CursorAI 代码编辑器$20/月(Pro)语音 + AI 编程
KiroAI IDE(AWS)免费 / $19/月(Pro)Spec-Driven 开发
Claude CodeCLI AI 编程助手按 API 用量计费终端语音编程
Talon Voice语音控制电脑免费(开源)无障碍编程、RSI 预防

操作步骤

步骤 1:安装 Wispr Flow

# macOS(推荐) # 从 https://wisprflow.ai 下载安装 # 或通过 Homebrew brew install --cask wispr-flow # 配置 # 1. 打开 Wispr Flow → Settings # 2. 选择语言模型(推荐 Flow Pro 模式) # 3. 设置快捷键(默认:按住 Fn 键说话) # 4. 启用 "Developer Mode" 以识别代码术语

步骤 2:配置 IDE 集成

Cursor + Wispr Flow 工作流:

1. 打开 Cursor 编辑器 2. 按 Cmd+K 打开 AI 编辑面板 3. 按住 Fn 键(Wispr Flow 快捷键)开始说话: "创建一个 TypeScript 函数,接收用户列表, 按注册时间排序,返回最近 10 个活跃用户" 4. Wispr Flow 将语音转为文本,自动填入 Cursor 的 prompt 框 5. Cursor AI 生成代码 6. 语音审查:"把排序改成降序,加上类型注解"

Claude Code + Wispr Flow 工作流:

# 在终端中使用 Claude Code # 按住 Fn 说话,Wispr Flow 自动将语音转为文本输入终端 # 语音:"claude 帮我重构 src/utils/auth.ts, # 把所有的 callback 改成 async await" # Wispr Flow 输出: claude "帮我重构 src/utils/auth.ts,把所有的 callback 改成 async/await" # 语音:"查看最近的 git 提交记录,找出哪个提交引入了这个 bug" claude "查看最近的 git log,找出哪个 commit 引入了 TypeError bug"

步骤 3:语音驱动的 DevOps 操作

通过 MCP Server 连接基础设施工具,实现语音控制 DevOps:

# voice_devops_mcp.py — 语音 DevOps MCP Server 示例 # 这个 MCP Server 让 AI IDE 能通过语音执行 DevOps 操作 from mcp.server import Server from mcp.types import Tool, TextContent import subprocess import httpx server = Server("voice-devops") @server.tool() async def check_deployment_status(environment: str) -> list[TextContent]: """ 查询部署状态。 语音示例:"staging 环境现在是什么状态" """ async with httpx.AsyncClient() as client: resp = await client.get( f"https://api.github.com/repos/your-org/your-repo/deployments", headers={"Authorization": f"token {GITHUB_TOKEN}"}, params={"environment": environment} ) deployments = resp.json() if deployments: latest = deployments[0] return [TextContent( type="text", text=f"{environment} 环境最新部署:\n" f" 状态: {latest['status']}\n" f" 分支: {latest['ref']}\n" f" 时间: {latest['created_at']}" )] return [TextContent(type="text", text=f"{environment} 没有找到部署记录")] @server.tool() async def query_error_logs( service: str, time_range: str = "1h" ) -> list[TextContent]: """ 查询错误日志。 语音示例:"查一下 user-service 最近一小时的错误日志" """ async with httpx.AsyncClient() as client: resp = await client.post( "https://api.datadoghq.com/api/v2/logs/events/search", headers={ "DD-API-KEY": DATADOG_API_KEY, "DD-APPLICATION-KEY": DATADOG_APP_KEY }, json={ "filter": { "query": f"service:{service} status:error", "from": f"now-{time_range}", "to": "now" }, "sort": "-timestamp", "page": {"limit": 10} } ) logs = resp.json().get("data", []) if logs: summary = f"{service} 最近 {time_range}{len(logs)} 条错误:\n" for log in logs[:5]: msg = log["attributes"]["message"][:100] summary += f" - {msg}\n" return [TextContent(type="text", text=summary)] return [TextContent( type="text", text=f"{service} 最近 {time_range} 没有错误日志,一切正常" )] @server.tool() async def trigger_deployment( environment: str, branch: str = "main" ) -> list[TextContent]: """ 触发部署。 语音示例:"把 main 分支部署到 staging" """ async with httpx.AsyncClient() as client: resp = await client.post( "https://api.github.com/repos/your-org/your-repo/dispatches", headers={"Authorization": f"token {GITHUB_TOKEN}"}, json={ "event_type": "deploy", "client_payload": { "environment": environment, "branch": branch } } ) if resp.status_code == 204: return [TextContent( type="text", text=f"已触发部署:{branch}{environment}," f"预计 3-5 分钟完成。" )] return [TextContent( type="text", text=f"部署触发失败:{resp.status_code}" )]

语音编程典型工作流示例

┌─────────────────────────────────────────────────────────────┐ │ 语音编程一日工作流 │ │ │ │ 09:00 🎤 "查看今天的 GitHub Issues 和 PR" │ │ → MCP 调用 GitHub API → 显示待处理列表 │ │ │ │ 09:15 🎤 "开始处理 Issue 42,先看一下相关代码" │ │ → AI 定位相关文件 → 展示代码上下文 │ │ │ │ 09:30 🎤 "在 UserService 里加一个 getActiveUsers 方法, │ │ 查询最近 30 天有登录记录的用户,分页返回" │ │ → AI 生成代码 → 开发者语音审查修改 │ │ │ │ 10:00 🎤 "给这个方法写单元测试,覆盖空结果和分页边界" │ │ → AI 生成测试 → 运行测试 │ │ │ │ 10:30 🎤 "提交代码,PR 标题写修复 Issue 42" │ │ → 自动 git add/commit/push → 创建 PR │ │ │ │ 11:00 🎤 "staging 环境的错误日志有什么异常吗" │ │ → MCP 查询 Datadog → 返回错误摘要 │ │ │ │ 14:00 🎤 "把 PR 123 合并到 main,然后部署到 staging" │ │ → 合并 PR → 触发 CI/CD → 部署 │ │ │ │ 16:00 🎤 "生成今天的工作日报,包括完成的任务和明天计划" │ │ → AI 汇总 git log + Issues → 生成日报 │ └─────────────────────────────────────────────────────────────┘

成本分析

成本项传统键盘开发语音驱动开发差异
Wispr Flow$10/月+$10
AI IDE (Cursor Pro)$20/月$20/月¥0
LLM API 用量$30/月$50/月(语音 prompt 更多)+$20
月总成本$50$80+$30
开发效率基准提升 30-50%🚀
RSI 风险较高显著降低

注:语音编程的核心价值不在于省钱,而在于提升效率和保护健康。每月多花 $30,换来 30-50% 的效率提升和更低的重复性劳损(RSI)风险,ROI 极高。

案例分析

关键决策点:

  1. 选择 Wispr Flow 而非通用语音输入——它理解 camelCase、代码术语、编程上下文
  2. 搭配 AI IDE 而非纯语音编程——语音负责输入 prompt,AI 负责生成代码
  3. 通过 MCP 扩展能力——语音不仅能写代码,还能查日志、触发部署、查数据库
  4. 保留键盘作为补充——精细编辑仍用键盘,语音用于大块输入和指令

适用人群:

  • 有 RSI(重复性劳损)风险的开发者
  • 需要大量写 prompt 的 AI 辅助开发者
  • 喜欢”边想边说”的思维方式的人
  • 多任务切换频繁的全栈开发者

实战案例四:医疗预约语音 Agent

场景描述

一家连锁诊所每天接到 200+ 通预约电话,前台 3 名工作人员经常忙不过来,导致 30% 的来电无人接听。目标:用 AI 语音 Agent 7×24 小时自动处理预约、改约、取消和提醒,将未接来电率降至 5% 以下。

架构设计

┌─────────────────────────────────────────────────────────────────────┐ │ 医疗预约语音 Agent 架构 │ │ │ │ ┌──────────┐ ┌──────────────────────────────────────────────┐ │ │ │ 患者来电 │───→│ Retell AI / Twilio + 自建 │ │ │ │ (PSTN) │ │ │ │ │ └──────────┘ │ ┌────────┐ ┌────────┐ ┌────────────────┐ │ │ │ │ │Deepgram│→ │GPT-4o │→ │ ElevenLabs │ │ │ │ ┌──────────┐ │ │Nova-3 │ │(LLM) │ │ (TTS) │ │ │ │ │ AI 外呼 │───→│ │(STT) │ │ │ │ │ │ │ │ │ (提醒) │ │ └────────┘ └───┬────┘ └────────────────┘ │ │ │ └──────────┘ └──────────────────┼───────────────────────────┘ │ │ │ Function Calling │ │ ┌────────────────┼────────────────┐ │ │ ↓ ↓ ↓ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 排班系统 │ │ 患者档案 │ │ 短信通知 │ │ │ │ (日程API) │ │ (EMR/HIS)│ │ (Twilio) │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ │ ┌──────────────────────┼──────────────────────┐ │ │ │ 合规与安全层 │ │ │ │ · 通话录音加密存储 │ │ │ │ · 患者信息脱敏处理 │ │ │ │ · HIPAA / 个人信息保护法合规 │ │ │ │ · 敏感操作人工确认 │ │ │ └─────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘

技术选型

组件选择理由
语音平台Retell AI低延迟,支持 HIPAA 合规
STTDeepgram Nova-3医疗术语识别准确
LLMGPT-4o工具调用可靠,结构化输出好
TTSElevenLabs温暖自然的语音
排班系统自建 API / Acuity Scheduling医生排班和时段管理
短信通知Twilio SMS预约确认和提醒
数据存储PostgreSQL(加密)患者数据安全存储

代码实现

1. 医疗预约 Agent(Retell AI 版本)

# medical_agent.py — 医疗预约语音 Agent import os import json from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect from fastapi.responses import JSONResponse from datetime import datetime, timedelta from openai import AsyncOpenAI import httpx app = FastAPI() openai_client = AsyncOpenAI() MEDICAL_SYSTEM_PROMPT = """你是阳光诊所的 AI 预约助手"小阳"。 ## 身份与风格 - 语气:温暖、耐心、专业 - 语速:偏慢,确保患者(尤其老年人)听清 - 每次回复:1-2 句话,简洁明了 - 称呼:使用"您",称对方为"先生/女士" ## 核心能力 1. 新预约:帮患者预约门诊 2. 改约:修改已有预约时间 3. 取消预约:取消已有预约 4. 查询预约:查询预约详情 5. 科室咨询:介绍各科室和医生 ## 预约流程 1. 确认患者身份(姓名 + 手机号后四位) 2. 了解就诊需求(哪个科室、什么症状) 3. 推荐合适的医生和时段 4. 确认预约信息(医生、时间、科室) 5. 发送短信确认 ## 医疗特殊规则 - 不提供任何医疗诊断或用药建议 - 紧急情况(胸痛、呼吸困难等)立即建议拨打 120 - 患者描述症状时,只用于推荐科室,不做判断 - 涉及检查报告解读,转接医生 - 所有操作需患者口头确认 ## 电话规则 - 不使用 Markdown 格式 - 时间用口语:"明天上午十点"而非"2025-01-15 10:00" - 医生姓名要说全:"张明华主任"而非"张医生" - 重要信息重复确认 """ # Retell AI Webhook 处理 @app.post("/retell/webhook") async def handle_retell_webhook(request: Request): """处理 Retell AI 的工具调用""" body = await request.json() event = body.get("event") if event == "call_started": return JSONResponse({"status": "ok"}) elif event == "tool_call": tool_name = body["tool_call"]["name"] args = body["tool_call"]["arguments"] if tool_name == "check_availability": result = await check_doctor_availability(args) elif tool_name == "book_appointment": result = await book_appointment(args) elif tool_name == "cancel_appointment": result = await cancel_appointment(args) elif tool_name == "lookup_patient": result = await lookup_patient(args) elif tool_name == "send_confirmation_sms": result = await send_sms(args) else: result = "未知操作" return JSONResponse({ "tool_call_id": body["tool_call"]["id"], "result": result }) return JSONResponse({"status": "ok"})

2. 排班查询与预约逻辑

# scheduling.py — 排班和预约业务逻辑 from datetime import datetime, timedelta from typing import Optional import asyncpg # 数据库连接池(生产环境使用连接池) DB_URL = "postgresql://user:pass@localhost/clinic" async def check_doctor_availability(args: dict) -> str: """查询医生可用时段""" department = args.get("department", "") doctor_name = args.get("doctor_name", "") preferred_date = args.get("date", "") conn = await asyncpg.connect(DB_URL) try: # 查询指定科室/医生的可用时段 query = """ SELECT d.name, d.title, s.slot_date, s.slot_time, s.is_available FROM doctors d JOIN schedule_slots s ON d.id = s.doctor_id WHERE d.department = $1 AND s.slot_date >= $2 AND s.is_available = true """ params = [department, preferred_date or datetime.now().date()] if doctor_name: query += " AND d.name LIKE $3" params.append(f"%{doctor_name}%") query += " ORDER BY s.slot_date, s.slot_time LIMIT 6" rows = await conn.fetch(query, *params) if not rows: return ( f"抱歉,{department}近期暂时没有可用的预约时段。" f"需要我帮您查看其他科室或其他时间吗?" ) result = f"{department}可用时段:\n" for row in rows: date_str = row["slot_date"].strftime("%m月%d日") time_str = row["slot_time"].strftime("%H:%M") result += ( f"{row['name']}{row['title']}," f"{date_str} {time_str}\n" ) return result finally: await conn.close() async def book_appointment(args: dict) -> str: """创建预约""" patient_id = args.get("patient_id") doctor_name = args.get("doctor_name") slot_date = args.get("date") slot_time = args.get("time") conn = await asyncpg.connect(DB_URL) try: # 检查时段是否仍然可用(防止并发冲突) slot = await conn.fetchrow(""" SELECT s.id, d.name, d.department FROM schedule_slots s JOIN doctors d ON d.id = s.doctor_id WHERE d.name LIKE $1 AND s.slot_date = $2 AND s.slot_time = $3 AND s.is_available = true FOR UPDATE """, f"%{doctor_name}%", slot_date, slot_time) if not slot: return "抱歉,这个时段刚刚被预约了,需要我帮您看看其他时间吗?" # 创建预约记录 appointment_id = await conn.fetchval(""" INSERT INTO appointments (patient_id, slot_id, status, created_at) VALUES ($1, $2, 'confirmed', NOW()) RETURNING id """, patient_id, slot["id"]) # 标记时段为不可用 await conn.execute(""" UPDATE schedule_slots SET is_available = false WHERE id = $1 """, slot["id"]) date_str = slot_date if isinstance(slot_date, str) else slot_date.strftime("%m月%d日") return ( f"预约成功!预约编号 {appointment_id}。" f"{slot['name']}{date_str} {slot_time}," f"{slot['department']}。" f"我马上给您发一条确认短信。" ) finally: await conn.close() async def cancel_appointment(args: dict) -> str: """取消预约""" appointment_id = args.get("appointment_id") patient_id = args.get("patient_id") conn = await asyncpg.connect(DB_URL) try: appt = await conn.fetchrow(""" SELECT a.id, a.slot_id, s.slot_date, s.slot_time, d.name FROM appointments a JOIN schedule_slots s ON s.id = a.slot_id JOIN doctors d ON d.id = s.doctor_id WHERE a.id = $1 AND a.patient_id = $2 AND a.status = 'confirmed' """, appointment_id, patient_id) if not appt: return "没有找到这个预约记录,请确认预约编号是否正确。" # 取消预约并释放时段 await conn.execute(""" UPDATE appointments SET status = 'cancelled' WHERE id = $1 """, appointment_id) await conn.execute(""" UPDATE schedule_slots SET is_available = true WHERE id = $1 """, appt["slot_id"]) return ( f"已取消您在 {appt['name']} 处的预约。" f"如需重新预约,随时给我们打电话。" ) finally: await conn.close() async def lookup_patient(args: dict) -> str: """查询患者信息(用于身份验证)""" name = args.get("name", "") phone_last4 = args.get("phone_last4", "") conn = await asyncpg.connect(DB_URL) try: patient = await conn.fetchrow(""" SELECT id, name, phone FROM patients WHERE name = $1 AND RIGHT(phone, 4) = $2 """, name, phone_last4) if patient: return json.dumps({ "found": True, "patient_id": patient["id"], "name": patient["name"] }) return json.dumps({ "found": False, "message": "没有找到匹配的患者记录" }) finally: await conn.close() async def send_sms(args: dict) -> str: """发送预约确认短信""" phone = args.get("phone") message = args.get("message") async with httpx.AsyncClient() as client: await client.post( f"https://api.twilio.com/2010-04-01/Accounts/" f"{os.getenv('TWILIO_SID')}/Messages.json", auth=(os.getenv("TWILIO_SID"), os.getenv("TWILIO_TOKEN")), data={ "To": phone, "From": os.getenv("TWILIO_PHONE"), "Body": message } ) return "确认短信已发送。"

3. 预约提醒外呼

# reminder_caller.py — 预约提醒自动外呼 import asyncio from datetime import datetime, timedelta import asyncpg import requests import os RETELL_API_KEY = os.getenv("RETELL_API_KEY") REMINDER_PROMPT = """你是阳光诊所的预约提醒助手"小阳"。 你正在给患者打电话提醒明天的预约。 ## 任务 1. 确认对方身份 2. 提醒预约时间和医生 3. 确认是否按时就诊 4. 如需改约,帮助处理 ## 话术 - "您好,请问是 [患者姓名] 吗?" - "提醒您明天 [时间] 在 [科室] 有一个预约, 是 [医生姓名] 的门诊。" - "请问您能按时来吗?" - 如果确认:"好的,请记得带上医保卡,提前 15 分钟到。" - 如果要改约:"好的,我帮您看看其他时间。" - 如果要取消:"好的,已帮您取消,需要时随时预约。" ## 规则 - 最多尝试确认 2 次 - 如果对方说忙,简短说明后结束 - 不提供任何医疗建议 """ async def get_tomorrow_appointments() -> list: """获取明天的预约列表""" conn = await asyncpg.connect(DB_URL) try: tomorrow = datetime.now().date() + timedelta(days=1) rows = await conn.fetch(""" SELECT a.id, p.name, p.phone, d.name as doctor_name, d.department, s.slot_time FROM appointments a JOIN patients p ON p.id = a.patient_id JOIN schedule_slots s ON s.id = a.slot_id JOIN doctors d ON d.id = s.doctor_id WHERE s.slot_date = $1 AND a.status = 'confirmed' AND a.reminder_sent = false """, tomorrow) return [dict(row) for row in rows] finally: await conn.close() async def make_reminder_call(appointment: dict): """发起提醒电话""" prompt = REMINDER_PROMPT.replace( "[患者姓名]", appointment["name"] ).replace( "[时间]", appointment["slot_time"].strftime("%H:%M") ).replace( "[科室]", appointment["department"] ).replace( "[医生姓名]", appointment["doctor_name"] ) response = requests.post( "https://api.retellai.com/v2/create-phone-call", headers={ "Authorization": f"Bearer {RETELL_API_KEY}", "Content-Type": "application/json" }, json={ "from_number": os.getenv("CLINIC_PHONE"), "to_number": appointment["phone"], "agent_id": os.getenv("REMINDER_AGENT_ID"), "retell_llm_dynamic_variables": { "patient_name": appointment["name"], "appointment_time": appointment["slot_time"].strftime("%H:%M"), "doctor_name": appointment["doctor_name"], "department": appointment["department"] }, "metadata": { "appointment_id": appointment["id"] } } ) return response.json() async def run_daily_reminders(): """每天下午 4 点执行提醒外呼""" appointments = await get_tomorrow_appointments() print(f"明天共 {len(appointments)} 个预约需要提醒") for appt in appointments: result = await make_reminder_call(appt) print(f"提醒 {appt['name']}: {result.get('status')}") await asyncio.sleep(2) # 间隔 2 秒 if __name__ == "__main__": asyncio.run(run_daily_reminders())

成本分析

以日均 200 通来电 + 50 通提醒外呼、平均通话 2.5 分钟计算:

成本项人工前台AI 语音 Agent节省
人力成本¥18,000/月(3 人)¥0¥18,000
Retell AI 平台费¥3,150/月(250通×2.5min×30天×$0.07×7.2)
LLM (GPT-4o)¥1,500/月
Twilio 短信¥500/月¥500/月¥0
电话线路¥2,000/月¥1,000/月¥1,000
月总成本¥20,500¥6,150¥14,350(70%)

注:AI Agent 处理 85% 的预约电话,剩余 15%(复杂咨询、投诉)转人工。保留 1 名前台处理现场和转接。

合规注意事项

合规要求实现方式
患者隐私保护通话录音加密存储,90 天后自动删除
身份验证姓名 + 手机尾号双重验证
数据脱敏LLM 日志中不记录完整手机号和身份证号
知情同意通话开始时告知”本次通话由 AI 助手为您服务”
紧急情况检测到紧急症状关键词立即建议拨打 120
医疗免责AI 不提供任何诊断或用药建议

案例分析

关键决策点:

  1. 选择 Retell AI——低延迟对医疗场景很重要,老年患者对延迟更敏感
  2. 双重身份验证——医疗数据敏感,必须确认患者身份
  3. 预约提醒外呼——主动提醒将爽约率从 25% 降至 8%
  4. 严格的医疗免责——AI 绝不提供诊断建议,只做预约管理

效果指标(上线 2 个月后):

  • 未接来电率:从 30% 降至 4%
  • 预约处理时间:从 4 分钟降至 2 分钟
  • 爽约率:从 25% 降至 8%(得益于 AI 提醒外呼)
  • 前台工作量:减少 70%,可专注现场服务

避坑指南

❌ 常见错误

  1. 不告知用户正在与 AI 对话

    • 问题:在很多地区,不告知用户正在与 AI 通话可能违反消费者保护法规。即使法律未明确要求,用户发现被”欺骗”后信任度会大幅下降
    • 正确做法:通话开始时明确说明”本次通话由 AI 助手为您服务”,并提供转人工选项
  2. 让 AI 处理所有类型的来电

    • 问题:投诉、紧急情况、复杂谈判等场景,AI 处理不当会严重损害客户关系
    • 正确做法:明确定义 AI 的能力边界,设置自动转人工的触发条件(情绪检测、关键词匹配、连续澄清次数)
  3. 忽略延迟对用户体验的影响

    • 问题:电话对话中超过 1.5 秒的沉默会让用户感到不自然,超过 3 秒用户会以为断线
    • 正确做法:使用流式 TTS、选择低延迟的 STT/LLM 组合、添加填充语(“嗯,让我查一下”)掩盖处理时间
  4. 外呼不遵守时间和频率限制

    • 问题:在非工作时间拨打、对同一号码频繁拨打,可能违反电话营销法规,也会引起用户反感
    • 正确做法:严格限制拨打时段(9:00-12:00, 14:00-18:00),同一号码最多重试 2 次,提供退订机制
  5. 医疗/金融场景不做合规审查

    • 问题:医疗数据受 HIPAA/个人信息保护法约束,金融数据受监管要求约束,违规可能面临巨额罚款
    • 正确做法:选择支持合规的平台(如 Retell AI 的 HIPAA 模式),通话录音加密存储,患者/客户数据脱敏处理
  6. 销售外呼 prompt 过于激进

    • 问题:AI 按照过于激进的销售话术拨打电话,会被标记为骚扰电话,损害品牌形象
    • 正确做法:话术以了解需求为主,不硬推销,客户拒绝后礼貌结束,提供后续联系方式

✅ 最佳实践

  1. 从高频重复场景开始——先用 AI 处理占 70% 的简单重复来电(订单查询、预约确认),快速见效后再扩展到复杂场景

  2. 设计优雅的人工转接——AI 无法处理时,无缝转接人工客服,并将对话上下文一并传递,避免客户重复描述问题

  3. 持续监控和优化——每周分析通话录音和转录文本,识别 AI 处理不好的模式,更新 prompt 和工具

  4. A/B 测试不同话术——同一场景准备 2-3 套话术,通过 A/B 测试找到转化率最高的版本

  5. 建立反馈闭环——通话结束后发送满意度调查(短信/IVR),收集用户反馈持续改进

  6. 成本监控告警——设置每日/每月成本上限告警,避免异常流量导致费用失控

  7. 渐进式上线——先在 10% 的来电上测试 AI Agent,确认效果后逐步扩大到 100%

  8. 保留完整通话记录——所有通话的录音和转录文本都要保存,用于质量审查、纠纷处理和模型优化


相关资源与延伸阅读

  1. Vapi.ai 官方文档 — 快速入门指南  — 从零构建语音 Agent 的完整教程
  2. Bland.ai API 文档 — 批量外呼  — 大规模外呼 Agent 的 API 参考
  3. Retell AI 文档 — 企业语音 Agent  — 低延迟企业级语音 Agent 构建指南
  4. Twilio ConversationRelay 文档  — Twilio 官方 AI 语音集成指南
  5. Wispr Flow — 开发者语音编程  — AI 语音转文本工具,专为开发者设计
  6. Deepgram Nova-3 模型文档  — 高精度低延迟 STT 模型
  7. ElevenLabs Conversational AI  — 高质量语音对话 Agent 构建
  8. Home Assistant 语音控制指南  — 开源本地语音控制智能家居
  9. OpenAI Realtime API 文档  — 原生语音到语音对话 API
  10. AI Voice Agent 架构与权衡(2026)  — 生产环境语音 Agent 架构深度分析

参考来源


📖 返回 总览与导航 | 上一节:14c-AI电话Agent构建 | 下一节:14e-延迟优化与多语言

Last updated on