Skip to content

Groups #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1,990 commits into
base: coderabbitai/docstrings/4269df0
Choose a base branch
from
Open

Conversation

arthrod
Copy link
Owner

@arthrod arthrod commented Feb 19, 2025

Pull Request Checklist

Note to first-time contributors: Please open a discussion post in Discussions and describe your changes before submitting a pull request.

Before submitting, make sure you've checked the following:

  • Target branch: Please verify that the pull request targets the dev branch.
  • Description: Provide a concise description of the changes made in this pull request.
  • Changelog: Ensure a changelog entry following the format of Keep a Changelog is added at the bottom of the PR description.
  • Documentation: Have you updated relevant documentation Open WebUI Docs, or other documentation sources?
  • Dependencies: Are there any new dependencies? Have you updated the dependency versions in the documentation?
  • Testing: Have you written and run sufficient tests for validating the changes?
  • 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?
  • Prefix: To cleary categorize this pull request, prefix the pull request title, using one of the following:
    • BREAKING CHANGE: Significant changes that may affect compatibility
    • build: Changes that affect the build system or external dependencies
    • ci: Changes to our continuous integration processes or workflows
    • chore: Refactor, cleanup, or other non-functional code changes
    • docs: Documentation update or addition
    • feat: Introduces a new feature or enhancement to the codebase
    • fix: Bug fix or error correction
    • i18n: Internationalization or localization changes
    • perf: Performance improvement
    • refactor: Code restructuring for better maintainability, readability, or scalability
    • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc.)
    • test: Adding missing tests or correcting existing tests
    • WIP: Work in progress, a temporary label for incomplete or ongoing work

Changelog Entry

Description

  • [Concisely describe the changes made in this pull request, including any relevant motivation and impact (e.g., fixing a bug, adding a feature, or improving performance)]

Added

  • [List any new features, functionalities, or additions]

Changed

  • [List any changes, updates, refactorings, or optimizations]

Deprecated

  • [List any deprecated functionality or features that have been removed]

Removed

  • [List any removed features, files, or functionalities]

Fixed

  • [List any fixes, corrections, or bug fixes]

Security

  • [List any new or updated security-related changes, including vulnerability fixes]

Breaking Changes

  • BREAKING CHANGE: [List any breaking changes affecting compatibility or functionality]

Additional Information

  • [Insert any additional context, notes, or explanations for the changes]
    • [Reference any related issues, commits, or other relevant information]

Screenshots or Videos

  • [Attach any relevant screenshots or videos demonstrating the changes]

Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

Copy link

coderabbitai bot commented Feb 19, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added capability for configuring direct connections and code execution through new admin settings.
    • Introduced image prompt generation and integrated Deepgram‐powered audio transcription.
    • Chat cloning now supports custom titles.
    • Rebranded the interface from “Open WebUI” to “Global Chat”.
  • Improvements

    • Enhanced UI styling and theme consistency.
    • Improved overall stability and error handling.
  • Documentation

    • Updated changelog and guides to reflect version [0.5.18].

Summary by CodeRabbit

  • New Features

    • Rebranded interface now presents “Global Chat.”
    • Enhanced search functionality with full context and smarter workflows.
    • Chat cloning now supports custom titles.
    • New admin settings for direct connectivity and code execution.
    • Audio transcription integrated with Deepgram.
  • Improvements

    • Updated documentation featuring an Enterprise Plan tip and an Updating Guide.
    • Refined UI and notification styling for a cleaner, more responsive experience.
    • Robust error handling and streamlined configuration management across services.

Walkthrough

This pull request introduces widespread improvements across CI/CD pipelines, backend logic, frontend components, and dependency management. Changes include updates to GitHub Actions workflows, version bumps in CHANGELOG and dependency files, new environment variables and configurations for direct connections and code execution, refined access control and messaging logic in backend modules, and several UI and styling adjustments in Svelte components. Docker-compose files are restructured as well. Overall, the update modernizes development workflows, adds new API endpoints and configuration options, and adjusts styling for better clarity and consistency.

Changes

File(s) Change Summary
.github/workflows/integration-test.disabled, .github/workflows/release-pypi.yml, CHANGELOG.md, Dockerfile, README.md Updated CI/CD pipelines: added environment variables, version bumps, Node.js version update, and added a new Enterprise tip section.
backend/open_webui/** (e.g., __init__.py, config.py, env.py, functions.py, constants.py, various routers, models, retrieval and utils) Extended CLI commands with a new version callback, strengthened OAuth and direct connection configurations, refined access control, updated parameter signatures, and integrated new functions for chat completion, file handling, and embedding user context.
docker-compose*.yaml, start.sh, start_windows.bat Restructured service definitions: replaced “ollama” with “searxng” and added a new “tika” service; added conditional blocks for Playwright browser installation.
requirements.txt, pyproject.toml, package.json, postcss.config.js, run-compose.sh, scripts/prepare-pyodide.js Upgraded various dependency versions and added new packages (e.g., RestrictedPython, google-cloud-storage, azure-storage-blob, transformers) and proxy support for Pyodide.
src/app.css, src/app.html, src/lib/components/**/*.svelte Updated styling and class names (e.g., changing “outline-none” to “outline-hidden”, tweaking rounded classes), rebranded from “Open WebUI” to “Global Chat”, and exposed new exported variables for connection options.
searxng/settings.yml, searxng/uwsgi.ini Added new configuration files for SearxNG search engine and a new uWSGI configuration.
Other test and utility files (e.g., test_provider.py, various utils modules) Introduced unit tests for storage providers and added new utility functions for permission handling, dynamic payload processing, and robust error management.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant "Admin Settings\n(Svelte Component)"
    participant "API Config\nEndpoints"
    participant Backend
    User->>Admin Settings: Update Direct Connections / Code Execution settings
    Admin Settings->>API Config Endpoints: Submit configuration update request
    API Config Endpoints->>Backend: Validate token and update configuration
    Backend-->>API Config Endpoints: Return updated config/status
    API Config Endpoints-->>Admin Settings: Success response
    Admin Settings-->>User: Display success notification
Loading

Poem

In the code’s vast garden, I hop along,
Adjusting pipelines, both robust and strong.
New keys and flags sprout where tests now gleam,
Data flows refined like a well-tuned stream.
With style updates and config snug and tight,
I, a little rabbit, dance in pure delight!
Bugs flee fast from my gentle, nimble bite.


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary or crs to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or cr anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@arthrod
Copy link
Owner Author

arthrod commented Feb 22, 2025

@coderabbitai review

Copy link

coderabbitai bot commented Feb 22, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 32

🔭 Outside diff range comments (1)
backend/open_webui/routers/memories.py (1)

19-20: ⚠️ Potential issue

Update test endpoint to include user parameter.

The test endpoint get_embeddings needs to be updated to include the user parameter for consistency with other changes.

 @router.get("/ef")
-async def get_embeddings(request: Request):
-    return {"result": request.app.state.EMBEDDING_FUNCTION("hello world")}
+async def get_embeddings(request: Request, user=Depends(get_verified_user)):
+    return {"result": request.app.state.EMBEDDING_FUNCTION("hello world", user)}
🧹 Nitpick comments (115)
pyproject.toml (3)

58-58: Transformers Dependency
The transformers library has been added without a specified version. It is advisable to pin a version or define a version range to ensure reproducible builds and avoid unexpected breaking changes in the future.


100-102: New Google API Dependencies
Added google-api-python-client, google-auth-httplib2, and google-auth-oauthlib without specified versions. Consider pinning these dependencies to mitigate risks from future breaking changes and ensure reproducible builds.


116-116: New Dependency: firecrawl-py
Added firecrawl-py==1.12.0. Ensure that the new functionality provided by this library is covered by appropriate tests and integrated correctly within your codebase.

backend/open_webui/retrieval/web/jina_search.py (2)

31-31: Cap count more explicitly or document the rationale.

The payload restricts count to a maximum of 10. This is likely intended, but ensure it is clearly documented or validated externally so that calling code is aware of this cap.


33-34: Check response for partial successes.

While response.raise_for_status() helps, consider verifying partial or unexpected response data (e.g., a truncated result set). For reliability, you might also handle JSON decoding errors separately if the API fails in non-2XX scenarios.

backend/open_webui/retrieval/web/google_pse.py (3)

20-30: Enforce or clarify the maximum count in docs/code.

The docstring indicates a maximum of 100 results, but there’s no explicit check for count <= 100. If count is greater than 100, the loop might continue, though subsequent pages might fail. Clarify this either by enforcing it in code or documenting what behavior to expect beyond 100 results.


34-35: Initialize container variables close to usage.

all_results = [] and start_index = 1 are logically tied to the pagination loop below. Consider grouping them with the loop for improved clarity and maintainability.


37-58: Validate pagination termination logic.

The while count > 0: condition and if not results: break approach is correct, but ensure it gracefully handles any intermittent errors or empty pages from the API. Consider adding a specific limit on how many pages you attempt.

src/lib/apis/utils/index.ts (4)

3-4: Remove or handle unused error variable.

The error variable is assigned but never used upon returning. You could eliminate it for clarity or rethrow it to maintain consistent error handling.

-export const getGravatarUrl = async (token: string, email: string) => {
-	let error = null;
+export const getGravatarUrl = async (token: string, email: string) => {
🧰 Tools
🪛 ESLint

[error] 4-4: 'error' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


26-58: Suggest consolidating error handling.

The new executeCode function effectively captures errors, but consider consolidating the .then(async ...) and .catch(...) logic into try/catch for improved readability and consistent control flow.


60-60: Apply consistent approach or remove leftover variable.

Like other functions, formatPythonCode sets an error variable, but usage patterns differ across the file. Maintaining a consistent or simpler approach would reduce confusion.


94-105: Handle large attachments for chat PDF.

downloadChatAsPDF sends logs via JSON. If messages is large, consider chunked approaches or compression. Otherwise, you risk request size limits or timeouts.

🧰 Tools
🪛 ESLint

[error] 95-95: 'error' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)

backend/open_webui/utils/code_interpreter.py (2)

98-99: Consider clarifying variable naming for outputs.

Renaming variables such as stdout, stderr, and result to more descriptive names (e.g., captured_stdout, captured_stderr, captured_result) could improve readability and maintainability without altering functionality.


131-133: Ensure closed WebSocket connection on timeout.

When a timeout occurs, the code appends a timeout message to stderr and breaks out of the loop. Consider explicitly closing the WebSocket to avoid potential resource leaks.

backend/open_webui/utils/payload.py (1)

14-14: Use shorter params.get("system") call.

The default value None is redundant. You can replace params.get("system", None) with params.get("system") to adhere to the static analysis suggestion.

🧰 Tools
🪛 Ruff (0.8.2)

14-14: Use params.get("system") instead of params.get("system", None)

Replace params.get("system", None) with params.get("system")

(SIM910)

src/lib/apis/openai/index.ts (2)

211-236: Reduce duplication with verify logic.

getOpenAIModelsDirect and the direct branch of verifyOpenAIConnection share similar fetching and error handling patterns. Consider extracting common behavior into a shared helper for maintainability and consistency.


281-302: Consolidate error handling.

The direct connection logic includes similar fetch/catch approaches as elsewhere. Extracting a shared error-handling utility could simplify maintenance and keep error reporting consistent.

backend/open_webui/routers/configs.py (1)

61-66: Consider concurrency control for config updates.

When multiple requests update the config concurrently, there could be race conditions. If config changes must be consistent under concurrent writes, consider adding locks or switching to a thread-safe/unified storage mechanism (e.g., a database or an atomic file write).

src/lib/components/admin/Settings/Connections.svelte (2)

107-118: Add error handling for internal request failures.

While catching rejections with .catch((error) => { ... }) is good, you might also log or handle errors in a more user-friendly way, ensuring the UI properly reflects partial failures of other update requests in case of parallel calls.


196-202: Improve resilience in the combined submitHandler.

The submitHandler updates multiple services (OpenAI, Ollama, Direct Connections) in quick succession. On partial failure (e.g., if Ollama fails to update), the subsequent calls still proceed. Depending on your requirements, consider short‐circuiting on errors or enumerating them for finer user feedback.

backend/open_webui/routers/pipelines.py (3)

12-12: Avoid mixing synchronous requests import while migrating to async.
You still import requests (line 16) yet introduced aiohttp (line 12). If all requests in this file go through aiohttp, consider removing the requests import to reduce confusion and ensure consistency.

- import requests

69-78: Use of shared session context.
Creating a new aiohttp.ClientSession() inside each function call can be efficient if done once, but repeated usage in a larger scope may be beneficial. Consider centralizing session creation if there's a performance bottleneck.


83-104: Unused ClientResponseError variable and exception chaining.

  1. Variable e in except aiohttp.ClientResponseError as e (line 95) isn’t used. Consider omitting the variable name:
-except aiohttp.ClientResponseError as e:
+except aiohttp.ClientResponseError:
  1. Best practice: chain exceptions (line 102) for better traceback.
🧰 Tools
🪛 Ruff (0.8.2)

95-95: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


102-102: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

backend/open_webui/utils/oauth.py (4)

4-52: Consolidate logging configuration and remove duplicates.
Lines 38–43 and 48–52 define log configurations with multiple environment variables. Consider merging them or ensuring only one place sets logging to reduce confusion.


85-90: Clearer debug logs.
These newly added debug logs add clarity for admin role assignment, but consider using structured logs (e.g., including user IDs) for faster issue diagnosis.


139-146: Nested with statements & raise-from usage.

  • Lines 257–260: Static analysis suggests a single with statement for multiple contexts.
  • Line 284: Use raise ... from e for more informative tracebacks.

419-426: Cookie security checks.
Using httponly=True, samesite, secure=True is good. Periodically review if advanced settings (e.g., domain scoping) are needed for multi-domain setups.

backend/open_webui/routers/knowledge.py (3)

20-20: Remove unused import.
Static analysis indicates Storage is imported but not used.

-from open_webui.storage.provider import Storage
🧰 Tools
🪛 Ruff (0.8.2)

20-20: open_webui.storage.provider.Storage imported but unused

Remove unused import: open_webui.storage.provider.Storage

(F401)


267-271: File addition permission checks.
Reiterates the write permission logic for a different route. DRY principle might help centralize repeated access control checks.


510-539: Bulk model reference cleanup.
Updating each model to remove references to the deleted knowledge base is a good approach. Keep an eye on performance if references become large.

backend/open_webui/retrieval/utils.py (2)

218-233: Refine partial error handling.

get_all_items_from_collections logs exceptions and continues, which could lead to partially merged results. If this behavior is intended, ensure the caller is aware of potential incomplete merges. Otherwise, consider raising an exception to signal that some collections failed.


319-326: Avoid assigning a lambda expression to a variable.

According to static analysis (E731), it is more readable and debuggable to define a named function instead of assigning lambda to func.

-        func = lambda query, user=None: generate_embeddings(
-            engine=embedding_engine,
-            model=embedding_model,
-            text=query,
-            url=url,
-            key=key,
-            user=user,
-        )
+        def func(query, user=None):
+            return generate_embeddings(
+                engine=embedding_engine,
+                model=embedding_model,
+                text=query,
+                url=url,
+                key=key,
+                user=user,
+            )
🧰 Tools
🪛 Ruff (0.8.2)

319-326: Do not assign a lambda expression, use a def

Rewrite func as a def

(E731)

backend/open_webui/retrieval/web/utils.py (3)

87-96: Enhance metadata extraction.

extract_metadata is straightforward. Consider also extracting additional SEO meta tags (e.g., Open Graph data) if relevant for your workflow.


98-114: SSL verification is helpful but be mindful of performance.

verify_ssl_cert performs a socket connection each time. For a large batch of URLs, consider caching or reusing connections to reduce overhead.


447-450: Use a ternary operator for brevity.

You can streamline choosing a parser based on file extension with an inline conditional. This improves readability.

-            if url.endswith(".xml"):
-                parser = "xml"
-            else:
-                parser = self.default_parser
+            parser = "xml" if url.endswith(".xml") else self.default_parser
🧰 Tools
🪛 Ruff (0.8.2)

447-450: Use ternary operator parser = "xml" if url.endswith(".xml") else self.default_parser instead of if-else-block

Replace if-else-block with parser = "xml" if url.endswith(".xml") else self.default_parser

(SIM108)

backend/open_webui/routers/tasks.py (1)

579-580: Avoid specifying default of None if you're using get.

Where you do form_data.get("chat_id", None), you can omit None as it’s the default return if key is missing:

-    "chat_id": form_data.get("chat_id", None),
+    "chat_id": form_data.get("chat_id"),
🧰 Tools
🪛 Ruff (0.8.2)

579-579: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)

backend/open_webui/routers/images.py (5)

58-61: Add Gemini config to get_config
These lines add the Gemini API block to the config response. Consider validating or providing defaults in case configuration is incomplete.


246-251: Set default Gemini model
Using "imagen-3.0-generate-002" as a fallback. Consider making this configurable if additional Gemini models become available.


327-330: Limited Gemini model list
Only one default Gemini model is returned here. This is acceptable for now but might require more robust listing in the future.


423-433: Refactor load_url_image_data
Handles optional request headers and returns image content and MIME type. Consider using a ternary expression per the static analysis suggestion.

-def load_url_image_data(url, headers=None):
-    if headers:
-        r = requests.get(url, headers=headers)
-    else:
-        r = requests.get(url)
+def load_url_image_data(url, headers=None):
+    r = requests.get(url, headers=headers) if headers else requests.get(url)
🧰 Tools
🪛 Ruff (0.8.2)

425-428: Use ternary operator r = requests.get(url, headers=headers) if headers else requests.get(url) instead of if-else-block

Replace if-else-block with r = requests.get(url, headers=headers) if headers else requests.get(url)

(SIM108)


521-547: Gemini engine for image generation
Adds new logic to call the Gemini API with the x-goog-api-key header. Consider optionally adding user info headers for consistency with other providers.

backend/open_webui/routers/audio.py (2)

197-198: Store Deepgram key
Ensure the key isn’t logged or inadvertently exposed in error messages.


539-601: Deepgram transcription block
Implements new STT logic for Deepgram. Consider using raise ... from e to preserve traceback context in exceptions.

 except Exception as e:
     log.exception(e)
-    raise Exception(detail if detail else "Open WebUI: Server Connection Error")
+    raise Exception(detail if detail else "Open WebUI: Server Connection Error") from e
🧰 Tools
🪛 Ruff (0.8.2)

578-580: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


600-600: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

src/lib/apis/index.ts (3)

4-8: Use a more specific type for 'connections'.
Declaring connections as object | null sacrifices compile-time type safety. Consider creating an interface or a more descriptive type to clarify the exact shape of the connections parameter.


34-36: Consolidate nested checks on 'connections'.
You already check connections && !base at line 34, but line 37 re-checks if (connections). Merging or simplifying these conditions can reduce confusion.


77-83: Remove unused 'err' variable or log it for debugging.
Static analysis flags that err is never used. If you want to keep it for logging, use it in the block; otherwise, remove it from the function parameters.

