文章目录
- 实时 API(Beta)
- 使用实时API入门
- 示例应用
- 合作伙伴集成
- 用例
- 通过 WebRTC 连接
- 概述
- 连接详情
- 创建一个临时token
- 发送和接收事件
- 使用 WebSockets 连接
- 概述
- 连接详情
- 实时对话Beta
- 实时语音到语音会话
- 会话生命周期事件
- 文本输入和输出
- 音频输入和输出
- 语音选项
- 使用 WebRTC 处理音频
- WebRTC 中的客户端和服务器音频事件
- 使用 WebSockets 处理音频
- 将音频输入流式传输到服务器
- 发送完整音频消息
- 使用WebSocket处理音频输出
- 语音活动检测
- 禁用 VAD
- 保持VAD模式,但禁用自动响应
- 在默认对话之外创建响应
- 为响应创建自定义上下文
- 使用无上下文创建响应
- 函数调用
- 配置可调用的函数
- 检测模型何时想要调用函数
- 向模型提供函数调用的结果
- 错误处理
- 实时转录Beta
- 实时转录会话
- 处理转录
- 语音活动检测
- 额外配置
- 噪声降低
- 使用 logprobs
- 语音活动检测 (VAD)Beta
- 概述
- 服务器VAD
- 语义语音活动检测(Semantic VAD)
实时 API(Beta)
使用实时 API 构建低延迟、多模态的体验。
https://platform.openai.com/docs/guides/realtime
The OpenAI 实时 API 允许低延迟、多模态交互,包括语音到语音的对话体验和实时转录。
此API与原生的多模态模型(如 GPT-4o 和 GPT-4o mini)兼容,提供实时文本和音频处理、函数调用和语音生成等功能,以及最新的转录模型 GPT-4o Transcribe 和 GPT-4o mini Transcribe。
使用实时API入门
您可以通过两种方式连接到实时API:
- 使用 WebRTC,它非常适合客户端应用程序(例如,一个网页应用)
- 使用 WebSockets,这对于服务器到服务器的应用程序非常出色(例如,如果你的后端或你正在为电话构建语音代理)
开始探索下面的示例和合作伙伴集成,或者学习如何使用最适合您用例的方法连接到实时API。
示例应用
查看以下示例应用之一,以查看实时API的实际应用。
实时控制台
要快速开始,下载并配置实时控制台演示。查看事件来回流动,并检查它们的内容。学习如何通过函数调用执行自定义逻辑。
https://github.com/openai/openai-realtime-console
实时太阳系演示
一个使用WebRTC集成的实时API演示,通过功能调用通过语音导航太阳系。
https://github.com/openai/openai-realtime-solar-system
Twilio 集成演示
一个结合Realtime API和Twilio构建AI电话助手的演示。
https://github.com/openai/openai-realtime-twilio-demo
实时 API 代理演示
A 演示实时 API 语音代理之间的交接以及推理模型验证。
https://github.com/openai/openai-realtime-agents
合作伙伴集成
查看这些合作伙伴集成,它们在前端应用程序和电话用例中使用实时API。
LiveKit集成指南
如何使用实时API与LiveKit的WebRTC基础设施。
https://docs.livekit.io/agents/openai/overview/
Twilio集成指南
使用 Twilio 强大的语音 API 构建实时应用程序。
https://www.twilio.com/en-us/blog/twilio-openai-realtime-api-launch-integration
Agora 集成快速入门
如何将 Agora 的实时音频通信功能与 Realtime API 集成。
https://docs.agora.io/en/open-ai-integration/get-started/quickstart
Pipecat集成指南
创建使用 OpenAI 音频模型和 Pipecat 协奏框架的语音代理。
https://docs.pipecat.ai/guides/features/openai-audio-models-and-apis
客户端工具调用
使用 Cloudflare Workers 构建,一个展示客户端工具调用的示例应用程序。也请查看YouTube 上的教程。
https://github.com/craigsdennis/talk-to-javascript-openai-workers
用例
Realtime API 最常见的用例是构建实时、语音到语音、对话式的体验。这对于构建 语音代理 和其他带语音功能的应用程序来说非常出色。
Realtime API 还可以独立用于转录和轮次检测用例。客户端可以流式传输音频,当检测到语音时,Realtime API 会生成流式转录。
这两个用例都受益于内置的 语音活动检测 (VAD),可以自动检测用户何时完成说话。这有助于无缝处理对话轮次,或者逐句分析转录。
在专门的指南中了解更多关于这些用例的信息。
实时语音到语音
学习如何使用 Realtime API 进行流式语音到语音对话。
https://platform.openai.com/docs/guides/realtime-conversations
实时转录
学习如何使用 Realtime API 进行仅转录的用例。
https://platform.openai.com/docs/guides/realtime-transcription
根据您的用例(对话或转录),您应该以不同的方式初始化会话。使用下面的切换器查看每种情况的详细信息。
通过 WebRTC 连接
WebRTC 是一套强大的标准接口,用于构建实时应用。OpenAI 实时 API 支持通过 WebRTC 服务器间连接连接到实时模型。按照以下指南了解如何配置 WebRTC 连接到实时 API。
概述
在您希望从不受信任的客户端(如网页浏览器)通过网络连接到实时模型的情况下,我们建议使用 WebRTC 连接方法。WebRTC 更适合处理可变连接状态,并提供了一系列方便的 API 用于捕获用户音频输入和播放来自模型的远程音频流。
从浏览器连接到实时 API 应该使用一个临时 API 密钥,通过 OpenAI REST API 生成。初始化 WebRTC 连接的过程如下(假设客户端是网页浏览器):
- 浏览器向开发者控制的服务器发送请求,以创建一个临时 API 密钥。
- 开发者的服务器使用一个 标准 API 密钥 从 OpenAI REST API 请求一个临时密钥,并将这个新密钥返回给浏览器。请注意,临时密钥目前在被颁发后一分钟内过期。
- 浏览器使用临时密钥直接通过 WebRTC 互连 验证与 OpenAI 实时 API 的会话。

