Skip to content

Commit 51dcc80

Browse files
authored
Merge pull request #8 from Unsupervisedcom/upstream-v0.6.0
Upstream v0.6.0
2 parents be42d78 + 04799f1 commit 51dcc80

File tree

188 files changed

+11159
-2806
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

188 files changed

+11159
-2806
lines changed

.github/ISSUE_TEMPLATE/bug_report.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ body:
2727
options:
2828
- label: I have searched the existing issues and discussions.
2929
required: true
30+
- label: I am using the latest version of Open WebUI.
31+
required: true
3032

3133
- type: dropdown
3234
id: installation-method
@@ -83,9 +85,9 @@ body:
8385
required: true
8486
- label: I am using the latest version of **both** Open WebUI and Ollama.
8587
required: true
86-
- label: I have checked the browser console logs.
88+
- label: I have included the browser console logs.
8789
required: true
88-
- label: I have checked the Docker container logs.
90+
- label: I have included the Docker container logs.
8991
required: true
9092
- label: I have listed steps to reproduce the bug in detail.
9193
required: true
@@ -110,7 +112,7 @@ body:
110112
id: reproduction-steps
111113
attributes:
112114
label: Steps to Reproduce
113-
description: Provide step-by-step instructions to reproduce the issue.
115+
description: Providing clear, step-by-step instructions helps us reproduce and fix the issue faster. If we can't reproduce it, we can't fix it.
114116
placeholder: |
115117
1. Go to '...'
116118
2. Click on '...'

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
blank_issues_enabled: false