- .catch((err) => {
+ .catch(() => {
    return {
      object: 'list',
      data: [],
      urlIdx: idx
    };
  });
🧰 Tools
🪛 ESLint

[error] 77-77: 'err' is defined but never used.

(@typescript-eslint/no-unused-vars)

backend/open_webui/routers/auths.py (1)

170-170: Remove unused local variable.
LDAP_SERVER_LABEL is never referenced after assignment. You can remove the assignment to clean up the code.

🧰 Tools
🪛 Ruff (0.8.2)

170-170: Local variable LDAP_SERVER_LABEL is assigned to but never used

Remove assignment to unused variable LDAP_SERVER_LABEL

(F841)

backend/open_webui/main.py (4)

158-159: Remove unused imports for whisper models.
WHISPER_MODEL_AUTO_UPDATE and WHISPER_MODEL_DIR are not used anywhere, so it’s best to remove them to avoid confusion and maintain a clean import list.

Apply something like:

- from open_webui.config import (
-     WHISPER_MODEL_AUTO_UPDATE,
-     WHISPER_MODEL_DIR,
-     ...
- )
+ from open_webui.config import (
+     ...
+ )
🧰 Tools
🪛 Ruff (0.8.2)

158-158: open_webui.config.WHISPER_MODEL_AUTO_UPDATE imported but unused

Remove unused import

(F401)


159-159: open_webui.config.WHISPER_MODEL_DIR imported but unused

Remove unused import

(F401)


961-961: Prefer shorter .get() calls.
Replace form_data.get("model", None) with form_data.get("model") to simplify and conform to best practices.

- model_id = form_data.get("model", None)
+ model_id = form_data.get("model")
🧰 Tools
🪛 Ruff (0.8.2)

961-961: Use form_data.get("model") instead of form_data.get("model", None)

Replace form_data.get("model", None) with form_data.get("model")

(SIM910)


989-989: Shorten argument usage for 'variables'.
Replace form_data.get("variables", None) with form_data.get("variables") for consistency and readability.

- "variables": form_data.get("variables", None),
+ "variables": form_data.get("variables"),
🧰 Tools
🪛 Ruff (0.8.2)

989-989: Use form_data.get("variables") instead of form_data.get("variables", None)

Replace form_data.get("variables", None) with form_data.get("variables")

(SIM910)


1013-1016: Enhance clarity when re-raising exceptions.
You might consider using Python’s raise e from e or raise e from None for better traceback clarity. Example:

except Exception as e:
    raise e from None
🧰 Tools
🪛 Ruff (0.8.2)

1013-1016: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

backend/open_webui/routers/ollama.py (7)

267-272: Consolidate repeated fallback
Retrieving api_config with the same fallback pattern appears multiple times. It might be helpful to encapsulate it in a single helper for maintainability.

+def get_ollama_api_config(configs, idx, url):
+    return configs.get(str(idx), configs.get(url, {}))

287-292: Repeated logic
This code block replicates the same fallback approach for api_config. Avoid duplication by using a shared function if possible.


474-479: Similar pattern
Repeated fallback snippet. Refactoring could reduce code duplication.


921-924: Similar fallback approach
Again, consider centralizing repeated code for maintainability.


1228-1232: Handles fallback
Similar logic for retrieving api_config again. Consolidation in one place still recommended.


1476-1476: Remove extraneous f-string
Ruff identified an f-string without placeholders.

- log.info(f"Uploaded to /api/blobs")
+ log.info("Uploaded to /api/blobs")
🧰 Tools
🪛 Ruff (0.8.2)

1476-1476: f-string without any placeholders

Remove extraneous f prefix

(F541)


1500-1500: Another f-string without placeholders
Removing the redundant f prefix.

- log.info(f"API SUCCESS!")
+ log.info("API SUCCESS!")
🧰 Tools
🪛 Ruff (0.8.2)

1500-1500: f-string without any placeholders

Remove extraneous f prefix

(F541)

backend/open_webui/routers/retrieval.py (1)

797-799: Combine multiple isinstance checks
Ruff suggests merging these calls for clarity.

- if (
-     isinstance(value, datetime)
-     or isinstance(value, list)
-     or isinstance(value, dict)
- ):
+ if isinstance(value, (datetime, list, dict)):
🧰 Tools
🪛 Ruff (0.8.2)

797-799: Multiple isinstance calls for value, merge into a single call

Merge isinstance calls for value

(SIM101)

backend/open_webui/config.py (1)

5-5: Remove the unused base64 import.

Static analysis suggests that base64 is imported but not used anywhere in this file. Deleting it will help maintain a cleaner codebase.

- import base64
🧰 Tools
🪛 Ruff (0.8.2)

5-5: base64 imported but unused

Remove unused import: base64

(F401)

backend/open_webui/utils/middleware.py (12)

8-8: Remove the unused aiocache.cached import.

It seems that cached is never used in this file. Removing it will keep dependencies lean and the code clutter-free.

- from aiocache import cached
🧰 Tools
🪛 Ruff (0.8.2)

8-8: aiocache.cached imported but unused

Remove unused import: aiocache.cached

(F401)


9-9: Remove the unused typing.Any import.

The Any type is not referenced, so dropping the import helps reduce unnecessary code.

- from typing import Any
🧰 Tools
🪛 Ruff (0.8.2)

9-9: typing.Any imported but unused

Remove unused import: typing.Any

(F401)


10-10: Remove the unused random import.

This import is never used. Removing it will help maintain minimal imports.

- import random
🧰 Tools
🪛 Ruff (0.8.2)

10-10: random imported but unused

Remove unused import: random

(F401)


13-13: Remove the unused inspect import.

Since the inspect module is not used anywhere, removing it will clean up the file.

- import inspect
🧰 Tools
🪛 Ruff (0.8.2)

13-13: inspect imported but unused

Remove unused import: inspect

(F401)


42-44: Remove unused process_pipeline_outlet_filter import.

process_pipeline_outlet_filter is imported but never referenced. Removing it will help simplify the imports.

-from open_webui.routers.pipelines import (
-    process_pipeline_inlet_filter,
-    process_pipeline_outlet_filter,
+from open_webui.routers.pipelines import process_pipeline_inlet_filter
🧰 Tools
🪛 Ruff (0.8.2)

44-44: open_webui.routers.pipelines.process_pipeline_outlet_filter imported but unused

Remove unused import: open_webui.routers.pipelines.process_pipeline_outlet_filter

(F401)


436-436: Remove the unused negative_prompt variable.

The variable negative_prompt is set but never used. Deleting it avoids confusion and clutter.

- negative_prompt = ""
🧰 Tools
🪛 Ruff (0.8.2)

436-436: Local variable negative_prompt is assigned to but never used

Remove assignment to unused variable negative_prompt

(F841)


499-499: Remove the unnecessary 'f' prefix in the string.

No placeholders are used here, so removing the f keeps it consistent and avoids confusion.

- "description": f"An error occurred while generating an image",
+ "description": "An error occurred while generating an image",
🧰 Tools
🪛 Ruff (0.8.2)

499-499: f-string without any placeholders

Remove extraneous f prefix

(F541)


696-696: Remove the unused variables assignment.

The variables local variable is never used. Deleting it will keep things concise.

- variables = form_data.pop("variables", None)
🧰 Tools
🪛 Ruff (0.8.2)

696-696: Local variable variables is assigned to but never used

Remove assignment to unused variable variables

(F841)


715-715: Raise exceptions with clearer chaining.

Using raise ... from e preserves the original traceback and clarifies exception chaining.

- raise Exception(f"Error: {e}")
+ raise Exception(f"Error: {e}") from e
🧰 Tools
🪛 Ruff (0.8.2)

715-715: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


1180-1180: Rename the unused loop index to underscore.

This loop index is not used in the body. Renaming it to _idx clarifies that it’s intentionally unused.

- for idx, block in enumerate(content_blocks):
+ for _idx, block in enumerate(content_blocks):
🧰 Tools
🪛 Ruff (0.8.2)

1180-1180: Loop control variable idx not used within loop body

Rename unused idx to _idx

(B007)


1373-1374: Remove the unused e variable in the exception handler.

Since e is never referenced, simply catching and ignoring the exception without naming it clarifies the intent.

- except Exception as e:
+ except Exception:
    pass
🧰 Tools
🪛 Ruff (0.8.2)

1373-1373: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


1568-1570: Combine nested if statements.

You can streamline these checks into a single if condition for better readability.

- if content_blocks:
-     if content_blocks[-1]["type"] == "text":
+ if content_blocks and content_blocks[-1]["type"] == "text":
    # ...
🧰 Tools
🪛 Ruff (0.8.2)

1568-1570: Use a single if statement instead of nested if statements

(SIM102)

backend/open_webui/retrieval/web/main.py (1)

1-1: LGTM! Good addition of URL validation.

Adding URL validation before domain parsing is a good defensive programming practice. It helps prevent potential errors from invalid URLs and improves the robustness of the filtering logic.

Consider logging invalid URLs at debug level to help with troubleshooting:

 if not validators.url(url):
+    log.debug(f"Skipping invalid URL: {url}")
     continue

Also applies to: 15-16

backend/open_webui/retrieval/web/exa.py (2)

12-12: Consider making the API base URL configurable.

Move EXA_API_BASE to a configuration file to allow for environment-specific overrides.


40-46: Extract magic numbers into named constants.

The default count of 5 should be defined as a named constant at the module level.

+DEFAULT_RESULT_COUNT = 5
+
 payload = {
     "query": query,
-    "numResults": count or 5,
+    "numResults": count or DEFAULT_RESULT_COUNT,
     "includeDomains": filter_list,
     "contents": {"text": True, "highlights": True},
     "type": "auto",  # Use the auto search type (keyword or neural)
 }
backend/open_webui/retrieval/web/bocha.py (3)

13-34: Simplify nested dictionary access.

Consider using a more flat structure or dictionary get() method with default values to reduce nesting.

 def _parse_response(response):
-    result = {}
-    if "data" in response:
-        data = response["data"]
-        if "webPages" in data:
-            webPages = data["webPages"]
-            if "value" in webPages:
-                result["webpage"] = [
-                    {
-                        "id": item.get("id", ""),
-                        "name": item.get("name", ""),
-                        "url": item.get("url", ""),
-                        "snippet": item.get("snippet", ""),
-                        "summary": item.get("summary", ""),
-                        "siteName": item.get("siteName", ""),
-                        "siteIcon": item.get("siteIcon", ""),
-                        "datePublished": item.get("datePublished", "")
-                        or item.get("dateLastCrawled", ""),
-                    }
-                    for item in webPages["value"]
-                ]
-    return result
+    web_pages = response.get("data", {}).get("webPages", {}).get("value", [])
+    return {
+        "webpage": [
+            {
+                "id": item.get("id", ""),
+                "name": item.get("name", ""),
+                "url": item.get("url", ""),
+                "snippet": item.get("snippet", ""),
+                "summary": item.get("summary", ""),
+                "siteName": item.get("siteName", ""),
+                "siteIcon": item.get("siteIcon", ""),
+                "datePublished": item.get("datePublished", "") or item.get("dateLastCrawled", ""),
+            }
+            for item in web_pages
+        ]
+    }

46-46: Extract hardcoded values into constants.

Move the API URL and timeout into module-level constants.

+BOCHA_API_URL = "https://api.bochaai.com/v1/web-search?utm_source=ollama"
+REQUEST_TIMEOUT = 5
+
-    url = "https://api.bochaai.com/v1/web-search?utm_source=ollama"
+    url = BOCHA_API_URL

-    response = requests.post(url, headers=headers, data=payload, timeout=5)
+    response = requests.post(url, headers=headers, data=payload, timeout=REQUEST_TIMEOUT)

Also applies to: 53-53


56-56: Remove debug print statement.

Remove the print statement used for debugging.

-    print(results)
backend/open_webui/__init__.py (1)

16-21: Enhance version display with additional information.

Consider including more details in the version output, such as Python version and system information, to help with troubleshooting.

 def version_callback(value: bool):
     if value:
         from open_webui.env import VERSION
+        import platform
+        import sys
 
-        typer.echo(f"Open WebUI version: {VERSION}")
+        typer.echo(f"""Open WebUI version: {VERSION}
+Python version: {sys.version.split()[0]}
+Platform: {platform.platform()}""")
         raise typer.Exit()
backend/open_webui/internal/db.py (1)

103-104: LGTM! Consider adding schema validation.

The schema configuration is properly implemented. Consider adding validation to ensure DATABASE_SCHEMA is a valid identifier.

+def validate_schema_name(schema: str) -> str:
+    if not schema.isidentifier():
+        raise ValueError(f"Invalid schema name: {schema}")
+    return schema
+
 metadata_obj = MetaData(schema=DATABASE_SCHEMA)
+validate_schema_name(DATABASE_SCHEMA)
 Base = declarative_base(metadata=metadata_obj)
scripts/prepare-pyodide.js (1)

118-118: Consider moving proxy initialization.

The proxy should be initialized before any network operations to ensure all requests use the configured proxy.

-initNetworkProxyFromEnv();
-await downloadPackages();
-await copyPyodide();
+initNetworkProxyFromEnv();
+try {
+  await downloadPackages();
+  await copyPyodide();
+} catch (error) {
+  console.error('Failed to download or copy packages:', error);
+  process.exit(1);
+}
backend/open_webui/utils/filter.py (2)

10-11: Address the TODO comment.

The TODO comment indicates a potential issue with the FunctionModel's valve handling.

Would you like me to help implement the valve handling in the FunctionModel?


74-84: Simplify nested conditions and improve error handling.

The nested if statements can be simplified, and the error handling could be more informative.

-            if "__user__" in sig.parameters:
-                if hasattr(function_module, "UserValves"):
+            if "__user__" in sig.parameters and hasattr(function_module, "UserValves"):
                     try:
                         params["__user__"]["valves"] = function_module.UserValves(
                             **Functions.get_user_valves_by_id_and_user_id(
                                 filter_id, params["__user__"]["id"]
                             )
                         )
                     except Exception as e:
-                        print(e)
+                        print(f"Error setting user valves for filter {filter_id}: {e}")
🧰 Tools
🪛 Ruff (0.8.2)

74-75: Use a single if statement instead of nested if statements

(SIM102)

backend/open_webui/routers/utils.py (1)

31-38: Improve error handling in format_code endpoint.

The exception handling could be more specific and informative.

     try:
         formatted_code = black.format_str(form_data.code, mode=black.Mode())
         return {"code": formatted_code}
     except black.NothingChanged:
         return {"code": form_data.code}
     except Exception as e:
-        raise HTTPException(status_code=400, detail=str(e))
+        raise HTTPException(
+            status_code=400,
+            detail=f"Failed to format code: {str(e)}"
+        ) from e
🧰 Tools
🪛 Ruff (0.8.2)

31-31: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


38-38: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

backend/open_webui/utils/response.py (1)

27-80: Consider adding type hints for nested dictionaries.

The function handles complex calculations and data transformations well. However, consider adding type hints for the nested dictionary structure to improve code maintainability.

-def convert_ollama_usage_to_openai(data: dict) -> dict:
+def convert_ollama_usage_to_openai(data: Dict[str, Any]) -> Dict[str, Union[str, int, float, Dict[str, int]]]:
backend/open_webui/routers/prompts.py (1)

150-154: Consider extracting access control logic to a helper function.

The same access control logic is duplicated in both update and delete operations. Consider extracting it to a helper function for better maintainability.

+def has_prompt_write_access(user, prompt) -> bool:
+    return (
+        prompt.user_id == user.id
+        or has_access(user.id, "write", prompt.access_control)
+        or user.role == "admin"
+    )

 @router.delete("/command/{command}/delete", response_model=bool)
 async def delete_prompt_by_command(command: str, user=Depends(get_verified_user)):
     prompt = Prompts.get_prompt_by_command(f"/{command}")
     if not prompt:
         raise HTTPException(
             status_code=status.HTTP_401_UNAUTHORIZED,
             detail=ERROR_MESSAGES.NOT_FOUND,
         )

-    if (
-        prompt.user_id != user.id
-        and not has_access(user.id, "write", prompt.access_control)
-        and user.role != "admin"
-    ):
+    if not has_prompt_write_access(user, prompt):
backend/open_webui/utils/pdf_generator.py (1)

80-81: Consider using a template engine for HTML generation.

While the HTML escaping is correct, consider using a template engine like Jinja2 for more maintainable HTML generation and automatic escaping.

Also applies to: 89-89

src/lib/apis/configs/index.ts (1)

61-173: Reduce code duplication by extracting common API request logic.

The new functions are well-implemented but contain significant code duplication in error handling logic. This pattern is repeated across all API functions in the file.

Consider extracting the common fetch logic into a reusable function:

async function makeRequest<T>(
  endpoint: string,
  token: string,
  method: 'GET' | 'POST' = 'GET',
  body?: object
): Promise<T> {
  let error = null;

  const res = await fetch(`${WEBUI_API_BASE_URL}${endpoint}`, {
    method,
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${token}`
    },
    ...(body && { body: JSON.stringify(body) })
  })
    .then(async (res) => {
      if (!res.ok) throw await res.json();
      return res.json();
    })
    .catch((err) => {
      console.log(err);
      error = err.detail;
      return null;
    });

  if (error) {
    throw error;
  }

  return res;
}

// Example usage:
export const getDirectConnectionsConfig = (token: string) =>
  makeRequest('/configs/direct_connections', token);

export const setDirectConnectionsConfig = (token: string, config: object) =>
  makeRequest('/configs/direct_connections', token, 'POST', config);
backend/open_webui/utils/auth.py (1)

12-12: Remove unused imports.

The List and Dict imports from typing are not used in the code.

Apply this diff:

-from typing import Optional, Union, List, Dict
+from typing import Optional, Union
🧰 Tools
🪛 Ruff (0.8.2)

12-12: typing.List imported but unused

Remove unused import

(F401)


12-12: typing.Dict imported but unused

Remove unused import

(F401)

backend/open_webui/utils/tools.py (2)

64-68: Consider a more robust solution for OpenAI API compatibility.

The current hack to convert "str" to "string" is fragile and might miss nested type definitions.

Consider using a recursive function to handle all levels of the schema:

+def convert_types_for_openai(obj):
+    if isinstance(obj, dict):
+        return {k: convert_types_for_openai(v) for k, v in obj.items()}
+    elif isinstance(obj, list):
+        return [convert_types_for_openai(v) for v in obj]
+    elif obj == "str":
+        return "string"
+    return obj

 # TODO: Fix hack for OpenAI API
-for val in spec.get("parameters", {}).get("properties", {}).values():
-    if val["type"] == "str":
-        val["type"] = "string"
+spec["parameters"] = convert_types_for_openai(spec["parameters"])

83-88: Improve docstring parsing.

The current implementation has two issues:

  1. Uses positional arguments in re.split
  2. Doesn't handle multiline docstrings well

Apply this diff:

-            if callable.__doc__ and callable.__doc__.strip() != "":
-                s = re.split(":(param|return)", callable.__doc__, 1)
-                spec["description"] = s[0]
-            else:
-                spec["description"] = function_name
+            if callable.__doc__:
+                # Use keyword arguments for clarity
+                s = re.split(pattern=":(param|return)", string=callable.__doc__, maxsplit=1)
+                # Clean up multiline docstring
+                spec["description"] = s[0].strip().replace("\n", " ")
+            else:
+                spec["description"] = function_name
🧰 Tools
🪛 Ruff (0.8.2)

84-84: re.split should pass maxsplit and flags as keyword arguments to avoid confusion due to unintuitive argument positions

(B034)

src/lib/apis/users/index.ts (1)

286-289: Consider enhancing error handling and logging.

The current implementation silently handles errors by logging and returning null. This could make it difficult for callers to understand and handle error conditions appropriately.

Consider one of these approaches:

  1. Return a structured response that includes both the error and the result:
-const location = await getUserPosition().catch((err) => {
-  console.log(err);
-  return null;
-});
+const location = await getUserPosition().catch((err) => {
+  console.error('Failed to get user position:', err);
+  return { error: err.message, location: null };
+});

-if (location) {
+if (location?.location) {
-  await updateUserInfo(token, { location: location });
+  await updateUserInfo(token, { location: location.location });
-  return location;
+  return location.location;
 } else {
-  console.log('Failed to get user location');
+  console.error('Failed to get user location');
-  return null;
+  return { error: location?.error || 'Location not available', location: null };
 }
  1. Or, if you prefer the current approach, at least improve the logging:
 const location = await getUserPosition().catch((err) => {
-  console.log(err);
+  console.error('Failed to get user position:', err);
   return null;
 });

 if (location) {
   await updateUserInfo(token, { location: location });
   return location;
 } else {
-  console.log('Failed to get user location');
+  console.error('Failed to get user location');
   return null;
 }

Also applies to: 295-297

backend/open_webui/routers/users.py (2)

72-76: Consider more restrictive default chat permissions.

All chat permissions default to True, which might be too permissive. Consider following the principle of least privilege as implemented in WorkspacePermissions.

Consider setting more restrictive defaults:

-    controls: bool = True
-    file_upload: bool = True
-    delete: bool = True
-    edit: bool = True
-    temporary: bool = True
+    controls: bool = False
+    file_upload: bool = False
+    delete: bool = False
+    edit: bool = False
+    temporary: bool = False

79-82: Consider more restrictive default feature permissions.

All feature permissions default to True, which might be too permissive. Consider following the principle of least privilege.

Consider setting more restrictive defaults:

-    web_search: bool = True
-    image_generation: bool = True
-    code_interpreter: bool = True
+    web_search: bool = False
+    image_generation: bool = False
+    code_interpreter: bool = False
src/lib/components/admin/Settings/CodeExecution.svelte (1)

66-72: Consider adding a security notice component for Jupyter warnings.

The security warning for Jupyter execution is repeated in multiple places. Consider extracting it into a reusable component.

+import SecurityWarning from '$lib/components/common/SecurityWarning.svelte';

 {#if config.CODE_EXECUTION_ENGINE === 'jupyter'}
-    <div class="text-gray-500 text-xs">
-        {$i18n.t(
-            'Warning: Jupyter execution enables arbitrary code execution, posing severe security risks—proceed with extreme caution.'
-        )}
-    </div>
+    <SecurityWarning
+        message={$i18n.t('Warning: Jupyter execution enables arbitrary code execution, posing severe security risks—proceed with extreme caution.')}
+    />
 {/if}
backend/open_webui/socket/main.py (1)

327-343: Consider adding type hints to improve code clarity.

The function signature could benefit from type hints for better code maintainability and IDE support.

-def get_event_call(request_info):
+def get_event_call(request_info: dict) -> Callable:
-    async def __event_caller__(event_data):
+    async def __event_caller__(event_data: dict) -> Any:
backend/open_webui/utils/task.py (1)

226-242: Add docstring to the new image prompt generation function.

The new function should have a docstring explaining its purpose and parameters.

 def image_prompt_generation_template(
     template: str, messages: list[dict], user: Optional[dict] = None
 ) -> str:
+    """
+    Generate an image prompt based on a template and message history.
+    
+    Args:
+        template (str): The template string containing placeholders
+        messages (list[dict]): List of message dictionaries containing conversation history
+        user (Optional[dict]): Optional user information dictionary
+    
+    Returns:
+        str: The generated prompt with all placeholders replaced
+    """
src/lib/components/admin/Evaluations/Leaderboard.svelte (1)

291-292: Consider using semantic HTML for better accessibility.

The search input should have appropriate ARIA labels and roles.

 <input
     class="w-full text-sm pr-4 py-1 rounded-r-xl outline-hidden bg-transparent"
+    aria-label={$i18n.t('Search models by topic')}
+    role="searchbox"
     bind:value={query}
     placeholder={$i18n.t('Search')}
src/lib/apis/ollama/index.ts (1)

363-363: LGTM! Consider adding type definition for the payload.

The change to use a generic payload object improves flexibility. However, using object type in TypeScript is not type-safe.

Consider defining an interface for the payload:

-export const createModel = async (token: string, payload: object, urlIdx: string | null = null) => {
+interface CreateModelPayload {
+  tagName: string;
+  content: string;
+  // Add other potential fields
+}
+export const createModel = async (token: string, payload: CreateModelPayload, urlIdx: string | null = null) => {

Also applies to: 375-375

backend/open_webui/utils/misc.py (3)

13-19: Add type hints and docstring for better code maintainability.

The implementation is correct, but could benefit from better documentation.

Apply this diff to improve the function:

-def deep_update(d, u):
+def deep_update(d: dict, u: dict) -> dict:
+    """
+    Recursively update a dictionary with values from another dictionary.
+    
+    Args:
+        d: The target dictionary to update
+        u: The source dictionary containing updates
+    
+    Returns:
+        The updated dictionary
+    """
     for k, v in u.items():
         if isinstance(v, collections.abc.Mapping):
             d[k] = deep_update(d.get(k, {}), v)
         else:
             d[k] = v
     return d

146-162: Fix parameter name mismatch in docstring.

The docstring refers to parameter msg but the function uses content.

Apply this diff to fix the docstring:

 def add_or_update_user_message(content: str, messages: list[dict]):
     """
     Adds a new user message at the end of the messages list
     or updates the existing user message at the end.
 
-    :param msg: The message to be added or appended.
+    :param content: The message content to be added or appended.
     :param messages: The list of message dictionaries.
     :return: The updated list of message dictionaries.
     """

165-181: Fix parameter name mismatch in docstring.

The docstring refers to parameter msg but the function uses content.

Apply this diff to fix the docstring:

 def append_or_update_assistant_message(content: str, messages: list[dict]):
     """
     Adds a new assistant message at the end of the messages list
     or updates the existing assistant message at the end.
 
-    :param msg: The message to be added or appended.
+    :param content: The message content to be added or appended.
     :param messages: The list of message dictionaries.
     :return: The updated list of message dictionaries.
     """
backend/open_webui/utils/chat.py (1)

13-14: Remove unused imports.

Several imports are not used in the code:

  • status from fastapi
  • Response and JSONResponse from starlette.responses
  • UserModel from open_webui.models.users

Remove these unused imports to keep the code clean.

Also applies to: 17-17

🧰 Tools
🪛 Ruff (0.8.2)

13-13: fastapi.status imported but unused

Remove unused import: fastapi.status

(F401)


14-14: starlette.responses.Response imported but unused

Remove unused import

(F401)


14-14: starlette.responses.JSONResponse imported but unused

Remove unused import

(F401)

backend/open_webui/test/apps/webui/storage/test_provider.py (1)

59-425: Consider enhancing error case testing.

While the test coverage is comprehensive, consider:

  1. Using more specific exceptions instead of broad Exception catches
  2. Adding assertions for specific error messages
  3. Testing edge cases like file permissions and network errors
🧰 Tools
🪛 Ruff (0.8.2)

116-116: pytest.raises(Exception) should be considered evil

(B017)


218-218: pytest.raises(Exception) should be considered evil

(B017)


255-255: Comparison to None should be cond is None

Replace with cond is None

(E711)


279-279: Comparison to None should be cond is None

Replace with cond is None

(E711)


280-280: Comparison to None should be cond is None

Replace with cond is None

(E711)


302-302: Undefined name azure

(F821)


307-307: Undefined name azure

(F821)


312-312: Undefined name azure

(F821)


334-334: pytest.raises(Exception) should be considered evil

(B017)

src/lib/apis/chats/index.ts (1)

462-462: Consider preserving full error context.

The change to only use err.detail might lose valuable error information. Consider keeping the full error object or at least logging it before reducing to detail.

-error = err.detail;
+error = err.detail || err;
+console.error('Full error:', err);
docker-compose.playwright.yaml (1)

1-10: LGTM! Well-structured Playwright integration.

The configuration:

  • Correctly pins Playwright version
  • Properly exposes the service
  • Sets up required environment variables for integration

Add a newline at the end of the file to comply with YAML standards:

      - 'RAG_WEB_LOADER_ENGINE=playwright'
      - 'PLAYWRIGHT_WS_URI=ws://playwright:3000'
+
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 10-10: no new line character at the end of file

(new-line-at-end-of-file)

backend/requirements.txt (1)

50-51: Dependency Addition Without Version Pinning (transformers)
The dependency transformers is added without a specified version. It’s good practice to pin a version to avoid unexpected breaking changes. Consider specifying a version range.

src/app.html (1)

98-110: Commented Out Image Elements
There are commented-out <img> tags (lines 98–110 and 125–131). If these images (such as the splash logo) are no longer required, consider removing them to clean up the markup. If they will be re-enabled later, a TODO comment might help clarify their purpose.

README.md (1)

18-22: Introduce Enterprise Plan Tip Section

The new tip section promoting the Enterprise Plan is informative and eye-catching. It highlights benefits such as custom theming, branding, and SLA support. One minor note: consider hyphenating “Service-Level Agreement (SLA)” for consistency with common style guidelines.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~21-~21: When ‘Service-Level’ is used as a modifier, it is usually spelled with a hyphen.
Context: ...ding custom theming and branding, Service Level Agreement (SLA) support, **Long-Term Support (L...

(SERVICE_LEVEL_HYPHEN)

searxng/settings.yml (3)

1-32: General and Branding Sections – Clarity and Defaults
The “general” and “brand” sections are well organized and clearly commented. Please verify that setting values such as privacypolicy_url, donation_url, and contact_url to false is intentional (i.e. used to disable these links by default).

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 10-10: trailing spaces

(trailing-spaces)


10-10: Style Issue: Trailing Whitespace Detected
There is a trailing space at the end of the line defining donation_url: false on line 10. Removing extra whitespace will help maintain file cleanliness and consistency.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 10-10: trailing spaces

(trailing-spaces)


340-2551: Engine Definitions – Consider Modularization for Maintainability
The engines section is extremely comprehensive, listing a large number of search engine configurations. Although the extensive details provide flexibility, the section’s size could make future maintenance and updates challenging. Consider breaking these definitions into modular files or employing YAML merge keys/anchors to reduce repetition and improve readability. This will help keep the configuration manageable as more engines are added or modified over time.

CHANGELOG.md (3)

14-27: Well-Documented Additions for Version 0.5.15

The new features added in version 0.5.15 are comprehensively listed under “### Added”. The descriptions—including features like full context mode for local document search, smarter web search with agentic workflows, experimental Playwright support, and more—are informative and employ consistent use of emojis for clarity. As a suggestion, verify that the style (such as punctuation and emoji usage) remains uniform with previous version entries.


189-189: Avoid Bare URL Formatting

Static analysis flagged a bare URL used on line 189. For enhanced readability and to comply with markdown best practices, please replace any bare URL (for example, likely “https://github.com/open-webui/desktop” mentioned in the context of desktop app preparations) with proper markdown link syntax such as:

- Follow our progress and updates here: https://github.com/open-webui/desktop
+ Follow our progress and updates here: [Desktop App Progress](https://github.com/open-webui/desktop)

This small change will help avoid MD034 warnings and improve the overall presentation.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

189-189: Bare URL used
null

(MD034, no-bare-urls)


1-1681: Overall Changelog Consistency and Readability

The changelog is extremely comprehensive, documenting a wide range of fixes, additions, and changes from version 0.5.16 down to the earliest releases. It adheres well to the “Keep a Changelog” format and provides both technical specifics and user-facing details. As the document grows in length, consider whether splitting major version milestones into separate sections or files might improve navigability and maintenance. Also, ensure uniformity in the use of formatting elements such as emojis, link formatting, and consistent phrasing for clarity.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

189-189: Bare URL used
null

(MD034, no-bare-urls)


227-227: Bare URL used
null

(MD034, no-bare-urls)


276-276: Bare URL used
null

(MD034, no-bare-urls)


552-552: Bare URL used
null

(MD034, no-bare-urls)


1228-1228: Bare URL used
null

(MD034, no-bare-urls)


1292-1292: Bare URL used
null

(MD034, no-bare-urls)


1303-1303: Bare URL used
null

(MD034, no-bare-urls)


1342-1342: Bare URL used
null

(MD034, no-bare-urls)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0e9d57d and 3e3393e.

⛔ Files ignored due to path filters (3)
  • backend/open_webui/static/favicon.png is excluded by !**/*.png
  • backend/open_webui/static/logo.png is excluded by !**/*.png
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (108)
  • .github/workflows/integration-test.disabled (1 hunks)
  • .github/workflows/release-pypi.yml (1 hunks)
  • CHANGELOG.md (1 hunks)
  • Dockerfile (1 hunks)
  • README.md (2 hunks)
  • backend/open_webui/__init__.py (1 hunks)
  • backend/open_webui/config.py (25 hunks)
  • backend/open_webui/constants.py (2 hunks)
  • backend/open_webui/env.py (5 hunks)
  • backend/open_webui/functions.py (1 hunks)
  • backend/open_webui/internal/db.py (2 hunks)
  • backend/open_webui/main.py (34 hunks)
  • backend/open_webui/models/chats.py (2 hunks)
  • backend/open_webui/models/groups.py (3 hunks)
  • backend/open_webui/models/users.py (3 hunks)
  • backend/open_webui/retrieval/utils.py (13 hunks)
  • backend/open_webui/retrieval/vector/dbs/chroma.py (1 hunks)
  • backend/open_webui/retrieval/vector/dbs/milvus.py (1 hunks)
  • backend/open_webui/retrieval/vector/dbs/opensearch.py (1 hunks)
  • backend/open_webui/retrieval/vector/dbs/pgvector.py (3 hunks)
  • backend/open_webui/retrieval/web/bing.py (1 hunks)
  • backend/open_webui/retrieval/web/bocha.py (1 hunks)
  • backend/open_webui/retrieval/web/duckduckgo.py (1 hunks)
  • backend/open_webui/retrieval/web/exa.py (1 hunks)
  • backend/open_webui/retrieval/web/google_pse.py (1 hunks)
  • backend/open_webui/retrieval/web/jina_search.py (1 hunks)
  • backend/open_webui/retrieval/web/main.py (2 hunks)
  • backend/open_webui/retrieval/web/serpapi.py (1 hunks)
  • backend/open_webui/retrieval/web/tavily.py (2 hunks)
  • backend/open_webui/retrieval/web/utils.py (4 hunks)
  • backend/open_webui/routers/audio.py (10 hunks)
  • backend/open_webui/routers/auths.py (20 hunks)
  • backend/open_webui/routers/channels.py (3 hunks)
  • backend/open_webui/routers/chats.py (1 hunks)
  • backend/open_webui/routers/configs.py (1 hunks)
  • backend/open_webui/routers/files.py (9 hunks)
  • backend/open_webui/routers/groups.py (2 hunks)
  • backend/open_webui/routers/images.py (14 hunks)
  • backend/open_webui/routers/knowledge.py (11 hunks)
  • backend/open_webui/routers/memories.py (4 hunks)
  • backend/open_webui/routers/models.py (2 hunks)
  • backend/open_webui/routers/ollama.py (32 hunks)
  • backend/open_webui/routers/openai.py (10 hunks)
  • backend/open_webui/routers/pipelines.py (2 hunks)
  • backend/open_webui/routers/prompts.py (2 hunks)
  • backend/open_webui/routers/retrieval.py (30 hunks)
  • backend/open_webui/routers/tasks.py (20 hunks)
  • backend/open_webui/routers/tools.py (4 hunks)
  • backend/open_webui/routers/users.py (2 hunks)
  • backend/open_webui/routers/utils.py (2 hunks)
  • backend/open_webui/socket/main.py (2 hunks)
  • backend/open_webui/socket/utils.py (1 hunks)
  • backend/open_webui/static/swagger-ui/swagger-ui.css (0 hunks)
  • backend/open_webui/storage/provider.py (2 hunks)
  • backend/open_webui/test/apps/webui/storage/test_provider.py (1 hunks)
  • backend/open_webui/utils/access_control.py (3 hunks)
  • backend/open_webui/utils/auth.py (2 hunks)
  • backend/open_webui/utils/chat.py (6 hunks)
  • backend/open_webui/utils/code_interpreter.py (1 hunks)
  • backend/open_webui/utils/filter.py (1 hunks)
  • backend/open_webui/utils/images/comfyui.py (1 hunks)
  • backend/open_webui/utils/middleware.py (25 hunks)
  • backend/open_webui/utils/misc.py (6 hunks)
  • backend/open_webui/utils/models.py (1 hunks)
  • backend/open_webui/utils/oauth.py (13 hunks)
  • backend/open_webui/utils/payload.py (4 hunks)
  • backend/open_webui/utils/pdf_generator.py (4 hunks)
  • backend/open_webui/utils/plugin.py (1 hunks)
  • backend/open_webui/utils/response.py (2 hunks)
  • backend/open_webui/utils/task.py (3 hunks)
  • backend/open_webui/utils/tools.py (2 hunks)
  • backend/open_webui/utils/webhook.py (2 hunks)
  • backend/requirements.txt (7 hunks)
  • backend/start.sh (1 hunks)
  • backend/start_windows.bat (1 hunks)
  • docker-compose.playwright.yaml (1 hunks)
  • docker-compose.yaml (2 hunks)
  • docs/apache.md (2 hunks)
  • package.json (5 hunks)
  • postcss.config.js (1 hunks)
  • pyproject.toml (4 hunks)
  • run-compose.sh (5 hunks)
  • scripts/prepare-pyodide.js (2 hunks)
  • searxng/settings.yml (1 hunks)
  • searxng/uwsgi.ini (1 hunks)
  • src/app.css (6 hunks)
  • src/app.html (5 hunks)
  • src/lib/apis/chats/index.ts (3 hunks)
  • src/lib/apis/configs/index.ts (1 hunks)
  • src/lib/apis/index.ts (3 hunks)
  • src/lib/apis/models/index.ts (1 hunks)
  • src/lib/apis/ollama/index.ts (2 hunks)
  • src/lib/apis/openai/index.ts (3 hunks)
  • src/lib/apis/users/index.ts (1 hunks)
  • src/lib/apis/utils/index.ts (4 hunks)
  • src/lib/components/AddConnectionModal.svelte (9 hunks)
  • src/lib/components/ChangelogModal.svelte (1 hunks)
  • src/lib/components/NotificationToast.svelte (1 hunks)
  • src/lib/components/OnBoarding.svelte (1 hunks)
  • src/lib/components/admin/Evaluations/Feedbacks.svelte (4 hunks)
  • src/lib/components/admin/Evaluations/Leaderboard.svelte (4 hunks)
  • src/lib/components/admin/Functions.svelte (15 hunks)
  • src/lib/components/admin/Functions/FunctionEditor.svelte (4 hunks)
  • src/lib/components/admin/Functions/FunctionMenu.svelte (3 hunks)
  • src/lib/components/admin/Settings.svelte (3 hunks)
  • src/lib/components/admin/Settings/Audio.svelte (24 hunks)
  • src/lib/components/admin/Settings/CodeExecution.svelte (1 hunks)
  • src/lib/components/admin/Settings/Connections.svelte (16 hunks)
💤 Files with no reviewable changes (1)
  • backend/open_webui/static/swagger-ui/swagger-ui.css
✅ Files skipped from review due to trivial changes (6)
  • src/lib/components/NotificationToast.svelte
  • src/lib/components/admin/Functions/FunctionEditor.svelte
  • src/lib/components/ChangelogModal.svelte
  • searxng/uwsgi.ini
  • src/lib/components/admin/Functions/FunctionMenu.svelte
  • src/lib/components/admin/Evaluations/Feedbacks.svelte
🧰 Additional context used
🪛 LanguageTool
README.md

[uncategorized] ~21-~21: When ‘Service-Level’ is used as a modifier, it is usually spelled with a hyphen.
Context: ...ding custom theming and branding, Service Level Agreement (SLA) support, **Long-Term Support (L...

(SERVICE_LEVEL_HYPHEN)

🪛 YAMLlint (1.35.1)
docker-compose.playwright.yaml

[error] 10-10: no new line character at the end of file

(new-line-at-end-of-file)

searxng/settings.yml

[error] 10-10: trailing spaces

(trailing-spaces)

🪛 Ruff (0.8.2)
backend/open_webui/utils/tools.py

84-84: re.split should pass maxsplit and flags as keyword arguments to avoid confusion due to unintuitive argument positions

(B034)

backend/open_webui/utils/access_control.py

75-75: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)

backend/open_webui/routers/knowledge.py

20-20: open_webui.storage.provider.Storage imported but unused

Remove unused import: open_webui.storage.provider.Storage

(F401)

backend/open_webui/routers/tasks.py

305-305: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


355-355: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)


361-361: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


579-579: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)

backend/open_webui/test/apps/webui/storage/test_provider.py

10-10: azure.storage.blob.BlobServiceClient imported but unused

Remove unused import

(F401)


10-10: azure.storage.blob.ContainerClient imported but unused

Remove unused import

(F401)


10-10: azure.storage.blob.BlobClient imported but unused

Remove unused import

(F401)


23-23: Found useless expression. Either assign it to a variable or remove it.

(B018)


24-24: Found useless expression. Either assign it to a variable or remove it.

(B018)


25-25: Found useless expression. Either assign it to a variable or remove it.

(B018)


26-26: Found useless expression. Either assign it to a variable or remove it.

(B018)


27-27: Found useless expression. Either assign it to a variable or remove it.

(B018)


28-28: Found useless expression. Either assign it to a variable or remove it.

(B018)


116-116: pytest.raises(Exception) should be considered evil

(B017)


218-218: pytest.raises(Exception) should be considered evil

(B017)


255-255: Comparison to None should be cond is None

Replace with cond is None

(E711)


279-279: Comparison to None should be cond is None

Replace with cond is None

(E711)


280-280: Comparison to None should be cond is None

Replace with cond is None

(E711)


302-302: Undefined name azure

(F821)


307-307: Undefined name azure

(F821)


312-312: Undefined name azure

(F821)


334-334: pytest.raises(Exception) should be considered evil

(B017)

backend/open_webui/utils/filter.py

74-75: Use a single if statement instead of nested if statements

(SIM102)

backend/open_webui/routers/chats.py

453-453: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/open_webui/retrieval/vector/dbs/opensearch.py

141-141: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

backend/open_webui/routers/users.py

92-92: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/open_webui/utils/chat.py

13-13: fastapi.status imported but unused

Remove unused import: fastapi.status

(F401)


14-14: starlette.responses.Response imported but unused

Remove unused import

(F401)


14-14: starlette.responses.JSONResponse imported but unused

Remove unused import

(F401)


17-17: open_webui.models.users.UserModel imported but unused

Remove unused import: open_webui.models.users.UserModel

(F401)


128-131: Use contextlib.suppress(Exception) instead of try-except-pass

Replace with contextlib.suppress(Exception)

(SIM105)


130-130: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


226-226: Avoid equality comparisons to True; use if form_data.get("stream"): for truth checks

Replace with form_data.get("stream")

(E712)

backend/open_webui/retrieval/web/utils.py

447-450: Use ternary operator parser = "xml" if url.endswith(".xml") else self.default_parser instead of if-else-block

Replace if-else-block with parser = "xml" if url.endswith(".xml") else self.default_parser

(SIM108)

backend/open_webui/routers/pipelines.py

95-95: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


102-102: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


144-144: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

backend/open_webui/routers/configs.py

49-49: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


59-59: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


90-90: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


111-111: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/open_webui/utils/oauth.py

257-260: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


284-284: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


347-348: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)

backend/open_webui/routers/auths.py

170-170: Local variable LDAP_SERVER_LABEL is assigned to but never used

Remove assignment to unused variable LDAP_SERVER_LABEL

(F841)

backend/open_webui/utils/middleware.py

8-8: aiocache.cached imported but unused

Remove unused import: aiocache.cached

(F401)


9-9: typing.Any imported but unused

Remove unused import: typing.Any

(F401)


10-10: random imported but unused

Remove unused import: random

(F401)


13-13: inspect imported but unused

Remove unused import: inspect

(F401)


44-44: open_webui.routers.pipelines.process_pipeline_outlet_filter imported but unused

Remove unused import: open_webui.routers.pipelines.process_pipeline_outlet_filter

(F401)


64-64: open_webui.utils.misc.deep_update imported but unused

Remove unused import: open_webui.utils.misc.deep_update

(F401)


73-73: open_webui.utils.plugin.load_function_module_by_id imported but unused

Remove unused import: open_webui.utils.plugin.load_function_module_by_id

(F401)


436-436: Local variable negative_prompt is assigned to but never used

Remove assignment to unused variable negative_prompt

(F841)


461-461: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


499-499: f-string without any placeholders

Remove extraneous f prefix

(F541)


696-696: Local variable variables is assigned to but never used

Remove assignment to unused variable variables

(F841)


715-715: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


897-897: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


1180-1180: Loop control variable idx not used within loop body

Rename unused idx to _idx

(B007)


1373-1373: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


1568-1570: Use a single if statement instead of nested if statements

(SIM102)

backend/open_webui/routers/images.py

425-428: Use ternary operator r = requests.get(url, headers=headers) if headers else requests.get(url) instead of if-else-block

Replace if-else-block with r = requests.get(url, headers=headers) if headers else requests.get(url)

(SIM108)

backend/open_webui/utils/auth.py

12-12: typing.List imported but unused

Remove unused import

(F401)


12-12: typing.Dict imported but unused

Remove unused import

(F401)


79-79: Do not call setattr with a constant attribute value. It is not any safer than normal property access.

Replace setattr with assignment

(B010)


81-81: Do not call setattr with a constant attribute value. It is not any safer than normal property access.

Replace setattr with assignment

(B010)

backend/open_webui/utils/payload.py

14-14: Use params.get("system") instead of params.get("system", None)

Replace params.get("system", None) with params.get("system")

(SIM910)


76-76: Local variable param is assigned to but never used

(F841)


76-76: Use params.get(key) instead of params.get(key, None)

Replace params.get(key, None) with params.get(key)

(SIM910)

backend/open_webui/routers/audio.py

578-580: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


600-600: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

backend/open_webui/main.py

158-158: open_webui.config.WHISPER_MODEL_AUTO_UPDATE imported but unused

Remove unused import

(F401)


159-159: open_webui.config.WHISPER_MODEL_DIR imported but unused

Remove unused import

(F401)


162-162: open_webui.config.DEFAULT_RAG_TEMPLATE imported but unused

Remove unused import

(F401)


961-961: Use form_data.get("model") instead of form_data.get("model", None)

Replace form_data.get("model", None) with form_data.get("model")

(SIM910)


989-989: Use form_data.get("variables") instead of form_data.get("variables", None)

Replace form_data.get("variables", None) with form_data.get("variables")

(SIM910)


1013-1016: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


1213-1213: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/open_webui/routers/retrieval.py

797-799: Multiple isinstance calls for value, merge into a single call

Merge isinstance calls for value

(SIM101)

backend/open_webui/routers/files.py

37-37: Do not perform function call File in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


38-38: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


39-39: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)

backend/open_webui/retrieval/utils.py

17-17: open_webui.utils.misc.get_last_user_message imported but unused

Remove unused import

(F401)


17-17: open_webui.utils.misc.calculate_sha256_string imported but unused

Remove unused import

(F401)


319-326: Do not assign a lambda expression, use a def

Rewrite func as a def

(E731)


416-416: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

backend/open_webui/routers/utils.py

22-22: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


31-31: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


38-38: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


43-43: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


76-76: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


88-88: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/open_webui/routers/ollama.py

1476-1476: f-string without any placeholders

Remove extraneous f prefix

(F541)


1500-1500: f-string without any placeholders

Remove extraneous f prefix

(F541)

backend/open_webui/config.py

5-5: base64 imported but unused

Remove unused import: base64

(F401)

backend/open_webui/storage/provider.py

116-116: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


126-126: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


134-134: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


153-153: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


189-189: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


201-201: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


210-210: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


224-224: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


259-259: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


271-271: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


280-280: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


292-292: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🪛 ESLint
src/lib/components/admin/Settings/CodeExecution.svelte

[error] 2-2: 'toast' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 14-14: Don't use Function as a type. The Function type accepts any function-like value.
It provides no type safety when calling the function, which can be a common source of bugs.
It also accepts things like class declarations, which will throw at runtime as they will not be called with new.
If you are expecting the function to accept certain arguments, you should explicitly define the function shape.

(@typescript-eslint/ban-types)


[error] 21-21: 'res' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)

src/lib/apis/index.ts

[error] 77-77: 'err' is defined but never used.

(@typescript-eslint/no-unused-vars)

src/lib/apis/utils/index.ts

[error] 4-4: 'error' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 95-95: 'error' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)


[error] 122-122: 'error' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)

🪛 markdownlint-cli2 (0.17.2)
CHANGELOG.md

189-189: Bare URL used
null

(MD034, no-bare-urls)

🪛 Gitleaks (8.21.2)
searxng/settings.yml

99-99: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (244)
backend/open_webui/utils/webhook.py (2)

12-12: LGTM! Function signature updated correctly.

The addition of the name parameter enhances the flexibility of the webhook functionality.


42-42: LGTM! Microsoft Teams payload updated correctly.

The name parameter is properly integrated into the activitySubtitle field of the Microsoft Teams webhook payload.

backend/open_webui/routers/channels.py (3)

195-195: LGTM! Function signature updated correctly.

The addition of the name parameter aligns with the changes in the webhook utility.


208-210: LGTM! Webhook call updated correctly.

The name parameter is properly passed to the post_webhook function.


306-306: LGTM! Name parameter passed correctly.

The request.app.state.WEBUI_NAME is appropriately used as the source for the name parameter.

pyproject.toml (21)

9-9: FastAPI Version Update
The fastapi dependency has been upgraded to version 0.115.7. Please confirm that any breaking changes introduced by this update have been addressed and that your API endpoints remain fully compatible.


11-11: Pydantic Version Update
Upgraded pydantic to 2.10.6. Ensure that all model validations and serialization logic in your project adapt correctly to any changes in the new version.


15-15: Python-Jose Version Update
The python-jose dependency is updated to 3.4.0. Verify that this version works smoothly with your JWT token handling and any related cryptographic operations.


19-19: Aiohttp Version Update
aiohttp has been updated to 3.11.11. Please ensure that asynchronous HTTP client/session behaviors throughout your application remain compatible with this change.


40-42: New Dependency: RestrictedPython
Added RestrictedPython==8.0. Confirm that its integration meets your security and sandboxing requirements and that you have adequate tests covering its usage.


52-52: Chromadb Update
Upgraded chromadb to 0.6.2. Please test any database interactions that rely on chromadb to ensure they function as intended with the new version.


55-55: Opensearch-py Update
opensearch-py is now at 2.8.0. Verify that your search integration and any related functionalities remain stable after this update.


56-56: New Dependency: Playwright
Added playwright==1.49.1 for end-to-end testing. Ensure that your test suites are updated accordingly and confirm that any necessary browser configurations are in place.


66-66: Pymdown-extensions Update
Upgraded pymdown-extensions to 10.14.2. Please ensure that markdown rendering features and any extension-specific behavior utilized in your project continue to work as expected.


69-69: Unstructured Library Update
unstructured has been updated to 0.16.17. Verify that any document parsing or processing functionalities that depend on this library remain compatible with the updated API.


80-80: Soundfile Version Update
soundfile is now at 0.13.1. Please check any audio processing features to ensure they behave correctly with the new version.


82-82: Opencv-python-headless Update
Upgraded opencv-python-headless to 4.11.0.86. Confirm that any image processing or computer vision tasks in your project function correctly after this update.


86-86: Faster-Whisper Update
faster-whisper has been updated to 1.1.1. Ensure that integrations relying on speech-to-text functionalities are thoroughly tested against this new version.


89-89: Authlib Update
Upgraded authlib to 1.4.1. Please verify that any authentication or OAuth flows integrated into your application are fully compatible with this change.


98-98: Duckduckgo-search Update
duckduckgo-search has been updated to use the compatible version notation ~=7.3.2. Check that the search functionalities and any web scraping logic remain operational with this update.


107-107: New Dependency: moto[s3]
Added moto[s3]>=5.0.26 for simulating AWS S3 in tests. Ensure that your test suites cover S3 interactions effectively.


110-110: New Dependency: google-cloud-storage
Included google-cloud-storage==2.19.0. Verify that any Cloud Storage integrations are compatible with this version.


112-112: New Dependency: azure-identity
Added azure-identity==1.20.0 to support Azure authentication. Confirm that this dependency integrates smoothly with your Azure workflows.


113-113: New Dependency: azure-storage-blob
Added azure-storage-blob==12.24.1. Ensure that data storage and retrieval operations using Azure Blob storage are fully functional.


115-115: New Dependency: ldap3
Added ldap3==2.9.1. Please confirm that LDAP integrations, if used, adhere to current security best practices and requirements.


119-119: New Dependency: gcp-storage-emulator
Included gcp-storage-emulator>=2024.8.3. Verify that this emulator is used appropriately (e.g., in testing or local development environments) without impacting production workflows.

backend/open_webui/retrieval/web/jina_search.py (2)

24-29: Use caution with raw API key as Authorization header.

Currently, the code injects api_key directly under the Authorization header, which may be acceptable only if the Jina API requires a raw key. Otherwise, consider prefixing it with "Bearer " or confirming that this is indeed the correct authentication scheme.

Would you like to confirm this usage with Jina’s official documentation or by searching the web for best practices on Jina authentication?


39-39: Validate the "data" structure in response.

You're iterating data["data"] directly. If data or "data" is missing for any reason, this could raise a KeyError. Consider using safer access patterns (e.g., data.get("data", [])).

backend/open_webui/retrieval/web/google_pse.py (1)

60-61: Check filtering approach for potential data loss.

When applying get_filtered_results, confirm that vital data isn't mistakenly excluded. If the filter criteria are too broad, important results might get dropped.

src/lib/apis/utils/index.ts (3)

9-10: Header completeness.

The 'Authorization': \Bearer ${token}`header is set, but ensure calls do not silently fail iftoken` is empty or invalid. You may want to validate the token before issuing the request.


66-68: Confirm monitored security requirements.

The use of 'Authorization': \Bearer ${token}`` must match server logic. If your server expects a different scheme, you risk unexpected 401 errors.


121-129: Graceful error handling with parse exceptions.

If the response to getHTMLFromMarkdown isn’t valid JSON or doesn’t have html, your code can break at return res.html;. You might want to add a default fallback or extra checks.

🧰 Tools
🪛 ESLint

[error] 122-122: 'error' is assigned a value but never used.

(@typescript-eslint/no-unused-vars)

backend/open_webui/utils/code_interpreter.py (1)

27-47: Verify secure transport for password authentication.

When sending a password to the Jupyter server, ensure that the connection is established over HTTPS or another secure channel to protect user credentials.

src/lib/apis/openai/index.ts (1)

274-276: No issues found.

Throwing an error when url is missing is appropriate to prevent silent failures.

src/lib/components/admin/Settings/Connections.svelte (1)

174-184: Avoid using forEach with async.

Using forEach with async can lead to unawaited operations. If you want each iteration to run sequentially, consider a standard for-loop with await. If you need parallel execution, gather promises and await Promise.all. This ensures correct flow and error handling.

backend/open_webui/routers/pipelines.py (3)

60-60: Async migration check.
Changing to async def process_pipeline_inlet_filter is correct for non-blocking I/O. Confirm that all callers await this function; otherwise, the new async signature might be overlooked.


109-109: Maintain naming convention.
Be consistent with function naming. You used process_pipeline_inlet_filter, process_pipeline_outlet_filter, but some references might still use older naming conventions. Ensure all references are updated.


160-160: Consider additional error handling.
When returning payload, confirm it’s valid after filter chaining. Detect partial modifications or empty results to avoid unpredictable states.

backend/open_webui/utils/oauth.py (4)

73-77: Runtime injection of app dependency.
Passing app into OAuthManager is helpful for config usage. Ensure the app state or config is always accessible and not overwritten in a different context.


215-288: GitHub email retrieval flow.
This block adds robust fallback for email retrieval (lines 253–285). Good improvement! Consider caching or handling rate limits from GitHub to avoid repeated calls.

🧰 Tools
🪛 Ruff (0.8.2)

235-235: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


257-260: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


284-284: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


374-377: Ensure fallback name is correct.
When username_claim is missing, setting name = email is fine. For privacy, confirm that sharing an email publicly (e.g., in logs) matches user expectations.


385-396: Randomized password approach.
Generating a random password (line 383) is fine for OAuth users. Confirm that it’s never exposed to the user or used incorrectly in non-OAuth flows.

backend/open_webui/routers/knowledge.py (4)

28-28: New import usage check.
You imported Models, ModelForm to handle referencing knowledge bases in the model’s meta. Ensure these imports are utilized fully and remain consistent with the rest of the codebase.


217-221: Enhanced access control.
This block checks if the user is the owner or has write-group membership or is an admin. Good improvement; ensure alignment with other ACL checks for consistency.


444-451: Deleting file collection.
Removing the file’s dedicated collection (444–448) and deleting it from the DB (450) is logical. Confirm no references remain in other knowledge bases or model metas for the same file.


500-505: Cross-check knowledge removal preconditions.
When deleting a knowledge base, ensure all dependent references are updated. This check prevents partial deactivation scenarios.

backend/open_webui/retrieval/utils.py (6)

69-71: Unused parameter.

user is not used within query_doc. Consider removing or implementing usage if needed.


88-99: Unused parameter.

user is not used within get_doc. Consider removing or implementing usage if needed.


154-173: Ensure safe key access when merging results.

merge_get_results unconditionally expects each dictionary to contain "documents", "metadatas", and "ids". If any retrieved result is missing these keys, a KeyError will occur. Consider adding checks or defaults to prevent runtime errors.


259-264: Chroma ordering logic looks correct.

Conditionally reversing results for non-Chroma vector DBs is consistent with your code comments. No issues spotted.


300-305: Consistent hybrid search ordering logic.

Mirroring the sort logic for Chroma in query_collection_with_hybrid_search maintains consistency with query_collection. Looks good.


501-522: Potential PII leakage.

Forwarding user information (name, email, role) as headers to external services may reveal sensitive data. Verify that this is intentional and that the external API handles PII responsibly.

backend/open_webui/retrieval/web/utils.py (2)

65-74: Useful URL validation utility.

safe_validate_urls effectively filters out invalid or private IP addresses. Looks good for preventing SSRF attempts.


504-539: Loader instantiation logic is well-structured.

get_web_loader elegantly chooses the loader class from RAG_WEB_LOADER_ENGINES and applies proxy/SSL settings. Nicely done.

backend/open_webui/routers/tasks.py (4)

55-56: New field for image prompt generation is clearly exposed.

Including IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE in the GET config endpoint ensures it's visible to the client. Looks good.


72-74: Consistent representation of new fields in the form.

Defining ENABLE_TITLE_GENERATION and IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE here ensures UI parity and server sync.


147-151: Warn about disabled title generation.

The early return clarifies to the user that title generation is disabled. This is user-friendly.


303-367: Image prompt endpoint.

The new /image_prompt/completions route is structured similarly to the other tasks. Ensure you confirm user permissions if image generation APIs incur cost or handle sensitive data.

🧰 Tools
🪛 Ruff (0.8.2)

305-305: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


355-355: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)


361-361: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

backend/open_webui/routers/images.py (13)

3-3: Consolidated new imports
These lines add new imports for 'io', 'UploadFile', environment variables, and the upload_file function, along with pydantic. Implementation looks correct.

Also applies to: 12-12, 15-15, 16-16, 23-23


40-40: Include prompt_generation in get_config
Adding the 'prompt_generation' field to the returned config is consistent with existing patterns for exposing feature flags.


85-88: New GeminiConfigForm
Defines a form model with the Gemini API parameters. Straightforward and coherent with existing config forms.


93-93: Add prompt_generation field to ConfigForm
This boolean field captures whether prompt generation is enabled, aligning with other config parameters.


97-97: Gemini config in ConfigForm
The new gemini field references the GeminiConfigForm, ensuring a typed structure for Gemini settings.


107-109: Set ENABLE_IMAGE_PROMPT_GENERATION
Assigning form_data.prompt_generation to the app state persists the user’s prompt generation preference.


116-120: Set Gemini config in update_config
Storing Gemini API base URL and key in the app’s state is done correctly.


155-155: Return prompt_generation in config update
Ensures the updated configuration JSON includes the prompt_generation state for accurate front-end consumption.


173-176: Return Gemini config in updated response
Exposes the persisted Gemini parameters in the config response so that clients can retrieve and display them as needed.


408-419: Refactor load_b64_image_data
Refined to parse base64 strings and return the decoded image data plus MIME type. This increases clarity and reusability.


445-455: Implement upload_image
Using io.BytesIO to construct an UploadFile for uploading the generated image. Straightforward and follows existing patterns.


575-602: ComfyUI block enhancements
Retrieves images from URLs and uploads them. Clean integration that parallels other engine handlers.


646-655: Automatic1111 block: b64 decode and upload
Consistent patterned approach to decode images via load_b64_image_data and then upload them.

backend/open_webui/routers/openai.py (9)

78-92: Modify openai_o1_o3_handler
Renamed to handle O1/O3 model parameters, removing or renaming incompatible fields. This is a clear, minimal fix.


148-155: Refine removal of stale API configs
The dictionary comprehension neatly filters OPENAI_API_CONFIGS so only valid indices remain.


269-271: Check legacy configs
Continues backward compatibility by allowing either string indices or URL keys for config references.


278-283: Fallback to legacy key
Retrieves config using the index string or URL. Good approach for ensuring old configs remain accessible.


323-327: Prefix ID usage
Handles the optional prefix_id for model naming. This helps unify naming across different sources.


555-556: Pop metadata from payload
Separating out the "metadata" field from the main payload ensures the request body aligns with the API spec.


590-590: Fetch all models
Ensures the newest model data is retrieved before proceeding.


601-606: Retrieve API config
Falls back correctly to either index-based or URL-based keys for retrieving the config.


624-633: Handle special cases for O1/O3
Converts max_tokens to max_completion_tokens for O1/O3. This is a well-targeted fix for models that have different naming.

🧰 Tools
🪛 Ruff (0.8.2)

628-630: Use a single if statement instead of nested if statements

(SIM102)

backend/open_webui/routers/audio.py (6)

14-14: Import mimetypes
Facilitates MIME type detection for audio files, which is essential for the new STT engine logic.


138-143: Add DEEPGRAM_API_KEY
Introduces the field in STTConfigForm to support Deepgram transcription.


170-172: Return DEEPGRAM_API_KEY in STT config
Sensitive credentials are returned. Verify whether open disclosure is acceptable or if partial masking is needed.


270-273: OpenAI TTS request with custom timeout
Adds a ClientTimeout to help avoid indefinite blocking when calling the TTS endpoint.


330-333: ElevenLabs request with custom timeout
Maintains consistency by applying the same timeout logic to ElevenLabs requests.


390-393: Azure request with custom timeout
Uniformly sets a timeout for Azure TTS, preventing potential hanging requests.

src/lib/apis/index.ts (2)

2-2: Import appears valid and aligned with usage.
No issues found with this addition.


993-1000: Bearer token authorization looks correct.
The newly added headers ensure the request is authenticated with the provided token.

backend/open_webui/routers/auths.py (2)

28-29: Cookie variable renaming is clear.
Renaming WEBUI_SESSION_COOKIE_* to WEBUI_AUTH_COOKIE_* better reflects their purpose.


167-167: Confirm the impact of switching the response model.
Changing from SigninResponse to SessionUserResponse may break clients expecting the old response structure. Verify that downstream code and UI are updated accordingly.

backend/open_webui/main.py (1)

1213-1213: Safe to ignore this Ruff warning.
In FastAPI, it’s idiomatic to use user=Depends(get_verified_user) in function signatures. This is not an actual error and can be safely ignored.

🧰 Tools
🪛 Ruff (0.8.2)

1213-1213: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/open_webui/routers/ollama.py (20)

29-29: Import appended
The addition of ConfigDict and validator from Pydantic looks aligned with the new validation logic below.


153-158: Validate fallback logic
This modified helper function attempts to fetch configurations first by idx, then by base_url as a legacy fallback. Confirm that both paths are tested, especially if str(idx) or base_url entries are missing in the configs.


241-248: Confirm index bounds
The code prunes OLLAMA_API_CONFIGS based on the enumerated OLLAMA_BASE_URLS. Ensure that the derived keys list accurately reflects existing valid indices. If any mismatch occurs (e.g., accidental length changes), we might drop valid configs or keep stale ones.


262-264: Check config existence
When both str(idx) and url are absent in OLLAMA_API_CONFIGS, this branch defaults to send_get_request without an API config. Verify that subsequent usage handles missing credentials gracefully.


366-366: Usage check
Calling get_api_key here follows the established pattern. No functional concerns.


397-397: Filter assignment
Setting models["models"] = await get_filtered_models(...) assumes "models" is always a valid key in the original models dict. Consider verifying the structure if future modifications occur.


411-415: Consistent inline fallback
The usage for key-based authentication remains consistent with earlier logic.


511-511: Key retrieval usage
No issues. Matches the existing retrieval pattern.


551-551: Optional model
Defining model as Optional[str] = None is fine. Ensure callers handle the None case properly to avoid unexpected errors.


556-556: Allowing extra fields
ConfigDict(extra="allow") is a good way to accommodate additional fields within this Pydantic model.


573-573: Key retrieval
Fetching the API key here appears consistent with the rest of the module.


604-604: Same retrieval logic
No specific issues with reusing the get_api_key approach.


708-708: Consistent usage
No concerns. This line is aligned with the existing pattern.


933-933: Call to get_api_key
No issues detected.


939-953: New validator ensures content or tool_calls
Requiring at least one of content or tool_calls is a good way to prevent invalid messages. This helps maintain data integrity in chat usage.


965-965: Optional tools
Adding an optional tools field broadens the model's flexibility without affecting existing logic.


980-980: Explicit return
Returning (url, url_idx) clarifies usage for downstream calls.


994-994: Pop metadata
Extracting "metadata" from the form data is a clean approach to handle optional fields.


1023-1023: Apply system prompt
Ensure there's no conflict if metadata is None. Otherwise, the approach is consistent.


1242-1242: Consistent usage of get_api_key
No concerns; usage aligns with the existing pattern.

backend/open_webui/routers/retrieval.py (25)

24-24: Use of run_in_threadpool
Introducing run_in_threadpool can help offload CPU-bound tasks, improving concurrency.


49-49: New search engine import (Bocha)
Importing search_bocha broadens supported search backends.


54-54: SerpAPI import
This expands integration with the search_serpapi function.


61-61: Exa engine import
Similarly, this introduces another supported search engine.


395-397: Additional keys in the config dictionary
Including searchapi_engine, serpapi_api_key, and serpapi_engine in the JSON output is consistent with newly supported functionality. Ensure they’re set or default-handled if empty.


400-400: New EXA API key
Storing the exa_api_key in config allows integration with your custom EXA search engine.


403-403: Domain filter list
Exposing RAG_WEB_SEARCH_DOMAIN_FILTER_LIST in the output is a good approach for user-configurable domain restrictions.


440-440: Optional Bocha search key
Designating bocha_search_api_key as optional is consistent with the approach for other search engines.


448-449: SerpAPI fields
Making serpapi_api_key and serpapi_engine optional remains consistent with existing optional search engine credentials.


453-453: EXA API key
Configured as optional. No concerns.


456-456: Optional trust_env
Allowing toggling environment-based trust is useful for advanced configurations.


457-457: Optional domain_filter_list
Good approach to supply a default empty list, preventing potential NoneType issues.


462-462: ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION
Indicating SSL verification is optional aligns with possible insecure or dev test scenarios.


463-463: RAG_WEB_SEARCH_FULL_CONTEXT
Makes retrieving the entire context from web results switchable. This is a nice feature toggle.


467-467: RAG_FULL_CONTEXT
Allowing a full context toggle at the global RAG level is consistent with your feature set.


488-492: Updating RAG_FULL_CONTEXT
This snippet updates RAG_FULL_CONTEXT only if present in form_data. The fallback to the existing value is logical.


555-557: Bocha search API
Assigning BOCHA_SEARCH_API_KEY ensures the config is up-to-date with user input.


570-571: SerpAPI updates
Storing serpapi_api_key and serpapi_engine in the config is consistent with other search engines.


581-581: EXA API key
Ensuring EXA_API_KEY is saved. No concerns.


589-591: RAG_WEB_SEARCH_TRUST_ENV
This extends user control over trusted environment variables for web searches.


592-594: Set domain_filter_list
Assigning domain filters from user-provided data. Logical addition to search constraints.


629-629: Expose bocha_search_api_key
Including the Bocha API key in the response. Looks consistent with the other search APIs.


637-638: SerpAPI config
Returning these fields aligns with the rest of the optional search engine credentials.


643-643: EXA API key
Including EXA credentials in the final output is consistent.


646-647: Expose trust_env and domain_filter_list
Providing these values in the JSON output for front-end usage or debugging.

postcss.config.js (1)

3-3: Consolidate Tailwind configuration.

Replacing separate tailwindcss and autoprefixer entries with @tailwindcss/postcss seems consistent with newer Tailwind workflows. This looks good.

backend/open_webui/retrieval/web/duckduckgo.py (1)

36-46: LGTM! Improved efficiency and readability.

The changes improve both efficiency and readability by:

  1. Filtering results before constructing SearchResult objects
  2. Using list comprehension for cleaner result construction
backend/start_windows.bat (1)

9-18: LGTM! Well-structured conditional block for Playwright setup.

The implementation correctly:

  • Checks RAG_WEB_LOADER_ENGINE case-insensitively
  • Verifies PLAYWRIGHT_WS_URI is not set before installing browsers
  • Downloads required NLTK tokenizer
backend/open_webui/retrieval/web/bing.py (1)

26-26: LGTM! Parameter name aligned with Bing API.

The change from "answerCount" to "count" correctly matches Bing API's expected parameter name.

backend/open_webui/retrieval/web/exa.py (1)

48-76: LGTM! Well-implemented error handling and result transformation.

The implementation:

  • Properly handles API errors
  • Transforms results to the common SearchResult format
  • Includes informative logging
backend/open_webui/retrieval/web/bocha.py (1)

60-65: LGTM! Well-implemented result transformation.

The implementation correctly:

  • Transforms results to the common SearchResult format
  • Handles missing fields with get()
  • Respects the requested result count
backend/open_webui/socket/utils.py (1)

29-29: LGTM! Redundant decode removed.

The change correctly removes the redundant .decode('utf-8') call since Redis client is already configured with decode_responses=True.

backend/open_webui/routers/groups.py (2)

5-6: LGTM: Import statement is correctly placed.

The new import for the Users model is appropriately placed with other model imports.


85-86: LGTM: User validation is properly implemented.

The code now validates user IDs before updating group membership, which is a good security practice to prevent invalid user assignments.

scripts/prepare-pyodide.js (2)

26-50: LGTM: Proxy configuration is well-implemented.

The proxy configuration function:

  • Correctly prioritizes lowercase environment variables
  • Properly validates proxy URLs
  • Has good error handling
  • Includes helpful logging

12-15:

✅ Verification successful

Verify package compatibility with Pyodide.

Please ensure these new packages are compatible with Pyodide's WebAssembly environment.


🌐 Web query:

Are sympy, tiktoken, and pytz packages compatible with Pyodide?

💡 Result:

SymPy, tiktoken, and pytz are compatible with Pyodide under certain conditions based on their dependencies and how they interact with WebAssembly constraints:

SymPy

  • Compatibility: Fully supported via manual installation using micropip[5].
  • Details:
    SymPy isn't included by default in Pyodide but can be installed from PyPI using:
    await pyodide.loadPackage("micropip");
    await micropip.install("sympy")
    The SymPy Live Shell demonstrates this by dynamically fetching the latest SymPy wheel during deployment[5]. Note that while older Pyodide releases might bundle outdated SymPy versions, manual installation ensures compatibility[5].

tiktoken

  • Compatibility: Works as a pure Python package[2][10].
  • Details:
    tiktoken (a Byte-Pair Encoding tokenizer) has no native dependencies and can be installed via:
    await micropip.install("tiktoken")
    Testing confirms functionality in browser environments[10], though streaming downloads may require cross-origin isolation[1].

pytz

  • Compatibility: Supported via micropip[3][9].
  • Details:
    As a pure Python timezone library, pytz installs cleanly:
    await micropip.install("pytz")
    For timezone data in the standard library’s zoneinfo, load tzdata separately:
    await pyodide.loadPackage("tzdata")  # For stdlib zoneinfo

Key Considerations

  1. Installation Method: Use micropip for PyPI packages[3][9]. Binary packages require explicit loading via pyodide.loadPackage()[1][6].
  2. Network Limitations: Browser security policies (CORS) may block remote resource fetching unless configured properly[1][3].
  3. Missing Modules: Avoid dependencies on unsupported modules like multiprocessing or ssl (requires explicit loading)[1][7].

For all three packages, no fundamental incompatibilities exist with Pyodide’s WebAssembly runtime when installed correctly[1][3][9].

Citations:


Verified Pyodide Compatibility for New Packages

Based on the latest web query results:

  • Sympy: Compatible when manually installed via micropip; ensure you load micropip and install Sympy explicitly.
  • Tiktoken: A pure-Python package that installs cleanly with micropip.
  • Pytz: Works as expected via micropip; if relying on standard library timezone support, consider loading tzdata as needed.

The package additions in scripts/prepare-pyodide.js (lines 12–15) are fine provided these installation steps are followed. Also, verify that any additional packages (e.g., seaborn) adhere to similar compatibility guidelines if applicable.

backend/open_webui/utils/response.py (1)

9-24: LGTM! Well-structured tool call conversion function.

The function properly handles missing data using .get() and provides default values. The UUID generation for missing IDs is a good practice.

backend/open_webui/routers/prompts.py (1)

115-120: LGTM! Enhanced access control logic.

The updated condition properly checks for all three access scenarios: original creator, write access through groups, or admin role. The comment clearly explains the access requirements.

backend/open_webui/utils/pdf_generator.py (1)

45-52: LGTM! Proper HTML escaping implementation.

The code now properly escapes HTML special characters in all user-provided content, preventing potential HTML injection vulnerabilities. The newline to <br/> conversion maintains proper formatting.

Also applies to: 57-57

backend/open_webui/routers/memories.py (1)

60-60:

❓ Verification inconclusive

Verify the impact of user-specific embeddings.

The addition of the user parameter to EMBEDDING_FUNCTION calls suggests personalized embeddings. Ensure this change is compatible with the embedding model and verify its impact on memory retrieval accuracy.

Also applies to: 85-85, 108-108, 163-165


🏁 Script executed:

#!/bin/bash
# Check if the embedding function is imported and defined correctly
rg -A 5 "EMBEDDING_FUNCTION.*=.*" backend/

Length of output: 1250


Action: Verify compatibility of personalized embedding integration

The change in backend/open_webui/routers/memories.py (line 60, as well as lines 85, 108, and 163–165) now passes a user parameter to EMBEDDING_FUNCTION. However, our search results indicate that EMBEDDING_FUNCTION is initialized in both backend/open_webui/main.py and backend/open_webui/routers/retrieval.py via get_embedding_function without any sign of handling an extra parameter. Please ensure that:

  • The implementation of get_embedding_function (or the function it returns) is updated to accept and correctly process the additional user parameter.
  • The embedding model in use supports and appropriately utilizes personalized embeddings without compromising memory retrieval accuracy.
  • All usage sites are consistent in their parameter passing and that no side effects are introduced in the embedding calculations.
backend/open_webui/utils/access_control.py (1)

10-25: LGTM! Well-structured recursive function for filling missing permissions.

The implementation correctly handles nested dictionaries and ensures all default permissions are present.

src/lib/apis/models/index.ts (1)

222-222: LGTM! Improved error handling specificity.

Using err.detail instead of the full error object provides more focused error information to the user.

backend/open_webui/routers/models.py (2)

158-166: LGTM! Enhanced access control for model updates.

The implementation correctly checks for user ownership, write access, and admin role before allowing model updates.


186-190: LGTM! Improved access control for model deletion.

The implementation properly verifies admin role, user ownership, and write access before allowing model deletion.

backend/open_webui/constants.py (2)

60-60: LGTM! Improved error message clarity.

The updated message is more user-friendly and avoids listing specific formats, making it more maintainable.


116-116: LGTM! Added new task for image prompt generation.

The new task constant follows the existing naming convention and integrates well with the TASKS enum.

backend/open_webui/models/groups.py (1)

83-83: LGTM!

The addition of the permissions field with appropriate typing and default value is well-implemented.

backend/open_webui/utils/images/comfyui.py (1)

164-164:

❓ Verification inconclusive

Verify the reason for reducing the random seed range.

The upper limit for random seed generation has been reduced from 2^64-2 to 2^50. While this still provides a large range of possible seeds, please verify if this change is:

  1. Required for compatibility with external systems
  2. A performance optimization
  3. Has any specific reason

🌐 Web query:

What is the recommended range for random seeds in ComfyUI?

💡 Result:

ComfyUI's recommended seed ranges vary slightly depending on the specific nodes used, but generally follow these guidelines:

Standard Range
Most seed implementations use 64-bit unsigned integers ranging from:
0 to 18,446,744,073,709,551,615 (hex: 0xffffffffffffffff) [1][6]. This allows approximately 18 quintillion unique possibilities.

Special Values
Some nodes like rgthree's implementation accept extended ranges and special values:

  • -1: Random seed per generation [2][5]
  • -2/-3: Increment/decrement last used seed [2]
  • Extended signed range: -1,125,899,906,842,624 to +1,125,899,906,842,624 in rgthree nodes [5]

Key Implementation Details

  • Seeds control reproducibility - identical seeds with matching settings produce identical outputs [3][4]
  • Batch generation assigns sequential seeds automatically (first image uses input seed) [4]
  • Special samplers like Euler may override seed behavior compared to DPM variants [4][7]
  • Nodes like CR Seed and Seed Generator enforce unsigned 64-bit ranges by default [1][6]

For most workflows:

# Typical usage pattern
seed = 42  # Any value between 0-18446744073709551615

Use -1 in compatible nodes for automatic randomization[2][5].

Citations:


Seed range reduction may be intentionally set for compatibility with certain nodes (e.g. rgthree) that require seeds within a 50‑bit limit.

Based on the web reference, most ComfyUI seed implementations use the full 64‑bit range (0 to 2^64‑1). However, specific nodes—like those in rgthree’s implementation—appear to work with a signed range roughly between –2^50 and +2^50. Reducing the upper limit to 2^50 in backend/open_webui/utils/images/comfyui.py suggests a deliberate choice to ensure compatibility with such nodes.

To proceed, please verify that:

  • The limited 50‑bit range is expected by all downstream consumers (especially nodes that may enforce these limits).
  • There are no performance implications or unintended side effects for nodes that might normally accept values in the full 64‑bit range.
  • Documentation/comments are updated to clarify the reason for restricting the seed range for future maintainers.
backend/open_webui/utils/auth.py (1)

34-48: LGTM! Secure implementation of HMAC signature verification.

The implementation follows security best practices:

  • Uses constant-time comparison with hmac.compare_digest
  • Properly handles exceptions
  • Uses SHA-256 for hashing
.github/workflows/integration-test.disabled (1)

55-56: LGTM! Good addition for CI environment.

Setting LIBGL_ALWAYS_SOFTWARE=1 is a good practice for running Cypress in CI environments where hardware acceleration may not be available.

backend/open_webui/utils/models.py (1)

145-145: LGTM! Good defensive programming.

Using model.get("owned_by", "unknown owner") instead of direct dictionary access is a good practice to prevent KeyError exceptions.

backend/open_webui/routers/users.py (2)

65-68: LGTM! Good security practice.

Setting default workspace permissions to False follows the principle of least privilege, which is a good security practice.


156-156: LGTM! Good separation of concerns.

Using update_user_settings_by_id instead of update_user_by_id follows the principle of least privilege by limiting the scope of the update to just settings.

backend/open_webui/models/users.py (3)

274-291: LGTM! The user settings update implementation is robust.

The method properly handles null settings and uses appropriate error handling.


328-332: LGTM! The implementation is efficient and focused.

The method efficiently filters valid user IDs using SQL's IN clause.


292-309: LGTM! The user deletion cleanup is comprehensive.

The implementation properly cleans up user associations in the correct order: groups → chats → user.

backend/open_webui/retrieval/vector/dbs/milvus.py (2)

10-11: LGTM! New configuration imports are properly organized.

The imports are well-organized and follow the existing pattern.


18-21: LGTM! Token-based authentication is properly implemented.

The conditional initialization handles both token and non-token cases cleanly.

backend/open_webui/functions.py (1)

253-253:

✅ Verification successful

Verify the updated function signature.

The function call now includes metadata as a new parameter. Ensure that the apply_model_system_prompt_to_body function in the payload utils module has been updated to accept this parameter.


🏁 Script executed:

#!/bin/bash
# Description: Verify the function signature of apply_model_system_prompt_to_body

# Search for the function definition
rg -A 5 "def apply_model_system_prompt_to_body"

Length of output: 477


The updated function signature has been verified.
The call in backend/open_webui/functions.py now properly passes the metadata parameter along with params, form_data, and user, which aligns with the definition in backend/open_webui/utils/payload.py. No further changes are needed.

src/lib/components/AddConnectionModal.svelte (3)

24-25: LGTM! Props are properly declared.

The new props follow Svelte conventions with appropriate default values.


42-43: LGTM! Error handling is consistent.

The error handling is improved with consistent string formatting.

Also applies to: 51-55


205-205: LGTM! Layout classes improve responsiveness.

The added flex and shrink utilities enhance the layout structure.

backend/open_webui/socket/main.py (1)

282-284: Improve error handling for missing chat_id and message_id.

Using .get() with a default value of None is a good defensive programming practice to handle missing keys.

backend/open_webui/utils/task.py (1)

25-25: Improve error handling for model ownership check.

Using .get() with a default value is a good defensive programming practice to handle missing keys.

src/lib/components/admin/Evaluations/Leaderboard.svelte (2)

354-355: Use consistent class naming.

Changed from flex-shrink-0 to shrink-0 for consistency with Tailwind's class naming conventions.


3-5:

❓ Verification inconclusive

Verify WASM paths configuration.

The WASM paths configuration needs to be verified to ensure the files are available at the specified location.


🏁 Script executed:

#!/bin/bash
# Check if WASM files exist in the public directory
fd -t f . public/wasm -e wasm

Length of output: 130


Action Required: Confirm WASM Files Location

The current verification command indicates that the public/wasm directory does not exist (error: “Search path 'public/wasm' is not a directory”). Please manually verify that the WASM files are correctly deployed and that the runtime environment maps the /wasm/ URL to the proper directory. If your build or deployment setup places these files in a different location, update the configuration accordingly.

backend/open_webui/routers/files.py (2)

233-245: LGTM! Improved PDF file handling.

The changes properly handle PDF files by setting the appropriate content disposition and content type headers, allowing PDFs to be displayed inline in the browser.


125-125: Simplify error logging messages.

The error logging has been simplified to use consistent messages across different functions.

Also applies to: 254-254, 285-285

backend/open_webui/env.py (3)

57-62: LGTM! Improved device detection for Apple Silicon.

The addition of MPS (Metal Performance Shaders) device detection improves performance on Apple Silicon devices.


359-375: LGTM! Enhanced cookie security settings.

The changes improve cookie security by:

  1. Separating session and auth cookie settings
  2. Making settings configurable via environment variables
  3. Maintaining backward compatibility

110-114:

✅ Verification successful

Verify the new configuration values.

The WebUI name, favicon URL, and trusted signature key have been updated with new default values.


🌐 Web query:

Is "Prediction Guard Chat" a valid default name for this application? This seems to be a significant branding change.

💡 Result:

The name "Prediction Guard Chat" appears consistently across multiple official contexts as part of Prediction Guard's product ecosystem:

  1. LangChain Integration
    The Python library langchain_predictionguard explicitly uses ChatPredictionGuard as its chat interface class[1]. Documentation refers to it as "Prediction Guard Chat" when describing API endpoints for building chatbots[1].

  2. GitHub Implementation
    Prediction Guard's guarded-chat repository describes itself as providing access to their "Chat endpoint" while displaying "Prediction Guard Chatbot" in the interface[3]. This suggests "Chat" is an accepted shorthand in developer contexts.

  3. API Documentation
    Prediction Guard's API guides use "Chat API" as a standard term when explaining how to implement conversational features[4].

While no explicit branding announcement appears in these sources, the pattern shows:

  • Consistency: Used uniformly across technical implementations
  • Differentiation: Separates chat functionality from other services like completions and embeddings[1]
  • Developer Familiarity: Follows naming conventions seen in AI/ML frameworks (e.g., LangChain's chat models)

The name appears valid based on current technical documentation rather than indicating a recent rebranding effort.

Citations:


Configuration Values Verified

The updated default for WEBUI_NAME ("Prediction Guard Chat") has been confirmed against official documentation and appears consistently in Prediction Guard’s product ecosystem. In addition, the favicon URL and the signature key defaults seem appropriate given their usage context. No further actions are required.

backend/open_webui/routers/tools.py (2)

72-74: LGTM! Updated permission check.

The permission check now correctly verifies "workspace.tools" instead of "workspace.knowledge".


168-173: LGTM! Enhanced access control logic.

The access control logic has been improved to:

  1. Check if the user is the original creator
  2. Verify write access through access control groups
  3. Allow admin access
  4. Use appropriate HTTP status codes (400 for prohibited access)

Also applies to: 230-234, 317-325

backend/open_webui/retrieval/vector/dbs/pgvector.py (1)

97-124: LGTM! Improved error handling and robustness.

The changes enhance the check_vector_length method by:

  • Adding early return if table doesn't exist
  • Providing clear error messages for different scenarios
  • Properly checking vector column type and dimensions
backend/open_webui/utils/chat.py (1)

63-155: LGTM! Well-structured direct chat completion implementation.

The implementation:

  • Properly handles streaming responses using asyncio.Queue
  • Cleans up socket handlers in background tasks
  • Provides clear error handling

However, consider using contextlib.suppress for cleaner error handling:

-            async def background():
-                try:
-                    del sio.handlers["/"][channel]
-                except Exception as e:
-                    pass
+            from contextlib import suppress
+            async def background():
+                with suppress(Exception):
+                    del sio.handlers["/"][channel]
🧰 Tools
🪛 Ruff (0.8.2)

128-131: Use contextlib.suppress(Exception) instead of try-except-pass

Replace with contextlib.suppress(Exception)

(SIM105)


130-130: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

src/lib/components/admin/Settings.svelte (1)

192-216: LGTM! Consistent implementation of Code Execution settings.

The changes:

  • Follow existing button styling patterns
  • Properly integrate the CodeExecution component
  • Implement save handler consistently with other settings

Also applies to: 394-402

src/lib/components/admin/Functions.svelte (4)

6-6: LGTM!

The addition of settings import is necessary for the direct connections feature.


64-64: LGTM: Consistent error message formatting.

Error messages are now consistently formatted using template literals.

Also applies to: 91-91, 107-107, 121-121, 140-140, 437-437


54-57: LGTM: Consistent model fetching with direct connections support.

All model fetching calls have been updated to include the direct connections parameter, maintaining consistency across the codebase.

Also applies to: 372-378, 515-520, 541-546


183-183:

❓ Verification inconclusive

Verify the custom event name.

The event name 'blur-sm' is non-standard. Ensure this is intentional and the event is properly defined elsewhere in the codebase.

Also applies to: 188-188


🏁 Script executed:

#!/bin/bash
# Search for other occurrences of 'blur-sm' event
rg -A 5 "addEventListener\('blur-sm'"

Length of output: 1913


Action Required: Verify 'blur-sm' Custom Event Usage

  • The event "blur-sm" is used consistently in multiple components:
    • src/lib/components/admin/Functions.svelte (lines 183 and 188)
    • src/lib/components/layout/Sidebar.svelte
    • src/lib/components/workspace/Models.svelte
    • src/lib/components/workspace/Tools.svelte
  • Since "blur-sm" is not a standard browser event, please confirm that it is an intentional custom event. If so, verify that it is correctly defined and dispatched (e.g., via CustomEvent) and consider adding documentation or inline comments to clarify its purpose.
backend/open_webui/test/apps/webui/storage/test_provider.py (2)

1-12: LGTM: Comprehensive test setup.

The imports provide all necessary dependencies for testing various storage providers.

🧰 Tools
🪛 Ruff (0.8.2)

10-10: azure.storage.blob.BlobServiceClient imported but unused

Remove unused import

(F401)


10-10: azure.storage.blob.ContainerClient imported but unused

Remove unused import

(F401)


10-10: azure.storage.blob.BlobClient imported but unused

Remove unused import

(F401)


14-57: LGTM: Well-structured test helpers and basic provider tests.

The implementation includes:

  • A reusable mock_upload_dir helper
  • Comprehensive provider instantiation tests
  • Good error case coverage
🧰 Tools
🪛 Ruff (0.8.2)

23-23: Found useless expression. Either assign it to a variable or remove it.

(B018)


24-24: Found useless expression. Either assign it to a variable or remove it.

(B018)


25-25: Found useless expression. Either assign it to a variable or remove it.

(B018)


26-26: Found useless expression. Either assign it to a variable or remove it.

(B018)


27-27: Found useless expression. Either assign it to a variable or remove it.

(B018)


28-28: Found useless expression. Either assign it to a variable or remove it.

(B018)

src/lib/components/admin/Settings/Audio.svelte (2)

42-42: LGTM: Well-implemented Deepgram integration.

The implementation includes:

  • Secure API key handling
  • Clear UI for model selection
  • Helpful documentation links

Also applies to: 180-182, 220-250


54-57: LGTM: Consistent model fetching implementation.

The model fetching logic aligns with the direct connections feature implementation in Functions.svelte.

backend/open_webui/routers/chats.py (1)

447-449: LGTM: Well-structured form class.

The CloneForm class properly defines an optional title field.

src/lib/apis/chats/index.ts (1)

583-595: LGTM! Clean implementation of optional title parameter.

The implementation correctly:

  • Adds optional title parameter to function signature
  • Uses spread operator to conditionally include title in request body
  • Maintains backward compatibility
backend/open_webui/models/chats.py (2)

473-473: LGTM! Fixed typo in comment.

Simple correction of "checkng" to "checking" in the comment.


396-396:

❓ Verification inconclusive

Verify impact of removing folder_id filter.

The removal of .filter_by(folder_id=None) means this method will now return all chats for a user, regardless of folder. Ensure this change is intentional and that all consuming code handles the expanded result set correctly.


🏁 Script executed:

#!/bin/bash
# Search for direct usages of get_chat_list_by_user_id
rg -A 5 "get_chat_list_by_user_id"

Length of output: 2223


Impact of Updated Chat Query in get_chat_list_by_user_id

  • The removal of the folder_id filter in get_chat_list_by_user_id (backend/open_webui/models/chats.py, line 396) means that all chats for a given user will now be returned, regardless of folder association. Verify that downstream consumers—such as the calls in backend/open_webui/routers/chats.py—are intended to work with this broader result set.
  • The comment fix in get_chat_by_share_id is a straightforward typo correction with no functional impact.
.github/workflows/release-pypi.yml (1)

22-22:

✅ Verification successful

Consider using LTS version of Node.js.

Node.js 22 is currently in development and not yet an LTS release. This could potentially introduce stability issues in the build process.

Consider using the latest LTS version instead:

-          node-version: 22
+          node-version: 20

🌐 Web query:

What is the latest LTS version of Node.js?

💡 Result:

The latest Long Term Support (LTS) version of Node.js is v22.x (codename "Jod"), which entered Active LTS status on October 29, 2024[1][8]. This version will receive critical updates and security patches until April 2027[7][8], with:

  • Active LTS support until October 2025
  • Maintenance LTS support from October 2025 to April 2027

Key details about Node.js v22 LTS:

  • Includes a built-in WebSocket client for native real-time communication[1]
  • Ships with OpenSSL 3.0.x (quictls fork) for enhanced security[8]
  • Provides stable APIs and performance improvements from previous versions[1]

The current recommended production version as of February 2025 is v22.14.0[6][10], which can be downloaded from the official Node.js website. Previous LTS versions like v20.x ("Iron") are now in Maintenance LTS until April 2026[4][7], but new projects should adopt v22.x for maximum support coverage.

For development environments needing cutting-edge features, Node.js v23.x remains in Current release status but isn't recommended for production use[3].

Citations:


Node.js v22 is now the proper LTS version

The update to node-version: 22 is valid. Node.js v22.x entered Active LTS status in October 2024 and is the current recommended production version as of February 2025. No changes are needed, as using Node.js 22 aligns with the latest LTS recommendations.

docker-compose.yaml (5)

1-3: File Header and Version Declaration
The version declaration and service container are formatted correctly.


4-25: New Service searxng Added
The new searxng service is well configured with proper container name, image, ports, volume, environment file, restart policy, and security capabilities. Please verify that the environment file (.env) contains the correct configuration for searxng and that all volume paths are accessible.


27-47: Update to open-webui Service Dependencies and Environment
The open-webui service now depends on searxng, which is consistent with the new changes. However, note that the environment variable on line 46 still points to OLLAMA_BASE_URL=http://ollama:11434. Since the ollama service is removed, consider updating or removing this variable unless it is still used for legacy purposes.


52-57: New Service tika Added
The addition of the tika service with its container name, image, and port mapping is clear and follows the style of other service definitions.


59-63: Volumes Configuration Review
A new volume favicons has been added appropriately for mounting assets. However, the volume ollama is still declared (line 60) even though the ollama service was removed. Please verify if ollama volume is still needed or if it should be removed to keep the configuration clean.

backend/requirements.txt (6)

1-4: Dependency Version Updates (FastAPI and Pydantic)
The updates for fastapi and pydantic to versions 0.115.7 and 2.10.6 respectively are clear. Ensure that these newer versions are compatible with your existing backend code and that all tests pass.


7-12: Other Core Dependencies Updated
Version bump for python-jose to 3.4.0 and aiohttp to 3.11.11 are noted. Please verify any breaking changes between the old and new versions in the context of your application.


32-34: New Dependency RestrictedPython Added
The addition of RestrictedPython==8.0 looks appropriate; just ensure that its usage in the codebase is properly covered by tests and that security reviews have been conducted for sandboxing requirements.


48-51: Dependency Updates for AI/ML and Browser Automation Tools
The updates for chromadb, opensearch-py, and playwright are consistent with modernizing the stack. Note the comment regarding the Playwright version—ensure that it matches the configuration in your Docker Compose setups.


55-64: Other Dependency Version Updates and Additions
The remaining version updates (e.g., pymdown-extensions, unstructured, soundfile, opencv-python-headless, faster-whisper, authlib, and duckduckgo-search) are clearly listed. Please double-check that your integration tests validate compatibility after these updates.


104-108: New Cloud and Identity Libraries
The additions and updates for google-cloud-storage, azure-identity, and azure-storage-blob are appropriate given the expanded cloud functionality. Verify that any new authentication or storage code interacts seamlessly with these libraries.

backend/start.sh (2)

17-37: Legacy Configuration for Secret Key and Conditional Service Starts
The remainder of the script (lines 17–37) remains unchanged and appears to handle key loading and legacy service starts (like ollama serve) correctly. Ensure that any deprecated code (related to ollama) is revisited in line with other service removal updates.

🧰 Tools
🪛 Shellcheck (0.10.0)

[warning] 27-27: Quote this to prevent word splitting.

(SC2046)


39-43: CUDA Library Path Update
The update for USE_CUDA_DOCKER (lines 39–42) properly appends the necessary paths for CUDA libraries.

package.json (5)

1-8: Version Bump and New Script Addition
The project version has been updated from "0.5.4" to "0.5.16", and a new development script "dev:5050" has been added. Both changes improve clarity and offer additional development options.


28-29: New DevDependencies for Tailwind Plugins
The addition of "@tailwindcss/container-queries": "^0.1.1" and "@tailwindcss/postcss": "^4.0.0" in the devDependencies helps enhance styling capabilities. Make sure these plugins are integrated into your PostCSS configuration.


46-51: Dependency Updates for Build Tools
The upgrades for "tailwindcss", "vite", and "vitest" are noted. Ensure that these updates are compatible with your SvelteKit configuration and that existing tests run as expected after these changes.


87-89: Dependency Updates and Additions in Production Dependencies
Dependencies such as "katex", "kokoro-js", and "pyodide" have been updated or added. Confirm that these dependencies work together seamlessly in your build process and that any breaking changes have been addressed.


109-112: New Dependencies: undici and vite-plugin-static-copy
The addition of "undici" and "vite-plugin-static-copy" should be reviewed in context—ensure that their usage in the codebase is as intended and that they are properly configured in your build pipeline.

src/app.html (4)

8-10: Rebranding: Updated Apple Mobile Web App Title
The <meta name="apple-mobile-web-app-title" content="Global Chat" /> tag now reflects the new branding. This is consistent with the overall rebranding effort.


17-23: Rebranding: Updated Description and Search Metadata
The changes to the <meta name="description"> and <link rel="search"> tags now using "Global Chat" are appropriate for the rebranding.


24-25: New Script Inclusion: Loader Script
The addition of the <script src="/static/loader.js" defer></script> tag (line 24) is clear. Verify that the loader script exists at the specified location and that it does not introduce performance issues during page load.


80-81: Updated Page Title for Rebranding
The <title> tag is updated to "Global Chat", which aligns with the new branding direction.

docs/apache.md (2)

19-21: Add HTTP WebSocket Proxy Configuration

The new lines add WebSocket proxy configuration (with the comment "Needed after 0.5") immediately after the standard HTTP reverse proxy setup. This is clear and concise for enabling WebSocket support in the HTTP VirtualHost.


38-40: Add HTTPS WebSocket Proxy Configuration

Similarly, the addition of WebSocket proxy configuration for the HTTPS VirtualHost is consistent with the HTTP setup. It’s properly documented with the “Needed after 0.5” comment and ensures that WebSocket requests over SSL are handled correctly.

Dockerfile (1)

33-35: Increase Node.js Memory Allocation

The new environment variable

ENV NODE_OPTIONS="--max-old-space-size=4096"

correctly increases the memory allocation for the Node.js build process. This change can help avoid potential out-of-memory issues during the build.

run-compose.sh (3)

77-78: Document the Playwright Option in Usage

The usage message now includes the --playwright option with a clear description ("Enable Playwright support for web scraping."). This informs users about the new functionality right from the help output.


134-136: Parse the Playwright Flag

The argument parsing correctly sets the enable_playwright flag when the --playwright option is encountered:

--playwright)
    enable_playwright=true
    ;;

This is clean and follows the style of the other flag parsing logic.


190-192: Integrate Playwright into Docker Compose Command

The conditional block appends the docker-compose.playwright.yaml configuration when enable_playwright is true:

if [[ $enable_playwright == true ]]; then
    DEFAULT_COMPOSE_COMMAND+=" -f docker-compose.playwright.yaml"
fi

This approach cleanly integrates Playwright support into the compose command.

src/app.css (9)

1-2: Reference Tailwind CSS

The new @reference "./tailwind.css"; at the top ensures that Tailwind’s utilities are included. This clear reference enhances modularity and consistency in styling.


57-59: Enhance Markdown Prose Styling

The updated .markdown-prose class now applies additional utilities (like border styling for blockquotes and adjusted typography), which should improve the readability of markdown content.


61-63: Update Smaller Markdown Prose Styling

The .markdown-prose-xs class now includes similar enhancements as the standard version, ensuring consistency across different text sizes.


73-82: Introduce Drag-and-Drop Region Classes

The additions of the .drag-region, .drag-region a, .drag-region button, and .no-drag-region classes (with appropriate -webkit-app-region settings) are well implemented. They provide clear control over draggable regions which is useful for desktop app interfaces.


119-121: Adjust Select Element Background Position

Changing the background-position of the select element to right 0rem center fine-tunes its appearance. Removing the previously commented-out padding adjustments also cleans up the code.


132-139: Add Shimmer Keyframe Animation

The new @keyframes shimmer definition provides a smooth background animation, which is then used in the .shimmer class to create a visually appealing loading effect. The fallback color definition is also a nice touch.


141-149: Implement the Shimmer Class

The .shimmer class leverages the new keyframe animation effectively. This creates an engaging text effect and demonstrates attention to detail in UI feedback.


161-170: Add Smooth Fade-In Animation

The newly defined @keyframes smoothFadeIn and the accompanying .status-description class introduce a subtle animated appearance, enhancing the user experience for status messages.


222-230: Refine Scrollbar Visibility for Code Scroller

The modifications to the .cm-scroller scrollbar styling now conditionally show/hide the scrollbar thumb. This update improves the usability of scrollable areas, especially during user interaction.

README.md (1)

182-183: Update Documentation Link for Updating Guide

The updated link replacing the old migration guide with the "Updating Guide" improves guidance for users. Ensure the URL is verified to match the latest documentation.

searxng/settings.yml (4)

82-112: Server and Redis Sections – Environment Variable Integration
The “server” section is well documented with notes on environment variable overrides, and the inline comments help clarify the purpose of each setting (for example, base_url and secret_key notes). Ensure that the base_url value (set to /) meets your deployment requirements and is correctly interpreted as a string. Also, verify that setting redis.url to false correctly signals that no connection should be established or that it is intended to be overridden via environment variables.

🧰 Tools
🪛 Gitleaks (8.21.2)

99-99: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


118-171: UI Settings – Customization and Defaults
The UI section is detailed and offers a wide range of customization options (such as paths, themes, and behaviors). Ensure that the default values (for example, empty strings for static_path and templates_path) are intended, and consider adding more descriptive comments if users are expected to override these values.


186-221: Outgoing Communication Settings – Timeouts and Connection Handling
The settings under “outgoing” are clearly defined and include sensible default values (e.g. request_timeout: 3.0, pool_connections: 100). Please double-check that these values meet your performance and reliability requirements, and that the additional configuration (like HTTP/2 support) is aligned with your environment.


2566-2575: DOI Resolvers Configuration – Clear and Concise
The DOI resolvers section, along with the default_doi_resolver setting, is clearly defined and appears consistent. Just ensure that the URLs provided for each resolver are current and that the default choice (oadoi.org) aligns with your desired behavior for DOI resolution.

CHANGELOG.md (2)

8-9: Version Heading Update Verification

The changelog now begins with the updated version header “## [0.5.16] - 2025-02-20”. This update clearly reflects the jump from version 0.5.4 to 0.5.16 as specified in the PR objectives. Please ensure that corresponding release notes and documentation are also updated to match this version change.


10-12: Clear Documentation of Fixed Issues for Version 0.5.16

The “### Fixed” section under version 0.5.16 documents the restoration of web search retrieval very clearly. The bullet point outlines the correction in reverting deduplication changes, which is both concise and comprehensible. This aids readers in quickly understanding the critical fix.

Comment on lines 9 to 11
async def execute_code_jupyter(
jupyter_url, code, token=None, password=None, timeout=10
):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider using an asynchronous HTTP client for concurrency.

The execute_code_jupyter function is defined as async yet uses requests (a blocking HTTP client) which can block the event loop. To improve concurrency, consider switching to a non-blocking library like aiohttp.

Comment on lines 76 to +79
if (param := params.get(key, None)) is not None:
form_data[value] = param
# Copy the parameter to new name then delete it, to prevent Ollama warning of invalid option provided
params[value] = params[key]
del params[key]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove unused variable assignment.

(param := params.get(key, None)) is assigned but never used. Remove or refactor this assignment to avoid confusion and adhere to best practices.

- if (param := params.get(key, None)) is not None:
+ if params.get(key) is not None:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (param := params.get(key, None)) is not None:
form_data[value] = param
# Copy the parameter to new name then delete it, to prevent Ollama warning of invalid option provided
params[value] = params[key]
del params[key]
if params.get(key) is not None:
# Copy the parameter to new name then delete it, to prevent Ollama warning of invalid option provided
params[value] = params[key]
del params[key]
🧰 Tools
🪛 Ruff (0.8.2)

76-76: Local variable param is assigned to but never used

(F841)


76-76: Use params.get(key) instead of params.get(key, None)

Replace params.get(key, None) with params.get(key)

(SIM910)



@router.get("/direct_connections", response_model=DirectConnectionsConfigForm)
async def get_direct_connections_config(request: Request, user=Depends(get_admin_user)):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid using Depends(...) as a default parameter value [ruff B008].

FastAPI recommends assigning dependencies via function parameters (or router-level dependencies) instead of using them as default parameter values to comply with best practices and avoid potential pitfalls:

Use a pattern like:

-async def get_direct_connections_config(request: Request, user=Depends(get_admin_user)):
+async def get_direct_connections_config(request: Request, user: User = Depends(get_admin_user)):
    ...

-async def set_code_execution_config(
-    request: Request, form_data: CodeInterpreterConfigForm, user=Depends(get_admin_user)
-):
+async def set_code_execution_config(
+    request: Request, form_data: CodeInterpreterConfigForm, user: User = Depends(get_admin_user)
+):
    ...

Also applies to: 59-59, 90-90, 111-111

🧰 Tools
🪛 Ruff (0.8.2)

49-49: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

Comment on lines 115 to 117
except ClientError as e:
raise RuntimeError(f"Error uploading file to S3: {e}")

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use explicit exception chaining ([ruff B904]).

When re-raising an exception, provide from e to clarify the cause and preserve the original traceback. Example fix:

-except ClientError as e:
-    raise RuntimeError(f"Error uploading file to S3: {e}")
+except ClientError as e:
+    raise RuntimeError(f"Error uploading file to S3: {e}") from e

Repeating similarly for GCS and Azure exceptions will improve debugging and clarity of error origins.

Also applies to: 125-127, 133-135, 153-154, 189-190, 201-202, 210-211, 224-225, 259-260, 271-272, 280-281, 292-293

🧰 Tools
🪛 Ruff (0.8.2)

116-116: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

Comment on lines 118 to 157
async with aiohttp.ClientSession() as session:
for filter in sorted_filters:
urlIdx = filter.get("urlIdx")
if urlIdx is None:
continue

url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = request.app.state.config.OPENAI_API_KEYS[urlIdx]

if key != "":
r = requests.post(
f"{url}/{filter['id']}/filter/outlet",
headers={"Authorization": f"Bearer {key}"},
json={
"user": user,
"body": payload,
},
)
if not key:
continue

r.raise_for_status()
data = r.json()
payload = data
except Exception as e:
# Handle connection error here
print(f"Connection error: {e}")
headers = {"Authorization": f"Bearer {key}"}
request_data = {
"user": user,
"body": payload,
}

if r is not None:
try:
async with session.post(
f"{url}/{filter['id']}/filter/outlet",
headers=headers,
json=request_data,
) as response:
response.raise_for_status()
payload = await response.json()
except aiohttp.ClientResponseError as e:
try:
res = r.json()
res = (
await response.json()
if "application/json" in response.content_type
else {}
)
if "detail" in res:
return Exception(r.status_code, res)
raise Exception(response.status, res)
except Exception:
pass

else:
pass
except Exception as e:
print(f"Connection error: {e}")

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Unused ClientResponseError variable and concurrency caution.

  1. Variable e in except aiohttp.ClientResponseError as e (line 144) isn’t used. Remove the variable or reference it if needed.
  2. Ensure no data race on payload when shared across multiple coroutines. If payload is mutated, concurrency locks might be needed.
-except aiohttp.ClientResponseError as e:
+except aiohttp.ClientResponseError:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async with aiohttp.ClientSession() as session:
for filter in sorted_filters:
urlIdx = filter.get("urlIdx")
if urlIdx is None:
continue
url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = request.app.state.config.OPENAI_API_KEYS[urlIdx]
if key != "":
r = requests.post(
f"{url}/{filter['id']}/filter/outlet",
headers={"Authorization": f"Bearer {key}"},
json={
"user": user,
"body": payload,
},
)
if not key:
continue
r.raise_for_status()
data = r.json()
payload = data
except Exception as e:
# Handle connection error here
print(f"Connection error: {e}")
headers = {"Authorization": f"Bearer {key}"}
request_data = {
"user": user,
"body": payload,
}
if r is not None:
try:
async with session.post(
f"{url}/{filter['id']}/filter/outlet",
headers=headers,
json=request_data,
) as response:
response.raise_for_status()
payload = await response.json()
except aiohttp.ClientResponseError as e:
try:
res = r.json()
res = (
await response.json()
if "application/json" in response.content_type
else {}
)
if "detail" in res:
return Exception(r.status_code, res)
raise Exception(response.status, res)
except Exception:
pass
else:
pass
except Exception as e:
print(f"Connection error: {e}")
async with aiohttp.ClientSession() as session:
for filter in sorted_filters:
urlIdx = filter.get("urlIdx")
if urlIdx is None:
continue
url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx]
key = request.app.state.config.OPENAI_API_KEYS[urlIdx]
if not key:
continue
headers = {"Authorization": f"Bearer {key}"}
request_data = {
"user": user,
"body": payload,
}
try:
async with session.post(
f"{url}/{filter['id']}/filter/outlet",
headers=headers,
json=request_data,
) as response:
response.raise_for_status()
payload = await response.json()
except aiohttp.ClientResponseError:
try:
res = (
await response.json()
if "application/json" in response.content_type
else {}
)
if "detail" in res:
raise Exception(response.status, res)
except Exception:
pass
except Exception as e:
print(f"Connection error: {e}")
🧰 Tools
🪛 Ruff (0.8.2)

144-144: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

self.Storage.delete_file(gcs_file_path)
# check that deleting file from gcs will delete the local file as well
assert not (upload_dir / self.filename).exists()
assert self.Storage.bucket.get_blob(self.filename) == None
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix None comparisons to follow Python idioms.

Use 'is None' instead of '== None' for proper Python idioms.

-assert self.Storage.bucket.get_blob(self.filename) == None
+assert self.Storage.bucket.get_blob(self.filename) is None

-assert self.Storage.bucket.get_blob(self.filename) == None
-assert self.Storage.bucket.get_blob(self.filename_extra) == None
+assert self.Storage.bucket.get_blob(self.filename) is None
+assert self.Storage.bucket.get_blob(self.filename_extra) is None

Also applies to: 279-280

🧰 Tools
🪛 Ruff (0.8.2)

255-255: Comparison to None should be cond is None

Replace with cond is None

(E711)

@@ -166,13 +172,14 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Speech-to-Text Engine')}</div>
<div class="flex items-center relative">
<select
class="dark:bg-gray-900 cursor-pointer w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
class="dark:bg-gray-900 cursor-pointer w-fit pr-8 rounded-sm px-2 p-1 text-xs bg-transparent outline-hidden text-right"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix invalid Tailwind CSS classes.

Replace all instances of 'outline-hidden' with 'outline-none' as it's the correct Tailwind CSS class.

Example fix:

-class="dark:bg-gray-900 cursor-pointer w-fit pr-8 rounded-sm px-2 p-1 text-xs bg-transparent outline-hidden text-right"
+class="dark:bg-gray-900 cursor-pointer w-fit pr-8 rounded-sm px-2 p-1 text-xs bg-transparent outline-none text-right"

Apply similar changes to all other instances.

Also applies to: 191-191, 209-209, 234-234, 258-258, 375-375, 388-388, 399-399, 405-405, 422-422, 446-446, 487-487, 507-507, 528-528, 547-547, 569-569, 596-596, 612-612

Comment on lines +452 to +454
async def clone_chat_by_id(
form_data: CloneForm, id: str, user=Depends(get_verified_user)
):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix FastAPI dependency injection pattern.

Move the Depends call into the function signature to follow FastAPI best practices.

-async def clone_chat_by_id(
-    form_data: CloneForm, id: str, user=Depends(get_verified_user)
-):
+async def clone_chat_by_id(
+    form_data: CloneForm,
+    id: str,
+    user: User = Depends(get_verified_user)
+):
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async def clone_chat_by_id(
form_data: CloneForm, id: str, user=Depends(get_verified_user)
):
async def clone_chat_by_id(
form_data: CloneForm,
id: str,
user: User = Depends(get_verified_user)
):
🧰 Tools
🪛 Ruff (0.8.2)

453-453: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/start.sh Outdated
Comment on lines 6 to 15
# Add conditional Playwright browser installation
if [[ "${RAG_WEB_LOADER_ENGINE,,}" == "playwright" ]]; then
if [[ -z "${PLAYWRIGHT_WS_URI}" ]]; then
echo "Installing Playwright browsers..."
playwright install chromium
playwright install-deps chromium
fi

python -c "import nltk; nltk.download('punkt_tab')"
fi
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Conditional Playwright Browser Installation and NLTK Resource Download
The newly added conditional block (lines 6–15) for installing Playwright browsers based on the RAG_WEB_LOADER_ENGINE variable is clear. However, please double-check that the NLTK resource name 'punkt_tab' is intentional. Typically, NLTK downloads the 'punkt' tokenizer; if 'punkt_tab' is a custom resource, ensure that it exists. Additionally, consider adding error handling for the Playwright installation commands.

# If your instance owns a /etc/searxng/settings.yml file, then set the following
# values there.

secret_key: "68c0af85bed7d563749c41a2b34b8c1634142620640d02e3c5953f722a37e1c0" # Is overwritten by ${SEARXNG_SECRET}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical Security: Hardcoded Secret Key
The secret_key on line 99 is hardcoded in the configuration. Storing sensitive keys in version-controlled files poses a security risk. It is strongly recommended to remove the static key from the file and instead retrieve it from an environment variable or a secure secrets manager, especially for production deployments.

🧰 Tools
🪛 Gitleaks (8.21.2)

99-99: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

Copy link

coderabbitai bot commented Feb 22, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@arthrod
Copy link
Owner Author

arthrod commented Feb 24, 2025

@coderabbitai summary

Copy link

coderabbitai bot commented Feb 24, 2025

✅ Actions performed

Summary regeneration triggered.

@arthrod
Copy link
Owner Author

arthrod commented Mar 6, 2025

@coderabbitai review

Copy link

coderabbitai bot commented Mar 6, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🔭 Outside diff range comments (1)
backend/open_webui/routers/files.py (1)

314-357: 🛠️ Refactor suggestion

Duplicate function name.

There are two functions named get_file_content_by_id in this file (lines 231 and 314), which could cause confusion during maintenance.

Rename one of the functions to better reflect its specific purpose, such as:

-@router.get("/{id}/content/{file_name}")
-async def get_file_content_by_id(id: str, user=Depends(get_verified_user)):
+@router.get("/{id}/content/{file_name}")
+async def get_file_content_with_name(id: str, user=Depends(get_verified_user)):
🧰 Tools
🪛 Ruff (0.8.2)

314-314: Redefinition of unused get_file_content_by_id from line 231

(F811)


314-314: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


342-342: Local variable file_name is assigned to but never used

Remove assignment to unused variable file_name

(F841)

♻️ Duplicate comments (2)
backend/open_webui/retrieval/vector/dbs/chroma.py (1)

59-60: ⚠️ Potential issue

Likely incorrect comparison when list_collections() returns collection objects.

This pattern has been previously flagged. If list_collections() returns objects rather than simple strings, verifying membership with collection_name in collection_names might be incorrect. Ensure that you're comparing the correct attribute (e.g., collection.name) instead of the collection object.

-collection_names = self.client.list_collections()
-return collection_name in collection_names
+collections = self.client.list_collections()
+return collection_name in [c.name for c in collections]
backend/open_webui/routers/files.py (1)

39-40: ⚠️ Potential issue

Fix function parameter defaults.

Using mutable default arguments and function calls in parameter defaults can lead to unexpected behavior.

-def upload_file(
-    request: Request,
-    file: UploadFile = File(...),
-    user=Depends(get_verified_user),
-    file_metadata: dict = {},
-):
+def upload_file(
+    request: Request,
+    file: UploadFile = File(...),
+    user=Depends(get_verified_user),
+    file_metadata: dict | None = None,
+):
+    if file_metadata is None:
+        file_metadata = {}
🧰 Tools
🪛 Ruff (0.8.2)

39-39: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


40-40: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)

🧹 Nitpick comments (65)
backend/open_webui/retrieval/vector/dbs/qdrant.py (1)

14-15: Avoid setting log level in library code
Configuring the logger’s level here might override global logging configurations. Typically, libraries should defer log-level settings to the application-level entry point.

 log = logging.getLogger(__name__)
-log.setLevel(SRC_LOG_LEVELS["RAG"])
+# Consider removing this line or checking for a default fallback
backend/open_webui/utils/misc.py (6)

8-8: Remove unused import
Static analysis indicates that typing.Callable is unused. Remove it to keep imports clean.

-from typing import Callable, Optional
+from typing import Optional
🧰 Tools
🪛 Ruff (0.8.2)

8-8: typing.Callable imported but unused

Remove unused import: typing.Callable

(F401)


14-15: Avoid library-level log configuration
Setting a specific log level in a utility file may inadvertently override user-configured log levels. Consider removing or making it optional.


18-25: Document in-place modification
The deep_update function is helpful, but clarify in a docstring that it mutates d in-place to avoid surprises.

 def deep_update(d, u):
+    """
+    Recursively update dictionary d with dictionary u and return d.
+    Note: This function mutates d in-place.
+    """
     for k, v in u.items():
         ...

151-168: Docstring param mismatch
The docstring mentions :param msg: but the function signature uses content. Update the docstring for consistency.

def add_or_update_user_message(content: str, messages: list[dict]):
    """
-    :param msg: The message to be added or appended.
+    :param content: The message text to be added or appended.
     ...

170-187: Docstring param mismatch (assistant message)
Similarly, the docstring references :param msg:; rename it to align with content to avoid confusion.


260-265: File-based hash computation
Introducing a chunk size for computing the file hash is more efficient for large files. Consider adding a docstring to clarify usage and default chunk size if any.

pyproject.toml (1)

9-125:

❓ Verification inconclusive

Review dependency expansions
A large set of new or upgraded dependencies can introduce potential bloat or conflicts. Consider grouping some libraries under optional extras to minimize the default install overhead. Also, note that libraries like playwright may require additional system dependencies and could impact CI.


🏁 Script executed:

#!/bin/bash
# Verify potential dependency conflicts using pip’s resolver in a temporary environment

# 1. Create a new virtualenv
python -m venv /tmp/test_env
source /tmp/test_env/bin/activate

# 2. Install dependencies from pyproject.toml
# Hatch is specified but let's try using pip for conflict detection
pip install --upgrade pip setuptools wheel
pip install tomli

# Convert pyproject.toml to requirements via a script or a plugin if needed
# Or parse and install them line-by-line
# For demonstration, just do:
pip install fastapi==0.115.7 pydantic==2.10.6 aiohttp==3.11.11 ...

# 3. Check for conflicts
pip check

Length of output: 2446


Attention: Dependency Grouping Recommendation

The dependency list installs without reported conflicts (aside from the demonstration placeholder “…”), but the expansion remains a potential source of bloat and unexpected CI impacts—especially for packages like playwright that may require extra system dependencies. Please consider these points:

  • Optional Extras: Group related packages (e.g., web frameworks, database drivers, ML tools) under optional extras to minimize the default install overhead.
  • CI Considerations: Be aware that libraries such as playwright might impact CI builds due to additional system dependencies.
  • Verification: Although the temporary pip conflict check (ignoring the placeholder “...”) reported no broken requirements, manually verify that all dependency groupings align with usage patterns and deployment needs.

Please review these recommendations and confirm that dependencies are organized optimally.

backend/open_webui/retrieval/vector/dbs/pgvector.py (5)

33-34: Logger instantiation and configuration.

Using logging.getLogger(__name__) and setting the log level from config fosters consistent logging. Consider verifying that SRC_LOG_LEVELS["RAG"] is always valid or handle missing keys.


91-91: Initialization info log.

Logging successful initialization is a helpful indicator. Adding more context (e.g., DB URL or partial config detail) might further assist in debugging.


94-94: Exception logging during initialization.

log.exception automatically includes the traceback, so the f"{e}" in the message is somewhat redundant. You might omit it or repurpose it for additional context.

- log.exception(f"Error during initialization: {e}")
+ log.exception("Error during initialization")

289-289: Exception handling in search.

Consider logging additional query context (e.g., collection_name, vector sizes) to expedite debugging if an error surfaces.


370-370: Rollback on delete exception.

Good practice. As with other exception blocks, consider adding more specific context to the log if needed.

backend/open_webui/utils/filter.py (2)

35-66: Filter function loading logic.

Loading function modules into a cached state object (request.app.state.FUNCTIONS) is a neat approach. Continue verifying advanced concurrency scenarios if multiple requests load the same filter simultaneously.


85-86: Combine nested if statements.

As flagged by static analysis, lines 85-86 can be refactored into a single check for readability:

- if "__user__" in sig.parameters:
-     if hasattr(function_module, "UserValves"):
+ if "__user__" in sig.parameters and hasattr(function_module, "UserValves"):
🧰 Tools
🪛 Ruff (0.8.2)

85-86: Use a single if statement instead of nested if statements

(SIM102)

backend/open_webui/utils/chat.py (3)

13-14: Unused imports detected.

There are several imports that aren't being used in the code.

-from fastapi import Request, status
+from fastapi import Request
-from starlette.responses import Response, StreamingResponse, JSONResponse
+from starlette.responses import StreamingResponse
🧰 Tools
🪛 Ruff (0.8.2)

13-13: fastapi.status imported but unused

Remove unused import: fastapi.status

(F401)


14-14: starlette.responses.Response imported but unused

Remove unused import

(F401)


14-14: starlette.responses.JSONResponse imported but unused

Remove unused import

(F401)


17-17: Unused import: UserModel.

The UserModel import is not being used in this file.

-from open_webui.models.users import UserModel
🧰 Tools
🪛 Ruff (0.8.2)

17-17: open_webui.models.users.UserModel imported but unused

Remove unused import: open_webui.models.users.UserModel

(F401)


128-131: Use contextlib.suppress for cleaner exception handling.

The try-except-pass pattern could be replaced with a more Pythonic approach.

-            async def background():
-                try:
-                    del sio.handlers["/"][channel]
-                except Exception as e:
-                    pass
+            async def background():
+                from contextlib import suppress
+                with suppress(Exception):
+                    del sio.handlers["/"][channel]
🧰 Tools
🪛 Ruff (0.8.2)

128-131: Use contextlib.suppress(Exception) instead of try-except-pass

Replace with contextlib.suppress(Exception)

(SIM105)


130-130: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

CHANGELOG.md (1)

21-21: Bare URLs in markdown.

There are instances of bare URLs that should be properly formatted with markdown link syntax for better readability and accessibility.

For example, change:

- **🔎 "Stream" Hook for Real-Time Filtering**: The new "stream" hook allows dynamic real-time message filtering. Learn more in our documentation (https://docs.openwebui.com/features/plugin/functions/filter).

to:

- **🔎 "Stream" Hook for Real-Time Filtering**: The new "stream" hook allows dynamic real-time message filtering. Learn more in our [documentation](https://docs.openwebui.com/features/plugin/functions/filter).

Also applies to: 218-218

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

21-21: Bare URL used
null

(MD034, no-bare-urls)

backend/open_webui/models/chats.py (1)

1-2: Unused imports.

There are imports that aren't being used in the code.

import logging
-import json
import time
import uuid
from typing import Optional

from open_webui.internal.db import Base, get_db
-from open_webui.models.tags import TagModel, Tag, Tags
+from open_webui.models.tags import TagModel, Tags
from open_webui.env import SRC_LOG_LEVELS

Also applies to: 8-9

🧰 Tools
🪛 Ruff (0.8.2)

2-2: json imported but unused

Remove unused import: json

(F401)

backend/open_webui/routers/auths.py (3)

169-169: Remove unused variable
LDAP_SERVER_LABEL is never referenced after assignment. Consider removing it to avoid confusion.

- LDAP_SERVER_LABEL = request.app.state.config.LDAP_SERVER_LABEL
🧰 Tools
🪛 Ruff (0.8.2)

169-169: Local variable LDAP_SERVER_LABEL is assigned to but never used

Remove assignment to unused variable LDAP_SERVER_LABEL

(F841)


487-488: Posting sign-up webhook
Consider handling potential network failures around post_webhook, e.g., retries or logging.


764-764: Setting mail attribute from user input
Consider validating this new mail attribute name if your system supports only certain known attributes.

backend/open_webui/routers/tasks.py (5)

23-26: Unused filter imports
get_sorted_filter_ids and process_filter_functions appear unused. Kindly remove them to keep imports clean.

-from open_webui.utils.filter import (
-    get_sorted_filter_ids,
-    process_filter_functions,
-)
+# Remove or comment out if not used
🧰 Tools
🪛 Ruff (0.8.2)

24-24: open_webui.utils.filter.get_sorted_filter_ids imported but unused

Remove unused import

(F401)


25-25: open_webui.utils.filter.process_filter_functions imported but unused

Remove unused import

(F401)


192-198: Stripping


Your regex approach effectively removes reasoning details. Keep an eye on complexity for large inputs.


221-225: Optional “chat_id” usage
Static analysis recommends dropping the default “None”.

- "chat_id": form_data.get("chat_id", None),
+ "chat_id": form_data.get("chat_id"),
🧰 Tools
🪛 Ruff (0.8.2)

224-224: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)


255-260: Repeated direct-model check
Several endpoints check getattr(request.state, "direct", False) and request.state.model. Consider abstracting to a helper for maintainability.


319-389: New image prompt generation endpoint
Implementation parallels existing completions. You may reduce code duplication by creating a shared workflow function.

🧰 Tools
🪛 Ruff (0.8.2)

321-321: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


371-371: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)


383-383: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

backend/open_webui/routers/pipelines.py (1)

102-102: Raise exceptions with clearer context
When re-raising, consider using raise ... from e for clarity.

🧰 Tools
🪛 Ruff (0.8.2)

102-102: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

backend/open_webui/utils/audit.py (1)

210-215: Simplify the return
Static analysis suggests returning this condition directly for fewer branches.

- if pattern.match(request.url.path):
-     return True
- return False
+ return bool(pattern.match(request.url.path))
🧰 Tools
🪛 Ruff (0.8.2)

212-215: Return the condition bool(pattern.match(request.url.path)) directly

Replace with return bool(pattern.match(request.url.path))

(SIM103)

backend/open_webui/routers/audio.py (3)

269-272: Consider separate connect/read timeouts.
Specifying connect and read timeouts separately can provide finer control in case of partial slowdowns.


540-544: Graceful fallback on undetectable MIME type.
Falling back to "audio/wav" is sensible if mimetypes fails. Consider logging a warning to inform users about an unknown file extension.


575-579: Include original exception context when re-raising.
Raising an exception with raise ... from e helps preserve the original stack trace for debugging.

 except (KeyError, IndexError) as e:
     log.error(f"Malformed response from Deepgram: {str(e)}")
-    raise Exception("Failed to parse Deepgram response - unexpected response format")
+    raise Exception("Failed to parse Deepgram response - unexpected response format") from e
🧰 Tools
🪛 Ruff (0.8.2)

577-579: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

backend/open_webui/env.py (1)

420-442: Audit logging settings look good.
Consider validating the rotation size format (e.g., "10MB") in code if user input is untrusted.

backend/open_webui/utils/auth.py (2)

24-24: Remove or comment out unused imports.
Response is not used, so you can remove it to streamline imports.

-from fastapi import BackgroundTasks, Depends, HTTPException, Request, Response, status
+from fastapi import BackgroundTasks, Depends, HTTPException, Request, status
🧰 Tools
🪛 Ruff (0.8.2)

24-24: fastapi.Response imported but unused

Remove unused import: fastapi.Response

(F401)


87-89: Use direct attribute assignment instead of setattr.
This is clearer and aligns with best practices.

-    setattr(app.state, "USER_COUNT", v)
-elif k == "webui_name":
-    setattr(app.state, "WEBUI_NAME", v)
+    app.state.USER_COUNT = v
+elif k == "webui_name":
+    app.state.WEBUI_NAME = v
🧰 Tools
🪛 Ruff (0.8.2)

87-87: Do not call setattr with a constant attribute value. It is not any safer than normal property access.

Replace setattr with assignment

(B010)


89-89: Do not call setattr with a constant attribute value. It is not any safer than normal property access.

Replace setattr with assignment

(B010)

backend/open_webui/utils/oauth.py (2)

316-316: Remove unused variable assignment.

The user_count variable is assigned but never used in this code block.

- user_count = Users.get_num_users()
🧰 Tools
🪛 Ruff (0.8.2)

316-316: Local variable user_count is assigned to but never used

Remove assignment to unused variable user_count

(F841)


334-354: Consider combining nested with statements.

Similar to the earlier suggestion, the nested with statements here could be combined for better readability.

- async with aiohttp.ClientSession() as session:
-     async with session.get(picture_url, **get_kwargs) as resp:
+ async with aiohttp.ClientSession() as session, session.get(picture_url, **get_kwargs) as resp:
🧰 Tools
🪛 Ruff (0.8.2)

338-339: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)

backend/open_webui/routers/images.py (1)

433-450: Refactored URL image loading with improved error handling.

The function now supports custom headers and returns image data and MIME type instead of saving files directly.

Consider simplifying the conditional logic using a ternary operator:

- if headers:
-     r = requests.get(url, headers=headers)
- else:
-     r = requests.get(url)
+ r = requests.get(url, headers=headers) if headers else requests.get(url)
🧰 Tools
🪛 Ruff (0.8.2)

435-438: Use ternary operator r = requests.get(url, headers=headers) if headers else requests.get(url) instead of if-else-block

Replace if-else-block with r = requests.get(url, headers=headers) if headers else requests.get(url)

(SIM108)

backend/open_webui/utils/middleware.py (3)

41-45: Added imports for pipelines and improved modularity.

The new imports support the pipeline filtering mechanism, enhancing the modularity of the code.

However, the static analysis indicates that process_pipeline_outlet_filter is imported but not used.

- from open_webui.routers.pipelines import (
-     process_pipeline_inlet_filter,
-     process_pipeline_outlet_filter,
- )
+ from open_webui.routers.pipelines import process_pipeline_inlet_filter
🧰 Tools
🪛 Ruff (0.8.2)

44-44: open_webui.routers.pipelines.process_pipeline_outlet_filter imported but unused

Remove unused import: open_webui.routers.pipelines.process_pipeline_outlet_filter

(F401)


1233-1378: Complex content tag handler implementation.

The tag_content_handler function is quite complex and handles multiple tag types with a lot of regex operations. Consider adding more detailed comments explaining the function's behavior or splitting it into smaller, more focused functions.


1763-1947: Complex code interpreter execution logic.

The code interpreter execution logic is comprehensive but very complex. Consider breaking this into smaller functions with clear responsibilities to improve maintainability.

backend/open_webui/routers/files.py (1)

369-370: Add Chroma cleanup implementation.

The comment indicates a needed feature but lacks implementation. Consider implementing the Chroma cleanup or creating a follow-up task.

Would you like me to help generate a basic implementation for cleaning up Chroma collections related to deleted files?

backend/open_webui/utils/payload.py (1)

14-14: Avoid using default 'None' in params.get("system", None)

This is a minor style improvement suggested by static analysis. You can safely remove the redundant None default value:

- system = params.get("system", None)
+ system = params.get("system")
🧰 Tools
🪛 Ruff (0.8.2)

14-14: Use params.get("system") instead of params.get("system", None)

Replace params.get("system", None) with params.get("system")

(SIM910)

backend/open_webui/routers/utils.py (1)

27-27: Avoid Depends(...) calls in function parameter defaults

Static analysis (Ruff B008) warns against calling Depends in function defaults. This is more a stylistic matter than a functional bug, but you might consider moving these dependency calls inside the function body to align with recommended FastAPI patterns.

Also applies to: 36-36, 48-48, 81-81, 93-93

🧰 Tools
🪛 Ruff (0.8.2)

27-27: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/open_webui/retrieval/utils.py (4)

316-316: Avoid assigning a lambda to a variable.

Assigning lambdas to variables can reduce code readability and is flagged by linters. Prefer defining a named function or returning the lambda directly if functional style is desired.

-def func = lambda query, user=None: generate_embeddings(...)
+def generate_single_embedding(query, user=None):
+    return generate_embeddings(...)

...

-return lambda query, user=None: generate_multiple(query, user, func)
+def generate_multiple_embeds(query, user=None):
+    return generate_multiple(query, user, generate_single_embedding)

Also applies to: 337-337

🧰 Tools
🪛 Ruff (0.8.2)

316-323: Do not assign a lambda expression, use a def

Rewrite func as a def

(E731)


839-841: Combine multiple isinstance checks.

Merging these checks into a single isinstance call improves readability and aligns with recommended best practices.

-if (
-    isinstance(value, datetime)
-    or isinstance(value, list)
-    or isinstance(value, dict)
-):
+if isinstance(value, (datetime, list, dict)):

925-930: Use a context manager or specify exception types.

Catching all exceptions with a bare except: and ignoring them might hide real problems. Use contextlib.suppress for known exceptions or handle specific exception types.

-try:
-    VECTOR_DB_CLIENT.delete_collection(collection_name=f"file-{file.id}")
-except:
-    pass
+import contextlib
+with contextlib.suppress(SomeExpectedException):
+    VECTOR_DB_CLIENT.delete_collection(collection_name=f"file-{file.id}")

1042-1042: Refactor the conditional expression.

This can be simplified to a boolean cast for better readability and to comply with lint checks.

-add=(True if form_data.collection_name else False),
+add=bool(form_data.collection_name),
backend/open_webui/routers/retrieval.py (1)

474-478: Consider concurrency and resource usage in large-scale cases.

The code now uses run_in_threadpool for asynchronous document loading and indexing. For high-volume queries, ensure that concurrency limits and potential memory constraints are properly handled to avoid overwhelming the system.

backend/open_webui/routers/ollama.py (2)

1590-1590: Remove extraneous f prefixes.

Both log statements use f-strings without placeholders. They can be replaced with standard string literals.

- log.info(f"Uploaded to /api/blobs")
+ log.info("Uploaded to /api/blobs")

- log.info(f"API SUCCESS!")
+ log.info("API SUCCESS!")

Also applies to: 1614-1614

🧰 Tools
🪛 Ruff (0.8.2)

1590-1590: f-string without any placeholders

Remove extraneous f prefix

(F541)


1539-1635: Improve handling of partial or interrupted uploads.

While chunked uploads are effective for large files, consider adding a mechanism to handle partial uploads or network interruptions gracefully (e.g., resumable uploads or robust status checks) to minimize data corruption or repeated transfers.

🧰 Tools
🪛 Ruff (0.8.2)

1543-1543: Do not perform function call File in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


1545-1545: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


1590-1590: f-string without any placeholders

Remove extraneous f prefix

(F541)


1614-1614: f-string without any placeholders

Remove extraneous f prefix

(F541)

backend/open_webui/main.py (5)

108-121: Introduce code execution and interpreter config.

These environment variables (CODE_EXECUTION_ENGINE, CODE_EXECUTION_JUPYTER_URL, etc.) bring powerful features. Verify that untrusted code cannot be executed by default. Consider sandboxing, timeouts, or containerization for security.


382-387: ASCII banner display.

This welcome banner is purely cosmetic and does not affect functionality. Ensure it does not spam logs in production.


661-669: Configure code execution engine.

Storing code execution parameters (engine, URL, auth details) directly in app.state.config offers clarity but carry out robust validation and strict timeouts (line 668) to prevent resource abuse.


697-698: Gemini API parameters.

Assigning IMAGES_GEMINI_API_BASE_URL and IMAGES_GEMINI_API_KEY is helpful for alternative image generation sources. Confirm that secrets (API keys) aren’t leaked in logs.


901-913: Audit logging setup.

Configuring the AuditLoggingMiddleware with audit_level, excluded_paths, and max_body_size is a strong addition. Mind that the logs don’t accidentally capture sensitive user data.

backend/open_webui/config.py (5)

5-5: Remove unused import base64.

Static analysis indicates base64 is unused. Consider removing it to keep the codebase lean.

- import base64
🧰 Tools
🪛 Ruff (0.8.2)

5-5: base64 imported but unused

Remove unused import: base64

(F401)


366-389: Add GitHub OAuth config parameters.

Defining GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, etc. aligns with new OAuth providers. Verify they’re stored securely; rotation policies or secrets management might be necessary.


661-667: New LICENSE_KEY persistent config.

The PersistentConfig approach ensures the license is saved in the database. Confirm the UI or API properly notifies users if the key is invalid, and avoid storing it without encryption if it’s sensitive.


1142-1158: Default title generation prompt template.

This instructs models to produce a short title with optional emoji. Implementation is conceptually clear. Confirm the JSON structure is enforced in your prompt parsing logic.


1382-1413: Code execution config (interpreter).

Similar to lines 661–669, this chunk sets up environment for code interpreter. The logic largely repeats for the specialized code interpreter fields. Ensure duplication is intentional and well documented.

backend/open_webui/storage/provider.py (3)

102-129: S3StorageProvider upload and get_file.

Uploading starts by storing locally, then uploading that file to S3.

  • Consider using memory-only streams if large disk writes are unnecessary.
  • Within except ClientError blocks (lines 131, 141, 149, 168), follow best practices to chain exceptions for improved traceback:
- except ClientError as e:
-     raise RuntimeError(f"Error uploading file to S3: {e}")
+ except ClientError as e:
+     raise RuntimeError(f"Error uploading file to S3: {e}") from e

143-153: S3 delete logic.

Deletes from S3, then calls local removal. This order is sensible. Again, consider explicit exception chaining in the except blocks for clarity.

🧰 Tools
🪛 Ruff (0.8.2)

149-149: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


154-172: Delete all files from S3.

Lists objects, removes those matching key_prefix. Then removes local. Good approach—just be wary of bucket with large object counts. Consider pagination or concurrency as optimization if needed.

🧰 Tools
🪛 Ruff (0.8.2)

168-168: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3e3393e and 95e6996.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (50)
  • CHANGELOG.md (1 hunks)
  • backend/open_webui/config.py (31 hunks)
  • backend/open_webui/env.py (6 hunks)
  • backend/open_webui/functions.py (3 hunks)
  • backend/open_webui/main.py (38 hunks)
  • backend/open_webui/models/chats.py (8 hunks)
  • backend/open_webui/models/feedbacks.py (1 hunks)
  • backend/open_webui/models/files.py (1 hunks)
  • backend/open_webui/models/folders.py (1 hunks)
  • backend/open_webui/models/functions.py (4 hunks)
  • backend/open_webui/models/models.py (2 hunks)
  • backend/open_webui/models/tags.py (1 hunks)
  • backend/open_webui/models/tools.py (4 hunks)
  • backend/open_webui/retrieval/loaders/main.py (3 hunks)
  • backend/open_webui/retrieval/models/colbert.py (1 hunks)
  • backend/open_webui/retrieval/utils.py (11 hunks)
  • backend/open_webui/retrieval/vector/dbs/chroma.py (4 hunks)
  • backend/open_webui/retrieval/vector/dbs/milvus.py (3 hunks)
  • backend/open_webui/retrieval/vector/dbs/pgvector.py (12 hunks)
  • backend/open_webui/retrieval/vector/dbs/qdrant.py (3 hunks)
  • backend/open_webui/routers/audio.py (15 hunks)
  • backend/open_webui/routers/auths.py (21 hunks)
  • backend/open_webui/routers/files.py (10 hunks)
  • backend/open_webui/routers/functions.py (6 hunks)
  • backend/open_webui/routers/groups.py (7 hunks)
  • backend/open_webui/routers/images.py (17 hunks)
  • backend/open_webui/routers/knowledge.py (11 hunks)
  • backend/open_webui/routers/ollama.py (50 hunks)
  • backend/open_webui/routers/openai.py (18 hunks)
  • backend/open_webui/routers/pipelines.py (11 hunks)
  • backend/open_webui/routers/retrieval.py (33 hunks)
  • backend/open_webui/routers/tasks.py (20 hunks)
  • backend/open_webui/routers/tools.py (10 hunks)
  • backend/open_webui/routers/utils.py (3 hunks)
  • backend/open_webui/storage/provider.py (1 hunks)
  • backend/open_webui/utils/audit.py (1 hunks)
  • backend/open_webui/utils/auth.py (4 hunks)
  • backend/open_webui/utils/chat.py (5 hunks)
  • backend/open_webui/utils/filter.py (1 hunks)
  • backend/open_webui/utils/logger.py (1 hunks)
  • backend/open_webui/utils/middleware.py (28 hunks)
  • backend/open_webui/utils/misc.py (7 hunks)
  • backend/open_webui/utils/models.py (3 hunks)
  • backend/open_webui/utils/oauth.py (13 hunks)
  • backend/open_webui/utils/payload.py (4 hunks)
  • backend/open_webui/utils/plugin.py (2 hunks)
  • backend/open_webui/utils/response.py (2 hunks)
  • backend/requirements.txt (7 hunks)
  • package.json (5 hunks)
  • pyproject.toml (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • backend/open_webui/utils/plugin.py
  • backend/open_webui/utils/models.py
  • backend/open_webui/functions.py
  • backend/open_webui/routers/tools.py
  • backend/requirements.txt
  • package.json
🧰 Additional context used
🪛 Ruff (0.8.2)
backend/open_webui/routers/knowledge.py

20-20: open_webui.storage.provider.Storage imported but unused

Remove unused import: open_webui.storage.provider.Storage

(F401)

backend/open_webui/routers/auths.py

169-169: Local variable LDAP_SERVER_LABEL is assigned to but never used

Remove assignment to unused variable LDAP_SERVER_LABEL

(F841)

backend/open_webui/routers/tasks.py

24-24: open_webui.utils.filter.get_sorted_filter_ids imported but unused

Remove unused import

(F401)


25-25: open_webui.utils.filter.process_filter_functions imported but unused

Remove unused import

(F401)


224-224: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)


299-299: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)


321-321: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


371-371: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)


383-383: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


454-454: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)


541-541: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)


613-613: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)


681-681: Use form_data.get("chat_id") instead of form_data.get("chat_id", None)

Replace form_data.get("chat_id", None) with form_data.get("chat_id")

(SIM910)

backend/open_webui/utils/middleware.py

8-8: aiocache.cached imported but unused

Remove unused import: aiocache.cached

(F401)


9-9: typing.Any imported but unused

Remove unused import: typing.Any

(F401)


10-10: random imported but unused

Remove unused import: random

(F401)


13-13: inspect imported but unused

Remove unused import: inspect

(F401)


44-44: open_webui.routers.pipelines.process_pipeline_outlet_filter imported but unused

Remove unused import: open_webui.routers.pipelines.process_pipeline_outlet_filter

(F401)


64-64: open_webui.utils.misc.deep_update imported but unused

Remove unused import: open_webui.utils.misc.deep_update

(F401)


73-73: open_webui.utils.plugin.load_function_module_by_id imported but unused

Remove unused import: open_webui.utils.plugin.load_function_module_by_id

(F401)


437-437: Local variable negative_prompt is assigned to but never used

Remove assignment to unused variable negative_prompt

(F841)


462-462: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


500-500: f-string without any placeholders

Remove extraneous f prefix

(F541)


548-548: Do not use bare except

(E722)


699-699: Local variable variables is assigned to but never used

Remove assignment to unused variable variables

(F841)


718-718: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


899-899: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


1197-1197: Loop control variable idx not used within loop body

Rename unused idx to _idx

(B007)


1392-1392: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


1627-1629: Use a single if statement instead of nested if statements

(SIM102)

backend/open_webui/utils/audit.py

212-215: Return the condition bool(pattern.match(request.url.path)) directly

Replace with return bool(pattern.match(request.url.path))

(SIM103)

backend/open_webui/utils/auth.py

12-12: typing.List imported but unused

Remove unused import

(F401)


12-12: typing.Dict imported but unused

Remove unused import

(F401)


24-24: fastapi.Response imported but unused

Remove unused import: fastapi.Response

(F401)


87-87: Do not call setattr with a constant attribute value. It is not any safer than normal property access.

Replace setattr with assignment

(B010)


89-89: Do not call setattr with a constant attribute value. It is not any safer than normal property access.

Replace setattr with assignment

(B010)

backend/open_webui/routers/pipelines.py

95-95: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


102-102: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


144-144: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

backend/open_webui/routers/images.py

435-438: Use ternary operator r = requests.get(url, headers=headers) if headers else requests.get(url) instead of if-else-block

Replace if-else-block with r = requests.get(url, headers=headers) if headers else requests.get(url)

(SIM108)

backend/open_webui/utils/chat.py

13-13: fastapi.status imported but unused

Remove unused import: fastapi.status

(F401)


14-14: starlette.responses.Response imported but unused

Remove unused import

(F401)


14-14: starlette.responses.JSONResponse imported but unused

Remove unused import

(F401)


17-17: open_webui.models.users.UserModel imported but unused

Remove unused import: open_webui.models.users.UserModel

(F401)


128-131: Use contextlib.suppress(Exception) instead of try-except-pass

Replace with contextlib.suppress(Exception)

(SIM105)


130-130: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


226-226: Avoid equality comparisons to True; use if form_data.get("stream"): for truth checks

Replace with form_data.get("stream")

(E712)

backend/open_webui/storage/provider.py

131-131: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


141-141: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


149-149: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


168-168: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


204-204: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


216-216: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


225-225: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


239-239: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


274-274: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


286-286: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


295-295: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


307-307: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

backend/open_webui/routers/ollama.py

1590-1590: f-string without any placeholders

Remove extraneous f prefix

(F541)


1614-1614: f-string without any placeholders

Remove extraneous f prefix

(F541)

backend/open_webui/retrieval/utils.py

18-18: open_webui.utils.misc.get_last_user_message imported but unused

Remove unused import

(F401)


18-18: open_webui.utils.misc.calculate_sha256_string imported but unused

Remove unused import

(F401)


316-323: Do not assign a lambda expression, use a def

Rewrite func as a def

(E731)


459-459: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

backend/open_webui/utils/misc.py

8-8: typing.Callable imported but unused

Remove unused import: typing.Callable

(F401)

backend/open_webui/routers/retrieval.py

839-841: Multiple isinstance calls for value, merge into a single call

Merge isinstance calls for value

(SIM101)


925-930: Use contextlib.suppress(Exception) instead of try-except-pass

(SIM105)


928-928: Do not use bare except

(E722)


1042-1042: Use bool(...) instead of True if ... else False

Replace with `bool(...)

(SIM210)

backend/open_webui/main.py

162-162: open_webui.config.WHISPER_MODEL_AUTO_UPDATE imported but unused

Remove unused import

(F401)


163-163: open_webui.config.WHISPER_MODEL_DIR imported but unused

Remove unused import

(F401)


166-166: open_webui.config.DEFAULT_RAG_TEMPLATE imported but unused

Remove unused import

(F401)


225-225: Redefinition of unused ONEDRIVE_CLIENT_ID from line 101

Remove definition: ONEDRIVE_CLIENT_ID

(F811)


227-227: open_webui.config.ENABLE_RAG_LOCAL_WEB_FETCH imported but unused

Remove unused import

(F401)


993-993: Use form_data.get("model") instead of form_data.get("model", None)

Replace form_data.get("model", None) with form_data.get("model")

(SIM910)


1021-1021: Use form_data.get("variables") instead of form_data.get("variables", None)

Replace form_data.get("variables", None) with form_data.get("variables")

(SIM910)


1045-1048: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


1247-1247: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/open_webui/config.py

5-5: base64 imported but unused

Remove unused import: base64

(F401)

backend/open_webui/models/chats.py

2-2: json imported but unused

Remove unused import: json

(F401)


8-8: open_webui.models.tags.Tag imported but unused

Remove unused import: open_webui.models.tags.Tag

(F401)

backend/open_webui/retrieval/vector/dbs/chroma.py

110-110: Do not use bare except

(E722)

backend/open_webui/routers/audio.py

577-579: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


599-599: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

backend/open_webui/routers/files.py

38-38: Do not perform function call File in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


39-39: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


40-40: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)

backend/open_webui/routers/groups.py

46-46: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/open_webui/routers/utils.py

27-27: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


36-36: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


43-43: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


48-48: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


81-81: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


93-93: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/open_webui/utils/filter.py

85-86: Use a single if statement instead of nested if statements

(SIM102)

backend/open_webui/utils/oauth.py

257-260: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


284-284: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


316-316: Local variable user_count is assigned to but never used

Remove assignment to unused variable user_count

(F841)


338-339: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)

backend/open_webui/utils/payload.py

14-14: Use params.get("system") instead of params.get("system", None)

Replace params.get("system", None) with params.get("system")

(SIM910)


76-76: Local variable param is assigned to but never used

(F841)


76-76: Use params.get(key) instead of params.get(key, None)

Replace params.get(key, None) with params.get(key)

(SIM910)

🪛 markdownlint-cli2 (0.17.2)
CHANGELOG.md

21-21: Bare URL used
null

(MD034, no-bare-urls)


218-218: Bare URL used
null

(MD034, no-bare-urls)

🔇 Additional comments (198)
backend/open_webui/retrieval/models/colbert.py (1)

8-11: LGTM: Good logging configuration.

Properly setting up logging with configurable log levels is a good practice. This helps with debugging and monitoring while allowing centralized control over verbosity.

backend/open_webui/retrieval/vector/dbs/qdrant.py (4)

2-2: Use of logging library
Importing the logging module is a good practice that aligns with structured logging throughout the codebase.


10-10: Ensure environment variable usage
Importing SRC_LOG_LEVELS is correct, but verify that the environment variable or configuration is properly set to avoid potential runtime errors.


57-57: Replacing print with log
Using log.info here is a great improvement over print statements for better log management.


128-128: Structured error handling
Replacing print with log.exception greatly improves traceability of errors by including stack traces.

backend/open_webui/utils/misc.py (7)

5-5: Structured logging adoption
Good choice to switch to the logging library for consistent log management.


11-11: Check usage of collections.abc
This import is valid since it’s used for mapping checks in deep_update.


12-12: Reliance on environment-based log levels
Ensure SRC_LOG_LEVELS["MAIN"] is consistently defined for all modules to prevent KeyErrors or mismatched logging levels.


40-40: Return None consistency
Returning None if a message is not found matches typical Python conventions.


199-218: Enhanced template parameters
Adding content and tool_calls for openai_chat_chunk_message_template provides flexibility. Verify all callers pass these arguments or handle None gracefully.


224-238: Consistency with chunk message template
The modifications for openai_chat_completion_message_template mirror the chunk template changes. Ensure both are used consistently.


420-420: Improved exception logging
Using log.exception here captures stack trace details for debugging parameter parsing.

backend/open_webui/models/files.py (1)

122-122: Improved error logging

Replacing print statements with structured logging is a good practice. Using log.exception() instead of a simple print statement not only logs the error message but also captures the full traceback, which is crucial for debugging.

backend/open_webui/models/feedbacks.py (1)

121-121: Enhanced error reporting

Good improvement replacing the print statement with proper logging. The log.exception() method provides more context and captures the full traceback compared to simple print statements.

backend/open_webui/models/tags.py (1)

64-64: Better error handling with structured logging

Using log.exception() provides a more comprehensive error report than print statements by capturing the full exception traceback. This is part of a consistent improvement across the codebase.

backend/open_webui/models/tools.py (4)

134-134: Improved error logging with context

Good switch from print statement to structured logging with log.exception(), which captures the full traceback for better debugging.


178-178: Enhanced error reporting with method context

The error message now includes both the method context (getting tool valves) and the specific ID, which will make troubleshooting much easier.


207-209: Better error reporting with detailed context

Good improvement in error reporting by providing both the tool ID and user ID in the error message. The multi-line formatting also improves readability of the complex string.


232-234: Comprehensive error logging with operation details

Error message now clearly indicates which operation failed (updating user valves) and includes both IDs needed for troubleshooting, making debugging much more efficient.

backend/open_webui/models/folders.py (1)

85-85: Use of structured logging is a good practice.

Replacing a print statement with log.exception is an improvement as it provides better clarity and stack traces for debugging.

backend/open_webui/retrieval/vector/dbs/chroma.py (1)

2-3: Structured logger initialization looks good.

Initializing a logger here and setting it to a configured log level is a solid approach for consistent, centralized logging.

Also applies to: 20-23

backend/open_webui/models/models.py (2)

169-169: Switched to structured logging.

Using log.exception improves error visibility over a plain print.


249-249: Consistent exception logging.

Replacing print with log.exception aligns with the project's enhanced error handling strategy.

backend/open_webui/retrieval/loaders/main.py (4)

7-7: New loader import recognized.

Importing AzureAIDocumentIntelligenceLoader paves the way for enhanced document parsing from Azure’s services.


80-80: Adding "json" to known source extensions is beneficial.

Properly covering JSON ensures that the loader can handle or differentiate JSON files.


152-167: Conditional check for Azure Document Intelligence Loader.

The condition ensures that the necessary endpoint, key, and file types are provided. This is a good approach to controlling loader behavior.


168-172: AzureAIDocumentIntelligenceLoader usage is correct.

This instantiation passes essential credentials and file path to the loader. Remember to verify secure handling of the key.

backend/open_webui/retrieval/vector/dbs/milvus.py (3)

4-4: Good addition of structured logging.

Replacing print statements with proper logging is a great improvement for maintainability and observability.

Also applies to: 13-16


22-25: Improved client initialization with conditional token handling.

The conditional initialization based on MILVUS_TOKEN presence provides better flexibility and security.


175-175: Enhanced error logging with better context.

Replacing print statements with appropriate logging levels and adding detailed error context will help with debugging and monitoring.

Also applies to: 202-202, 205-207

backend/open_webui/routers/functions.py (4)

2-2: Good addition of structured logging.

Replacing print statements with proper logging is a great improvement for maintainability and observability.

Also applies to: 17-20


88-88: Enhanced exception logging.

Improved error handling with structured logging to capture function creation failures.


192-192: Added debug logging for function updates.

This helps with troubleshooting by logging the updated function data.


308-308: Improved error context in exception logging.

Adding function and ID information to the exception logs will make troubleshooting easier.

Also applies to: 397-397

backend/open_webui/models/functions.py (2)

108-108: Enhanced error logging.

Improved error reporting for function creation failures.


173-173: Improved error context in exception logging.

Adding function and user ID information to the exception logs will make troubleshooting easier.

Also applies to: 205-207, 230-232

backend/open_webui/routers/groups.py (3)

46-46: Fixed function name to match its purpose.

Renamed from create_new_function to create_new_group, which correctly reflects the function's purpose.

Note: The static analysis warning about using Depends in the argument default is a false positive, as this is the standard pattern in FastAPI.

🧰 Tools
🪛 Ruff (0.8.2)

46-46: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


91-93: Added user validation before updating groups.

Good addition of user validation to ensure only valid user IDs are added to groups.


57-57: Enhanced error logging with better context.

Replacing print statements with exception logging and adding context about the specific group ID will help with debugging.

Also applies to: 103-103, 127-127

backend/open_webui/retrieval/vector/dbs/pgvector.py (12)

2-2: Switching to structured logging is beneficial.

Importing the logging module is appropriate here. Ensure that print statements across the module are fully replaced with logging calls for consistency.


13-13: Good use of SQLAlchemy's Table.

By using Table directly, the reflection approach becomes more flexible. Just ensure you’ve tested table reflection with partial or missing schemas if that’s a possibility in your environment.


23-23: Catching NoSuchTableError is sensible.

This is effective for handling missing tables gracefully. Keep an eye out for any additional exception classes if multiple table checks are introduced later.


28-29: Proper usage of SRC_LOG_LEVELS.

Importing environment-based log levels ensures consistent logging configurations across modules. This is a good approach for centralized log-level management.


103-111: Reflection logic for document_chunk table.

This approach to reflect the table is correct, and the NoSuchTableError handling is properly placed. Ensure that any future migrations or table renames are also accounted for.


112-130: Detailed checks on the vector column.

The dimension consistency checks look robust. Using clear exception messages for mismatches helps devs understand the necessary migration process.


321-321: Exception logging in query.

Everything looks good. As with other methods, providing relevant contextual info (e.g., filter values) could be beneficial in logs.


345-345: Exception logging in get.

Same pattern here—solid usage of log.exception.


367-367: Informational logging for deletion.

Logging the number of items deleted gives insight into DB operations. This is helpful for auditing.


377-379: Ensuring file reprocessing with process_file.

Be mindful of concurrency. If the same file is processed concurrently, ensure race conditions or partial updates won’t corrupt metadata or DB state.


398-398: Exception logging for has_collection().

Return of False in error scenarios is consistent, but be certain no call sites need to differentiate between errors and a missing collection.


403-403: Cleanup log message on collection deletion.

This info-level log is good for monitoring, especially if you have to trace usage or removal frequency of knowledge collections.

backend/open_webui/utils/filter.py (6)

1-2: Imports for inspection and logging.

Using inspect can be powerful for dynamically assembling handler arguments. Ensure performance remains acceptable when used repeatedly.


4-6: Appropriate environment-based logging.

load_function_module_by_id and SRC_LOG_LEVELS references are consistent with your new logging approach. Good job centralizing configuration.


8-9: Logger setup.

The logger is created and leveled with "MAIN". Confirm "MAIN" is a defined key in SRC_LOG_LEVELS to avoid runtime issues.


12-32: get_sorted_filter_ids: Priority-based sorting.

The logic correctly extracts and sorts filter IDs by a configurable priority. Consider adding warnings or logs if some filters can’t be found or remain inactive.


67-106: Parameter assembly and dynamic call.

Combining user valves with the function signature is well structured. Watch out for large form_data objects to avoid performance hits.

🧰 Tools
🪛 Ruff (0.8.2)

85-86: Use a single if statement instead of nested if statements

(SIM102)


107-110: File skipping logic.

Removing file metadata from form_data can prevent unintended processing. This is a good example of providing an “escape hatch” for certain filter operations.

backend/open_webui/routers/knowledge.py (8)

28-28: Models, ModelForm import.

Used later for referencing model data. Ensure that circular-import issues are handled if knowledge references models while models reference knowledge.


216-221: Write-access checks for knowledge updating.

Nicely ensures only original creators, group members with write privileges, or admins can modify knowledge. The role-based check is correct.


267-271: Access checks before file addition.

Consistent with your approach in other routes. This ensures data consistency and user isolation.


351-355: Updating an existing file within knowledge.

The vector DB removal followed by reprocessing ensures updated content is reflected accurately. Validate that partial reprocesses don’t lead to mismatch states.


423-426: Removal access checks.

Again, consistent with your overall knowledge base permission model. Good approach.


501-504: Delete knowledge permission check.

Same pattern as other knowledge modifications. Maintaining consistency is helpful for maintainability.


510-539: Model references cleanup on knowledge deletion.

Updating all models to remove references to this knowledge base ensures no orphan references remain. This is a thorough approach; well done.


617-617: Bulk file additions logging.

Logging the count of files helps track usage. This block properly ensures only valid files are processed.

backend/open_webui/utils/logger.py (1)

1-141: New structured logging utility.

  1. Blending Loguru with Python’s standard logging is powerful.
  2. InterceptHandler ensures all logs come through a unified pipeline.
  3. file_format method with JSON is excellent for downstream analytics.
  4. start_logger function provides a clear, centralized init.

Overall, the module is well-organized and significantly improves logging consistency.

backend/open_webui/utils/response.py (6)

9-24: Well-structured conversion utility for tool calls.

The new function convert_ollama_tool_call_to_openai provides a clean way to transform Ollama tool calls to OpenAI format. The function properly handles missing fields with sensible defaults and generates UUIDs for calls without IDs.


27-80: Comprehensive usage metrics conversion with proper error handling.

This function provides a thorough transformation of Ollama usage metrics to OpenAI-compatible format, with appropriate handling of edge cases (like division by zero) and clear documentation of equivalent fields.


86-90: Clean implementation of tool calls processing.

The code now properly detects and handles tool calls in responses, using the new conversion utility function for consistent formatting.


94-94: Modularized usage metrics conversion.

Good refactoring to use the dedicated conversion function rather than inline calculation, improving maintainability.


107-112: Consistent handling of streaming tool calls.

The streaming response handler now properly processes tool calls using the same conversion logic as the non-streaming handler, ensuring consistency.


118-118: Unified usage metrics handling.

Using the same conversion function for both streaming and non-streaming responses ensures consistent behavior.

backend/open_webui/utils/chat.py (2)

63-156: Well-implemented direct chat completion function.

The new generate_direct_chat_completion function introduces a robust mechanism for handling direct model connections with proper WebSocket communication. The implementation correctly handles both streaming and non-streaming responses, with appropriate error handling.

🧰 Tools
🪛 Ruff (0.8.2)

128-131: Use contextlib.suppress(Exception) instead of try-except-pass

Replace with contextlib.suppress(Exception)

(SIM105)


130-130: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


158-195: Enhanced chat completion with direct connection support.

The modified generate_chat_completion function now checks for direct connections and delegates to the new direct chat completion function when appropriate. This provides a clean integration path for the new functionality.

CHANGELOG.md (2)

8-14: Comprehensive documentation of important fixes in 0.5.18.

The changelog properly documents the critical fixes in this version, providing clear information about what issues were resolved.


16-36: Detailed feature documentation for version 0.5.17.

The changelog provides comprehensive information about new features, fixes and changes in version 0.5.17, making it easy for users to understand what's new.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

21-21: Bare URL used
null

(MD034, no-bare-urls)

backend/open_webui/models/chats.py (4)

20-21: Proper logging setup.

Adding a logger with appropriate log level configuration is a good practice for structured logging.


400-400: Query simplification in get_chat_list_by_user_id.

Removing the filter for folder_id allows retrieving all chats for a user regardless of folder association, which appears to be a deliberate change to expand the query's scope.


477-477: Improved comment clarity.

The updated comment better explains the logic for checking if a chat is still shared.


677-677: Replaced print statements with proper logging.

Converting print statements to structured logging is a good practice for better observability and log management.

Also applies to: 738-738, 759-759, 817-817

backend/open_webui/routers/auths.py (21)

28-29: Use environment-based cookie settings
Great to see these environment variables in use for cookie configuration. This approach is more secure and flexible.


34-34: Import for LDAP and OAuth
Straightforward import addition. No issues here.


52-54: Conditional import for LDAP modules
Using ENABLE_LDAP.value to guard LDAP imports prevents unnecessary overhead when LDAP is disabled. Looks good.


97-98: Secure cookie parameters
Including httponly=True, samesite, and secure is a best practice to protect session cookies.


163-166: Updated response model for LDAP authentication
The endpoint now returns SessionUserResponse. Verify your frontend and any other consumers expect this shape.


172-172: Environment variable for LDAP mail attribute
Ensure LDAP_ATTRIBUTE_FOR_MAIL is properly set in all environments.


221-225: Expanded LDAP search attributes
Including the mail attribute is necessary for identifying user emails. This is a sensible addition.


233-235: Blocking LDAP sign-in without an email
Throwing an exception when mail is missing prevents ambiguous user records and is good practice.


253-254: Retrieving user count
Using Users.get_num_users() is fine here. Monitor performance on very large user stores.


257-257: First LDAP user as admin
Assigning admin rights on the first user is a design choice—confirm this is desired for production.


292-294: Fetching user permissions
Looks good. This code cleanly centralizes permission retrieval.


304-304: Include permissions in response
Consistent with the rest of your response structure. No issues.


387-388: Cookie security on sign-in
Again, using samesite and secure for session cookies is commendable.


432-432: LDAP sign-up user count
Same user counting approach. No concerns at this point.


442-442: Assigning default role
Double-check that your workflow demands making the first user an admin for all signups.


482-483: Secure cookie on signup
Ensuring session cookies have secure attributes is fundamental for production security.


709-709: Default mail attribute
A sane default (“mail”) helps standardize LDAP mail lookups.


726-726: Retrieve mail attribute in server config
No issue. This complements the new LDAP configuration logic.


738-738: New admin route for LDAP server config
Providing an endpoint for LDAP server configuration changes is handy and straightforward.


745-745: Mail attribute as required
Good job enforcing mail as part of the required fields.


780-780: Returning “attribute_for_mail”
Nice to expose the updated field in the response for clarity.

backend/open_webui/routers/tasks.py (11)

7-7: Regex import
Direct usage of re is clear for the upcoming text transformations.


13-13: Added template import
Importing image_prompt_generation_template aligns with the new image prompt endpoint.


32-32: New default image prompt template
Adding DEFAULT_IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE ensures consistent fallback logic.


60-60: Expose image prompt template
Surfacing IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE in config matches your new feature.


65-65: Enable title generation
Likewise, exposing ENABLE_TITLE_GENERATION in the config endpoint keeps the UI in sync.


76-76: New boolean field
ENABLE_TITLE_GENERATION in TaskConfigForm is straightforward and well-typed.


78-78: String field for image prompt template
A strong addition for custom image prompt formatting.


95-95: Apply new config
Assigning ENABLE_TITLE_GENERATION from the form data correctly updates the config.


100-102: Apply custom image prompt generation template
Implementation is consistent with other config fields.


132-134: Confirming new config fields
Returning ENABLE_TITLE_GENERATION and IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE helps ensure the UI shows updated values.


150-155: Disable title generation
This early return clarifies that title generation is off, preventing unnecessary processing.

backend/open_webui/routers/pipelines.py (3)

12-12: Async I/O
Switching to aiohttp fosters non-blocking flows for the pipeline. Good improvement.


95-95: Unused exception variable
You previously flagged this in older commits; removing e is best to avoid confusion.

-except aiohttp.ClientResponseError as e:
+except aiohttp.ClientResponseError:
🧰 Tools
🪛 Ruff (0.8.2)

95-95: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


144-144: Unused variable in outlet filter
Same scenario as before: remove e if unused.

-except aiohttp.ClientResponseError as e:
+except aiohttp.ClientResponseError:
🧰 Tools
🪛 Ruff (0.8.2)

144-144: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

backend/open_webui/utils/audit.py (3)

1-35: New module for audit logging
Introduces structured auditing classes and context managers. The design is clear and well-documented.


36-91: AuditLogEntry and AuditLogger
Data classes and logger binding are well-structured and should help produce consistent audit records.


92-250: Audit logging middleware
This middleware effectively intercepts requests and captures relevant data. Carefully consider the overhead of storing request/response bodies for large payloads, but it appears you have a cap with MAX_BODY_LOG_SIZE.

🧰 Tools
🪛 Ruff (0.8.2)

212-215: Return the condition bool(pattern.match(request.url.path)) directly

Replace with return bool(pattern.match(request.url.path))

(SIM103)

backend/open_webui/routers/audio.py (7)

14-14: Import usage looks good.
The mimetypes import is correctly used later to guess file types for Deepgram support.


40-40: Importing the new timeout configuration is fine.
No further remarks on this addition.


74-74: Clearer logging for missing files.
Logging an error here can help identify misconfigurations or unexpected audio paths.


91-91: Useful conversion log message.
This log statement helps track audio conversions; no issues found.


329-332: Same suggestion regarding timeouts.
The mention about separate connect/read timeouts also applies here.


389-392: Same suggestion regarding timeouts.
The recommendation to specify more granular timeouts applies here as well.


469-469: Informative log statement looks good.
This helps trace audio transcription requests succinctly.

backend/open_webui/env.py (7)

57-57: CUDA to MPS fallback block usage looks fine.
This import under a try is consistent with checking for device availability.


95-95: New log source "OAUTH" is fine.
No issues—just be sure it is used where relevant.


110-110: Default name change is straightforward.
It’s acceptable to rename the application in this way.


112-112: Favicon URL default looks good.
No concerns regarding the updated default.


114-114: Verify that the signature key is properly encoded.
Be aware that environment variables are typically strings, and downstream code may need to encode it into bytes for HMAC usage.


279-279: Database schema variable introduced.
No issues, ensures flexible schema usage if multiple schemas are needed.


359-375: Confirm secure cookie settings in production.
Using Secure=True and strict SameSite can prevent session hijacking, but double-check that these reflect the intended environment.

backend/open_webui/utils/auth.py (4)

4-8: Imports are used, except note the static analysis for unused references below.
Base modules appear relevant for new functions like signature verification.


31-32: Fine-grained log level usage.
Redirecting auth-specific logs to "OAUTH" source can help isolate security events.


58-69: Path check is partial.
If the environment includes Windows backslashes or other edge cases, this might be bypassed. Please see past reviewer suggestions regarding normalizing paths to avoid directory traversal.


153-153: Asynchronous user update is well-implemented.
Adding BackgroundTasks to refresh last active timestamps without blocking the request is a good design choice.

backend/open_webui/utils/oauth.py (5)

4-5: Import additions and environment variables look good.

The added imports for sys and additional environment variables for cookie security settings enhance the functionality and configuration options.

Also applies to: 38-43


73-77: Good enhancement with app parameter in the constructor.

Storing the app as an instance variable and refactoring the provider registration process to use a register method simplifies the initialization logic.


109-113: Enhanced debugging with detailed log statements.

The additional logging for OAuth roles provides better visibility into the authorization process, which is helpful for troubleshooting.


154-159: Improved debugging in group management.

The additional log statements help track OAuth group processing, making it easier to debug group-related issues.


415-417: Good security enhancement with configurable cookie settings.

Using environment variables for cookie security settings allows for better security configuration across different environments.

backend/open_webui/routers/images.py (11)

58-61: Good addition of Gemini configuration to API response.

Adding Gemini configuration to the config endpoint response makes it accessible to the client.


85-88: Clean implementation of GeminiConfigForm.

The new Gemini configuration form follows the established pattern of other provider forms.


93-93: Updated ConfigForm with new properties.

The ConfigForm has been appropriately updated to include the new prompt_generation flag and Gemini configuration.

Also applies to: 97-97


107-109: Added support for image prompt generation configuration.

This configuration option will allow enabling/disabling automatic prompt generation for images.


116-120: Added Gemini API configuration handling.

The implementation properly stores Gemini API configuration in the application state.


256-261: Good addition of Gemini model support.

The implementation follows the pattern established for other image generation models.


418-430: Refactored image loading from base64.

The function has been improved to return image data and MIME type instead of saving files directly, enhancing modularity.


453-465: Good implementation of image upload utility.

This function centralizes the image upload logic, making the code more maintainable and reusable.


525-557: Well-implemented Gemini image generation support.

The Gemini API integration follows the pattern of other image generation engines and includes proper error handling.


597-612: Added headers support and improved image upload for ComfyUI.

The changes allow for authentication headers when accessing ComfyUI generated images and use the centralized upload function.


656-664: Consolidated image upload for Automatic1111.

Using the centralized upload_image function makes the code more consistent across different image generation engines.

backend/open_webui/utils/middleware.py (9)

15-16: New imports for enhanced functionality.

The addition of re and ast modules support the new parsing and processing capabilities in the middleware.


102-103: Updated tools handler signature.

The function now accepts a tools parameter instead of extra_params, making the parameter name more semantically meaningful.


179-245: Well-implemented async tool call handler.

The refactoring using an inner async function for tool call handling improves code organization and readability. The tool output processing logic is also well-structured.


422-513: Strong implementation of image generation in chat.

The new chat_image_generation_handler adds support for generating images based on user messages, with appropriate error handling and user feedback.

🧰 Tools
🪛 Ruff (0.8.2)

437-437: Local variable negative_prompt is assigned to but never used

Remove assignment to unused variable negative_prompt

(F841)


462-462: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


500-500: f-string without any placeholders

Remove extraneous f prefix

(F541)


554-574: Improved file source retrieval with async execution.

The refactoring to use a ThreadPoolExecutor for get_sources_from_files improves performance by offloading the potentially expensive operation to a separate thread.


611-613: Added support for reasoning effort parameter.

This enhancement provides more control over the reasoning process.


1080-1089: Added helper function for content processing.

The split_content_and_whitespace function cleanly separates content from trailing whitespace, which is useful for preservation during transformations.


1090-1094: Added code block detection function.

The is_opening_code_block function uses a clever approach to detect if the current string is opening a new code block by counting backtick segments.


748-748:

❓ Verification inconclusive

Consider including a check for empty files.

The code assumes files is not None after popping it, but it could be empty. Consider adding an explicit check.


🏁 Script executed:

#!/bin/bash
# Look for any places where files is checked for None vs. empty
rg -A 3 "files = form_data\.pop\(\"files\", None\)" --include "*.py"
rg -A 5 "if files:" --include "*.py"

Length of output: 991


Below is a revised review comment that reflects the need to address an empty list even when the popped value isn’t None. (Note that since our initial rg-based search didn’t produce useful results due to incorrect flag usage, please manually verify the exact locations where—if at all—an empty files list is handled.)


Action Item: Ensure explicit handling of empty file lists

It appears that while the code pops "files" from the request data with a default of None, there isn’t a check for the case where "files" is an empty collection. Even if "files" isn’t None, an empty list might lead to unexpected behavior later on. Consider adding an explicit conditional, for example:

files = form_data.pop("files", None)
if not files:
    # Handle the empty files case explicitly,
    # e.g., by returning an error response or taking an alternate code path.

This additional check will make the code more robust in handling edge cases.

backend/open_webui/routers/files.py (5)

64-64: Good enhancement with file metadata inclusion.

Including the provided metadata in the file's meta object allows for rich context to be associated with uploaded files.


71-86: Excellent addition of audio transcription support.

Detecting audio file types and automatically transcribing them before processing is a valuable enhancement that improves the user experience.


209-210: Added user context to process_file.

Passing the user to process_file provides better context for file processing operations.


244-261: Improved content type handling for file responses.

The enhanced logic to handle PDF files with inline display improves the user experience when viewing document files.


292-292: Informative logging for file paths.

Adding this log statement helps with debugging file path issues.

backend/open_webui/utils/payload.py (1)

76-76: Local variable param is assigned but never used
Referencing the previous comment about removing or refactoring this unused variable.

🧰 Tools
🪛 Ruff (0.8.2)

76-76: Local variable param is assigned to but never used

(F841)


76-76: Use params.get(key) instead of params.get(key, None)

Replace params.get(key, None) with params.get(key)

(SIM910)

backend/open_webui/routers/openai.py (2)

101-110: Verify handling of multiple “system” messages

Currently, openai_o1_o3_handler modifies only the first message if it has a system role. If there can be multiple system messages in the payload, consider whether they should be handled similarly.


55-73: Confirm user data safety in forwarded headers

Sensitive user information is added to custom headers. If “username,” “email,” or other fields can contain special or untrusted characters, consider sanitizing them before appending to HTTP headers.

backend/open_webui/routers/utils.py (1)

46-72: Revisit the code execution timeout handling

A previous review suggested adding tighter exception handling (e.g., catching asyncio.TimeoutError) to gracefully handle timeouts during code execution. Consider reintroducing that logic to improve fault tolerance.

🧰 Tools
🪛 Ruff (0.8.2)

48-48: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

backend/open_webui/retrieval/utils.py (3)

18-18: Remove unused imports.

Both get_last_user_message and calculate_sha256_string are not referenced anywhere in this file. Removing unused imports reduces clutter and prevents confusion.

- from open_webui.utils.misc import get_last_user_message, calculate_sha256_string
🧰 Tools
🪛 Ruff (0.8.2)

18-18: open_webui.utils.misc.get_last_user_message imported but unused

Remove unused import

(F401)


18-18: open_webui.utils.misc.calculate_sha256_string imported but unused

Remove unused import

(F401)


72-72: Verify necessity of the new user parameter.

The user parameter was introduced but is never utilized in this function. Confirm whether it’s intended for future expansions like audit logging or access control. If not, consider removing it to keep the signature clean.


86-88: Exception handling looks good.

Using log.exception is a solid approach for recording stack traces. These lines properly re-raise the exception to avoid silent failures.

backend/open_webui/routers/retrieval.py (1)

49-49: Validate new search engine API credentials.

These newly imported search engines (bocha, serpapi, exa) rely on associated API keys. Ensure you check for missing or invalid environment variables to prevent runtime errors.

Also applies to: 54-54, 61-61

backend/open_webui/main.py (9)

48-50: Add logging and audit imports.

These imports bring in structured logging, auditing levels, and the logger initialization function. They seem properly utilized below (e.g., start_logger at line 399 and audit middleware around line 908).


94-94: Verify proper handling of LICENSE_KEY.

While loading LICENSE_KEY from config is straightforward, ensure the logic around license checks (lines 403–405) gracefully handles invalid or missing keys and does not block application startup unexpectedly.


105-105: Minor inline comment.

No issues found; this is just a comment marker for the new "Direct Connections" section.


106-106: Enable direct connections configuration.

The addition of ENABLE_DIRECT_CONNECTIONS aligns with allowing direct model usage (e.g., lines 992–1008). Ensure thorough testing of any security implications.


399-399: Initialize logger on application lifespan start.

Good call to start_logger() early in the lifecycle. Verify that repeated calls do not reconfigure the logger multiple times inadvertently.


403-405: Load license data if available.

Retrieves license data only if LICENSE_KEY is present. This logic is consistent—just confirm robust error handling if service calls fail.


450-455: Comment block for direct connections.

These lines merely structure the file. No actionable items needed.


456-457: Set direct connections config state.

Assigning app.state.config.ENABLE_DIRECT_CONNECTIONS is straightforward and consistent with the new feature. Looks good.


692-692: Enable image prompt generation.

Check whether image prompt generation needs additional rate-limiting or external call controls if large volumes of prompt generation are possible.

backend/open_webui/config.py (6)

538-550: GitHub OAuth registration block.

The github_oauth_register function properly sets up endpoints. Confirm you handle potential userinfo mismatch or GitHub scope changes gracefully (lines 541–548).


606-613: Attempting to copy loader.js.

These lines handle copying an additional static asset. Handle exceptions carefully (as done with try/except). No issues noted.


974-993: Default user permissions for new features.

Including web search, image generation, and code interpreter flags for user roles is a neat approach. Just ensure these new permissions (lines 959–971) integrate seamlessly with your role-based checks.


1100-1102: Error loading WEBUI_BANNERS.

Wrapped in an exception; logs the error with log.exception(). This is fine—just confirm it’s not too verbose if environment variables are missing.


1187-1212: Image prompt generation template.

Descriptive instructions for generating images from chat context. This template references a JSON output format. Again, ensure callers robustly parse the JSON since user models can deviate.


1219-1224: Enable title generation.

Key-based toggle to turn this feature on/off. Looks consistent with the other toggles.

backend/open_webui/storage/provider.py (9)

3-10: New imports and reorganized dependencies.

Grouping AWS, GCS, and Azure libraries indicates a multi-provider approach. Verify dependencies are pinned to secure versions in your requirements.


41-57: Abstract StorageProvider class.

Defining an interface with upload_file, get_file, delete_file, and delete_all_files is a clean approach. Encourages consistent usage across providers.


59-98: LocalStorageProvider implementation.

The local provider writes files into UPLOAD_DIR.

  • Raises a ValueError if empty (line 64).
  • Logs any failures to delete.
    Everything looks correct for local usage.

133-142: S3 download logic.

Your approach _extract_s3_key_get_local_file_path then download_file is straightforward. Confirm that partial or large downloads handle network disruptions.

🧰 Tools
🪛 Ruff (0.8.2)

141-141: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


174-179: Helpers for S3 keys and local path.

Extracting the S3 key from an “s3://” style path and forming the local path is fine. Confirm correct behavior with subfolders, if supported.


181-243: GCSStorageProvider.

Similar pattern as S3:

  • Upload saves locally first, then uploads to GCS.
  • For NotFound handling (lines 215, 225, 239), consider raise ... from e for clarity.
🧰 Tools
🪛 Ruff (0.8.2)

204-204: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


216-216: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


225-225: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


239-239: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


245-311: AzureStorageProvider.

Implements the same interface. Notably uses upload_blob(contents, overwrite=True).

  • In except blocks (lines 274, 286, 295, 307), ensuring we chain or re-raise from the original error improves debugging.
🧰 Tools
🪛 Ruff (0.8.2)

274-274: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


286-286: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


295-295: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


307-307: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


313-325: Factory method for selecting storage provider.

get_storage_provider returns the correct provider based on config. Raise RuntimeError for unsupported providers. This is a clean design.


327-327: Global Storage instance.

Instantiates the chosen provider once. Looks good—just confirm concurrency safety if multiple threads/processes.


class ColBERT:
def __init__(self, name, **kwargs) -> None:
print("ColBERT: Loading model", name)
log.info("ColBERT: Loading model", name)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the logging format.

The current logging statement uses incorrect formatting for Python's logging module. When passing variables to logging methods, you should use string formatting with placeholders rather than passing them as additional arguments.

-        log.info("ColBERT: Loading model", name)
+        log.info("ColBERT: Loading model %s", name)

Alternatively, you could use an f-string:

-        log.info("ColBERT: Loading model", name)
+        log.info(f"ColBERT: Loading model {name}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
log.info("ColBERT: Loading model", name)
log.info("ColBERT: Loading model %s", name)

@@ -102,8 +107,7 @@ def query(
}
)
return None
except Exception as e:
print(e)
except:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid bare except.

Catching all exceptions without specifying the exception type can mask errors and complicate debugging.

-        except:
+        except Exception:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
except:
except Exception:
🧰 Tools
🪛 Ruff (0.8.2)

110-110: Do not use bare except

(E722)

@@ -17,14 +17,15 @@
process_files_batch,
BatchProcessFilesForm,
)

from open_webui.storage.provider import Storage
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove unused import.

from open_webui.storage.provider import Storage is not used in this file. Removing it avoids confusion and meets linting guidelines.

- from open_webui.storage.provider import Storage
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from open_webui.storage.provider import Storage
🧰 Tools
🪛 Ruff (0.8.2)

20-20: open_webui.storage.provider.Storage imported but unused

Remove unused import: open_webui.storage.provider.Storage

(F401)

Comment on lines +589 to +599
except Exception as e:
log.exception(e)
detail = None
if r is not None:
try:
res = r.json()
if "error" in res:
detail = f"External: {res['error'].get('message', '')}"
except Exception:
detail = f"External: {e}"
raise Exception(detail if detail else "Open WebUI: Server Connection Error")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure r is defined before usage and preserve exception trace.
If requests.post fails before assigning r, referencing r in the except clause may cause an UnboundLocalError. Also consider using raise ... from e to maintain original context.

         try:
+            r = None
             r = requests.post(
                 ...
             )
             r.raise_for_status()
         except Exception as e:
             log.exception(e)
             detail = None
             if r is not None:
                 try:
                     res = r.json()
                     ...
-            raise Exception(detail if detail else "Open WebUI: Server Connection Error")
+            raise Exception(detail if detail else "Open WebUI: Server Connection Error") from e
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
except Exception as e:
log.exception(e)
detail = None
if r is not None:
try:
res = r.json()
if "error" in res:
detail = f"External: {res['error'].get('message', '')}"
except Exception:
detail = f"External: {e}"
raise Exception(detail if detail else "Open WebUI: Server Connection Error")
try:
+ r = None
r = requests.post(
...
)
r.raise_for_status()
except Exception as e:
log.exception(e)
detail = None
if r is not None:
try:
res = r.json()
if "error" in res:
detail = f"External: {res['error'].get('message', '')}"
except Exception:
detail = f"External: {e}"
- raise Exception(detail if detail else "Open WebUI: Server Connection Error")
+ raise Exception(detail if detail else "Open WebUI: Server Connection Error") from e
🧰 Tools
🪛 Ruff (0.8.2)

599-599: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

Comment on lines +42 to +49
def verify_signature(payload: str, signature: str) -> bool:
"""
Verifies the HMAC signature of the received payload.
"""
try:
expected_signature = base64.b64encode(
hmac.new(TRUSTED_SIGNATURE_KEY, payload.encode(), hashlib.sha256).digest()
).decode()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure the HMAC key is in bytes.
TRUSTED_SIGNATURE_KEY is likely a string, so consider encoding it before calling hmac.new. Otherwise, it may throw a TypeError.

 expected_signature = base64.b64encode(
-    hmac.new(TRUSTED_SIGNATURE_KEY, payload.encode(), hashlib.sha256).digest()
+    hmac.new(TRUSTED_SIGNATURE_KEY.encode(), payload.encode(), hashlib.sha256).digest()
 ).decode()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def verify_signature(payload: str, signature: str) -> bool:
"""
Verifies the HMAC signature of the received payload.
"""
try:
expected_signature = base64.b64encode(
hmac.new(TRUSTED_SIGNATURE_KEY, payload.encode(), hashlib.sha256).digest()
).decode()
def verify_signature(payload: str, signature: str) -> bool:
"""
Verifies the HMAC signature of the received payload.
"""
try:
expected_signature = base64.b64encode(
hmac.new(TRUSTED_SIGNATURE_KEY.encode(), payload.encode(), hashlib.sha256).digest()
).decode()

Comment on lines +252 to +285
# If the provider is GitHub,and public email is not provided, we can use the access token to fetch the user's email
if provider == "github":
try:
access_token = token.get("access_token")
headers = {"Authorization": f"Bearer {access_token}"}
async with aiohttp.ClientSession() as session:
async with session.get(
"https://api.github.com/user/emails", headers=headers
) as resp:
if resp.ok:
emails = await resp.json()
# use the primary email as the user's email
primary_email = next(
(e["email"] for e in emails if e.get("primary")),
None,
)
if primary_email:
email = primary_email
else:
log.warning(
"No primary email found in GitHub response"
)
raise HTTPException(
400, detail=ERROR_MESSAGES.INVALID_CRED
)
else:
log.warning("Failed to fetch GitHub email")
raise HTTPException(
400, detail=ERROR_MESSAGES.INVALID_CRED
)
except Exception as e:
log.warning(f"Error fetching GitHub email: {e}")
raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)
else:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Good addition of GitHub email retrieval fallback.

The implementation to fetch email from GitHub when not provided in the initial authentication response is a robust enhancement, particularly for users with private email settings.

However, there's an issue with exception handling:

- except Exception as e:
-     log.warning(f"Error fetching GitHub email: {e}")
-     raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)
+ except Exception as e:
+     log.warning(f"Error fetching GitHub email: {e}")
+     raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) from e

