Compare commits

...

17 Commits

Author SHA1 Message Date
Jeff
06e8d30900 Merge pull request #20 from Fu-Jie/copilot/fix-session-alias-errors
Harden async context compression against new DB session alias and runtime edge cases
2026-01-11 17:26:03 +08:00
fujie
cbf2ff7f93 chore: release async-context-compression v1.1.2
- Enhanced error reporting via status bar and console
- Robust model ID handling
- Open WebUI v0.7.x compatibility (dynamic DB session)
- Updated documentation and version bumps
2026-01-11 17:25:07 +08:00
copilot-swe-agent[bot]
abbe3fb248 chore: centralize chat_id extraction helper
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:36:13 +00:00
copilot-swe-agent[bot]
7e44dde979 chore: add discovery docstrings
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:31:10 +00:00
copilot-swe-agent[bot]
3649d75539 chore: add discovery debug logs
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:30:02 +00:00
copilot-swe-agent[bot]
d3b4219a9a chore: refine db session discovery messaging
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:28:52 +00:00
copilot-swe-agent[bot]
9e98d55e11 fix: make async compression db session discovery robust
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:27:36 +00:00
copilot-swe-agent[bot]
4b8515f682 fix: ensure empty summary model skips compression
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:25:33 +00:00
copilot-swe-agent[bot]
d2f35ce396 fix: harden async compression compatibility
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:24:56 +00:00
copilot-swe-agent[bot]
f479f23b38 Initial plan 2026-01-11 08:19:33 +00:00
github-actions[bot]
51048f9e5d chore: update community stats 2026-01-10 2026-01-10 18:11:03 +00:00
github-actions[bot]
1118ae34c4 chore: update community stats 2026-01-10 2026-01-10 14:07:43 +00:00
github-actions[bot]
7a5e1a4e12 chore: update community stats 2026-01-10 2026-01-10 12:12:24 +00:00
fujie
8e377e1794 Update Copilot instructions: Limit What's New section to latest 3 updates 2026-01-10 19:09:09 +08:00
fujie
d66360b02d Update READMEs with v1.1.1 release notes 2026-01-10 19:07:49 +08:00
fujie
1ece648006 Update Async Context Compression docs to v1.1.1 and improve plugin update logic to detect README changes 2026-01-10 19:07:49 +08:00
github-actions[bot]
a262a716a3 chore: update community stats 2026-01-10 2026-01-10 11:06:57 +00:00
14 changed files with 477 additions and 133 deletions

View File

@@ -40,7 +40,7 @@ plugins/actions/export_to_docx/
- 格式: `**Author:** [Fu-Jie](https://github.com/Fu-Jie) | **Version:** x.x.x | **Project:** [Awesome OpenWebUI](https://github.com/Fu-Jie/awesome-openwebui)` - 格式: `**Author:** [Fu-Jie](https://github.com/Fu-Jie) | **Version:** x.x.x | **Project:** [Awesome OpenWebUI](https://github.com/Fu-Jie/awesome-openwebui)`
- **注意**: Author 和 Project 为固定值,仅需更新 Version 版本号 - **注意**: Author 和 Project 为固定值,仅需更新 Version 版本号
3. **描述 (Description)**: 一句话功能介绍 3. **描述 (Description)**: 一句话功能介绍
4. **最新更新 (What's New)**: **必须**放在描述之后,显著展示最新版本的变更点 4. **最新更新 (What's New)**: **必须**放在描述之后,显著展示最新版本的变更点 (仅展示最近 3 次更新)
5. **核心特性 (Key Features)**: 使用 Emoji + 粗体标题 + 描述格式 5. **核心特性 (Key Features)**: 使用 Emoji + 粗体标题 + 描述格式
6. **使用方法 (How to Use)**: 按步骤说明 6. **使用方法 (How to Use)**: 按步骤说明
7. **配置参数 (Configuration/Valves)**: 使用表格格式,包含参数名、默认值、描述 7. **配置参数 (Configuration/Valves)**: 使用表格格式,包含参数名、默认值、描述
@@ -96,7 +96,7 @@ example code or syntax here
### 文档内容要求 (Content Requirements) ### 文档内容要求 (Content Requirements)
- **新增功能**: 必须在 "What's New" 章节中明确列出,使用 Emoji + 粗体标题格式。 - **新增功能**: 必须在 "What's New" 章节中明确列出,使用 Emoji + 粗体标题格式 (仅保留最近 3 个版本的更新记录)
- **双语**: 必须提供 `README.md` (英文) 和 `README_CN.md` (中文)。 - **双语**: 必须提供 `README.md` (英文) 和 `README_CN.md` (中文)。
- **表格对齐**: 配置参数表格使用左对齐 `:---` - **表格对齐**: 配置参数表格使用左对齐 `:---`
- **Emoji 规范**: 标题使用合适的 Emoji 增强可读性。 - **Emoji 规范**: 标题使用合适的 Emoji 增强可读性。

View File

