跳到主要内容

🛠️ 开发

编写自定义工具包

工具包定义在一个单独的 Python 文件中,具有包含元数据的顶级文档字符串和一个 Tools 类。

示例顶级文档字符串

"""
标题: 字符串逆转
作者: 你的名字
作者链接: https://website.com
git链接: https://github.com/username/string-reverse.git
描述: 该工具计算字符串的逆序
所需的最低Open WebUI版本: 0.4.0
依赖: langchain-openai, langgraph, ollama, langchain_ollama
版本: 0.4.0
许可: MIT
"""

Tools 类

工具必须定义为一个名为 Tools 的类中的方法,可选地还可以有名为 ValvesUserValves 的子类,例如:

class Tools:
def __init__(self):
"""初始化工具。"""
self.valves = self.Valves()

class Valves(BaseModel):
api_key: str = Field("", description="你的API密钥")

def reverse_string(self, string: str) -> str:
"""
将输入字符串逆转。
:param string: 要逆转的字符串
"""
# 使用阀门示例
if self.valves.api_key != "42":
return "错误的API密钥"
return string[::-1]

类型提示

每个工具必须为参数提供类型提示。类型也可以是嵌套的,例如 queries_and_docs: list[tuple[str, int]]。这些类型提示用于生成发送到模型的 JSON Schema。没有类型提示的工具工作的一致性会大大降低。

阀门和用户阀门 - (可选,但强烈推荐)

阀门和用户阀门用于指定工具的可自定义设置,你可以在专门的阀门和用户阀门页面中了解更多。

可选参数

以下是您的工具可以依赖的可选参数列表:

  • __event_emitter__: 发出事件(请参阅以下部分)
  • __event_call__: 与事件发射器相同,但可用于用户交互
  • __user__: 包含用户信息的字典,还包含用户阀门对象 UserValves,位于 __user__["valves"]
  • __metadata__: 包含对话元数据的字典
  • __messages__: 之前消息的列表
  • __files__: 附件文件
  • __model__: 包含模型信息的字典

只需像上面的示例中对待 __user__ 一样,将它们添加到工具类中任何方法的参数中即可。

事件发射器

事件发射器用于向聊天界面添加额外的信息。与过滤出口类似,事件发射器可以将内容附加到聊天中。与过滤出口不同,它们无法删除信息。此外,发射器可以在工具期间的任何阶段激活。

有两种不同类型的事件发射器:

如果模型似乎无法调用工具,请确保它已启用(可以通过模型页面或聊天输入框旁的 + 图标打开)。您还可以将模型页面 高级参数 部分的 功能调用 参数从 默认 更改为 原生

状态

这用于在执行步骤时向消息添加状态。它们可以在工具的任何阶段完成。这些状态显示在消息内容的正上方。对于延迟LLM响应或处理大量信息的工具来说非常有用。这允许您实时通知用户正在处理的内容。

await __event_emitter__(
{
"type": "status", # 在此设置类型
"data": {"description": "显示在聊天中的消息", "done": False, "hidden": False},
# 注意这里的done为False,表示我们仍然在发出状态
}
)
示例
async def test_function(
self, prompt: str, __user__: dict, __event_emitter__=None
) -> str:
"""
这是一个演示

:param test: 这是一个测试参数
"""

await __event_emitter__(
{
"type": "status", # 在此设置类型
"data": {"description": "显示在聊天中的消息", "done": False},
# 注意这里的done为False,表示我们仍然在发出状态
}
)

# 此处执行其他逻辑
await __event_emitter__(
{
"type": "status",
"data": {"description": "完成任务消息", "done": True, "hidden": False},
# 注意这里done为True,表示我们已完成发出状态
# 如果希望在消息返回后移除状态,可以设置为 "hidden": True
}
)

except Exception as e:
await __event_emitter__(
{
"type": "status",
"data": {"description": f"发生错误: {e}", "done": True},
}
)

return f"告诉用户: {e}"

消息

该类型用于在工具中的任意阶段向LLM追加消息。这意味着您可以在LLM响应之前、之后或期间追加消息、嵌入图片,甚至渲染网页。

await __event_emitter__(
{
"type": "message", # 我们在这里设置类型
"data": {"content": "此消息将被追加到聊天中。"},
# 注意,对于消息类型我们不需要设置完成条件
}
)
示例
async def test_function(
self, prompt: str, __user__: dict, __event_emitter__=None
) -> str:
"""
这是一个演示

:param test: 这是一个测试参数
"""

await __event_emitter__(
{
"type": "message", # 我们在这里设置类型
"data": {"content": "此消息将被追加到聊天中。"},
# 注意,对于消息类型我们不需要设置完成条件
}
)

except Exception as e:
await __event_emitter__(
{
"type": "status",
"data": {"description": f"发生了一个错误: {e}", "done": True},
}
)

return f"告诉用户: {e}"

引用

该类型用于在聊天中提供引用或参考文献。您可以利用它来指定内容、来源和任何相关的元数据。以下是发出引用事件的示例:

await __event_emitter__(
{
"type": "citation",
"data": {
"document": [content],
"metadata": [
{
"date_accessed": datetime.now().isoformat(),
"source": title,
}
],
"source": {"name": title, "url": url},
},
}
)

如果您要发送多个引用,可以迭代引用并多次调用发射器。当实现自定义引用时,请确保在Tools类的__init__方法中设置self.citation = False。否则,内置的引用会覆盖您推送的引用内容。例如:

def __init__(self):
self.citation = False

警告:如果您设置self.citation = True,这将用自动生成的返回引用替换您发送的任何自定义引用。通过禁用它,您可以完全管理自己的引用。

示例
class Tools:
class UserValves(BaseModel):
test: bool = Field(
default=True, description="测试"
)

def __init__(self):
self.citation = False

async def test_function(
self, prompt: str, __user__: dict, __event_emitter__=None
) -> str:
"""
这是一个只创建引用的演示

:param test: 这是一个测试参数
"""

await __event_emitter__(
{
"type": "citation",
"data": {
"document": ["此消息将作为引用追加到聊天中,当点击时显示具体内容"],
"metadata": [
{
"date_accessed": datetime.now().isoformat(),
"source": title,
}
],
"source": {"name": "内容标题", "url": "http://引用链接"},
},
}
)

外部包

在工具定义的元数据中,您可以指定自定义包。当您点击“保存”时,这些内容将被解析,并且pip install将一次性安装所有依赖。

请记住,由于pip与Open WebUI在同一进程中运行,因此安装期间UI会完全无响应。

未采取任何措施来处理与Open WebUI依赖项冲突的包。这意味着,如果您不小心,指定的依赖可能会破坏Open WebUI。您可以尝试通过将open-webui本身指定为依赖来解决此问题。

示例
"""
标题: myToolName
作者: myName
捐赠链接: [任何链接都会显示在一个“心形”按钮后,供用户支持您]
版本: 1.0.0
# 版本信息会显示在UI中,帮助用户追踪更新。
许可证: GPLv3
描述: [推荐]
依赖: package1>=2.7.0,package2,package3
"""