.github/pull_request_template.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
- [ ] **Changelog:** Ensure a changelog entry following the format of [Keep a Changelog](https://keepachangelog.com/) is added at the bottom of the PR description.
1010
- [ ] **Documentation:** Have you updated relevant documentation [Open WebUI Docs](https://github.com/open-webui/docs), or other documentation sources?
1111
- [ ] **Dependencies:** Are there any new dependencies? Have you updated the dependency versions in the documentation?
12-
- [ ] **Testing:** Have you written and run sufficient tests for validating the changes?
12+
- [ ] **Testing:** Have you written and run sufficient tests to validate the changes?
1313
- [ ] **Code review:** Have you performed a self-review of your code, addressing any coding standard issues and ensuring adherence to the project's coding standards?
14-
- [ ] **Prefix:** To cleary categorize this pull request, prefix the pull request title, using one of the following:
14+
- [ ] **Prefix:** To clearly categorize this pull request, prefix the pull request title using one of the following:
1515
- **BREAKING CHANGE**: Significant changes that may affect compatibility
1616
- **build**: Changes that affect the build system or external dependencies
1717
- **ci**: Changes to our continuous integration processes or workflows
@@ -22,7 +22,7 @@
2222
- **i18n**: Internationalization or localization changes
2323
- **perf**: Performance improvement
2424
- **refactor**: Code restructuring for better maintainability, readability, or scalability
25-
- **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc.)
25+
- **style**: Changes that do not affect the meaning of the code (white space, formatting, missing semi-colons, etc.)
2626
- **test**: Adding missing tests or correcting existing tests
2727
- **WIP**: Work in progress, a temporary label for incomplete or ongoing work
2828

CHANGELOG.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,55 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.6.0] - 2025-03-31
9+
10+
### Added
11+
12+
- 🧩 **External Tool Server Support via OpenAPI**: Connect Open WebUI to any OpenAPI-compatible REST server instantly—offering immediate integration with thousands of developer tools, SDKs, and SaaS systems for powerful extensibility. Learn more: https://github.com/open-webui/openapi-servers
13+
- 🛠️ **MCP Server Support via MCPO**: You can now convert and expose your internal MCP tools as interoperable OpenAPI HTTP servers within Open WebUI for seamless, plug-n-play AI toolchain creation. Learn more: https://github.com/open-webui/mcpo
14+
- 📨 **/messages Chat API Endpoint Support**: For power users building external AI systems, new endpoints allow precise control of messages asynchronously—feed long-running external responses into Open WebUI chats without coupling with the frontend.
15+
- 📝 **Client-Side PDF Generation**: PDF exports are now generated fully client-side for drastically improved output quality—perfect for saving conversations or documents.
16+
- 💼 **Enforced Temporary Chats Mode**: Admins can now enforce temporary chat sessions by default to align with stringent data retention and compliance requirements.
17+
- 🌍 **Public Resource Sharing Permission Controls**: Fine-grained user group permissions now allow enabling/disabling public sharing for models, knowledge, prompts, and tools—ideal for privacy, team control, and internal deployments.
18+
- 📦 **Custom pip Options for Tools/Functions**: You can now specify custom pip installation options with "PIP_OPTIONS", "PIP_PACKAGE_INDEX_OPTIONS" environment variables—improving compatibility, support for private indexes, and better control over Python environments.
19+
- 🔢 **Editable Message Counter**: You can now double-click the message count number and jump straight to editing the index—quickly navigate complex chats or regenerate specific messages precisely.
20+
- 🧠 **Embedding Prefix Support Added**: Add custom prefixes to your embeddings for instruct-style tokens, enabling stronger model alignment and more consistent RAG performance.
21+
- 🙈 **Ability to Hide Base Models**: Optionally hide base models from the UI, helping users streamline model visibility and limit access to only usable endpoints..
22+
- 📚 **Docling Content Extraction Support**: Open WebUI now supports Docling as a content extraction engine, enabling smarter and more accurate parsing of complex file formats—ideal for advanced document understanding and Retrieval-Augmented Generation (RAG) workflows.
23+
- 🗃️ **Redis Sentinel Support Added**: Enhance deployment redundancy with support for Redis Sentinel for highly available, failover-safe Redis-based caching or pub/sub.
24+
- 📚 **JSON Schema Format for Ollama**: Added support for defining the format using JSON schema in Ollama-compatible models, improving flexibility and validation of model outputs.
25+
- 🔍 **Chat Sidebar Search "Clear” Button**: Quickly clear search filters in chat sidebar using the new ✖️ button—streamline your chat navigation with one click.
26+
- 🗂️ **Auto-Focus + Enter Submit for Folder Name**: When creating a new folder, the system automatically enters rename mode with name preselected—simplifying your org workflow.
27+
- 🧱 **Markdown Alerts Rendering**: Blockquotes with syntax hinting (e.g. ⚠️, ℹ️, ✅) now render styled Markdown alert banners, making messages and documentation more visually structured.
28+
- 🔁 **Hybrid Search Runs in Parallel Now**: Hybrid (BM25 + embedding) search components now run in parallel—dramatically reducing response times and speeding up document retrieval.
29+
- 📋 **Cleaner UI for Tool Call Display**: Optimized the visual layout of called tools inside chat messages for better clarity and reduced visual clutter.
30+
- 🧪 **Playwright Timeout Now Configurable**: Default timeout for Playwright processes is now shorter and adjustable via environment variables—making web scraping more robust and tunable to environments.
31+
- 📈 **OpenTelemetry Support for Observability**: Open WebUI now integrates with OpenTelemetry, allowing you to connect with tools like Grafana, Jaeger, or Prometheus for detailed performance insights and real-time visibility—entirely opt-in and fully self-hosted. Even if enabled, no data is ever sent to us, ensuring your privacy and ownership over all telemetry data.
32+
- 🛠 **General UI Enhancements & UX Polish**: Numerous refinements across sidebar, code blocks, modal interactions, button alignment, scrollbar visibility, and folder behavior improve overall fluidity and usability of the interface.
33+
- 🧱 **General Backend Refactoring**: Numerous backend components have been refactored to improve stability, maintainability, and performance—ensuring a more consistent and reliable system across all features.
34+
- 🌍 **Internationalization Language Support Updates**: Added Estonian and Galician languages, improved Spanish (fully revised), Traditional Chinese, Simplified Chinese, Turkish, Catalan, Ukrainian, and German for a more localized and inclusive interface.
35+
36+
### Fixed
37+
38+
- 🧑‍💻 **Firefox Input Height Bug**: Text input in Firefox now maintains proper height, ensuring message boxes look consistent and behave predictably.
39+
- 🧾 **Tika Blank Line Bug**: PDFs processed with Apache Tika 3.1.0.0 no longer introduce excessive blank lines—improving RAG output quality and visual cleanliness.
40+
- 🧪 **CSV Loader Encoding Issues**: CSV files with unknown encodings now automatically detect character sets, resolving import errors in non-UTF-8 datasets.
41+
-**LDAP Auth Config Fix**: Path to certificate file is now optional for LDAP setups, fixing authentication trouble for users without preconfigured cert paths.
42+
- 📥 **File Deletion in Bypass Mode**: Resolved issue where files couldn’t be deleted from knowledge when “bypass embedding” mode was enabled.
43+
- 🧩 **Hybrid Search Result Sorting & Deduplication Fixed**: Fixed citation and sorting issues in RAG hybrid and reranker modes, ensuring retrieved documents are shown in correct order per score.
44+
- 🧷 **Model Export/Import Broken for a Single Model**: Fixed bug where individual models couldn’t be exported or re-imported, restoring full portability.
45+
- 📫 **Auth Redirect Fix**: Logged-in users are now routed properly without unnecessary login prompts when already authenticated.
46+
47+
### Changed
48+
49+
- 🧠 **Prompt Autocompletion Disabled By Default**: Autocomplete suggestions while typing are now disabled unless explicitly re-enabled in user preferences—reduces distractions while composing prompts for advanced users.
50+
- 🧾 **Normalize Citation Numbering**: Source citations now properly begin from "1" instead of "0"—improving consistency and professional presentation in AI outputs.
51+
- 📚 **Improved Error Handling from Pipelines**: Pipelines now show the actual returned error message from failed tasks rather than generic "Connection closed"—making debugging far more user-friendly.
52+
53+
### Removed
54+
55+
- 🧾 **ENABLE_AUDIT_LOGS Setting Removed**: Deprecated setting “ENABLE_AUDIT_LOGS” has been fully removed—now controlled via “AUDIT_LOG_LEVEL” instead.
56+
857
## [0.5.20] - 2025-03-05
958

