跳到主要内容
版本:Dev

使用 Chat Completions 输入和输出音频

支持音频的聊天模型可以接收消息中的录制音频,并在同一个 Chat Completions 响应中返回生成的音频。这适合需要模型理解音频或以音频回答,同时保持兼容 OpenAI 的 POST /v1/chat/completions 请求形态的轮次式应用。

如需独立转录、翻译或语音生成,请使用语音与音频。如需交互式双向会话,请使用 Realtime API。

当所选上游使用兼容的 OpenAI 形态 API 时,AISIX 会保留 OpenAI 聊天音频请求和响应字段。它不会将这些字段转换为其他服务提供方的原生音频协议。

准备工作​

请先准备以下内容:

  • 一个可以处理代理请求的 AISIX 网关。
  • 一个可以访问该模型别名的调用方 API Key。
  • 一个由支持音频的 Chat Completions 模型支撑的模型别名。其服务提供方密钥必须使用 openai 或 azure-openai 适配器,且上游必须实现 OpenAI 聊天音频请求和响应形态。
  • 一个名为 question.wav 的本地 WAV 录音,用于音频输入示例。
  • 示例所需的 curl、jq、Python 3,以及 base64、file 和 tr 命令行工具。

如果尚未配置上游,请参阅 OpenAI、Azure OpenAI或自带端点。选择上游当前支持的音频模型,并为其创建 AISIX 别名。

对于路由别名,每个符合条件的目标都必须使用上述适配器之一,并支持相同的聊天音频字段。如果故障转移到仅支持文本或形态不同的服务提供方,音频内容可能丢失,或请求可能在上游失败。

导出网关连接和请求值:

# AISIX_PROXY 不含尾部斜杠或 /v1 等端点路径
# 本地快速入门使用 http://127.0.0.1:3000。
export AISIX_PROXY="YOUR_AISIX_GATEWAY_URL"
export AISIX_API_KEY="YOUR_CALLER_API_KEY"
export AISIX_MODEL="audio-chat-prod"

生成音频响应​

同时请求文本和音频输出,然后保存完整响应:

curl -sS -X POST "${AISIX_PROXY}/v1/chat/completions" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "'"${AISIX_MODEL}"'",
"modalities": ["text", "audio"],
"audio": {
"voice": "alloy",
"format": "wav"
},
"messages": [
{
"role": "user",
"content": "Say: Your AISIX audio route is working."
}
]
}' > chat-audio-response.json

AISIX 会在分发前将别名替换为上游模型 ID。上游决定接受哪些声音和输出格式。

检查返回的音频元数据,但不打印 base64 载荷:

jq '{
model,
audio: (.choices[0].message.audio | {
id,
transcript,
expires_at,
encoded_characters: (.data | length)
})
}' chat-audio-response.json

响应中的 model 会保持为 AISIX 别名。如果上游返回相应字段,audio 对象会包含服务提供方的音频标识、base64 数据、转录文本和过期时间戳。

使用 Python 标准库解码生成的 WAV 文件:

python3 - <<'PY'
import base64
import json

with open("chat-audio-response.json", encoding="utf-8") as response_file:
response = json.load(response_file)

audio = response["choices"][0]["message"]["audio"]
with open("aisix-chat-audio.wav", "wb") as audio_file:
audio_file.write(base64.b64decode(audio["data"]))

print(audio.get("transcript", ""))
PY

file aisix-chat-audio.wav

最后一条命令应将其识别为 WAV 文件。如果请求了其他格式,请使用匹配的文件名和媒体播放器。

在消息中发送音频​

编码本地录音,并将其放入 input_audio 内容块。此示例要求模型以音频回答,以便使用与上一个请求相同的响应处理方式:

base64 < question.wav | tr -d '\n' | \
jq -Rs \
--arg model "$AISIX_MODEL" \
'{
model: $model,
modalities: ["text", "audio"],
audio: {
voice: "alloy",
format: "wav"
},
messages: [
{
role: "user",
content: [
{
type: "text",
text: "Answer the question in this recording."
},
{
type: "input_audio",
input_audio: {
data: .,
format: "wav"
}
}
]
}
]
}' > chat-audio-input.json

curl -sS -X POST "${AISIX_PROXY}/v1/chat/completions" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
--data @chat-audio-input.json \
> chat-audio-response.json

兼容 OpenAI 的适配器会原样转发带类型的内容块,不会解码录音。

了解当前行为​

聊天音频使用普通 Chat Completions 的身份认证、模型访问、路由、重试和请求遥测路径。音频专属行为存在以下边界:

  • 流式和非流式均可。 完整响应会保留 message.audio。流式响应会按上游自己的形态转发 delta.audio,包括其 id、transcript、data 以及末尾的 expires_at 分片;设置 stream_options.include_usage 时,最后的用量分片会带上音频 Token 数。这适用于 OpenAI 及兼容 OpenAI 的上游、Azure OpenAI,以及 Amazon Bedrock 和 Vertex AI 的兼容 OpenAI 路由。
  • 保持服务提供方协议兼容。 兼容 OpenAI 的适配器会保留音频请求字段和 message.audio 对象。原生协议的上游,例如 Anthropic、Vertex AI 或 Amazon Bedrock 上的 Claude、Vertex AI Gemini 以及 Bedrock Converse,在支持该类媒体时会以自己的媒体块接收 input_audio 部分;不支持时(例如向 Claude 发送音频),AISIX 返回 400 并以 messages[i].content[j] 指出该部分,而不是将其丢弃。AISIX 不会把音频输出字段转换为服务提供方原生语音 API。
  • 区分文本与音频的安全护栏行为。 输入安全护栏可以检查文本内容块,输出安全护栏可以检查普通的返回消息文本。它们不会检查 input_audio 中的字节、生成的音频数据,或嵌套在 message.audio 或流式 delta.audio 中的转录文本。
  • 将音频成本视为上游细节。 响应的 usage 会带上上游报告的音频 Token 数,用量事件会将其记录为 prompt_audio_tokens 和 completion_audio_tokens。控制面定价没有单独的音频 Token 费率,因此按请求的提示词和补全费率计费。

音频以 base64 编码在 JSON 中,因此请求体和响应体会大于底层二进制文件。设置客户端、代理或负载均衡器的请求体和响应体大小限制时,请计入这部分膨胀。

排查聊天音频问题​

如果响应成功但没有 message.audio,请检查请求是否包含音频模态和 audio 对象,并确认上游模型支持通过 Chat Completions 输出音频。仅支持文本的模型可能接受 HTTP 请求,但会在上游拒绝或忽略不受支持的音频字段。

如果 AISIX 返回上游解码错误或服务提供方错误,请按照服务提供方文档中说明的请求格式直接调用同一个上游模型。更改网关策略前,请先确认模型 ID、声音、格式和音频输入编码。

当应用需要增量双向音频时,请使用 Realtime API。

下一步​

你现在已经在兼容 OpenAI 的聊天请求中发送和接收音频。如需独立转录或语音合成,请继续阅读语音与音频;如需交互式语音会话,请阅读 Realtime API。