Also, consider combining the nested with statements for better readability:

- async with aiohttp.ClientSession() as session:
-     async with session.get(
-         "https://api.github.com/user/emails", headers=headers
-     ) as resp:
+ async with aiohttp.ClientSession() as session, session.get(
+     "https://api.github.com/user/emails", headers=headers
+ ) as resp:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# If the provider is GitHub,and public email is not provided, we can use the access token to fetch the user's email
if provider == "github":
try:
access_token = token.get("access_token")
headers = {"Authorization": f"Bearer {access_token}"}
async with aiohttp.ClientSession() as session:
async with session.get(
"https://api.github.com/user/emails", headers=headers
) as resp:
if resp.ok:
emails = await resp.json()
# use the primary email as the user's email
primary_email = next(
(e["email"] for e in emails if e.get("primary")),
None,
)
if primary_email:
email = primary_email
else:
log.warning(
"No primary email found in GitHub response"
)
raise HTTPException(
400, detail=ERROR_MESSAGES.INVALID_CRED
)
else:
log.warning("Failed to fetch GitHub email")
raise HTTPException(
400, detail=ERROR_MESSAGES.INVALID_CRED
)
except Exception as e:
log.warning(f"Error fetching GitHub email: {e}")
raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)
else:
# If the provider is GitHub,and public email is not provided, we can use the access token to fetch the user's email
if provider == "github":
try:
access_token = token.get("access_token")
headers = {"Authorization": f"Bearer {access_token}"}
async with aiohttp.ClientSession() as session, session.get(
"https://api.github.com/user/emails", headers=headers
) as resp:
if resp.ok:
emails = await resp.json()
# use the primary email as the user's email
primary_email = next(
(e["email"] for e in emails if e.get("primary")),
None,
)
if primary_email:
email = primary_email
else:
log.warning(
"No primary email found in GitHub response"
)
raise HTTPException(
400, detail=ERROR_MESSAGES.INVALID_CRED
)
else:
log.warning("Failed to fetch GitHub email")
raise HTTPException(
400, detail=ERROR_MESSAGES.INVALID_CRED
)
except Exception as e:
log.warning(f"Error fetching GitHub email: {e}")
raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) from e
else:
🧰 Tools
🪛 Ruff (0.8.2)

