工具执行系统(中文译文)
原始 DeepWiki 页面:https://deepwiki.com/open-webui/open-webui/6.3-tool-execution-system
翻译时间:2026-06-09T16:08:51.786Z
翻译模型:deepseek-chat
原文字符数:10916
项目:Open WebUI (open-webui)
---
工具执行系统
相关源文件
以下文件为本 wiki 页面的生成提供了上下文:
backend/open_webui/models/functions.pybackend/open_webui/models/models.pybackend/open_webui/models/tags.pybackend/open_webui/routers/functions.pybackend/open_webui/routers/models.pybackend/open_webui/routers/prompts.pybackend/open_webui/routers/terminals.pybackend/open_webui/routers/tools.pybackend/open_webui/tools/builtin.pybackend/open_webui/utils/middleware.pybackend/open_webui/utils/tools.pysrc/lib/apis/models/index.tssrc/lib/components/chat/FileNav/PortList.sveltesrc/lib/components/chat/FileNav/PortPreview.sveltesrc/lib/components/chat/XTerminal.sveltesrc/lib/components/workspace/Models/BuiltinTools.svelte
目的与范围
工具执行系统使 AI 模型能够在聊天补全过程中调用外部函数、执行代码并与外部服务交互。该系统为四种主要执行路径提供了统一接口:内置工具(原生能力)、基于函数的工具(用户自定义 Python 代码)、外部工具服务器(OpenAPI/HTTP)以及 MCP 服务器(模型上下文协议)。系统负责工具发现、通过任务模型进行结构化调用、结果处理,以及将工具输出(包括媒体和引用)集成回对话上下文。
关于编排工具调用的中间件管道,请参阅 6.2 聊天中间件与请求流。关于基于 RAG 的文档检索,请参阅 7. RAG 与知识系统。
工具类型与架构
工具分类
Open WebUI 支持多种不同的工具执行机制,并为 LLM 整合为单一接口。
| 工具类型 | 描述 | 实现 | 执行上下文 |
|---|---|---|---|
| 内置工具 | 原生能力,如网络搜索、图像生成和内存访问。 | backend/open_webui/tools/builtin.py:1-101 | 后端 FastAPI 进程 |
| 函数 | 通过自定义 pipe 或 filter 类在服务端执行的 Python 代码。 | backend/open_webui/models/functions.py:21-35 | 后端 FastAPI 进程 |
| OpenAPI 工具 | 通过 OpenAPI 规范定义的外部 HTTP API。 | backend/open_webui/utils/tools.py:164-210 | 外部 HTTP 端点 |
| MCP 服务器 | 提供资源和工具的模型上下文协议服务器。 | backend/open_webui/utils/middleware.py:117 | 外部 MCP 进程 |
来源:backend/open_webui/utils/middleware.py:48-59, backend/open_webui/utils/tools.py:58-101, backend/open_webui/tools/builtin.py:1-101
工具状态与发现
系统在应用状态和数据库中维护工具定义。运行时,get_tools 函数将这些定义整合为统一的注册表,应用用户特定的 "Valves"(配置)并检查权限。
graph TB
subgraph "应用状态 [FastAPI app.state]"
STATE_TOOLS["app.state.TOOLS<br/>(工具模块)"]
STATE_FUNCTIONS["app.state.FUNCTIONS<br/>(函数模块)"]
end
subgraph "注册表逻辑 [utils/tools.py]"
GET_TOOLS["get_tools()"]
GET_BUILTIN["get_builtin_tools()"]
APPLY_VALVES["get_tool_valves_by_id()"]
end
subgraph "数据存储 [models/]"
DB_TOOLS["ToolsTable (SQLite/PG)"]
DB_FUNCTIONS["FunctionsTable (SQLite/PG)"]
DB_GRANTS["AccessGrantsTable"]
end
DB_TOOLS --> GET_TOOLS
DB_FUNCTIONS --> GET_TOOLS
DB_GRANTS -.->|"AccessGrants.has_access()"| GET_TOOLS
STATE_TOOLS --> GET_TOOLS
GET_BUILTIN --> UNIFIED["统一工具注册表<br/>{spec, callable, valves}"]
GET_TOOLS --> APPLY_VALVES
APPLY_VALVES --> UNIFIED
图:工具状态架构与注册表
来源:backend/open_webui/utils/tools.py:164-224, backend/open_webui/models/tools.py:39-43, backend/open_webui/models/functions.py:110-141
工具调用流程
函数调用生成
工具执行系统采用两阶段方法:首先通过任务模型生成工具调用,然后执行所选工具。中间件中的 chat_completion_tools_handler 负责管理此循环。
sequenceDiagram
participant 用户
participant 中间件 as "middleware.py<br/>chat_completion_tools_handler"
participant 任务模型 as "任务模型<br/>(get_task_model_id)"
participant 工具注册表 as "utils/tools.py<br/>get_tools"
participant 执行器 as "utils/middleware.py<br/>tool_call_handler"
用户->>中间件: 携带 tool_ids 的聊天请求
中间件->>工具注册表: get_tools(tool_ids, user)
工具注册表-->>中间件: tools_dict{}
中间件->>任务模型: 生成工具调用<br/>(tools_function_calling_generation_template)
任务模型-->>中间件: JSON tool_calls[]
Note over 中间件: _split_tool_calls() 处理<br/>拼接的 JSON 对象
loop 对每个 tool_call
中间件->>执行器: tool_call_handler()
执行器-->>中间件: tool_result
end
中间件->>用户: 包含工具上下文的最终 LLM 响应
图:工具调用序列
系统使用 tools_function_calling_generation_template backend/open_webui/utils/task.py:82 来指导任务模型生成结构化的工具调用。它还包含一个专门的 _split_tool_calls 工具函数 backend/open_webui/utils/middleware.py:172-218,用于处理模型在单个参数字符串中返回多个 JSON 对象的情况。
来源:backend/open_webui/utils/middleware.py:172-218, backend/open_webui/utils/task.py:79-83, backend/open_webui/utils/tools.py:164-180
工具调用处理器实现
执行特定工具调用的核心逻辑封装在 tool_call_handler 中。它判断工具是 "直接"(通过事件发射器处理,用于 MCP/外部服务器)还是 "本地"(由后端执行)。
graph TD
START["tool_call_handler(tool_call)"] --> FIND_TOOL{"工具存在于<br/>注册表中?"}
FIND_TOOL -- "否" --> RETURN_NONE["返回空结果"]
FIND_TOOL -- "是" --> CHECK_TYPE{"是否为直接工具<br/>(MCP/外部)?"}
CHECK_TYPE -- "是" --> EVENT_CALL["get_event_call()<br/>'execute:tool'"]
CHECK_TYPE -- "否" --> RUN_CALLABLE["await tool_function(**params)"]
EVENT_CALL --> PROCESS["process_tool_result()"]
RUN_CALLABLE --> PROCESS
PROCESS --> EXTRACT_MEDIA["提取文件/嵌入"]
EXTRACT_MEDIA --> EMIT["get_event_emitter()<br/>发射 'files'/'embeds'"]
图:工具调用处理器控制流
来源:backend/open_webui/utils/middleware.py:33-36, backend/open_webui/utils/tools.py:111-147
工具结果处理
多格式结果处理
process_tool_result 函数处理多种输出格式,从纯文本到复杂的媒体对象。
| 结果类型 | 处理逻辑 | 输出格式 |
|---|---|---|
| MCP 结果 | 遍历 text、image 和 audio 类型。 | 文本 + 文件 URL |
| JSON/字典 | 使用 json.dumps(indent=2) 序列化。 | 格式化的 Markdown 代码块 |
| 媒体结果 | 通过 get_file_url_from_base64 处理 base64 或 URL。 | 文件 UI 组件 |
来源:backend/open_webui/utils/middleware.py:62-67, backend/open_webui/utils/middleware.py:172-218
媒体与引用集成
工具可以返回媒体,这些媒体会被集成到聊天 UI 中:
- 文件:图像和音频被转换为数据 URL,并通过
get_event_emitterbackend/open_webui/utils/middleware.py:35作为files事件发射。 - 引用:结果被解析为源字典,使用
get_citation_source_from_tool_result以便在消息元数据中显示backend/open_webui/utils/middleware.py:221-230。
代码执行引擎
Open WebUI 支持通过两个主要引擎执行代码片段(主要是 Python)。
1. Pyodide(客户端)
使用 WebAssembly 直接在用户浏览器中执行 Python 代码。
- 实现:使用
CODE_INTERPRETER_PYODIDE_PROMPT指导模型backend/open_webui/config.py:125。
2. Jupyter(服务端)
在远程或本地 Jupyter 服务器上执行代码,适用于较重的工作负载或持久化环境。
- 实现:
execute_code_jupyter管理内核会话和执行请求backend/open_webui/utils/middleware.py:114。 - 配置:通过
DEFAULT_CODE_INTERPRETER_PROMPT管理backend/open_webui/config.py:124。
来源:backend/open_webui/utils/middleware.py:114, backend/open_webui/config.py:124-127, backend/open_webui/utils/sanitize.py:77
内置工具注册表
builtin.py 模块定义了模型可用的核心能力。
| 工具函数 | 用途 | 来源 |
|---|---|---|
search_web | 通过 Brave、Google 等进行公共网络搜索。 | backend/open_webui/tools/builtin.py:184-202 |
get_current_timestamp | UTC 和本地时间计算。 | backend/open_webui/tools/builtin.py:52-86 |
query_memory | 对用户特定记忆进行语义搜索。 | backend/open_webui/tools/builtin.py:26-33 |
execute_code | 通过 Pyodide 或 Jupyter 执行代码。 | backend/open_webui/tools/builtin.py:63 |
来源:backend/open_webui/tools/builtin.py:1-101, backend/open_webui/utils/tools.py:58-101
访问控制与权限
工具执行受多层权限模型约束:
- 注册表过滤:
get_tools检查AccessGrants以确保用户对特定工具 ID 具有read权限backend/open_webui/utils/tools.py:181-187。 - 组访问:可以通过
Groups.get_groups_by_member_idbackend/open_webui/utils/tools.py:172将工具访问权限授予特定组。 - 管理员绕过:
BYPASS_ADMIN_ACCESS_CONTROL配置允许管理员访问所有工具,无论是否有显式授权backend/open_webui/utils/tools.py:45。
来源:backend/open_webui/utils/tools.py:164-190, backend/open_webui/utils/access_control.py:44-45