实时语音代理

实时代理通过双向音频流实现与 AI 助手的语音交互。adk-realtime crate 提供了一个统一的接口,用于构建支持 OpenAI's Realtime APIGoogle's Gemini Live API 的语音代理。

概述

实时代理与基于文本的 LlmAgent 在几个关键方面有所不同:

功能LlmAgentRealtimeAgent
输入文本音频/文本
输出文本音频/文本
连接HTTP 请求WebSocket
延迟请求/响应实时流
VAD不适用服务器端语音检测

架构

              ┌─────────────────────────────────────────┐
              │                代理特质                 │
              │  (name, description, run, sub_agents)   │
              └────────────────┬────────────────────────┘
                               │
       ┌───────────────────────┼───────────────────────┐
       │                       │                       │
┌──────▼──────┐      ┌─────────▼─────────┐   ┌─────────▼─────────┐
│  LlmAgent   │      │  RealtimeAgent    │   │  SequentialAgent  │
│ (基于文本)│      │   (基于语音)    │   │     (工作流)    │
└─────────────┘      └───────────────────┘   └───────────────────┘

RealtimeAgent 实现了与 LlmAgent 相同的 Agent 特质,共享以下功能:

  • 指令(静态和动态)
  • 工具注册和执行
  • 回调(before_agent, after_agent, before_tool, after_tool)
  • 子代理切换

快速入门

安装

添加到你的 Cargo.toml

[dependencies]
adk-realtime = { version = "0.2.0", features = ["openai"] }

基本用法

use adk_realtime::{
    RealtimeAgent, RealtimeModel, RealtimeConfig, ServerEvent,
    openai::OpenAIRealtimeModel,
};
use std::sync::Arc;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api_key = std::env::var("OPENAI_API_KEY")?;

    // Create the realtime model
    let model: Arc<dyn RealtimeModel> = Arc::new(
        OpenAIRealtimeModel::new(&api_key, "gpt-4o-realtime-preview-2024-12-17")
    );

    // Build the realtime agent
    let agent = RealtimeAgent::builder("voice_assistant")
        .model(model.clone())
        .instruction("You are a helpful voice assistant. Be concise.")
        .voice("alloy")
        .server_vad()  // Enable voice activity detection
        .build()?;

    // Or use the low-level session API directly
    let config = RealtimeConfig::default()
        .with_instruction("You are a helpful assistant.")
        .with_voice("alloy")
        .with_modalities(vec!["text".to_string(), "audio".to_string()]);

    let session = model.connect(config).await?;

    // Send text and get response
    session.send_text("Hello!").await?;
    session.create_response().await?;

    // Process events
    while let Some(event) = session.next_event().await {
        match event? {
            ServerEvent::TextDelta { delta, .. } => print!("{}", delta),
            ServerEvent::AudioDelta { delta, .. } => {
                // Play audio (delta is base64-encoded PCM)
            }
            ServerEvent::ResponseDone { .. } => break,
            _ => {}
        }
    }

    Ok(())
}

支持的提供商

提供商ModelFeature Flag音频格式
OpenAIgpt-4o-realtime-preview-2024-12-17openaiPCM16 24kHz
OpenAIgpt-realtimeopenaiPCM16 24kHz
Googlegemini-2.0-flash-live-preview-04-09geminiPCM16 16kHz/24kHz

注意gpt-realtime 是 OpenAI 最新的实时模型,具有改进的语音质量、情感和函数调用能力。

RealtimeAgent Builder

RealtimeAgentBuilder 提供了一个流畅的 API,用于配置 Agent:

let agent = RealtimeAgent::builder("assistant")
    // 必需
    .model(model)

    // 指令 (与 LlmAgent 相同)
    .instruction("You are helpful.")
    .instruction_provider(|ctx| format!("User: {}", ctx.user_name()))

    // 语音设置
    .voice("alloy")  // 选项:alloy, coral, sage, shimmer 等
    
    // 语音活动检测
    .server_vad()  // 使用默认值
    .vad(VadConfig {
        mode: VadMode::ServerVad,
        threshold: Some(0.5),
        prefix_padding_ms: Some(300),
        silence_duration_ms: Some(500),
        interrupt_response: Some(true),
        eagerness: None,
    })

    // 工具 (与 LlmAgent 相同)
    .tool(Arc::new(weather_tool))
    .tool(Arc::new(search_tool))

    // 用于交接的子Agent
    .sub_agent(booking_agent)
    .sub_agent(support_agent)

    // 回调 (与 LlmAgent 相同)
    .before_agent_callback(|ctx| async { Ok(()) })
    .after_agent_callback(|ctx, event| async { Ok(()) })
    .before_tool_callback(|ctx, tool, args| async { Ok(None) })
    .after_tool_callback(|ctx, tool, result| async { Ok(result) })

    // 实时特定回调
    .on_audio(|audio_chunk| { /* 播放音频 */ })
    .on_transcript(|text| { /* 显示转录 */ })

    .build()?;

语音活动检测 (VAD)

VAD 通过检测用户何时开始和停止说话,实现自然的对话流程。

服务端 VAD (推荐)