257-260: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)


284-284: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

Comment on lines +670 to +682
app.state.config.ENABLE_CODE_INTERPRETER = ENABLE_CODE_INTERPRETER
app.state.config.CODE_INTERPRETER_ENGINE = CODE_INTERPRETER_ENGINE
app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE = CODE_INTERPRETER_PROMPT_TEMPLATE

app.state.config.CODE_INTERPRETER_JUPYTER_URL = CODE_INTERPRETER_JUPYTER_URL
app.state.config.CODE_INTERPRETER_JUPYTER_AUTH = CODE_INTERPRETER_JUPYTER_AUTH
app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN = (
CODE_INTERPRETER_JUPYTER_AUTH_TOKEN
)
app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD = (
CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD
)
app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT = CODE_INTERPRETER_JUPYTER_TIMEOUT
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Enable code interpreter.

Allowing a code interpreter inside the application can pose significant security risks. Recommend verifying user roles, implementing safe execution sandboxes, and restricting file system access.

# Ollama
ENABLE_OLLAMA_API,
OLLAMA_BASE_URLS,
OLLAMA_API_CONFIGS,
# OpenAI
ENABLE_OPENAI_API,
ONEDRIVE_CLIENT_ID,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Redundant ONEDRIVE_CLIENT_ID import.

