docs: add full zh translations for site
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
This commit is contained in:
328
docs/development/documentation-guide.zh.md
Normal file
328
docs/development/documentation-guide.zh.md
Normal file
@@ -0,0 +1,328 @@
|
||||
# 文档编写指南
|
||||
|
||||
本文介绍如何为 OpenWebUI Extras 编写与贡献文档。
|
||||
|
||||
---
|
||||
|
||||
## 概览
|
||||
|
||||
文档基于 [MkDocs](https://www.mkdocs.org/) 与 [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) 主题构建。了解 Markdown 与 MkDocs 的基础有助于高效贡献。
|
||||
|
||||
---
|
||||
|
||||
## 开始之前
|
||||
|
||||
### 前置条件
|
||||
|
||||
1. Python 3.8 及以上
|
||||
2. Git
|
||||
|
||||
### 本地环境搭建
|
||||
|
||||
```bash
|
||||
# 克隆仓库
|
||||
git clone https://github.com/Fu-Jie/awesome-openwebui.git
|
||||
cd awesome-openwebui
|
||||
|
||||
# 安装依赖
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 启动开发服务器
|
||||
mkdocs serve
|
||||
```
|
||||
|
||||
访问 `http://localhost:8000` 预览文档。
|
||||
|
||||
---
|
||||
|
||||
## 文档结构
|
||||
|
||||
```
|
||||
docs/
|
||||
├── index.md # 首页
|
||||
├── contributing.md # 贡献指南
|
||||
├── plugins/ # 插件文档
|
||||
│ ├── index.md # 插件中心概览
|
||||
│ ├── actions/ # Action 插件
|
||||
│ ├── filters/ # Filter 插件
|
||||
│ ├── pipes/ # Pipe 插件
|
||||
│ └── pipelines/ # Pipeline 插件
|
||||
├── prompts/ # 提示词库
|
||||
├── enhancements/ # 增强指南
|
||||
├── development/ # 开发指南
|
||||
└── stylesheets/ # 自定义 CSS
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 编写插件文档
|
||||
|
||||
### 模板
|
||||
|
||||
新建插件文档可参考以下模板:
|
||||
|
||||
```markdown
|
||||
# Plugin Name
|
||||
|
||||
<span class="category-badge action">Action</span>
|
||||
<span class="version-badge">v1.0.0</span>
|
||||
|
||||
Brief description of what the plugin does.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Detailed explanation of the plugin's purpose and functionality.
|
||||
|
||||
## Features
|
||||
|
||||
- :material-icon-name: **Feature 1**: Description
|
||||
- :material-icon-name: **Feature 2**: Description
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
1. Download the plugin file
|
||||
2. Upload to OpenWebUI
|
||||
3. Configure settings
|
||||
4. Enable the plugin
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
Step-by-step usage instructions.
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `option_name` | type | `default` | Description |
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
!!! note "Prerequisites"
|
||||
- OpenWebUI v0.3.0 or later
|
||||
- Any additional requirements
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
??? question "Common issue?"
|
||||
Solution to the issue.
|
||||
|
||||
---
|
||||
|
||||
## Source Code
|
||||
|
||||
[:fontawesome-brands-github: View on GitHub](https://github.com/Fu-Jie/awesome-openwebui/tree/main/plugins/...){ .md-button }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Markdown 扩展
|
||||
|
||||
### 提示块(Admonitions)
|
||||
|
||||
用来突出重要信息:
|
||||
|
||||
```markdown
|
||||
!!! note "Title"
|
||||
This is a note.
|
||||
|
||||
!!! warning "Caution"
|
||||
This is a warning.
|
||||
|
||||
!!! tip "Pro Tip"
|
||||
This is a helpful tip.
|
||||
|
||||
!!! danger "Warning"
|
||||
This is a critical warning.
|
||||
```
|
||||
|
||||
### 可折叠区域
|
||||
|
||||
```markdown
|
||||
??? question "Frequently asked question?"
|
||||
This is the answer.
|
||||
|
||||
???+ note "Open by default"
|
||||
This section is expanded by default.
|
||||
```
|
||||
|
||||
### 代码块
|
||||
|
||||
````markdown
|
||||
```python title="example.py" linenums="1"
|
||||
def hello():
|
||||
print("Hello, World!")
|
||||
```
|
||||
````
|
||||
|
||||
### Tabs
|
||||
|
||||
```markdown
|
||||
=== "Python"
|
||||
|
||||
```python
|
||||
print("Hello")
|
||||
```
|
||||
|
||||
=== "JavaScript"
|
||||
|
||||
```javascript
|
||||
console.log("Hello");
|
||||
```
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 图标
|
||||
|
||||
使用 `:material-icon-name:` 语法调用 Material Design Icons:
|
||||
|
||||
- `:material-brain:` :material-brain:
|
||||
- `:material-puzzle:` :material-puzzle:
|
||||
- `:material-download:` :material-download:
|
||||
- `:material-github:` :material-github:
|
||||
|
||||
更多图标见 [Material Design Icons](https://pictogrammers.com/library/mdi/)。
|
||||
|
||||
### 图标尺寸
|
||||
|
||||
```markdown
|
||||
:material-brain:{ .lg .middle } Large icon
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 分类徽章
|
||||
|
||||
为不同插件类型添加徽章:
|
||||
|
||||
```markdown
|
||||
<span class="category-badge action">Action</span>
|
||||
<span class="category-badge filter">Filter</span>
|
||||
<span class="category-badge pipe">Pipe</span>
|
||||
<span class="category-badge pipeline">Pipeline</span>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 表格
|
||||
|
||||
```markdown
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
|----------|----------|----------|
|
||||
| Value 1 | Value 2 | Value 3 |
|
||||
```
|
||||
|
||||
更好的对齐方式:
|
||||
|
||||
```markdown
|
||||
| Left | Center | Right |
|
||||
|:-----|:------:|------:|
|
||||
| L | C | R |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 网格卡片
|
||||
|
||||
创建卡片式导航:
|
||||
|
||||
```markdown
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- :material-icon:{ .lg .middle } **Card Title**
|
||||
|
||||
---
|
||||
|
||||
Card description goes here.
|
||||
|
||||
[:octicons-arrow-right-24: Link Text](link.md)
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 链接
|
||||
|
||||
### 内部链接
|
||||
|
||||
```markdown
|
||||
[Link Text](../path/to/page.md)
|
||||
```
|
||||
|
||||
### 外部链接
|
||||
|
||||
```markdown
|
||||
[Link Text](https://example.com){ target="_blank" }
|
||||
```
|
||||
|
||||
### 按钮样式链接
|
||||
|
||||
```markdown
|
||||
[Button Text](link.md){ .md-button }
|
||||
[Primary Button](link.md){ .md-button .md-button--primary }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 图片
|
||||
|
||||
```markdown
|
||||

|
||||
|
||||
<!-- With attributes -->
|
||||
{ width="300" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 写作风格
|
||||
|
||||
1. **简洁**:快速切入主题
|
||||
2. **示例驱动**:展示而不只是说明
|
||||
3. **一致性**:遵循现有模式
|
||||
4. **面向新手**:假设读者基础有限
|
||||
|
||||
### 格式
|
||||
|
||||
1. 使用正确的标题层级(H1 → H2 → H3)
|
||||
2. 主要段落间添加水平分割线(`---`)
|
||||
3. 使用列表呈现步骤与特性
|
||||
4. 需要时提供代码示例
|
||||
|
||||
### SEO
|
||||
|
||||
1. 使用描述性页面标题
|
||||
2. 自然融入相关关键词
|
||||
3. 需要时在前置区添加 meta 描述
|
||||
|
||||
---
|
||||
|
||||
## 提交修改
|
||||
|
||||
1. 创建功能分支
|
||||
2. 完成文档修改
|
||||
3. 通过 `mkdocs serve` 本地验证
|
||||
4. 提交 Pull Request
|
||||
|
||||
---
|
||||
|
||||
## 其他资源
|
||||
|
||||
- [MkDocs Documentation](https://www.mkdocs.org/)
|
||||
- [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/)
|
||||
- [Markdown Guide](https://www.markdownguide.org/)
|
||||
168
docs/development/index.zh.md
Normal file
168
docs/development/index.zh.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# 开发指南
|
||||
|
||||
了解如何开发插件并为 OpenWebUI Extras 做出贡献。
|
||||
|
||||
---
|
||||
|
||||
## 快速开始
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- :material-book-open-page-variant:{ .lg .middle } **插件开发指南**
|
||||
|
||||
---
|
||||
|
||||
从入门到高级模式、最佳实践的完整指南。
|
||||
|
||||
[:octicons-arrow-right-24: 阅读指南](plugin-guide.md)
|
||||
|
||||
- :material-file-document-edit:{ .lg .middle } **文档编写指南**
|
||||
|
||||
---
|
||||
|
||||
学习如何使用 MkDocs 与 Material 主题编写和贡献文档。
|
||||
|
||||
[:octicons-arrow-right-24: 阅读指南](documentation-guide.md)
|
||||
|
||||
- :material-github:{ .lg .middle } **贡献指南**
|
||||
|
||||
---
|
||||
|
||||
了解如何贡献插件、提示词与文档。
|
||||
|
||||
[:octicons-arrow-right-24: 贡献说明](../contributing.md)
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## 插件类型概览
|
||||
|
||||
OpenWebUI 支持三种主要插件类型:
|
||||
|
||||
| 类型 | 目的 | 入口方法 |
|
||||
|------|---------|--------------|
|
||||
| **Action** | 为消息添加按钮 | `action()` |
|
||||
| **Filter** | 处理消息 | `inlet()` / `outlet()` |
|
||||
| **Pipe** | 自定义模型集成 | `pipe()` |
|
||||
|
||||
---
|
||||
|
||||
## 快速开始模板
|
||||
|
||||
### Action 插件
|
||||
|
||||
```python
|
||||
"""
|
||||
title: My Action
|
||||
author: Your Name
|
||||
version: 1.0.0
|
||||
"""
|
||||
|
||||
class Action:
|
||||
async def action(self, body: dict, __event_emitter__=None):
|
||||
await __event_emitter__({"type": "notification", "data": {"content": "Hello!"}})
|
||||
return body
|
||||
```
|
||||
|
||||
### Filter 插件
|
||||
|
||||
```python
|
||||
"""
|
||||
title: My Filter
|
||||
author: Your Name
|
||||
version: 1.0.0
|
||||
"""
|
||||
|
||||
class Filter:
|
||||
async def inlet(self, body: dict, __metadata__: dict) -> dict:
|
||||
# 发送到 LLM 之前处理
|
||||
return body
|
||||
|
||||
async def outlet(self, body: dict, __metadata__: dict) -> dict:
|
||||
# LLM 返回后处理
|
||||
return body
|
||||
```
|
||||
|
||||
### Pipe 插件
|
||||
|
||||
```python
|
||||
"""
|
||||
title: My Pipe
|
||||
author: Your Name
|
||||
version: 1.0.0
|
||||
"""
|
||||
|
||||
class Pipe:
|
||||
def pipes(self):
|
||||
return [{"id": "my-model", "name": "My Model"}]
|
||||
|
||||
def pipe(self, body: dict):
|
||||
return "Response from custom pipe"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 核心概念
|
||||
|
||||
### Valves 配置
|
||||
|
||||
Valves 允许用户在界面中配置插件:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
class Action:
|
||||
class Valves(BaseModel):
|
||||
api_key: str = Field(default="", description="API Key")
|
||||
enabled: bool = Field(default=True, description="Enable plugin")
|
||||
|
||||
def __init__(self):
|
||||
self.valves = self.Valves()
|
||||
```
|
||||
|
||||
### 事件发送器
|
||||
|
||||
发送通知与状态更新:
|
||||
|
||||
```python
|
||||
# Notification
|
||||
await __event_emitter__({
|
||||
"type": "notification",
|
||||
"data": {"type": "success", "content": "Done!"}
|
||||
})
|
||||
|
||||
# Status update
|
||||
await __event_emitter__({
|
||||
"type": "status",
|
||||
"data": {"description": "Processing...", "done": False}
|
||||
})
|
||||
```
|
||||
|
||||
### 用户上下文
|
||||
|
||||
获取用户信息:
|
||||
|
||||
```python
|
||||
user_name = __user__.get("name", "User")
|
||||
user_id = __user__.get("id")
|
||||
user_language = __user__.get("language", "en-US")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **异步操作**:I/O 请使用 `async/await`
|
||||
2. **错误处理**:捕获异常并通知用户
|
||||
3. **状态反馈**:长耗时操作提供进度提示
|
||||
4. **配置化**:使用 Valves 暴露可调参数
|
||||
5. **文档**:提供清晰的 docstring 与 README
|
||||
|
||||
---
|
||||
|
||||
## 资源
|
||||
|
||||
- [完整开发指南](plugin-guide.md)
|
||||
- [插件示例](https://github.com/Fu-Jie/awesome-openwebui/tree/main/plugins)
|
||||
- [OpenWebUI 文档](https://docs.openwebui.com/)
|
||||
234
docs/development/plugin-guide.zh.md
Normal file
234
docs/development/plugin-guide.zh.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# OpenWebUI 插件开发权威指南
|
||||
|
||||
> 本指南整合了官方文档、SDK 详解及最佳实践,旨在为开发者提供一份从入门到精通的系统化教程。
|
||||
|
||||
## 📚 目录
|
||||
|
||||
1. [插件开发快速入门](#1-插件开发快速入门)
|
||||
2. [核心概念与 SDK 详解](#2-核心概念与-sdk-详解)
|
||||
3. [插件类型深度解析](#3-插件类型深度解析)
|
||||
* [Action (动作)](#31-action-动作)
|
||||
* [Filter (过滤器)](#32-filter-过滤器)
|
||||
* [Pipe (管道)](#33-pipe-管道)
|
||||
4. [高级开发模式](#4-高级开发模式)
|
||||
5. [最佳实践与设计原则](#5-最佳实践与设计原则)
|
||||
6. [故障排查](#6-故障排查)
|
||||
|
||||
---
|
||||
|
||||
## 1. 插件开发快速入门
|
||||
|
||||
### 1.1 什么是 OpenWebUI 插件?
|
||||
|
||||
OpenWebUI 插件(官方称为 "Functions")是扩展平台功能的主要方式。它们运行在后端 Python 环境中,允许你:
|
||||
* 🔌 **集成新模型**:通过 Pipe 接入 Claude、Gemini 或自定义 RAG。
|
||||
* 🎨 **增强交互**:通过 Action 在消息旁添加按钮(如"导出"、"生成图表")。
|
||||
* 🔧 **干预流程**:通过 Filter 在请求前后修改数据(如注入上下文、敏感词过滤)。
|
||||
|
||||
### 1.2 你的第一个插件 (Hello World)
|
||||
|
||||
保存以下代码为 `hello.py` 并上传到 OpenWebUI 的 **Functions** 面板:
|
||||
|
||||
```python
|
||||
"""
|
||||
title: Hello World Action
|
||||
author: Demo
|
||||
version: 1.0.0
|
||||
"""
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional
|
||||
|
||||
class Action:
|
||||
class Valves(BaseModel):
|
||||
greeting: str = Field(default="你好", description="问候语")
|
||||
|
||||
def __init__(self):
|
||||
self.valves = self.Valves()
|
||||
|
||||
async def action(
|
||||
self,
|
||||
body: dict,
|
||||
__event_emitter__=None,
|
||||
__user__=None
|
||||
) -> Optional[dict]:
|
||||
user_name = __user__.get("name", "朋友") if __user__ else "朋友"
|
||||
|
||||
if __event_emitter__:
|
||||
await __event_emitter__({
|
||||
"type": "notification",
|
||||
"data": {"type": "success", "content": f"{self.valves.greeting}, {user_name}!"}
|
||||
})
|
||||
return body
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心概念与 SDK 详解
|
||||
|
||||
### 2.1 ⚠️ 重要:同步与异步
|
||||
|
||||
OpenWebUI 插件运行在 `asyncio` 事件循环中。
|
||||
* **原则**:所有 I/O 操作(数据库、文件、网络)必须非阻塞。
|
||||
* **陷阱**:直接调用同步方法(如 `time.sleep`, `requests.get`)会卡死整个服务器。
|
||||
* **解决**:使用 `await asyncio.to_thread(sync_func, ...)` 包装同步调用。
|
||||
|
||||
### 2.2 核心参数详解
|
||||
|
||||
所有插件方法(`inlet`, `outlet`, `pipe`, `action`)都支持注入以下特殊参数:
|
||||
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| :--- | :--- | :--- |
|
||||
| `body` | `dict` | **核心数据**。包含 `messages`, `model`, `stream` 等请求信息。 |
|
||||
| `__user__` | `dict` | **当前用户**。包含 `id`, `name`, `role`, `valves` (用户配置) 等。 |
|
||||
| `__metadata__` | `dict` | **元数据**。包含 `chat_id`, `message_id`。其中 `variables` 字段包含 `{{USER_NAME}}`, `{{CURRENT_TIME}}` 等预置变量。 |
|
||||
| `__request__` | `Request` | **FastAPI 请求对象**。可访问 `app.state` 进行跨插件通信。 |
|
||||
| `__event_emitter__` | `func` | **单向通知**。用于发送 Toast 通知或状态条更新。 |
|
||||
| `__event_call__` | `func` | **双向交互**。用于在前端执行 JS 代码、弹出确认框或输入框。 |
|
||||
|
||||
### 2.3 配置系统 (Valves)
|
||||
|
||||
* **`Valves`**: 管理员全局配置。
|
||||
* **`UserValves`**: 用户级配置(优先级更高,可覆盖全局)。
|
||||
|
||||
```python
|
||||
class Filter:
|
||||
class Valves(BaseModel):
|
||||
API_KEY: str = Field(default="", description="全局 API Key")
|
||||
|
||||
class UserValves(BaseModel):
|
||||
API_KEY: str = Field(default="", description="用户私有 API Key")
|
||||
|
||||
def inlet(self, body, __user__):
|
||||
# 优先使用用户的 Key
|
||||
user_valves = __user__.get("valves", self.UserValves())
|
||||
api_key = user_valves.API_KEY or self.valves.API_KEY
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 插件类型深度解析
|
||||
|
||||
### 3.1 Action (动作)
|
||||
|
||||
**定位**:在消息下方添加按钮,用户点击触发。
|
||||
|
||||
**高级用法:前端执行 JavaScript (文件下载示例)**
|
||||
|
||||
```python
|
||||
import base64
|
||||
|
||||
async def action(self, body, __event_call__):
|
||||
# 1. 后端生成内容
|
||||
content = "Hello OpenWebUI".encode()
|
||||
b64 = base64.b64encode(content).decode()
|
||||
|
||||
# 2. 发送 JS 到前端执行
|
||||
js = f"""
|
||||
const blob = new Blob([atob('{b64}')], {{type: 'text/plain'}});
|
||||
const a = document.createElement('a');
|
||||
a.href = URL.createObjectURL(blob);
|
||||
a.download = 'hello.txt';
|
||||
a.click();
|
||||
"""
|
||||
await __event_call__({"type": "execute", "data": {"code": js}})
|
||||
```
|
||||
|
||||
### 3.2 Filter (过滤器)
|
||||
|
||||
**定位**:中间件,拦截并修改请求/响应。
|
||||
|
||||
* **`inlet`**: 请求前。用于注入上下文、修改模型参数。
|
||||
* **`outlet`**: 响应后。用于格式化输出、保存日志。
|
||||
* **`stream`**: 流式处理中。用于实时敏感词过滤。
|
||||
|
||||
**示例:注入环境变量**
|
||||
|
||||
```python
|
||||
async def inlet(self, body, __metadata__):
|
||||
vars = __metadata__.get("variables", {})
|
||||
context = f"当前时间: {vars.get('{{CURRENT_DATETIME}}')}"
|
||||
|
||||
# 注入到 System Prompt 或第一条消息
|
||||
if body.get("messages"):
|
||||
body["messages"][0]["content"] += f"\n\n{context}"
|
||||
return body
|
||||
```
|
||||
|
||||
### 3.3 Pipe (管道)
|
||||
|
||||
**定位**:自定义模型/代理。
|
||||
|
||||
**示例:简单的 OpenAI 代理**
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
class Pipe:
|
||||
def pipes(self):
|
||||
return [{"id": "my-gpt", "name": "My GPT Wrapper"}]
|
||||
|
||||
def pipe(self, body):
|
||||
# 可以在这里修改 body,例如强制添加 prompt
|
||||
headers = {"Authorization": f"Bearer {self.valves.API_KEY}"}
|
||||
r = requests.post("https://api.openai.com/v1/chat/completions", json=body, headers=headers, stream=True)
|
||||
return r.iter_lines()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 高级开发模式
|
||||
|
||||
### 4.1 Pipe 与 Filter 协同
|
||||
利用 `__request__.app.state` 在不同插件间共享数据。
|
||||
* **Pipe**: `__request__.app.state.search_results = [...]`
|
||||
* **Filter (Outlet)**: 读取 `search_results` 并将其格式化为引用链接附加到回复末尾。
|
||||
|
||||
### 4.2 异步后台任务
|
||||
不阻塞用户响应,在后台执行耗时操作(如生成总结、存库)。
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
|
||||
async def outlet(self, body, __metadata__):
|
||||
asyncio.create_task(self.background_job(__metadata__["chat_id"]))
|
||||
return body
|
||||
|
||||
async def background_job(self, chat_id):
|
||||
# 执行耗时操作...
|
||||
pass
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 最佳实践与设计原则
|
||||
|
||||
### 5.1 命名与定位
|
||||
* **简短有力**:如 "闪记卡", "精读"。避免 "文本分析助手" 这种泛词。
|
||||
* **功能互补**:不要重复造轮子,明确你的插件解决了什么特定问题。
|
||||
|
||||
### 5.2 用户体验 (UX)
|
||||
* **反馈及时**:耗时操作前先发送 `notification` ("正在生成...")。
|
||||
* **视觉美观**:Action 输出 HTML 时,使用现代化的 CSS(圆角、阴影、渐变)。
|
||||
* **智能引导**:检测到文本过短时,提示用户"建议输入更多内容以获得更好结果"。
|
||||
|
||||
### 5.3 错误处理
|
||||
永远不要让插件静默失败。捕获异常并通过 `__event_emitter__` 告知用户。
|
||||
|
||||
```python
|
||||
try:
|
||||
# 业务逻辑
|
||||
except Exception as e:
|
||||
await __event_emitter__({
|
||||
"type": "notification",
|
||||
"data": {"type": "error", "content": f"处理失败: {str(e)}"}
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 故障排查
|
||||
|
||||
* **HTML 不显示?** 确保包裹在 ` ```html ... ``` ` 代码块中。
|
||||
* **数据库报错?** 检查是否在 `async` 函数中直接调用了同步的 DB 方法,请使用 `asyncio.to_thread`。
|
||||
* **参数未生效?** 检查 `Valves` 定义是否正确,以及是否被 `UserValves` 覆盖。
|
||||
Reference in New Issue
Block a user