后端控制的 API 流程
后端控制且兼容 UI 的 API 流程
本教程为社区贡献,不属 于 Open WebUI 团队的官方支持范围。它仅用于演示如何针对您的特定用例自定义 Open WebUI。想要贡献?请参阅 贡献指南教程。
本教程演示了如何实现 Open WebUI 对话的服务器端编排,同时确保 Assistant 的回复能正常显示在前端 UI 中。这种方法不需要任何前端参与,并允许后端对对话流程进行完全控制。
本教程已验证适用于 Open WebUI v0.6.15 版本。未来的版本可能会引入行为或 API 结构的变更。
前提条件
在开始本教程之前,请确保您拥有:
- 一个正在运行的 Open WebUI 实例
- 有效的 API 身份验证 Token
- 对 Open WebUI 后端 API 的访问权限
- 对 REST API 和 JSON 的基本了解
- 命令行工具:
curl、jq(解析 JSON 选填)
概述
本教程介绍了一个包含 6 个步骤的完整过程,该过程支持对 Open WebUI 对话进行服务器端编排,同时确保 Assistant 的回复在前端 UI 中正确显示。
流程步骤
核心步骤包括:
- 创建包含 User 和 Assistant 消息的新对话 —— 使用用户的输入和空的 Assistant 占位符初始化对话
- 触发 Assistant 补全 —— 生成实际的 AI 响应(可选择集成知识库)
- 等待响应完成 —— 监控 Assistant 的响应,直到完全生成
- 获取并处理最终对话 —— 检索并解析已完成的对话
这实现了服务端编排,同时依然可以让回复呈现在前端 UI 中,就像是通过普通用户交互生成的一样。
重要概念
消息 ID 由调用者生成
所有消息 ID(user-msg-id、assistant-msg-id)在调用 API 之前必须由调用者生成为有效的 UUID。Open WebUI 不会为您分配消息 ID。请使用任何 UUID v4 生成器来创建它们。
示例 (bash):
USER_MSG_ID=$(uuidgen || python3 -c "import uuid; print(uuid.uuid4())")
ASSISTANT_MSG_ID=$(uuidgen || python3 -c "import uuid; print(uuid.uuid4())")childrenIds 字段
Open WebUI 前端将消息渲染为树状结构。每条消息必须包含一个 childrenIds 数组,其中列出其直接子消息的 ID。如果缺少此字段,前端将无法遍历消息树,导致消息无法渲染,即使它们已存在于数据库中。
- User 消息 必须在
childrenIds中列出其 Assistant 回复的 ID - Assistant 消息 通常具有
childrenIds: [](空),除非后续有其他跟进消息
currentId 字段
history 对象必须使用 currentId(小驼峰命名法,而不是 current_id)。这会告诉前端哪条消息处于当前活动对话线的最末端。
实现指南
关键步骤:使用 Assistant 消息富化对话响应
Assistant 消息在触发补全之前,必须作为关键前提存在于对话数据中。这一步是必不可少的,因为 Open WebUI 前端要求 Assistant 消息必须存在于特定的结构中。
Assistant 消息必须同时出现在这两个位置:
chat.messages[]—— 主消息数组(用于历史版本兼容)chat.history.messages[<assistantId>]—— 索引消息历史(被前端用来渲染树状结构)
Assistant 消息的预期结构:
{
"id": "<uuid>",
"role": "assistant",
"content": "",
"parentId": "<user-msg-id>",
"childrenIds": [],
"model": "gpt-4o",
"modelName": "gpt-4o",
"modelIdx": 0,
"done": false,
"timestamp": 1720000001
}如果不进行这一步富化,即使补全成功,Assistant 的响应也不会出现在前端界面中。
逐步实现指南
步骤 1:创建包含 User 和 Assistant 消息的对话
这将在单个请求中创建包含用户消息和空 Assistant 占位符的对话。响应会返回一个 chatId(包含在 id 字段中),供后续请求使用。
您可以将创建对话与 Assistant 富化合并在此单一步骤中。关键是在初始的 Payload 中同时包含 User 消息和空 Assistant 消息,并提供正确的 parentId、childrenIds 和 currentId 字段。
USER_MSG_ID=$(uuidgen || python3 -c "import uuid; print(uuid.uuid4())")
ASSISTANT_MSG_ID=$(uuidgen || python3 -c "import uuid; print(uuid.uuid4())")
TIMESTAMP=$(date +%s)
curl -X POST https://<host>/api/v1/chats/new \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"chat": {
"title": "New Chat",
"models": ["gpt-4o"],
"messages": [
{
"id": "'"$USER_MSG_ID"'",
"role": "user",
"content": "Hi, what is the capital of France?",
"timestamp": '"$TIMESTAMP"',
"models": ["gpt-4o"],
"childrenIds": ["'"$ASSISTANT_MSG_ID"'"]
},
{
"id": "'"$ASSISTANT_MSG_ID"'",
"role": "assistant",
"content": "",
"parentId": "'"$USER_MSG_ID"'",
"childrenIds": [],
"model": "gpt-4o",
"modelName": "gpt-4o",
"modelIdx": 0,
"done": false,
"timestamp": '"$((TIMESTAMP + 1))"'
}
],
"history": {
"currentId": "'"$ASSISTANT_MSG_ID"'",
"messages": {
"'"$USER_MSG_ID"'": {
"id": "'"$USER_MSG_ID"'",
"role": "user",
"content": "Hi, what is the capital of France?",
"timestamp": '"$TIMESTAMP"',
"models": ["gpt-4o"],
"childrenIds": ["'"$ASSISTANT_MSG_ID"'"]
},
"'"$ASSISTANT_MSG_ID"'": {
"id": "'"$ASSISTANT_MSG_ID"'",
"role": "assistant",
"content": "",
"parentId": "'"$USER_MSG_ID"'",
"childrenIds": [],
"model": "gpt-4o",
"modelName": "gpt-4o",
"modelIdx": 0,
"done": false,
"timestamp": '"$((TIMESTAMP + 1))"'
}
}
}
}
}'保存响应中的 id 字段 —— 这就是您后续所有步骤所需的 chatId。
最外层的 messages[] 数组是一个扁平列表,用于兼容历史版本。history.messages{} 对象则是最权威的结构 —— 它是一个以消息 ID 为键的字典,前端通过 parentId 和 childrenIds 使用该结构来构建对话树。
步骤 2:触发 Assistant 补全
使用补全接口生成实际的 AI 响应。使用步骤 1 中获取的 chatId:
curl -X POST https://<host>/api/chat/completions \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"chat_id": "<chatId>",
"id": "'"$ASSISTANT_MSG_ID"'",
"messages": [
{
"role": "user",
"content": "Hi, what is the capital of France?"
}
],
"model": "gpt-4o",
"stream": true,
"background_tasks": {
"title_generation": true,
"tags_generation": false,
"follow_up_generation": false
},
"features": {
"code_interpreter": false,
"web_search": false,
"image_generation": false,
"memory": false
},
"variables": {
"{{USER_NAME}}": "",
"{{USER_LANGUAGE}}": "en-US",
"{{CURRENT_DATETIME}}": "2025-07-14T12:00:00Z",
"{{CURRENT_TIMEZONE}}": "Europe"
},
"session_id": "<session-uuid>"
}'session_id 应该是您为该会话生成的一个唯一 UUID。它有助于维持对话上下文,并且如果前端处于打开状态,它还将被用于 WebSocket 事件路由。
步骤 2.1:触发带知识库集成 (RAG) 的 Assistant 补全
对于涉及知识库或文档集合的高级用例,请在补全请求中包含知识库文件:
curl -X POST https://<host>/api/chat/completions \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"chat_id": "<chatId>",
"id": "'"$ASSISTANT_MSG_ID"'",
"messages": [
{
"role": "user",
"content": "Hi, what is the capital of France?"
}
],
"model": "gpt-4o",
"stream": true,
"files": [
{
"id": "knowledge-collection-id",
"type": "collection",
"status": "processed"
}
],
"background_tasks": {
"title_generation": true,
"tags_generation": false,
"follow_up_generation": false
},
"features": {
"code_interpreter": false,
"web_search": false,
"image_generation": false,
"memory": false
},
"variables": {
"{{USER_NAME}}": "",
"{{USER_LANGUAGE}}": "en-US",
"{{CURRENT_DATETIME}}": "2025-07-14T12:00:00Z",
"{{CURRENT_TIMEZONE}}": "Europe"
},
"session_id": "<session-uuid>"
}'