API 接口
本指南提供了如何有效地与 API 接口进行交互的核心信息,以利用我们的模型实现无缝集成与自动化。请注意,这目前是一个实验性配置,未来可能会进行更新和优化。
身份验证
为确保安全访问 API,必须进行身份验证 🛡️。您可以使用 Bearer Token 机制来验证您的 API 请求。在 Open WebUI 中从 设置 > 账户 获取您的 API Key,或者也可以使用 JWT (JSON Web Token) 进行身份验证。有关启用和生成 API Key 的完整说明(包括管理员开关以及非管理员用户所需的组权限),请参阅 API Keys。
当 Open WebUI 部署在反向代理后,且该代理已将 Authorization 请求头用于自身验证时,您可以通过自定义请求头(默认是 x-api-key)来传递 API Key。管理员可以通过 CUSTOM_API_KEY_HEADER 环境变量重命名该请求头以避免冲突 —— 详见完整模式 Behind a reverse proxy that consumes Authorization?。
Swagger 文档链接
请确保将 ENV 环境变量设置为 dev,以便访问这些服务的 Swagger 文档。如果不进行此项配置,文档将不可用。
访问 Open WebUI 提供的不同服务的详细 API 文档:
| 主应用 | 文档路径 |
|---|---|
| Main | /docs |
常用 API 接口
📜 获取所有模型
-
接口:
GET /api/models -
描述: 获取通过 Open WebUI 创建或添加的所有模型。
-
示例:
curl -H "Authorization: Bearer YOUR_API_KEY" http://localhost:3000/api/models
💬 对话补全
-
接口:
POST /api/chat/completions -
描述: 作为与 OpenAI API 兼容的对话补全接口,适用于 Open WebUI 上的模型,包括 Ollama 模型、OpenAI 模型以及 Open WebUI Function 模型。
-
Curl 示例:
curl -X POST http://localhost:3000/api/chat/completions \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "llama3.1", "messages": [ { "role": "user", "content": "Why is the sky blue?" } ] }' -
Python 示例:
import requests def chat_with_model(token): url = 'http://localhost:3000/api/chat/completions' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } data = { "model": "granite3.1-dense:8b", "messages": [ { "role": "user", "content": "Why is the sky blue?" } ] } response = requests.post(url, headers=headers, json=data) return response.json()
🔮 Anthropic Messages API
Open WebUI 提供了一个兼容 Anthropic Messages API 的接口。这允许为 Anthropic API 构建的工具、SDK 和应用直接与 Open WebUI 协同工作 —— 将 请求路由到所有配置的模型、过滤器和 Pipelines。
在内部,该接口将 Anthropic 请求格式转换为 OpenAI Chat Completions 格式,并通过现有的对话补全 Pipeline 进行路由,最后将响应转回 Anthropic 格式。流式和非流式请求均支持。
-
接口:
POST /api/message,POST /api/v1/messages -
身份验证: 同时支持
Authorization: Bearer YOUR_API_KEY和 Anthropic 的x-api-key: YOUR_API_KEY请求头 -
Curl 示例 (非流式):
curl -X POST http://localhost:3000/api/v1/messages \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o", "max_tokens": 1024, "messages": [ { "role": "user", "content": "Why is the sky blue?" } ] }' -
Curl 示例 (流式):
curl -X POST http://localhost:3000/api/v1/messages \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o", "max_tokens": 1024, "stream": true, "messages": [ { "role": "user", "content": "Why is the sky blue?" } ] }' -
Python 示例 (使用 Anthropic SDK):
from anthropic import Anthropic client = Anthropic( api_key="YOUR_OPEN_WEBUI_API_KEY", base_url="http://localhost:3000/api", ) message = client.messages.create( model="gpt-4o", max_tokens=1024, messages=[ {"role": "user", "content": "Why is the sky blue?"} ], ) print(message.content[0].text)注意base_url必须是http://localhost:3000/api(而不是/api/v1)。Anthropic SDK 会自动将/v1/messages追加到 base URL 后面。 -
Claude Code 配置:
要将 Claude Code 与作为代理的 Open WebUI 配合使用,请将其配置为指向您的 Open WebUI 实例:
# 为 Claude Code 设置环境变量 export ANTHROPIC_BASE_URL="http://localhost:3000/api" export ANTHROPIC_API_KEY="YOUR_OPEN_WEBUI_API_KEY" # 然后正常运行 Claude Code claude或者,创建或编辑
~/.claude/settings.json:{ "env": { "ANTHROPIC_BASE_URL": "http://localhost:3000/api", "ANTHROPIC_AUTH_TOKEN": "YOUR_OPEN_WEBUI_API_KEY" } }这将所有 Claude Code 请求通过 Open WebUI 的身份验证和访问控制层进行路由,使您能够将任何已配置的模型(包括通过 Ollama 或 vLLM 的本地模型)与 Claude Code 界面配合使用。
在 Open WebUI 中配置的所有模型都可以通过此接口访问 —— 包括 Ollama 模型、OpenAI 模型以及任何自定义的 Function 模型。model 字段应使用在 Open WebUI 中显示的模型 ID。过滤器 (inlet/stream) 同样适用于这些请求,这与兼容 OpenAI 的接口完全一致。
工具使用 (Tool Use): Anthropic Messages 接口支持工具使用(tools 和 tool_choice 参数)。来自上游模型的工具调用在流式和非流式响应中都会被翻译成 Anthropic 格式的 tool_use 内容块。
🔧 过滤器和 Function 在 API 请求中的行为
当直接使用 API 接口时,过滤器 (Functions) 的行为与来自 Web 界面的请求有所不同。
Open WebUI 在 API 身份验证中同时接受 API Keys(前缀为 sk-)和 JWT Token。这是有意设计的 —— Web 界面在内部使用 JWT Token 访问相同的 API 接口。两种验证方法提供等效的 API 访问权限。
过滤器执行
| 过滤函数 | WebUI 请求 | 直接 API — 稳定版 (main) | 直接 API — 预发布版 (dev) |
|---|---|---|---|
inlet() | ✅ 运行 | ✅ 运行 | ✅ 运行 |
stream() | ✅ 运行 | ✅ 运行 | ✅ 运行 |
outlet() | ✅ 运行 | ❌ /api/chat/completions 不调用 — 使用 /api/chat/completed | ⚠️ 仅在严格条件下内联运行(见下文) |
inlet() 函数始终执行,这使其非常适用于:
- 限流 (Rate limiting) - 跟踪并限制每个用户的请求
- 请求日志 (Request logging) - 记录所有 API 使用情况以进行监控
- 输入验证 (Input validation) - 在请求到达模型之前拒绝无效请求
本页面的早期版本曾指出 outlet() 在 WebUI 和 API 请求的 /api/chat/completions 期间会内联运行。这是错误的。经过在后端源码中验证,准确的情况是:
在正式发布版本 / main 分支上: outlet() 完全不会被 /api/chat/completions 内联调用。只有当调用者向 /api/chat/completed 发起第二个 POST 请求时它才会运行。目前,如果您的集成需要 outlet(),您仍必须进行第二次调用。
在 dev / 预发布版本上: outlet() 可以在 /api/chat/completions 之后内联运行,但仅在所有以下条件满足时才 有效:
- 请求体中同时包含
chat_id和id(助手消息的 ID)。如果缺少任何一个,后端将没有event_emitter并静默跳过 outlet 块。 chat_id是已通过身份验证的用户已经拥有的对话,否则在到达 outlet 路径之前请求将返回 404。(或者,发送不带chat_id的parent_id: null来触发服务器上的新对话创建。)- 请求是非流式的。满足 (1) 和 (2) 的流式请求会进入为 WebUI 设计的代码路径:服务器自身消费上游流,并将内容路由到用户的 WebSocket,因此流式 API 调用者的 HTTP 响应实际上是空的。Outlet 会运行,但您无法在 HTTP 上看到其效果。
即使在非流式情况下,outlet() 也不会重写 HTTP 响应体。它会更新持久化的对话消息并触发 chat:outlet WebSocket 事件,但您的客户端接收到的 JSON 是 pre-outlet(运行前)的内容。如果您需要 outlet 过滤后的文本,请从对话记录中重新读取、订阅 WebSocket 或继续使用 /api/chat/completed。
实用建议: 如果您是纯粹的 API 消费者(如 Continue.dev、Claude Code、自定义脚本、Langfuse Pipelines 等),请将 /api/chat/completed 视为当前运行 outlet() 的推荐支持方式。dev 上的内联执行主要是为了已经在监听 WebSocket 的类 WebUI 客户端设计的。
遗留/API 支持的接口:/api/chat/completed
POST /api/chat/completed 是可以为直接 API 集成可靠运行 outlet() 的接口。在 dev 版本上,它被标记为已废弃以支持内联执行,但如上文所述,内联执行目前不会将过滤后的负载返回给纯 API 调用者 —— 因此在实践中,对于当今大多数 API 集成,/api/chat/completed 仍然是正确的选择。
-
接口:
POST /api/chat/completed -
描述: 在已完成的对话负载上无条件运行
outlet()过滤器(和 Pipeline outlet 过滤器)。返回过滤后的负载。 -
Curl 示例:
curl -X POST http://localhost:3000/api/chat/completed \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "llama3.1", "messages": [ {"role": "user", "content": "Hello"}, {"role": "assistant", "content": "Hi! How can I help you today?"} ], "chat_id": "optional-uuid", "session_id": "optional-session-id" }' -
Python 示例:
import requests def complete_chat_with_outlet(token, model, messages, chat_id=None): """ 第二步调用,实际为直接 API 调用者运行 outlet()。 在正式发布版本上,/api/chat/completions 完全不会内联运行 outlet。 在 dev 上,它仅在窄条件下内联运行,且不会重写 HTTP 响应体, 因此对于希望通过 HTTP 获取 outlet 输出的大多数 API 集成,该接口仍然是正确的调用选择。 """ url = 'http://localhost:3000/api/chat/completed' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } payload = { 'model': model, 'messages': messages # 包含带有助手响应的完整对话 } if chat_id: payload['chat_id'] = chat_id response = requests.post(url, headers=headers, json=payload) return response.json()
如果您现在需要在 HTTP 上获取 outlet() 的输出,请先调用 /api/chat/completions 然后再调用 /api/chat/completed。dev 上的内联执行主要针对读取 WebSocket 的类 WebUI 客户端。有关过滤器行为的更多详细信息,请参阅 Filter Function 说明文档。
🦙 Ollama API 代理支持
如果您想直接与 Ollama 模型交互 —— 包括生成嵌入(Embedding)或原始 Prompt 流式处理 —— Open WebUI 通过代理路由提供了对原生 Ollama API 的透明透传。
- 基础 URL:
/ollama/<api> - 参考: Ollama API 文档
🔁 生成补全(流式)
curl http://localhost:3000/ollama/api/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "llama3.2",
"prompt": "Why is the sky blue?"
}'📦 列出可用模型
curl http://localhost:3000/ollama/api/tags \
-H "Authorization: Bearer YOUR_API_KEY"🧠 生成嵌入
curl -X POST http://localhost:3000/ollama/api/embed \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "llama3.2",
"input": ["Open WebUI is great!", "Let'\''s generate embeddings."]
}'使用 Ollama 代理接口时,对于 POST 请求您必须包含 Content-Type: application/json 请求头,否则 API 可能会解 析请求体失败。如果您的实例已启用安全保护,还需要提供 Authorization 请求头。
🔮 Responses API(兼容 OpenAI)
Ollama 支持 OpenAI Responses API 格式。Open WebUI 通过 Ollama 路由器对此进行代理,其使用的模型解析、访问控制和前缀处理与对话补全(Chat Completions)完全相同。
curl -X POST http://localhost:3000/ollama/v1/responses \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "llama3.2",
"input": "Why is the sky blue?"
}'这允许 API 消费者(如 Codex、Claude Code 等)直接将 Responses API 用于 Ollama 托管的模型,而无需配置单独的兼容 OpenAI 的连接。
这非常适合在 Open WebUI 后端使用 Ollama 模型构建搜索索引、检索系统或自定义 Pipelines。
🧩 检索增强生成 (RAG)
检索增强生成 (RAG) 功能允许您通过引入外部数据源的数据来增强模型响应。在下方,您将找到通过 API 管理文件和知识库集合的方法,以及如何在对话补全中有效使用它们。
上传文件
要在 RAG 响应中使用外部数据,您首先需要上传文件。上传文件的内容会自动被提取并存储在向量数据库中。
-
接口:
POST /api/v1/files/ -
查询参数:
process(布尔值,默认:true): 是否提取内容并计算嵌入 (Embeddings)process_in_background(布尔值,默认:true): 是否异步处理
-
Curl 示例:
curl -X POST -H "Authorization: Bearer YOUR_API_KEY" -H "Accept: application/json" \ -F "file=@/path/to/your/file" http://localhost:3000/api/v1/files/ -
Python 示例:
import requests def upload_file(token, file_path): url = 'http://localhost:3000/api/v1/files/' headers = { 'Authorization': f'Bearer {token}', 'Accept': 'application/json' } files = {'file': open(file_path, 'rb')} response = requests.post(url, headers=headers, files=files) return response.json()
默认情况下,文件上传是异步处理的。上传接口会立即返回文件 ID,但内容提取和嵌入计算会在后台继续进行。
如果您在处理完成前尝试将文件添加到知识库中,您将收到一个 400 错误:
The content provided is empty. Please ensure that there is text or data present before proceeding.
在将文件添加到知识库之前,您必须等待文件处理完成。 请参阅下方的检查文件处理状态部分。
检查文件处理状态
在将文件添加到知识库之前,请使用状态接口验证处理是否已完成。
- 接口:
GET /api/v1/files/{id}/process/status - 查询参数:
stream(布尔值,默认:false): 如果为true,则返回 Server-Sent Events (SSE) 流
状态值:
| 状态 | 描述 |
|---|---|
pending | 文件仍在处理中 |
completed | 处理成功完成 |
failed | 处理失败(检查 error 字段了解详情) |
-
Python 示例 (轮询):
import requests import time def wait_for_file_processing(token, file_id, timeout=300, poll_interval=2): """ 等待文件处理完成。 返回: dict: 最终状态,包含 'status' 键('completed' 或 'failed') 抛出: TimeoutError: 如果处理未在超时时间内完成 """ url = f'http://localhost:3000/api/v1/files/{file_id}/process/status' headers = {'Authorization': f'Bearer {token}'} start_time = time.time() while time.time() - start_time < timeout: response = requests.get(url, headers=headers) result = response.json() status = result.get('status') if status == 'completed': return result elif status == 'failed': raise Exception(f"File processing failed: {result.get('error')}") time.sleep(poll_interval) raise TimeoutError(f"File processing did not complete within {timeout} seconds") -
Python 示例 (SSE 流式):
import requests import json def wait_for_file_processing_stream(token, file_id): """ 使用 Server-Sent Events 流等待文件处理。 对于长时间运行的操作,这比轮询更高效。 """ url = f'http://localhost:3000/api/v1/files/{file_id}/process/status?stream=true' headers = {'Authorization': f'Bearer {token}'} with requests.get(url, headers=headers, stream=True) as response: for line in response.iter_lines(): if line: line = line.decode('utf-8') if line.startswith('data: '): data = json.loads(line[6:]) status = data.get('status') if status == 'completed': return data elif status == 'failed': raise Exception(f"File processing failed: {data.get('error')}") raise Exception("Stream ended unexpectedly")
将文件添加到知识库集合
上传后,您可以将文件分组到知识库集合中,或者在对话中单独引用它们。
在将文件添加到知识库之前,始终等待文件处理完成。 仍在处理中的文件内容为空,这将导致 400 错误。使用上文描述的状态接口来验证文件状态是否为 completed。
-
接口:
POST /api/v1/knowledge/{id}/file/add -
Curl 示例:
curl -X POST http://localhost:3000/api/v1/knowledge/{knowledge_id}/file/add \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"file_id": "your-file-id-here"}' -
Python 示例:
import requests def add_file_to_knowledge(token, knowledge_id, file_id): url = f'http://localhost:3000/api/v1/knowledge/{knowledge_id}/file/add' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } data = {'file_id': file_id} response = requests.post(url, headers=headers, json=data) return response.json()
将网页 URL 处理到知识库集合
使用此接口获取网页、提取内容,并将生成的文本块 (Chunks) 存储在知识库集合中。
- 接口:
POST /api/v1/retrieval/process/web - 查询参数:
process(布尔值,默认:true): 如果为false,则仅获取并返回提取的内容,而不保存向量overwrite(布尔值,默认:true): 是否在保存新文本块之前替换目标集合中现有的向量,从而有效地清空给定集合并将其替换为给定 URL 的内容。
- 请求体:
url(字符串,必填): 要获取并解析的网页 URLcollection_name(字符串,选填): 目标集合名称。如果省略,Open WebUI 会根据 URL 生成一个名称
overwrite 行为:
| 值 | 结果 |
|---|---|
true(默认) | 在插入新的 URL 文本块之前,先替换目标集合中现有的向量 |
false | 保留现有的向量,并将新的 URL 文本块添加到同一集合中 |
-
Curl 示例 (保留现有向量):
curl -X POST 'http://localhost:3000/api/v1/retrieval/process/web?process=true&overwrite=false' \ -H 'Authorization: Bearer YOUR_API_KEY' \ -H 'Content-Type: application/json' \ -d '{ "url": "https://example.com/docs", "collection_name": "testkb" }' -
Python 示例:
import requests def process_web_url(token, url, collection_name="testkb", overwrite=False): response = requests.post( 'http://localhost:3000/api/v1/retrieval/process/web', headers={ 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' }, params={ 'process': 'true', 'overwrite': str(overwrite).lower() }, json={ 'url': url, 'collection_name': collection_name } ) return response.json()
如果启用了 ENV=dev,则此接口的 Schema(包括类似 overwrite 的查询参数)在 Swagger 中的 /docs 处也是可见的。
完整工作流示例
以下是一个完整的示例,用于上传文件、等待处理完成,然后将其添加到知识库中:
import requests
import time
WEBUI_URL = 'http://localhost:3000'
TOKEN = 'your-api-key-here'
def upload_and_add_to_knowledge(file_path, knowledge_id, timeout=300):
"""
上传文件并将其添加到知识库中。
在添加之前会妥善等待处理完成。
"""
headers = {
'Authorization': f'Bearer {TOKEN}',
'Accept': 'application/json'
}
# 步骤 1: 上传文件
with open(file_path, 'rb') as f:
response = requests.post(
f'{WEBUI_URL}/api/v1/files/',
headers=headers,
files={'file': f}
)
if response.status_code != 200:
raise Exception(f"Upload failed: {response.text}")
file_data = response.json()
file_id = file_data['id']
print(f"File uploaded with ID: {file_id}")
# 步骤 2: 等待处理完成
print("Waiting for file processing...")
start_time = time.time()
while time.time() - start_time < timeout:
status_response = requests.get(
f'{WEBUI_URL}/api/v1/files/{file_id}/process/status',
headers=headers
)
status_data = status_response.json()
status = status_data.get('status')
if status == 'completed':
print("File processing completed!")
break
elif status == 'failed':
raise Exception(f"Processing failed: {status_data.get('error')}")
time.sleep(2) # 每 2 秒轮询一次
else:
raise TimeoutError("File processing timed out")
# 步骤 3: 添加到知识库
add_response = requests.post(
f'{WEBUI_URL}/api/v1/knowledge/{knowledge_id}/file/add',
headers={**headers, 'Content-Type': 'application/json'},
json={'file_id': file_id}
)
if add_response.status_code != 200:
raise Exception(f"Failed to add to knowledge: {add_response.text}")
print(f"File successfully added to knowledge base!")
return add_response.json()
# 使用示例
result = upload_and_add_to_knowledge('/path/to/document.pdf', 'your-knowledge-id')在对话补全中使用文件和集合
您可以在 RAG 查询中同时引用单个文件或整个知识库集合,以获取更丰富的模型回复。
在对话补全中使用单个文件
当您希望对话模型的回答集中在特定文件的内容上时,此方法非常有用。
-
接口:
POST /api/chat/completions -
Curl 示例:
curl -X POST http://localhost:3000/api/chat/completions \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4-turbo", "messages": [ {"role": "user", "content": "Explain the concepts in this document."} ], "files": [ {"type": "file", "id": "your-file-id-here"} ] }' -
Python 示例:
import requests def chat_with_file(token, model, query, file_id): url = 'http://localhost:3000/api/chat/completions' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } payload = { 'model': model, 'messages': [{'role': 'user', 'content': query}], 'files': [{'type': 'file', 'id': file_id}] } response = requests.post(url, headers=headers, json=payload) return response.json()
在对话补全中使用知识库集合
当查询可能会受益于更广泛的上下文或多个文档时,利用知识库集合来增强回答。
-
接口:
POST /api/chat/completions -
Curl 示例:
curl -X POST http://localhost:3000/api/chat/completions \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4-turbo", "messages": [ {"role": "user", "content": "Provide insights on the historical perspectives covered in the collection."} ], "files": [ {"type": "collection", "id": "your-collection-id-here"} ] }' -
Python 示例:
import requests def chat_with_collection(token, model, query, collection_id): url = 'http://localhost:3000/api/chat/completions' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } payload = { 'model': model, 'messages': [{'role': 'user', 'content': query}], 'files': [{'type': 'collection', 'id': collection_id}] } response = requests.post(url, headers=headers, json=payload) return response.json()
这些方法能够通过上传的文件和精心策划的知识库集合有效利用外部知识,从而使用 Open WebUI API 增强聊天应用的能力。无论是单独使用文件还是在集合中使用,您都可以根据具体需求自定义集成。
使用 Open WebUI 作为统一 LLM 提供商的优势
Open WebUI 提供了诸多优势,使其成为开发者和企业的必备工具:
- 统一界面: 通过单个集成平台简化您与不同大语言模型 (LLM) 的交互。
- 易于实现: 依托完善的文档和社区支持,实现快速启动集成。
通过遵循这些指南,您可以迅速集成并开始利用 Open WebUI API。如果您遇到任何问题或疑问,欢迎随时通过我们的 Discord 社区取得联系或查阅 FAQ。祝您编码愉快!🌟