diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index 93ed6b75ef..ed6906edcf 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -1232,19 +1232,23 @@ USER_PERMISSIONS_WORKSPACE_TOOLS_ACCESS = ( ) USER_PERMISSIONS_WORKSPACE_MODELS_IMPORT = ( - os.environ.get("USER_PERMISSIONS_WORKSPACE_MODELS_IMPORT", "False").lower() == "true" + os.environ.get("USER_PERMISSIONS_WORKSPACE_MODELS_IMPORT", "False").lower() + == "true" ) USER_PERMISSIONS_WORKSPACE_MODELS_EXPORT = ( - os.environ.get("USER_PERMISSIONS_WORKSPACE_MODELS_EXPORT", "False").lower() == "true" + os.environ.get("USER_PERMISSIONS_WORKSPACE_MODELS_EXPORT", "False").lower() + == "true" ) USER_PERMISSIONS_WORKSPACE_PROMPTS_IMPORT = ( - os.environ.get("USER_PERMISSIONS_WORKSPACE_PROMPTS_IMPORT", "False").lower() == "true" + os.environ.get("USER_PERMISSIONS_WORKSPACE_PROMPTS_IMPORT", "False").lower() + == "true" ) USER_PERMISSIONS_WORKSPACE_PROMPTS_EXPORT = ( - os.environ.get("USER_PERMISSIONS_WORKSPACE_PROMPTS_EXPORT", "False").lower() == "true" + os.environ.get("USER_PERMISSIONS_WORKSPACE_PROMPTS_EXPORT", "False").lower() + == "true" ) USER_PERMISSIONS_WORKSPACE_TOOLS_IMPORT = ( @@ -2149,14 +2153,9 @@ PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH = int( os.environ.get("PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH", "1536") ) -PGVECTOR_USE_HALFVEC = ( - os.getenv("PGVECTOR_USE_HALFVEC", "false").lower() == "true" -) +PGVECTOR_USE_HALFVEC = os.getenv("PGVECTOR_USE_HALFVEC", "false").lower() == "true" -if ( - PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH > 2000 - and not PGVECTOR_USE_HALFVEC -): +if PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH > 2000 and not PGVECTOR_USE_HALFVEC: raise ValueError( "PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH is set to " f"{PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH}, which exceeds the 2000 dimension limit of the " @@ -3449,6 +3448,18 @@ IMAGES_OPENAI_API_KEY = PersistentConfig( os.getenv("IMAGES_OPENAI_API_KEY", OPENAI_API_KEY), ) +images_openai_params = os.getenv("IMAGES_OPENAI_PARAMS", "") +try: + images_openai_params = json.loads(images_openai_params) +except json.JSONDecodeError: + images_openai_params = {} + + +IMAGES_OPENAI_API_PARAMS = PersistentConfig( + "IMAGES_OPENAI_API_PARAMS", "image_generation.openai.params", images_openai_params +) + + IMAGES_GEMINI_API_BASE_URL = PersistentConfig( "IMAGES_GEMINI_API_BASE_URL", "image_generation.gemini.api_base_url", diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index c694008696..4c39a649a0 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -160,6 +160,7 @@ from open_webui.config import ( IMAGES_OPENAI_API_BASE_URL, IMAGES_OPENAI_API_VERSION, IMAGES_OPENAI_API_KEY, + IMAGES_OPENAI_API_PARAMS, IMAGES_GEMINI_API_BASE_URL, IMAGES_GEMINI_API_KEY, IMAGES_GEMINI_ENDPOINT_METHOD, @@ -1094,6 +1095,7 @@ app.state.config.IMAGE_STEPS = IMAGE_STEPS app.state.config.IMAGES_OPENAI_API_BASE_URL = IMAGES_OPENAI_API_BASE_URL app.state.config.IMAGES_OPENAI_API_VERSION = IMAGES_OPENAI_API_VERSION app.state.config.IMAGES_OPENAI_API_KEY = IMAGES_OPENAI_API_KEY +app.state.config.IMAGES_OPENAI_API_PARAMS = IMAGES_OPENAI_API_PARAMS app.state.config.IMAGES_GEMINI_API_BASE_URL = IMAGES_GEMINI_API_BASE_URL app.state.config.IMAGES_GEMINI_API_KEY = IMAGES_GEMINI_API_KEY diff --git a/backend/open_webui/routers/images.py b/backend/open_webui/routers/images.py index 6b7b09f8a1..5f035695a9 100644 --- a/backend/open_webui/routers/images.py +++ b/backend/open_webui/routers/images.py @@ -111,6 +111,7 @@ class ImagesConfig(BaseModel): IMAGES_OPENAI_API_BASE_URL: str IMAGES_OPENAI_API_KEY: str IMAGES_OPENAI_API_VERSION: str + IMAGES_OPENAI_API_PARAMS: Optional[dict | str] AUTOMATIC1111_BASE_URL: str AUTOMATIC1111_API_AUTH: Optional[dict | str] @@ -152,6 +153,7 @@ async def get_config(request: Request, user=Depends(get_admin_user)): "IMAGES_OPENAI_API_BASE_URL": request.app.state.config.IMAGES_OPENAI_API_BASE_URL, "IMAGES_OPENAI_API_KEY": request.app.state.config.IMAGES_OPENAI_API_KEY, "IMAGES_OPENAI_API_VERSION": request.app.state.config.IMAGES_OPENAI_API_VERSION, + "IMAGES_OPENAI_API_PARAMS": request.app.state.config.IMAGES_OPENAI_API_PARAMS, "AUTOMATIC1111_BASE_URL": request.app.state.config.AUTOMATIC1111_BASE_URL, "AUTOMATIC1111_API_AUTH": request.app.state.config.AUTOMATIC1111_API_AUTH, "AUTOMATIC1111_PARAMS": request.app.state.config.AUTOMATIC1111_PARAMS, @@ -229,6 +231,9 @@ async def update_config( request.app.state.config.IMAGES_OPENAI_API_VERSION = ( form_data.IMAGES_OPENAI_API_VERSION ) + request.app.state.config.IMAGES_OPENAI_API_PARAMS = ( + form_data.IMAGES_OPENAI_API_PARAMS + ) request.app.state.config.AUTOMATIC1111_BASE_URL = form_data.AUTOMATIC1111_BASE_URL request.app.state.config.AUTOMATIC1111_API_AUTH = form_data.AUTOMATIC1111_API_AUTH @@ -292,6 +297,7 @@ async def update_config( "IMAGES_OPENAI_API_BASE_URL": request.app.state.config.IMAGES_OPENAI_API_BASE_URL, "IMAGES_OPENAI_API_KEY": request.app.state.config.IMAGES_OPENAI_API_KEY, "IMAGES_OPENAI_API_VERSION": request.app.state.config.IMAGES_OPENAI_API_VERSION, + "IMAGES_OPENAI_API_PARAMS": request.app.state.config.IMAGES_OPENAI_API_PARAMS, "AUTOMATIC1111_BASE_URL": request.app.state.config.AUTOMATIC1111_BASE_URL, "AUTOMATIC1111_API_AUTH": request.app.state.config.AUTOMATIC1111_API_AUTH, "AUTOMATIC1111_PARAMS": request.app.state.config.AUTOMATIC1111_PARAMS, @@ -539,6 +545,12 @@ async def image_generations( if ENABLE_FORWARD_USER_INFO_HEADERS: headers = include_user_info_headers(headers, user) + url = ( + f"{request.app.state.config.IMAGES_OPENAI_API_BASE_URL}/images/generations", + ) + if request.app.state.config.IMAGES_OPENAI_API_VERSION: + url = f"{url}?api-version={request.app.state.config.IMAGES_OPENAI_API_VERSION}" + data = { "model": model, "prompt": form_data.prompt, @@ -553,18 +565,17 @@ async def image_generations( if "gpt-image-1" in request.app.state.config.IMAGE_GENERATION_MODEL else {"response_format": "b64_json"} ), + **( + {} + if not request.app.state.config.IMAGES_OPENAI_API_PARAMS + else request.app.state.config.IMAGES_OPENAI_API_PARAMS + ), } - api_version_query_param = "" - if request.app.state.config.IMAGES_OPENAI_API_VERSION: - api_version_query_param = ( - f"?api-version={request.app.state.config.IMAGES_OPENAI_API_VERSION}" - ) - # Use asyncio.to_thread for the requests.post call r = await asyncio.to_thread( requests.post, - url=f"{request.app.state.config.IMAGES_OPENAI_API_BASE_URL}/images/generations{api_version_query_param}", + url=url, json=data, headers=headers, ) diff --git a/src/lib/components/admin/Settings/Images.svelte b/src/lib/components/admin/Settings/Images.svelte index 41d7b7cfea..2794f2bbaa 100644 --- a/src/lib/components/admin/Settings/Images.svelte +++ b/src/lib/components/admin/Settings/Images.svelte @@ -129,6 +129,11 @@ AUTOMATIC1111_PARAMS: typeof config.AUTOMATIC1111_PARAMS === 'string' && config.AUTOMATIC1111_PARAMS.trim() !== '' ? JSON.parse(config.AUTOMATIC1111_PARAMS) + : {}, + IMAGES_OPENAI_API_PARAMS: + typeof config.IMAGES_OPENAI_API_PARAMS === 'string' && + config.IMAGES_OPENAI_API_PARAMS.trim() !== '' + ? JSON.parse(config.IMAGES_OPENAI_API_PARAMS) : {} }).catch((error) => { toast.error(`${error}`); @@ -249,6 +254,11 @@ } } + config.IMAGES_OPENAI_API_PARAMS = + typeof config.IMAGES_OPENAI_API_PARAMS === 'object' + ? JSON.stringify(config.IMAGES_OPENAI_API_PARAMS ?? {}, null, 2) + : config.IMAGES_OPENAI_API_PARAMS; + config.AUTOMATIC1111_PARAMS = typeof config.AUTOMATIC1111_PARAMS === 'object' ? JSON.stringify(config.AUTOMATIC1111_PARAMS ?? {}, null, 2) @@ -465,6 +475,26 @@ + +