From 0e71b965975dc4300c2daa9926addc3ea3a41caa Mon Sep 17 00:00:00 2001 From: Self Denial Date: Mon, 7 Apr 2025 14:49:47 -0600 Subject: [PATCH 01/11] fix: Upgrade OpenTelemetry instrumentation packages to 0.52b1 This commit updates all OpenTelemetry instrumentation dependencies (FastAPI, SQLAlchemy, Redis, Requests, Logging, HTTPX, aiohttp-client) from version 0.52b0 to 0.52b1 to satisfy opentelemetry-sdk==1.31.1 dependencies. --- backend/requirements.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/requirements.txt b/backend/requirements.txt index 73c855084..56cde3862 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -127,11 +127,11 @@ firecrawl-py==1.12.0 opentelemetry-api==1.31.1 opentelemetry-sdk==1.31.1 opentelemetry-exporter-otlp==1.31.1 -opentelemetry-instrumentation==0.52b0 -opentelemetry-instrumentation-fastapi==0.52b0 -opentelemetry-instrumentation-sqlalchemy==0.52b0 -opentelemetry-instrumentation-redis==0.52b0 -opentelemetry-instrumentation-requests==0.52b0 -opentelemetry-instrumentation-logging==0.52b0 -opentelemetry-instrumentation-httpx==0.52b0 -opentelemetry-instrumentation-aiohttp-client==0.52b0 \ No newline at end of file +opentelemetry-instrumentation==0.52b1 +opentelemetry-instrumentation-fastapi==0.52b1 +opentelemetry-instrumentation-sqlalchemy==0.52b1 +opentelemetry-instrumentation-redis==0.52b1 +opentelemetry-instrumentation-requests==0.52b1 +opentelemetry-instrumentation-logging==0.52b1 +opentelemetry-instrumentation-httpx==0.52b1 +opentelemetry-instrumentation-aiohttp-client==0.52b1 From 337c7caafa0225badaaedd361ec323b63f75734a Mon Sep 17 00:00:00 2001 From: Florian Maurer Date: Tue, 8 Apr 2025 13:51:54 +0200 Subject: [PATCH 02/11] improve stack trace of duckduckgo exception * fix search_results out of scope * ddgs.text does already always return a list --- backend/open_webui/retrieval/web/duckduckgo.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/open_webui/retrieval/web/duckduckgo.py b/backend/open_webui/retrieval/web/duckduckgo.py index d95086671..550c59793 100644 --- a/backend/open_webui/retrieval/web/duckduckgo.py +++ b/backend/open_webui/retrieval/web/duckduckgo.py @@ -3,6 +3,7 @@ from typing import Optional from open_webui.retrieval.web.main import SearchResult, get_filtered_results from duckduckgo_search import DDGS +from duckduckgo_search.exceptions import RatelimitException from open_webui.env import SRC_LOG_LEVELS log = logging.getLogger(__name__) @@ -22,16 +23,15 @@ def search_duckduckgo( list[SearchResult]: A list of search results """ # Use the DDGS context manager to create a DDGS object + search_results = [] with DDGS() as ddgs: # Use the ddgs.text() method to perform the search - ddgs_gen = ddgs.text( - query, safesearch="moderate", max_results=count, backend="api" - ) - # Check if there are search results - if ddgs_gen: - # Convert the search results into a list - search_results = [r for r in ddgs_gen] - + try: + search_results = ddgs.text( + query, safesearch="moderate", max_results=count, backend="api" + ) + except RatelimitException as e: + log.error(f"RatelimitException: {e}") if filter_list: search_results = get_filtered_results(search_results, filter_list) From 760ea3f4afbbaa4f2046dc53aa9ea3fd2f784c53 Mon Sep 17 00:00:00 2001 From: Florian Maurer Date: Tue, 8 Apr 2025 14:01:44 +0200 Subject: [PATCH 03/11] duckduckgo: backend api has been deprecated since december also increase duckduckgo-search version see https://github.com/deedy5/duckduckgo_search/commit/3ee8e08b1c8efc9b7356f406db299f1114dc4860 --- backend/open_webui/retrieval/web/duckduckgo.py | 2 +- backend/requirements.txt | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/open_webui/retrieval/web/duckduckgo.py b/backend/open_webui/retrieval/web/duckduckgo.py index 550c59793..bf8ae6880 100644 --- a/backend/open_webui/retrieval/web/duckduckgo.py +++ b/backend/open_webui/retrieval/web/duckduckgo.py @@ -28,7 +28,7 @@ def search_duckduckgo( # Use the ddgs.text() method to perform the search try: search_results = ddgs.text( - query, safesearch="moderate", max_results=count, backend="api" + query, safesearch="moderate", max_results=count, backend="lite" ) except RatelimitException as e: log.error(f"RatelimitException: {e}") diff --git a/backend/requirements.txt b/backend/requirements.txt index 56cde3862..ad490d00a 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -98,7 +98,7 @@ pytube==15.0.0 extract_msg pydub -duckduckgo-search~=7.3.2 +duckduckgo-search~=7.5.5 ## Google Drive google-api-python-client diff --git a/pyproject.toml b/pyproject.toml index 52260e45e..18e833290 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -104,7 +104,7 @@ dependencies = [ "extract_msg", "pydub", - "duckduckgo-search~=7.3.2", + "duckduckgo-search~=7.5.5", "google-api-python-client", "google-auth-httplib2", From 2337b3660993cf0de96d4a189e9bf5ec1ac9ece4 Mon Sep 17 00:00:00 2001 From: Robert Norberg Date: Tue, 8 Apr 2025 12:08:32 -0400 Subject: [PATCH 04/11] add debug logging to RAG utils --- backend/open_webui/retrieval/utils.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/open_webui/retrieval/utils.py b/backend/open_webui/retrieval/utils.py index 12d48f869..a00e6982c 100644 --- a/backend/open_webui/retrieval/utils.py +++ b/backend/open_webui/retrieval/utils.py @@ -77,6 +77,7 @@ def query_doc( collection_name: str, query_embedding: list[float], k: int, user: UserModel = None ): try: + log.debug(f"query_doc:doc {collection_name}") result = VECTOR_DB_CLIENT.search( collection_name=collection_name, vectors=[query_embedding], @@ -94,6 +95,7 @@ def query_doc( def get_doc(collection_name: str, user: UserModel = None): try: + log.debug(f"get_doc:doc {collection_name}") result = VECTOR_DB_CLIENT.get(collection_name=collection_name) if result: @@ -116,6 +118,7 @@ def query_doc_with_hybrid_search( r: float, ) -> dict: try: + log.debug(f"query_doc_with_hybrid_search:doc {collection_name}") bm25_retriever = BM25Retriever.from_texts( texts=collection_result.documents[0], metadatas=collection_result.metadatas[0], @@ -168,6 +171,7 @@ def query_doc_with_hybrid_search( ) return result except Exception as e: + log.exception(f"Error querying doc {collection_name} with hybrid search: {e}") raise e @@ -257,6 +261,7 @@ def query_collection( ) -> dict: results = [] for query in queries: + log.debug(f"query_collection:query {query}") query_embedding = embedding_function(query, prefix=RAG_EMBEDDING_QUERY_PREFIX) for collection_name in collection_names: if collection_name: @@ -292,6 +297,7 @@ def query_collection_with_hybrid_search( collection_results = {} for collection_name in collection_names: try: + log.debug(f"query_collection_with_hybrid_search:VECTOR_DB_CLIENT.get:collection {collection_name}") collection_results[collection_name] = VECTOR_DB_CLIENT.get( collection_name=collection_name ) @@ -613,6 +619,7 @@ def generate_openai_batch_embeddings( user: UserModel = None, ) -> Optional[list[list[float]]]: try: + log.debug(f"generate_openai_batch_embeddings:model {model} batch size: {len(texts)}") json_data = {"input": texts, "model": model} if isinstance(RAG_EMBEDDING_PREFIX_FIELD_NAME, str) and isinstance(prefix, str): json_data[RAG_EMBEDDING_PREFIX_FIELD_NAME] = prefix @@ -655,6 +662,7 @@ def generate_ollama_batch_embeddings( user: UserModel = None, ) -> Optional[list[list[float]]]: try: + log.debug(f"generate_ollama_batch_embeddings:model {model} batch size: {len(texts)}") json_data = {"input": texts, "model": model} if isinstance(RAG_EMBEDDING_PREFIX_FIELD_NAME, str) and isinstance(prefix, str): json_data[RAG_EMBEDDING_PREFIX_FIELD_NAME] = prefix From f822d89350dc67a1c5adc399bbe216caf953b314 Mon Sep 17 00:00:00 2001 From: DrMelone <27028174+Classic298@users.noreply.github.com> Date: Tue, 8 Apr 2025 18:38:00 +0200 Subject: [PATCH 05/11] Update env.py --- backend/open_webui/env.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/backend/open_webui/env.py b/backend/open_webui/env.py index e3819fdc5..27ea3eda2 100644 --- a/backend/open_webui/env.py +++ b/backend/open_webui/env.py @@ -326,6 +326,19 @@ REDIS_URL = os.environ.get("REDIS_URL", "") REDIS_SENTINEL_HOSTS = os.environ.get("REDIS_SENTINEL_HOSTS", "") REDIS_SENTINEL_PORT = os.environ.get("REDIS_SENTINEL_PORT", "26379") +#################################### +# UVICORN WORKERS +#################################### + +UVICORN_WORKERS = os.environ.get("UVICORN_WORKERS", "1") +try: + UVICORN_WORKERS = int(UVICORN_WORKERS) + if UVICORN_WORKERS < 1: + UVICORN_WORKERS = 1 +except ValueError: + UVICORN_WORKERS = 1 + log.info(f"Invalid UVICORN_WORKERS value, defaulting to {UVICORN_WORKERS}") + #################################### # WEBUI_AUTH (Required for security) #################################### From 4c9a791b0640f5932d5c4219472a5580c403b046 Mon Sep 17 00:00:00 2001 From: DrMelone <27028174+Classic298@users.noreply.github.com> Date: Tue, 8 Apr 2025 18:47:48 +0200 Subject: [PATCH 06/11] Update env.py --- backend/open_webui/env.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/open_webui/env.py b/backend/open_webui/env.py index 27ea3eda2..49aee4457 100644 --- a/backend/open_webui/env.py +++ b/backend/open_webui/env.py @@ -330,6 +330,7 @@ REDIS_SENTINEL_PORT = os.environ.get("REDIS_SENTINEL_PORT", "26379") # UVICORN WORKERS #################################### +# Number of uvicorn worker processes for handling requests UVICORN_WORKERS = os.environ.get("UVICORN_WORKERS", "1") try: UVICORN_WORKERS = int(UVICORN_WORKERS) From 2c1d0e385742d16f26b6e2eba23ec84826e51e1b Mon Sep 17 00:00:00 2001 From: DrMelone <27028174+Classic298@users.noreply.github.com> Date: Tue, 8 Apr 2025 18:50:07 +0200 Subject: [PATCH 07/11] Update start.sh --- backend/start.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/start.sh b/backend/start.sh index 671c22ff7..b9a30fd3d 100755 --- a/backend/start.sh +++ b/backend/start.sh @@ -65,4 +65,4 @@ if [ -n "$SPACE_ID" ]; then export WEBUI_URL=${SPACE_HOST} fi -WEBUI_SECRET_KEY="$WEBUI_SECRET_KEY" exec uvicorn open_webui.main:app --host "$HOST" --port "$PORT" --forwarded-allow-ips '*' +WEBUI_SECRET_KEY="$WEBUI_SECRET_KEY" exec uvicorn open_webui.main:app --host "$HOST" --port "$PORT" --forwarded-allow-ips '*' --workers "${UVICORN_WORKERS:-1}" From 65b5c6c0c72b4ad30f76b54deb34e98dc5a3cf40 Mon Sep 17 00:00:00 2001 From: DrMelone <27028174+Classic298@users.noreply.github.com> Date: Tue, 8 Apr 2025 18:52:12 +0200 Subject: [PATCH 08/11] Update start_windows.bat --- backend/start_windows.bat | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/start_windows.bat b/backend/start_windows.bat index 19f6f123c..661ecc494 100644 --- a/backend/start_windows.bat +++ b/backend/start_windows.bat @@ -41,5 +41,6 @@ IF "%WEBUI_SECRET_KEY%%WEBUI_JWT_SECRET_KEY%" == " " ( :: Execute uvicorn SET "WEBUI_SECRET_KEY=%WEBUI_SECRET_KEY%" -uvicorn open_webui.main:app --host "%HOST%" --port "%PORT%" --forwarded-allow-ips '*' --ws auto +IF "%UVICORN_WORKERS%"=="" SET UVICORN_WORKERS=1 +uvicorn open_webui.main:app --host "%HOST%" --port "%PORT%" --forwarded-allow-ips '*' --workers %UVICORN_WORKERS% --ws auto :: For ssl user uvicorn open_webui.main:app --host "%HOST%" --port "%PORT%" --forwarded-allow-ips '*' --ssl-keyfile "key.pem" --ssl-certfile "cert.pem" --ws auto From f17befc853bee73d60354a1e62e78056dfed4a10 Mon Sep 17 00:00:00 2001 From: DrMelone <27028174+Classic298@users.noreply.github.com> Date: Tue, 8 Apr 2025 18:55:07 +0200 Subject: [PATCH 09/11] Update __init__.py --- backend/open_webui/__init__.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/__init__.py b/backend/open_webui/__init__.py index d85be48da..0c70cb63a 100644 --- a/backend/open_webui/__init__.py +++ b/backend/open_webui/__init__.py @@ -73,8 +73,15 @@ def serve( os.environ["LD_LIBRARY_PATH"] = ":".join(LD_LIBRARY_PATH) import open_webui.main # we need set environment variables before importing main + from open_webui.env import UVICORN_WORKERS # Import the workers setting - uvicorn.run(open_webui.main.app, host=host, port=port, forwarded_allow_ips="*") + uvicorn.run( + open_webui.main.app, + host=host, + port=port, + forwarded_allow_ips="*", + workers=UVICORN_WORKERS + ) @app.command() From 60d11c1f6f2982209f89083c3e2a2c471587bdfb Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Tue, 8 Apr 2025 12:50:25 -0700 Subject: [PATCH 10/11] enh: password max length verification --- backend/open_webui/constants.py | 1 + backend/open_webui/routers/auths.py | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/backend/open_webui/constants.py b/backend/open_webui/constants.py index 86d87a2c3..95c54a0d2 100644 --- a/backend/open_webui/constants.py +++ b/backend/open_webui/constants.py @@ -31,6 +31,7 @@ class ERROR_MESSAGES(str, Enum): USERNAME_TAKEN = ( "Uh-oh! This username is already registered. Please choose another username." ) + PASSWORD_TOO_LONG = "Uh-oh! The password you entered is too long. Please make sure your password is less than 72 bytes long." COMMAND_TAKEN = "Uh-oh! This command is already registered. Please choose another command string." FILE_EXISTS = "Uh-oh! This file is already registered. Please choose another file." diff --git a/backend/open_webui/routers/auths.py b/backend/open_webui/routers/auths.py index 67c2e9f2a..7905799e6 100644 --- a/backend/open_webui/routers/auths.py +++ b/backend/open_webui/routers/auths.py @@ -454,6 +454,13 @@ async def signup(request: Request, response: Response, form_data: SignupForm): # Disable signup after the first user is created request.app.state.config.ENABLE_SIGNUP = False + # The password passed to bcrypt must be 72 bytes or fewer. If it is longer, it will be truncated before hashing. + if len(form_data.password.encode("utf-8")) > 72: + raise HTTPException( + status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.PASSWORD_TOO_LONG, + ) + hashed = get_password_hash(form_data.password) user = Auths.insert_new_auth( form_data.email.lower(), From 63eab422082c6da8d762870c8dbd9a7971aa88f0 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Tue, 8 Apr 2025 12:51:48 -0700 Subject: [PATCH 11/11] refac --- src/lib/components/chat/ToolServersModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/chat/ToolServersModal.svelte b/src/lib/components/chat/ToolServersModal.svelte index 3f25b184e..24a86e48b 100644 --- a/src/lib/components/chat/ToolServersModal.svelte +++ b/src/lib/components/chat/ToolServersModal.svelte @@ -15,7 +15,7 @@ let selectedTools = []; - $: selectedTools = $tools.filter((tool) => selectedToolIds.includes(tool.id)); + $: selectedTools = ($tools ?? []).filter((tool) => selectedToolIds.includes(tool.id)); const i18n = getContext('i18n');