在实时对话式 AI 场景中,除了集成火山方舟和 Coze 平台外,还支持您接入自研或第三方的大模型/Agent(如 Dify Agent),以满足特定业务需求。
准备第三方大模型或 Agent 的请求接口 URL,并满足以下要求:
调用 StartVoiceChat 接口,按照规定参数结构配置 LLMConfig。
详细参数说明,请参见 StartVoiceChat。
| 功能 | StartVoiceChat 配置字段 | 说明 |
|---|---|---|
核心接入参数 | ||
| 服务类型 | Mode (必填) | 固定值 CustomLLM,以启用第三方模型模式。 |
| 指定服务地址 | Url (必填) | 你的模型/Agent 的 HTTPS 服务接口地址。 |
| Bearer Token鉴权 | APIKey | 如果你的接口需要 Bearer Token,系统自动添加 Authorization Header。 |
传入自定义请求、header、业务参数 | ||
| 自定义 Header | ExtraHeader | 透传任意自定义 HTTP Header,用于复杂鉴权或业务逻辑。 |
| 自定义 Query 参数 | (拼接在 Url 后) | 可在 Url 后拼接 ?key=value 来传递非敏感业务参数,格式为:https://<第三方模型或Agent的API地址>?<业务自定义参数名>=<参数值> |
| 自定义业务参数 | Custom | 可通过此 JSON 字符串字段,向你的接口请求体中透传自定义的业务数据。 |
其他配置 | ||
| 模型参数透传 | ModelName、Temperature、TopP、MaxTokens | 系统将这些标准模型参数透传到你接口的请求体中。 |
| 上下文管理 | SystemMessages、UserPrompts、HistoryLength | 对话上下文由这三个字段共同控制系统。具体说明,参看第三方大模型上下文管理机制 |
| 视觉理解 | VisionConfig | 将实时视频帧或外部图片数据发送给你的模型接口,从而实现感知环境、理解真人行为、图像问答等视觉交互。详细使用说明,请参见 视觉理解能力。 |
| Prefill 策略 | Prefill | 将 ASR 的中间识别结果提前发送给你的模型,以降低延迟。 |
| 对话轮次 | EnableRoundId | 在请求体中加入字段 round_id,你可以解析该字段,用于日志追踪、问题排查和数据审计等。 |
以下是一个 LLMConfig 配置示例。
{ // ... AppId, RoomId, TaskId ... "Config": { // ... ASRConfig, TTSConfig ... "LLMConfig": { "Mode": "CustomLLM", "Url": "https://api.my-custom-agent.com/v1/chat-stream?user_tier=premium", "APIKey": "bearer-token-for-my-agent", "ExtraHeader": { "X-Request-Source": "RTC-VoiceChat" }, "ModelName": "my-vertical-model-v2", "Temperature": 0.5, "HistoryLength": 5, "SystemMessages": [ "你是一个专业的法律顾问,回答问题时请引用法条。" ], "UserPrompts": [ { "Role": "user", "Content": "你好" }, { "Role": "assistant", "Content": "您好,请问有什么法律问题可以帮您?" } ], "Custom": "{\"case_id\":\"2024-A-567\"}", "EnableRoundId": true } }, // ... AgentConfig ... }
在对话期间,将按照以下格式通过 POST 请求访问你配置的第三方大模型或 Agent 的接口地址,获取相应结果。接口返回需支持 SSE 协议。
Method: POST
Headers:
Request body:
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
| messages | Array of messages | 是 | 参考 StartVoiceChat.HistoryLength,包含最近 HistoryLength 轮对话内容。当前 ASR 内容在数组末位。 |
| stream | Boolean | 否 | 取值:true。 |
| temperature | Float | 否 | 透传 StartVoiceChat.LLMConfig.temperature。 |
| max_tokens | Int | 否 | 透传 StartVoiceChat.LLMConfig.MaxTokens。 |
| model | String | 是 | 透传 StartVoiceChat.LLMConfig.ModelName。 |
| top_p | Float | 否 | 透传 StartVoiceChat.LLMConfig.TopP。 |
| custom | String | 否 | 自定义 JSON 字符串,透传业务传入的自定义参数。 |
messages
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
| role | String | 是 | 可取值及含义如下:
|
| content | String | 否 | 对话内容。 |
注意
data: [DONE] 结束符。收到这个结束符系统才会把大模型的文本提交给 TTS 合成音频。| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
| id | String | 是 | 请求 UUID。不同请求的 ID 需不同,但同一个流式请求的 ID 需相同。 |
| choices | Array of choices | 是 | 流式回复对象。 |
| created | Int | 是 | UnixTime 时间戳,精确到秒。同一个请求的流式所有块拥有相同的时间戳。 |
| usage | Object of usage | 否 | 最后一个包可带此参数。 |
| object | String | 是 | 取值:chat.completion.chunk。填错将导致接口行为异常。 |
| model | String | 是 | 模型 ID。 |
| stream_options | object of stream_options | 是 | 流接口选项。 |
Choices
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
| finish_reason | String | 是 | null:流式请求未结束。最后一个流式片段需填入以下值:
|
| delta | Object of delta | 是 | 流式片段对象。 |
| index | Int | 是 | 数组中位置,从 0 开始。 |
delta
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
| content | String | 是 | 对话内容。 |
| role | String | 是 | 可取值及含义如下:
|
usage
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
| completion_tokens | Int | 是 | generated tokens 长度。 |
| prompt_tokens | Int | 是 | prompt tokens 长度。 |
| total_tokens | Int | 是 | prompt+generated tokens 长度。 |
stream_options
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
| include_usage | Boolean | 是 | 固定为 true,表示流式传输。 |
成功请求及返回样例如下:
curl -v --location 'https://rtc-cloud-rendering.byted.org/voicechat/test-sse' \ --header 'Content-Type: application/json' \ --data '{ "messages":[{ "role":"user", "content":"今天适合干什么?" }], "stream": true, "temperature": 0.1, "max_tokens": 100, "top_p": 0.9, "model": "doubao-32k", "stream_options": {"include_usage":true} }' > POST /voicechat/test-sse HTTP/1.1 > Host: rtc-cloud-rendering.byted.org > User-Agent: curl/8.4.0 > Accept: */* > Content-Type: application/json > Content-Length: 254 > < HTTP/1.1 200 OK < Date: Thu, 15 Aug 2024 09:36:02 GMT < Content-Type: text/event-stream < Transfer-Encoding: chunked < Connection: keep-alive < Access-Control-Allow-Origin: * < Cache-Control: no-cache data: {"id":"c99d67a4-5ae9-11ef-bdf5-b8cef6dcdbe2","object":"chat.completion.chunk","choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant"}}],"model":"doubao-32k-2024-07-25","created":1723714562} data: {"id":"c99d67a4-5ae9-11ef-bdf5-b8cef6dcdbe2","object":"chat.completion.chunk","choices":[{"finish_reason":null,"index":1,"delta":{"content":"天"}},{"finish_reason":null,"index":0,"delta":{"content":"从明"}}],"model":"doubao-32k-2024-07-25","created":1723714562} data: {"id":"c99d67a4-5ae9-11ef-bdf5-b8cef6dcdbe2","object":"chat.completion.chunk","choices":[{"finish_reason":null,"index":0,"delta":{"content":"起,"}}],"model":"doubao-32k-2024-07-25","created":1723714562} data: {"id":"c99d67a4-5ae9-11ef-bdf5-b8cef6dcdbe2","object":"chat.completion.chunk","choices":[{"finish_reason":null,"index":1,"delta":{"content":"幸福"}},{"finish_reason":null,"index":0,"delta":{"content":"做一个"}}],"model":"doubao-32k-2024-07-25","created":1723714562} data: {"id":"c99d67a4-5ae9-11ef-bdf5-b8cef6dcdbe2","object":"chat.completion.chunk","choices":[{"finish_reason":null,"index":0,"delta":{"content":"的"}}],"model":"doubao-32k-2024-07-25","created":1723714562} data: {"id":"c99d67a4-5ae9-11ef-bdf5-b8cef6dcdbe2","object":"chat.completion.chunk","choices":[{"finish_reason":null,"index":0,"delta":{"content":"人"}}],"model":"doubao-32k-2024-07-25","created":1723714562} data: {"id":"c99d67a4-5ae9-11ef-bdf5-b8cef6dcdbe2","object":"chat.completion.chunk","choices":[{"finish_reason":null,"index":0,"delta":{"content":"。"}}],"model":"doubao-32k-2024-07-25","created":1723714562} data: {"id":"c99d67a4-5ae9-11ef-bdf5-b8cef6dcdbe2","object":"chat.completion.chunk","choices":[{"finish_reason":null,"index":0,"delta":{"content":"喂马,"}}],"model":"doubao-32k-2024-07-25","created":1723714562} data: {"id":"c99d67a4-5ae9-11ef-bdf5-b8cef6dcdbe2","object":"chat.completion.chunk","choices":[{"finish_reason":null,"index":0,"delta":{"content":"劈柴,"}},{"finish_reason":null,"index":1,"delta":{"content":"周游"}}],"model":"doubao-32k-2024-07-25","created":1723714562} data: {"id":"c99d67a4-5ae9-11ef-bdf5-b8cef6dcdbe2","object":"chat.completion.chunk","choices":[{"finish_reason":null,"index":0,"delta":{"content":"世界"}},{"finish_reason":null,"index":1,"delta":{"content":"。"}}],"model":"doubao-32k-2024-07-25","created":1723714562} data: {"id":"c99d67a4-5ae9-11ef-bdf5-b8cef6dcdbe2","object":"chat.completion.chunk","choices":[{"finish_reason":"stop","index":0,"delta":{}}],"model":"doubao-32k-2024-07-25","created":1723714562,"usage":{"prompt_tokens":1,"completion_tokens":2,"total_tokens":3}} data: [DONE]
请求终止,报错返回。RTC 不做任何处理,仅报错。
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
| Error | Error | 是 | 错误详情。 |
Error
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
| Code | String | 是 | 错误码。 |
| Message | String | 是 | 错误原因。 |
此时 RTC 不做任何处理,仅报错,直接报错返回 StatusCode。
你可以使用工具验证第三方大模型或 Agent 的请求接口是否符合标准规范。如果符合要求,工具可以返回大模型或 Agent 预期的输出结果,否则将返回错误信息。
注意
目前验证工具仅支持在 Linux 和 macOS 系统上使用。
注意
如果你使用 zsh 终端,且 URL 中包含特殊字符(如 ?、=、& 等)时,必须对特殊字符进行转义。
./app-linux <llmAPIUrl> <llmModel> <llmAPIKey> <LLMQuestion>
./app-mac <llmAPIUrl> <llmModel> <llmAPIKey> <LLMQuestion>
| 参数名 | 类型 | 是否必填 | 描述 | 示例 |
|---|---|---|---|---|
| llmAPIUrl | String | 是 | 第三方大模型或 Agent 的完整请求 URL。 | https://api.cn/v1/chat/completion |
| llmModel | String | 否 | 第三方大模型或 Agent 的名称。默认值为空。 | model-v1-chat |
| llmAPIKey | String | 否 | APIKey。默认值为空。 | sk-0aeQbtlX2reL |
| LLMQuestion | String | 否 | 发送给第三方大模型或 Agent 的测试问题。 | 你好 |
执行结果类似如下所示,表示验证通过:


支持。
HistoryLength 未生效,每次请求只传递了最新一条对话内容怎么办?可以尝试以下排查:
data: [DONE]。如果第三方服务没有在响应末尾返回此结束符,系统可能无法正确识别一次完整请求的结束,从而无法正确地存储和使用历史对话记录。