let agent = RealtimeAgent::builder("assistant")
    .model(model)
    .server_vad()  // 使用合理默认值
    .build()?;

自定义 VAD 配置

use adk_realtime::{VadConfig, VadMode};

let vad = VadConfig {
    mode: VadMode::ServerVad,
    threshold: Some(0.5),           // 语音检测灵敏度 (0.0-1.0)
    prefix_padding_ms: Some(300),   // 语音前要包含的音频
    silence_duration_ms: Some(500), // 结束回合前的静默时间
    interrupt_response: Some(true), // 允许打断助理
    eagerness: None,                // 用于 SemanticVad 模式
};

let agent = RealtimeAgent::builder("assistant")
    .model(model)
    .vad(vad)
    .build()?;

Semantic VAD (Gemini)

对于 Gemini 模型,您可以使用考虑语义的 semantic VAD:

let vad = VadConfig {
    mode: VadMode::SemanticVad,
    eagerness: Some("high".to_string()),  // low, medium, high
    ..Default::default()
};

工具调用

实时代理在语音对话期间支持工具调用:

use adk_realtime::{config::ToolDefinition, ToolResponse};
use serde_json::json;

// Define tools
let tools = vec![
    ToolDefinition {
        name: "get_weather".to_string(),
        description: Some("Get weather for a location".to_string()),
        parameters: Some(json!({
            "type": "object",
            "properties": {
                "location": { "type": "string" }
            },
            "required": ["location"]
        })),
    },
];

let config = RealtimeConfig::default()
    .with_tools(tools)
    .with_instruction("Use tools to help the user.");

let session = model.connect(config).await?;

// Handle tool calls in the event loop
while let Some(event) = session.next_event().await {
    match event? {
        ServerEvent::FunctionCallDone { call_id, name, arguments, .. } => {
            // Execute the tool
            let result = execute_tool(&name, &arguments);

            // Send the response
            let response = ToolResponse::new(&call_id, result);
            session.send_tool_response(response).await?;
        }
        _ => {}
    }
}

多代理移交

在专用代理之间转移对话:

// Create sub-agents
let booking_agent = Arc::new(RealtimeAgent::builder("booking_agent")
    .model(model.clone())
    .instruction("Help with reservations.")
    .build()?);

let support_agent = Arc::new(RealtimeAgent::builder("support_agent")
    .model(model.clone())
    .instruction("Help with technical issues.")
    .build()?);

// Create main agent with sub-agents
let receptionist = RealtimeAgent::builder("receptionist")
    .model(model)
    .instruction(
        "Route customers: bookings → booking_agent, issues → support_agent. \
         Use transfer_to_agent tool to hand off."
    )
    .sub_agent(booking_agent)
    .sub_agent(support_agent)
    .build()?;

当模型调用 transfer_to_agent 时,RealtimeRunner 会自动处理移交。

音频格式

格式采样率位深声道用例
PCM1624000 Hz16单声道OpenAI (默认)
PCM1616000 Hz16单声道Gemini 输入
G711 u-law8000 Hz8单声道电话系统
G711 A-law8000 Hz8单声道电话系统
use adk_realtime::{AudioFormat, AudioChunk};

// Create audio format
let format = AudioFormat::pcm16_24khz();

// Work with audio chunks
let chunk = AudioChunk::new(audio_bytes, format);
let base64 = chunk.to_base64();
let decoded = AudioChunk::from_base64(&base64, format)?;

事件类型

服务器事件

事件描述
SessionCreated连接已建立
AudioDelta音频块 (base64 PCM)
TextDelta文本响应块
TranscriptDelta输入音频转录
FunctionCallDone工具调用请求
ResponseDone响应已完成
SpeechStartedVAD 检测到语音开始
SpeechStoppedVAD 检测到语音结束
Error发生错误

客户端事件

事件描述
AudioInput发送音频块
AudioCommit提交音频缓冲区
ItemCreate发送文本或工具响应
CreateResponse请求响应
CancelResponse取消当前响应
SessionUpdate更新配置

示例

运行包含的示例:

# Basic text-only session
cargo run --example realtime_basic --features realtime-openai

# Voice assistant with VAD
cargo run --example realtime_vad --features realtime-openai

# Tool calling
cargo run --example realtime_tools --features realtime-openai

# Multi-agent handoffs
cargo run --example realtime_handoff --features realtime-openai

最佳实践

  1. 使用服务器VAD:让服务器处理语音检测以降低延迟
  2. 处理中断:启用 interrupt_response 以实现自然对话
  3. 保持指令简洁:语音响应应简短
  4. 首先用文本测试:在添加音频之前,先用文本调试你的 Agent 逻辑
  5. 优雅地处理错误:网络问题在使用 WebSocket 连接时很常见

与 OpenAI Agents SDK 的比较

adk-rust 的实时实现遵循 OpenAI Agents SDK 模式:

功能OpenAI SDKadk-rust
Agent 基类AgentAgent trait
实时 AgentRealtimeAgentRealtimeAgent
工具函数定义Tool trait + ToolDefinition
切换transfer_to_agentsub_agents + 自动生成的工具
回调钩子before_* / after_* callbacks

上一页: ← 图 Agent | 下一页: 模型提供商 →