@@ -7,26 +7,26 @@ A collection of enhancements, plugins, and prompts for [OpenWebUI](https://githu
<!-- STATS_START --> <!-- STATS_START -->
## 📊 Community Stats ## 📊 Community Stats
> 🕐 Auto-updated: 2026-01-10 17:08 > 🕐 Auto-updated: 2026-01-11 02:11
| 👤 Author | 👥 Followers | ⭐ Points | 🏆 Contributions | | 👤 Author | 👥 Followers | ⭐ Points | 🏆 Contributions |
|:---:|:---:|:---:|:---:| |:---:|:---:|:---:|:---:|
| [Fu-Jie](https://openwebui.com/u/Fu-Jie) | **71** | **72** | **21** | | [Fu-Jie](https://openwebui.com/u/Fu-Jie) | **75** | **77** | **22** |
| 📝 Posts | ⬇️ Downloads | 👁️ Views | 👍 Upvotes | 💾 Saves | | 📝 Posts | ⬇️ Downloads | 👁️ Views | 👍 Upvotes | 💾 Saves |
|:---:|:---:|:---:|:---:|:---:| |:---:|:---:|:---:|:---:|:---:|
| **14** | **1066** | **11486** | **64** | **66** | | **14** | **1087** | **11853** | **68** | **67** |
### 🔥 Top 6 Popular Plugins ### 🔥 Top 6 Popular Plugins
| Rank | Plugin | Downloads | Views | | Rank | Plugin | Downloads | Views |
|:---:|------|:---:|:---:| |:---:|------|:---:|:---:|
| 🥇 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | 341 | 3080 | | 🥇 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | 348 | 3165 |
| 🥈 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | 181 | 551 | | 🥈 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | 181 | 559 |
| 🥉 | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | 125 | 1390 | | 🥉 | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | 128 | 1437 |
| 4⃣ | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | 116 | 1355 | | 4⃣ | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | 120 | 1393 |
| 5⃣ | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | 92 | 1735 | | 5⃣ | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | 94 | 1766 |
| 6⃣ | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | 87 | 800 | | 6⃣ | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | 87 | 814 |
*See full stats in [Community Stats Report](./docs/community-stats.md)* *See full stats in [Community Stats Report](./docs/community-stats.md)*
<!-- STATS_END --> <!-- STATS_END -->

View File

@@ -7,26 +7,26 @@ OpenWebUI 增强功能集合。包含个人开发与收集的插件、提示词
<!-- STATS_START --> <!-- STATS_START -->
## 📊 社区统计 ## 📊 社区统计
> 🕐 自动更新于 2026-01-10 17:08 > 🕐 自动更新于 2026-01-11 02:11
| 👤 作者 | 👥 粉丝 | ⭐ 积分 | 🏆 贡献 | | 👤 作者 | 👥 粉丝 | ⭐ 积分 | 🏆 贡献 |
|:---:|:---:|:---:|:---:| |:---:|:---:|:---:|:---:|
| [Fu-Jie](https://openwebui.com/u/Fu-Jie) | **71** | **72** | **21** | | [Fu-Jie](https://openwebui.com/u/Fu-Jie) | **75** | **77** | **22** |
| 📝 发布 | ⬇️ 下载 | 👁️ 浏览 | 👍 点赞 | 💾 收藏 | | 📝 发布 | ⬇️ 下载 | 👁️ 浏览 | 👍 点赞 | 💾 收藏 |
|:---:|:---:|:---:|:---:|:---:| |:---:|:---:|:---:|:---:|:---:|
| **14** | **1066** | **11486** | **64** | **66** | | **14** | **1087** | **11853** | **68** | **67** |
### 🔥 热门插件 Top 6 ### 🔥 热门插件 Top 6
| 排名 | 插件 | 下载 | 浏览 | | 排名 | 插件 | 下载 | 浏览 |
|:---:|------|:---:|:---:| |:---:|------|:---:|:---:|
| 🥇 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | 341 | 3080 | | 🥇 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | 348 | 3165 |
| 🥈 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | 181 | 551 | | 🥈 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | 181 | 559 |
| 🥉 | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | 125 | 1390 | | 🥉 | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | 128 | 1437 |
| 4⃣ | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | 116 | 1355 | | 4⃣ | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | 120 | 1393 |
| 5⃣ | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | 92 | 1735 | | 5⃣ | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | 94 | 1766 |
| 6⃣ | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | 87 | 800 | | 6⃣ | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | 87 | 814 |
*完整统计请查看 [社区统计报告](./docs/community-stats.zh.md)* *完整统计请查看 [社区统计报告](./docs/community-stats.zh.md)*
<!-- STATS_END --> <!-- STATS_END -->

View File

@@ -1,15 +1,15 @@
{ {
"total_posts": 14, "total_posts": 14,
"total_downloads": 1066, "total_downloads": 1087,
"total_views": 11486, "total_views": 11853,
"total_upvotes": 64, "total_upvotes": 68,
"total_downvotes": 2, "total_downvotes": 2,
"total_saves": 66, "total_saves": 67,
"total_comments": 15, "total_comments": 17,
"by_type": { "by_type": {
"filter": 2,
"unknown": 1, "unknown": 1,
"action": 11, "action": 11
"filter": 2
}, },
"posts": [ "posts": [
{ {
@@ -19,8 +19,8 @@
"version": "0.9.1", "version": "0.9.1",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "Intelligently analyzes text content and generates interactive mind maps to help users structure and visualize knowledge.", "description": "Intelligently analyzes text content and generates interactive mind maps to help users structure and visualize knowledge.",
"downloads": 341, "downloads": 348,
"views": 3080, "views": 3165,
"upvotes": 10, "upvotes": 10,
"saves": 21, "saves": 21,
"comments": 10, "comments": 10,
@@ -36,7 +36,7 @@
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "Extracts tables from chat messages and exports them to Excel (.xlsx) files with smart formatting.", "description": "Extracts tables from chat messages and exports them to Excel (.xlsx) files with smart formatting.",
"downloads": 181, "downloads": 181,
"views": 551, "views": 559,
"upvotes": 3, "upvotes": 3,
"saves": 4, "saves": 4,
"comments": 0, "comments": 0,
@@ -48,16 +48,16 @@
"title": "Async Context Compression", "title": "Async Context Compression",
"slug": "async_context_compression_b1655bc8", "slug": "async_context_compression_b1655bc8",
"type": "filter", "type": "filter",
"version": "1.1.0", "version": "1.1.1",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "Reduces token consumption in long conversations while maintaining coherence through intelligent summarization and message compression.", "description": "Reduces token consumption in long conversations while maintaining coherence through intelligent summarization and message compression.",
"downloads": 125, "downloads": 128,
"views": 1390, "views": 1437,
"upvotes": 5, "upvotes": 5,
"saves": 9, "saves": 9,
"comments": 0, "comments": 0,
"created_at": "2025-11-08", "created_at": "2025-11-08",
"updated_at": "2026-01-07", "updated_at": "2026-01-10",
"url": "https://openwebui.com/posts/async_context_compression_b1655bc8" "url": "https://openwebui.com/posts/async_context_compression_b1655bc8"
}, },
{ {
@@ -67,8 +67,8 @@
"version": "1.4.1", "version": "1.4.1",
"author": "jeff", "author": "jeff",
"description": "AI-powered infographic generator based on AntV Infographic. Supports professional templates, auto-icon matching, and SVG/PNG downloads.", "description": "AI-powered infographic generator based on AntV Infographic. Supports professional templates, auto-icon matching, and SVG/PNG downloads.",
"downloads": 116, "downloads": 120,
"views": 1355, "views": 1393,
"upvotes": 7, "upvotes": 7,
"saves": 9, "saves": 9,
"comments": 2, "comments": 2,
@@ -83,8 +83,8 @@
"version": "0.2.4", "version": "0.2.4",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "Quickly generates beautiful flashcards from text, extracting key points and categories.", "description": "Quickly generates beautiful flashcards from text, extracting key points and categories.",
"downloads": 92, "downloads": 94,
"views": 1735, "views": 1766,
"upvotes": 8, "upvotes": 8,
"saves": 6, "saves": 6,
"comments": 2, "comments": 2,
@@ -100,7 +100,7 @@
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "Export current conversation from Markdown to Word (.docx) with Mermaid diagrams rendered client-side (Mermaid.js, SVG+PNG), LaTeX math, real hyperlinks, improved tables, syntax highlighting, and blockquote support.", "description": "Export current conversation from Markdown to Word (.docx) with Mermaid diagrams rendered client-side (Mermaid.js, SVG+PNG), LaTeX math, real hyperlinks, improved tables, syntax highlighting, and blockquote support.",
"downloads": 87, "downloads": 87,
"views": 800, "views": 814,
"upvotes": 5, "upvotes": 5,
"saves": 8, "saves": 8,
"comments": 0, "comments": 0,
@@ -116,7 +116,7 @@
"author": "jeff", "author": "jeff",
"description": "基于 AntV Infographic 的智能信息图生成插件。支持多种专业模板,自动图标匹配,并提供 SVG/PNG 下载功能。", "description": "基于 AntV Infographic 的智能信息图生成插件。支持多种专业模板,自动图标匹配,并提供 SVG/PNG 下载功能。",
"downloads": 35, "downloads": 35,
"views": 480, "views": 486,
"upvotes": 3, "upvotes": 3,
"saves": 0, "saves": 0,
"comments": 0, "comments": 0,
@@ -131,8 +131,8 @@
"version": "0.4.3", "version": "0.4.3",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "将对话导出为 Word (.docx),支持 Mermaid 图表 (客户端渲染 SVG+PNG)、LaTeX 数学公式、真实超链接、增强表格格式、代码高亮和引用块。", "description": "将对话导出为 Word (.docx),支持 Mermaid 图表 (客户端渲染 SVG+PNG)、LaTeX 数学公式、真实超链接、增强表格格式、代码高亮和引用块。",
"downloads": 31, "downloads": 33,
"views": 929, "views": 955,
"upvotes": 8, "upvotes": 8,
"saves": 2, "saves": 2,
"comments": 1, "comments": 1,
@@ -147,8 +147,8 @@
"version": "1.0.0", "version": "1.0.0",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "A comprehensive thinking lens that dives deep into any content - from context to logic, insights, and action paths.", "description": "A comprehensive thinking lens that dives deep into any content - from context to logic, insights, and action paths.",
"downloads": 22, "downloads": 24,
"views": 259, "views": 272,
"upvotes": 3, "upvotes": 3,
"saves": 3, "saves": 3,
"comments": 0, "comments": 0,
@@ -164,7 +164,7 @@
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "智能分析文本内容,生成交互式思维导图,帮助用户结构化和可视化知识。", "description": "智能分析文本内容,生成交互式思维导图,帮助用户结构化和可视化知识。",
"downloads": 17, "downloads": 17,
"views": 304, "views": 306,
"upvotes": 2, "upvotes": 2,
"saves": 1, "saves": 1,
"comments": 0, "comments": 0,
@@ -180,7 +180,7 @@
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "快速将文本提炼为精美的学习记忆卡片,支持核心要点提取与分类。", "description": "快速将文本提炼为精美的学习记忆卡片,支持核心要点提取与分类。",
"downloads": 12, "downloads": 12,
"views": 345, "views": 349,
"upvotes": 4, "upvotes": 4,
"saves": 1, "saves": 1,
"comments": 0, "comments": 0,
@@ -192,16 +192,16 @@
"title": "异步上下文压缩", "title": "异步上下文压缩",
"slug": "异步上下文压缩_5c0617cb", "slug": "异步上下文压缩_5c0617cb",
"type": "filter", "type": "filter",
"version": "1.1.0", "version": "1.1.1",
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "通过智能摘要和消息压缩,降低长对话的 token 消耗,同时保持对话连贯性。", "description": "通过智能摘要和消息压缩,降低长对话的 token 消耗,同时保持对话连贯性。",
"downloads": 6, "downloads": 7,
"views": 153, "views": 177,
"upvotes": 2, "upvotes": 3,
"saves": 1, "saves": 1,
"comments": 0, "comments": 0,
"created_at": "2025-11-08", "created_at": "2025-11-08",
"updated_at": "2026-01-07", "updated_at": "2026-01-10",
"url": "https://openwebui.com/posts/异步上下文压缩_5c0617cb" "url": "https://openwebui.com/posts/异步上下文压缩_5c0617cb"
}, },
{ {
@@ -212,7 +212,7 @@
"author": "Fu-Jie", "author": "Fu-Jie",
"description": "全方位的思维透镜 —— 从背景全景到逻辑脉络,从深度洞察到行动路径。", "description": "全方位的思维透镜 —— 从背景全景到逻辑脉络,从深度洞察到行动路径。",
"downloads": 1, "downloads": 1,
"views": 86, "views": 94,
"upvotes": 2, "upvotes": 2,
"saves": 1, "saves": 1,
"comments": 0, "comments": 0,
@@ -228,10 +228,10 @@
"author": "", "author": "",
"description": "", "description": "",
"downloads": 0, "downloads": 0,
"views": 19, "views": 80,
"upvotes": 2, "upvotes": 5,
"saves": 0, "saves": 1,
"comments": 0, "comments": 2,
"created_at": "2026-01-10", "created_at": "2026-01-10",
"updated_at": "2026-01-10", "updated_at": "2026-01-10",
"url": "https://openwebui.com/posts/debug_open_webui_plugins_in_your_browser_81bf7960" "url": "https://openwebui.com/posts/debug_open_webui_plugins_in_your_browser_81bf7960"
@@ -242,11 +242,11 @@
"name": "Fu-Jie", "name": "Fu-Jie",
"profile_url": "https://openwebui.com/u/Fu-Jie", "profile_url": "https://openwebui.com/u/Fu-Jie",
"profile_image": "https://community.s3.openwebui.com/uploads/users/b15d1348-4347-42b4-b815-e053342d6cb0/profile_d9510745-4bd4-4f8f-a997-4a21847d9300.webp", "profile_image": "https://community.s3.openwebui.com/uploads/users/b15d1348-4347-42b4-b815-e053342d6cb0/profile_d9510745-4bd4-4f8f-a997-4a21847d9300.webp",
"followers": 71, "followers": 75,
"following": 2, "following": 2,
"total_points": 72, "total_points": 77,
"post_points": 62, "post_points": 66,
"comment_points": 10, "comment_points": 11,
"contributions": 21 "contributions": 22
} }
} }

View File

@@ -1,39 +1,39 @@
# 📊 OpenWebUI Community Stats Report # 📊 OpenWebUI Community Stats Report
> 📅 Updated: 2026-01-10 17:08 > 📅 Updated: 2026-01-11 02:11
## 📈 Overview ## 📈 Overview
| Metric | Value | | Metric | Value |
|------|------| |------|------|
| 📝 Total Posts | 14 | | 📝 Total Posts | 14 |
| ⬇️ Total Downloads | 1066 | | ⬇️ Total Downloads | 1087 |
| 👁️ Total Views | 11486 | | 👁️ Total Views | 11853 |
| 👍 Total Upvotes | 64 | | 👍 Total Upvotes | 68 |
| 💾 Total Saves | 66 | | 💾 Total Saves | 67 |
| 💬 Total Comments | 15 | | 💬 Total Comments | 17 |
## 📂 By Type ## 📂 By Type
- **filter**: 2
- **unknown**: 1 - **unknown**: 1
- **action**: 11 - **action**: 11
- **filter**: 2
## 📋 Posts List ## 📋 Posts List
| Rank | Title | Type | Version | Downloads | Views | Upvotes | Saves | Updated | | Rank | Title | Type | Version | Downloads | Views | Upvotes | Saves | Updated |
|:---:|------|:---:|:---:|:---:|:---:|:---:|:---:|:---:| |:---:|------|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| 1 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | action | 0.9.1 | 341 | 3080 | 10 | 21 | 2026-01-07 | | 1 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | action | 0.9.1 | 348 | 3165 | 10 | 21 | 2026-01-07 |
| 2 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | action | 0.3.7 | 181 | 551 | 3 | 4 | 2026-01-07 | | 2 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | action | 0.3.7 | 181 | 559 | 3 | 4 | 2026-01-07 |
| 3 | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | filter | 1.1.0 | 125 | 1390 | 5 | 9 | 2026-01-07 | | 3 | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | filter | 1.1.1 | 128 | 1437 | 5 | 9 | 2026-01-10 |
| 4 | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | action | 1.4.1 | 116 | 1355 | 7 | 9 | 2026-01-07 | | 4 | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | action | 1.4.1 | 120 | 1393 | 7 | 9 | 2026-01-07 |
| 5 | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | action | 0.2.4 | 92 | 1735 | 8 | 6 | 2026-01-07 | | 5 | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | action | 0.2.4 | 94 | 1766 | 8 | 6 | 2026-01-07 |
| 6 | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | action | 0.4.3 | 87 | 800 | 5 | 8 | 2026-01-07 | | 6 | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | action | 0.4.3 | 87 | 814 | 5 | 8 | 2026-01-07 |
| 7 | [📊 智能信息图 (AntV Infographic)](https://openwebui.com/posts/智能信息图_e04a48ff) | action | 1.4.1 | 35 | 480 | 3 | 0 | 2026-01-07 | | 7 | [📊 智能信息图 (AntV Infographic)](https://openwebui.com/posts/智能信息图_e04a48ff) | action | 1.4.1 | 35 | 486 | 3 | 0 | 2026-01-07 |
| 8 | [导出为 Word (增强版)](https://openwebui.com/posts/导出为_word_支持公式流程图表格和代码块_8a6306c0) | action | 0.4.3 | 31 | 929 | 8 | 2 | 2026-01-07 | | 8 | [导出为 Word (增强版)](https://openwebui.com/posts/导出为_word_支持公式流程图表格和代码块_8a6306c0) | action | 0.4.3 | 33 | 955 | 8 | 2 | 2026-01-07 |
| 9 | [Deep Dive](https://openwebui.com/posts/deep_dive_c0b846e4) | action | 1.0.0 | 22 | 259 | 3 | 3 | 2026-01-08 | | 9 | [Deep Dive](https://openwebui.com/posts/deep_dive_c0b846e4) | action | 1.0.0 | 24 | 272 | 3 | 3 | 2026-01-08 |
| 10 | [思维导图](https://openwebui.com/posts/智能生成交互式思维导图帮助用户可视化知识_8d4b097b) | action | 0.9.1 | 17 | 304 | 2 | 1 | 2026-01-07 | | 10 | [思维导图](https://openwebui.com/posts/智能生成交互式思维导图帮助用户可视化知识_8d4b097b) | action | 0.9.1 | 17 | 306 | 2 | 1 | 2026-01-07 |
| 11 | [闪记卡 (Flash Card)](https://openwebui.com/posts/闪记卡生成插件_4a31eac3) | action | 0.2.4 | 12 | 345 | 4 | 1 | 2026-01-07 | | 11 | [闪记卡 (Flash Card)](https://openwebui.com/posts/闪记卡生成插件_4a31eac3) | action | 0.2.4 | 12 | 349 | 4 | 1 | 2026-01-07 |
| 12 | [异步上下文压缩](https://openwebui.com/posts/异步上下文压缩_5c0617cb) | filter | 1.1.0 | 6 | 153 | 2 | 1 | 2026-01-07 | | 12 | [异步上下文压缩](https://openwebui.com/posts/异步上下文压缩_5c0617cb) | filter | 1.1.1 | 7 | 177 | 3 | 1 | 2026-01-10 |
| 13 | [精读](https://openwebui.com/posts/精读_99830b0f) | action | 1.0.0 | 1 | 86 | 2 | 1 | 2026-01-08 | | 13 | [精读](https://openwebui.com/posts/精读_99830b0f) | action | 1.0.0 | 1 | 94 | 2 | 1 | 2026-01-08 |
| 14 | [ 🛠️ Debug Open WebUI Plugins in Your Browser](https://openwebui.com/posts/debug_open_webui_plugins_in_your_browser_81bf7960) | unknown | | 0 | 19 | 2 | 0 | 2026-01-10 | | 14 | [ 🛠️ Debug Open WebUI Plugins in Your Browser](https://openwebui.com/posts/debug_open_webui_plugins_in_your_browser_81bf7960) | unknown | | 0 | 80 | 5 | 1 | 2026-01-10 |

View File

@@ -1,39 +1,39 @@
# 📊 OpenWebUI 社区统计报告 # 📊 OpenWebUI 社区统计报告
> 📅 更新时间: 2026-01-10 17:08 > 📅 更新时间: 2026-01-11 02:11
## 📈 总览 ## 📈 总览
| 指标 | 数值 | | 指标 | 数值 |
|------|------| |------|------|
| 📝 发布数量 | 14 | | 📝 发布数量 | 14 |
| ⬇️ 总下载量 | 1066 | | ⬇️ 总下载量 | 1087 |
| 👁️ 总浏览量 | 11486 | | 👁️ 总浏览量 | 11853 |
| 👍 总点赞数 | 64 | | 👍 总点赞数 | 68 |
| 💾 总收藏数 | 66 | | 💾 总收藏数 | 67 |
| 💬 总评论数 | 15 | | 💬 总评论数 | 17 |
## 📂 按类型分类 ## 📂 按类型分类
- **filter**: 2
- **unknown**: 1 - **unknown**: 1
- **action**: 11 - **action**: 11
- **filter**: 2
## 📋 发布列表 ## 📋 发布列表
| 排名 | 标题 | 类型 | 版本 | 下载 | 浏览 | 点赞 | 收藏 | 更新日期 | | 排名 | 标题 | 类型 | 版本 | 下载 | 浏览 | 点赞 | 收藏 | 更新日期 |
|:---:|------|:---:|:---:|:---:|:---:|:---:|:---:|:---:| |:---:|------|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| 1 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | action | 0.9.1 | 341 | 3080 | 10 | 21 | 2026-01-07 | | 1 | [Smart Mind Map](https://openwebui.com/posts/turn_any_text_into_beautiful_mind_maps_3094c59a) | action | 0.9.1 | 348 | 3165 | 10 | 21 | 2026-01-07 |
| 2 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | action | 0.3.7 | 181 | 551 | 3 | 4 | 2026-01-07 | | 2 | [Export to Excel](https://openwebui.com/posts/export_mulit_table_to_excel_244b8f9d) | action | 0.3.7 | 181 | 559 | 3 | 4 | 2026-01-07 |
| 3 | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | filter | 1.1.0 | 125 | 1390 | 5 | 9 | 2026-01-07 | | 3 | [Async Context Compression](https://openwebui.com/posts/async_context_compression_b1655bc8) | filter | 1.1.1 | 128 | 1437 | 5 | 9 | 2026-01-10 |
| 4 | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | action | 1.4.1 | 116 | 1355 | 7 | 9 | 2026-01-07 | | 4 | [📊 Smart Infographic (AntV)](https://openwebui.com/posts/smart_infographic_ad6f0c7f) | action | 1.4.1 | 120 | 1393 | 7 | 9 | 2026-01-07 |
| 5 | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | action | 0.2.4 | 92 | 1735 | 8 | 6 | 2026-01-07 | | 5 | [Flash Card](https://openwebui.com/posts/flash_card_65a2ea8f) | action | 0.2.4 | 94 | 1766 | 8 | 6 | 2026-01-07 |
| 6 | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | action | 0.4.3 | 87 | 800 | 5 | 8 | 2026-01-07 | | 6 | [Export to Word (Enhanced)](https://openwebui.com/posts/export_to_word_enhanced_formatting_fca6a315) | action | 0.4.3 | 87 | 814 | 5 | 8 | 2026-01-07 |
| 7 | [📊 智能信息图 (AntV Infographic)](https://openwebui.com/posts/智能信息图_e04a48ff) | action | 1.4.1 | 35 | 480 | 3 | 0 | 2026-01-07 | | 7 | [📊 智能信息图 (AntV Infographic)](https://openwebui.com/posts/智能信息图_e04a48ff) | action | 1.4.1 | 35 | 486 | 3 | 0 | 2026-01-07 |
| 8 | [导出为 Word (增强版)](https://openwebui.com/posts/导出为_word_支持公式流程图表格和代码块_8a6306c0) | action | 0.4.3 | 31 | 929 | 8 | 2 | 2026-01-07 | | 8 | [导出为 Word (增强版)](https://openwebui.com/posts/导出为_word_支持公式流程图表格和代码块_8a6306c0) | action | 0.4.3 | 33 | 955 | 8 | 2 | 2026-01-07 |
| 9 | [Deep Dive](https://openwebui.com/posts/deep_dive_c0b846e4) | action | 1.0.0 | 22 | 259 | 3 | 3 | 2026-01-08 | | 9 | [Deep Dive](https://openwebui.com/posts/deep_dive_c0b846e4) | action | 1.0.0 | 24 | 272 | 3 | 3 | 2026-01-08 |
| 10 | [思维导图](https://openwebui.com/posts/智能生成交互式思维导图帮助用户可视化知识_8d4b097b) | action | 0.9.1 | 17 | 304 | 2 | 1 | 2026-01-07 | | 10 | [思维导图](https://openwebui.com/posts/智能生成交互式思维导图帮助用户可视化知识_8d4b097b) | action | 0.9.1 | 17 | 306 | 2 | 1 | 2026-01-07 |
| 11 | [闪记卡 (Flash Card)](https://openwebui.com/posts/闪记卡生成插件_4a31eac3) | action | 0.2.4 | 12 | 345 | 4 | 1 | 2026-01-07 | | 11 | [闪记卡 (Flash Card)](https://openwebui.com/posts/闪记卡生成插件_4a31eac3) | action | 0.2.4 | 12 | 349 | 4 | 1 | 2026-01-07 |
| 12 | [异步上下文压缩](https://openwebui.com/posts/异步上下文压缩_5c0617cb) | filter | 1.1.0 | 6 | 153 | 2 | 1 | 2026-01-07 | | 12 | [异步上下文压缩](https://openwebui.com/posts/异步上下文压缩_5c0617cb) | filter | 1.1.1 | 7 | 177 | 3 | 1 | 2026-01-10 |
| 13 | [精读](https://openwebui.com/posts/精读_99830b0f) | action | 1.0.0 | 1 | 86 | 2 | 1 | 2026-01-08 | | 13 | [精读](https://openwebui.com/posts/精读_99830b0f) | action | 1.0.0 | 1 | 94 | 2 | 1 | 2026-01-08 |
| 14 | [ 🛠️ Debug Open WebUI Plugins in Your Browser](https://openwebui.com/posts/debug_open_webui_plugins_in_your_browser_81bf7960) | unknown | | 0 | 19 | 2 | 0 | 2026-01-10 | | 14 | [ 🛠️ Debug Open WebUI Plugins in Your Browser](https://openwebui.com/posts/debug_open_webui_plugins_in_your_browser_81bf7960) | unknown | | 0 | 80 | 5 | 1 | 2026-01-10 |

View File

@@ -1,7 +1,7 @@
# Async Context Compression # Async Context Compression
<span class="category-badge filter">Filter</span> <span class="category-badge filter">Filter</span>
<span class="version-badge">v1.1.0</span> <span class="version-badge">v1.1.2</span>
Reduces token consumption in long conversations through intelligent summarization while maintaining conversational coherence. Reduces token consumption in long conversations through intelligent summarization while maintaining conversational coherence.
@@ -29,6 +29,9 @@ This is especially useful for:
- :material-clock-fast: **Async Processing**: Non-blocking background compression - :material-clock-fast: **Async Processing**: Non-blocking background compression
- :material-memory: **Context Preservation**: Keeps important information - :material-memory: **Context Preservation**: Keeps important information
- :material-currency-usd-off: **Cost Reduction**: Minimize token usage - :material-currency-usd-off: **Cost Reduction**: Minimize token usage
- :material-console: **Frontend Debugging**: Debug logs in browser console
- :material-alert-circle-check: **Enhanced Error Reporting**: Clear error status notifications
- :material-check-all: **Open WebUI v0.7.x Compatibility**: Dynamic DB session handling
--- ---

View File

@@ -1,7 +1,7 @@
# Async Context Compression异步上下文压缩 # Async Context Compression异步上下文压缩
<span class="category-badge filter">Filter</span> <span class="category-badge filter">Filter</span>
<span class="version-badge">v1.1.0</span> <span class="version-badge">v1.1.2</span>
通过智能摘要减少长对话的 token 消耗,同时保持对话连贯。 通过智能摘要减少长对话的 token 消耗,同时保持对话连贯。
@@ -29,6 +29,9 @@ Async Context Compression 过滤器通过以下方式帮助管理长对话的 to
- :material-clock-fast: **异步处理**:后台非阻塞压缩 - :material-clock-fast: **异步处理**:后台非阻塞压缩
- :material-memory: **保留上下文**:尽量保留重要信息 - :material-memory: **保留上下文**:尽量保留重要信息
- :material-currency-usd-off: **降低成本**:减少 token 使用 - :material-currency-usd-off: **降低成本**:减少 token 使用
- :material-console: **前端调试**:支持浏览器控制台日志
- :material-alert-circle-check: **增强错误报告**:清晰的错误状态通知
- :material-check-all: **Open WebUI v0.7.x 兼容性**:动态数据库会话处理
--- ---

View File

@@ -22,7 +22,7 @@ Filters act as middleware in the message pipeline:
Reduces token consumption in long conversations through intelligent summarization while maintaining coherence. Reduces token consumption in long conversations through intelligent summarization while maintaining coherence.
**Version:** 1.1.0 **Version:** 1.1.2
[:octicons-arrow-right-24: Documentation](async-context-compression.md) [:octicons-arrow-right-24: Documentation](async-context-compression.md)

View File

@@ -1,9 +1,20 @@
# Async Context Compression Filter # Async Context Compression Filter
**Author:** [Fu-Jie](https://github.com/Fu-Jie) | **Version:** 1.1.0 | **License:** MIT **Author:** [Fu-Jie](https://github.com/Fu-Jie) | **Version:** 1.1.2 | **License:** MIT
This filter reduces token consumption in long conversations through intelligent summarization and message compression while keeping conversations coherent. This filter reduces token consumption in long conversations through intelligent summarization and message compression while keeping conversations coherent.
## What's new in 1.1.2
- **Open WebUI v0.7.x Compatibility**: Resolved a critical database session binding error affecting Open WebUI v0.7.x users. The plugin now dynamically discovers the database engine and session context, ensuring compatibility across versions.
- **Enhanced Error Reporting**: Errors during background summary generation are now reported via both the status bar and browser console.
- **Robust Model Handling**: Improved handling of missing or invalid model IDs to prevent crashes.
## What's new in 1.1.1
- **Frontend Debugging**: Added `show_debug_log` option to print debug info to the browser console (F12).
- **Optimized Compression**: Improved token calculation logic to prevent aggressive truncation of history, ensuring more context is retained.
## What's new in 1.1.0 ## What's new in 1.1.0
- Reuses Open WebUI's shared database connection by default (no custom engine or env vars required). - Reuses Open WebUI's shared database connection by default (no custom engine or env vars required).
@@ -54,6 +65,7 @@ It is recommended to keep this filter early in the chain so it runs before filte
| `summary_temperature` | `0.3` | Randomness for summary generation. Lower is more deterministic. | | `summary_temperature` | `0.3` | Randomness for summary generation. Lower is more deterministic. |
| `model_thresholds` | `{}` | Per-model overrides for `compression_threshold_tokens` and `max_context_tokens` (useful for mixed models). | | `model_thresholds` | `{}` | Per-model overrides for `compression_threshold_tokens` and `max_context_tokens` (useful for mixed models). |
| `debug_mode` | `true` | Log verbose debug info. Set to `false` in production. | | `debug_mode` | `true` | Log verbose debug info. Set to `false` in production. |
| `show_debug_log` | `false` | Print debug logs to browser console (F12). Useful for frontend debugging. |
--- ---

View File

@@ -1,11 +1,22 @@
# 异步上下文压缩过滤器 # 异步上下文压缩过滤器
**作者:** [Fu-Jie](https://github.com/Fu-Jie) | **版本:** 1.2.0 | **许可证:** MIT **作者:** [Fu-Jie](https://github.com/Fu-Jie) | **版本:** 1.1.2 | **许可证:** MIT
> **重要提示**:为了确保所有过滤器的可维护性和易用性,每个过滤器都应附带清晰、完整的文档,以确保其功能、配置和使用方法得到充分说明。 > **重要提示**:为了确保所有过滤器的可维护性和易用性,每个过滤器都应附带清晰、完整的文档,以确保其功能、配置和使用方法得到充分说明。
本过滤器通过智能摘要和消息压缩技术,在保持对话连贯性的同时,显著降低长对话的 Token 消耗。 本过滤器通过智能摘要和消息压缩技术,在保持对话连贯性的同时,显著降低长对话的 Token 消耗。
## 1.1.2 版本更新
- **Open WebUI v0.7.x 兼容性**: 修复了影响 Open WebUI v0.7.x 用户的严重数据库会话绑定错误。插件现在动态发现数据库引擎和会话上下文,确保跨版本兼容性。
- **增强错误报告**: 后台摘要生成过程中的错误现在会通过状态栏和浏览器控制台同时报告。
- **健壮的模型处理**: 改进了对缺失或无效模型 ID 的处理,防止程序崩溃。
## 1.1.1 版本更新
- **前端调试**: 新增 `show_debug_log` 选项,支持在浏览器控制台 (F12) 打印调试信息。
- **压缩优化**: 优化 Token 计算逻辑,防止历史记录被过度截断,保留更多上下文。
## 1.1.0 版本更新 ## 1.1.0 版本更新
- 默认复用 OpenWebUI 内置数据库连接,无需自建引擎、无需配置 `DATABASE_URL` - 默认复用 OpenWebUI 内置数据库连接,无需自建引擎、无需配置 `DATABASE_URL`
@@ -94,6 +105,11 @@
- **默认值**: `true` - **默认值**: `true`
- **描述**: 是否在 Open WebUI 的控制台日志中打印详细的调试信息(如 Token 计数、压缩进度、数据库操作等)。生产环境建议设为 `false` - **描述**: 是否在 Open WebUI 的控制台日志中打印详细的调试信息(如 Token 计数、压缩进度、数据库操作等)。生产环境建议设为 `false`
#### `show_debug_log`
- **默认值**: `false`
- **描述**: 是否在浏览器控制台 (F12) 打印调试日志。便于前端调试。
--- ---
## 故障排除 ## 故障排除

View File

@@ -5,7 +5,7 @@ author: Fu-Jie
author_url: https://github.com/Fu-Jie author_url: https://github.com/Fu-Jie
funding_url: https://github.com/Fu-Jie/awesome-openwebui funding_url: https://github.com/Fu-Jie/awesome-openwebui
description: Reduces token consumption in long conversations while maintaining coherence through intelligent summarization and message compression. description: Reduces token consumption in long conversations while maintaining coherence through intelligent summarization and message compression.
version: 1.1.1 version: 1.1.2
openwebui_id: b1655bc8-6de9-4cad-8cb5-a6f7829a02ce openwebui_id: b1655bc8-6de9-4cad-8cb5-a6f7829a02ce
license: MIT license: MIT
@@ -249,6 +249,7 @@ import asyncio
import json import json
import hashlib import hashlib
import time import time
import contextlib
# Open WebUI built-in imports # Open WebUI built-in imports
from open_webui.utils.chat import generate_chat_completion from open_webui.utils.chat import generate_chat_completion
@@ -257,9 +258,10 @@ from fastapi.requests import Request
from open_webui.main import app as webui_app from open_webui.main import app as webui_app
# Open WebUI internal database (re-use shared connection) # Open WebUI internal database (re-use shared connection)
from open_webui.internal.db import engine as owui_engine try:
from open_webui.internal.db import Session as owui_Session from open_webui.internal import db as owui_db
from open_webui.internal.db import Base as owui_Base except ModuleNotFoundError: # pragma: no cover - filter runs inside Open WebUI
owui_db = None
# Try to import tiktoken # Try to import tiktoken
try: try:
@@ -269,14 +271,91 @@ except ImportError:
# Database imports # Database imports
from sqlalchemy import Column, String, Text, DateTime, Integer, inspect from sqlalchemy import Column, String, Text, DateTime, Integer, inspect
from sqlalchemy.orm import declarative_base, sessionmaker
from sqlalchemy.engine import Engine
from datetime import datetime from datetime import datetime
def _discover_owui_engine(db_module: Any) -> Optional[Engine]:
"""Discover the Open WebUI SQLAlchemy engine via provided db module helpers."""
if db_module is None:
return None
db_context = getattr(db_module, "get_db_context", None) or getattr(
db_module, "get_db", None
)
if callable(db_context):
try:
with db_context() as session:
try:
return session.get_bind()
except AttributeError:
return getattr(session, "bind", None) or getattr(
session, "engine", None
)
except Exception as exc:
print(f"[DB Discover] get_db_context failed: {exc}")
for attr in ("engine", "ENGINE", "bind", "BIND"):
candidate = getattr(db_module, attr, None)
if candidate is not None:
return candidate
return None
def _discover_owui_schema(db_module: Any) -> Optional[str]:
"""Discover the Open WebUI database schema name if configured."""
if db_module is None:
return None
try:
base = getattr(db_module, "Base", None)
metadata = getattr(base, "metadata", None) if base is not None else None
candidate = getattr(metadata, "schema", None) if metadata is not None else None
if isinstance(candidate, str) and candidate.strip():
return candidate.strip()
except Exception as exc:
print(f"[DB Discover] Base metadata schema lookup failed: {exc}")
try:
metadata_obj = getattr(db_module, "metadata_obj", None)
candidate = (
getattr(metadata_obj, "schema", None) if metadata_obj is not None else None
)
if isinstance(candidate, str) and candidate.strip():
return candidate.strip()
except Exception as exc:
print(f"[DB Discover] metadata_obj schema lookup failed: {exc}")
try:
from open_webui import env as owui_env
candidate = getattr(owui_env, "DATABASE_SCHEMA", None)
if isinstance(candidate, str) and candidate.strip():
return candidate.strip()
except Exception as exc:
print(f"[DB Discover] env schema lookup failed: {exc}")
return None
owui_engine = _discover_owui_engine(owui_db)
owui_schema = _discover_owui_schema(owui_db)
owui_Base = getattr(owui_db, "Base", None) if owui_db is not None else None
if owui_Base is None:
owui_Base = declarative_base()
class ChatSummary(owui_Base): class ChatSummary(owui_Base):
"""Chat Summary Storage Table""" """Chat Summary Storage Table"""
__tablename__ = "chat_summary" __tablename__ = "chat_summary"
__table_args__ = {"extend_existing": True} __table_args__ = (
{"extend_existing": True, "schema": owui_schema}
if owui_schema
else {"extend_existing": True}
)
id = Column(Integer, primary_key=True, autoincrement=True) id = Column(Integer, primary_key=True, autoincrement=True)
chat_id = Column(String(255), unique=True, nullable=False, index=True) chat_id = Column(String(255), unique=True, nullable=False, index=True)
@@ -289,14 +368,66 @@ class ChatSummary(owui_Base):
class Filter: class Filter:
def __init__(self): def __init__(self):
self.valves = self.Valves() self.valves = self.Valves()
self._owui_db = owui_db
self._db_engine = owui_engine self._db_engine = owui_engine
self._SessionLocal = owui_Session
self.temp_state = {} # Used to pass temporary data between inlet and outlet self.temp_state = {} # Used to pass temporary data between inlet and outlet
self._fallback_session_factory = (
sessionmaker(bind=self._db_engine) if self._db_engine else None
)
self._init_database() self._init_database()
@contextlib.contextmanager
def _db_session(self):
"""Yield a database session using Open WebUI helpers with graceful fallbacks."""
db_module = self._owui_db
db_context = None
if db_module is not None:
db_context = getattr(db_module, "get_db_context", None) or getattr(
db_module, "get_db", None
)
if callable(db_context):
with db_context() as session:
yield session
return
factory = None
if db_module is not None:
factory = getattr(db_module, "SessionLocal", None) or getattr(
db_module, "ScopedSession", None
)
if callable(factory):
session = factory()
try:
yield session
finally:
close = getattr(session, "close", None)
if callable(close):
close()
return
if self._fallback_session_factory is None:
raise RuntimeError(
"Open WebUI database session is unavailable. Ensure Open WebUI's database layer is initialized."
)
session = self._fallback_session_factory()
try:
yield session
finally:
try:
session.close()
except Exception as exc: # pragma: no cover - best-effort cleanup
print(f"[Database] ⚠️ Failed to close fallback session: {exc}")
def _init_database(self): def _init_database(self):
"""Initializes the database table using Open WebUI's shared connection.""" """Initializes the database table using Open WebUI's shared connection."""
try: try:
if self._db_engine is None:
raise RuntimeError(
"Open WebUI database engine is unavailable. Ensure Open WebUI is configured with a valid DATABASE_URL."
)
# Check if table exists using SQLAlchemy inspect # Check if table exists using SQLAlchemy inspect
inspector = inspect(self._db_engine) inspector = inspect(self._db_engine)
if not inspector.has_table("chat_summary"): if not inspector.has_table("chat_summary"):
@@ -366,7 +497,7 @@ class Filter:
def _save_summary(self, chat_id: str, summary: str, compressed_count: int): def _save_summary(self, chat_id: str, summary: str, compressed_count: int):
"""Saves the summary to the database.""" """Saves the summary to the database."""
try: try:
with self._SessionLocal() as session: with self._db_session() as session:
# Find existing record # Find existing record
existing = session.query(ChatSummary).filter_by(chat_id=chat_id).first() existing = session.query(ChatSummary).filter_by(chat_id=chat_id).first()
@@ -406,7 +537,7 @@ class Filter:
def _load_summary_record(self, chat_id: str) -> Optional[ChatSummary]: def _load_summary_record(self, chat_id: str) -> Optional[ChatSummary]:
"""Loads the summary record object from the database.""" """Loads the summary record object from the database."""
try: try:
with self._SessionLocal() as session: with self._db_session() as session:
record = session.query(ChatSummary).filter_by(chat_id=chat_id).first() record = session.query(ChatSummary).filter_by(chat_id=chat_id).first()
if record: if record:
# Detach the object from the session so it can be used after session close # Detach the object from the session so it can be used after session close
@@ -487,6 +618,26 @@ class Filter:
"max_context_tokens": self.valves.max_context_tokens, "max_context_tokens": self.valves.max_context_tokens,
} }
def _extract_chat_id(self, body: dict, metadata: Optional[dict]) -> str:
"""Extract chat_id from body or metadata."""
if isinstance(body, dict):
chat_id = body.get("chat_id")
if isinstance(chat_id, str) and chat_id.strip():
return chat_id.strip()
body_metadata = body.get("metadata", {})
if isinstance(body_metadata, dict):
chat_id = body_metadata.get("chat_id")
if isinstance(chat_id, str) and chat_id.strip():
return chat_id.strip()
if isinstance(metadata, dict):
chat_id = metadata.get("chat_id")
if isinstance(chat_id, str) and chat_id.strip():
return chat_id.strip()
return ""
def _inject_summary_to_first_message(self, message: dict, summary: str) -> dict: def _inject_summary_to_first_message(self, message: dict, summary: str) -> dict:
"""Injects the summary into the first message (prepended to content).""" """Injects the summary into the first message (prepended to content)."""
content = message.get("content", "") content = message.get("content", "")
@@ -632,7 +783,15 @@ class Filter:
Compression Strategy: Only responsible for injecting existing summaries, no Token calculation. Compression Strategy: Only responsible for injecting existing summaries, no Token calculation.
""" """
messages = body.get("messages", []) messages = body.get("messages", [])
chat_id = __metadata__["chat_id"] chat_id = self._extract_chat_id(body, __metadata__)
if not chat_id:
await self._log(
"[Inlet] ❌ Missing chat_id in metadata, skipping compression",
type="error",
event_call=__event_call__,
)
return body
if self.valves.debug_mode or self.valves.show_debug_log: if self.valves.debug_mode or self.valves.show_debug_log:
await self._log( await self._log(
@@ -747,7 +906,14 @@ class Filter:
Executed after the LLM response is complete. Executed after the LLM response is complete.
Calculates Token count in the background and triggers summary generation (does not block current response, does not affect content output). Calculates Token count in the background and triggers summary generation (does not block current response, does not affect content output).
""" """
chat_id = __metadata__["chat_id"] chat_id = self._extract_chat_id(body, __metadata__)
if not chat_id:
await self._log(
"[Outlet] ❌ Missing chat_id in metadata, skipping compression",
type="error",
event_call=__event_call__,
)
return body
model = body.get("model", "gpt-3.5-turbo") model = body.get("model", "gpt-3.5-turbo")
if self.valves.debug_mode or self.valves.show_debug_log: if self.valves.debug_mode or self.valves.show_debug_log:
@@ -836,6 +1002,13 @@ class Filter:
event_call=__event_call__, event_call=__event_call__,
) )
def _clean_model_id(self, model_id: Optional[str]) -> Optional[str]:
"""Cleans the model ID by removing whitespace and quotes."""
if not model_id:
return None
cleaned = model_id.strip().strip('"').strip("'")
return cleaned if cleaned else None
async def _generate_summary_async( async def _generate_summary_async(
self, self,
messages: list, messages: list,
@@ -892,9 +1065,17 @@ class Filter:
# 3. Check Token limit and truncate (Max Context Truncation) # 3. Check Token limit and truncate (Max Context Truncation)
# [Optimization] Use the summary model's (if any) threshold to decide how many middle messages can be processed # [Optimization] Use the summary model's (if any) threshold to decide how many middle messages can be processed
# This allows using a long-window model (like gemini-flash) to compress history exceeding the current model's window # This allows using a long-window model (like gemini-flash) to compress history exceeding the current model's window
summary_model_id = self.valves.summary_model or body.get( summary_model_id = self._clean_model_id(
"model", "gpt-3.5-turbo" self.valves.summary_model
) or self._clean_model_id(body.get("model"))
if not summary_model_id:
await self._log(
"[🤖 Async Summary Task] ⚠️ Summary model does not exist, skipping compression",
type="warning",
event_call=__event_call__,
) )
return
thresholds = self._get_model_thresholds(summary_model_id) thresholds = self._get_model_thresholds(summary_model_id)
# Note: Using the summary model's max context limit here # Note: Using the summary model's max context limit here
@@ -966,9 +1147,21 @@ class Filter:
) )
new_summary = await self._call_summary_llm( new_summary = await self._call_summary_llm(
None, conversation_text, body, user_data, __event_call__ None,
conversation_text,
{**body, "model": summary_model_id},
user_data,
__event_call__,
) )
if not new_summary:
await self._log(
"[🤖 Async Summary Task] ⚠️ Summary generation returned empty result, skipping save",
type="warning",
event_call=__event_call__,
)
return
# 6. Save new summary # 6. Save new summary
await self._log( await self._log(
"[Optimization] Saving summary in a background thread to avoid blocking the event loop.", "[Optimization] Saving summary in a background thread to avoid blocking the event loop.",
@@ -1007,6 +1200,18 @@ class Filter:
type="error", type="error",
event_call=__event_call__, event_call=__event_call__,
) )
if __event_emitter__:
await __event_emitter__(
{
"type": "status",
"data": {
"description": f"Summary Error: {str(e)[:100]}...",
"done": True,
},
}
)
import traceback import traceback
traceback.print_exc() traceback.print_exc()
@@ -1088,7 +1293,17 @@ This conversation may contain previous summaries (as system messages or text) an
Based on the content above, generate the summary: Based on the content above, generate the summary:
""" """
# Determine the model to use # Determine the model to use
model = self.valves.summary_model or body.get("model", "") model = self._clean_model_id(self.valves.summary_model) or self._clean_model_id(
body.get("model")
)
if not model:
await self._log(
"[🤖 LLM Call] ⚠️ Summary model does not exist, skipping summary generation",
type="warning",
event_call=__event_call__,
)
return ""
await self._log(f"[🤖 LLM Call] Model: {model}", event_call=__event_call__) await self._log(f"[🤖 LLM Call] Model: {model}", event_call=__event_call__)
@@ -1142,7 +1357,12 @@ Based on the content above, generate the summary:
return summary return summary
except Exception as e: except Exception as e:
error_message = f"Error occurred while calling LLM ({model}) to generate summary: {str(e)}" error_msg = str(e)
# Handle specific error messages
if "Model not found" in error_msg:
error_message = f"Summary model '{model}' not found."
else:
error_message = f"Summary LLM Error ({model}): {error_msg}"
if not self.valves.summary_model: if not self.valves.summary_model:
error_message += ( error_message += (
"\n[Hint] You did not specify a summary_model, so the filter attempted to use the current conversation's model. " "\n[Hint] You did not specify a summary_model, so the filter attempted to use the current conversation's model. "

View File

@@ -5,7 +5,7 @@ author: Fu-Jie
author_url: https://github.com/Fu-Jie author_url: https://github.com/Fu-Jie
funding_url: https://github.com/Fu-Jie/awesome-openwebui funding_url: https://github.com/Fu-Jie/awesome-openwebui
description: 通过智能摘要和消息压缩,降低长对话的 token 消耗,同时保持对话连贯性。 description: 通过智能摘要和消息压缩,降低长对话的 token 消耗,同时保持对话连贯性。
version: 1.1.1 version: 1.1.2
openwebui_id: 5c0617cb-a9e4-4bd6-a440-d276534ebd18 openwebui_id: 5c0617cb-a9e4-4bd6-a440-d276534ebd18
license: MIT license: MIT
@@ -820,6 +820,13 @@ class Filter:
event_call=__event_call__, event_call=__event_call__,
) )
def _clean_model_id(self, model_id: Optional[str]) -> Optional[str]:
"""Cleans the model ID by removing whitespace and quotes."""
if not model_id:
return None
cleaned = model_id.strip().strip('"').strip("'")
return cleaned if cleaned else None
async def _generate_summary_async( async def _generate_summary_async(
self, self,
messages: list, messages: list,
@@ -874,7 +881,17 @@ class Filter:
# 3. 检查 Token 上限并截断 (Max Context Truncation) # 3. 检查 Token 上限并截断 (Max Context Truncation)
# [优化] 使用摘要模型(如果有)的阈值来决定能处理多少中间消息 # [优化] 使用摘要模型(如果有)的阈值来决定能处理多少中间消息
# 这样可以用长窗口模型(如 gemini-flash)来压缩超过当前模型窗口的历史记录 # 这样可以用长窗口模型(如 gemini-flash)来压缩超过当前模型窗口的历史记录
summary_model_id = self.valves.summary_model or body.get("model") summary_model_id = self._clean_model_id(
self.valves.summary_model
) or self._clean_model_id(body.get("model"))
if not summary_model_id:
await self._log(
"[🤖 异步摘要任务] ⚠️ 摘要模型不存在,跳过压缩",
type="warning",
event_call=__event_call__,
)
return
thresholds = self._get_model_thresholds(summary_model_id) thresholds = self._get_model_thresholds(summary_model_id)
# 注意:这里使用的是摘要模型的最大上下文限制 # 注意:这里使用的是摘要模型的最大上下文限制
@@ -946,9 +963,21 @@ class Filter:
) )
new_summary = await self._call_summary_llm( new_summary = await self._call_summary_llm(
None, conversation_text, body, user_data, __event_call__ None,
conversation_text,
{**body, "model": summary_model_id},
user_data,
__event_call__,
) )
if not new_summary:
await self._log(
"[🤖 异步摘要任务] ⚠️ 摘要生成返回空结果,跳过保存",
type="warning",
event_call=__event_call__,
)
return
# 6. 保存新摘要 # 6. 保存新摘要
await self._log( await self._log(
"[优化] 在后台线程中保存摘要以避免阻塞事件循环。", "[优化] 在后台线程中保存摘要以避免阻塞事件循环。",
@@ -987,6 +1016,18 @@ class Filter:
type="error", type="error",
event_call=__event_call__, event_call=__event_call__,
) )
if __event_emitter__:
await __event_emitter__(
{
"type": "status",
"data": {
"description": f"摘要生成错误: {str(e)[:100]}...",
"done": True,
},
}
)
import traceback import traceback
traceback.print_exc() traceback.print_exc()
@@ -1068,7 +1109,17 @@ class Filter:
请根据上述内容,生成摘要: 请根据上述内容,生成摘要:
""" """
# 确定使用的模型 # 确定使用的模型
model = self.valves.summary_model or body.get("model", "") model = self._clean_model_id(self.valves.summary_model) or self._clean_model_id(
body.get("model")
)
if not model:
await self._log(
"[🤖 LLM 调用] ⚠️ 摘要模型不存在,跳过摘要生成",
type="warning",
event_call=__event_call__,
)
return ""
await self._log(f"[🤖 LLM 调用] 模型: {model}", event_call=__event_call__) await self._log(f"[🤖 LLM 调用] 模型: {model}", event_call=__event_call__)
@@ -1122,7 +1173,12 @@ class Filter:
return summary return summary
except Exception as e: except Exception as e:
error_message = f"调用 LLM ({model}) 生成摘要时发生错误: {str(e)}" error_msg = str(e)
# Handle specific error messages
if "Model not found" in error_msg:
error_message = f"摘要模型 '{model}' 不存在。"
else:
error_message = f"摘要 LLM 错误 ({model}): {error_msg}"
if not self.valves.summary_model: if not self.valves.summary_model:
error_message += ( error_message += (
"\n[提示] 您未指定 summary_model因此过滤器尝试使用当前对话的模型。" "\n[提示] 您未指定 summary_model因此过滤器尝试使用当前对话的模型。"

View File

@@ -469,10 +469,42 @@ class OpenWebUICommunityClient:
return True, f"Created new post (ID: {new_post_id})" return True, f"Created new post (ID: {new_post_id})"
return False, "Failed to create new post" return False, "Failed to create new post"
# 获取远程帖子信息(只需获取一次)
remote_post = None
if post_id:
remote_post = self.get_post(post_id)
# 版本检查(仅对更新有效) # 版本检查(仅对更新有效)
if not force and local_version: if not force and local_version and remote_post:
if not self.version_needs_update(post_id, local_version): remote_version = (
return True, f"Skipped: version {local_version} matches remote" remote_post.get("data", {})
.get("function", {})
.get("meta", {})
.get("manifest", {})
.get("version")
)
version_changed = local_version != remote_version
# 检查 README 是否变化
readme_changed = False
remote_content = remote_post.get("content", "")
local_content = readme_content or metadata.get("description", "")
# 简单的内容比较 (去除首尾空白)
if (local_content or "").strip() != (remote_content or "").strip():
readme_changed = True
if not version_changed and not readme_changed:
return (
True,
f"Skipped: version {local_version} matches remote and no README changes",
)
if readme_changed and not version_changed:
print(
f" Version match ({local_version}) but README changed. Updating..."
)
# 更新 # 更新
success = self.update_plugin( success = self.update_plugin(
@@ -484,7 +516,9 @@ class OpenWebUICommunityClient:
) )
if success: if success:
if local_version:
return True, f"Updated to version {local_version}" return True, f"Updated to version {local_version}"
return True, "Updated plugin"
return False, "Update failed" return False, "Update failed"
def _parse_frontmatter(self, content: str) -> Dict[str, str]: def _parse_frontmatter(self, content: str) -> Dict[str, str]: