Skip to content

Commit 24be96a

Browse files
authored
Merge pull request #1 from open-webui/main
Upgrade to v0.6.11
2 parents bb62bd9 + 737dc77 commit 24be96a

File tree

159 files changed

+6080
-3456
lines changed

Some content is hidden

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

159 files changed

+6080
-3456
lines changed

.github/ISSUE_TEMPLATE/bug_report.yaml

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,20 @@ body:
8989
required: true
9090
- label: I have included the Docker container logs.
9191
required: true
92-
- label: I have listed steps to reproduce the bug in detail.
92+
- label: I have **provided every relevant configuration, setting, and environment variable used in my setup.**
93+
required: true
94+
- label: I have clearly **listed every relevant configuration, custom setting, environment variable, and command-line option that influences my setup** (such as Docker Compose overrides, .env values, browser settings, authentication configurations, etc).
95+
required: true
96+
- label: |
97+
I have documented **step-by-step reproduction instructions that are precise, sequential, and leave nothing to interpretation**. My steps:
98+
- Start with the initial platform/version/OS and dependencies used,
99+
- Specify exact install/launch/configure commands,
100+
- List URLs visited, user input (incl. example values/emails/passwords if needed),
101+
- Describe all options and toggles enabled or changed,
102+
- Include any files or environmental changes,
103+
- Identify the expected and actual result at each stage,
104+
- Ensure any reasonably skilled user can follow and hit the same issue.
93105
required: true
94-
95106
- type: textarea
96107
id: expected-behavior
97108
attributes:
@@ -112,15 +123,25 @@ body:
112123
id: reproduction-steps
113124
attributes:
114125
label: Steps to Reproduce
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.
126+
description: |
127+
Please provide a **very detailed, step-by-step guide** to reproduce the issue. Your instructions should be so clear and precise that anyone can follow them without guesswork. Include every relevant detail—settings, configuration options, exact commands used, values entered, and any prerequisites or environment variables.
128+
**If full reproduction steps and all relevant settings are not provided, your issue may not be addressed.**
129+
116130
placeholder: |
117-
1. Go to '...'
118-
2. Click on '...'
119-
3. Scroll down to '...'
120-
4. See the error message '...'
131+
Example (include every detail):
132+
1. Start with a clean Ubuntu 22.04 install.
133+
2. Install Docker v24.0.5 and start the service.
134+
3. Clone the Open WebUI repo (git clone ...).
135+
4. Use the Docker Compose file without modifications.
136+
5. Open browser Chrome 115.0 in incognito mode.
137+
6. Go to http://localhost:8080 and log in with user "[email protected]".
138+
7. Set the language to "English" and theme to "Dark".
139+
8. Attempt to connect to Ollama at "http://localhost:11434".
140+
9. Observe that the error message "Connection refused" appears at the top right.
141+
142+
Please list each step carefully and include all relevant configuration, settings, and options.
121143
validations:
122144
required: true
123-
124145
- type: textarea
125146
id: logs-screenshots
126147
attributes:

CHANGELOG.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,54 @@ 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.11] - 2025-05-27
9+
10+
### Added
11+
12+
- 🟢 **Ollama Model Status Indicator in Model Selector**: Instantly see which Ollama models are currently loaded with a clear indicator in the model selector, helping you stay organized and optimize local model usage.
13+
- 🗑️ **Unload Ollama Model Directly from Model Selector**: Easily release memory and resources by unloading any loaded Ollama model right in the model selector—streamline hardware management without switching pages.
14+
- 🗣️ **User-Configurable Speech-to-Text Language Setting**: Improve transcription accuracy by letting individual users explicitly set their preferred STT language in their settings—ideal for multilingual teams and clear audio capture.
15+
-**Granular Audio Playback Speed Control**: Instead of just presets, you can now choose granular audio speed using a numeric input, giving you complete control over playback pace in transcriptions and media reviews.
16+
- 📦 **GZip, Brotli, ZStd Compression Middleware**: Enjoy significantly faster page loads and reduced bandwidth usage with new server-side compression—giving users a snappier, more efficient experience.
17+
- 🏷️ **Configurable Weight for BM25 in Hybrid Search**: Fine-tune search relevance by adjusting the weight for BM25 inside hybrid search from the UI, letting you tailor knowledge search results to your workflow.
18+
- 🧪 **Bypass File Creation with CTRL + SHIFT + V**: When “Paste Large Text as File” is enabled, use CTRL + SHIFT + V to skip the file creation dialog and instantly upload text as a file—perfect for rapid document prep.
19+
- 🌐 **Bypass Web Loader in Web Search**: Choose to bypass web content loading and use snippets directly in web search for faster, more reliable results when page loads are slow or blocked.
20+
- 🚀 **Environment Variable: WEBUI_AUTH_TRUSTED_GROUPS_HEADER**: Now sync and manage user groups directly via trusted HTTP header, unlocking smoother single sign-on and identity integrations for organizations.
21+
- 🏢 **Workspace Models Visibility Controls**: You can now hide workspace-level models from both the model selector and shared environments—keep your team focused and reduce clutter from rarely-used endpoints.
22+
- 🛡️ **Copy Model Link**: You can now copy a direct link to any model—including those hidden from the selector—making sharing and onboarding others more seamless.
23+
- 🔗 **Load Function Directly from URL**: Simplify custom function management—just paste any GitHub function URL into Open WebUI and import new functions in seconds.
24+
- ⚙️ **Custom Name/Description for External Tool Servers**: Personalize and clarify external tool servers by assigning custom names and descriptions, making it easier to manage integrations in large-scale workspaces.
25+
- 🌍 **Custom OpenAPI JSON URL Support for Tool Servers**: Supports specifying any custom OpenAPI JSON URL, unlocking more flexible integration with any backend for tool calls.
26+
- 📊 **Source Field Now Displays in Non-Streaming Responses with Attachments**: When files or knowledge are attached, the "source" field now appears for all responses, even in non-streaming mode—enabling improved citation workflow.
27+
- 🎛 **Pinned Chats**: Reduced payload size on pinned chat requests—leading to faster load times and less data usage, especially on busy warehouses.
28+
- 🛠 **Import/Export Default Prompt Suggestions**: Enjoy one-click import/export of prompt suggestions, making it much easier to share, reuse, and manage best practices across teams or deployments.
29+
- 🍰 **Banners Now Sortable from Admin Settings**: Quickly re-order or prioritize banners, letting you highlight the most critical info for your team.
30+
- 🛠 **Advanced Chat Parameters—Clearer Ollama Support Labels**: Parameters and advanced settings now explicitly indicate if they are Ollama-specific, reducing confusion and improving setup accuracy.
31+
- 🤏 **Scroll Bar Thumb Improved for Better Visibility**: Enhanced scrollbar styling makes navigation more accessible and visually intuitive.
32+
- 🗄️ **Modal Redesign for Archived and User Chat Listings**: Clean, modern modal interface for browsing archived and user-specific chats makes locating conversations faster and more pleasant.
33+
- 📝 **Add/Edit Memory Modal UX**: Memory modals are now larger and have resizable input fields, supporting easier editing of long or complex memory content.
34+
- 🏆 **Translation & Localization Enhancements**: Major upgrades to Chinese (Simplified & Traditional), Korean, Russian, German, Danish, Finnish—not just fixing typos, but consistency, tone, and terminology for a more natural native-language experience.
35+
-**General Backend Stability & Security Enhancements**: Various backend refinements ensure a more resilient, reliable, and secure platform for smoother operation and peace of mind.
36+
37+
### Fixed
38+
39+
- 🖼️ **Image Generation with Allowed File Extensions Now Works Reliably**: Ensure seamless image generation even when strict file extension rules are set—no more blocked creative workflows due to technical hiccups.
40+
- 🗂 **Remove Leading Dot for File Extension Check**: Fixed an issue where file validation failed because of a leading dot, making file uploads and knowledge management more robust.
41+
- 🏷️ **Correct Local/External Model Classification**: The platform now accurately distinguishes between local and external models—preventing local models from showing up as external (and vice versa)—ensuring seamless setup, clarity, and management of your AI model endpoints.
42+
- 📄 **External Document Loader Now Functions as Intended**: External document loaders are reliably invoked, ensuring smoother knowledge ingestion from external sources—expanding your RAG and knowledge workflows.
43+
- 🎯 **Correct Handling of Toggle Filters**: Toggle filters are now robustly managed, preventing accidental auto-activation and ensuring user preferences are always respected.
44+
- 🗃 **S3 Tagging Character Restrictions Fixed**: Tags for files in S3 now automatically meet Amazon’s allowed character set, avoiding upload errors and ensuring cross-cloud compatibility.
45+
- 🛡️ **Authentication Now Uses Password Hash When Duplicate Emails Exist**: Ensures account security and prevents access issues if duplicate emails are present in your system.
46+
47+
### Changed
48+
49+
- 🧩 **Admin Settings: OAuth Redirects Now Use WEBUI_URL**: The OAuth redirect URL is now based on the explicitly set WEBUI_URL, ensuring single sign-on and identity provider integrations always send users to the correct frontend.
50+
51+
### Removed
52+
53+
- 💡 **Duplicate/Typo Component Removals**: Obsolete components have been cleaned up, reducing confusion and improving overall code quality for the team.
54+
- 🚫 **Streaming Upsert in Pinecone Removed**: Removed streaming upsert references for better compatibility and future-proofing with latest Pinecone SDK updates.
55+
856
## [0.6.10] - 2025-05-19
957

1058
### Added

backend/open_webui/config.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,6 +1928,11 @@ class BannerModel(BaseModel):
19281928
"rag.relevance_threshold",
19291929
float(os.environ.get("RAG_RELEVANCE_THRESHOLD", "0.0")),
19301930
)
1931+
RAG_HYBRID_BM25_WEIGHT = PersistentConfig(
1932+
"RAG_HYBRID_BM25_WEIGHT",
1933+
"rag.hybrid_bm25_weight",
1934+
float(os.environ.get("RAG_HYBRID_BM25_WEIGHT", "0.5")),
1935+
)
19311936

19321937
ENABLE_RAG_HYBRID_SEARCH = PersistentConfig(
19331938
"ENABLE_RAG_HYBRID_SEARCH",
@@ -2177,6 +2182,12 @@ class BannerModel(BaseModel):
21772182
)
21782183

21792184

2185+
BYPASS_WEB_SEARCH_WEB_LOADER = PersistentConfig(
2186+
"BYPASS_WEB_SEARCH_WEB_LOADER",
2187+
"rag.web.search.bypass_web_loader",
2188+
os.getenv("BYPASS_WEB_SEARCH_WEB_LOADER", "False").lower() == "true",
2189+
)
2190+
21802191
WEB_SEARCH_RESULT_COUNT = PersistentConfig(
21812192
"WEB_SEARCH_RESULT_COUNT",
21822193
"rag.web.search.result_count",
@@ -2202,6 +2213,7 @@ class BannerModel(BaseModel):
22022213
int(os.getenv("WEB_SEARCH_CONCURRENT_REQUESTS", "10")),
22032214
)
22042215

2216+
22052217
WEB_LOADER_ENGINE = PersistentConfig(
22062218
"WEB_LOADER_ENGINE",
22072219
"rag.web.loader.engine",

backend/open_webui/env.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,10 @@ def parse_section(section):
349349
"WEBUI_AUTH_TRUSTED_EMAIL_HEADER", None
350350
)
351351
WEBUI_AUTH_TRUSTED_NAME_HEADER = os.environ.get("WEBUI_AUTH_TRUSTED_NAME_HEADER", None)
352+
WEBUI_AUTH_TRUSTED_GROUPS_HEADER = os.environ.get(
353+
"WEBUI_AUTH_TRUSTED_GROUPS_HEADER", None
354+
)
355+
352356

353357
BYPASS_MODEL_ACCESS_CONTROL = (
354358
os.environ.get("BYPASS_MODEL_ACCESS_CONTROL", "False").lower() == "true"

backend/open_webui/functions.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,8 @@
5454

5555
def get_function_module_by_id(request: Request, pipe_id: str):
5656
# Check if function is already loaded
57-
if pipe_id not in request.app.state.FUNCTIONS:
58-
function_module, _, _ = load_function_module_by_id(pipe_id)
59-
request.app.state.FUNCTIONS[pipe_id] = function_module
60-
else:
61-
function_module = request.app.state.FUNCTIONS[pipe_id]
57+
function_module, _, _ = load_function_module_by_id(pipe_id)
58+
request.app.state.FUNCTIONS[pipe_id] = function_module
6259

6360
if hasattr(function_module, "valves") and hasattr(function_module, "Valves"):
6461
valves = Functions.get_function_valves_by_id(pipe_id)

backend/open_webui/internal/wrappers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@ class ReconnectingPostgresqlDatabase(CustomReconnectMixin, PostgresqlDatabase):
4343

4444

4545
def register_connection(db_url):
46-
db = connect(db_url, unquote_password=True)
46+
db = connect(db_url, unquote_user=True, unquote_password=True)
4747
if isinstance(db, PostgresqlDatabase):
4848
# Enable autoconnect for SQLite databases, managed by Peewee
4949
db.autoconnect = True
5050
db.reuse_if_open = True
5151
log.info("Connected to PostgreSQL database")
5252

5353
# Get the connection details
54-
connection = parse(db_url, unquote_password=True)
54+
connection = parse(db_url, unquote_user=True, unquote_password=True)
5555

5656
# Use our custom database class that supports reconnection
5757
db = ReconnectingPostgresqlDatabase(**connection)

backend/open_webui/main.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
from fastapi.responses import JSONResponse, RedirectResponse
4141
from fastapi.staticfiles import StaticFiles
4242

43+
from starlette_compress import CompressMiddleware
44+
4345
from starlette.exceptions import HTTPException as StarletteHTTPException
4446
from starlette.middleware.base import BaseHTTPMiddleware
4547
from starlette.middleware.sessions import SessionMiddleware
@@ -196,7 +198,10 @@
196198
RAG_RERANKING_MODEL_TRUST_REMOTE_CODE,
197199
RAG_EMBEDDING_ENGINE,
198200
RAG_EMBEDDING_BATCH_SIZE,
201+
RAG_TOP_K,
202+
RAG_TOP_K_RERANKER,
199203
RAG_RELEVANCE_THRESHOLD,
204+
RAG_HYBRID_BM25_WEIGHT,
200205
RAG_ALLOWED_FILE_EXTENSIONS,
201206
RAG_FILE_MAX_COUNT,
202207
RAG_FILE_MAX_SIZE,
@@ -217,8 +222,6 @@
217222
DOCUMENT_INTELLIGENCE_ENDPOINT,
218223
DOCUMENT_INTELLIGENCE_KEY,
219224
MISTRAL_OCR_API_KEY,
220-
RAG_TOP_K,
221-
RAG_TOP_K_RERANKER,
222225
RAG_TEXT_SPLITTER,
223226
TIKTOKEN_ENCODING_NAME,
224227
PDF_EXTRACT_IMAGES,
@@ -228,6 +231,7 @@
228231
ENABLE_WEB_SEARCH,
229232
WEB_SEARCH_ENGINE,
230233
BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL,
234+
BYPASS_WEB_SEARCH_WEB_LOADER,
231235
WEB_SEARCH_RESULT_COUNT,
232236
WEB_SEARCH_CONCURRENT_REQUESTS,
233237
WEB_SEARCH_TRUST_ENV,
@@ -646,6 +650,7 @@ async def lifespan(app: FastAPI):
646650
app.state.config.TOP_K = RAG_TOP_K
647651
app.state.config.TOP_K_RERANKER = RAG_TOP_K_RERANKER
648652
app.state.config.RELEVANCE_THRESHOLD = RAG_RELEVANCE_THRESHOLD
653+
app.state.config.HYBRID_BM25_WEIGHT = RAG_HYBRID_BM25_WEIGHT
649654
app.state.config.ALLOWED_FILE_EXTENSIONS = RAG_ALLOWED_FILE_EXTENSIONS
650655
app.state.config.FILE_MAX_SIZE = RAG_FILE_MAX_SIZE
651656
app.state.config.FILE_MAX_COUNT = RAG_FILE_MAX_COUNT
@@ -707,6 +712,7 @@ async def lifespan(app: FastAPI):
707712
app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = (
708713
BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL
709714
)
715+
app.state.config.BYPASS_WEB_SEARCH_WEB_LOADER = BYPASS_WEB_SEARCH_WEB_LOADER
710716

711717
app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION = ENABLE_GOOGLE_DRIVE_INTEGRATION
712718
app.state.config.ENABLE_ONEDRIVE_INTEGRATION = ENABLE_ONEDRIVE_INTEGRATION
@@ -959,6 +965,7 @@ async def dispatch(self, request: Request, call_next):
959965

960966

961967
# Add the middleware to the app
968+
app.add_middleware(CompressMiddleware)
962969
app.add_middleware(RedirectMiddleware)
963970
app.add_middleware(SecurityHeadersMiddleware)
964971

backend/open_webui/models/auths.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,16 @@ def insert_new_auth(
129129

130130
def authenticate_user(self, email: str, password: str) -> Optional[UserModel]:
131131
log.info(f"authenticate_user: {email}")
132+
133+
user = Users.get_user_by_email(email)
134+
if not user:
135+
return None
136+
132137
try:
133138
with get_db() as db:
134-
auth = db.query(Auth).filter_by(email=email, active=True).first()
139+
auth = db.query(Auth).filter_by(id=user.id, active=True).first()
135140
if auth:
136141
if verify_password(password, auth.password):
137-
user = Users.get_user_by_id(auth.id)
138142
return user
139143
else:
140144
return None
@@ -155,8 +159,8 @@ def authenticate_user_by_api_key(self, api_key: str) -> Optional[UserModel]:
155159
except Exception:
156160
return False
157161

158-
def authenticate_user_by_trusted_header(self, email: str) -> Optional[UserModel]:
159-
log.info(f"authenticate_user_by_trusted_header: {email}")
162+
def authenticate_user_by_email(self, email: str) -> Optional[UserModel]:
163+
log.info(f"authenticate_user_by_email: {email}")
160164
try:
161165
with get_db() as db:
162166
auth = db.query(Auth).filter_by(email=email, active=True).first()

backend/open_webui/models/chats.py

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -377,22 +377,47 @@ def archive_all_chats_by_user_id(self, user_id: str) -> bool:
377377
return False
378378

379379
def get_archived_chat_list_by_user_id(
380-
self, user_id: str, skip: int = 0, limit: int = 50
380+
self,
381+
user_id: str,
382+
filter: Optional[dict] = None,
383+
skip: int = 0,
384+
limit: int = 50,
381385
) -> list[ChatModel]:
386+
382387
with get_db() as db:
383-
all_chats = (
384-
db.query(Chat)
385-
.filter_by(user_id=user_id, archived=True)
386-
.order_by(Chat.updated_at.desc())
387-
# .limit(limit).offset(skip)
388-
.all()
389-
)
388+
query = db.query(Chat).filter_by(user_id=user_id, archived=True)
389+
390+
if filter:
391+
query_key = filter.get("query")
392+
if query_key:
393+
query = query.filter(Chat.title.ilike(f"%{query_key}%"))
394+
395+
order_by = filter.get("order_by")
396+
direction = filter.get("direction")
397+
398+
if order_by and direction and getattr(Chat, order_by):
399+
if direction.lower() == "asc":
400+
query = query.order_by(getattr(Chat, order_by).asc())
401+
elif direction.lower() == "desc":
402+
query = query.order_by(getattr(Chat, order_by).desc())
403+
else:
404+
raise ValueError("Invalid direction for ordering")
405+
else:
406+
query = query.order_by(Chat.updated_at.desc())
407+
408+
if skip:
409+
query = query.offset(skip)
410+
if limit:
411+
query = query.limit(limit)
412+
413+
all_chats = query.all()
390414
return [ChatModel.model_validate(chat) for chat in all_chats]
391415

392416
def get_chat_list_by_user_id(
393417
self,
394418
user_id: str,
395419
include_archived: bool = False,
420+
filter: Optional[dict] = None,
396421
skip: int = 0,
397422
limit: int = 50,
398423
) -> list[ChatModel]:
@@ -401,7 +426,23 @@ def get_chat_list_by_user_id(
401426
if not include_archived:
402427
query = query.filter_by(archived=False)
403428

404-
query = query.order_by(Chat.updated_at.desc())
429+
if filter:
430+
query_key = filter.get("query")
431+
if query_key:
432+
query = query.filter(Chat.title.ilike(f"%{query_key}%"))
433+
434+
order_by = filter.get("order_by")
435+
direction = filter.get("direction")
436+
437+
if order_by and direction and getattr(Chat, order_by):
438+
if direction.lower() == "asc":
439+
query = query.order_by(getattr(Chat, order_by).asc())
440+
elif direction.lower() == "desc":
441+
query = query.order_by(getattr(Chat, order_by).desc())
442+
else:
443+
raise ValueError("Invalid direction for ordering")
444+
else:
445+
query = query.order_by(Chat.updated_at.desc())
405446

406447
if skip:
407448
query = query.offset(skip)
@@ -542,7 +583,9 @@ def get_chats_by_user_id_and_search_text(
542583
search_text = search_text.lower().strip()
543584

544585
if not search_text:
545-
return self.get_chat_list_by_user_id(user_id, include_archived, skip, limit)
586+
return self.get_chat_list_by_user_id(
587+
user_id, include_archived, filter={}, skip=skip, limit=limit
588+
)
546589

547590
search_text_words = search_text.split(" ")
548591

0 commit comments

Comments
 (0)