2024-08-25 22:52:36 +08:00
import importlib . metadata
2024-08-28 06:10:27 +08:00
import json
import logging
import os
2024-08-25 22:52:36 +08:00
import pkgutil
2024-08-28 06:10:27 +08:00
import sys
2024-09-04 23:14:24 +08:00
import shutil
2025-06-09 01:21:51 +08:00
from uuid import uuid4
2024-08-28 06:10:27 +08:00
from pathlib import Path
2025-07-30 03:45:25 +08:00
from cryptography . hazmat . primitives import serialization
2024-08-25 22:52:36 +08:00
import markdown
from bs4 import BeautifulSoup
2024-09-04 22:54:48 +08:00
from open_webui . constants import ERROR_MESSAGES
2024-08-25 22:52:36 +08:00
####################################
# Load .env file
####################################
2024-09-04 22:54:48 +08:00
OPEN_WEBUI_DIR = Path ( __file__ ) . parent # the path containing this file
print ( OPEN_WEBUI_DIR )
BACKEND_DIR = OPEN_WEBUI_DIR . parent # the path containing this file
2024-08-25 22:52:36 +08:00
BASE_DIR = BACKEND_DIR . parent # the path containing the backend/
2024-09-04 22:54:48 +08:00
print ( BACKEND_DIR )
2024-08-25 22:52:36 +08:00
print ( BASE_DIR )
try :
2024-08-28 06:10:27 +08:00
from dotenv import find_dotenv , load_dotenv
2024-08-25 22:52:36 +08:00
load_dotenv ( find_dotenv ( str ( BASE_DIR / " .env " ) ) )
except ImportError :
print ( " dotenv not installed, skipping... " )
2024-09-20 02:56:13 +08:00
DOCKER = os . environ . get ( " DOCKER " , " False " ) . lower ( ) == " true "
2024-08-25 22:52:36 +08:00
2024-09-10 08:37:36 +08:00
# device type embedding models - "cpu" (default), "cuda" (nvidia gpu required) or "mps" (apple silicon) - choosing this right can lead to better performance
USE_CUDA = os . environ . get ( " USE_CUDA_DOCKER " , " false " )
if USE_CUDA . lower ( ) == " true " :
2024-09-13 23:12:00 +08:00
try :
import torch
2024-09-13 23:18:44 +08:00
2024-09-13 23:12:00 +08:00
assert torch . cuda . is_available ( ) , " CUDA not available "
DEVICE_TYPE = " cuda "
except Exception as e :
cuda_error = (
" Error when testing CUDA but USE_CUDA_DOCKER is true. "
f " Resetting USE_CUDA_DOCKER to false: { e } "
)
os . environ [ " USE_CUDA_DOCKER " ] = " false "
USE_CUDA = " false "
DEVICE_TYPE = " cpu "
2024-09-10 08:37:36 +08:00
else :
DEVICE_TYPE = " cpu "
2025-01-05 16:28:36 +08:00
try :
2025-01-07 02:08:12 +08:00
import torch
2025-01-05 16:28:36 +08:00
if torch . backends . mps . is_available ( ) and torch . backends . mps . is_built ( ) :
DEVICE_TYPE = " mps "
except Exception :
pass
2025-01-05 16:27:44 +08:00
2024-08-25 22:52:36 +08:00
####################################
# LOGGING
####################################
GLOBAL_LOG_LEVEL = os . environ . get ( " GLOBAL_LOG_LEVEL " , " " ) . upper ( )
2025-02-27 17:19:27 +08:00
if GLOBAL_LOG_LEVEL in logging . getLevelNamesMapping ( ) :
2024-08-25 22:52:36 +08:00
logging . basicConfig ( stream = sys . stdout , level = GLOBAL_LOG_LEVEL , force = True )
else :
GLOBAL_LOG_LEVEL = " INFO "
log = logging . getLogger ( __name__ )
log . info ( f " GLOBAL_LOG_LEVEL: { GLOBAL_LOG_LEVEL } " )
2024-09-13 23:12:00 +08:00
if " cuda_error " in locals ( ) :
log . exception ( cuda_error )
2025-03-04 12:55:07 +08:00
del cuda_error
2024-09-13 23:12:00 +08:00
2024-08-25 22:52:36 +08:00
log_sources = [
" AUDIO " ,
" COMFYUI " ,
" CONFIG " ,
" DB " ,
" IMAGES " ,
" MAIN " ,
" MODELS " ,
" OLLAMA " ,
" OPENAI " ,
" RAG " ,
" WEBHOOK " ,
2024-09-22 08:14:59 +08:00
" SOCKET " ,
2025-02-08 03:53:25 +08:00
" OAUTH " ,
2024-08-25 22:52:36 +08:00
]
SRC_LOG_LEVELS = { }
for source in log_sources :
log_env_var = source + " _LOG_LEVEL "
SRC_LOG_LEVELS [ source ] = os . environ . get ( log_env_var , " " ) . upper ( )
2025-02-27 17:19:27 +08:00
if SRC_LOG_LEVELS [ source ] not in logging . getLevelNamesMapping ( ) :
2024-08-25 22:52:36 +08:00
SRC_LOG_LEVELS [ source ] = GLOBAL_LOG_LEVEL
log . info ( f " { log_env_var } : { SRC_LOG_LEVELS [ source ] } " )
log . setLevel ( SRC_LOG_LEVELS [ " CONFIG " ] )
WEBUI_NAME = os . environ . get ( " WEBUI_NAME " , " Open WebUI " )
if WEBUI_NAME != " Open WebUI " :
WEBUI_NAME + = " (Open WebUI) "
WEBUI_FAVICON_URL = " https://openwebui.com/favicon.png "
2025-02-16 16:11:18 +08:00
TRUSTED_SIGNATURE_KEY = os . environ . get ( " TRUSTED_SIGNATURE_KEY " , " " )
2024-08-25 22:52:36 +08:00
####################################
# ENV (dev,test,prod)
####################################
ENV = os . environ . get ( " ENV " , " dev " )
2024-09-06 10:59:20 +08:00
FROM_INIT_PY = os . environ . get ( " FROM_INIT_PY " , " False " ) . lower ( ) == " true "
2024-09-04 22:54:48 +08:00
2024-09-06 10:59:20 +08:00
if FROM_INIT_PY :
2024-09-04 22:54:48 +08:00
PACKAGE_DATA = { " version " : importlib . metadata . version ( " open-webui " ) }
else :
2024-08-25 22:52:36 +08:00
try :
2024-09-04 22:54:48 +08:00
PACKAGE_DATA = json . loads ( ( BASE_DIR / " package.json " ) . read_text ( ) )
except Exception :
2024-08-25 22:52:36 +08:00
PACKAGE_DATA = { " version " : " 0.0.0 " }
VERSION = PACKAGE_DATA [ " version " ]
2025-06-09 01:21:51 +08:00
INSTANCE_ID = os . environ . get ( " INSTANCE_ID " , str ( uuid4 ( ) ) )
2024-08-25 22:52:36 +08:00
# Function to parse each section
def parse_section ( section ) :
items = [ ]
for li in section . find_all ( " li " ) :
# Extract raw HTML string
raw_html = str ( li )
# Extract text without HTML tags
text = li . get_text ( separator = " " , strip = True )
# Split into title and content
parts = text . split ( " : " , 1 )
title = parts [ 0 ] . strip ( ) if len ( parts ) > 1 else " "
content = parts [ 1 ] . strip ( ) if len ( parts ) > 1 else text
items . append ( { " title " : title , " content " : content , " raw " : raw_html } )
return items
try :
changelog_path = BASE_DIR / " CHANGELOG.md "
with open ( str ( changelog_path . absolute ( ) ) , " r " , encoding = " utf8 " ) as file :
changelog_content = file . read ( )
except Exception :
changelog_content = ( pkgutil . get_data ( " open_webui " , " CHANGELOG.md " ) or b " " ) . decode ( )
# Convert markdown content to HTML
html_content = markdown . markdown ( changelog_content )
# Parse the HTML content
soup = BeautifulSoup ( html_content , " html.parser " )
# Initialize JSON structure
changelog_json = { }
# Iterate over each version
for version in soup . find_all ( " h2 " ) :
version_number = version . get_text ( ) . strip ( ) . split ( " - " ) [ 0 ] [ 1 : - 1 ] # Remove brackets
date = version . get_text ( ) . strip ( ) . split ( " - " ) [ 1 ]
version_data = { " date " : date }
# Find the next sibling that is a h3 tag (section title)
current = version . find_next_sibling ( )
while current and current . name != " h2 " :
if current . name == " h3 " :
section_title = current . get_text ( ) . lower ( ) # e.g., "added", "fixed"
section_items = parse_section ( current . find_next_sibling ( " ul " ) )
version_data [ section_title ] = section_items
# Move to the next element
current = current . find_next_sibling ( )
changelog_json [ version_number ] = version_data
CHANGELOG = changelog_json
####################################
# SAFE_MODE
####################################
SAFE_MODE = os . environ . get ( " SAFE_MODE " , " false " ) . lower ( ) == " true "
2025-06-21 21:58:56 +08:00
2024-11-01 23:23:18 +08:00
####################################
2024-11-01 23:24:10 +08:00
# ENABLE_FORWARD_USER_INFO_HEADERS
2024-11-01 23:23:18 +08:00
####################################
2024-11-04 09:07:24 +08:00
ENABLE_FORWARD_USER_INFO_HEADERS = (
os . environ . get ( " ENABLE_FORWARD_USER_INFO_HEADERS " , " False " ) . lower ( ) == " true "
)
2024-11-01 23:23:18 +08:00
2024-08-25 22:52:36 +08:00
####################################
# WEBUI_BUILD_HASH
####################################
WEBUI_BUILD_HASH = os . environ . get ( " WEBUI_BUILD_HASH " , " dev-build " )
####################################
# DATA/FRONTEND BUILD DIR
####################################
DATA_DIR = Path ( os . getenv ( " DATA_DIR " , BACKEND_DIR / " data " ) ) . resolve ( )
2024-09-04 22:54:48 +08:00
2024-09-06 10:59:20 +08:00
if FROM_INIT_PY :
2024-09-04 23:47:51 +08:00
NEW_DATA_DIR = Path ( os . getenv ( " DATA_DIR " , OPEN_WEBUI_DIR / " data " ) ) . resolve ( )
NEW_DATA_DIR . mkdir ( parents = True , exist_ok = True )
2024-09-04 22:54:48 +08:00
# Check if the data directory exists in the package directory
2024-09-05 22:11:07 +08:00
if DATA_DIR . exists ( ) and DATA_DIR != NEW_DATA_DIR :
2024-09-04 23:47:51 +08:00
log . info ( f " Moving { DATA_DIR } to { NEW_DATA_DIR } " )
for item in DATA_DIR . iterdir ( ) :
dest = NEW_DATA_DIR / item . name
if item . is_dir ( ) :
shutil . copytree ( item , dest , dirs_exist_ok = True )
else :
shutil . copy2 ( item , dest )
2024-09-26 09:13:38 +08:00
# Zip the data directory
shutil . make_archive ( DATA_DIR . parent / " open_webui_data " , " zip " , DATA_DIR )
# Remove the old data directory
shutil . rmtree ( DATA_DIR )
2024-09-26 09:02:08 +08:00
2024-09-05 14:17:58 +08:00
DATA_DIR = Path ( os . getenv ( " DATA_DIR " , OPEN_WEBUI_DIR / " data " ) )
2024-09-04 22:54:48 +08:00
2024-10-13 15:05:28 +08:00
STATIC_DIR = Path ( os . getenv ( " STATIC_DIR " , OPEN_WEBUI_DIR / " static " ) )
2024-09-06 21:52:23 +08:00
FONTS_DIR = Path ( os . getenv ( " FONTS_DIR " , OPEN_WEBUI_DIR / " static " / " fonts " ) )
2024-08-25 22:52:36 +08:00
FRONTEND_BUILD_DIR = Path ( os . getenv ( " FRONTEND_BUILD_DIR " , BASE_DIR / " build " ) ) . resolve ( )
2024-09-05 22:11:07 +08:00
2024-09-06 10:59:20 +08:00
if FROM_INIT_PY :
2024-09-04 23:47:51 +08:00
FRONTEND_BUILD_DIR = Path (
os . getenv ( " FRONTEND_BUILD_DIR " , OPEN_WEBUI_DIR / " frontend " )
) . resolve ( )
2024-08-25 22:52:36 +08:00
####################################
# Database
####################################
# Check if the file exists
if os . path . exists ( f " { DATA_DIR } /ollama.db " ) :
# Rename the file
os . rename ( f " { DATA_DIR } /ollama.db " , f " { DATA_DIR } /webui.db " )
log . info ( " Database migrated from Ollama-WebUI successfully. " )
else :
pass
DATABASE_URL = os . environ . get ( " DATABASE_URL " , f " sqlite:/// { DATA_DIR } /webui.db " )
2025-07-03 21:47:12 +08:00
DATABASE_TYPE = os . environ . get ( " DATABASE_TYPE " )
DATABASE_USER = os . environ . get ( " DATABASE_USER " )
DATABASE_PASSWORD = os . environ . get ( " DATABASE_PASSWORD " )
DATABASE_CRED = " "
if DATABASE_USER :
DATABASE_CRED + = f " { DATABASE_USER } "
if DATABASE_PASSWORD :
DATABASE_CRED + = f " : { DATABASE_PASSWORD } "
DB_VARS = {
" db_type " : DATABASE_TYPE ,
" db_cred " : DATABASE_CRED ,
" db_host " : os . environ . get ( " DATABASE_HOST " ) ,
" db_port " : os . environ . get ( " DATABASE_PORT " ) ,
" db_name " : os . environ . get ( " DATABASE_NAME " ) ,
}
if all ( DB_VARS . values ( ) ) :
DATABASE_URL = f " { DB_VARS [ ' db_type ' ] } :// { DB_VARS [ ' db_cred ' ] } @ { DB_VARS [ ' db_host ' ] } : { DB_VARS [ ' db_port ' ] } / { DB_VARS [ ' db_name ' ] } "
2025-07-30 05:42:36 +08:00
elif DATABASE_TYPE == " sqlite+sqlcipher " and not os . environ . get ( " DATABASE_URL " ) :
# Handle SQLCipher with local file when DATABASE_URL wasn't explicitly set
DATABASE_URL = f " sqlite+sqlcipher:/// { DATA_DIR } /webui.db "
2025-07-03 21:47:12 +08:00
2024-08-25 22:52:36 +08:00
# Replace the postgres:// with postgresql://
if " postgres:// " in DATABASE_URL :
DATABASE_URL = DATABASE_URL . replace ( " postgres:// " , " postgresql:// " )
2024-12-10 22:18:26 +08:00
DATABASE_SCHEMA = os . environ . get ( " DATABASE_SCHEMA " , None )
2025-06-21 20:37:21 +08:00
DATABASE_POOL_SIZE = os . environ . get ( " DATABASE_POOL_SIZE " , None )
2024-10-06 22:46:35 +08:00
2025-06-21 20:37:21 +08:00
if DATABASE_POOL_SIZE != None :
2024-10-06 22:46:35 +08:00
try :
DATABASE_POOL_SIZE = int ( DATABASE_POOL_SIZE )
except Exception :
2025-06-21 20:37:21 +08:00
DATABASE_POOL_SIZE = None
2024-10-06 22:46:35 +08:00
DATABASE_POOL_MAX_OVERFLOW = os . environ . get ( " DATABASE_POOL_MAX_OVERFLOW " , 0 )
if DATABASE_POOL_MAX_OVERFLOW == " " :
DATABASE_POOL_MAX_OVERFLOW = 0
else :
try :
DATABASE_POOL_MAX_OVERFLOW = int ( DATABASE_POOL_MAX_OVERFLOW )
except Exception :
DATABASE_POOL_MAX_OVERFLOW = 0
DATABASE_POOL_TIMEOUT = os . environ . get ( " DATABASE_POOL_TIMEOUT " , 30 )
if DATABASE_POOL_TIMEOUT == " " :
DATABASE_POOL_TIMEOUT = 30
else :
try :
DATABASE_POOL_TIMEOUT = int ( DATABASE_POOL_TIMEOUT )
except Exception :
DATABASE_POOL_TIMEOUT = 30
DATABASE_POOL_RECYCLE = os . environ . get ( " DATABASE_POOL_RECYCLE " , 3600 )
if DATABASE_POOL_RECYCLE == " " :
DATABASE_POOL_RECYCLE = 3600
else :
try :
DATABASE_POOL_RECYCLE = int ( DATABASE_POOL_RECYCLE )
except Exception :
DATABASE_POOL_RECYCLE = 3600
2024-08-25 22:52:36 +08:00
2024-09-25 07:06:11 +08:00
RESET_CONFIG_ON_START = (
os . environ . get ( " RESET_CONFIG_ON_START " , " False " ) . lower ( ) == " true "
)
2024-12-28 14:36:14 +08:00
ENABLE_REALTIME_CHAT_SAVE = (
2025-01-02 12:12:42 +08:00
os . environ . get ( " ENABLE_REALTIME_CHAT_SAVE " , " False " ) . lower ( ) == " true "
2024-12-28 14:36:14 +08:00
)
2024-10-09 14:37:37 +08:00
####################################
# REDIS
####################################
2025-03-09 01:59:15 +08:00
REDIS_URL = os . environ . get ( " REDIS_URL " , " " )
2025-08-04 18:15:08 +08:00
REDIS_CLUSTER = os . environ . get ( " REDIS_CLUSTER " , " False " ) . lower ( ) == " true "
2025-06-29 01:11:26 +08:00
REDIS_KEY_PREFIX = os . environ . get ( " REDIS_KEY_PREFIX " , " open-webui " )
2025-08-04 18:15:08 +08:00
2025-03-27 15:51:55 +08:00
REDIS_SENTINEL_HOSTS = os . environ . get ( " REDIS_SENTINEL_HOSTS " , " " )
REDIS_SENTINEL_PORT = os . environ . get ( " REDIS_SENTINEL_PORT " , " 26379 " )
2024-10-09 14:37:37 +08:00
2025-07-16 08:11:08 +08:00
# Maximum number of retries for Redis operations when using Sentinel fail-over
REDIS_SENTINEL_MAX_RETRY_COUNT = os . environ . get ( " REDIS_SENTINEL_MAX_RETRY_COUNT " , " 2 " )
try :
REDIS_SENTINEL_MAX_RETRY_COUNT = int ( REDIS_SENTINEL_MAX_RETRY_COUNT )
if REDIS_SENTINEL_MAX_RETRY_COUNT < 1 :
REDIS_SENTINEL_MAX_RETRY_COUNT = 2
except ValueError :
REDIS_SENTINEL_MAX_RETRY_COUNT = 2
2025-04-09 00:38:00 +08:00
####################################
# UVICORN WORKERS
####################################
2025-04-09 00:47:48 +08:00
# Number of uvicorn worker processes for handling requests
2025-04-09 00:38:00 +08:00
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 } " )
2024-08-25 22:52:36 +08:00
####################################
# WEBUI_AUTH (Required for security)
####################################
WEBUI_AUTH = os . environ . get ( " WEBUI_AUTH " , " True " ) . lower ( ) == " true "
2025-07-31 20:43:37 +08:00
ENABLE_SIGNUP_PASSWORD_CONFIRMATION = (
os . environ . get ( " ENABLE_SIGNUP_PASSWORD_CONFIRMATION " , " False " ) . lower ( ) == " true "
)
2024-08-25 22:52:36 +08:00
WEBUI_AUTH_TRUSTED_EMAIL_HEADER = os . environ . get (
" WEBUI_AUTH_TRUSTED_EMAIL_HEADER " , None
)
WEBUI_AUTH_TRUSTED_NAME_HEADER = os . environ . get ( " WEBUI_AUTH_TRUSTED_NAME_HEADER " , None )
2025-05-25 03:17:12 +08:00
WEBUI_AUTH_TRUSTED_GROUPS_HEADER = os . environ . get (
" WEBUI_AUTH_TRUSTED_GROUPS_HEADER " , None
)
2024-08-25 22:52:36 +08:00
2024-12-02 10:25:44 +08:00
BYPASS_MODEL_ACCESS_CONTROL = (
os . environ . get ( " BYPASS_MODEL_ACCESS_CONTROL " , " False " ) . lower ( ) == " true "
)
2024-08-25 22:52:36 +08:00
2025-04-19 14:58:37 +08:00
WEBUI_AUTH_SIGNOUT_REDIRECT_URL = os . environ . get (
" WEBUI_AUTH_SIGNOUT_REDIRECT_URL " , None
)
2025-04-08 09:39:00 +08:00
2024-08-25 22:52:36 +08:00
####################################
# WEBUI_SECRET_KEY
####################################
WEBUI_SECRET_KEY = os . environ . get (
" WEBUI_SECRET_KEY " ,
os . environ . get (
" WEBUI_JWT_SECRET_KEY " , " t0p-s3cr3t "
) , # DEPRECATED: remove at next major version
)
2025-01-23 22:16:50 +08:00
WEBUI_SESSION_COOKIE_SAME_SITE = os . environ . get ( " WEBUI_SESSION_COOKIE_SAME_SITE " , " lax " )
2024-08-25 22:52:36 +08:00
2025-02-04 05:37:29 +08:00
WEBUI_SESSION_COOKIE_SECURE = (
os . environ . get ( " WEBUI_SESSION_COOKIE_SECURE " , " false " ) . lower ( ) == " true "
)
2025-01-23 22:16:50 +08:00
2025-02-04 05:37:29 +08:00
WEBUI_AUTH_COOKIE_SAME_SITE = os . environ . get (
" WEBUI_AUTH_COOKIE_SAME_SITE " , WEBUI_SESSION_COOKIE_SAME_SITE
)
2025-01-23 22:16:50 +08:00
2025-02-04 05:37:29 +08:00
WEBUI_AUTH_COOKIE_SECURE = (
os . environ . get (
" WEBUI_AUTH_COOKIE_SECURE " ,
os . environ . get ( " WEBUI_SESSION_COOKIE_SECURE " , " false " ) ,
) . lower ( )
== " true "
)
2024-08-25 22:52:36 +08:00
if WEBUI_AUTH and WEBUI_SECRET_KEY == " " :
raise ValueError ( ERROR_MESSAGES . ENV_VAR_NOT_FOUND )
2024-09-10 06:17:17 +08:00
2025-06-21 21:58:56 +08:00
ENABLE_COMPRESSION_MIDDLEWARE = (
os . environ . get ( " ENABLE_COMPRESSION_MIDDLEWARE " , " True " ) . lower ( ) == " true "
)
2025-07-30 03:45:25 +08:00
2025-08-06 18:25:42 +08:00
####################################
# SCIM Configuration
####################################
SCIM_ENABLED = os . environ . get ( " SCIM_ENABLED " , " False " ) . lower ( ) == " true "
SCIM_TOKEN = os . environ . get ( " SCIM_TOKEN " , " " )
2025-07-30 03:45:25 +08:00
####################################
# LICENSE_KEY
####################################
LICENSE_KEY = os . environ . get ( " LICENSE_KEY " , " " )
LICENSE_BLOB = None
LICENSE_BLOB_PATH = os . environ . get ( " LICENSE_BLOB_PATH " , DATA_DIR / " l.data " )
if LICENSE_BLOB_PATH and os . path . exists ( LICENSE_BLOB_PATH ) :
with open ( LICENSE_BLOB_PATH , " rb " ) as f :
LICENSE_BLOB = f . read ( )
LICENSE_PUBLIC_KEY = os . environ . get ( " LICENSE_PUBLIC_KEY " , " " )
pk = None
if LICENSE_PUBLIC_KEY :
pk = serialization . load_pem_public_key (
f """
- - - - - BEGIN PUBLIC KEY - - - - -
{ LICENSE_PUBLIC_KEY }
- - - - - END PUBLIC KEY - - - - -
""" .encode(
" utf-8 "
)
)
2025-06-28 18:44:47 +08:00
####################################
# MODELS
####################################
2024-09-21 05:43:22 +08:00
2025-06-28 18:44:47 +08:00
MODELS_CACHE_TTL = os . environ . get ( " MODELS_CACHE_TTL " , " 1 " )
if MODELS_CACHE_TTL == " " :
MODELS_CACHE_TTL = None
2025-06-27 19:59:30 +08:00
else :
try :
2025-06-28 18:44:47 +08:00
MODELS_CACHE_TTL = int ( MODELS_CACHE_TTL )
2025-06-27 19:59:30 +08:00
except Exception :
2025-06-28 18:44:47 +08:00
MODELS_CACHE_TTL = 1
2025-08-10 03:49:56 +08:00
####################################
# CHAT
####################################
CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE = os . environ . get (
" CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE " , " 1 "
)
if CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE == " " :
CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE = 1
else :
try :
CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE = int (
CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE
)
except Exception :
CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE = 1
2025-06-28 18:44:47 +08:00
####################################
# WEBSOCKET SUPPORT
####################################
ENABLE_WEBSOCKET_SUPPORT = (
os . environ . get ( " ENABLE_WEBSOCKET_SUPPORT " , " True " ) . lower ( ) == " true "
)
2025-06-27 19:59:30 +08:00
2024-09-21 05:43:22 +08:00
WEBSOCKET_MANAGER = os . environ . get ( " WEBSOCKET_MANAGER " , " " )
2024-10-09 14:37:37 +08:00
WEBSOCKET_REDIS_URL = os . environ . get ( " WEBSOCKET_REDIS_URL " , REDIS_URL )
2025-08-04 18:15:08 +08:00
WEBSOCKET_REDIS_CLUSTER = (
os . environ . get ( " WEBSOCKET_REDIS_CLUSTER " , str ( REDIS_CLUSTER ) ) . lower ( ) == " true "
)
2025-07-15 22:10:36 +08:00
websocket_redis_lock_timeout = os . environ . get ( " WEBSOCKET_REDIS_LOCK_TIMEOUT " , " 60 " )
try :
WEBSOCKET_REDIS_LOCK_TIMEOUT = int ( websocket_redis_lock_timeout )
except ValueError :
WEBSOCKET_REDIS_LOCK_TIMEOUT = 60
2024-09-30 22:32:38 +08:00
2025-03-04 18:10:07 +08:00
WEBSOCKET_SENTINEL_HOSTS = os . environ . get ( " WEBSOCKET_SENTINEL_HOSTS " , " " )
WEBSOCKET_SENTINEL_PORT = os . environ . get ( " WEBSOCKET_SENTINEL_PORT " , " 26379 " )
2025-08-04 18:15:08 +08:00
2024-09-30 22:32:38 +08:00
AIOHTTP_CLIENT_TIMEOUT = os . environ . get ( " AIOHTTP_CLIENT_TIMEOUT " , " " )
if AIOHTTP_CLIENT_TIMEOUT == " " :
AIOHTTP_CLIENT_TIMEOUT = None
else :
try :
AIOHTTP_CLIENT_TIMEOUT = int ( AIOHTTP_CLIENT_TIMEOUT )
except Exception :
AIOHTTP_CLIENT_TIMEOUT = 300
2024-10-08 13:13:49 +08:00
2025-04-18 13:11:42 +08:00
AIOHTTP_CLIENT_SESSION_SSL = (
os . environ . get ( " AIOHTTP_CLIENT_SESSION_SSL " , " True " ) . lower ( ) == " true "
)
2025-03-04 12:24:10 +08:00
AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST = os . environ . get (
" AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST " ,
2025-03-19 23:32:31 +08:00
os . environ . get ( " AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST " , " 10 " ) ,
2024-10-14 13:56:33 +08:00
)
2024-10-14 08:52:59 +08:00
2025-03-04 12:24:10 +08:00
if AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST == " " :
AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST = None
2024-10-14 08:52:59 +08:00
else :
try :
2025-03-04 12:24:10 +08:00
AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST = int ( AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST )
2024-10-14 08:52:59 +08:00
except Exception :
2025-03-19 23:32:31 +08:00
AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST = 10
2025-03-04 12:24:10 +08:00
2025-04-11 01:23:14 +08:00
AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA = os . environ . get (
" AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA " , " 10 "
)
2025-04-11 02:18:53 +08:00
if AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA == " " :
AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA = None
else :
try :
AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA = int (
AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA
)
except Exception :
AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA = 10
2025-04-18 13:02:16 +08:00
AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL = (
os . environ . get ( " AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL " , " True " ) . lower ( ) == " true "
)
2025-04-24 00:55:18 +08:00
####################################
# SENTENCE TRANSFORMERS
####################################
SENTENCE_TRANSFORMERS_BACKEND = os . environ . get ( " SENTENCE_TRANSFORMERS_BACKEND " , " " )
if SENTENCE_TRANSFORMERS_BACKEND == " " :
SENTENCE_TRANSFORMERS_BACKEND = " torch "
SENTENCE_TRANSFORMERS_MODEL_KWARGS = os . environ . get (
" SENTENCE_TRANSFORMERS_MODEL_KWARGS " , " "
)
if SENTENCE_TRANSFORMERS_MODEL_KWARGS == " " :
SENTENCE_TRANSFORMERS_MODEL_KWARGS = None
else :
try :
SENTENCE_TRANSFORMERS_MODEL_KWARGS = json . loads (
SENTENCE_TRANSFORMERS_MODEL_KWARGS
)
except Exception :
SENTENCE_TRANSFORMERS_MODEL_KWARGS = None
SENTENCE_TRANSFORMERS_CROSS_ENCODER_BACKEND = os . environ . get (
" SENTENCE_TRANSFORMERS_CROSS_ENCODER_BACKEND " , " "
)
if SENTENCE_TRANSFORMERS_CROSS_ENCODER_BACKEND == " " :
SENTENCE_TRANSFORMERS_CROSS_ENCODER_BACKEND = " torch "
SENTENCE_TRANSFORMERS_CROSS_ENCODER_MODEL_KWARGS = os . environ . get (
" SENTENCE_TRANSFORMERS_CROSS_ENCODER_MODEL_KWARGS " , " "
)
if SENTENCE_TRANSFORMERS_CROSS_ENCODER_MODEL_KWARGS == " " :
SENTENCE_TRANSFORMERS_CROSS_ENCODER_MODEL_KWARGS = None
else :
try :
SENTENCE_TRANSFORMERS_CROSS_ENCODER_MODEL_KWARGS = json . loads (
SENTENCE_TRANSFORMERS_CROSS_ENCODER_MODEL_KWARGS
)
except Exception :
SENTENCE_TRANSFORMERS_CROSS_ENCODER_MODEL_KWARGS = None
2024-10-08 13:13:49 +08:00
####################################
# OFFLINE_MODE
####################################
2025-07-02 20:43:57 +08:00
ENABLE_VERSION_UPDATE_CHECK = (
os . environ . get ( " ENABLE_VERSION_UPDATE_CHECK " , " true " ) . lower ( ) == " true "
)
2024-10-08 13:13:49 +08:00
OFFLINE_MODE = os . environ . get ( " OFFLINE_MODE " , " false " ) . lower ( ) == " true "
2024-12-29 14:23:09 +08:00
if OFFLINE_MODE :
os . environ [ " HF_HUB_OFFLINE " ] = " 1 "
2025-07-02 20:43:57 +08:00
ENABLE_VERSION_UPDATE_CHECK = False
2025-04-24 00:55:18 +08:00
2025-02-20 22:15:38 +08:00
####################################
# AUDIT LOGGING
####################################
# Where to store log file
AUDIT_LOGS_FILE_PATH = f " { DATA_DIR } /audit.log "
# Maximum size of a file before rotating into a new log file
AUDIT_LOG_FILE_ROTATION_SIZE = os . getenv ( " AUDIT_LOG_FILE_ROTATION_SIZE " , " 10MB " )
2025-07-04 01:54:25 +08:00
# Comma separated list of logger names to use for audit logging
# Default is "uvicorn.access" which is the access log for Uvicorn
# You can add more logger names to this list if you want to capture more logs
AUDIT_UVICORN_LOGGER_NAMES = os . getenv (
" AUDIT_UVICORN_LOGGER_NAMES " , " uvicorn.access "
) . split ( " , " )
2025-02-20 22:15:38 +08:00
# METADATA | REQUEST | REQUEST_RESPONSE
2025-03-22 15:21:05 +08:00
AUDIT_LOG_LEVEL = os . getenv ( " AUDIT_LOG_LEVEL " , " NONE " ) . upper ( )
2025-02-20 22:15:38 +08:00
try :
MAX_BODY_LOG_SIZE = int ( os . environ . get ( " MAX_BODY_LOG_SIZE " ) or 2048 )
except ValueError :
MAX_BODY_LOG_SIZE = 2048
# Comma separated list for urls to exclude from audit
AUDIT_EXCLUDED_PATHS = os . getenv ( " AUDIT_EXCLUDED_PATHS " , " /chats,/chat,/folders " ) . split (
" , "
)
AUDIT_EXCLUDED_PATHS = [ path . strip ( ) for path in AUDIT_EXCLUDED_PATHS ]
AUDIT_EXCLUDED_PATHS = [ path . lstrip ( " / " ) for path in AUDIT_EXCLUDED_PATHS ]
2025-03-10 22:27:31 +08:00
2025-04-24 00:55:18 +08:00
2025-03-10 22:27:31 +08:00
####################################
# OPENTELEMETRY
####################################
2025-03-12 02:55:30 +08:00
ENABLE_OTEL = os . environ . get ( " ENABLE_OTEL " , " False " ) . lower ( ) == " true "
2025-05-23 06:18:15 +08:00
ENABLE_OTEL_METRICS = os . environ . get ( " ENABLE_OTEL_METRICS " , " False " ) . lower ( ) == " true "
2025-08-01 02:58:49 +08:00
ENABLE_OTEL_LOGS = os . environ . get ( " ENABLE_OTEL_LOGS " , " False " ) . lower ( ) == " true "
2025-08-02 16:30:34 +08:00
2025-03-11 11:53:03 +08:00
OTEL_EXPORTER_OTLP_ENDPOINT = os . environ . get (
" OTEL_EXPORTER_OTLP_ENDPOINT " , " http://localhost:4317 "
)
2025-08-02 16:30:34 +08:00
OTEL_METRICS_EXPORTER_OTLP_ENDPOINT = os . environ . get (
" OTEL_METRICS_EXPORTER_OTLP_ENDPOINT " , OTEL_EXPORTER_OTLP_ENDPOINT
)
2025-08-03 03:15:22 +08:00
OTEL_LOGS_EXPORTER_OTLP_ENDPOINT = os . environ . get (
" OTEL_LOGS_EXPORTER_OTLP_ENDPOINT " , OTEL_EXPORTER_OTLP_ENDPOINT
)
2025-06-18 17:42:33 +08:00
OTEL_EXPORTER_OTLP_INSECURE = (
os . environ . get ( " OTEL_EXPORTER_OTLP_INSECURE " , " False " ) . lower ( ) == " true "
)
2025-08-02 16:30:34 +08:00
OTEL_METRICS_EXPORTER_OTLP_INSECURE = (
2025-08-10 17:49:28 +08:00
os . environ . get (
" OTEL_METRICS_EXPORTER_OTLP_INSECURE " , str ( OTEL_EXPORTER_OTLP_INSECURE )
) . lower ( )
== " true "
2025-08-02 16:30:34 +08:00
)
2025-08-03 03:15:22 +08:00
OTEL_LOGS_EXPORTER_OTLP_INSECURE = (
2025-08-10 17:49:28 +08:00
os . environ . get (
" OTEL_LOGS_EXPORTER_OTLP_INSECURE " , str ( OTEL_EXPORTER_OTLP_INSECURE )
) . lower ( )
== " true "
2025-08-03 03:15:22 +08:00
)
2025-03-11 11:53:03 +08:00
OTEL_SERVICE_NAME = os . environ . get ( " OTEL_SERVICE_NAME " , " open-webui " )
OTEL_RESOURCE_ATTRIBUTES = os . environ . get (
" OTEL_RESOURCE_ATTRIBUTES " , " "
) # e.g. key1=val1,key2=val2
OTEL_TRACES_SAMPLER = os . environ . get (
" OTEL_TRACES_SAMPLER " , " parentbased_always_on "
) . lower ( )
2025-06-18 17:42:33 +08:00
OTEL_BASIC_AUTH_USERNAME = os . environ . get ( " OTEL_BASIC_AUTH_USERNAME " , " " )
OTEL_BASIC_AUTH_PASSWORD = os . environ . get ( " OTEL_BASIC_AUTH_PASSWORD " , " " )
2025-03-13 05:15:26 +08:00
2025-08-02 16:30:34 +08:00
OTEL_METRICS_BASIC_AUTH_USERNAME = os . environ . get (
" OTEL_METRICS_BASIC_AUTH_USERNAME " , OTEL_BASIC_AUTH_USERNAME
)
OTEL_METRICS_BASIC_AUTH_PASSWORD = os . environ . get (
" OTEL_METRICS_BASIC_AUTH_PASSWORD " , OTEL_BASIC_AUTH_PASSWORD
)
2025-08-03 03:15:22 +08:00
OTEL_LOGS_BASIC_AUTH_USERNAME = os . environ . get (
" OTEL_LOGS_BASIC_AUTH_USERNAME " , OTEL_BASIC_AUTH_USERNAME
)
OTEL_LOGS_BASIC_AUTH_PASSWORD = os . environ . get (
" OTEL_LOGS_BASIC_AUTH_PASSWORD " , OTEL_BASIC_AUTH_PASSWORD
)
2025-06-30 19:52:32 +08:00
OTEL_OTLP_SPAN_EXPORTER = os . environ . get (
" OTEL_OTLP_SPAN_EXPORTER " , " grpc "
) . lower ( ) # grpc or http
2025-08-02 16:30:34 +08:00
OTEL_METRICS_OTLP_SPAN_EXPORTER = os . environ . get (
" OTEL_METRICS_OTLP_SPAN_EXPORTER " , OTEL_OTLP_SPAN_EXPORTER
) . lower ( ) # grpc or http
2025-08-03 03:15:22 +08:00
OTEL_LOGS_OTLP_SPAN_EXPORTER = os . environ . get (
" OTEL_LOGS_OTLP_SPAN_EXPORTER " , OTEL_OTLP_SPAN_EXPORTER
) . lower ( ) # grpc or http
2025-06-30 19:52:32 +08:00
2025-03-13 05:15:26 +08:00
####################################
# TOOLS/FUNCTIONS PIP OPTIONS
####################################
PIP_OPTIONS = os . getenv ( " PIP_OPTIONS " , " " ) . split ( )
PIP_PACKAGE_INDEX_OPTIONS = os . getenv ( " PIP_PACKAGE_INDEX_OPTIONS " , " " ) . split ( )
2025-04-11 01:35:43 +08:00
####################################
# PROGRESSIVE WEB APP OPTIONS
####################################
2025-04-13 07:35:11 +08:00
EXTERNAL_PWA_MANIFEST_URL = os . environ . get ( " EXTERNAL_PWA_MANIFEST_URL " )