为Open WebUI构建安全代码执行沙箱:基于gVisor的本地LLM编程实践
1. 项目概述:为Open WebUI构建安全的代码执行沙箱
如果你正在使用Open WebUI来管理你的本地大语言模型,比如通过Ollama部署的Llama、Qwen或者DeepSeek,那么你很可能遇到过这样一个痛点:模型可以生成代码,但你却无法让它真正“跑起来”。无论是想让它帮你写个Python脚本处理数据,还是执行一段Shell命令来检查系统状态,最终都只能停留在“纸上谈兵”的阶段。这极大地限制了LLM作为“智能助手”的潜力,尤其是在数据分析、自动化脚本编写和系统运维等场景下。
今天要聊的这个项目——EtiennePerot/safe-code-execution,就是为了解决这个问题而生的。它的核心目标很明确:为Open WebUI安全地增加代码执行能力。这里的“安全”是重中之重。直接让LLM在宿主机器上运行任意代码无异于打开潘多拉魔盒,一个rm -rf /或者恶意下载脚本就足以造成灾难。因此,该项目借鉴了业界成熟的做法,使用Google开源的gVisor作为沙箱隔离层。有趣的是,根据项目文档的提示,这甚至是ChatGPT内部采用的一种安全机制。简单来说,gVisor会在用户空间模拟一个内核,让代码在一个高度隔离的“容器”中运行,既能访问必要的资源(如计算、临时文件),又无法触及宿主机的核心系统,从而在功能性和安全性之间取得了绝佳的平衡。
这个项目提供了两种集成模式,适应不同的使用习惯:一种是代码执行函数(Function),它会在LLM生成的消息下方显示一个按钮,由你手动点击触发执行,结果对双方可见;另一种是代码执行工具(Tool),直接授予LLM自主调用执行代码的权限,就像给它装上了“Web搜索”一样,它可以在思考过程中自行决定何时运行代码来获取信息,整个过程对用户可能是透明的。无论你是喜欢保持绝对控制权,还是希望赋予AI更大的自主性,都能找到合适的方案。接下来,我将带你从零开始,彻底搞懂这个项目的部署、原理、使用技巧以及那些官方文档可能没细说的“坑”。
2. 核心概念解析:Function与Tool的双重奏
在深入动手之前,我们必须先厘清项目提供的两个核心组件:代码执行函数(Code Execution Function)和代码执行工具(Code Execution Tool)。虽然它们最终都调用相同的底层gVisor沙箱来执行代码,但设计哲学和使用体验截然不同。理解二者的区别,是选择最适合你工作流的关键。
2.1 代码执行函数:手动控制的精准打击
你可以把代码执行函数想象成一个“代码运行器”插件。它的工作流程非常直观:
- 你向LLM提问,例如:“写一个Python脚本来列出当前目录下所有大于100MB的文件。”
- LLM生成回复,并在消息中附带一个格式正确的代码块(通常是Markdown的
python ...格式)。 - 在该条LLM回复消息的下方,会出现一个“Run code”按钮。
- 由你手动点击这个按钮,触发代码在gVisor沙箱中执行。
- 执行结果(包括标准输出和错误信息)会直接显示在聊天界面中,作为一条新的消息。同时,这个结果也会被反馈给对话上下文,LLM可以基于这个结果继续回答你的问题。
这种模式的优势在于:
- 绝对控制权:代码是否执行、何时执行,完全由你决定。这给了你充分的机会审查LLM生成的代码,避免运行可能存在风险的指令。
- 结果可视化:执行过程的结果对你是完全透明的,你可以清晰看到代码的输出或报错信息。
- 交互式调试:如果代码运行出错,你可以将错误信息反馈给LLM,让它修正代码,然后再次点击运行,形成一个交互式的编程调试循环。
它最适合的场景是:
- 代码审查与学习:当你想要LLM教你编程或解释一段代码时,可以手动执行来看结果。
- 敏感操作:涉及文件操作、系统查询等命令,你需要先看一眼代码再决定是否运行。
- 分步任务:将一个复杂任务分解成多个代码片段,你逐步运行并检查中间结果。
2.2 代码执行工具:赋予AI自主行动权
代码执行工具则代表了另一种思路:将执行能力作为一件“工具”赋予LLM本身。这类似于为LLM开启了“函数调用”(Function Calling)或“工具调用”(Tool Calling)能力。
它的工作流程如下:
- 在聊天界面,你需要手动激活本次对话的“Run code”工具开关(通常在输入框附近)。
- 你提出一个任务,例如:“帮我查一下今天的天气,然后计算如果明天气温下降3度会是多少。”
- LLM在内部推理时,可能会认为:“要完成这个任务,我需要先获取当前日期,然后模拟一个网络请求获取天气数据,最后进行数学计算。”
- 于是,LLM可以自主决定调用“Run code”工具。它可能会生成一段Python代码,使用
datetime模块获取日期,或用requests库(如果沙箱内允许网络访问)查询一个天气API。 - 工具在后台静默执行这段代码,并将执行结果(纯文本)返回给LLM。
- LLM接收到结果后,整合信息,最终生成给你的自然语言回复,例如:“今天是2023年10月27日。根据模拟数据(示例),当前气温是22度。明天气温下降3度后,预计是19度。”
这种模式的优势在于:
- 自动化与流畅性:LLM可以自主规划并执行多步任务,无需你反复点击按钮,体验更接近一个真正能“做事”的智能体。
- 信息获取:LLM可以主动运行代码来获取实时信息(如时间、从特定网页抓取数据),突破其训练数据的时间限制。
- 复杂计算:对于复杂的数学运算、数据处理,LLM可以借助代码工具获得精确结果,避免大模型在数学上的“幻觉”。
它最适合的场景是:
- 需要实时数据的问答:例如,“现在纽约是几点?”、“某某股票最新价是多少?”(需配合网络访问)。
- 多步骤问题解决:问题本身需要查询、计算、再推理等多个步骤。
- 当你信任模型时:用于执行相对安全、定义明确的任务。
注意:选择哪种模式?对于初学者或处理不确定性任务,强烈建议从代码执行函数开始,它更安全、可控。当你熟悉了LLM的行为模式,并且任务模式固定后,可以尝试使用工具模式来提升效率。好消息是,这两个组件可以同时安装,互不冲突,你可以根据对话的上下文灵活选择使用方式。
3. 环境准备与核心依赖:gVisor沙箱深度解析
项目的安全基石完全建立在gVisor之上。因此,在安装插件之前,我们必须先搭建好gVisor的运行环境。这个过程比安装普通软件包稍复杂,但理解其原理能帮你更好地排查后续问题。
3.1 gVisor是什么?为什么是它?
gVisor不是一个传统的虚拟机(VM),也不是一个普通的Docker容器。它是一个用户态内核(Userspace Kernel)。我们来做个类比:
- 宿主系统:就像你家的大房子(硬件和主操作系统)。
- Docker容器:就像在房子里用石膏板隔出的一个房间。它看起来是独立的,但与房子共享同一个内核(地基和承重墙)。如果内核有漏洞,攻击者可能打穿石膏板,进入其他房间。
- 传统虚拟机:就像在房子旁边完全用砖头重建了一个带独立地基的小房子。完全隔离,但启动慢、资源占用高。
- gVisor沙箱:就像在你家房子里放了一个特制的、全封闭的“游戏舱”。你可以在舱内跑、跳、操作各种设备(系统调用),但这些动作都被舱内的机械结构(用户态内核)翻译和过滤了一遍,再以安全的方式影响房子。舱体本身很轻便,但隔离性远超石膏板隔间。
gVisor通过拦截应用程序发出的所有系统调用(如读写文件、创建进程、网络通信),在自己实现的安全内核中处理它们,从而彻底隔离了沙箱内应用与宿主内核的直接接触。这正是ChatGPT等服务选择它来运行不可信代码的原因。
3.2 系统环境检查与依赖安装
首先,确保你的Open WebUI运行在Linux系统上。gVisor对Linux支持最完善。虽然macOS和Windows通过Linux虚拟机也可能运行,但会复杂很多,且非官方支持。
1. 基础依赖安装:在终端中执行以下命令,安装必要的工具。以Ubuntu/Debian为例:
sudo apt-get update sudo apt-get install -y curl git python3-pip2. 安装gVisor的runsc运行时:runsc是gVisor的核心组件,它是一个符合OCI(开放容器标准)的运行时,可以替代runc来运行容器。
# 下载最新稳定版的runsc curl -fsSL https://gvisor.dev/archive.key | sudo gpg --dearmor -o /usr/share/keyrings/gvisor-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/gvisor-archive-keyring.gpg] https://storage.googleapis.com/gvisor/releases release main" | sudo tee /etc/apt/sources.list.d/gvisor.list > /dev/null sudo apt-get update && sudo apt-get install -y runsc安装完成后,需要将其配置到Docker(如果你的Open WebUI使用Docker运行)或Containerd中。
3. 配置Docker使用gVisor运行时:编辑Docker的守护进程配置文件:
sudo nano /etc/docker/daemon.json如果文件已存在,在其中添加"runtimes"部分;如果不存在,创建包含以下内容的文件:
{ "runtimes": { "runsc": { "path": "/usr/bin/runsc" } } }保存并退出,然后重启Docker服务使配置生效:
sudo systemctl restart docker验证配置是否成功:
sudo docker info | grep -i runtime你应该能看到runsc在运行时列表中。
4. 验证gVisor安装:运行一个简单的测试容器,确认gVisor能正常工作:
sudo docker run --runtime=runsc --rm alpine echo "Hello from gVisor sandbox!"如果命令成功执行并输出信息,说明gVisor环境配置正确。
实操心得:网络与权限的坑
- 网络问题:默认情况下,gVisor沙箱内的网络是受限的,与宿主机隔离。这意味着如果你希望LLM运行的代码能访问互联网(例如用Python的
requests库获取网页),需要额外配置。项目通常通过映射宿主网络或使用桥接模式来实现。在后续配置Open WebUI时需要注意相关设置。- 文件系统访问:沙箱内默认只有临时文件系统。如果代码需要读取宿主机的特定文件或向宿主机写入持久化结果,需要预先在Docker运行参数或Open WebUI配置中定义卷映射(Volume Mounts)。这是一个关键的安全/功能平衡点:映射越多,功能越强,风险也略微增加。
- 用户与权限:确保运行Open WebUI服务的用户(如
docker组用户)有权限调用runsc。有时需要将用户加入docker组并重新登录。
4. Open WebUI的沙箱化配置
有了gVisor基础环境,下一步是让Open WebUI知道如何使用这个沙箱来运行代码。safe-code-execution项目通过一个自定义的“工作器”(Worker)来实现这一点。我们需要在Open WebUI的配置中指明,当有代码执行请求时,应该使用我们配置好的gVisor沙箱环境。
4.1 获取并配置工作器脚本
项目文档中提到的[**set up Open WebUI for sandboxing**](docs/setup.md)是关键一步。我们手动完成这个过程。
首先,克隆项目仓库(或直接下载关键文件):
git clone https://github.com/EtiennePerot/safe-code-execution.git cd safe-code-execution核心的配置文件是openwebui.compose.yaml。这个文件定义了一个Docker服务,它包含了与gVisor交互的代码执行逻辑。我们不需要直接运行这个Compose文件,但需要理解其内容,并将其整合到我们已有的Open WebUI部署中。
关键配置解析:查看openwebui.compose.yaml,你会看到它定义了一个codebox服务。这个服务镜像是ghcr.io/open-webui/codebox:latest,这是Open WebUI官方提供的代码执行后端。配置中的核心部分是:
runtime: runsc:指定使用gVisor运行时。network_mode: "host":让沙箱共享宿主网络,这样沙箱内的代码才能访问互联网。这是实现网络访问的关键。- 挂载了
/tmp卷,为代码执行提供临时文件空间。
4.2 整合到现有Open WebUI部署
假设你的Open WebUI是通过Docker Compose部署的(这是最常见的方式)。你需要编辑你的docker-compose.yaml文件。
- 添加
codebox服务:将上述openwebui.compose.yaml中的codebox服务定义复制到你的Compose文件中。 - 修改Open WebUI服务依赖:在你的
open-webui服务定义中,添加对codebox服务的依赖,并设置环境变量指向它。services: open-webui: # ... 你原有的配置(镜像、端口、卷等) ... depends_on: - codebox # 添加这行 environment: - WEBUI_SECURE_COOKIES=false # 可能已有 - WEBUI_NAME="My Open WebUI" # 添加以下环境变量,告诉Open WebUI代码执行后端的位置 - CODEBOX_API_URL=http://codebox:8000 - CODEBOX_TIMEOUT=300 # ... 其他配置 ... # 新增codebox服务 codebox: image: ghcr.io/open-webui/codebox:latest container_name: codebox runtime: runsc # 使用gVisor运行时 network_mode: "host" # 共享主机网络,使沙箱内代码可访问外网 volumes: - /tmp:/tmp:rw # 提供临时文件空间 restart: unless-stopped - 重启服务:
docker-compose down docker-compose up -d
4.3 验证沙箱配置
服务启动后,可以通过以下方式验证:
- 进入Open WebUI容器内部执行命令检查:
如果返回docker exec -it open-webui-container-name curl -f http://codebox:8000/healthOK,则说明后端服务连通正常。 - 在Open WebUI的“设置”(Settings)或“系统信息”中,有时会显示代码执行后端的连接状态。
注意事项:网络模式与安全权衡使用
network_mode: "host"是一个重要的安全决策。它让沙箱拥有了接近宿主机的网络能力,极大地增强了代码的实用性(可以访问API、下载包等)。但同时,这也意味着恶意代码有可能利用网络进行扫描或攻击外部系统(尽管仍受限于沙箱的用户权限)。对于纯粹隔离的离线环境,你可以移除这个配置,这样沙箱将完全无网络访问。请根据你的实际安全需求进行评估。
5. 安装代码执行函数(Function)
环境就绪后,我们就可以在Open WebUI的界面中安装第一个组件:代码执行函数。这个过程主要在Web UI上完成,相对直观。
5.1 详细安装步骤
- 登录Open WebUI,进入管理界面。
- 在左侧导航栏找到并点击
Workspace,然后选择Functions子菜单。这里管理着所有自定义函数。 - 点击页面上的
+(添加)按钮,会弹出一个函数编辑窗口。 - 按照以下信息填写表单:
- Function name:
Run code(建议保持默认,便于识别) - Function description:
Run arbitrary code safely in a gVisor sandbox.(描述清晰即可) - Code section: 这是核心部分。你需要清空默认的代码,然后将项目中的函数代码粘贴进去。代码地址是:
https://raw.githubusercontent.com/EtiennePerot/safe-code-execution/master/open-webui/functions/run_code.py你可以直接在终端用curl获取,或者去GitHub页面复制。
将输出的全部内容粘贴到代码框中。curl -s https://raw.githubusercontent.com/EtiennePerot/safe-code-execution/master/open-webui/functions/run_code.py
- Function name:
- 点击
Save按钮保存函数。 - 保存后,你会在函数列表中找到新添加的“Run code”。确保其右侧的两个开关都处于**开启(绿色)**状态。第一个开关控制函数是否全局可用,第二个开关可能控制其在聊天中的显示。
5.2 函数代码浅析与自定义
虽然直接粘贴就能用,但了解代码的大致逻辑有助于调试和自定义。打开run_code.py,你会发现它主要包含:
@register_function装饰器:这是Open WebUI的函数注册机制。run_code函数:这是核心函数。它接收code(代码字符串)和language(编程语言)两个参数。- 内部逻辑:函数内部会构造一个HTTP POST请求,发送到你之前配置的
CODEBOX_API_URL(即http://codebox:8000),请求体包含了代码、语言和超时设置。 - 结果处理:接收后端返回的执行结果(标准输出、标准错误、退出码),并格式化成易读的消息返回给UI。
你可以进行哪些自定义?
- 超时时间:代码中默认超时是
CODEBOX_TIMEOUT环境变量或300秒。如果经常运行长任务,可以在Open WebUI的环境变量中调整CODEBOX_TIMEOUT,或者在函数代码里硬编码一个更长的值(不推荐,最好用环境变量)。 - 语言支持:后端
codebox服务支持的语言是固定的(通常包括Python, JavaScript, Shell, PHP等)。你可以在函数描述中注明支持的语言,但无法直接在此处添加新语言,需要修改后端镜像。 - 结果格式化:如果你希望执行结果的展示样式不同(比如高亮错误),可以修改函数最后返回消息的Markdown格式。
安装完成后,你就可以在聊天中测试了。找一个能生成代码的模型(如CodeLlama、DeepSeek-Coder等),问它一个编程问题,看看生成的代码块下方是否出现了“Run code”按钮。
6. 安装代码执行工具(Tool)
工具的安装流程与函数类似,但它的作用位置和启用方式不同。工具是赋予模型自主权的关键。
6.1 工具安装步骤
- 同样在
Workspace下,这次选择Tools子菜单。 - 点击
+添加新工具。 - 填写工具信息:
- Toolkit name:
Run code - Toolkit description:
Run arbitrary code safely in a gVisor sandbox. - Code section: 清空后粘贴工具专用的代码。地址为:
https://raw.githubusercontent.com/EtiennePerot/safe-code-execution/master/open-webui/tools/run_code.pycurl -s https://raw.githubusercontent.com/EtiennePerot/safe-code-execution/master/open-webui/tools/run_code.py
- Toolkit name:
- 点击
Save保存。
工具代码run_code.py的结构与函数版类似,但它遵循Open WebUI的工具定义规范,通常包含一个@register_tool装饰器和更详细的工具描述(如输入参数的模式定义),以便LLM能更好地理解何时以及如何调用这个工具。
6.2 为特定模型启用工具
安装工具后,它并不会自动对所有模型生效。你需要为每个支持“工具调用”功能的模型单独启用。
- 进入
Workspace->Models。 - 在模型列表中,找到你想要启用代码执行能力的模型(例如
llama3.1:8b,qwen2.5:7b等),点击其旁边的铅笔(✏️)编辑图标。 - 在模型的编辑页面,向下滚动找到
Tools部分。 - 你应该能看到一个
Run Code的复选框。勾选它。 - 点击
Save & Update保存模型配置。
重要提示:并非所有模型都支持工具调用。这需要模型本身在训练时具备函数调用/工具调用的能力。Ollama的许多较新模型(如Llama 3.1及以后版本、Qwen2.5、DeepSeek最新版等)都支持。如果在这里看不到工具选项,说明你加载的模型可能不支持此特性,需要更换模型。
6.3 工具的使用方法
启用后,在聊天界面使用该模型时,你会发现输入框上方或附近多了一个工具选择区域。通常有一个“Run code”的开关或图标。
- 手动触发模式:在发送消息前,确保“Run code”工具开关是打开状态。这样,你的这次提问就允许模型在思考过程中自主调用代码工具。
- 对话过程:当你提出一个需要计算、查询或执行的任务时,观察模型的回复。如果它决定使用工具,你可能会在回复中看到短暂的“思考”状态,或者在某些UI设计中,消息旁会有一个小图标表示工具被调用。工具执行的过程和原始输出对用户可能是不可见的,你最终看到的是模型整合了工具结果后的自然语言回答。
- 示例:开启工具后,问:“圆周率的前10位小数是什么?” 模型可能会内部调用一个计算
math.pi的Python代码,然后告诉你结果,而你不会直接看到那段代码和它的原始打印输出。
7. 实战应用与高级技巧
安装配置完毕,我们来探讨如何在实际场景中高效、安全地使用这个强大的功能。
7.1 场景一:数据分析与可视化助手
假设你有一个CSV数据文件sales.csv,想让AI帮你分析。
- 使用函数模式:首先,你需要让代码能访问到这个文件。由于沙箱隔离,你需要通过卷映射将宿主机的数据目录挂载到沙箱内。这需要在
codebox服务的Docker Compose配置中额外添加卷映射,例如- /path/to/your/data:/data:ro(只读)。 - 提问:“请编写一个Python脚本,读取
/data/sales.csv文件,计算每个月的总销售额,并用柱状图显示。” - 手动执行与迭代:LLM生成代码后,你点击“Run code”。如果出错(比如缺少pandas库),错误信息会显示出来。你可以将错误反馈给LLM:“运行出错,提示没有pandas模块。请修改脚本,考虑在沙箱环境中安装依赖。” LLM可能会生成包含
subprocess.run([‘pip’, ‘install’, ‘pandas’])的代码。你再次运行,直到成功生成图表图片(沙箱可能需要配置输出图片的路径)。
7.2 场景二:自动化系统信息监控
你想让AI定期检查服务器状态。
- 使用工具模式:为支持工具的模型(如
llama3.1)启用“Run code”工具。 - 提问(开启工具开关):“检查当前系统的内存使用率和磁盘剩余空间。”
- 自主执行:模型会自动生成并执行Shell命令(如
free -h和df -h),解析输出,然后用自然语言总结给你:“当前内存使用率为65%,剩余8.2GB。根目录磁盘使用率为78%,剩余45GB。” - 进阶:你可以结合Open WebUI的“提示词预设”或“工作流”功能,创建一个定时任务,每天自动询问并记录系统状态。
7.3 安全使用准则与限制
尽管有gVisor沙箱,但“安全”是相对的。请务必遵守以下准则:
- 最小权限原则:卷映射只挂载必要的、非敏感的目录,且尽量使用只读(
:ro)模式。 - 资源限制:gVisor和Docker本身可以限制CPU、内存使用。考虑在
codebox服务配置中添加资源限制,防止恶意代码耗尽资源。deploy: resources: limits: cpus: '1.0' memory: 512M - 网络访问控制:如果不需要外部网络,移除
network_mode: “host”。如果需要但想限制,可以考虑使用Docker网络策略或防火墙规则来限制沙箱容器的出站连接。 - 审计日志:Open WebUI和Docker的日志会记录代码执行请求。定期检查这些日志,了解代码执行情况。
- 不要处理极端敏感信息:避免让AI操作含有密码、密钥或核心业务数据的代码。沙箱逃逸虽然极难,但并非100%不可能(取决于gVisor和内核的漏洞)。
8. 常见问题排查与调试实录
在实际部署和使用中,你几乎一定会遇到一些问题。以下是我踩过坑后总结的排查清单。
8.1 问题:“Run code”按钮不出现
- 可能原因1:模型回复中没有正确的代码块。
- 排查:检查LLM的回复是否用Markdown的代码语法包裹,例如
python ...。有些模型在普通对话中可能不会主动生成代码块。在提示词中明确要求:“请将代码放在代码块中。”
- 排查:检查LLM的回复是否用Markdown的代码语法包裹,例如
- 可能原因2:函数未正确启用。
- 排查:进入
Workspace -> Functions,确认“Run code”函数存在,且两个开关都已打开(绿色)。
- 排查:进入
- 可能原因3:Open WebUI版本或配置问题。
- 排查:确保你的Open WebUI版本较新,支持自定义函数功能。检查浏览器控制台(F12)是否有JavaScript错误。
8.2 问题:点击“Run code”后长时间无响应或报超时错误
- 可能原因1:
codebox后端服务未启动或连接失败。- 排查:
docker ps | grep codebox # 检查容器是否在运行 docker logs codebox # 查看后端日志,是否有错误 # 在Open WebUI容器内测试连通性 docker exec open-webui curl -v http://codebox:8000/health - 解决:检查
docker-compose.yaml中codebox服务的配置是否正确,特别是runtime: runsc和网络设置。确保Open WebUI容器的环境变量CODEBOX_API_URL设置正确。
- 排查:
- 可能原因2:gVisor (
runsc) 初始化慢或失败。- 排查:查看
codebox容器日志的前几行,是否有关于runsc的报错。首次启动gVisor沙箱可能需要加载内核模块,会稍慢。 - 解决:确保系统已安装最新的
linux-modules-extra包(如果适用)。可以尝试增加CODEBOX_TIMEOUT环境变量。
- 排查:查看
- 可能原因3:代码本身陷入死循环或等待。
- 排查:尝试运行一段非常简单的代码,如
print(“Hello”)。如果简单代码可以,复杂代码超时,可能是代码逻辑问题。
- 排查:尝试运行一段非常简单的代码,如
8.3 问题:代码执行成功,但无法访问网络/文件
- 网络问题:
- 现象:代码中
requests.get(“http://example.com”)失败。 - 排查:确认
codebox服务配置中使用了network_mode: “host”。如果没有,添加该配置并重启服务。注意,在Docker Compose中,network_mode和networks配置是互斥的。
- 现象:代码中
- 文件访问问题:
- 现象:代码中
open(‘/data/file.txt’)报FileNotFoundError。 - 排查:确认在
codebox服务的volumes中正确挂载了宿主机的路径到容器内的目标路径(如/host/path:/data)。并确认挂载的权限是可读(或可写)的。
- 现象:代码中
8.4 问题:工具模式下,模型不调用代码工具
- 可能原因1:模型不支持工具调用。
- 排查:在
Workspace -> Models中编辑该模型,查看是否有Tools选项。如果没有,换一个支持工具调用的模型,如llama3.1:8b-instruct-q4_K_M。
- 排查:在
- 可能原因2:提示词未激发工具使用。
- 排查:工具调用需要模型在理解任务后,自主决定使用。尝试更明确的任务,如“请使用你拥有的工具,计算2的100次方是多少?”或者在系统提示词中强调模型可以使用代码工具。
- 可能原因3:工具开关未打开。
- 排查:在聊天界面,确认本次消息发送前,“Run code”工具的开关是激活状态(通常会有高亮或勾选显示)。
8.5 性能优化与经验之谈
- 冷启动延迟:gVisor沙箱的冷启动(第一次运行)可能有几百毫秒到一秒的延迟。对于需要频繁执行小代码片的场景,这可能有点慢。这是为了安全付出的代价。
- 资源复用:
codebox服务本身是持久运行的,它会处理多个执行请求。但每个代码执行请求都会启动一个独立的沙箱容器,执行完毕后销毁。因此,代码执行之间是隔离的,无法共享状态(如全局变量)。如果需要在多次执行间保留数据,必须通过挂载的卷来读写文件。 - 语言运行时缺失:默认的
codebox镜像可能只预装了Python和Node.js等少数语言。如果你需要运行Go、Rust等代码,需要自定义构建codebox镜像,添加相应的编译和运行环境。这涉及到Docker镜像构建,是更高级的用法。
通过以上步骤和问题排查指南,你应该能够顺利地在Open WebUI中搭建起一个既强大又安全的代码执行环境。这套组合拳——Ollama提供本地模型、Open WebUI提供交互界面、gVisor提供安全沙箱——真正释放了本地大模型在编程和自动化方面的潜力,让它从一个“聊天专家”升级为一个可以动手的“数字助手”。