1059
### Added

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ RUN if [ "$USE_OLLAMA" = "true" ]; then \
132132
# install python dependencies
133133
COPY --chown=$UID:$GID ./backend/requirements.txt ./requirements.txt
134134

135-
RUN pip3 install uv && \
135+
RUN pip3 install --no-cache-dir uv && \
136136
if [ "$USE_CUDA" = "true" ]; then \
137137
# If you use CUDA the whisper and embedding model will be downloaded on first use
138138
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/$USE_CUDA_DOCKER_VER --no-cache-dir && \

backend/open_webui/config.py

Lines changed: 121 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import os
44
import shutil
55
import base64
6+
import redis
67

78
from datetime import datetime
89
from pathlib import Path
@@ -17,6 +18,9 @@
1718
DATA_DIR,
1819
DATABASE_URL,
1920
ENV,
21+
REDIS_URL,
22+
REDIS_SENTINEL_HOSTS,
23+
REDIS_SENTINEL_PORT,
2024
FRONTEND_BUILD_DIR,
2125
OFFLINE_MODE,
2226
OPEN_WEBUI_DIR,
@@ -26,6 +30,7 @@
2630
log,
2731
)
2832
from open_webui.internal.db import Base, get_db
33+
from open_webui.utils.redis import get_redis_connection
2934

3035