虽然从技术上讲,可以使用 标准API密钥 来验证客户端WebRTC会话,但 这种做法是危险且不安全的,因为它会泄露您的密钥。标准API密钥可以访问您的完整OpenAI API账户,并且应该仅在安全的服务器端环境中使用。我们建议在可能的情况下,在客户端应用程序中使用临时密钥。
连接详情
通过 WebRTC 连接需要以下连接信息:
URL | https://api.openai.com/v1/realtime |
---|---|
查询参数 | model 要连接的实时 模型 ID,例如 gpt-4o-realtime-preview-2024-12-17 |
头部 | Authorization: Bearer EPHEMERAL_KEY 用临时 API 密钥替换 EPHEMERAL_KEY - 有关如何生成一个的详细信息见下文。 |
以下示例展示了如何初始化一个 WebRTC 会话(包括用于发送和接收实时 API 事件的 数据通道)。它假设您已经获取了一个临时 API 密钥(用于此目的的示例服务器代码可以在 下一节 中找到)。
async function init() {
// Get an ephemeral key from your server - see server code below
const tokenResponse = await fetch("/session");
const data = await tokenResponse.json();
const EPHEMERAL_KEY = data.client_secret.value;
// Create a peer connection
const pc = new RTCPeerConnection();
// Set up to play remote audio from the model
const audioEl = document.createElement("audio");
audioEl.autoplay = true;
pc.ontrack = e => audioEl.srcObject = e.streams[0];
// Add local audio track for microphone input in the browser
const ms = await navigator.mediaDevices.getUserMedia({
audio: true
});
pc.addTrack(ms.getTracks()[0]);
// Set up data channel for sending and receiving events
const dc = pc.createDataChannel("oai-events");
dc.addEventListener("message", (e) => {
// Realtime server events appear here!
console.log(e);
});
// Start the session using the Session Description Protocol (SDP)
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const baseUrl = "https://api.openai.com/v1/realtime";
const model = "gpt-4o-realtime-preview-2024-12-17";
const sdpResponse = await fetch(`${baseUrl}?model=${model}`, {
method: "POST",
body: offer.sdp,
headers: {
Authorization: `Bearer ${EPHEMERAL_KEY}`,
"Content-Type": "application/sdp"
},
});
const answer = {
type: "answer",
sdp: await sdpResponse.text(),
};
await pc.setRemoteDescription(answer);
}
init();
WebRTC API 提供了丰富的控件来处理媒体流和输入设备。有关在 WebRTC 上构建用户界面的更多指导,请参阅 MDN 上的文档。
创建一个临时token
要创建一个用于客户端的临时token ,您需要构建一个小的服务器端应用程序(或集成现有的一个)来通过 OpenAI REST API 请求一个临时密钥。您将使用一个 标准 API 密钥 在您的后端服务器上对这次请求进行身份验证。
以下是一个简单的 Node.js express 服务器示例,它使用 REST API 签发一个临时 API 密钥:
import express from "express";
const app = express();
// An endpoint which would work with the client code above - it returns
// the contents of a REST API request to this protected endpoint
app.get("/session", async (req, res) => {
const r = await fetch("https://api.openai.com/v1/realtime/sessions", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.OPENAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gpt-4o-realtime-preview-2024-12-17",
voice: "verse",
}),
});
const data = await r.json();
// Send back the JSON we received from the OpenAI REST API
res.send(data);
});
app.listen(3000);
您可以在任何可以发送和接收HTTP请求的平台创建一个类似这样的服务器端点。只需确保您只在服务器上使用标准的OpenAI API密钥,而不是在浏览器中。
发送和接收事件
要了解如何通过WebRTC数据通道发送和接收事件,请参阅实时对话指南。
使用 WebSockets 连接
WebSockets 是一个广泛支持的实时数据传输 API,也是连接到 OpenAI 实时 API 在服务器到服务器应用中的绝佳选择。对于浏览器和移动客户端,我们建议通过 WebRTC 进行连接。
概述
在与 Realtime 的服务器到服务器集成中,您的后端系统将通过 WebSocket 直接连接到 Realtime API。您可以使用 标准 API 密钥 来验证此连接,因为token 只能在您的安全后端服务器上可用。
如果您选择通过客户端设备上的 WebSocket 连接到 Realtime API,则 WebSocket 连接也可以使用临时客户端令牌进行身份验证(如上文 WebRTC 部分所示)。
标准 OpenAI API 令牌应仅用于安全的服务器端环境。
连接详情
语音到语音转录
通过WebSocket连接需要以下连接信息:
URL | wss://api.openai.com/v1/realtime |
---|---|
查询参数 | model 要连接的实时 模型ID,例如 gpt-4o-realtime-preview-2024-12-17 |
头部 | Authorization: Bearer YOUR_API_KEY 将 YOUR_API_KEY 替换为服务器上的 标准API密钥,或在非安全客户端上的 临时token (注意,对于此用例,建议使用WebRTC)。OpenAI-Beta: realtime=v1 在测试期间,此头部是必需的。 |
以下是一些使用这些连接详情初始化WebSocket连接到实时API的示例。
ws模块(Node.js)websocket-client(Python)WebSocket(浏览器)
使用ws模块(Node.js)进行连接
import WebSocket from "ws";
const url = "wss://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview-2024-12-17";
const ws = new WebSocket(url, {
headers: {
"Authorization": "Bearer " + process.env.OPENAI_API_KEY,
"OpenAI-Beta": "realtime=v1",
},
});
ws.on("open", function open() {
console.log("Connected to server.");
});
ws.on("message", function incoming(message) {
console.log(JSON.parse(message.toString()));
});
实时对话Beta
了解如何管理实时语音到语音对话。
https://platform.openai.com/docs/guides/realtime-conversations
一旦通过WebRTC或WebSocket连接到实时API,您就可以调用实时模型(例如gpt-4o-realtime-preview)进行语音到语音的对话。这样做需要您发送客户端事件来启动操作,并监听服务器事件以响应实时API采取的操作。
本指南将介绍使用模型功能(如音频和文本生成以及功能调用)所需的事件流程,以及如何考虑实时会话的状态。
如果您不需要与模型进行对话,即您不期望任何响应,您可以使用实时 API 的 转录模式。
实时语音到语音会话
实时会话是模型与连接客户端之间的有状态交互。会话的关键组件包括:
- 会话对象,它控制交互的参数,如使用的模型、生成输出的声音以及其他配置。
- 对话,它表示当前会话期间产生的用户输入项和模型输出项。
- 响应,这是模型生成的音频或文本项,被添加到对话中。
输入音频缓冲区和WebSockets
如果您使用WebRTC,发送和接收模型音频所需的媒体处理的大部分工作都由WebRTC API辅助完成。
如果您使用WebSockets进行音频传输,您需要手动与输入音频缓冲区进行交互,通过发送音频到服务器,这些音频以JSON事件的形式发送,并使用base64编码。
所有这些组件共同构成了一个实时会话。您将使用客户端事件来更新会话的状态,并监听服务器事件以响应会话中的状态变化。
会话生命周期事件
通过 WebRTC 或 WebSockets 初始化会话后,服务器将发送一个 session.created
事件,表示会话已准备好。在客户端,您可以使用 session.update
事件更新当前会话配置。大多数会话属性可以在任何时间更新,但模型在会话中响应音频一次后,用于音频输出的 voice
无法更新。实时会话的最大时长为 30分钟。
以下示例展示了使用 session.update
客户端事件更新会话。有关在这些通道上发送客户端事件的更多信息,请参阅 WebRTC 或 WebSocket 指南。
更新此会话中模型使用的系统指令
event = {
"type": "session.update",
"session": {
"instructions": "Never use the word 'moist' in your responses!"
}
}
ws.send(json.dumps(event))
当会话被更新后,服务器将发出一个 session.updated
(https://platform.openai.com/docs/api-reference/realtime-server-events/session/updated) 事件,包含会话的新状态。
相关客户端事件 | 相关服务器事件 |
---|---|
session.update | session.created session.updated |
文本输入和输出
要使用实时模型生成文本,您可以向当前对话中添加文本输入,要求模型生成响应,并监听表示模型响应进度的服务器发送事件。为了生成文本,会话必须配置为使用 text
模式(默认情况下是这样)。
使用 conversation.item.create
客户端事件创建一个新的文本对话项。这类似于在 Chat Completions 中发送一个用户消息(提示)。
创建一个包含用户输入的对话项
event = {
"type": "conversation.item.create",
"item": {
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "What Prince album sold the most copies?",
}
]
}
}
ws.send(json.dumps(event))
在将用户消息添加到对话后,发送 response.create
事件 以从模型中启动响应。如果当前会话启用了音频和文本,则模型将以音频和文本内容进行响应。如果您只想生成文本,可以在发送 response.create
客户端事件时指定,如下所示。
生成纯文本响应
event = {
"type": "response.create",
"response": {
"modalities": [ "text" ]
}
}
ws.send(json.dumps(event))
当响应完全完成后,服务器将发出response.done
事件。此事件将包含模型生成的完整文本,如下所示。
监听 response.done 以查看最终结果
def on_message(ws, message):
server_event = json.loads(message)
if server_event.type == "response.done":
print(server_event.response.output[0])
在模型响应生成过程中,服务器将在处理过程中发出一系列生命周期事件。您可以监听这些事件,例如response.text.delta
,以在响应生成时向用户提供实时反馈。服务器发出的所有事件列表如下,在相关服务器事件部分。它们按照事件发出的顺序提供,以及与文本生成相关的客户端事件。
相关客户端事件 | 相关服务器事件 |
---|---|
conversation.item.create response.create | conversation.item.created response.created response.output_item.added response.content_part.added response.text.delta response.text.done response.content_part.done response.output_item.done response.done rate_limits.updated |
音频输入和输出
Realtime API 最强大的功能之一是与模型进行语音到语音的交互,无需中间的文本到语音或语音到文本步骤。这使语音界面的延迟更低,并给模型提供了更多关于语音输入的语调和语气的数据来处理。
语音选项
实时会话可以配置为在生成音频输出时使用几个内置语音之一。您可以在会话创建时(或在 response.create
上)设置 voice
来控制模型的声音。当前语音选项有 alloy
、ash
、ballad
、coral
、echo
、sage
、shimmer
和 verse
。一旦模型在一个会话中发出音频,该会话的 voice
就不能修改。
使用 WebRTC 处理音频
如果您使用 WebRTC 连接到实时 API,实时 API 正在充当您的客户端的 peer connection。模型输出的音频以 remote media stream 的形式发送到您的客户端。模型输入的音频通过音频设备(getUserMedia
)收集,并将媒体流作为轨道添加到 peer connection。
来自 WebRTC 连接指南 的示例代码展示了使用浏览器 API 配置本地和远程音频的基本示例:
// Create a peer connection
const pc = new RTCPeerConnection();
// Set up to play remote audio from the model
const audioEl = document.createElement("audio");
audioEl.autoplay = true;
pc.ontrack = e => audioEl.srcObject = e.streams[0];
// Add local audio track for microphone input in the browser
const ms = await navigator.mediaDevices.getUserMedia({
audio: true
});
pc.addTrack(ms.getTracks()[0]);
上面的代码片段可以启用与实时API的简单交互,但还有更多可以做的事情。有关不同类型用户界面的更多示例,请查看WebRTC samples存储库。这些样本的实时演示也可以在这里找到。
使用 媒体捕获和流 浏览器中的功能,您可以实现诸如静音和取消静音麦克风、选择收集输入的设备等功能。
WebRTC 中的客户端和服务器音频事件
默认情况下,WebRTC 客户端在发送音频输入之前不需要向实时 API 发送任何客户端事件。一旦将本地音频轨道添加到对等连接中,您的用户就可以开始说话了!
然而,当音频在客户端和服务器之间通过对等连接来回传输时,WebRTC 客户端仍然会接收到许多由服务器发送的生命周期事件。例如:
- 当输入通过本地媒体轨道发送时,您将从服务器接收到
input_audio_buffer.speech_started
事件。 - 当本地音频输入停止时,您将接收到
input_audio_buffer.speech_stopped
事件。 - 您将接收到 正在进行中的音频转录的 delta 事件。
- 当模型转录并完成发送响应时,您将接收到
response.done
事件。
操作 WebRTC API 以获取媒体流可能为您提供所需的所有控制。然而,有时可能需要使用更底层的接口来处理音频输入和输出。有关更多信息以及用于细粒度音频输入处理所需的事件列表,请参阅下方的 WebSockets 部分。
使用 WebSockets 处理音频
在通过 WebSocket 发送和接收音频时,您需要做更多的工作来从客户端发送媒体,并从服务器接收媒体。以下是一个表格,描述了在 WebSocket 会话期间的事件流程,这些事件对于通过 WebSocket 发送和接收音频是必要的。
以下事件按生命周期顺序给出,尽管某些事件(如 delta
事件)可能同时发生。
生命周期阶段 | 客户端事件 | 服务器事件 |
---|---|---|
会话初始化 | session.update | session.created session.updated |
用户音频输入 | conversation.item.create (发送整个音频消息) input_audio_buffer.append (分块流式传输音频) input_audio_buffer.commit (当 VAD 禁用时使用) response.create (当 VAD 禁用时使用) | input_audio_buffer.speech_started input_audio_buffer.speech_stopped input_audio_buffer.committed |
服务器音频输出 | input_audio_buffer.clear (当 VAD 禁用时使用) | conversation.item.created response.created response.output_item.created response.content_part.added response.audio.delta response.audio_transcript.delta response.text.delta response.audio.done response.audio_transcript.done response.text.done response.content_part.done response.output_item.done response.done rate_limits.updated |
将音频输入流式传输到服务器
要将音频输入流式传输到服务器,您可以使用客户端事件 input_audio_buffer.append
。此事件要求您通过套接字将 Base64 编码的音频字节块 发送到实时 API。每个块的大小不能超过 15 MB。
输入块格式可以配置为整个会话或每个响应。
- 会话:在
session.update
中的session.input_audio_format
- 响应:在
response.create
中的response.input_audio_format
将音频输入字节追加到对话中
import base64
import json
import struct
import soundfile as sf
from websocket import create_connection
# ... create websocket-client named ws ...
def float_to_16bit_pcm(float32_array):
clipped = [max(-1.0, min(1.0, x)) for x in float32_array]
pcm16 = b''.join(struct.pack('<h', int(x * 32767)) for x in clipped)
return pcm16
def base64_encode_audio(float32_array):
pcm_bytes = float_to_16bit_pcm(float32_array)
encoded = base64.b64encode(pcm_bytes).decode('ascii')
return encoded
files = [
'./path/to/sample1.wav',
'./path/to/sample2.wav',
'./path/to/sample3.wav'
]
for filename in files:
data, samplerate = sf.read(filename, dtype='float32')
channel_data = data[:, 0] if data.ndim > 1 else data
base64_chunk = base64_encode_audio(channel_data)
# Send the client event
event = {
"type": "input_audio_buffer.append",
"audio": base64_chunk
}
ws.send(json.dumps(event))
发送完整音频消息
也可以创建包含完整音频录音的对话消息。使用 conversation.item.create
客户端事件来创建包含 input_audio
内容的消息。
创建包含完整音频输入的对话项目
fullAudio = "<a base64-encoded string of audio bytes>"
event = {
"type": "conversation.item.create",
"item": {
"type": "message",
"role": "user",
"content": [
{
"type": "input_audio",
"audio": fullAudio,
}
],
},
}
ws.send(json.dumps(event))
使用WebSocket处理音频输出
要在客户端设备(如网页浏览器)上播放输出音频,我们建议使用WebRTC而不是WebSocket。WebRTC在发送媒体到客户端设备时,即使在不确定的网络条件下,也会更加稳健。
但是,要使用WebSocket在服务器到服务器的应用程序中处理音频输出,您需要监听包含从模型中编码的音频数据块的Base64编码的response.audio.delta
事件。您可能需要缓冲这些块并将它们写入文件,或者立即将它们流式传输到另一个源,例如与Twilio的电话通话。
请注意,response.audio.done
和response.done
事件实际上不会包含音频数据 - 只包含音频内容转录。要获取实际的字节,您需要监听response.audio.delta
事件。
输出块格式可以配置为整个会话或每个响应。
- 会话:在
session.update
中的session.output_audio_format
session.update - 响应:在
response.create
中的response.output_audio_format
response.create
监听response.audio.delta事件
def on_message(ws, message):
server_event = json.loads(message)
if server_event.type == "response.audio.delta":
# Access Base64-encoded audio chunks:
# print(server_event.delta)
语音活动检测
默认情况下,实时会话已启用 语音活动检测 (VAD),这意味着 API 将确定用户何时开始或停止说话,并自动响应。
了解更多关于如何配置 VAD 的信息,请参阅我们的 语音活动检测 指南。
禁用 VAD
可以通过将 turn_detection
设置为 null
并使用 session.update
客户端事件来禁用 VAD。这在需要精细控制音频输入的接口中非常有用,例如 push to talk 接口。
当 VAD 被禁用时,客户端将需要手动发出一些额外的客户端事件来触发音频响应:
- 手动发送
input_audio_buffer.commit
,这将为新对话创建一个新的用户输入项。 - 手动发送
response.create
以触发模型生成的音频响应。 - 在开始新的用户输入之前发送
input_audio_buffer.clear
。
保持VAD模式,但禁用自动响应
如果您想保持VAD模式开启,但只想保留手动决定何时生成响应的能力,您可以将 turn_detection.interrupt_response
和 turn_detection.create_response
设置为 false
,使用 session.update
(会话更新)客户端事件。这将保留VAD的所有行为,但不会自动创建新的响应。客户端可以使用 response.create
(创建响应)事件手动触发这些操作。
这在用于内容审核或输入验证或RAG模式时可能很有用,在这些模式中,您更愿意在交互的延迟与对输入的控制之间进行权衡。
在默认对话之外创建响应
默认情况下,在会话期间生成的所有响应都会添加到会话的对话状态(即“默认对话”)中。然而,您可能希望在不属于会话默认对话的上下文中生成模型响应,或者希望同时生成多个响应。您还可能希望对模型在生成响应时考虑的对话项有更精细的控制(例如,仅考虑最后 N 个回合)。
通过在创建响应时将 response.conversation
字段设置为字符串 none
,可以使用 response.create
客户端事件生成不属于默认对话状态的“场外”响应。
在创建场外响应时,您可能还希望有一种方式来识别哪些服务器发送的事件与该响应相关。您可以为模型响应提供 metadata
,这有助于您识别为该客户端发送的事件生成的哪个响应。
创建一个场外模型响应
prompt = """
Analyze the conversation so far. If it is related to support, output
"support". If it is related to sales, output "sales".
"""
event = {
"type": "response.create",
"response": {
# Setting to "none" indicates the response is out of band,
# and will not be added to the default conversation
"conversation": "none",
# Set metadata to help identify responses sent back from the model
"metadata": { "topic": "classification" },
# Set any other available response fields
"modalities": [ "text" ],
"instructions": prompt,
},
}
ws.send(json.dumps(event))
现在,当您监听 response.done
服务器事件时,您可以识别出您的非带外响应的结果。
创建一个带外模型响应
def on_message(ws, message):
server_event = json.loads(message)
topic = ""
# See if metadata is present
try:
topic = server_event.response.metadata.topic
except AttributeError:
print("topic not set")
if server_event.type == "response.done" and topic == "classification":
# this server event pertained to our OOB model response
print(server_event.response.output[0])
为响应创建自定义上下文
您还可以创建一个自定义上下文,该模型将使用该上下文在默认/当前对话之外生成响应。这可以通过使用 response.create
客户端事件上的 input
数组来完成。查看文档。您可以使用新的输入,或者通过 ID 引用对话中的现有输入项。
监听具有自定义上下文的出站模型响应
event = {
"type": "response.create",
"response": {
"conversation": "none",
"metadata": { "topic": "pizza" },
"modalities": [ "text" ],
# Create a custom input array for this request with whatever
# context is appropriate
"input": [
# potentially include existing conversation items:
{
"type": "item_reference",
"id": "some_conversation_item_id"
},
# include new content as well
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "Is it okay to put pineapple on pizza?",
}
],
}
],
},
}
ws.send(json.dumps(event))
使用无上下文创建响应
您还可以将响应插入到默认对话中,忽略所有其他指令和上下文。通过将 input
设置为空数组来实现。
将无上下文模型响应插入到默认对话中
prompt = """
Say exactly the following:
I'm a little teapot, short and stout!
This is my handle, this is my spout!
"""
event = {
"type": "response.create",
"response": {
# An empty input array removes all prior context
"input": [],
"instructions": prompt,
},
}
ws.send(json.dumps(event))
函数调用
实时模型也支持函数调用,这使您能够执行自定义代码以扩展模型的功能。以下是它在高层次上的工作原理:
- 当更新会话或创建响应时,您可以指定模型可以调用的可用函数列表。
- 如果在处理输入时,模型确定它应该进行函数调用,它将向对话中添加代表函数调用参数的项目。
- 当客户端检测到包含函数调用参数的对话项目时,它将使用这些参数执行自定义代码。
- 当自定义代码执行完毕后,客户端将创建新的对话项目,其中包含函数调用的输出,并要求模型进行响应。
让我们通过添加一个可调用的函数来展示这将在实践中如何工作,该函数将为模型的用户提供今天的星座运势。我们将展示需要发送的客户端事件对象的形状,以及服务器将相应地发出什么。
配置可调用的函数
首先,我们必须为模型提供一个基于用户输入它可以调用的函数选择。可用的函数可以在会话级别或单个响应级别进行配置。
- 会话:
session.tools
属性在 session.update - 响应:
response.tools
属性在 response.create
以下是一个配置占星术生成函数的 session.update
客户端事件负载示例,该函数接受单个参数(需要生成占星术的星座):
session.update
{
"type": "session.update",
"session": {
"tools": [
{
"type": "function",
"name": "generate_horoscope",
"description": "Give today's horoscope for an astrological sign.",
"parameters": {
"type": "object",
"properties": {
"sign": {
"type": "string",
"description": "The sign for the horoscope.",
"enum": [
"Aries",
"Taurus",
"Gemini",
"Cancer",
"Leo",
"Virgo",
"Libra",
"Scorpio",
"Sagittarius",
"Capricorn",
"Aquarius",
"Pisces"
]
}
},
"required": ["sign"]
}
}
],
"tool_choice": "auto",
}
}
函数和参数的 description
字段有助于模型选择是否调用该函数以及每个参数应包含哪些数据。如果模型接收到指示用户想要他们的星座运势的输入,它将使用 sign
参数调用此函数。
检测模型何时想要调用函数
根据模型接收到的输入,模型可能会决定调用一个函数以生成最佳响应。假设我们的应用程序添加了以下对话项并尝试生成响应:
conversation.item.create
{
"type": "conversation.item.create",
"item": {
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "What is my horoscope? I am an aquarius."
}
]
}
}
随后是一个客户端事件以生成响应:
response.create
{
"type": "response.create"
}
而不是立即返回文本或音频响应,模型将生成一个包含应传递给开发者应用程序中函数的参数的响应。您可以使用response.function_call_arguments.delta
服务器事件来监听函数调用参数的实时更新,但response.done
也将包含我们调用函数所需的完整数据。
response.done
{
"type": "response.done",
"event_id": "event_AeqLA8iR6FK20L4XZs2P6",
"response": {
"object": "realtime.response",
"id": "resp_AeqL8XwMUOri9OhcQJIu9",
"status": "completed",
"status_details": null,
"output": [
{
"object": "realtime.item",
"id": "item_AeqL8gmRWDn9bIsUM2T35",
"type": "function_call",
"status": "completed",
"name": "generate_horoscope",
"call_id": "call_sHlR7iaFwQ2YQOqm",
"arguments": "{\"sign\":\"Aquarius\"}"
}
],
"usage": {
"total_tokens": 541,
"input_tokens": 521,
"output_tokens": 20,
"input_token_details": {
"text_tokens": 292,
"audio_tokens": 229,
"cached_tokens": 0,
"cached_tokens_details": { "text_tokens": 0, "audio_tokens": 0 }
},
"output_token_details": {
"text_tokens": 20,
"audio_tokens": 0
}
},
"metadata": null
}
}
在服务器发出的 JSON 中,我们可以检测到模型想要调用一个自定义函数:
属性 | 函数调用目的 |
---|---|
response.output[0].type | 当设置为 function_call 时,表示此响应包含对命名函数调用的参数。 |
response.output[0].name | 调用的配置函数的名称,在此例中为 generate_horoscope |
response.output[0].arguments | 包含函数参数的 JSON 字符串。在我们的例子中,"{\"sign\":\"Aquarius\"}" 。 |
response.output[0].call_id | 一个为此次函数调用生成的ID - 您需要此ID将函数调用结果返回到模型中。 |
鉴于这些信息,我们可以在我们的应用程序中执行代码以生成星座运势,然后将其信息反馈给模型,以便它可以生成响应。 |
向模型提供函数调用的结果
在接收到模型返回的函数调用参数后,您的应用程序可以执行满足函数调用的代码。这可以是您想要做任何事情,比如与外部API通信或访问数据库。
一旦您准备好向模型提供您自定义代码的结果,您可以通过 conversation.item.create
客户端事件创建一个新的对话项来包含该结果。
conversation.item.create
{
"type": "conversation.item.create",
"item": {
"type": "function_call_output",
"call_id": "call_sHlR7iaFwQ2YQOqm",
"output": "{\"horoscope\": \"You will soon meet a new friend.\"}"
}
}
- 对话项类型是
function_call_output
item.call_id
是我们在上面的response.done
事件中得到的相同 IDitem.output
是一个包含我们函数调用结果的 JSON 字符串
一旦我们添加了包含我们的函数调用结果的对话项,我们再次从客户端发出 response.create
事件。这将触发使用函数调用数据的一个模型响应。
response.create
{
"type": "response.create"
}
错误处理
当服务器在会话期间遇到错误条件时,会触发一个名为 error
的 事件。偶尔,这些错误可以追溯到由您的应用程序发出的客户端事件。
与 HTTP 请求和响应不同,其中响应隐式地与客户端的请求相关联,我们需要使用客户端事件上的 event_id
属性来确定其中一个事件何时在服务器上触发了错误条件。以下代码展示了这种技术,其中客户端尝试发出一个不支持的事件类型。
const event = {
event_id: "my_awesome_event",
type: "scooby.dooby.doo",
};
dataChannel.send(JSON.stringify(event));
此客户端发送的失败事件将触发以下错误事件:
{
"type": "invalid_request_error",
"code": "invalid_value",
"message": "Invalid value: 'scooby.dooby.doo' ...",
"param": "type",
"event_id": "my_awesome_event"
}
实时转录Beta
学习如何使用实时API进行实时音频转录。
https://platform.openai.com/docs/guides/realtime-transcription
您可以使用实时API进行仅转录的使用场景,无论是从麦克风输入还是从文件输入。例如,您可以使用它实时生成字幕或转录。在仅转录模式下,模型将不会生成响应。
如果您想让模型生成响应,您可以使用实时 API 在 语音到语音对话模式 中。
实时转录会话
要使用实时API进行转录,您需要创建一个转录会话,通过 WebSockets 或 WebRTC 连接。
与常规实时API会话进行对话不同,转录会话通常不包含来自模型的响应。
转录会话对象也与常规实时API会话不同:
{
object: "realtime.transcription_session",
id: string,
input_audio_format: string,
input_audio_transcription: [{
model: string,
prompt: string,
language: string
}],
turn_detection: {
type: "server_vad",
threshold: float,
prefix_padding_ms: integer,
silence_duration_ms: integer,
} | null,
input_audio_noise_reduction: {
type: "near_field" | "far_field"
},
include: list[string] | null
}
一些转录会话支持的附加属性包括:
input_audio_transcription.model
: 要使用的转录模型,目前支持gpt-4o-transcribe
、gpt-4o-mini-transcribe
和whisper-1
input_audio_transcription.prompt
: 用于转录的提示,用于指导模型(例如:“期待与科技相关的词语”)input_audio_transcription.language
: 用于转录的语言,理想情况下采用 ISO-639-1 格式(例如 “en”, “fr”…)以提高准确性和延迟input_audio_noise_reduction
:用于转录的降噪配置include
: 要包含在转录事件中的属性列表
可能的输入音频格式值为:pcm16
(默认)、g711_ulaw
和 g711_alaw
。
您可以在API参考中找到有关转录会话对象的更多信息。
处理转录
当使用实时API进行转录时,您可以监听 conversation.item.input_audio_transcription.delta
和 conversation.item.input_audio_transcription.completed
事件。
对于 whisper-1
,delta
事件将包含完整的回合转录,与 completed
事件相同。对于 gpt-4o-transcribe
和 gpt-4o-mini-transcribe
,delta
事件将包含增量转录,这些转录将随着从模型中流出来进行。
以下是一个转录 delta 事件的示例:
{
"event_id": "event_2122",
"type": "conversation.item.input_audio_transcription.delta",
"item_id": "item_003",
"content_index": 0,
"delta": "Hello,"
}
以下是示例转录完成事件:
{
"event_id": "event_2122",
"type": "conversation.item.input_audio_transcription.completed",
"item_id": "item_003",
"content_index": 0,
"transcript": "Hello, how are you?"
}
请注意,来自不同说话轮次的完成事件之间的顺序不保证。您应使用 item_id
将这些事件与 input_audio_buffer.committed
事件匹配,并使用 input_audio_buffer.committed.previous_item_id
来处理顺序。
要将音频数据发送到转录会话,您可以使用 input_audio_buffer.append
事件。
您有 2 个选项:
- 使用流式麦克风输入
- 从wav文件中流式传输数据
语音活动检测
实时API支持自动语音活动检测(VAD)。默认启用,VAD将控制何时提交输入音频缓冲区,因此何时开始转录。
有关配置VAD的更多信息,请参阅我们的语音活动检测指南。
您还可以通过将turn_detection
属性设置为null
来禁用VAD,并控制何时在您端提交输入音频。
额外配置
噪声降低
您可以使用 input_audio_noise_reduction
属性来配置如何处理音频流中的噪声降低。
可能的值有:
near_field
:使用近场噪声降低。far_field
:使用远场噪声降低。null
:禁用噪声降低。
默认值是 near_field
,您可以通过将属性设置为 null
来禁用噪声降低。
使用 logprobs
您可以使用 include
属性来在转录事件中包含 logprobs,使用 item.input_audio_transcription.logprobs
。
这些 logprobs 可以用来计算转录的置信度得分。
{
"type": "transcription_session.update",
"input_audio_format": "pcm16",
"input_audio_transcription": {
"model": "gpt-4o-transcribe",
"prompt": "",
"language": ""
},
"turn_detection": {
"type": "server_vad",
"threshold": 0.5,
"prefix_padding_ms": 300,
"silence_duration_ms": 500,
},
"input_audio_noise_reduction": {
"type": "near_field"
},
"include": [
"item.input_audio_transcription.logprobs",
],
}
语音活动检测 (VAD)Beta
了解 Realtime API 中的自动语音活动检测。
https://platform.openai.com/docs/guides/realtime-vad
语音活动检测(VAD)是实时API中的一项功能,允许自动检测用户何时开始或停止说话。在 语音到语音 或 转录 实时会话中默认启用,但它是可选的,可以关闭。
概述
当启用VAD(语音活动检测)时,音频会自动分块,并且实时API会发送事件来指示用户何时开始或停止说话:
input_audio_buffer.speech_started
:语音回合的开始input_audio_buffer.speech_stopped
:语音回合的结束
您可以使用这些事件来处理您的应用程序中的语音回合。例如,您可以使用它们来管理会话状态或分块处理转录本。
您可以使用session.update
事件的turn_detection
属性来配置每个语音到文本样本中音频的分块方式。
VAD有两种模式:
server_vad
:根据静默期间自动分块音频。semantic_vad
:当模型根据用户说的词语认为他们已完成其语音时,分块音频。
默认值是server_vad
。
阅读以下内容了解有关不同模式的更多信息。
服务器VAD
服务器VAD是实时会话的默认模式,并使用静默时间段来自动分割音频。
您可以调整以下属性以微调VAD设置:
threshold
:激活阈值(0到1)。较高的阈值将需要更响亮的音频来激活模型,因此可能在嘈杂环境中表现更好。prefix_padding_ms
:在VAD检测到语音之前包含的音频量(以毫秒为单位)。silence_duration_ms
:检测语音停止的静默持续时间(以毫秒为单位)。较短的值会使转弯检测更快。
以下是一个VAD配置示例:
{
"type": "session.update",
"session": {
"turn_detection": {
"type": "server_vad",
"threshold": 0.5,
"prefix_padding_ms": 300,
"silence_duration_ms": 500,
"create_response": true, // only in conversation mode
"interrupt_response": true, // only in conversation mode
}
}
}
语义语音活动检测(Semantic VAD)
语义语音活动检测是一种新模式,它使用语义分类器来检测用户何时完成说话,基于他们所使用的词语。这个分类器根据用户完成说话的概率对输入音频进行评分。当概率低时,模型将等待超时,而当概率高时,则无需等待。例如,以“嗯嗯…”结尾的用户音频会导致比明确陈述更长的超时时间。
使用此模式,模型在语音到语音对话中打断用户的可能性较小,或者在使用户完成说话之前截取转录。
可以通过将 turn_detection.type
设置为 semantic_vad
在一个 session.update
(https://platform.openai.com/docs/api-reference/realtime-client-events/session/update) 事件中激活语义语音活动检测。
它可以这样配置:
{
"type": "session.update",
"session": {
"turn_detection": {
"type": "semantic_vad",
"eagerness": "low" | "medium" | "high" | "auto", // optional
"create_response": true, // only in conversation mode
"interrupt_response": true, // only in conversation mode
}
}
}
可选的 eagerness
属性是一种控制模型如何急切地打断用户的属性,调整最大等待超时时间。在转录模式下,即使模型不回复,它也会影响音频的分割方式。
auto
是默认值,等同于medium
。low
将让用户有更多时间说话。high
将尽可能快地分割音频。
如果您希望模型在对话模式下更频繁地回应,或者在转录模式下更快地返回转录事件,可以将eagerness
设置为high
。
另一方面,如果您想在对话模式下让用户不间断地说话,或者您希望在转录模式下有更大的转录片段,您可以设置eagerness
为low
。
2025-03-29(六)