为Open WebUI构建安全代码执行沙箱:基于gVisor的本地LLM增强方案
1. 项目概述为Open WebUI构建安全的代码执行沙箱如果你正在本地部署大语言模型比如用Ollama跑Llama 3或者Qwen并且通过Open WebUI这个漂亮的Web界面来交互那你可能遇到过这样的场景你问模型“帮我写个Python脚本来整理桌面文件”模型很听话地给出了代码但接下来呢你只能手动复制这段代码打开终端新建一个文件粘贴运行。这个过程不仅打断了流畅的对话体验更关键的是如果模型生成的代码存在风险哪怕是无意的直接在你的宿主机上运行无异于“裸奔”。这正是EtiennePerot/safe-code-execution这个项目要解决的核心痛点。它不是一个独立的软件而是一个为Open WebUI量身定制的插件或称为“功能”与“工具”其核心价值在于在WebUI对话界面内安全、一键式地执行模型生成的代码。它的安全基石是Google开源的容器沙箱技术——gVisor。没错就是那个为Google Cloud和ChatGPT等产品提供安全隔离的底层运行时。这个选择本身就很有说服力我们不是在用玩具级别的隔离而是在复用业界顶尖生产环境验证过的方案。简单来说这个项目让你能在Open WebUI里像点击“发送”消息一样点击“运行代码”。代码会在一个由gVisor构建的、与宿主机高度隔离的沙箱环境中执行结果直接返回到对话中。这彻底改变了我们与本地LLM的协作模式从“聊天-复制-手动执行”的割裂流程变成了“提问-生成-验证-迭代”的闭环交互。无论是验证一段数据处理逻辑、测试一个算法还是让模型自己写代码查询实时信息比如日期、网络请求都变得无比顺畅和安全。2. 核心概念解析Function与Tool的双重角色刚接触这个项目你可能会对“Function”函数和“Tool”工具这两个概念感到困惑。它们都提供代码执行能力但设计哲学和使用场景有本质区别。理解这一点是高效利用该项目的关键。2.1 代码执行函数用户主导的显式执行你可以把“代码执行函数”想象成一个由你完全控制的“执行按钮”。它的工作流程非常直观你向模型提问例如“用Python计算斐波那契数列的前10项。”模型在回复中生成一个代码块Markdown格式的python ...。在该条模型回复的下方会出现一个“Run code”按钮。由你点击这个按钮触发代码在沙箱中执行。执行结果标准输出、错误信息会作为一个新的、可见的消息插入到对话中你和模型都能看到。它的核心特点是“用户显式控制”。每一次代码执行都需要你主动点击确认。这带来了两个好处一是安全性感知更强你清楚地知道什么时候、什么代码被执行了二是结果对对话双方透明便于你和模型基于执行结果进行后续的讨论和调试。这非常适合教育、代码评审、分步问题解决等场景即你希望与模型协作并清晰地跟踪每一个执行步骤。2.2 代码执行工具赋予模型的自主能力而“代码执行工具”则更进一步它尝试将执行能力“赋予”模型本身。其工作流程更像是一个自动化的智能体你在发送消息时在输入框旁激活“Run code”工具的开关。你提出一个复杂需求例如“请帮我分析一下今天GitHub上Trending的Python项目总结它们的共同特点。”模型在内部“思考”后可能会自主决定“要完成这个任务我需要先获取当前日期然后发起一个网络请求抓取GitHub页面最后对内容进行解析和总结。”于是模型会自动、隐形地调用“Run code”工具。它可能会先执行一段获取日期的代码再执行一段使用requests库抓取网页的代码。这些工具调用的过程对你是不可见的但执行的结果会作为背景信息反馈给模型。最终模型整合这些信息给你一个完整的、基于实时数据生成的答案。它的核心特点是“模型自主决策”。这模拟了ChatGPT的“代码解释器”或“联网搜索”功能。工具的执行过程对用户是黑盒只有最终答案呈现出来。这极大地扩展了模型的能力边界使其能够处理需要实时数据、复杂计算或外部交互的任务。适合用于数据分析、信息检索、自动化脚本生成等你希望模型“自主完成”的场景。选择建议对于初学者或注重可控性的用户建议先安装并使用“函数”。它简单直观风险完全可控。当你熟悉了沙箱的执行效果并且有需要模型自主完成复杂链式任务的需求时再考虑启用“工具”。在实际使用中我通常两者都安装根据对话的上下文灵活选择使用方式。3. 环境准备构建gVisor沙箱基础安全是这一切的前提。safe-code-execution的强大隔离能力完全依赖于gVisor。因此第一步不是安装插件本身而是搭建一个能让Open WebUI安全调用gVisor的环境。这个过程需要一些Linux系统操作知识但每一步都有明确的意图。3.1 系统与权限检查首先确保你在一个Linux系统上Windows的WSL2理论上可行但可能遇到更多路径和服务管理问题本文以原生Linux为例。该项目重度依赖Linux的命名空间和cgroup特性。你需要拥有root权限或能通过sudo执行管理命令。因为我们要创建系统级服务、挂载文件系统、调整内核参数。打开终端我们先做一个快速检查# 检查当前用户是否有sudo权限 sudo echo “权限检查通过” # 检查uname确认是Linux内核 uname -s如果第一条命令报错你需要切换到有sudo权限的用户或联系系统管理员。3.2 安装与配置gVisorgVisor的安装有多种方式这里我们采用其官方推荐的、最适合与容器运行时集成的runsc安装方式。下载最新稳定版runsc runsc是gVisor的运行时组件。我们直接从Google的存储库下载预编译二进制文件这通常比从源码编译更可靠。( set -e ARCH$(uname -m) [ “$ARCH” “x86_64” ] ARCH“amd64” [ “$ARCH” “aarch64” ] ARCH“arm64” wget https://storage.googleapis.com/gvisor/releases/release/latest/${ARCH}/runsc wget https://storage.googleapis.com/gvisor/releases/release/latest/${ARCH}/runsc.sha512 sha512sum -c runsc.sha512 sudo mv runsc /usr/local/bin sudo chmod arx /usr/local/bin/runsc )这段脚本做了几件事自动检测系统架构amd64或arm64下载对应的runsc二进制文件和校验文件验证文件完整性然后将其安装到/usr/local/bin目录并赋予执行权限。set -e确保过程中任何一步出错都会停止避免安装不完整的文件。将runsc注册为Docker/Containerd的运行时 gVisor需要作为容器运行时被调用。我们将其配置为Docker的一个可选运行时。sudo runsc install --runtimerunsc-gvisor执行成功后你需要重启Docker服务来使配置生效sudo systemctl restart docker验证gVisor安装 让我们运行一个简单的测试容器确认gVisor工作正常并且体验一下它的隔离效果。# 使用gVisor运行时运行一个Alpine Linux容器 sudo docker run --runtimerunsc-gvisor -it alpine:latest /bin/sh进入容器后尝试执行一些命令# 查看内核版本会发现不是宿主机的内核而是gVisor模拟的 uname -a # 尝试访问/proc或/sys下的某些敏感文件可能会受到限制 # 退出容器 exit如果你看到内核版本显示类似4.4.0等字样而非你宿主机的真实内核版本并且某些系统操作被限制说明gVisor正在正常工作提供了有效的隔离。3.3 为Open WebUI配置沙箱执行服务这是最关键的一步。Open WebUI本身是一个Web应用它不能直接以root权限去执行docker run命令。我们需要创建一个安全的中间层——一个简单的本地HTTP API服务由它来代表Open WebUI与gVisor沙箱交互。项目作者提供了优雅的解决方案。创建专用系统用户和目录 为了最小化权限我们创建一个仅用于运行此服务的系统用户。sudo useradd -r -s /bin/false openwebui-sandbox sudo mkdir -p /opt/openwebui-sandbox sudo chown openwebui-sandbox:openwebui-sandbox /opt/openwebui-sandbox部署服务脚本 从项目仓库获取核心的服务端Python脚本。sudo wget -O /opt/openwebui-sandbox/sandbox_server.py https://raw.githubusercontent.com/EtiennePerot/safe-code-execution/master/sandbox_server.py sudo chown openwebui-sandbox:openwebui-sandbox /opt/openwebui-sandbox/sandbox_server.py sudo chmod x /opt/openwebui-sandbox/sandbox_server.py这个sandbox_server.py脚本就是我们的“安全代理”。它启动一个HTTP服务器监听本地请求。当收到执行代码的请求时它以openwebui-sandbox用户的身份使用sudo权限通过特定的配置启动一个gVisor容器在容器内执行代码然后将结果返回。配置sudo权限无需密码 我们需要让openwebui-sandbox用户能无密码地以root身份执行特定的docker命令而不能做其他任何事情。这是通过sudoers文件实现的务必精确操作。sudo visudo -f /etc/sudoers.d/openwebui-sandbox在打开的编辑器中输入以下内容# 允许openwebui-sandbox用户无密码运行特定的docker命令 openwebui-sandbox ALL(ALL) NOPASSWD: /usr/bin/docker run --rm --runtimerunsc-gvisor * openwebui-sandbox ALL(ALL) NOPASSWD: /usr/bin/docker kill *重要解释第一行允许该用户运行docker run命令且必须包含--runtimerunsc-gvisor参数这强制使用gVisor沙箱。*通配符允许接收任意后续参数如镜像名、命令等。第二行允许它kill容器用于超时控制。配置完成后保存退出。visudo命令会进行语法检查比直接编辑文件更安全。创建并启用Systemd服务 为了让服务随系统启动并稳定运行我们将其配置为Systemd服务。sudo tee /etc/systemd/system/openwebui-sandbox.service ‘EOF’ [Unit] DescriptionOpen WebUI Safe Code Execution Sandbox Server Afterdocker.service network.target Requiresdocker.service [Service] Typesimple Useropenwebui-sandbox Groupopenwebui-sandbox WorkingDirectory/opt/openwebui-sandbox ExecStart/usr/bin/python3 /opt/openwebui-sandbox/sandbox_server.py Restartalways RestartSec5 # 安全限制 NoNewPrivilegesyes PrivateTmpyes ProtectSystemstrict ReadWritePaths/var/run/docker.sock [Install] WantedBymulti-user.target EOF这个服务单元文件做了严格的沙箱化以专用用户运行限制其权限只允许访问Docker套接字并设置自动重启。启动并测试服务sudo systemctl daemon-reload sudo systemctl enable --now openwebui-sandbox.service sudo systemctl status openwebui-sandbox.service查看状态确认服务是active (running)。然后我们可以用curl测试一下这个本地API是否工作curl -X POST http://localhost:8080/run \ -H “Content-Type: application/json” \ -d ‘{“image”: “python:3.11-slim”, “command”: “python -c \“print(‘Hello from gVisor!’)\“”}’如果返回包含“Hello from gVisor!”的JSON响应恭喜你沙箱服务已经就绪。这个localhost:8080就是后续Open WebUI插件需要连接的地址。4. 在Open WebUI中安装与配置插件基础环境搭建好后剩下的就是在Open WebUI界面里的配置工作了这部分相对直观。4.1 安装代码执行函数打开你的Open WebUI界面登录后进入Workspace工作区菜单。选择Functions函数子菜单。这里管理着所有自定义的交互功能。点击页面上的按钮开始创建新函数。在弹出的表单中填写以下信息Function name:Run code这个名字会显示在按钮上Function description:Run arbitrary code safely in a gVisor sandbox.描述有助于理解功能Code section: 这是核心。你需要清空默认的代码然后将浏览器导航到项目的GitHub仓库找到open-webui/functions/run_code.py这个文件点击“Raw”按钮查看原始内容并将其全部复制粘贴到这里。点击Save按钮保存。保存后你会在函数列表里看到新添加的Run code。确保其右侧的两个开关一个可能是“启用”另一个是“显示在消息中”或类似含义都处于打开绿色状态。关键代码解析粘贴的run_code.py文件内容并不长它的核心逻辑是当用户在UI点击按钮时Open WebUI会调用这个函数。函数会提取当前消息中的代码块然后向我们之前部署的本地服务http://localhost:8080/run发起一个POST请求。请求体中包含了要执行的代码、指定的语言如python以及超时时间。本地沙箱服务执行完毕后将结果返回函数再把这个结果格式化成一条新的消息插入对话。整个过程Open WebUI只与localhost:8080通信不直接接触Docker或系统命令。4.2 安装代码执行工具工具的安装过程与函数极其相似但位置不同。在Open WebUI的Workspace下这次选择Tools工具子菜单。同样点击按钮。填写表单Toolkit name:Run codeToolkit description:Run arbitrary code safely in a gVisor sandbox.Code section: 清空后从项目的open-webui/tools/run_code.py文件中复制全部内容并粘贴。点击Save。函数与工具代码的差异虽然两者都叫run_code.py但tools目录下的版本逻辑略有不同。它被设计成一个“工具调用”的端点其输入输出格式需要符合Open WebUI工具调用的规范通常是一个更结构化的JSON。当模型决定使用工具时它会向这个端点发送一个符合规范的请求。本质上它和函数一样也是将请求转发给本地的沙箱服务。4.3 为模型启用工具调用能力安装工具后它并不会自动对所有模型生效。你需要为支持工具调用Tool Calling的模型单独启用它。进入Workspace-Models。在模型列表中找到你想要启用代码执行能力的模型例如llama3.1:8b,qwen2.5:7b等较新的模型通常支持点击其旁边的铅笔编辑图标。在模型的编辑页面向下滚动你应该能看到一个Tools或Tool Calling的区块。在工具列表中勾选我们刚刚添加的Run Code。点击Save Update保存模型配置。重要提示不是所有模型都支持工具调用。这需要模型在训练时具备相关能力。Ollama官方的llama3.1及以后版本、qwen2.5、deepseek-coder等模型通常支持。如果你勾选后工具不生效首先应确认模型是否具备此能力。5. 实战应用与效果演示配置完成让我们看看它如何改变工作流。假设我们已安装好“函数”和“工具”并为一个支持工具调用的模型如Llama 3.1启用了工具。5.1 使用代码执行函数进行交互式编程场景我想让模型帮我写一个Python脚本用来查找并打印当前目录下所有大于1MB的.log文件。提问在聊天框输入“写一个Python脚本找出当前工作目录下所有大小超过1MB的.log文件并打印它们的完整路径和大小。”模型回复模型生成了一段包含代码块的回复类似你可以使用以下Python脚本实现该功能 python import os def find_large_log_files(directory‘.’, size_threshold_mb1): size_threshold size_threshold_mb * 1024 * 1024 # 转换为字节 for root, dirs, files in os.walk(directory): for file in files: if file.endswith(‘.log’): file_path os.path.join(root, file) try: file_size os.path.getsize(file_path) if file_size size_threshold: print(f“File: {file_path}, Size: {file_size / (1024*1024):.2f} MB”) except OSError as e: print(f“Error accessing {file_path}: {e}”) if __name__ “__main__”: find_large_log_files() 执行验证在这条回复的下方你会看到一个Run code按钮。点击它。查看结果几秒钟后一条新的系统消息会出现内容就是这段代码在gVisor沙箱中执行的标准输出。因为沙箱环境是全新的目录下可能没有.log文件输出可能是空的或者提示找不到文件。但这已经完成了验证。迭代优化你可以基于结果继续对话“这个脚本在找不到文件时输出不够友好如果目录下没有.log文件请提示‘未找到符合条件的文件’。” 模型会生成改进后的代码你可以再次点击运行验证。这个过程的价值你无需离开浏览器无需打开终端就在同一个上下文里完成了“提出需求 - 生成代码 - 即时验证 - 反馈优化”的完整循环。对于学习编程、快速原型验证、自动化脚本编写来说效率提升是巨大的。5.2 使用代码执行工具进行自动化任务场景我想知道当前日期并获取一个最新新闻标题假设模型训练数据截止日期较早。准备在发送消息前确保聊天输入框附近的“Run code”工具开关被激活通常是一个小图标点击后变亮。提问输入“告诉我今天的日期并且去BBC新闻首页看看今天的一条头条新闻标题是什么。”模型自主执行模型收到这个请求后内部会进行“思考”。它意识到需要两个实时信息当前日期和网络数据。于是它可能会自主发起两次工具调用第一次调用执行python -c “from datetime import datetime; print(datetime.now().strftime(‘%Y-%m-%d %H:%M:%S’))”来获取精确时间。第二次调用执行一个使用requests和BeautifulSoup库的Python脚本去抓取BBC新闻首页解析出第一个头条新闻的标题。返回最终答案你不会看到工具调用的中间过程。稍等片刻后模型会直接给出一个整合后的答案例如“今天是2023年10月27日。根据抓取的BBC新闻首页信息当前的一条头条新闻标题是‘Global Summit Reaches New Climate Agreement’。”验证与追问你可以追问“这条新闻的链接是什么” 模型可能会再次自主调用工具从刚才抓取的页面中提取出链接并告诉你。工具模式的核心优势它将LLM从一个纯文本生成器变成了一个可以主动使用“手脚”工具的智能体。对于需要结合实时信息、计算或外部API的复杂问答这种能力是革命性的。你只需要提出最终目标模型会自己规划步骤并执行。6. 深入原理gVisor如何保障安全我们一直在提“安全沙箱”那么gVisor到底做了什么理解其原理能让你更放心地使用这个方案并理解其能力边界。6.1 与传统容器Docker的隔离差异普通的Docker容器使用Linux内核的命名空间namespace和控制组cgroup进行隔离。虽然这提供了不错的资源视图隔离但所有容器共享宿主机的内核。如果一个容器内的进程通过系统调用syscall利用到了内核漏洞就有可能影响到宿主机或其他容器。这被称为“容器逃逸”。gVisor采取了截然不同的思路。它不是一个“更严格的容器”而是一个用户态的内核实现。当你在gVisor中运行一个程序时拦截系统调用应用程序发出的每一个系统调用如打开文件、网络通信都不会直接到达宿主机内核。Sentinel代理gVisor的核心组件runsc会拦截这些调用。用户态内核处理gVisor自己实现了一套完整的、用Go语言编写的Linux内核语义包括文件系统、网络栈、进程调度等在用户态处理这个系统调用。安全的宿主调用只有当必要时如需要真正的硬件资源、访问受控的外部文件gVisor才会通过一个极简的、经过严格审查的“主机系统调用接口”与宿主机内核通信这个接口暴露的攻击面非常小。简单比喻传统容器像是给每个租客容器一个带锁的独立房间命名空间但大家共用一套中央水电系统内核。gVisor则是给每个租客一个完全独立的、自包含的迷你屋用户态内核迷你屋通过一个极其狭窄、坚固的管道主机接口与外界交换水电这个管道很难被滥用。6.2 本项目中的安全架构safe-code-execution项目构建了一个纵深防御体系第一层gVisor沙箱代码最终在gVisor容器内运行与宿主机内核隔离。即使代码恶意尝试执行rm -rf /或进行网络扫描其破坏力也被限制在沙箱内。第二层容器限制通过Docker命令我们还附加了额外的安全限制--read-only容器根文件系统只读防止代码篡改系统文件。--network none或 严格限制的网络策略默认可以切断网络或仅允许访问特定地址防止数据外泄或网络攻击。--memory,--cpus限制资源使用防止耗尽主机资源。--user nobody以非root用户身份运行容器内的进程。第三层权限隔离服务我们创建的openwebui-sandbox系统用户和Systemd服务本身权限就被严格控制只能执行特定的Docker命令。第四层Open WebUI上下文整个流程由Web UI触发最终用户不直接接触服务器命令行。这种多层防护使得在Open WebUI中执行任意代码的风险变得极低。当然没有绝对的安全。gVisor的性能开销比普通容器稍高因为系统调用需要经过转换且对某些极其底层的系统调用支持可能有限但对于执行Python脚本、Shell命令等AI代码生成场景这完全是可接受的权衡。7. 高级配置与故障排查在实际使用中你可能会需要调整一些配置或者遇到问题。这里分享一些进阶技巧和常见问题的解决方法。7.1 自定义沙箱环境默认情况下插件使用python:3.11-slim镜像来执行Python代码。但你可能需要其他语言或特定依赖。修改默认镜像你需要编辑之前部署的sandbox_server.py脚本。找到其中类似default_image “python:3.11-slim”的行将其修改为你需要的镜像例如node:20-alpine用于执行JavaScript/Node.js代码。golang:1.21-alpine用于执行Go代码。ubuntu:22.04用于一个更完整的Linux环境可以安装多种工具。修改后需要重启服务sudo systemctl restart openwebui-sandbox.service为工具调用传递语言参数在工具的Python脚本open-webui/tools/run_code.py中你可以看到它如何构造请求。你可以修改逻辑让模型在调用工具时指定language如bash,javascript服务端根据语言选择不同的基础镜像。这需要一些额外的编程工作。7.2 网络访问控制默认配置可能允许沙箱访问外部网络用于pip install或抓取网页。如果你希望完全禁止可以在docker run命令中添加--network none参数。在sandbox_server.py中找到执行docker run命令的部分通常在subprocess.run调用中添加此参数。反之如果网络访问有问题请检查gVisor的网络支持确保宿主机网络正常且gVisor的runsc支持你的网络配置如bridge模式。防火墙宿主机防火墙是否阻止了容器出站流量。代理如果你的环境需要HTTP代理才能访问外网需要在Docker容器内设置环境变量如HTTP_PROXY这需要在sandbox_server.py中构建命令时添加-e参数。7.3 常见问题与解决问题1点击“Run code”按钮或使用工具后长时间无响应最终报超时错误。排查首先检查沙箱服务状态sudo systemctl status openwebui-sandbox.service。查看日志sudo journalctl -u openwebui-sandbox.service -f。可能原因及解决服务未运行按照第3.3节步骤重启服务。Docker权限问题确认/var/run/docker.sock的权限确保openwebui-sandbox用户所在组有读写权限。通常docker组有权限可以将用户加入该组sudo usermod -aG docker openwebui-sandbox然后重启服务。gVisor运行时未注册运行sudo docker info | grep -i runtime检查输出中是否包含runsc-gvisor。如果没有重新执行sudo runsc install --runtimerunsc-gvisor并重启Docker。镜像拉取慢首次运行会拉取Docker镜像如python:3.11-slim如果网络慢会导致超时。可以手动提前拉取sudo docker pull python:3.11-slim。问题2代码执行成功但返回结果乱码或格式错乱。排查这通常是编码问题。沙箱内是纯净环境默认编码可能是POSIX或C.UTF-8。解决在生成的代码中显式指定编码。对于Python可以在脚本开头添加import sys import io sys.stdout io.TextIOWrapper(sys.stdout.buffer, encoding‘utf-8’) sys.stderr io.TextIOWrapper(sys.stderr.buffer, encoding‘utf-8’)或者在sandbox_server.py中为docker run命令设置环境变量-e PYTHONIOENCODINGutf-8。问题3工具调用不生效模型无视我的请求。排查确认模型是否支持工具调用。尝试问模型“你支持工具调用Tool Calling吗” 一些旧版模型可能不支持。在Open WebUI的模型设置页面确认Run Code工具已被勾选并保存。发送消息时确认输入框旁的“Run code”工具图标是激活状态高亮。查看Open WebUI的后台日志或浏览器开发者工具的网络请求看是否有向/api/tools/run_code发起的请求。解决如果模型不支持需要更换模型。如果支持但未触发尝试更明确的指令如“请使用代码执行工具来获取当前日期”。问题4执行需要安装额外包的Python代码失败ModuleNotFoundError。原因gVisor沙箱每次都是全新的、纯净的环境。解决在代码中内联安装。例如# 在执行主逻辑前先安装依赖 import subprocess import sys subprocess.check_call([sys.executable, “-m”, “pip”, “install”, “-q”, “pandas”, “requests”]) # 然后导入并使用 import pandas as pd ...注意这会增加代码执行时间。对于常用且稳定的依赖更好的方式是构建一个自定义的Docker镜像预装好这些包然后修改sandbox_server.py使用这个自定义镜像作为默认镜像。8. 性能优化与生产考量在个人开发环境中默认配置通常足够。但如果使用频繁或考虑在团队中部署以下几点优化建议值得参考镜像层缓存虽然gVisor容器本身是临时的但Docker镜像层会被缓存。确保使用像python:3.11-slim这样体积较小的官方镜像。可以进一步构建一个包含常用数据科学库如numpy, pandas, scikit-learn的专属镜像避免每次临时安装。资源限制在sandbox_server.py的docker run命令中明确设置内存-m 512m和CPU--cpus1限制防止单个失控的代码耗尽主机资源。超时控制插件本身和sandbox_server.py都有超时设置如30秒。对于复杂计算可能需要适当调高。但务必设置一个上限避免无限循环代码挂起服务。日志与审计生产环境应考虑记录代码执行日志。可以修改sandbox_server.py将收到的请求去除敏感信息后和执行结果摘要写入一个日志文件或发送到监控系统用于安全审计和故障排查。多语言支持增强目前的实现主要针对Python。你可以扩展sandbox_server.py使其能根据请求中的language字段智能选择不同的基础镜像和执行命令如Node.js用node -eBash用/bin/bash -c。将安全的代码执行能力集成到Open WebUI中通过gVisor沙箱提供坚实隔离这不仅仅是添加了一个功能而是从根本上扩展了本地大语言模型的实用性和安全性边界。它模糊了“对话”与“执行”的界限让LLM从一位博学的顾问变成了一个能动手操作的伙伴。从简单的计算验证到复杂的、需要实时数据的自动化任务这个组合为你打开了一扇新的大门。