3136
class EndpointFilter(logging.Filter):
@@ -248,9 +253,17 @@ def save(self):
248253

249254
class AppConfig:
250255
_state: dict[str, PersistentConfig]
256+
_redis: Optional[redis.Redis] = None
251257

252-
def __init__(self):
258+
def __init__(
259+
self, redis_url: Optional[str] = None, redis_sentinels: Optional[list] = []
260+
):
253261
super().__setattr__("_state", {})
262+
if redis_url:
263+
super().__setattr__(
264+
"_redis",
265+
get_redis_connection(redis_url, redis_sentinels, decode_responses=True),
266+
)
254267

255268
def __setattr__(self, key, value):
256269
if isinstance(value, PersistentConfig):
@@ -259,7 +272,31 @@ def __setattr__(self, key, value):
259272
self._state[key].value = value
260273
self._state[key].save()
261274

275+
if self._redis:
276+
redis_key = f"open-webui:config:{key}"
277+
self._redis.set(redis_key, json.dumps(self._state[key].value))
278+
262279
def __getattr__(self, key):
280+
if key not in self._state:
281+
raise AttributeError(f"Config key '{key}' not found")
282+
283+
# If Redis is available, check for an updated value
284+
if self._redis:
285+
redis_key = f"open-webui:config:{key}"
286+
redis_value = self._redis.get(redis_key)
287+
288+
if redis_value is not None:
289+
try:
290+
decoded_value = json.loads(redis_value)
291+
292+
# Update the in-memory value if different
293+
if self._state[key].value != decoded_value:
294+
self._state[key].value = decoded_value
295+
log.info(f"Updated {key} from Redis: {decoded_value}")
296+
297+
except json.JSONDecodeError:
298+
log.error(f"Invalid JSON format in Redis for {key}: {redis_value}")
299+
263300
return self._state[key].value
264301

265302

@@ -943,6 +980,35 @@ def oidc_oauth_register(client):
943980
os.environ.get("USER_PERMISSIONS_WORKSPACE_TOOLS_ACCESS", "False").lower() == "true"
944981
)
945982

983+
USER_PERMISSIONS_WORKSPACE_MODELS_ALLOW_PUBLIC_SHARING = (
984+
os.environ.get(
985+
"USER_PERMISSIONS_WORKSPACE_MODELS_ALLOW_PUBLIC_SHARING", "False"
986+
).lower()
987+
== "true"
988+
)
989+
990+
USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ALLOW_PUBLIC_SHARING = (
991+
os.environ.get(
992+
"USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ALLOW_PUBLIC_SHARING", "False"
993+
).lower()
994+
== "true"
995+
)
996+
997+
USER_PERMISSIONS_WORKSPACE_PROMPTS_ALLOW_PUBLIC_SHARING = (
998+
os.environ.get(
999+
"USER_PERMISSIONS_WORKSPACE_PROMPTS_ALLOW_PUBLIC_SHARING", "False"
1000+
).lower()
1001+
== "true"
1002+
)
1003+
1004+
USER_PERMISSIONS_WORKSPACE_TOOLS_ALLOW_PUBLIC_SHARING = (
1005+
os.environ.get(
1006+
"USER_PERMISSIONS_WORKSPACE_TOOLS_ALLOW_PUBLIC_SHARING", "False"
1007+
).lower()
1008+
== "true"
1009+
)
1010+
1011+
9461012
USER_PERMISSIONS_CHAT_CONTROLS = (
9471013
os.environ.get("USER_PERMISSIONS_CHAT_CONTROLS", "True").lower() == "true"
9481014
)
@@ -963,6 +1029,11 @@ def oidc_oauth_register(client):
9631029
os.environ.get("USER_PERMISSIONS_CHAT_TEMPORARY", "True").lower() == "true"
9641030
)
9651031

