diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index 675176ee54..02b8192522 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -3462,6 +3462,12 @@ IMAGE_GENERATION_MODEL = PersistentConfig( os.getenv("IMAGE_GENERATION_MODEL", ""), ) +# Regex pattern for models that support IMAGE_SIZE = "auto". +IMAGE_AUTO_SIZE_MODELS_REGEX_PATTERN = os.getenv("IMAGE_AUTO_SIZE_MODELS_REGEX_PATTERN", "^gpt-image") + +# Regex pattern for models that return URLs instead of base64 data. +IMAGE_URL_RESPONSE_MODELS_REGEX_PATTERN = os.getenv("IMAGE_URL_RESPONSE_MODELS_REGEX_PATTERN", "^gpt-image") + IMAGE_SIZE = PersistentConfig( "IMAGE_SIZE", "image_generation.size", os.getenv("IMAGE_SIZE", "512x512") ) diff --git a/backend/open_webui/routers/images.py b/backend/open_webui/routers/images.py index 7fdd84b3fa..05afa63bb6 100644 --- a/backend/open_webui/routers/images.py +++ b/backend/open_webui/routers/images.py @@ -14,7 +14,7 @@ import requests from fastapi import APIRouter, Depends, HTTPException, Request, UploadFile from fastapi.responses import FileResponse -from open_webui.config import CACHE_DIR +from open_webui.config import CACHE_DIR, IMAGE_AUTO_SIZE_MODELS_REGEX_PATTERN, IMAGE_URL_RESPONSE_MODELS_REGEX_PATTERN from open_webui.constants import ERROR_MESSAGES from open_webui.retrieval.web.utils import validate_url from open_webui.env import ENABLE_FORWARD_USER_INFO_HEADERS @@ -201,12 +201,12 @@ async def update_config( set_image_model(request, form_data.IMAGE_GENERATION_MODEL) if ( form_data.IMAGE_SIZE == "auto" - and not form_data.IMAGE_GENERATION_MODEL.startswith("gpt-image") + and not re.match(IMAGE_AUTO_SIZE_MODELS_REGEX_PATTERN, form_data.IMAGE_GENERATION_MODEL) ): raise HTTPException( status_code=400, detail=ERROR_MESSAGES.INCORRECT_FORMAT( - " (auto is only allowed with gpt-image models)." + f" (auto is only allowed with models matching {IMAGE_AUTO_SIZE_MODELS_REGEX_PATTERN})." ), ) @@ -610,9 +610,7 @@ async def image_generations( ), **( {} - if request.app.state.config.IMAGE_GENERATION_MODEL.startswith( - "gpt-image" - ) + if re.match(IMAGE_URL_RESPONSE_MODELS_REGEX_PATTERN, request.app.state.config.IMAGE_GENERATION_MODEL) else {"response_format": "b64_json"} ), **( @@ -949,7 +947,7 @@ async def image_edits( **({"size": size} if size else {}), **( {} - if request.app.state.config.IMAGE_EDIT_MODEL.startswith("gpt-image") + if re.match(IMAGE_URL_RESPONSE_MODELS_REGEX_PATTERN, request.app.state.config.IMAGE_EDIT_MODEL) else {"response_format": "b64_json"} ), } diff --git a/backend/open_webui/utils/telemetry/instrumentors.py b/backend/open_webui/utils/telemetry/instrumentors.py index dbc4ebb2cb..9e251e38ae 100644 --- a/backend/open_webui/utils/telemetry/instrumentors.py +++ b/backend/open_webui/utils/telemetry/instrumentors.py @@ -22,6 +22,7 @@ from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor from opentelemetry.instrumentation.aiohttp_client import AioHttpClientInstrumentor from opentelemetry.trace import Span, StatusCode from redis import Redis +from redis.cluster import RedisCluster from requests import PreparedRequest, Response from sqlalchemy import Engine from fastapi import status @@ -59,16 +60,28 @@ def response_hook(span: Span, request: PreparedRequest, response: Response): span.set_status(StatusCode.ERROR if response.status_code >= 400 else StatusCode.OK) -def redis_request_hook(span: Span, instance: Redis, args, kwargs): +def redis_request_hook(span: Span, instance: Union[Redis|RedisCluster], args, kwargs): """ Redis Request Hook """ + # In cluster mode, the instance can be of two types: + # - redis.asyncio.cluster.RedisCluster + # - redis.cluster.RedisCluster + # Instead of checking the type, we check if the instance has a nodes_manager attribute. try: - connection_kwargs: dict = instance.connection_pool.connection_kwargs - host = connection_kwargs.get("host") - port = connection_kwargs.get("port") - db = connection_kwargs.get("db") + db = "" + if hasattr(instance, 'nodes_manager'): + default_node = instance.nodes_manager.default_node + if not default_node: + return + host = default_node.host + port = default_node.port + else: + connection_kwargs: dict = instance.connection_pool.connection_kwargs + host = connection_kwargs.get("host") + port = connection_kwargs.get("port") + db = connection_kwargs.get("db") span.set_attributes( { SpanAttributes.DB_INSTANCE: f"{host}/{db}", diff --git a/src/lib/components/chat/Messages/RateComment.svelte b/src/lib/components/chat/Messages/RateComment.svelte index d64c41c006..9a309ec4de 100644 --- a/src/lib/components/chat/Messages/RateComment.svelte +++ b/src/lib/components/chat/Messages/RateComment.svelte @@ -258,7 +258,7 @@ class="flex cursor-pointer items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-850 w-full px-3 py-2 rounded-xl transition" >
{selectedHistoryEntry?.snapshot
+ {selectedHistoryEntry?.snapshot
?.content || content}