Static analysis suggests a redefinition of ONEDRIVE_CLIENT_ID. Verify it's genuinely needed here. If not, consider removing this import to avoid confusion.

-    ONEDRIVE_CLIENT_ID,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ONEDRIVE_CLIENT_ID,

@arthrod
Copy link
Owner Author

arthrod commented Mar 12, 2025

@gemini conduct ane extremely granular review of the PR, additionally, provide a full walkthrough, including an evaluation (worse or better) of the proposed changes.

Copy link

Okay, I will conduct an extremely granular review of the PR and provide a full walkthrough, including an evaluation of the proposed changes.

Granular Code Review

I have reviewed the pull request in detail, focusing on correctness, efficiency, maintainability, and security. Here's a breakdown of the key changes and some suggestions for improvement.

  • File: .github/ISSUE_TEMPLATE/bug_report.md
    • This file has been removed and replaced with .github/ISSUE_TEMPLATE/bug_report.yaml. This is generally a good change as YAML is more structured and easier to parse than Markdown for issue templates.
  • File: .github/ISSUE_TEMPLATE/config.yml
    • A new file has been added to disable blank issues. This is a good practice to guide users to use the issue templates.
  • File: .github/ISSUE_TEMPLATE/feature_request.md
    • This file has been removed and replaced with .github/ISSUE_TEMPLATE/feature_request.yaml. Similar to the bug report, using YAML for feature requests provides a more structured approach.
  • File: .github/workflows/docker-build.yaml
    • The runs-on key has been updated to use a conditional expression based on the matrix.platform. This is a good change as it allows the workflow to run on different platforms.
  • File: .github/workflows/integration-test.disabled
    • A new environment variable LIBGL_ALWAYS_SOFTWARE: 1 has been added to the Cypress run step. This is likely to address issues with running Cypress in a Docker container.
  • File: .github/workflows/release-pypi.yml
    • The node-version has been updated from 18 to 22. This ensures that the workflow uses a more recent version of Node.js.
  • File: CHANGELOG.md
    • A detailed changelog entry has been added for version 0.5.20 and prior versions. This is excellent for documenting changes and providing users with a clear understanding of what has been updated.
  • File: Dockerfile
    • A new environment variable NODE_OPTIONS="--max-old-space-size=4096" has been added. This is likely to address memory issues during the build process.
  • File: README.md
    • A tip about the Enterprise Plan has been added. This is good for promoting the enterprise version of the software.
    • The link to the Migration Guide has been updated to an Updating Guide. This ensures that users are directed to the correct documentation.
  • File: backend/open_webui/__init__.py
    • A new version callback has been added to the Typer app. This allows users to check the version of the software from the command line.
  • File: backend/open_webui/config.py
    • Several new configuration options have been added, including support for GitHub OAuth, code execution, and image prompt generation. This provides users with more control over the software's behavior.
    • The way static files are handled has been updated. This ensures that static files are served correctly.
    • The prompt template for title generation has been updated to use a JSON format. This provides a more structured approach to title generation.
  • File: backend/open_webui/constants.py
    • The error message for unsupported file types has been updated. This provides users with a more informative error message.
  • File: backend/open_webui/env.py
    • The way logging is handled has been updated. This provides more flexibility in configuring logging.
    • New environment variables have been added for audit logging. This allows administrators to track user activity.
  • File: backend/open_webui/functions.py
    • The way pipes are handled has been updated to support asynchronous functions. This allows for more complex filter pipelines.
  • File: backend/open_webui/models/groups.py
    • The GroupForm model has been updated to exclude None values. This ensures that only valid values are used when creating groups.
  • File: backend/open_webui/models/users.py
    • A new method update_user_settings_by_id has been added to update user settings. This provides a more convenient way to update user settings.
  • File: backend/open_webui/retrieval/utils.py
    • The way hybrid search results are merged has been updated to ensure uniqueness. This prevents duplicate results from being returned.
  • File: backend/open_webui/routers/auths.py
    • The way LDAP authentication is handled has been updated. This provides more flexibility in configuring LDAP authentication.
  • File: backend/open_webui/routers/images.py
    • The way image generation is handled has been updated to support Gemini. This provides users with more options for image generation.
  • File: backend/open_webui/routers/retrieval.py
    • The way web searches are handled has been updated to support more search engines. This provides users with more options for web search.
  • File: backend/open_webui/routers/tasks.py
    • The way tasks are handled has been updated to support image prompt generation. This allows users to generate prompts for image generation tasks.
  • File: backend/open_webui/static/favicon.svg
    • The favicon has been updated.
  • File: backend/open_webui/static/site.webmanifest
    • The paths to the icons have been updated.
  • File: scripts/prepare-pyodide.js
    • New packages have been added to the Pyodide environment. This provides users with more tools for data analysis and manipulation.
    • Proxy support has been added to the Pyodide environment. This allows users to use a proxy server when downloading packages.

Full Walkthrough

This pull request introduces a wide range of new features, improvements, and bug fixes. The changes span across the entire codebase, from the frontend to the backend, and include updates to the build system, documentation, and dependencies.

New Features

  • Support for Gemini image generation
  • Support for OneDrive storage integration
  • Support for Elasticsearch Vector DB
  • Support for code execution via Jupyter Notebook
  • Support for image prompt generation
  • Support for multiple tool calls in native function mode
  • New admin settings for direct connectivity and code execution
  • New "stream" hook for real-time filtering
  • Rebranding of the interface from "Open WebUI" to "Global Chat"

Improvements

  • Enhanced UI styling and theme consistency
  • Improved overall stability and error handling
  • Refined UI and notification styling for a cleaner, more responsive experience
  • Strengthened OAuth and direct connection configurations
  • Streamlined configuration management across services
  • Modernized development workflows
  • Robust error management
  • Refined multilingual support for better localization and accuracy across various languages
  • Enhanced logging with Loguru
  • Smarter web search with agentic workflows
  • Optimized asynchronous web search
  • Improved image generation metadata handling
  • Desktop App Preparations

Bug Fixes

  • Fixed a critical import error
  • Fixed a circular import issue
  • Fixed MPS functionality for Mac users
  • Fixed temporary chat message duplication
  • Fixed OAuth name field fallback
  • Fixed non-root container issue
  • Fixed web manifest loading issue
  • Fixed Pinyin Keyboard Enter Key
  • Fixed OpenAI Usage Statistics
  • Fixed WebSocket Chat Event Registration
  • Fixed Models Displaying with ENABLE_FORWARD_USER_INFO_HEADERS
  • Fixed Direct Connections for Regular Users
  • Fixed Landing Page Input Lag with Long Text
  • Fixed Parameter in Functions
  • Fixed Web Search Configuration Bug
  • Fixed Temporary Chat Message Continue Button
  • Fixed GGUF Model Upload Stability
  • Fixed User Settings Persistence
  • Fixed OpenID Username Retrieval
  • Fixed System Prompts Templating via API
  • Fixed DuckDuckGo Search Rate Limit Handling
  • Fixed File Upload Permission Indicator
  • Fixed Max Tokens Issue
  • Fixed Validation for RAG Web Search URLs
  • Fixed Title Generation Bug
  • Fixed '' Tag Display Issue
  • Fixed Code Interpreter Stability with Custom Functions
  • Fixed Web Search Retrieval
  • Fixed Mobile Hover Issue
  • Fixed Reliable Model Imports from the Community Platform
  • Fixed UI Now Reflects Deleted Connections Instantly
  • Fixed Open WebUI Now Works Over LAN in Insecure Context
  • Fixed LDAP Email Case Sensitivity

