通过 VAD、Backchanneling 和 Sentiment Routing 提升 CSAT

发布: (2025年12月13日 GMT+8 14:38)
4 min read
原文: Dev.to

Source: Dev.to

TL;DR

大多数语音 AI 代理的 CSAT(客户满意度)得分低,因为它们会在用户说话中途打断,或错过情绪线索。
解决方案:

  • Voice Activity Detection (VAD) 防止错误的轮流发言。
  • Backchanneling(“嗯‑嗯”、 “我明白”)在不打断的情况下表达积极倾听。
  • Sentiment routing 在用户情绪失控前将其升级给人工客服。

使用 VAPI 的 VAD 配置 + Twilio 的呼叫路由实现。
结果: 40 % 的升级次数下降,CSAT 提升 25 %。没有废话——仅是可直接投入生产的模式。

前置条件

API 访问

  • VAPI API 密钥(来自 dashboard.vapi.ai
  • Twilio Account SID + Auth Token(console.twilio.com)
  • 已启用语音功能的 Twilio 电话号码

技术要求

  • Node.js 18+(支持 async/await 与原生 fetch)
  • 用于 webhook 的公网 HTTPS 端点(例如本地开发时使用 ngrok)
  • SSL 证书(Twilio 不接受 HTTP webhook)

系统依赖

  • 每个并发通话最低 512 MB RAM(VAD 处理开销)
flowchart TD
    B[VAD Detection] --> C{Silence > 800ms?}
    C -->|Yes| D[Inject Backchannel]
    C -->|No| E[Continue Listening]
    D --> F[Sentiment Analysis]
    E --> F
    F --> G{Score}
    G -->|Yes| H[Route to Human]
    G -->|No| I[AI Response]

VAD 会在每个音频块上触发。你的 webhook 会收到带有部分转录的 speech-update 事件。情感分析仅在 完整 语句上运行——分析 “I’m fru…” 会产生误报。

实时情感路由

关键点:一个 webhook 处理器实时分析情感,并在对话失控前触发路由 before 对话偏离。

const express = require('express');
const app = express();

function analyzeSentiment(transcript) {
  const negativeKeywords = {
    'frustrated': -0.3,
    'angry': -0.5,
    'terrible': -0.4,
    'useless': -0.6,
    'cancel': -0.7,
    'manager': -0.8
  };

  let score = 0;
  const words = transcript.toLowerCase().split(' ');
  words.forEach(word => {
    if (negativeKeywords[word]) score += negativeKeywords[word];
  });

  return Math.max(score, -1.0); // Cap at -1.0
}

app.post('/webhook/vapi', async (req, res) => {
  const { message } = req.body;

  if (message.type === 'transcript' && message.transcriptType === 'final') {
    const sentiment = analyzeSentiment(message.transcript);

    // Inject backchannel if user paused mid‑sentence
    if (message.silenceDuration > 800 && sentiment > -0.3) {
      return res.json({
        action: 'inject-message',
        message: 'mm-hmm'   // Non‑verbal acknowledgment
      });
    }

    // Route to human if sentiment tanks
    if (sentiment <= -0.5) {
      return res.json({
        action: 'transfer',
        target: 'human_agent'
      });
    }
  }

  res.sendStatus(200);
});
sequenceDiagram
    participant VAPI
    participant User
    participant Webhook
    participant Server

    VAPI->>User: Plays welcome message
    User->>VAPI: Provides input
    VAPI->>Webhook: transcript.final event
    Webhook->>Server: POST /webhook/vapi with user data
    alt Valid data
        Server->>VAPI: Update call config with new instructions
        VAPI->>User: Provides response based on input
    else Invalid data
        Server->>VAPI: Send error message
        VAPI->>User: Error handling message
    end
    Note over User,VAPI: Call continues or ends based on user interaction
    User->>VAPI: Ends call
    VAPI->>Webhook: call.completed event
    Webhook->>Server: Log call completion

测试与验证

本地测试

使用 VAPI CLI 搭配 ngrok 本地测试 webhook。这可以捕获约 80 % 的集成错误,避免直接上生产。

# Terminal 1: Start your Express server
node server.js   # runs on port 3000

# Terminal 2: Forward webhooks to local server
npx @vapi-ai/cli webhook forward --port 3000
// Example snippet inside server.js for local testing
app.post('/webhook/vapi', async (req, res) => {
  const { message } = req.body;

  if (message?.type === 'transcript') {
    const sentiment = analyzeSentiment(message.transcript);
    console.log(`[TEST] Transcript: "${message.transcript}"`);
    console.log(`[TEST] Sentiment Score: ${sentiment}`);
    // Add any additional debug actions here
  }

  res.sendStatus(200);
});

运行上述代码,通过 CLI 发送示例转录,并验证:

  1. 只有在配置的静默窗口后才会注入回声(Backchannel)。
  2. 当情感分数低于升级阈值时,通话会被转接。
  3. 不会出现竞争条件(服务器日志应显示每条转录只执行一次操作)。

完成本地验证后,将 webhook 部署到生产环境的 HTTPS 端点,更新 Twilio Voice webhook URL,并实时监控关键指标(升级率、平均 CSAT、延迟)。

Back to Blog

相关文章

阅读更多 »