123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809 |
- import importlib.metadata
- import json
- import logging
- import os
- import pkgutil
- import sys
- import shutil
- from uuid import uuid4
- from pathlib import Path
- from cryptography.hazmat.primitives import serialization
- import markdown
- from bs4 import BeautifulSoup
- from open_webui.constants import ERROR_MESSAGES
- ####################################
- # Load .env file
- ####################################
- # Use .resolve() to get the canonical path, removing any '..' or '.' components
- ENV_FILE_PATH = Path(__file__).resolve()
- # OPEN_WEBUI_DIR should be the directory where env.py resides (open_webui/)
- OPEN_WEBUI_DIR = ENV_FILE_PATH.parent
- # BACKEND_DIR is the parent of OPEN_WEBUI_DIR (backend/)
- BACKEND_DIR = OPEN_WEBUI_DIR.parent
- # BASE_DIR is the parent of BACKEND_DIR (open-webui-dev/)
- BASE_DIR = BACKEND_DIR.parent
- try:
- from dotenv import find_dotenv, load_dotenv
- load_dotenv(find_dotenv(str(BASE_DIR / ".env")))
- except ImportError:
- print("dotenv not installed, skipping...")
- DOCKER = os.environ.get("DOCKER", "False").lower() == "true"
- # 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":
- try:
- import torch
- 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"
- else:
- DEVICE_TYPE = "cpu"
- try:
- import torch
- if torch.backends.mps.is_available() and torch.backends.mps.is_built():
- DEVICE_TYPE = "mps"
- except Exception:
- pass
- ####################################
- # LOGGING
- ####################################
- GLOBAL_LOG_LEVEL = os.environ.get("GLOBAL_LOG_LEVEL", "").upper()
- if GLOBAL_LOG_LEVEL in logging.getLevelNamesMapping():
- 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}")
- if "cuda_error" in locals():
- log.exception(cuda_error)
- del cuda_error
- log_sources = [
- "AUDIO",
- "COMFYUI",
- "CONFIG",
- "DB",
- "IMAGES",
- "MAIN",
- "MODELS",
- "OLLAMA",
- "OPENAI",
- "RAG",
- "WEBHOOK",
- "SOCKET",
- "OAUTH",
- ]
- 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()
- if SRC_LOG_LEVELS[source] not in logging.getLevelNamesMapping():
- 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"
- TRUSTED_SIGNATURE_KEY = os.environ.get("TRUSTED_SIGNATURE_KEY", "")
- ####################################
- # ENV (dev,test,prod)
- ####################################
- ENV = os.environ.get("ENV", "dev")
- FROM_INIT_PY = os.environ.get("FROM_INIT_PY", "False").lower() == "true"
- if FROM_INIT_PY:
- PACKAGE_DATA = {"version": importlib.metadata.version("open-webui")}
- else:
- try:
- PACKAGE_DATA = json.loads((BASE_DIR / "package.json").read_text())
- except Exception:
- PACKAGE_DATA = {"version": "0.0.0"}
- VERSION = PACKAGE_DATA["version"]
- INSTANCE_ID = os.environ.get("INSTANCE_ID", str(uuid4()))
- # 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"
- ####################################
- # ENABLE_FORWARD_USER_INFO_HEADERS
- ####################################
- ENABLE_FORWARD_USER_INFO_HEADERS = (
- os.environ.get("ENABLE_FORWARD_USER_INFO_HEADERS", "False").lower() == "true"
- )
- ####################################
- # 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()
- if FROM_INIT_PY:
- NEW_DATA_DIR = Path(os.getenv("DATA_DIR", OPEN_WEBUI_DIR / "data")).resolve()
- NEW_DATA_DIR.mkdir(parents=True, exist_ok=True)
- # Check if the data directory exists in the package directory
- if DATA_DIR.exists() and DATA_DIR != NEW_DATA_DIR:
- 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)
- # 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)
- DATA_DIR = Path(os.getenv("DATA_DIR", OPEN_WEBUI_DIR / "data"))
- STATIC_DIR = Path(os.getenv("STATIC_DIR", OPEN_WEBUI_DIR / "static"))
- FONTS_DIR = Path(os.getenv("FONTS_DIR", OPEN_WEBUI_DIR / "static" / "fonts"))
- FRONTEND_BUILD_DIR = Path(os.getenv("FRONTEND_BUILD_DIR", BASE_DIR / "build")).resolve()
- if FROM_INIT_PY:
- FRONTEND_BUILD_DIR = Path(
- os.getenv("FRONTEND_BUILD_DIR", OPEN_WEBUI_DIR / "frontend")
- ).resolve()
- ####################################
- # 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")
- 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']}"
- 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"
- # Replace the postgres:// with postgresql://
- if "postgres://" in DATABASE_URL:
- DATABASE_URL = DATABASE_URL.replace("postgres://", "postgresql://")
- DATABASE_SCHEMA = os.environ.get("DATABASE_SCHEMA", None)
- DATABASE_POOL_SIZE = os.environ.get("DATABASE_POOL_SIZE", None)
- if DATABASE_POOL_SIZE != None:
- try:
- DATABASE_POOL_SIZE = int(DATABASE_POOL_SIZE)
- except Exception:
- DATABASE_POOL_SIZE = None
- 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
- DATABASE_ENABLE_SQLITE_WAL = (
- os.environ.get("DATABASE_ENABLE_SQLITE_WAL", "False").lower() == "true"
- )
- DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL = os.environ.get(
- "DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL", None
- )
- if DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL is not None:
- try:
- DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL = float(
- DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL
- )
- except Exception:
- DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL = 0.0
- RESET_CONFIG_ON_START = (
- os.environ.get("RESET_CONFIG_ON_START", "False").lower() == "true"
- )
- ENABLE_REALTIME_CHAT_SAVE = (
- os.environ.get("ENABLE_REALTIME_CHAT_SAVE", "False").lower() == "true"
- )
- ENABLE_QUERIES_CACHE = os.environ.get("ENABLE_QUERIES_CACHE", "False").lower() == "true"
- ####################################
- # REDIS
- ####################################
- REDIS_URL = os.environ.get("REDIS_URL", "")
- REDIS_CLUSTER = os.environ.get("REDIS_CLUSTER", "False").lower() == "true"
- REDIS_KEY_PREFIX = os.environ.get("REDIS_KEY_PREFIX", "open-webui")
- REDIS_SENTINEL_HOSTS = os.environ.get("REDIS_SENTINEL_HOSTS", "")
- REDIS_SENTINEL_PORT = os.environ.get("REDIS_SENTINEL_PORT", "26379")
- # 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
- ####################################
- # UVICORN WORKERS
- ####################################
- # Number of uvicorn worker processes for handling requests
- 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)
- ####################################
- WEBUI_AUTH = os.environ.get("WEBUI_AUTH", "True").lower() == "true"
- ENABLE_INITIAL_ADMIN_SIGNUP = (
- os.environ.get("ENABLE_INITIAL_ADMIN_SIGNUP", "False").lower() == "true"
- )
- ENABLE_SIGNUP_PASSWORD_CONFIRMATION = (
- os.environ.get("ENABLE_SIGNUP_PASSWORD_CONFIRMATION", "False").lower() == "true"
- )
- 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)
- WEBUI_AUTH_TRUSTED_GROUPS_HEADER = os.environ.get(
- "WEBUI_AUTH_TRUSTED_GROUPS_HEADER", None
- )
- BYPASS_MODEL_ACCESS_CONTROL = (
- os.environ.get("BYPASS_MODEL_ACCESS_CONTROL", "False").lower() == "true"
- )
- WEBUI_AUTH_SIGNOUT_REDIRECT_URL = os.environ.get(
- "WEBUI_AUTH_SIGNOUT_REDIRECT_URL", None
- )
- ####################################
- # 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
- )
- WEBUI_SESSION_COOKIE_SAME_SITE = os.environ.get("WEBUI_SESSION_COOKIE_SAME_SITE", "lax")
- WEBUI_SESSION_COOKIE_SECURE = (
- os.environ.get("WEBUI_SESSION_COOKIE_SECURE", "false").lower() == "true"
- )
- WEBUI_AUTH_COOKIE_SAME_SITE = os.environ.get(
- "WEBUI_AUTH_COOKIE_SAME_SITE", WEBUI_SESSION_COOKIE_SAME_SITE
- )
- WEBUI_AUTH_COOKIE_SECURE = (
- os.environ.get(
- "WEBUI_AUTH_COOKIE_SECURE",
- os.environ.get("WEBUI_SESSION_COOKIE_SECURE", "false"),
- ).lower()
- == "true"
- )
- if WEBUI_AUTH and WEBUI_SECRET_KEY == "":
- raise ValueError(ERROR_MESSAGES.ENV_VAR_NOT_FOUND)
- ENABLE_COMPRESSION_MIDDLEWARE = (
- os.environ.get("ENABLE_COMPRESSION_MIDDLEWARE", "True").lower() == "true"
- )
- ####################################
- # OAUTH Configuration
- ####################################
- ENABLE_OAUTH_ID_TOKEN_COOKIE = (
- os.environ.get("ENABLE_OAUTH_ID_TOKEN_COOKIE", "True").lower() == "true"
- )
- OAUTH_CLIENT_INFO_ENCRYPTION_KEY = os.environ.get(
- "OAUTH_CLIENT_INFO_ENCRYPTION_KEY", WEBUI_SECRET_KEY
- )
- OAUTH_SESSION_TOKEN_ENCRYPTION_KEY = os.environ.get(
- "OAUTH_SESSION_TOKEN_ENCRYPTION_KEY", WEBUI_SECRET_KEY
- )
- ####################################
- # SCIM Configuration
- ####################################
- SCIM_ENABLED = os.environ.get("SCIM_ENABLED", "False").lower() == "true"
- SCIM_TOKEN = os.environ.get("SCIM_TOKEN", "")
- ####################################
- # 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"
- )
- )
- ####################################
- # MODELS
- ####################################
- MODELS_CACHE_TTL = os.environ.get("MODELS_CACHE_TTL", "1")
- if MODELS_CACHE_TTL == "":
- MODELS_CACHE_TTL = None
- else:
- try:
- MODELS_CACHE_TTL = int(MODELS_CACHE_TTL)
- except Exception:
- MODELS_CACHE_TTL = 1
- ####################################
- # 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
- CHAT_RESPONSE_MAX_TOOL_CALL_RETRIES = os.environ.get(
- "CHAT_RESPONSE_MAX_TOOL_CALL_RETRIES", "30"
- )
- if CHAT_RESPONSE_MAX_TOOL_CALL_RETRIES == "":
- CHAT_RESPONSE_MAX_TOOL_CALL_RETRIES = 30
- else:
- try:
- CHAT_RESPONSE_MAX_TOOL_CALL_RETRIES = int(CHAT_RESPONSE_MAX_TOOL_CALL_RETRIES)
- except Exception:
- CHAT_RESPONSE_MAX_TOOL_CALL_RETRIES = 30
- ####################################
- # WEBSOCKET SUPPORT
- ####################################
- ENABLE_WEBSOCKET_SUPPORT = (
- os.environ.get("ENABLE_WEBSOCKET_SUPPORT", "True").lower() == "true"
- )
- WEBSOCKET_MANAGER = os.environ.get("WEBSOCKET_MANAGER", "")
- WEBSOCKET_REDIS_URL = os.environ.get("WEBSOCKET_REDIS_URL", REDIS_URL)
- WEBSOCKET_REDIS_CLUSTER = (
- os.environ.get("WEBSOCKET_REDIS_CLUSTER", str(REDIS_CLUSTER)).lower() == "true"
- )
- 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
- WEBSOCKET_SENTINEL_HOSTS = os.environ.get("WEBSOCKET_SENTINEL_HOSTS", "")
- WEBSOCKET_SENTINEL_PORT = os.environ.get("WEBSOCKET_SENTINEL_PORT", "26379")
- 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
- AIOHTTP_CLIENT_SESSION_SSL = (
- os.environ.get("AIOHTTP_CLIENT_SESSION_SSL", "True").lower() == "true"
- )
- AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST = os.environ.get(
- "AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST",
- os.environ.get("AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST", "10"),
- )
- if AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST == "":
- AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST = None
- else:
- try:
- AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST = int(AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST)
- except Exception:
- AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST = 10
- AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA = os.environ.get(
- "AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA", "10"
- )
- 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
- AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL = (
- os.environ.get("AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL", "True").lower() == "true"
- )
- ####################################
- # 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
- ####################################
- # OFFLINE_MODE
- ####################################
- ENABLE_VERSION_UPDATE_CHECK = (
- os.environ.get("ENABLE_VERSION_UPDATE_CHECK", "true").lower() == "true"
- )
- OFFLINE_MODE = os.environ.get("OFFLINE_MODE", "false").lower() == "true"
- if OFFLINE_MODE:
- os.environ["HF_HUB_OFFLINE"] = "1"
- ENABLE_VERSION_UPDATE_CHECK = False
- ####################################
- # 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")
- # 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(",")
- # METADATA | REQUEST | REQUEST_RESPONSE
- AUDIT_LOG_LEVEL = os.getenv("AUDIT_LOG_LEVEL", "NONE").upper()
- 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]
- ####################################
- # OPENTELEMETRY
- ####################################
- ENABLE_OTEL = os.environ.get("ENABLE_OTEL", "False").lower() == "true"
- ENABLE_OTEL_TRACES = os.environ.get("ENABLE_OTEL_TRACES", "False").lower() == "true"
- ENABLE_OTEL_METRICS = os.environ.get("ENABLE_OTEL_METRICS", "False").lower() == "true"
- ENABLE_OTEL_LOGS = os.environ.get("ENABLE_OTEL_LOGS", "False").lower() == "true"
- OTEL_EXPORTER_OTLP_ENDPOINT = os.environ.get(
- "OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4317"
- )
- OTEL_METRICS_EXPORTER_OTLP_ENDPOINT = os.environ.get(
- "OTEL_METRICS_EXPORTER_OTLP_ENDPOINT", OTEL_EXPORTER_OTLP_ENDPOINT
- )
- OTEL_LOGS_EXPORTER_OTLP_ENDPOINT = os.environ.get(
- "OTEL_LOGS_EXPORTER_OTLP_ENDPOINT", OTEL_EXPORTER_OTLP_ENDPOINT
- )
- OTEL_EXPORTER_OTLP_INSECURE = (
- os.environ.get("OTEL_EXPORTER_OTLP_INSECURE", "False").lower() == "true"
- )
- OTEL_METRICS_EXPORTER_OTLP_INSECURE = (
- os.environ.get(
- "OTEL_METRICS_EXPORTER_OTLP_INSECURE", str(OTEL_EXPORTER_OTLP_INSECURE)
- ).lower()
- == "true"
- )
- OTEL_LOGS_EXPORTER_OTLP_INSECURE = (
- os.environ.get(
- "OTEL_LOGS_EXPORTER_OTLP_INSECURE", str(OTEL_EXPORTER_OTLP_INSECURE)
- ).lower()
- == "true"
- )
- 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()
- OTEL_BASIC_AUTH_USERNAME = os.environ.get("OTEL_BASIC_AUTH_USERNAME", "")
- OTEL_BASIC_AUTH_PASSWORD = os.environ.get("OTEL_BASIC_AUTH_PASSWORD", "")
- 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
- )
- 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
- )
- OTEL_OTLP_SPAN_EXPORTER = os.environ.get(
- "OTEL_OTLP_SPAN_EXPORTER", "grpc"
- ).lower() # grpc or http
- OTEL_METRICS_OTLP_SPAN_EXPORTER = os.environ.get(
- "OTEL_METRICS_OTLP_SPAN_EXPORTER", OTEL_OTLP_SPAN_EXPORTER
- ).lower() # grpc or http
- OTEL_LOGS_OTLP_SPAN_EXPORTER = os.environ.get(
- "OTEL_LOGS_OTLP_SPAN_EXPORTER", OTEL_OTLP_SPAN_EXPORTER
- ).lower() # grpc or http
- ####################################
- # TOOLS/FUNCTIONS PIP OPTIONS
- ####################################
- PIP_OPTIONS = os.getenv("PIP_OPTIONS", "").split()
- PIP_PACKAGE_INDEX_OPTIONS = os.getenv("PIP_PACKAGE_INDEX_OPTIONS", "").split()
- ####################################
- # PROGRESSIVE WEB APP OPTIONS
- ####################################
- EXTERNAL_PWA_MANIFEST_URL = os.environ.get("EXTERNAL_PWA_MANIFEST_URL")
|