语音AI客服与销售系统落地:从Grok Voice到Starlink的工程架构与实践
发布时间:2026/8/28 16:00:55 作者:尧图编辑部 阅读量:1,286

客服与销售场景是语音 AI 落地最直接也最难规模化的领域之一。Grok Voice 这类具备自然对话能力的语音服务进入 Starlink 客服与销售链路后真正需要面对的已经不是“能不能说话”而是并发、延迟、状态管理、用户意图识别、服务转人工、成交指标、故障回退等一套系统工程问题。把语音模型接到电话网关只是第一步后面的可观测性、降级策略、合规校验和销售话术控制才决定这套系统能不能长期运行。本文从一个可落地的语音客服 Agent 出发拆解如何为 Starlink 这类客户规模大、地域分散、网络产品解释成本高的业务设计一套语音客服与销售系统。1. 语音客服与文本客服的业务差异决定了系统设计起点1.1 “客服”和“销售”是两种不同目标驱动的会话客服会话和销售会话虽然共用同一套语音交互链路但目标函数完全不同。客服会话的目标是“解决存量问题”用户设备离线、网速不达标、账单有疑问、需要取消服务。成功指标是问题解决率、转人工率、通话时长和满意度。销售会话的目标是“创造增量价值”用户咨询更高套餐、加购 Mesh 路由器、续费、升级服务区域。成功指标是转化率、客单价、线索完成率和成交后回访率。把两类会话塞进同一个提示词模板里是最常见的错误。客服场景需要保守、精确、可回退销售场景需要引导、解释、促成。正确做法是在会话开始前就通过主叫号码、IVR 按键、用户标签或上一通会话结果确定会话类型并把类型写入会话上下文。Grok Voice 这类模型虽然能感知对话风格但业务系统必须在模型之外控制会话方向否则 AI 可能在客服会话里过度推销或在销售会话里给出不准确的故障承诺。1.2 Starlink 业务场景的语音会话特征Starlink 这类卫星互联网服务客户群分布广、设备环境差异大、故障原因复杂。常见咨询包括套餐怎么选、当前区域是否覆盖、安装是否需要屋顶走线、阴雨天为什么掉速、Starlink 应用里看到的“视野受阻”是什么意思、账单扣款失败后如何处理、设备返修流程是什么。这些问题的共同点是“不能只靠聊天回答”。查询订单状态需要读 CRM 接口判断是否覆盖需要传入地理位置和仰角数据解决掉线问题需要解析客户端 telemetry销售推荐需要结合套餐和服务区域。因此语音 Agent 不能做成通用闲聊必须把它设计成“语音交互外壳 业务工具调用层 对话生成内核”的组合体。1.3 语音链路比文本链路多出哪些状态文本聊天只需要处理“收到消息、生成回复、发送回复”三个事件。语音呼叫则增加了大量实时状态用户是否在说话需要 VAD 判断。用户说完话后需要“端点检测”判断何时结束。模型生成回复期间用户可能直接打断也就是 barge-in。ASR 转写可能出现同音字错误需要置信度判断。TTS 合成需要时间用户等待超过阈值会产生焦虑。通话可能被运营商中断、主叫方挂断、信号丢包导致音频断裂。这些状态必须由代码显式管理。否则模型回复再自然只要静默超时处理不当用户就会觉得“AI 卡住了”。这也是语音客服系统在架构上不能只依赖 LLM 的原因。维度文本客服语音客服输入粒度文本消息连续音频流时长压力低高秒级等待都影响体验错误来源用户打字表达不准用户口音、环境噪声、ASR 误识别打断能力无需考虑必须支持 barge-in转人工成本点击按钮或输入转人工需要语音指令识别或坐席抢接数据完整性文本可留痕需要录音转写事件三份数据2. 语音链路架构不能先接模型再补工程2.1 一条通话从接入到响应的完整路径一条语音通话要经过电话网关、媒体服务、ASR、事件总线、会话服务、LLM、TTS 等多个组件。常见链路如下用户拨打客服热线运营商通过 SIP 中继接入。媒体服务器把 RTP 音频流转成可处理的 PCM/Opus 流。语音活动检测器识别用户开始说话把音频片段送入 ASR。ASR 输出转写文本和置信度投递到 Redis Stream 或 Kafka。Voice Agent 消费转写结果更新会话状态机。Agent 根据意图调用 CRM、订单、工单等业务接口。Agent 把业务结果和对话历史交给 Grok Voice 类模型生成回复。回复文本进入 TTS合成音频后通过媒体服务器播放给用户。通话结束后录音、转写、状态事件统一归档。这条路看起来长但每一层都有必要。实际项目中不建议把媒体服务器直接接到模型推理服务上因为音频流是连续且高吞吐的而 LLM 推理是突发且延迟敏感的中间需要有队列和状态层做缓冲。2.2 ASR、意图识别与回复生成分层处理很多团队想用一个大模型同时完成 ASR、意图识别、回复生成甚至语音合成。短期内能演示但生产环境中问题很多。一点口音变化会导致 ASR 完全错乱业务意图频繁变化时调整一次大模型提示词的成本远高于调整一个轻量分类器TTS 失败时也没有办法快速降级。推荐分层ASR 单独使用语音识别服务或本地模型输出文本、时间戳、置信度。意图识别使用规则 少样本分类至少对“故障报修、订单查询、账单查询、销售咨询、转人工、取消服务”这些意图保证高准确率。回复生成使用 Grok Voice 类 LLM上下文包含用户画像、业务接口结果、话术约束。TTS 单独配置音色、语速和打断策略。分层之后每一层都能单独验证、单独扩容、单独降级。例如 ASR 置信度低于 0.6 时不进入 LLM而是直接播放“没有听清请再说一遍”。2.3 为什么不能让模型直接驱动整条链路LLM 擅长语言生成但不擅长处理状态和硬约束。它不知道用户已经等了 8 秒不知道用户刚才因为听不清已经重复了两遍不知道当前订单号已经查过三次也不知道销售话术里哪些承诺是被合规禁止的。因此在语音客服链路里模型的定位是“回复生成器”而不是“会话控制器”。会话控制器由状态机、超时策略、业务接口调用和人工接管逻辑组成。这就像在 Ku 波段卫星通信波形中导频和其他可预测元素被用来做同步和信道估计语音客服链路同样需要可预测的控制元素会话 ID、状态码、超时阈值、重试次数、转人工标志。如果没有这些“导频”模型再聪明系统也会在异常场景里漂移。3. 用一个最小会话服务跑通 Grok Voice 类语音 Agent3.1 搭建 VoiceAgent 服务骨架下面用一个 FastAPI WebSocket 示例说明会话服务的核心结构。这个骨架不直接处理音频编解码而是假设上游媒体服务已经把语音转成结构化事件推送过来。这样做更贴近真实工程媒体层、ASR、会话层分离。# voice_agent_server.py from fastapi import FastAPI, WebSocket, WebSocketDisconnect from enum import Enum import asyncio import uuid app FastAPI() class SessionState(str, Enum): IDLE idle LISTENING listening THINKING thinking SPEAKING speaking ENDED ended class VoiceSession: def __init__(self, session_id: str, session_type: str support): self.session_id session_id self.session_type session_type self.state SessionState.LISTENING self.transcript [] self.intent None self.business_data {} self.fallback_count 0 def transition(self, new_state: SessionState) - bool: allowed { SessionState.LISTENING: {SessionState.THINKING, SessionState.ENDED}, SessionState.THINKING: {SessionState.SPEAKING, SessionState.ENDED}, SessionState.SPEAKING: {SessionState.LISTENING, SessionState.ENDED}, } if new_state in allowed[self.state]: self.state new_state return True return False sessions: dict[str, VoiceSession] {} app.websocket(/v1/session/{session_id}) async def voice_session_endpoint(ws: WebSocket, session_id: str): await ws.accept() session VoiceSession(session_idsession_id) sessions[session_id] session try: while True: event await ws.receive_json() if event[type] asr_text: if session.state SessionState.LISTENING: session.transcript.append(event[text]) session.intent await detect_intent(event[text]) session.transition(SessionState.THINKING) reply await generate_reply(session, event[text]) session.transition(SessionState.SPEAKING) await ws.send_json({type: tts, text: reply}) elif event[type] user_barge_in: # 用户打断Agent 停止播放并重新进入监听 session.transition(SessionState.LISTENING) elif event[type] call_end: session.transition(SessionState.ENDED) break except WebSocketDisconnect: session.transition(SessionState.ENDED) finally: await persist_session(session) sessions.pop(session_id, None) async def detect_intent(text: str) - str: # 生产环境用规则 分类模型不要只靠 LLM if 转人工 in text or 人工 in text: return human_handoff if 订单 in text or 物流 in text: return order_status if 升级 in text or 套餐 in text or 购买 in text: return sales_inquiry return support_other async def generate_reply(session: VoiceSession, text: str) - str: # 这里可以调用 Grok Voice 或同类对话模型也可以先返回静态话术 if session.intent human_handoff: return 好的我将为您转接人工坐席请稍候。 if session.intent order_status: return 请提供您的订单号我帮您查询订单进度。 return 请问您遇到的具体问题是什么是网络掉线、速度慢还是设备故障 async def persist_session(session: VoiceSession) - None: # 生产环境写入 PostgreSQL 或 ClickHouse print(fpersist {session.session_id}: {session.transcript})运行服务pip install fastapi uvicorn uvicorn voice_agent_server:app --host 0.0.0.0 --port 8000这段代码说明了一个关键点会话状态和业务决策不应该被 LLM 的提示词替代。意图识别、转人工和查单触发都显式写在代码里模型只负责生成话术。这样即使模型服务超时也能快速返回兜底话术。3.2 会话状态机的合法迁移关系状态机的价值是让每一步都有明确语义。上例中允许的迁移如下当前状态允许迁移到迁移原因LISTENINGTHINKINGASR 文本到达进入意图识别和回复生成LISTENINGENDED用户挂断THINKINGSPEAKING回复生成完成进入 TTSTHINKINGENDED通话中断或超时SPEAKINGLISTENING用户打断重新开始监听SPEAKINGENDED播放完成并继续下一轮或用户挂断注意实际项目中不要允许从 THINKING 直接回到 SPEAKING 再回到 THINKING 这种无限制循环。每一轮都要有最大重试次数。比如 ASR 置信度不足最多重复追问两次第三次转人工。否则用户会陷入“听不清-重说-再听不清”的死循环。3.3 对接 CRM 和订单/工单系统的边界语音 Agent 需要查询 Starlink 订单状态、账户余额、服务区覆盖、工单进度时应该通过后端封装好的业务接口获取不能直接让 LLM 生成 SQL 或调用内部服务。推荐的交互方式是“工具调用”。会话服务识别到意图后构造一个结构化工具调用请求{ type: tool_call, name: query_order_status, arguments: { order_id: ST-20250101-0001 }, auth_context: { account_id: acct_88421, csr_id: voice-agent-prod } }然后把工具返回结果放进提示词上下文再由 Grok Voice 类模型生成最终话术。这样做有三个好处业务权限集中在服务层控制语音 Agent 拿不到数据库凭据。工具返回的结构化字段可以直接做合规校验比如“预计送达时间不能随便承诺”。每次工具调用都能记录日志方便后续分析模型是否错误使用业务结果。4. 从单路并发到规模化服务的扩容路径4.1 用业务指标估算并发容量语音客服和销售系统必须按“忙时并发”设计而不是按“日通话量”设计。假设某地区忙时有 800 通呼叫请求平均每通通话 240 秒然后计算同时占用的 Agent 会话数。可以用一个粗略公式估算CPS 峰值呼叫量 / 3600每秒呼叫数。Erlang CPS * 平均处理时长表示同时占用的会话资源。如果忙时 800 通分布不均匀最集中 5 分钟内有 200 通则CPS 200 / 300 0.67Erlang 0.67 * 240 ≈ 160。也就是说至少需要能支撑 160 个并发语音会话的容量。再加上排队、重试、转人工等待建议预留 1.3 到 1.5 倍也就是 210 到 240 路并发。这个估算决定了后面所有扩容指标Kubernetes Pod 数量、WebSocket 连接数、模型推理并发度、TTS 并发度、数据库连接池大小。如果模型推理只能支持 20 并发而媒体服务能接入 200 路语音队列就会积压用户会听不到回复。4.2 语音网关与模型推理服务之间用队列削峰模型推理服务往往是整个链路里最慢、最不稳的环节。语音媒体流是实时的但业务回复不一定需要“逐字实时”。这里要区分两个概念音频流必须实时传输否则用户听到断续。语义回复可以有一次 200 到 800 毫秒的生成等待但不能超过 3 秒。所以媒体服务器和 ASR 之间要保持低延迟而 ASR 文本和 LLM 之间可以加入队列。当模型负载高时队列能把请求先缓冲起来避免丢弃呼叫。但队列也不能无限长必须设置最大等待时间。超过阈值后直接播放“当前话务繁忙请稍后再试”或转人工。# 使用 Redis Stream 做事件缓冲 redis-cli XADD voice:events * event_typeasr_text session_idabc123 text我的订单什么时候到消费端从 Stream 里读取事件执行业务接口和模型调用。这样媒体服务不需要关心模型是否繁忙它只负责把音频和事件交给下游。4.3 Kubernetes 自动扩缩容配置在线会话是典型的 Pod 级指标。建议用active_voice_sessions这个业务指标扩缩容而不是只依赖 CPU。因为一个会话可能大部分时间在等待 TTS 或业务接口CPU 不高但会话资源已占满。apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: voice-agent-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: voice-agent minReplicas: 3 maxReplicas: 50 metrics: - type: Pods pods: metric: name: active_voice_sessions target: type: AverageValue averageValue: 20这个配置的含义是当每个 Pod 平均活跃语音会话数超过 20 时HPA 自动扩容最多扩到 50 个副本。如果并发上量很快还需要结合 KEDA 或自定义调度器避免冷启动时间过长。生产环境建议预置一部分热 Pod防止突发拨入时被扩容延迟拖垮。4.4 学习环境、测试环境与生产环境的差异本地跑通上面的 FastAPI 骨架只算学习环境。测试环境要额外引入模拟电话网关、模拟 ASR、模拟订单接口构造脚本验证状态机。生产环境还要补齐以下能力配置外置模型服务地址、业务接口地址、阈值不要硬编码。权限隔离语音 Agent 服务只能调用白名单 API不能访问数据库。日志监控录音、转写、状态事件、模型响应时间要全链路关联。回滚方案模型服务版本和话术模板要支持快速回滚。压力测试用真实长度音频回放验证并发下是否出现静默或掉线。5. 可观测性、质量评估与人工接管5.1 每个会话至少沉淀三份数据语音客服系统的排障不能靠“复现”必须靠“回放”。每个会话建议保存三类数据录音文件对象存储保存路径关联会话 ID。转写文本和 ASR 置信度结构化存储。状态转移事件包括每轮状态、耗时、模型响应、工具调用结果。可以设计一张会话事件表字段示例说明session_id20250101-abc123全局会话 IDevent_time2025-01-01 10:00:03.122事件发生时间event_typeasr_text事件类型state_fromlistening上一个状态state_tothinking新状态text我的订单什么时候到转写或模型文本duration_ms345本阶段耗时model_namegrok-voice-v1模型版本confidence0.92ASR 置信度有了这三份数据才能回答“用户为什么没有转人工”“模型为什么推荐了错误套餐”“系统为什么卡了 8 秒”。5.2 语音客服核心指标建议至少监控四个层级接通层、交互层、模型层、业务层。指标作用参考观察重点接通率呼叫是否进入 Agent降低时看网关和资源平均静默时长用户等待回复时间超过 2 秒需关注模型/TTS 延迟ASR 置信度转写是否可靠低于 0.6 时追问或转人工转人工率服务能力边界过高说明自动化解题率不足会话解决率是否解决用户问题需要工单系统回传结果销售转化率销售会话是否成交需与订单/CRM 对账打断率用户是否频繁打断过高说明回复过长或不符合预期这些指标不是只在后台看而是必须落到会话级标签上。例如“这个会话转人工原因是 ASR 连续两轮低置信度”便于复盘。5.3 模型异常时的降级与人工接管即使 Grok Voice 类模型质量很高也不能假设它永远可用。超时、限流、内容安全拦截、上下文超长都可能导致回复失败。降级顺序要提前设计模型超时 2 秒重试一次。重试仍失败返回静态话术“请稍等我正在查询”。静态话术播放后 5 秒仍无法恢复播放“我将为您转接人工坐席”。同时把会话标记为degradedtrue触发人工坐席抢接。DEGRADED_RESPONSE 请稍等我正在为您查询。 async def generate_reply_with_fallback(session: VoiceSession, text: str): try: reply await asyncio.wait_for( call_llm(session, text), timeout2.0 ) return reply except asyncio.TimeoutError: session.fallback_count 1 if session.fallback_count 2: session.transition(SessionState.ENDED) await transfer_to_human(session.session_id) return 我将为您转接人工坐席请稍候。 return DEGRADED_RESPONSE生产环境里转人工不是简单发一个事件。要确保人工坐席能同时看到转写文本、客户资料、当前业务上下文否则用户还要把问题再重复一遍体验很差。6. 合规、风险与常见排错6.1 通话录音、语音数据和隐私合规语音客服系统天然采集用户声音这类数据属于敏感个人信息。上线前必须确认是否在通话开始时明确提示用户“本次通话可能被录音”。录音和转写文本是否存储在合规区域。语音数据的保存周期是否受限。用户要求删除数据时是否能从录音、转写、日志中同步删除。销售场景是否需要对成交客户做二次确认。这些不是技术博客能替代法务意见的内容但工程上必须在第一天设计删除接口和存证标记而不是等到监管要求时再补。6.2 销售话术里的“可预测元素”不能交给模型自由发挥Starlink 这类卫星互联网服务销售话术特别容易踩雷。AI 不能承诺“任何地方都能安装”“速度一定达到某数值”“雨天完全不受影响”。这类承诺涉及覆盖范围、天气衰减和安装条件必须由业务配置控制。可以建立话术模板列表模型只能基于模板生成变体不能自由编造。同时在回复给用户之前用规则引擎检查是否包含禁用词或承诺词。这就像 Ku 波段波形里的导频和其他可预测元素通信系统依靠可预测信号做同步语音销售系统也需要用可预测的模板、关键词、阈值来约束生成结果。没有这些约束模型会越说越具体最后造成客诉和合规风险。6.3 常见故障现象与排查顺序故障现象可能原因检查方式处理建议用户说话但 Agent 无响应VAD 没有识别到语音或 ASR 未输出文本检查媒体服务器音频流和 ASR 日志先确认是否有 RTP 包再查 ASR 超时配置用户听到回复但明显延迟LLM/TTS 耗时过高或排队过长查看事件表中 thinking 和 speaking 耗时压缩上下文、提升推理并发、优化 TTS 缓存ASR 转写文字完全错误口音、噪声、语速问题看 ASR 置信度分数和音频样本增加领域热词、训练语言模型、低置信度时追问转人工后坐席看不到上下文转人工事件没有把会话对象传过去查看转人工事件负载打通 CRM 工单 ID 和会话 ID多轮会话突然回到初始状态状态机没有持久化Pod 重启后会话丢失检查 session 存储和 WebSocket 重连逻辑使用 Redis 保存会话快照销售转化数据对不上CRM 记录和语音会话未关联检查订单接口参数统一 account_id 和 session_id 关联规则排查顺序建议先看会话事件表再看模型调用日志最后看音频文件。不要一开始就怀疑 Grok Voice 能力很多“模型答非所问”实际上是 ASR 转写错、业务接口返回错、上下文传错导致的。7. 上线前检查清单与后续扩展方向7.1 可复用的上线前置检查清单确认语音呼叫、ASR、Agent、TTS、CRM 五个环节之间都有唯一会话 ID。确认每个会话状态只能通过合法状态机迁移。确认 ASR 低置信度、模型超时、TTS 失败都有降级动作。确认销售话术经过规则引擎检查禁止出现绝对化承诺。确认转人工时坐席能拿到录音、转写、客户资料和业务上下文。确认录音删除接口和数据保留策略已实现。确认压测场景包含高峰并发、模型超时、ASR 乱码、转人工失败四类异常。确认模型版本和话术模板支持一键回滚。7.2 下一步扩展方向规模化的下一阶段可以考虑主动外呼、预测式外呼和情绪识别。主动外呼用于订单确认、续费提醒、故障回访。外呼比呼入更容易被投诉必须有严格时间窗口和退订机制。预测式外呼算法预测坐席空闲时间后自动拨号提高坐席利用率。但这套策略对语音 Agent 同样适用需要统计每个 Agent 的平均处理时长和转人工概率。情绪识别通过语速、音量、ASR 文本判断用户情绪在用户愤怒时快速转人工。情绪识别只能作为辅助信号不能单独决定话术。多语种也是 Starlink 这类全球化业务必须考虑的方向。不同语言的话术模板、ASR 模型、TTS 音色都要做独立配置和测试。7.3 一次规模化后的关键判断Grok Voice 这类模型能提供更自然的回复生成但规模化客服与销售系统的成败更多取决于工程控制面状态机是否正确、超时策略是否兜底、业务接口是否稳定、转人工是否顺畅、数据是否能回放。语音模型是这套系统的“表达层”不是“决策层”。对新团队而言下一步最有价值的事不是继续调模型提示词而是把真实通话样本、状态转移日志和人工坐席操作记录沉淀下来形成可评估、可回放、可迭代的数据闭环。