1032+
USER_PERMISSIONS_CHAT_TEMPORARY_ENFORCED = (
1033+
os.environ.get("USER_PERMISSIONS_CHAT_TEMPORARY_ENFORCED", "False").lower()
1034+
== "true"
1035+
)
1036+
9661037
USER_PERMISSIONS_FEATURES_WEB_SEARCH = (
9671038
os.environ.get("USER_PERMISSIONS_FEATURES_WEB_SEARCH", "True").lower() == "true"
9681039
)
@@ -985,12 +1056,19 @@ def oidc_oauth_register(client):
9851056
"prompts": USER_PERMISSIONS_WORKSPACE_PROMPTS_ACCESS,
9861057
"tools": USER_PERMISSIONS_WORKSPACE_TOOLS_ACCESS,
9871058
},
1059+
"sharing": {
1060+
"public_models": USER_PERMISSIONS_WORKSPACE_MODELS_ALLOW_PUBLIC_SHARING,
1061+
"public_knowledge": USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ALLOW_PUBLIC_SHARING,
1062+
"public_prompts": USER_PERMISSIONS_WORKSPACE_PROMPTS_ALLOW_PUBLIC_SHARING,
1063+
"public_tools": USER_PERMISSIONS_WORKSPACE_TOOLS_ALLOW_PUBLIC_SHARING,
1064+
},
9881065
"chat": {
9891066
"controls": USER_PERMISSIONS_CHAT_CONTROLS,
9901067
"file_upload": USER_PERMISSIONS_CHAT_FILE_UPLOAD,
9911068
"delete": USER_PERMISSIONS_CHAT_DELETE,
9921069
"edit": USER_PERMISSIONS_CHAT_EDIT,
9931070
"temporary": USER_PERMISSIONS_CHAT_TEMPORARY,
1071+
"temporary_enforced": USER_PERMISSIONS_CHAT_TEMPORARY_ENFORCED,
9941072
},
9951073
"features": {
9961074
"web_search": USER_PERMISSIONS_FEATURES_WEB_SEARCH,
@@ -1055,6 +1133,12 @@ def oidc_oauth_register(client):
10551133
os.environ.get("ENABLE_MESSAGE_RATING", "True").lower() == "true",
10561134
)
10571135

1136+
ENABLE_USER_WEBHOOKS = PersistentConfig(
1137+
"ENABLE_USER_WEBHOOKS",
1138+
"ui.enable_user_webhooks",
1139+
os.environ.get("ENABLE_USER_WEBHOOKS", "True").lower() == "true",
1140+
)
1141+
10581142

10591143
def validate_cors_origins(origins):
10601144
for origin in origins:
@@ -1276,7 +1360,7 @@ class BannerModel(BaseModel):
12761360
ENABLE_AUTOCOMPLETE_GENERATION = PersistentConfig(
12771361
"ENABLE_AUTOCOMPLETE_GENERATION",
12781362
"task.autocomplete.enable",
1279-
os.environ.get("ENABLE_AUTOCOMPLETE_GENERATION", "True").lower() == "true",
1363+
os.environ.get("ENABLE_AUTOCOMPLETE_GENERATION", "False").lower() == "true",
12801364
)
12811365

12821366
AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH = PersistentConfig(
@@ -1548,8 +1632,10 @@ class BannerModel(BaseModel):
15481632

15491633
# OpenSearch
15501634
OPENSEARCH_URI = os.environ.get("OPENSEARCH_URI", "https://localhost:9200")
1551-
OPENSEARCH_SSL = os.environ.get("OPENSEARCH_SSL", True)
1552-
OPENSEARCH_CERT_VERIFY = os.environ.get("OPENSEARCH_CERT_VERIFY", False)
1635+
OPENSEARCH_SSL = os.environ.get("OPENSEARCH_SSL", "true").lower() == "true"
1636+
OPENSEARCH_CERT_VERIFY = (
1637+
os.environ.get("OPENSEARCH_CERT_VERIFY", "false").lower() == "true"
1638+
)
15531639
OPENSEARCH_USERNAME = os.environ.get("OPENSEARCH_USERNAME", None)
15541640
OPENSEARCH_PASSWORD = os.environ.get("OPENSEARCH_PASSWORD", None)
15551641

@@ -1623,6 +1709,12 @@ class BannerModel(BaseModel):
16231709
os.getenv("TIKA_SERVER_URL", "http://tika:9998"), # Default for sidecar deployment
16241710
)
16251711

