跳到主要内容

后端控制的 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 的基本了解
  • 命令行工具:curljq(解析 JSON 选填)

概述

本教程介绍了一个包含 6 个步骤的完整过程,该过程支持对 Open WebUI 对话进行服务器端编排,同时确保 Assistant 的回复在前端 UI 中正确显示。

流程步骤

核心步骤包括:

  1. 创建包含 User 和 Assistant 消息的新对话 —— 使用用户的输入和空的 Assistant 占位符初始化对话
  2. 触发 Assistant 补全 —— 生成实际的 AI 响应(可选择集成知识库)
  3. 等待响应完成 —— 监控 Assistant 的响应,直到完全生成
  4. 获取并处理最终对话 —— 检索并解析已完成的对话

这实现了服务端编排,同时依然可以让回复呈现在前端 UI 中,就像是通过普通用户交互生成的一样。

重要概念

消息 ID 由调用者生成

所有消息 ID(user-msg-idassistant-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 消息,并提供正确的 parentIdchildrenIdscurrentId 字段。

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 为键的字典,前端通过 parentIdchildrenIds 使用该结构来构建对话树。

步骤 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>"
  }'

步骤 3:等待 Assistant 响应完成

根据您的实现需求,可以通过以下两种方式处理 Assistant 的响应:

如果在补全请求中使用 stream: true,您可以实时处理流式响应并等待流结束。这是 Open WebUI 网页界面所采用的方法,能提供即时反馈。

选项 B:轮询方法

对于无法处理流式的实现,请轮询对话接口直到响应就绪。请使用带有指数退避的重试机制:

# 每隔几秒轮询一次,直到 Assistant 内容被填充
while true; do
  response=$(curl -s -X GET https://<host>/api/v1/chats/<chatId> \
    -H "Authorization: Bearer <token>")

  # 检查 Assistant 消息是否包含内容(响应就绪)
  assistant_content=$(echo "$response" | jq -r ".chat.history.messages[\"$ASSISTANT_MSG_ID\"].content // empty")
  if [ -n "$assistant_content" ]; then
    echo "Assistant response is ready!"
    echo "$assistant_content"
    break
  fi

  echo "Waiting for assistant response..."
  sleep 2
done

步骤 4:获取最终的对话

检索已完成的对话:

curl -X GET https://<host>/api/v1/chats/<chatId> \
  -H "Authorization: Bearer <token>"

其他 API 接口

获取知识库集合

检索 RAG 集成所需的知识库信息:

curl -X GET https://<host>/api/v1/knowledge/<knowledge-id> \
  -H "Authorization: Bearer <token>"

获取模型信息

获取特定模型的详细信息:

curl -X GET https://<host>/api/v1/models/model?id=<model-name> \
  -H "Authorization: Bearer <token>"

向现有对话发送额外消息

对于多轮对话,您可以向现有对话中添加新消息。您必须包含完整的已更新消息树,并带有正确的 parentIdchildrenIds 关联:

NEW_USER_MSG_ID=$(uuidgen || python3 -c "import uuid; print(uuid.uuid4())")
NEW_ASSISTANT_MSG_ID=$(uuidgen || python3 -c "import uuid; print(uuid.uuid4())")

# 第一步:更新对话以添加新的 User 消息 + Assistant 占位符
# 您需要通过 childrenIds 将前一条 Assistant 消息链接到新的 User 消息
curl -X POST https://<host>/api/v1/chats/<chatId> \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "chat": {
      "history": {
        "currentId": "'"$NEW_ASSISTANT_MSG_ID"'",
        "messages": {
          "'"$ASSISTANT_MSG_ID"'": {
            "childrenIds": ["'"$NEW_USER_MSG_ID"'"]
          },
          "'"$NEW_USER_MSG_ID"'": {
            "id": "'"$NEW_USER_MSG_ID"'",
            "role": "user",
            "content": "Can you tell me more about Paris?",
            "parentId": "'"$ASSISTANT_MSG_ID"'",
            "childrenIds": ["'"$NEW_ASSISTANT_MSG_ID"'"],
            "timestamp": '"$(date +%s)"',
            "models": ["gpt-4o"]
          },
          "'"$NEW_ASSISTANT_MSG_ID"'": {
            "id": "'"$NEW_ASSISTANT_MSG_ID"'",
            "role": "assistant",
            "content": "",
            "parentId": "'"$NEW_USER_MSG_ID"'",
            "childrenIds": [],
            "model": "gpt-4o",
            "modelName": "gpt-4o",
            "modelIdx": 0,
            "done": false,
            "timestamp": '"$(($(date +%s) + 1))"'
          }
        }
      }
    }
  }'

# 第二步:为新的 Assistant 消息触发补全(与步骤 2 相同)
curl -X POST http://localhost:3000/api/chat/completions \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "<chatId>",
    "id": "'"$NEW_ASSISTANT_MSG_ID"'",
    "messages": [
      { "role": "user", "content": "Hi, what is the capital of France?" },
      { "role": "assistant", "content": "The capital of France is Paris." },
      { "role": "user", "content": "Can you tell me more about Paris?" }
    ],
    "model": "gpt-4o",
    "stream": true,
    "session_id": "<session-uuid>"
  }'
备注

当通过 POST /api/v1/chats/<chatId> 更新现有对话时,Payload 会与现有的对话数据进行合并。您只需包含要更改的字段即可。对于 history.messages,您可以传递部分更新 —— 更新中未包含的现有消息将被保留。

响应处理

解析 Assistant 响应

Assistant 的响应可能会包裹在 Markdown 代码块中。以下是清洗它们的方法:

# 来自 Assistant 的原始响应示例
raw_response='```json
{
  "result": "The capital of France is Paris.",
  "confidence": 0.99
}
```'

# 清洗响应(移除 Markdown 包装)
cleaned_response=$(echo "$raw_response" | sed 's/^```json//' | sed 's/```$//' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//')

echo "$cleaned_response" | jq '.'

此清洗过程将处理:

  • 移除 ````json` 前缀
  • 移除 ```` 尾缀
  • 修剪空白字符
  • JSON 校验

API 参考

DTO 结构

Chat DTO(完整结构)

{
  "id": "chat-uuid-12345",
  "title": "New Chat",
  "models": ["gpt-4o"],
  "files": [],
  "tags": [],
  "params": {
    "temperature": 0.7,
    "max_tokens": 1000
  },
  "timestamp": 1720000000,
  "messages": [
    {
      "id": "user-msg-id",
      "role": "user",
      "content": "Hi, what is the capital of France?",
      "timestamp": 1720000000,
      "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": 1720000001
    }
  ],
  "history": {
    "currentId": "assistant-msg-id",
    "messages": {
      "user-msg-id": {
        "id": "user-msg-id",
        "role": "user",
        "content": "Hi, what is the capital of France?",
        "timestamp": 1720000000,
        "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": 1720000001
      }
    }
  },
  "currentId": "assistant-msg-id"
}

ChatCompletionsRequest DTO

{
  "chat_id": "chat-uuid-12345",
  "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-67890",
  "filter_ids": [],
  "files": [
    {
      "id": "knowledge-collection-id",
      "type": "collection",
      "status": "processed"
    }
  ]
}

ChatCompletionMessage DTO

{
  "role": "user",
  "content": "Hi, what is the capital of France?"
}

History DTO

{
  "currentId": "assistant-msg-id",
  "messages": {
    "user-msg-id": {
      "id": "user-msg-id",
      "role": "user",
      "content": "Hi, what is the capital of France?",
      "timestamp": 1720000000,
      "models": ["gpt-4o"],
      "childrenIds": ["assistant-msg-id"]
    },
    "assistant-msg-id": {
      "id": "assistant-msg-id",
      "role": "assistant",
      "content": "The capital of France is Paris.",
      "parentId": "user-msg-id",
      "childrenIds": [],
      "model": "gpt-4o",
      "modelName": "gpt-4o",
      "modelIdx": 0,
      "timestamp": 1720000001
    }
  }
}

Message DTO(完整结构)

User 消息:

{
  "id": "user-msg-id",
  "role": "user",
  "content": "Hi, what is the capital of France?",
  "timestamp": 1720000000,
  "models": ["gpt-4o"],
  "childrenIds": ["assistant-msg-id"]
}

Assistant 消息:

{
  "id": "assistant-msg-id",
  "role": "assistant",
  "content": "The capital of France is Paris.",
  "parentId": "user-msg-id",
  "childrenIds": [],
  "model": "gpt-4o",
  "modelName": "gpt-4o",
  "modelIdx": 0,
  "done": true,
  "timestamp": 1720000001
}

响应示例

创建对话的响应

{
  "id": "chat-uuid-12345",
  "user_id": "user-uuid",
  "title": "New Chat",
  "chat": {
    "title": "New Chat",
    "models": ["gpt-4o"],
    "messages": [
      {
        "id": "user-msg-id",
        "role": "user",
        "content": "Hi, what is the capital of France?",
        "timestamp": 1720000000,
        "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": 1720000001
      }
    ],
    "history": {
      "currentId": "assistant-msg-id",
      "messages": {
        "user-msg-id": {
          "id": "user-msg-id",
          "role": "user",
          "content": "Hi, what is the capital of France?",
          "timestamp": 1720000000,
          "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": 1720000001
        }
      }
    },
    "currentId": "assistant-msg-id"
  },
  "updated_at": 1720000000,
  "created_at": 1720000000
}

最终对话响应(补全后)

{
  "id": "chat-uuid-12345",
  "title": "Capital of France Discussion",
  "chat": {
    "models": ["gpt-4o"],
    "history": {
      "currentId": "assistant-msg-id",
      "messages": {
        "user-msg-id": {
          "id": "user-msg-id",
          "role": "user",
          "content": "Hi, what is the capital of France?",
          "timestamp": 1720000000,
          "models": ["gpt-4o"],
          "childrenIds": ["assistant-msg-id"]
        },
        "assistant-msg-id": {
          "id": "assistant-msg-id",
          "role": "assistant",
          "content": "The capital of France is Paris. Paris is not only the capital but also the most populous city in France, known for its iconic landmarks such as the Eiffel Tower, the Louvre Museum, and Notre-Dame Cathedral.",
          "parentId": "user-msg-id",
          "childrenIds": [],
          "model": "gpt-4o",
          "modelName": "gpt-4o",
          "modelIdx": 0,
          "done": true,
          "timestamp": 1720000001
        }
      }
    },
    "currentId": "assistant-msg-id"
  }
}

OWUIKnowledge DTO(知识库集合)

{
  "id": "knowledge-collection-id",
  "type": "collection",
  "status": "processed",
  "name": "Geography Knowledge Base",
  "description": "Contains information about world geography and capitals",
  "created_at": 1720000000,
  "updated_at": 1720000001
}

模型信息响应

{
  "id": "gpt-4o",
  "name": "GPT-4 Optimized",
  "model": "gpt-4o",
  "base_model_id": "gpt-4o",
  "meta": {
    "description": "Most advanced GPT-4 model optimized for performance",
    "capabilities": ["text", "vision", "function_calling"],
    "context_length": 128000,
    "max_output_tokens": 4096
  },
  "params": {
    "temperature": 0.7,
    "top_p": 1.0,
    "frequency_penalty": 0.0,
    "presence_penalty": 0.0
  },
  "created_at": 1720000000,
  "updated_at": 1720000001
}

字段参考指南

必填 vs 选填字段

对话创建 - 必填字段:

  • title —— 对话标题(字符串)
  • models —— 模型名称数组(string[]
  • messages —— 初始消息数组
  • history —— 带有 currentIdmessages 映射的消息树

对话创建 - 选填字段:

  • files —— 用于 RAG 的知识库文件(默认为空数组)
  • tags —— 对话标签(默认为空数组)
  • params —— 模型参数(默认为空对象)

消息结构 - User 消息:

  • 必填: idrolecontenttimestampmodelschildrenIds
  • 选填: parentId(用于分支线;对话中的第一条消息可省略)

消息结构 - Assistant 消息:

  • 必填: idrolecontentparentIdchildrenIdsmodelmodelNamemodelIdxtimestamp
  • 选填: done(布尔值,默认为 false),其他元数据字段

ChatCompletionsRequest - 必填字段:

  • chat_id —— 目标对话 ID
  • id —— Assistant 消息 ID
  • messages —— ChatCompletionMessage 数组
  • model —— 模型标识符
  • session_id —— 会话标识符(调用者生成的 UUID)

ChatCompletionsRequest - 选填字段:

  • stream —— 启用流式传输(默认为 false)
  • background_tasks —— 控制自动生成的后台任务
  • features —— 启用/禁用功能
  • variables —— 模板变量
  • filter_ids —— Pipeline 过滤器
  • files —— 用于 RAG 的知识库集合

字段约束

时间戳 (Timestamps):

  • 格式:history.messages 中消息时间戳的格式为 Unix 时间戳,以为单位(而非毫秒)
  • 外层的对话 timestamp 字段使用毫秒
  • 示例:1720000000(2024年7月3日)

UUIDs:

  • 所有 ID 字段(idparentIdsession_id)应使用有效的 UUID v4 格式
  • 示例:550e8400-e29b-41d4-a716-446655440000
  • ID 由调用者生成,而非由服务器分配

模型名称 (Model Names):

  • 必须与您的 Open WebUI 实例中可用的模型相匹配
  • 常见示例:gpt-4ogpt-3.5-turboclaude-3-sonnet

会话 ID (Session IDs):

  • 可以是任何唯一的字符串标识符
  • 建议:为保持一致性,请使用 UUID 格式

知识库文件状态 (Knowledge File Status):

  • 有效值:"processed""processing""error"
  • 仅使用 "processed" 状态的文件进行补全

重要注意事项

  • 此工作流与 Open WebUI + 后端编排方案兼容。
  • 至关重要: 在 history 对象中使用 currentId(小驼峰命名法),不要使用 current_id(蛇形命名法)。
  • 至关重要: 在每条消息中都包含 childrenIds —— 前端通过它来构建消息树。
  • 该方法不需要修改任何前端代码。
  • stream: true 参数支持在需要时进行实时响应流式传输。
  • 当请求体中存在 chat_idid(消息 ID)时,outlet() 过滤器会在 /api/chat/completions 执行期间内联运行。省略这些字段的纯 API 调用者将静默跳过 outlet 运行 —— 请参阅 Filter Functions: 为 API 调用者运行 outlet() 了解解决方法。单独的 /api/chat/completed 接口已被废弃且不再需要。
  • 可以通过 background_tasks 对象控制标题生成等后台任务。
  • 会话 ID 有助于在多次请求之间维持对话上下文。
  • 知识库集成: 使用 files 数组引入知识库集合,以实现 RAG 能力。
  • 响应解析: 处理可能包裹在 Markdown 代码块中的 JSON 响应。
  • 错误处理: 针对网络超时和服务器错误实施妥善的重试机制。

常见陷阱

表现原因修复方法
对话已创建,但消息未显示在 UI 中消息中缺少 childrenIds添加关联父子消息的 childrenIds 数组
对话显示 "How can I help you today?"使用了 current_id 而不是 currentId在 history 对象中使用小驼峰的 currentId
补全成功但响应仅以通知形式出现触发补全前 Assistant 消息不在对话历史中在步骤 1 中包含空 Assistant 占位符
数据库中存在消息,但前端显示空对话缺少 parentId 或树状链条断裂确保每条消息都具有正确的 parentId 且父消息的 childrenIds 包含了该子消息

总结

使用 Open WebUI 后端 API 实现:

  1. 创建包含消息的对话 —— 创建包含用户输入和空 Assistant 占位符(包含正确的 childrenIdscurrentId)的对话
  2. 触发回复 —— 生成 AI 响应(可选集成知识库)
  3. 监控补全状态 —— 使用流式传输或轮询等待 Assistant 响应
  4. 获取最终对话 —— 检索并解析已完成的对话

增强能力:

  • RAG 集成 —— 包含知识库集合以进行上下文感知响应
  • 异步处理 —— 使用流式传输或轮询处理运行时间较长的 AI 操作
  • 响应解析 —— 清洗并校验来自 Assistant 的 JSON 响应
  • 会话管理 —— 跨请求维护对话上下文

这实现了后端控制的工作流,同时它们依然能够在 Web UI 前端对话界面中正确呈现,在程序化控制与用户体验之间提供了无缝集成。

这种方法的核心优势在于,它在与 Open WebUI 前端保持完全兼容的同时,允许对对话流进行完全的后端编排,包括知识库集成和异步响应处理等高级功能。

测试

您可以通过遵循上面提供的逐步 curl 示例来测试您的实现。请确保将占位符值替换为您的实际内容:

  • 托管的主机 URL
  • 身份验证 Token
  • 对话 ID(来自创建对话的响应)
  • 消息 ID(由您生成的 UUID)
  • 模型名称(与您配置的模型匹配)
提示

从简单的 User 消息开始,一旦基本流程能够正常运转,再逐渐增加类似知识库集成和高级功能等复杂度。

This content is for informational purposes only and does not constitute a warranty, guarantee, or contractual commitment. Open WebUI is provided "as is." See your license for applicable terms.