Evaluation of Proposed Changes

Overall, the proposed changes significantly improve the functionality, stability, and user experience of Open WebUI. The addition of new features such as Gemini image generation, OneDrive storage integration, and Elasticsearch Vector DB support expands the platform's capabilities and provides users with more flexibility. The numerous bug fixes address critical issues and enhance the reliability of the software. The rebranding of the interface from "Open WebUI" to "Global Chat" may be a good change, but it depends on the target audience and the overall branding strategy.

Worse or Better?

These changes are definitively better for the project. The new features and improvements outweigh any potential drawbacks, and the bug fixes address critical issues that were affecting the user experience.

@arthrod
Copy link
Owner Author

arthrod commented Mar 23, 2025

@coderrabitai review the code to determine if we have a dash card and landing page now

tjbck and others added 30 commits April 12, 2025 23:01
This commit fixes an issue created on commit 2e7a01f.

Ldap object is type <class 'ldap3.abstract.attribute.Attribute'>.
So we need to return the value and verify if it's null, string or list.

Fixes open-webui#12813
fix: Properly handle ldap3.abstract.attribute.Attribute value
feat/Enable vad_filter to improve quality of transcription in faster-whisper
Fix: Robust Handling of LDAP Email Attribute Types
Co-Authored-By: Sebastian Whincop <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.