1712+
DOCLING_SERVER_URL = PersistentConfig(
1713+
"DOCLING_SERVER_URL",
1714+
"rag.docling_server_url",
1715+
os.getenv("DOCLING_SERVER_URL", "http://docling:5001"),
1716+
)
1717+
16261718
DOCUMENT_INTELLIGENCE_ENDPOINT = PersistentConfig(
16271719
"DOCUMENT_INTELLIGENCE_ENDPOINT",
16281720
"rag.document_intelligence_endpoint",
@@ -1646,6 +1738,11 @@ class BannerModel(BaseModel):
16461738
RAG_TOP_K = PersistentConfig(
16471739
"RAG_TOP_K", "rag.top_k", int(os.environ.get("RAG_TOP_K", "3"))
16481740
)
1741+
RAG_TOP_K_RERANKER = PersistentConfig(
1742+
"RAG_TOP_K_RERANKER",
1743+
"rag.top_k_reranker",
1744+
int(os.environ.get("RAG_TOP_K_RERANKER", "3")),
1745+
)
16491746
RAG_RELEVANCE_THRESHOLD = PersistentConfig(
16501747
"RAG_RELEVANCE_THRESHOLD",
16511748
"rag.relevance_threshold",
@@ -1727,6 +1824,14 @@ class BannerModel(BaseModel):
17271824
),
17281825
)
17291826

1827+
RAG_EMBEDDING_QUERY_PREFIX = os.environ.get("RAG_EMBEDDING_QUERY_PREFIX", None)
1828+
1829+
RAG_EMBEDDING_CONTENT_PREFIX = os.environ.get("RAG_EMBEDDING_CONTENT_PREFIX", None)
1830+
1831+
RAG_EMBEDDING_PREFIX_FIELD_NAME = os.environ.get(
1832+
"RAG_EMBEDDING_PREFIX_FIELD_NAME", None
1833+
)
1834+
17301835
RAG_RERANKING_MODEL = PersistentConfig(
17311836
"RAG_RERANKING_MODEL",
17321837
"rag.reranking_model",
@@ -1950,6 +2055,12 @@ class BannerModel(BaseModel):
19502055
os.getenv("TAVILY_API_KEY", ""),
19512056
)
19522057

2058+
TAVILY_EXTRACT_DEPTH = PersistentConfig(
2059+
"TAVILY_EXTRACT_DEPTH",
2060+
"rag.web.search.tavily_extract_depth",
2061+
os.getenv("TAVILY_EXTRACT_DEPTH", "basic"),
2062+
)
2063+
19532064
JINA_API_KEY = PersistentConfig(
19542065
"JINA_API_KEY",
19552066
"rag.web.search.jina_api_key",
@@ -2036,6 +2147,12 @@ class BannerModel(BaseModel):
20362147
os.environ.get("PLAYWRIGHT_WS_URI", None),
20372148
)
20382149

2150+
PLAYWRIGHT_TIMEOUT = PersistentConfig(
2151+
"PLAYWRIGHT_TIMEOUT",
2152+
"rag.web.loader.engine.playwright.timeout",
2153+
int(os.environ.get("PLAYWRIGHT_TIMEOUT", "10")),
2154+
)
2155+
20392156
FIRECRAWL_API_KEY = PersistentConfig(
20402157
"FIRECRAWL_API_KEY",
20412158
"firecrawl.api_key",

0 commit comments

Comments
 (0)