消息管理(中文译文)
原始 DeepWiki 页面:https://deepwiki.com/open-webui/open-webui/10.2-message-management
翻译时间:2026-06-09T16:10:21.567Z
翻译模型:deepseek-chat
原文字符数:14561
项目:Open WebUI (open-webui)
---
消息管理
相关源文件
以下文件为本 wiki 页面的生成上下文:
backend/open_webui/models/channels.pybackend/open_webui/models/messages.pybackend/open_webui/routers/channels.pysrc/lib/apis/channels/index.tssrc/lib/components/channel/Channel.sveltesrc/lib/components/channel/MessageInput.sveltesrc/lib/components/channel/MessageInput/InputMenu.sveltesrc/lib/components/channel/Messages.sveltesrc/lib/components/channel/Messages/Message.sveltesrc/lib/components/channel/Thread.svelte
本文档介绍 Open WebUI 频道功能中的消息管理系统,涵盖数据模型、CRUD 操作、反应、线程、置顶以及频道消息的文件附件处理。
关于频道基础设施和访问控制,请参阅频道架构。关于实时消息投递和输入状态指示,请参阅实时频道事件。
消息数据模型
消息系统采用支持对话、线程和回复的分层数据结构。
graph TB
subgraph "数据库层 (SQLAlchemy)"
Message["Message<br/>(backend/open_webui/models/messages.py)"]
MessageReaction["MessageReaction<br/>(backend/open_webui/models/messages.py)"]
end
subgraph "Pydantic 模型"
MessageModel["MessageModel<br/>基础消息数据"]
MessageForm["MessageForm<br/>输入验证"]
MessageResponse["MessageResponse<br/>包含用户、反应、回复数"]
MessageReplyToResponse["MessageReplyToResponse<br/>包含回复目标消息"]
MessageWithReactionsResponse["MessageWithReactionsResponse<br/>精简版,含反应"]
end
subgraph "核心字段"
CoreFields["id: str (UUID)<br/>user_id: str<br/>channel_id: str<br/>content: str<br/>created_at: int (time_ns)<br/>updated_at: int (time_ns)"]
end
subgraph "线程字段"
ThreadFields["parent_id: Optional[str]<br/>reply_to_id: Optional[str]"]
end
subgraph "可选数据"
OptionalData["data: dict (文件等)<br/>meta: dict (model_id, webhook)<br/>is_pinned: bool<br/>pinned_at: int<br/>pinned_by: str"]
end
Message --> MessageModel
MessageReaction --> MessageModel
MessageModel --> CoreFields
MessageModel --> ThreadFields
MessageModel --> OptionalData
MessageModel --> MessageResponse
MessageModel --> MessageReplyToResponse
MessageModel --> MessageWithReactionsResponse
MessageForm --> MessageModel
来源:backend/open_webui/models/messages.py:24-30、backend/open_webui/models/messages.py:43-63、backend/open_webui/models/messages.py:66-87、backend/open_webui/models/messages.py:94-101、backend/open_webui/models/messages.py:103-107、backend/open_webui/models/messages.py:109-111、backend/open_webui/models/messages.py:126-128、backend/open_webui/models/messages.py:134-138
关键消息字段
| 字段 | 类型 | 描述 |
|---|---|---|
id | str | UUID 主键 backend/open_webui/models/messages.py:45 |
user_id | str | 消息作者(或 webhook/模型 ID)backend/open_webui/models/messages.py:47 |
channel_id | str | 包含该消息的频道 backend/open_webui/models/messages.py:48 |
content | str | 消息文本内容(Markdown)backend/open_webui/models/messages.py:58 |
parent_id | Optional[str] | 线程父消息 ID(用于线程回复)backend/open_webui/models/messages.py:51 |
reply_to_id | Optional[str] | 直接回复目标消息 ID(用于引用回复)backend/open_webui/models/messages.py:50 |
data | Optional[dict] | 结构化数据(文件、附件)backend/open_webui/models/messages.py:59 |
meta | Optional[dict] | 元数据(model_id、webhook 信息等)backend/open_webui/models/messages.py:60 |
is_pinned | bool | 消息是否在频道中置顶 backend/open_webui/models/messages.py:54 |
created_at | int | 创建时间戳(纳秒)backend/open_webui/models/messages.py:62 |
updated_at | int | 最后更新时间戳(纳秒)backend/open_webui/models/messages.py:63 |
来源: backend/open_webui/models/messages.py:43-63
线程模型
系统支持两种不同的消息组织概念:
graph LR
subgraph "直接回复"
M1["消息 A"] -->|reply_to_id| M2["消息 B<br/>(显示 A 的引用)"]
end
subgraph "线程回复"
T1["根消息"] -->|parent_id| T2["线程回复 1"]
T1 -->|parent_id| T3["线程回复 2"]
T2 -->|reply_to_id| T3
end
来源:backend/open_webui/models/messages.py:50-51、src/lib/components/channel/Messages/Message.svelte:51-60
reply_to_id:创建直接回复,显示目标消息的引用预览。在移动端向右滑动消息或点击回复图标触发。src/lib/components/channel/Messages/Message.svelte:123-129、backend/open_webui/models/messages.py:50parent_id:将消息分组到线程对话中。所有具有相同parent_id的消息会一起显示在侧面板线程视图中。src/lib/components/channel/Thread.svelte:68-77、backend/open_webui/models/messages.py:51
来源: backend/open_webui/models/messages.py:50-51、src/lib/components/channel/Messages/Message.svelte:123-129、src/lib/components/channel/Thread.svelte:68-77
消息创建
后端消息投递
消息创建流程包括验证、存储和实时广播:
sequenceDiagram
participant 客户端
participant 路由器 as "POST /channels/{id}/messages/post"
participant 消息 as "Messages.insert_new_message()"
participant 数据库 as "PostgreSQL/SQLite"
participant 套接字 as "Socket.IO"
客户端->>路由器: POST 消息,携带 temp_id
路由器->>路由器: 验证频道访问权限
路由器->>消息: insert_new_message(form_data, channel_id, user_id)
消息->>数据库: INSERT INTO message
数据库-->>消息: MessageModel
消息-->>路由器: MessageModel
路由器->>套接字: emit 'events:channel' (type='message')
路由器-->>客户端: MessageResponse
套接字-->>客户端: 实时更新(替换 temp_id)
来源:backend/open_webui/routers/channels.py:1188-1233、backend/open_webui/models/messages.py:141-176
insert_new_message() 方法自动处理 UUID 生成、纳秒级时间戳创建,并通过 Channels.join_channel() 验证频道成员身份。backend/open_webui/models/messages.py:141-176
前端消息输入
MessageInput.svelte 组件管理消息编写,提供丰富的功能:
graph TB
MessageInput["MessageInput.svelte<br/>(src/lib/components/channel/MessageInput.svelte)"]
subgraph "输入功能"
RichTextInput["RichTextInput.svelte<br/>TipTap 编辑器"]
FileUpload["文件上传<br/>拖放、压缩"]
Variables["变量替换<br/>{{USER_NAME}}, {{CLIPBOARD}}"]
VoiceRecording["VoiceRecording.svelte<br/>语音转文字"]
end
subgraph "建议"
MentionList["MentionList.svelte<br/>@用户、@模型、#频道"]
CommandList["CommandSuggestionList.svelte<br/>/命令"]
end
MessageInput --> RichTextInput
MessageInput --> FileUpload
MessageInput --> Variables
MessageInput --> VoiceRecording
RichTextInput --> MentionList
RichTextInput --> CommandList
来源:src/lib/components/channel/MessageInput.svelte:32-42、src/lib/components/channel/MessageInput.svelte:86-223、src/lib/components/channel/MessageInput.svelte:439-505
变量替换系统
输入系统支持动态占位符,在消息发送前解析。支持的变量包括 {{CLIPBOARD}}、{{USER_NAME}}、{{CURRENT_DATE}} 和 {{USER_LOCATION}}。src/lib/components/channel/MessageInput.svelte:106-223
文件附件流程
附加到消息的文件会立即上传,并通过 ID 引用。src/lib/components/channel/MessageInput.svelte:439-505
sequenceDiagram
participant 用户
participant 输入 as "MessageInput.svelte"
participant 上传 as "uploadFile()"
participant API as "POST /files/"
participant 提交 as "onSubmit()"
用户->>输入: 拖放/选择文件
输入->>上传: uploadFile(file)
上传->>API: uploadFile(token, file)
API-->>上传: {id, url, content_type}
上传->>输入: 添加到文件数组
用户->>输入: 点击发送
输入->>提交: {content, data: {files: [...]}}
提交->>API: POST /channels/{id}/messages/post
来源:src/lib/components/channel/MessageInput.svelte:439-505、src/lib/apis/files/index.ts(在 src/lib/components/channel/MessageInput.svelte:26 中引用)
临时消息 ID
前端使用临时 UUID 提供即时反馈。它通过 uuidv4() 生成 temp_id,将消息添加到本地状态,然后在后端和 Socket.IO 广播永久 ID 后替换它。src/lib/components/channel/Channel.svelte:190-216
消息检索
获取消息列表
后端提供多个端点用于检索消息:
| 端点 | 用途 | 分页 |
|---|---|---|
GET /channels/{id}/messages | 主频道消息(无 parent_id) | skip、limit(默认 50)backend/open_webui/routers/channels.py:793-862 |
GET /channels/{id}/messages/pinned | 仅置顶消息 | page(每页 20 条)backend/open_webui/routers/channels.py:871-939 |
GET /channels/{id}/messages/{id}/thread | 线程回复(含 parent_id) | skip、limit(默认 50)backend/open_webui/routers/channels.py:1244-1327 |
消息查询实现
Messages.get_messages_by_channel_id() 方法高效地获取消息及其用户信息。它包含处理通过 webhook 发送的消息的逻辑,通过查找 meta 字段中的 webhook 身份来实现。backend/open_webui/models/messages.py:301-358
消息数据懒加载
对于包含 data 的消息,前端可以使用 getMessageData 懒加载完整负载。这在 Message.svelte 的挂载时处理。src/lib/components/channel/Messages/Message.svelte:131-144
消息编辑与删除
编辑消息
用户可以编辑自己的消息。编辑流程会触发本地状态的乐观更新,然后调用 updateMessage。src/lib/components/channel/Messages.svelte:149-163、backend/open_webui/routers/channels.py:1330-1349
删除消息
只有消息作者和管理员可以删除消息。backend/open_webui/routers/channels.py:1330-1367 前端会立即从列表中乐观地移除该消息。src/lib/components/channel/Messages.svelte:139-148
反应系统
反应系统允许用户为消息添加表情符号反应。
反应数据模型
反应存储在 message_reaction 表中,包含 id、user_id、message_id、name 和 created_at。backend/open_webui/models/messages.py:24-30 它们被聚合为响应格式,显示表情符号名称、计数和反应用户。backend/open_webui/models/messages.py:494-534
添加和移除反应
前端乐观地切换反应,并调用 addReaction 或 removeReaction。src/lib/components/channel/Messages.svelte:190-250 后端随后发出套接字事件以同步所有客户端。backend/open_webui/routers/channels.py:1370-1467
线程系统
线程允许在频道内进行聚焦的子对话。
线程架构
线程通过 parent_id 分组。src/lib/components/channel/Thread.svelte:17-18 后端统计回复数,并在 MessageResponse 中提供最新回复的时间戳。backend/open_webui/models/messages.py:224-237
线程 UI 组件
Thread.svelte 组件在侧面板中显示线程消息,使用带有 thread={true} 属性的 Messages.svelte 组件。src/lib/components/channel/Thread.svelte:190-218
消息置顶
置顶功能允许突出显示重要消息。
置顶/取消置顶流程
置顶切换 is_pinned 状态,并记录 pinned_at 和 pinned_by。backend/open_webui/routers/channels.py:1470-1529 UI 为这些消息显示黄色高亮和置顶指示器。src/lib/components/channel/Messages/Message.svelte:181-192
获取置顶消息
置顶消息可以通过支持分页的专用端点检索。backend/open_webui/routers/channels.py:871-939
特殊消息类型
Webhook 消息
频道支持 webhook 集成。Webhook 信息存储在 message.meta 中,作者身份在检索时从 webhook 数据构建。backend/open_webui/models/messages.py:201-218
模型响应消息
当频道中提及 AI 模型时,后端会处理生成聊天补全,并通过 Socket.IO 广播结果消息。backend/open_webui/routers/channels.py:976-1138
消息更新事件
所有消息变更(创建、更新、删除、反应、置顶)都会发出 Socket.IO 事件,以便在所有频道成员之间实时同步。backend/open_webui/routers/channels.py:1188-1233、src/lib/components/channel/Channel.svelte:115-188
来源:
backend/open_webui/models/messages.py:24-63backend/open_webui/routers/channels.py:1188-1233src/lib/components/channel/MessageInput.svelte:106-223src/lib/components/channel/Channel.svelte:115-224src/lib/components/channel/Messages/Message.svelte:181-192src/lib/components/channel/Thread.svelte:190-218