在这篇文章中,我想讨论自定义Open WebUI界面和功能的各种选项。我将讨论三个具体的例子。对于那些还不熟悉该应用程序的人来说,开源项目Open WebUI允许通过本地用户界面使用各种AI模型,而无需复杂的编程技能。这些模型可以通过LLM运行器Ollama集成。或者,也可以将这些模型以Hugging Face的GGFU格式实现并集成。接下来,我将简要介绍如何设置Open WebUI。如果应用程序已经存在,很遗憾,这一步还是不能跳过。为什么呢?因为这里有一个例子需要考虑。
设置 OPEN WEBUI 的步骤可以使用 Docker 或 Kubernetes 进行设置。本文将介绍如何使用 Docker 进行设置。首先,访问官网 Docker,下载 Docker Desktop [DD],在官网的“产品”页面下载,取决于你所使用的系统。
下载 Docker Desktop [自拍照 Ollama]
安装好DD之后,就可以启动应用程序了。目前还没有可用的“容器”。什么是容器?容器是一个可执行单元,包含应用程序及其所有依赖项,在一个独立的包中。这样做的一大好处是,应用程序可以在不同的系统上运行,且特定的环境条件不再成为限制因素。
暂时没有可用的容器 [Own Screenshot Ollama].
在处理 Open WebUI 之前,必须先安装 Ollama。如果已安装 Ollama,可以跳过。如果没有安装,我们将前往 Ollama 的官网并下载其应用程序。
点击 Ollama [Own Screenshot Ollama]
安装之后,你需要检查一下Ollama是否能用,你可能需要重启一下系统。你可以用下面的命令快速检查一下,看看有没有问题。
运行命令来查看版本号:
ollama --version
将 Ollama 和 Open WebUI 结合起来是有道理的。Ollama 提供了模型管理的基础设施,而与模型互动的界面则由 Open WebUI 提供。
我们现在可以访问到Open WebUI的官方GitHub仓库。在“如何安装”部分,可以找到各种安装应用的命令。根据你选择的命令,可能还需要做一些调整。如果已经安装了Ollama,根据仓库中的说明,应该使用以下命令:
docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main
如果你想让 Open WebUI 运行时带有 Nvidia GPU 支持,必须使用以下命令:
docker run -d -p 3000:8080 --gpus all --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:cuda
根据你选择的哪个命令,需要稍微调整一下,以便能让其中的一个扩展程序在界面上正常工作。
docker run -d -p 3000:8080 --gpus all --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --mount type=bind,source="C:\Users\scwom\Desktop\OPEN WEBUI FUNCTIONS\docker_data",target=/app/data --name open-webui --restart always ghcr.io/open-webui/open-webui:cuda
该命令在以下区域得到了扩展。
„--mount type=绑定,source="C:\Users\scwom\Desktop\OPEN WEBUI FUNCTIONS\docker_data",target=/app/data“. 用于绑定C盘路径到容器内的/app/data目录。
这个扩展功能是做什么的?将本地计算机(主机系统)中的 _‘dockerdata’ 文件夹挂载到容器中。存储在容器中的数据 ‘目标=/app/data’ 将在本地计算机上直接可用。需要根据实际路径调整 ‘目标=/app/data’ 的路径!通过这种方式,即使容器在隔离运行状态下,也可以实现数据交换。
挂载绑定 [自绘插图]
无法为正在运行的容器设置绑定挂载!这是什么原因呢?因为 Docker 不允许这样做。,为了能够交换,我们需要创建一个新的容器。因此,我们调整了上面的命令。安装完成后,容器 “open-webui” 应该会在 Docker Desktop 中出现。我们点击指定的端口,然后登录。
启动 WebUI 容器 [可选:自己的 Docker 桌面截图]
如果没有可用的本地模型,就必须通过Ollama下载。在Ollama页面上,转到“模型”选项卡,然后选择一个模型。在这里你可以看到当前的Llama3.1模型(由Meta提供)。使用命令“ollama run llama3.1”(输入该命令来加载模型)。系统重启后,你可以在Open WebUI中找到它。
模型管理功能 3.1 版本的 Llama [自己拍摄的 Ollama 截图]
OPEN WEBUI 中的功能你可以通过多种功能来自定义 Open WebUI 的用户界面,从而也可以自定义与模型的交互方式。这样,你可以打造一个符合你需求的个性化 WebUI。我将简要介绍一下这些功能。
模型的输入和输出筛选条件过滤器可以用来调整或控制现有语言模型的输出。这里区分两种功能。入口功能会在用户输入发送到大型语言模型之前对其进行预处理。输入因此可以被清理、格式化。出口功能会对模型的输出进行处理。不应输出的内容可以被移除。在教育环境下,过滤器是一个有用的特性,可以防止输入和输出不希望的内容。过滤器包含由管理员(Valves)或最终用户(UserValves)设定的配置选项。这允许用户控制过滤器的各个方面,例如,设置过滤器的优先级 [1]。
class Filter:
# 定义阀门类
class Valves(BaseModel):
priority: int = Field(
default=0, description="过滤操作的优先级设置."
)
test_valve: int = Field(
default=4, description="一个控制数值的阀门."
)
pass
# 定义用户阀门类
class UserValves(BaseModel):
test_user_valve: bool = Field(
default=False, description="一个控制开关状态的用户阀门."
)
pass
def __init__(self):
self.valves = self.Valves()
pass
def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
print(f"inlet:{__name__}")
print(f"inlet:body:{body}")
print(f"inlet:user:{__user__}")
# 预处理步骤
return body
def outlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
print(f"outlet:{__name__}")
print(f"outlet:body:{body}")
print(f"outlet:user:{__user__}")
# 后处理步骤
return body
通过互动操作获得更多互动
可以创建操作将交互按钮集成到Open WebUI用户界面中。_“操作”_功能定义了执行的操作类型以及处理的数据 [1]。
async def action(
self,
body: dict,
__user__=None,
__event_emitter__=None,
__event_call__=None,
) -> Optional[dict]:
print(f"操作:{__name__}")
response = await __event_call__(
{
"type": "输入类型",
"data": {
"标题": "写一条消息:",
"消息内容": "在此输入要追加的消息",
"提示": "请输入您的消息",
},
}
)
print(response)
从管道连接到管路
管道可以在Open WebUI中使用,以创建具有用户定义逻辑和处理功能的模型。换句话说,管道在WebUI中是一个独立的模型。主要的执行逻辑则定义在“pipe”函数中。一个管道可以管理多个模型。与管道相比,总线是一组模型。它们在一个系统中管理多个管道,就像管道管理模型一样【1】。
class Pipe:
class Valves(BaseModel):
RANDOM_CONFIG_OPTION: str = Field(default="")
def __init__(self):
self.type = "pipe"
self.id = "blah"
self.name = "Testing"
self.valves = self.Valves(
**{"RANDOM_CONFIG_OPTION": os.getenv("RANDOM_CONFIG_OPTION", "")}
)
def get_provider_models(self):
return [
{"id": "model_id_1", "name": "model_1"},
{"id": "model_id_2", "name": "model_2"},
{"id": "model_id_3", "name": "model_3"},
]
def pipe(self, body: dict) -> Union[str, Generator, Iterator]:
# Logic goes here
return body
共享功能模块
这些功能可以用于提供动态信息,例如 API密钥或配置选项。与过滤器功能一样,这些选项可以由管理员(管理员自定义选项)(Valves)或最终用户(用户自定义选项)(UserValves)自定义。
你现在的状态咋样?另一个有用的功能是允许通过事件发射器将状态信息整合到与模型的交互中。这可以让用户实时了解进度。这对于更复杂的查询及其后续计算特别有帮助。随时在传输的输入中插入额外消息也很重要,以便提供更多信息或报告错误。例如,如果传输的数据有误,可以中断模型的长时间计算。
Open WebUI 的官方文档 [1]展示了各种功能的实现示例。下面,我将讨论我所创建的三个例子。
新的网页界面功能这三个例子涵盖了不同的功能,我在前面已经讨论过了。第一个例子是关于状态发射器的介绍,第二个例子是关于过滤器的,最后一个例子是关于动作的演示。这些功能可以在本文末尾找到下载链接。
我们将要创建的三个新特性(注:自有插图)
状态发送器 —— OIF 例子 1第一个示例属于“工具”类。实现了一个异步方法,模拟了顺序处理过程。进度被发送到事件发射器。在 Python 中,异步编程所需的 “asyncio” 模块是必不可少的。在 “run” 函数中,处理进度通过变量 _“__event_emitter_” 来表示。进程启动后,执行一个迭代 5 次的循环 “for i in range(1, 6):”,最后输出进程完成的信息。这为用户界面增加了进度指示器。
import asyncio
class 工具类:
def __init__(self):
pass
async def 执行(self, 提示信息: str, __user__: dict, __event_emitter__=None) -> str:
"""
通过事件发射器向用户报告进度。
"""
if __event_emitter__:
await __event_emitter__(
{
"type": "STATUS",
"data": {"状态描述": "处理开始...", "完成状态": False},
}
)
for i in range(1, 6):
await asyncio.sleep(1)
if __event_emitter__:
await __event_emitter__(
{
"type": "STATUS",
"data": {
"状态描述": f"步骤 {i} 完成,共 5 步...",
"完成状态": False,
},
}
)
if __event_emitter__:
await __event_emitter__(
{
"type": "STATUS",
"data": {
"状态描述": "处理完成!",
"完成状态": True,
},
}
)
return "处理已完成。"
即使显示状态信息实际上是一个功能,代码也必须作为一个 “工具” 来整合。在 Open WebUI 中,我们进入 “工作区” 区域。在这里,我们点击 “工具”,然后点击加号。在下面的截图中,上述提到的工具已经包含在内了。
创建一个新工具(自己的截图打开WebUI) [Own Screenshot Open WebUI]
将Python脚本中的代码复制到编辑器里。定义一个工具的名字,并输入描述信息。最后,点击“保存”按钮。
将代码粘贴到代码编辑器中并保存(自己的截图:打开WebUI)
或者,您也可以通过社区市场集成该插件。在“工具”部分,点击“Made by OpenWebUI Community”区域中的“发现插件”,您会进入一个概览页面。在这里面,您可以在“工具”下查找@pietrusky。您也可以直接点击这个链接链接。
搜索社区来查找状态源 [截图并打开WebUI]
在工具页面上,点击 “获取”,然后确认 “导入到WebUI”。可能需要指定Docker容器的URL。或者,你可以将工具作为.json文件加载,然后将它上传到该区域的 “工作区部分”。
从OpenWebUI社区获取状态 (可以参考您自己的Open WebUI截图)
开始一个新的聊天会话,点击旁边的加号,激活该对话工具。
启用新工具[自定义截图打开WebUI]
实际上,状态信息看起来像这样:
这就是状态消息的显示效果,就像这样,请查看打开的WebUI GIF,自行查看。
不需要词汇过滤器 [示例 2]这其实是一个函数,而不是一个工具。具体来说,它是一个过滤器,可以防止某些单词被处理并在聊天历史中显示,而无需调整系统消息。我们简单看一下该函数的代码。“Filter”函数包含两个主要方法“inlet”和“outlet”。这些方法会分别在输入和输出中查找不需要的单词,如果找到,就会被替换为“[filtered]”。在这个例子中,只有“sugar”被定义为“_UNWANTEDWORDS”中的一个不需要的单词。这个单词列表可以根据具体的应用需求进行调整。
from pydantic import BaseModel, Field
from typing import Optional, Dict
import re
class Filter:
def __init__(self):
pass
def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
print(f"入口:当前模块名")
print(f"入口:过滤前的body:{body}")
print(f"入口:用户:{__user__}")
UNWANTED_WORDS = ["sugar"]
for message in body.get("messages", []):
content = message.get("content", "")
print(f"原始消息内容:{content}")
for word in UNWANTED_WORDS:
content = re.sub(
rf"\b{word}\b", "[filtered]", content, flags=re.IGNORECASE
)
message["content"] = content
print(f"过滤后的消息内容:{message['content']}")
print(f"入口:过滤后的body:{body}")
return body
def outlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
print(f"出口:当前模块名")
print(f"出口:过滤前的body:{body}")
UNWANTED_WORDS = ["sugar"]
for message in body.get("messages", []):
content = message.get("content", "")
for word in UNWANTED_WORDS:
content = re.sub(
rf"\b{word}\b", "[filtered]", content, flags=re.IGNORECASE
)
message["content"] = content
print(f"出口:过滤后的body:{body}")
return body
要使用Open WebUI中的该功能,必须先创建它。我们回到“Workspace”区域并点击“Functions”。再次点击加号按钮,并将文件“unwanted_words_filter.py”中的代码复制到编辑器中。或者,该功能也可以在社区中找到。创建完功能后,还需要激活它。功能可以为所有现有的模型全局激活模式。为此,请点击三个点并启用“全局”模式。这样用户就不必在每次对话中都单独激活该功能了,但使用上述工具则需要这样做。
激活新功能:屏幕截图并打开WebUI
在聊天历史中,显示 “[filtered]” 可能会有轻微的延迟。无论怎样,定义的词语将不再被 LLM 记录下来。输入和输出将会是这样的。这种功能在教育环境中特别有用,可以防止某些特定输入和输出。
带有新滤镜的对话 (来自自己截图的开放Web界面界面)
保存输出结果 [示例 3]让我们继续看最后一个例子。我们设置了一个函数来执行异步操作。具体来说,这个函数将大语言模型(LLM)的最后一个输出保存到文件中,以便日后进一步处理。我已经讨论过隔离容器和主机系统之间的数据交换(绑定挂载)。函数 “action” 将从“body”中的最后一个输出内容保存到文件中。该函数还包括一个发射器 _“__event_emitter_”,用来告诉用户输出已保存成功。如果有错误,也会显示出来。
import os
from pydantic import BaseModel, Field
from typing import Optional
class Action:
class Valves(BaseModel):
pass
class UserValves(BaseModel):
show_status: bool = Field(
default=True, description="显示操作状态."
)
pass
def __init__(self):
self.valves = self.Valves()
pass
async def action(
self,
body: dict,
__user__=None,
__event_emitter__=None,
__event_call__=None,
) -> Optional[dict]:
print(f"操作:{__name__}")
user_valves = __user__.get("valves")
if not user_valves:
user_valves = self.UserValves()
if __event_emitter__:
last_assistant_message = body["messages"][-1]
如果显示状态:
await __event_emitter__(
{
"type": "status",
"data": {"description": "正在保存至文件", "done": False},
}
)
try:
directory = "/app/data"
if not os.path.exists(directory):
os.makedirs(directory)
file_path = os.path.join(directory, "saved_outputs.txt")
with open(file_path, "a") as file:
file.write(f"{last_assistant_message['content']}\n\n")
print("输出已保存至容器中的文件,主机可访问.")
except Exception as e:
print(f"文件保存时出错: {str(e)}")
如果显示状态:
await __event_emitter__(
{
"type": "status",
"data": {
"description": "文件保存错误",
"done": True,
},
}
)
如果显示状态:
await __event_emitter__(
{
"type": "status",
"data": {"description": "输出已保存", "done": True},
}
)
LLM的输出保存在Docker容器的应用程序数据目录下的“saved_outputs.txt”文件中。
保存输出的文件 [自己的 Docker 桌面截屏]
在配置 Open WebUI 容器时自定义的命令会将 .txt 文件保存在本地计算机的。本地目录 _“C:\Users\scwom\Desktop\OPEN WEBUI FUNCTIONS\dockerdata” 与容器中的 “/app/data” 目录绑定,该目录中的文件会直接保存在计算机的 _“dockerdata” 目录下。
保存在 docker_data 文件夹里的文件 [截图]
该功能会在“工作区”区域创建,就像前面的例子一样。实现时,你可以选择使用Python脚本中的代码或者访问社区页面上的代码。因为最后这个例子是一个动作,所以会多出一个动作区域。在这个例子中,我选用了软盘图标来代表按钮。
关于新按钮的对话 [自定义截图 打开WebUI]
你可以自定义图标。只要符合格式即可。具体来说,图标被定义为 Base64 格式的 SVG 图形。“_iconurl”指定的长字符串会被用户界面解释为图形。例如,你可以在 Google 页面 找到类似的 SVG 图标。如果你不想用 Google 的 cookies,那你得找其他来源。
获取你想要的SVG图标 [Google Fonts 截图]
该图形可以转换成Base64格式,使用以下页面。将.svg文件拖放到相应的字段中之后,处理完毕后,点击_‘显示代码’_按钮,你就可以看到所需的字符串,例如:data:image/svg+xml;base64,...。
将您的图片转换为Base64,自己的截图 BASE64图像
然后你可以在概览中调整背景颜色(黑色或白色)。然后可以将字符串添加到代码中,从而相应地更改按钮图标。
复制一下生成的字符串 [自己的截图 BASE64 图像]
Python OIF 脚本 [下载]这些文件是以Python脚本.py的形式提供的。如果你想直接将这些函数上传到Open WebUI中,必须将它们转换为.json格式的JSON文件(更好地集成)。即使编辑器(如Visual Studio Code)显示了错误消息,转换仍然是必要的。现在点击文件夹下载包含这三个函数的zip文件。
点击文件夹加载Python脚本(自己的插图)
在这篇文章中,使用了三个示例来展示如何使用工具和功能扩展Open WebUI界面的功能。一方面,集成了处理输入时的状态消息、特定词汇的过滤功能以及输出的保存功能。这些例子旨在激发如何进一步优化界面,以提升LLM和用户之间的互动。自己动手自定义或创建功能。
你可以鼓掌最多五十下哦!
[1] OpenWebUI. (n.d.). 功能介绍. OpenWebUI 文档. 于 2025年8月24日 访问 https://docs.openwebui.com/tutorial/functions/。
仅供缩略图用 [本人绘制]
共同学习,写下你的评论
评论加载中...
作者其他优质文章