open-webui/backend/open_webui/main.py

2020 lines
68 KiB
Python
Raw Normal View History

2024-10-16 22:32:57 +08:00
import asyncio
2024-08-28 06:10:27 +08:00
import inspect
2024-02-23 16:30:26 +08:00
import json
import logging
import mimetypes
2024-08-28 06:10:27 +08:00
import os
2024-06-06 04:57:48 +08:00
import shutil
2024-08-28 06:10:27 +08:00
import sys
import time
2024-10-22 18:16:48 +08:00
import random
2025-06-09 00:58:31 +08:00
from uuid import uuid4
2024-12-12 10:36:59 +08:00
2024-08-28 06:10:27 +08:00
from contextlib import asynccontextmanager
2024-12-10 16:54:13 +08:00
from urllib.parse import urlencode, parse_qs, urlparse
from pydantic import BaseModel
from sqlalchemy import text
2024-02-23 16:30:26 +08:00
2024-12-10 16:54:13 +08:00
from typing import Optional
2024-11-16 20:41:07 +08:00
from aiocache import cached
2024-08-28 06:10:27 +08:00
import aiohttp
2025-04-18 21:30:34 +08:00
import anyio.to_thread
2024-08-28 06:10:27 +08:00
import requests
from redis import Redis
2024-12-18 05:52:57 +08:00
2024-10-16 22:58:03 +08:00
from fastapi import (
Depends,
FastAPI,
File,
Form,
HTTPException,
Request,
UploadFile,
status,
2024-12-18 05:51:29 +08:00
applications,
2024-12-19 17:00:32 +08:00
BackgroundTasks,
2024-10-16 22:58:03 +08:00
)
2024-12-17 02:00:51 +08:00
from fastapi.openapi.docs import get_swagger_ui_html
2024-12-18 05:52:57 +08:00
2024-10-16 22:58:03 +08:00
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse, JSONResponse, RedirectResponse
2024-10-16 22:58:03 +08:00
from fastapi.staticfiles import StaticFiles
2024-12-10 16:54:13 +08:00
from starlette_compress import CompressMiddleware
2024-10-16 22:58:03 +08:00
from starlette.exceptions import HTTPException as StarletteHTTPException
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.middleware.sessions import SessionMiddleware
from starlette.responses import Response, StreamingResponse
2025-06-28 19:12:31 +08:00
from starlette.datastructures import Headers
2024-12-10 16:54:13 +08:00
from open_webui.utils import logger
from open_webui.utils.audit import AuditLevel, AuditLoggingMiddleware
from open_webui.utils.logger import start_logger
2024-12-12 10:46:29 +08:00
from open_webui.socket.main import (
app as socket_app,
periodic_usage_pool_cleanup,
2025-08-19 05:24:53 +08:00
get_event_emitter,
2025-06-16 14:42:34 +08:00
get_models_in_use,
get_active_user_ids,
)
2024-12-10 16:54:13 +08:00
from open_webui.routers import (
audio,
images,
ollama,
openai,
retrieval,
pipelines,
tasks,
2024-12-11 18:41:25 +08:00
auths,
2024-12-22 18:42:19 +08:00
channels,
2024-12-11 18:41:25 +08:00
chats,
2025-05-03 22:16:32 +08:00
notes,
2024-12-11 18:41:25 +08:00
folders,
configs,
groups,
files,
functions,
memories,
models,
knowledge,
prompts,
evaluations,
tools,
users,
utils,
scim,
)
2024-12-12 12:39:55 +08:00
2024-12-12 10:08:55 +08:00
from open_webui.routers.retrieval import (
get_embedding_function,
get_reranking_function,
2024-12-12 10:46:29 +08:00
get_ef,
get_rf,
2024-12-12 10:08:55 +08:00
)
2024-12-10 16:54:13 +08:00
from open_webui.internal.db import Session, engine
2024-12-10 16:54:13 +08:00
from open_webui.models.functions import Functions
from open_webui.models.models import Models
from open_webui.models.users import UserModel, Users
2025-03-28 15:52:13 +08:00
from open_webui.models.chats import Chats
2024-12-10 16:54:13 +08:00
from open_webui.config import (
2024-12-10 16:54:13 +08:00
# Ollama
2024-08-28 06:10:27 +08:00
ENABLE_OLLAMA_API,
2024-12-10 16:54:13 +08:00
OLLAMA_BASE_URLS,
OLLAMA_API_CONFIGS,
# OpenAI
2024-08-28 06:10:27 +08:00
ENABLE_OPENAI_API,
2025-02-24 22:14:10 +08:00
ONEDRIVE_CLIENT_ID,
2025-04-14 23:27:59 +08:00
ONEDRIVE_SHAREPOINT_URL,
ONEDRIVE_SHAREPOINT_TENANT_ID,
2024-12-10 16:54:13 +08:00
OPENAI_API_BASE_URLS,
OPENAI_API_KEYS,
OPENAI_API_CONFIGS,
2025-02-12 15:12:00 +08:00
# Direct Connections
ENABLE_DIRECT_CONNECTIONS,
2025-06-28 19:12:31 +08:00
# Model list
ENABLE_BASE_MODELS_CACHE,
# Thread pool size for FastAPI/AnyIO
THREAD_POOL_SIZE,
2025-04-05 18:05:52 +08:00
# Tool Server Configs
TOOL_SERVER_CONNECTIONS,
2025-02-18 08:25:50 +08:00
# Code Execution
ENABLE_CODE_EXECUTION,
2025-02-18 08:25:50 +08:00
CODE_EXECUTION_ENGINE,
CODE_EXECUTION_JUPYTER_URL,
CODE_EXECUTION_JUPYTER_AUTH,
CODE_EXECUTION_JUPYTER_AUTH_TOKEN,
CODE_EXECUTION_JUPYTER_AUTH_PASSWORD,
CODE_EXECUTION_JUPYTER_TIMEOUT,
2025-02-10 18:25:02 +08:00
ENABLE_CODE_INTERPRETER,
CODE_INTERPRETER_ENGINE,
2025-02-12 13:36:16 +08:00
CODE_INTERPRETER_PROMPT_TEMPLATE,
2025-02-10 18:25:02 +08:00
CODE_INTERPRETER_JUPYTER_URL,
CODE_INTERPRETER_JUPYTER_AUTH,
CODE_INTERPRETER_JUPYTER_AUTH_TOKEN,
CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD,
CODE_INTERPRETER_JUPYTER_TIMEOUT,
2024-12-10 16:54:13 +08:00
# Image
AUTOMATIC1111_API_AUTH,
AUTOMATIC1111_BASE_URL,
AUTOMATIC1111_CFG_SCALE,
AUTOMATIC1111_SAMPLER,
AUTOMATIC1111_SCHEDULER,
COMFYUI_BASE_URL,
2024-12-17 15:29:00 +08:00
COMFYUI_API_KEY,
2024-12-10 16:54:13 +08:00
COMFYUI_WORKFLOW,
COMFYUI_WORKFLOW_NODES,
ENABLE_IMAGE_GENERATION,
2025-01-16 16:13:02 +08:00
ENABLE_IMAGE_PROMPT_GENERATION,
2024-12-10 16:54:13 +08:00
IMAGE_GENERATION_ENGINE,
IMAGE_GENERATION_MODEL,
IMAGE_SIZE,
IMAGE_STEPS,
IMAGES_OPENAI_API_BASE_URL,
IMAGES_OPENAI_API_VERSION,
2024-12-10 16:54:13 +08:00
IMAGES_OPENAI_API_KEY,
IMAGES_GEMINI_API_BASE_URL,
IMAGES_GEMINI_API_KEY,
2024-12-10 16:54:13 +08:00
# Audio
AUDIO_STT_ENGINE,
AUDIO_STT_MODEL,
AUDIO_STT_SUPPORTED_CONTENT_TYPES,
2024-12-10 16:54:13 +08:00
AUDIO_STT_OPENAI_API_BASE_URL,
AUDIO_STT_OPENAI_API_KEY,
AUDIO_STT_AZURE_API_KEY,
AUDIO_STT_AZURE_REGION,
AUDIO_STT_AZURE_LOCALES,
AUDIO_STT_AZURE_BASE_URL,
2025-05-01 20:39:36 +08:00
AUDIO_STT_AZURE_MAX_SPEAKERS,
2024-12-10 16:54:13 +08:00
AUDIO_TTS_API_KEY,
AUDIO_TTS_ENGINE,
AUDIO_TTS_MODEL,
AUDIO_TTS_OPENAI_API_BASE_URL,
AUDIO_TTS_OPENAI_API_KEY,
AUDIO_TTS_SPLIT_ON,
AUDIO_TTS_VOICE,
AUDIO_TTS_AZURE_SPEECH_REGION,
2025-05-06 10:08:48 +08:00
AUDIO_TTS_AZURE_SPEECH_BASE_URL,
2024-12-10 16:54:13 +08:00
AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT,
2025-04-13 07:33:36 +08:00
PLAYWRIGHT_WS_URL,
2025-03-21 05:01:47 +08:00
PLAYWRIGHT_TIMEOUT,
FIRECRAWL_API_BASE_URL,
FIRECRAWL_API_KEY,
2025-04-13 07:33:36 +08:00
WEB_LOADER_ENGINE,
WEB_LOADER_CONCURRENT_REQUESTS,
2024-12-10 16:54:13 +08:00
WHISPER_MODEL,
2025-04-14 14:39:38 +08:00
WHISPER_VAD_FILTER,
WHISPER_LANGUAGE,
2025-02-02 21:58:59 +08:00
DEEPGRAM_API_KEY,
2024-12-10 16:54:13 +08:00
WHISPER_MODEL_AUTO_UPDATE,
WHISPER_MODEL_DIR,
2024-12-11 18:41:25 +08:00
# Retrieval
RAG_TEMPLATE,
DEFAULT_RAG_TEMPLATE,
2025-02-19 13:14:58 +08:00
RAG_FULL_CONTEXT,
2025-02-27 07:42:19 +08:00
BYPASS_EMBEDDING_AND_RETRIEVAL,
2024-12-11 18:41:25 +08:00
RAG_EMBEDDING_MODEL,
RAG_EMBEDDING_MODEL_AUTO_UPDATE,
RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE,
RAG_RERANKING_ENGINE,
2024-12-11 18:41:25 +08:00
RAG_RERANKING_MODEL,
RAG_EXTERNAL_RERANKER_URL,
RAG_EXTERNAL_RERANKER_API_KEY,
2024-12-11 18:41:25 +08:00
RAG_RERANKING_MODEL_AUTO_UPDATE,
RAG_RERANKING_MODEL_TRUST_REMOTE_CODE,
RAG_EMBEDDING_ENGINE,
RAG_EMBEDDING_BATCH_SIZE,
RAG_TOP_K,
RAG_TOP_K_RERANKER,
2024-12-11 18:41:25 +08:00
RAG_RELEVANCE_THRESHOLD,
RAG_HYBRID_BM25_WEIGHT,
2025-05-15 03:06:33 +08:00
RAG_ALLOWED_FILE_EXTENSIONS,
2024-12-11 18:41:25 +08:00
RAG_FILE_MAX_COUNT,
RAG_FILE_MAX_SIZE,
2025-06-16 20:52:57 +08:00
FILE_IMAGE_COMPRESSION_WIDTH,
FILE_IMAGE_COMPRESSION_HEIGHT,
2024-12-11 18:41:25 +08:00
RAG_OPENAI_API_BASE_URL,
RAG_OPENAI_API_KEY,
2025-05-20 10:58:04 +08:00
RAG_AZURE_OPENAI_BASE_URL,
RAG_AZURE_OPENAI_API_KEY,
RAG_AZURE_OPENAI_API_VERSION,
2024-12-11 18:41:25 +08:00
RAG_OLLAMA_BASE_URL,
RAG_OLLAMA_API_KEY,
CHUNK_OVERLAP,
CHUNK_SIZE,
CONTENT_EXTRACTION_ENGINE,
DATALAB_MARKER_API_KEY,
2025-07-23 08:49:28 +08:00
DATALAB_MARKER_API_BASE_URL,
DATALAB_MARKER_ADDITIONAL_CONFIG,
DATALAB_MARKER_SKIP_CACHE,
DATALAB_MARKER_FORCE_OCR,
DATALAB_MARKER_PAGINATE,
DATALAB_MARKER_STRIP_EXISTING_OCR,
DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION,
2025-07-23 09:06:29 +08:00
DATALAB_MARKER_FORMAT_LINES,
DATALAB_MARKER_OUTPUT_FORMAT,
DATALAB_MARKER_USE_LLM,
2025-05-15 02:28:40 +08:00
EXTERNAL_DOCUMENT_LOADER_URL,
EXTERNAL_DOCUMENT_LOADER_API_KEY,
2024-12-11 18:41:25 +08:00
TIKA_SERVER_URL,
DOCLING_SERVER_URL,
DOCLING_DO_OCR,
DOCLING_FORCE_OCR,
DOCLING_OCR_ENGINE,
DOCLING_OCR_LANG,
DOCLING_PDF_BACKEND,
DOCLING_TABLE_MODE,
DOCLING_PIPELINE,
DOCLING_DO_PICTURE_DESCRIPTION,
DOCLING_PICTURE_DESCRIPTION_MODE,
2025-06-09 00:02:14 +08:00
DOCLING_PICTURE_DESCRIPTION_LOCAL,
DOCLING_PICTURE_DESCRIPTION_API,
DOCUMENT_INTELLIGENCE_ENDPOINT,
DOCUMENT_INTELLIGENCE_KEY,
MISTRAL_OCR_API_KEY,
2024-12-11 18:41:25 +08:00
RAG_TEXT_SPLITTER,
TIKTOKEN_ENCODING_NAME,
PDF_EXTRACT_IMAGES,
YOUTUBE_LOADER_LANGUAGE,
YOUTUBE_LOADER_PROXY_URL,
# Retrieval (Web Search)
2025-04-13 07:33:36 +08:00
ENABLE_WEB_SEARCH,
WEB_SEARCH_ENGINE,
2025-02-27 07:42:19 +08:00
BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL,
BYPASS_WEB_SEARCH_WEB_LOADER,
2025-04-13 07:33:36 +08:00
WEB_SEARCH_RESULT_COUNT,
WEB_SEARCH_CONCURRENT_REQUESTS,
WEB_SEARCH_TRUST_ENV,
WEB_SEARCH_DOMAIN_FILTER_LIST,
2024-12-11 18:41:25 +08:00
JINA_API_KEY,
SEARCHAPI_API_KEY,
SEARCHAPI_ENGINE,
2025-02-14 12:24:58 +08:00
SERPAPI_API_KEY,
SERPAPI_ENGINE,
2024-12-11 18:41:25 +08:00
SEARXNG_QUERY_URL,
YACY_QUERY_URL,
YACY_USERNAME,
YACY_PASSWORD,
2024-12-11 18:41:25 +08:00
SERPER_API_KEY,
SERPLY_API_KEY,
SERPSTACK_API_KEY,
SERPSTACK_HTTPS,
TAVILY_API_KEY,
TAVILY_EXTRACT_DEPTH,
2024-12-11 18:41:25 +08:00
BING_SEARCH_V7_ENDPOINT,
BING_SEARCH_V7_SUBSCRIPTION_KEY,
BRAVE_SEARCH_API_KEY,
EXA_API_KEY,
PERPLEXITY_API_KEY,
PERPLEXITY_MODEL,
PERPLEXITY_SEARCH_CONTEXT_USAGE,
SOUGOU_API_SID,
SOUGOU_API_SK,
2024-12-11 18:41:25 +08:00
KAGI_SEARCH_API_KEY,
MOJEEK_SEARCH_API_KEY,
2025-02-10 16:44:47 +08:00
BOCHA_SEARCH_API_KEY,
2024-12-11 18:41:25 +08:00
GOOGLE_PSE_API_KEY,
GOOGLE_PSE_ENGINE_ID,
2024-12-19 01:04:55 +08:00
GOOGLE_DRIVE_CLIENT_ID,
GOOGLE_DRIVE_API_KEY,
2025-02-24 22:14:10 +08:00
ONEDRIVE_CLIENT_ID,
2025-04-14 23:27:59 +08:00
ONEDRIVE_SHAREPOINT_URL,
ONEDRIVE_SHAREPOINT_TENANT_ID,
2024-12-11 18:41:25 +08:00
ENABLE_RAG_HYBRID_SEARCH,
ENABLE_RAG_LOCAL_WEB_FETCH,
2025-04-13 07:33:36 +08:00
ENABLE_WEB_LOADER_SSL_VERIFICATION,
2024-12-19 10:04:56 +08:00
ENABLE_GOOGLE_DRIVE_INTEGRATION,
2025-02-24 22:14:10 +08:00
ENABLE_ONEDRIVE_INTEGRATION,
2024-12-11 18:41:25 +08:00
UPLOAD_DIR,
EXTERNAL_WEB_SEARCH_URL,
EXTERNAL_WEB_SEARCH_API_KEY,
EXTERNAL_WEB_LOADER_URL,
EXTERNAL_WEB_LOADER_API_KEY,
2024-12-10 16:54:13 +08:00
# WebUI
WEBUI_AUTH,
WEBUI_NAME,
WEBUI_BANNERS,
WEBHOOK_URL,
ADMIN_EMAIL,
SHOW_ADMIN_DETAILS,
JWT_EXPIRES_IN,
ENABLE_SIGNUP,
ENABLE_LOGIN_FORM,
ENABLE_API_KEY,
ENABLE_API_KEY_ENDPOINT_RESTRICTIONS,
API_KEY_ALLOWED_ENDPOINTS,
2024-12-23 12:02:14 +08:00
ENABLE_CHANNELS,
2025-05-01 20:39:36 +08:00
ENABLE_NOTES,
2024-12-10 16:54:13 +08:00
ENABLE_COMMUNITY_SHARING,
ENABLE_MESSAGE_RATING,
2025-03-31 12:31:16 +08:00
ENABLE_USER_WEBHOOKS,
2024-12-10 16:54:13 +08:00
ENABLE_EVALUATION_ARENA_MODELS,
BYPASS_ADMIN_ACCESS_CONTROL,
2024-12-10 16:54:13 +08:00
USER_PERMISSIONS,
DEFAULT_USER_ROLE,
2025-05-15 01:39:17 +08:00
PENDING_USER_OVERLAY_CONTENT,
PENDING_USER_OVERLAY_TITLE,
2024-12-10 16:54:13 +08:00
DEFAULT_PROMPT_SUGGESTIONS,
DEFAULT_MODELS,
DEFAULT_ARENA_MODEL,
MODEL_ORDER_LIST,
EVALUATION_ARENA_MODELS,
# WebUI (OAuth)
ENABLE_OAUTH_ROLE_MANAGEMENT,
OAUTH_ROLES_CLAIM,
OAUTH_EMAIL_CLAIM,
OAUTH_PICTURE_CLAIM,
OAUTH_USERNAME_CLAIM,
OAUTH_ALLOWED_ROLES,
OAUTH_ADMIN_ROLES,
# WebUI (LDAP)
ENABLE_LDAP,
LDAP_SERVER_LABEL,
LDAP_SERVER_HOST,
LDAP_SERVER_PORT,
LDAP_ATTRIBUTE_FOR_MAIL,
2024-12-10 16:54:13 +08:00
LDAP_ATTRIBUTE_FOR_USERNAME,
LDAP_SEARCH_FILTERS,
LDAP_SEARCH_BASE,
LDAP_APP_DN,
LDAP_APP_PASSWORD,
LDAP_USE_TLS,
LDAP_CA_CERT_FILE,
LDAP_VALIDATE_CERT,
2024-12-10 16:54:13 +08:00
LDAP_CIPHERS,
# LDAP Group Management
ENABLE_LDAP_GROUP_MANAGEMENT,
ENABLE_LDAP_GROUP_CREATION,
LDAP_ATTRIBUTE_FOR_GROUPS,
2024-12-10 16:54:13 +08:00
# Misc
2024-08-28 06:10:27 +08:00
ENV,
2024-12-10 16:54:13 +08:00
CACHE_DIR,
STATIC_DIR,
2024-08-28 06:10:27 +08:00
FRONTEND_BUILD_DIR,
2024-12-10 16:54:13 +08:00
CORS_ALLOW_ORIGIN,
DEFAULT_LOCALE,
2024-08-28 06:10:27 +08:00
OAUTH_PROVIDERS,
2024-12-26 00:50:57 +08:00
WEBUI_URL,
2025-05-15 03:53:28 +08:00
RESPONSE_WATERMARK,
2024-12-10 16:54:13 +08:00
# Admin
ENABLE_ADMIN_CHAT_ACCESS,
BYPASS_ADMIN_ACCESS_CONTROL,
2024-12-10 16:54:13 +08:00
ENABLE_ADMIN_EXPORT,
# Tasks
2024-06-10 05:53:10 +08:00
TASK_MODEL,
TASK_MODEL_EXTERNAL,
2024-12-10 16:54:13 +08:00
ENABLE_TAGS_GENERATION,
ENABLE_TITLE_GENERATION,
2025-06-03 22:07:29 +08:00
ENABLE_FOLLOW_UP_GENERATION,
2024-11-19 18:24:32 +08:00
ENABLE_SEARCH_QUERY_GENERATION,
ENABLE_RETRIEVAL_QUERY_GENERATION,
2024-12-10 16:54:13 +08:00
ENABLE_AUTOCOMPLETE_GENERATION,
2024-06-10 05:25:31 +08:00
TITLE_GENERATION_PROMPT_TEMPLATE,
2025-06-03 22:07:29 +08:00
FOLLOW_UP_GENERATION_PROMPT_TEMPLATE,
TAGS_GENERATION_PROMPT_TEMPLATE,
2025-01-16 16:06:37 +08:00
IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE,
2024-06-11 14:40:27 +08:00
TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE,
2024-12-10 16:54:13 +08:00
QUERY_GENERATION_PROMPT_TEMPLATE,
AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE,
AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH,
2024-08-28 06:10:27 +08:00
AppConfig,
2024-09-25 07:06:11 +08:00
reset_config,
2024-08-28 06:10:27 +08:00
)
from open_webui.env import (
2025-07-30 03:45:25 +08:00
LICENSE_KEY,
AUDIT_EXCLUDED_PATHS,
AUDIT_LOG_LEVEL,
2024-08-28 06:10:27 +08:00
CHANGELOG,
2025-03-09 01:59:15 +08:00
REDIS_URL,
2025-08-04 18:15:08 +08:00
REDIS_CLUSTER,
REDIS_KEY_PREFIX,
2025-03-27 15:51:55 +08:00
REDIS_SENTINEL_HOSTS,
REDIS_SENTINEL_PORT,
2024-08-28 06:10:27 +08:00
GLOBAL_LOG_LEVEL,
MAX_BODY_LOG_SIZE,
2024-06-24 10:28:33 +08:00
SAFE_MODE,
2024-08-28 06:10:27 +08:00
SRC_LOG_LEVELS,
VERSION,
2025-06-09 01:21:51 +08:00
INSTANCE_ID,
2024-08-28 06:10:27 +08:00
WEBUI_BUILD_HASH,
WEBUI_SECRET_KEY,
WEBUI_SESSION_COOKIE_SAME_SITE,
2024-06-07 16:13:42 +08:00
WEBUI_SESSION_COOKIE_SECURE,
2025-07-31 20:43:37 +08:00
ENABLE_SIGNUP_PASSWORD_CONFIRMATION,
2024-12-10 16:54:13 +08:00
WEBUI_AUTH_TRUSTED_EMAIL_HEADER,
WEBUI_AUTH_TRUSTED_NAME_HEADER,
2025-04-19 14:58:37 +08:00
WEBUI_AUTH_SIGNOUT_REDIRECT_URL,
2025-08-06 18:25:42 +08:00
# SCIM
SCIM_ENABLED,
SCIM_TOKEN,
ENABLE_COMPRESSION_MIDDLEWARE,
ENABLE_WEBSOCKET_SUPPORT,
2024-12-02 10:25:44 +08:00
BYPASS_MODEL_ACCESS_CONTROL,
2024-09-25 07:06:11 +08:00
RESET_CONFIG_ON_START,
ENABLE_VERSION_UPDATE_CHECK,
2025-03-12 02:55:30 +08:00
ENABLE_OTEL,
2025-04-11 01:35:43 +08:00
EXTERNAL_PWA_MANIFEST_URL,
2025-05-15 03:33:52 +08:00
AIOHTTP_CLIENT_SESSION_SSL,
2024-08-28 06:10:27 +08:00
)
2024-12-10 16:54:13 +08:00
2024-12-13 12:22:17 +08:00
2024-12-13 14:28:42 +08:00
from open_webui.utils.models import (
get_all_models,
get_all_base_models,
check_model_access,
2024-10-16 22:32:57 +08:00
)
2024-12-13 12:22:17 +08:00
from open_webui.utils.chat import (
generate_chat_completion as chat_completion_handler,
chat_completed as chat_completed_handler,
chat_action as chat_action_handler,
2024-08-28 06:10:27 +08:00
)
2025-06-04 22:13:53 +08:00
from open_webui.utils.embeddings import generate_embeddings
2024-12-13 14:28:42 +08:00
from open_webui.utils.middleware import process_chat_payload, process_chat_response
2024-12-10 16:54:13 +08:00
from open_webui.utils.access_control import has_access
2024-12-09 08:01:56 +08:00
from open_webui.utils.auth import (
2025-02-17 10:35:09 +08:00
get_license_data,
2025-04-05 18:05:52 +08:00
get_http_authorization_cred,
2024-08-28 06:10:27 +08:00
decode_token,
get_admin_user,
get_verified_user,
2024-03-10 13:47:01 +08:00
)
2025-04-30 20:01:23 +08:00
from open_webui.utils.plugin import install_tool_and_function_dependencies
2025-02-16 16:11:18 +08:00
from open_webui.utils.oauth import OAuthManager
2024-12-10 16:54:13 +08:00
from open_webui.utils.security_headers import SecurityHeadersMiddleware
2025-06-09 00:58:31 +08:00
from open_webui.utils.redis import get_redis_connection
2024-12-10 16:54:13 +08:00
2025-04-13 11:51:02 +08:00
from open_webui.tasks import (
redis_task_command_listener,
2025-07-11 22:14:48 +08:00
list_task_ids_by_item_id,
2025-08-19 05:24:53 +08:00
create_task,
2025-04-13 11:51:02 +08:00
stop_task,
list_tasks,
) # Import from tasks.py
2025-03-18 16:28:47 +08:00
from open_webui.utils.redis import get_sentinels_from_env
2025-08-10 01:10:12 +08:00
from open_webui.constants import ERROR_MESSAGES
2024-06-24 10:28:33 +08:00
if SAFE_MODE:
print("SAFE MODE ENABLED")
Functions.deactivate_all_functions()
logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL)
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MAIN"])
2023-11-15 08:28:51 +08:00
2024-03-28 17:45:56 +08:00
2023-11-15 08:28:51 +08:00
class SPAStaticFiles(StaticFiles):
async def get_response(self, path: str, scope):
try:
return await super().get_response(path, scope)
except (HTTPException, StarletteHTTPException) as ex:
if ex.status_code == 404:
2025-02-11 21:21:27 +08:00
if path.endswith(".js"):
# Return 404 for javascript files
2025-02-11 18:49:36 +08:00
raise ex
2025-02-11 21:21:27 +08:00
else:
return await super().get_response("index.html", scope)
2023-11-15 08:28:51 +08:00
else:
raise ex
2024-04-02 18:03:55 +08:00
print(
2024-05-04 05:23:38 +08:00
rf"""
2024-04-02 18:03:55 +08:00
2025-05-07 00:15:09 +08:00
v{VERSION} - building the best AI user interface.
2024-05-26 15:49:30 +08:00
{f"Commit: {WEBUI_BUILD_HASH}" if WEBUI_BUILD_HASH != "dev-build" else ""}
2024-04-02 18:03:55 +08:00
https://github.com/open-webui/open-webui
"""
)
2023-11-15 08:28:51 +08:00
@asynccontextmanager
async def lifespan(app: FastAPI):
2025-06-09 01:21:51 +08:00
app.state.instance_id = INSTANCE_ID
start_logger()
2025-06-09 00:58:31 +08:00
2024-09-25 07:06:11 +08:00
if RESET_CONFIG_ON_START:
reset_config()
2025-03-04 16:32:27 +08:00
if LICENSE_KEY:
get_license_data(app, LICENSE_KEY)
2025-02-16 16:11:18 +08:00
2025-04-30 20:01:23 +08:00
# This should be blocking (sync) so functions are not deactivated on first /get_models calls
# when the first user lands on the / route.
log.info("Installing external dependencies of functions and tools...")
install_tool_and_function_dependencies()
2025-06-09 00:58:31 +08:00
app.state.redis = get_redis_connection(
redis_url=REDIS_URL,
redis_sentinels=get_sentinels_from_env(
REDIS_SENTINEL_HOSTS, REDIS_SENTINEL_PORT
),
2025-08-04 18:15:08 +08:00
redis_cluster=REDIS_CLUSTER,
2025-06-09 19:37:05 +08:00
async_mode=True,
2025-06-09 00:58:31 +08:00
)
2025-06-09 21:21:10 +08:00
if app.state.redis is not None:
app.state.redis_task_command_listener = asyncio.create_task(
redis_task_command_listener(app)
)
2025-05-09 00:47:41 +08:00
if THREAD_POOL_SIZE and THREAD_POOL_SIZE > 0:
2025-04-18 21:30:34 +08:00
limiter = anyio.to_thread.current_default_thread_limiter()
2025-05-09 00:47:41 +08:00
limiter.total_tokens = THREAD_POOL_SIZE
2024-09-24 23:43:43 +08:00
asyncio.create_task(periodic_usage_pool_cleanup())
if app.state.config.ENABLE_BASE_MODELS_CACHE:
2025-06-28 19:13:21 +08:00
await get_all_models(
2025-06-28 19:12:31 +08:00
Request(
# Creating a mock request object to pass to get_all_models
{
"type": "http",
"asgi.version": "3.0",
"asgi.spec_version": "2.0",
"method": "GET",
"path": "/internal",
"query_string": b"",
"headers": Headers({}).raw,
"client": ("127.0.0.1", 12345),
"server": ("127.0.0.1", 80),
"scheme": "http",
"app": app,
}
),
None,
)
yield
if hasattr(app.state, "redis_task_command_listener"):
app.state.redis_task_command_listener.cancel()
app = FastAPI(
title="Open WebUI",
2024-11-13 19:09:46 +08:00
docs_url="/docs" if ENV == "dev" else None,
openapi_url="/openapi.json" if ENV == "dev" else None,
redoc_url=None,
lifespan=lifespan,
)
2023-11-15 08:28:51 +08:00
2025-02-16 16:11:18 +08:00
oauth_manager = OAuthManager(app)
app.state.oauth_manager = oauth_manager
2025-02-16 16:11:18 +08:00
2025-06-09 00:58:31 +08:00
app.state.instance_id = None
2025-03-28 15:52:13 +08:00
app.state.config = AppConfig(
redis_url=REDIS_URL,
redis_sentinels=get_sentinels_from_env(REDIS_SENTINEL_HOSTS, REDIS_SENTINEL_PORT),
2025-08-04 18:15:08 +08:00
redis_cluster=REDIS_CLUSTER,
redis_key_prefix=REDIS_KEY_PREFIX,
2025-03-28 15:52:13 +08:00
)
2025-06-09 00:58:31 +08:00
app.state.redis = None
2024-05-24 16:40:48 +08:00
2025-02-16 16:11:18 +08:00
app.state.WEBUI_NAME = WEBUI_NAME
2025-03-04 17:16:08 +08:00
app.state.LICENSE_METADATA = None
2024-05-17 11:49:28 +08:00
2025-03-10 22:27:31 +08:00
########################################
#
# OPENTELEMETRY
#
########################################
2025-03-12 04:12:28 +08:00
if ENABLE_OTEL:
2025-03-12 03:30:09 +08:00
from open_webui.utils.telemetry.setup import setup as setup_opentelemetry
2025-03-12 02:55:30 +08:00
setup_opentelemetry(app=app, db_engine=engine)
2025-03-10 22:27:31 +08:00
2024-12-10 16:54:13 +08:00
########################################
2024-06-20 16:51:39 +08:00
#
2024-12-10 16:54:13 +08:00
# OLLAMA
2024-06-20 16:51:39 +08:00
#
2024-12-10 16:54:13 +08:00
########################################
2024-09-29 01:51:28 +08:00
2024-10-08 09:19:13 +08:00
2024-05-24 16:40:48 +08:00
app.state.config.ENABLE_OLLAMA_API = ENABLE_OLLAMA_API
2024-12-10 16:54:13 +08:00
app.state.config.OLLAMA_BASE_URLS = OLLAMA_BASE_URLS
app.state.config.OLLAMA_API_CONFIGS = OLLAMA_API_CONFIGS
2024-07-12 09:41:00 +08:00
2024-12-11 19:38:45 +08:00
app.state.OLLAMA_MODELS = {}
2024-07-12 09:41:00 +08:00
2024-12-10 16:54:13 +08:00
########################################
2024-06-20 16:51:39 +08:00
#
2024-12-10 16:54:13 +08:00
# OPENAI
2024-06-20 16:51:39 +08:00
#
2024-12-10 16:54:13 +08:00
########################################
2024-06-10 05:53:10 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.ENABLE_OPENAI_API = ENABLE_OPENAI_API
app.state.config.OPENAI_API_BASE_URLS = OPENAI_API_BASE_URLS
app.state.config.OPENAI_API_KEYS = OPENAI_API_KEYS
app.state.config.OPENAI_API_CONFIGS = OPENAI_API_CONFIGS
2024-10-20 11:34:17 +08:00
2024-12-11 19:38:45 +08:00
app.state.OPENAI_MODELS = {}
2024-06-13 04:34:34 +08:00
2025-04-05 18:05:52 +08:00
########################################
#
# TOOL SERVERS
#
########################################
app.state.config.TOOL_SERVER_CONNECTIONS = TOOL_SERVER_CONNECTIONS
app.state.TOOL_SERVERS = []
2025-02-12 14:29:45 +08:00
########################################
#
2025-02-12 15:12:00 +08:00
# DIRECT CONNECTIONS
2025-02-12 14:29:45 +08:00
#
########################################
2025-02-12 15:12:00 +08:00
app.state.config.ENABLE_DIRECT_CONNECTIONS = ENABLE_DIRECT_CONNECTIONS
2025-02-12 14:29:45 +08:00
########################################
#
# SCIM
#
########################################
2025-08-06 18:27:07 +08:00
app.state.SCIM_ENABLED = SCIM_ENABLED
app.state.SCIM_TOKEN = SCIM_TOKEN
2025-06-28 19:12:31 +08:00
########################################
#
# MODELS
2025-06-28 19:12:31 +08:00
#
########################################
app.state.config.ENABLE_BASE_MODELS_CACHE = ENABLE_BASE_MODELS_CACHE
app.state.BASE_MODELS = []
2025-06-28 19:12:31 +08:00
2024-12-10 16:54:13 +08:00
########################################
#
# WEBUI
#
########################################
2024-07-02 10:33:58 +08:00
2024-12-26 00:50:57 +08:00
app.state.config.WEBUI_URL = WEBUI_URL
2024-12-10 16:54:13 +08:00
app.state.config.ENABLE_SIGNUP = ENABLE_SIGNUP
app.state.config.ENABLE_LOGIN_FORM = ENABLE_LOGIN_FORM
2024-12-10 16:54:13 +08:00
app.state.config.ENABLE_API_KEY = ENABLE_API_KEY
app.state.config.ENABLE_API_KEY_ENDPOINT_RESTRICTIONS = (
ENABLE_API_KEY_ENDPOINT_RESTRICTIONS
)
app.state.config.API_KEY_ALLOWED_ENDPOINTS = API_KEY_ALLOWED_ENDPOINTS
2024-06-10 05:25:31 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.JWT_EXPIRES_IN = JWT_EXPIRES_IN
2024-06-10 05:25:31 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.SHOW_ADMIN_DETAILS = SHOW_ADMIN_DETAILS
app.state.config.ADMIN_EMAIL = ADMIN_EMAIL
2024-06-10 06:19:36 +08:00
2024-06-10 05:53:10 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.DEFAULT_MODELS = DEFAULT_MODELS
app.state.config.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS
app.state.config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE
2025-05-15 03:53:28 +08:00
2025-05-15 01:39:17 +08:00
app.state.config.PENDING_USER_OVERLAY_CONTENT = PENDING_USER_OVERLAY_CONTENT
app.state.config.PENDING_USER_OVERLAY_TITLE = PENDING_USER_OVERLAY_TITLE
2024-06-10 05:53:10 +08:00
2025-05-15 03:53:28 +08:00
app.state.config.RESPONSE_WATERMARK = RESPONSE_WATERMARK
2024-12-10 16:54:13 +08:00
app.state.config.USER_PERMISSIONS = USER_PERMISSIONS
app.state.config.WEBHOOK_URL = WEBHOOK_URL
2024-12-10 16:54:13 +08:00
app.state.config.BANNERS = WEBUI_BANNERS
app.state.config.MODEL_ORDER_LIST = MODEL_ORDER_LIST
2024-12-23 12:02:14 +08:00
app.state.config.ENABLE_CHANNELS = ENABLE_CHANNELS
2025-05-01 20:39:36 +08:00
app.state.config.ENABLE_NOTES = ENABLE_NOTES
2024-12-10 16:54:13 +08:00
app.state.config.ENABLE_COMMUNITY_SHARING = ENABLE_COMMUNITY_SHARING
app.state.config.ENABLE_MESSAGE_RATING = ENABLE_MESSAGE_RATING
2025-03-31 12:31:16 +08:00
app.state.config.ENABLE_USER_WEBHOOKS = ENABLE_USER_WEBHOOKS
2024-09-07 11:50:29 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.ENABLE_EVALUATION_ARENA_MODELS = ENABLE_EVALUATION_ARENA_MODELS
app.state.config.EVALUATION_ARENA_MODELS = EVALUATION_ARENA_MODELS
2024-09-08 07:51:12 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.OAUTH_USERNAME_CLAIM = OAUTH_USERNAME_CLAIM
app.state.config.OAUTH_PICTURE_CLAIM = OAUTH_PICTURE_CLAIM
app.state.config.OAUTH_EMAIL_CLAIM = OAUTH_EMAIL_CLAIM
2024-09-08 08:17:02 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.ENABLE_OAUTH_ROLE_MANAGEMENT = ENABLE_OAUTH_ROLE_MANAGEMENT
app.state.config.OAUTH_ROLES_CLAIM = OAUTH_ROLES_CLAIM
app.state.config.OAUTH_ALLOWED_ROLES = OAUTH_ALLOWED_ROLES
app.state.config.OAUTH_ADMIN_ROLES = OAUTH_ADMIN_ROLES
2024-06-10 05:53:10 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.ENABLE_LDAP = ENABLE_LDAP
app.state.config.LDAP_SERVER_LABEL = LDAP_SERVER_LABEL
app.state.config.LDAP_SERVER_HOST = LDAP_SERVER_HOST
app.state.config.LDAP_SERVER_PORT = LDAP_SERVER_PORT
app.state.config.LDAP_ATTRIBUTE_FOR_MAIL = LDAP_ATTRIBUTE_FOR_MAIL
2024-12-10 16:54:13 +08:00
app.state.config.LDAP_ATTRIBUTE_FOR_USERNAME = LDAP_ATTRIBUTE_FOR_USERNAME
app.state.config.LDAP_APP_DN = LDAP_APP_DN
app.state.config.LDAP_APP_PASSWORD = LDAP_APP_PASSWORD
app.state.config.LDAP_SEARCH_BASE = LDAP_SEARCH_BASE
app.state.config.LDAP_SEARCH_FILTERS = LDAP_SEARCH_FILTERS
app.state.config.LDAP_USE_TLS = LDAP_USE_TLS
app.state.config.LDAP_CA_CERT_FILE = LDAP_CA_CERT_FILE
app.state.config.LDAP_VALIDATE_CERT = LDAP_VALIDATE_CERT
2024-12-10 16:54:13 +08:00
app.state.config.LDAP_CIPHERS = LDAP_CIPHERS
2024-06-10 05:53:10 +08:00
# For LDAP Group Management
app.state.config.ENABLE_LDAP_GROUP_MANAGEMENT = ENABLE_LDAP_GROUP_MANAGEMENT
app.state.config.ENABLE_LDAP_GROUP_CREATION = ENABLE_LDAP_GROUP_CREATION
app.state.config.LDAP_ATTRIBUTE_FOR_GROUPS = LDAP_ATTRIBUTE_FOR_GROUPS
2024-09-07 11:50:29 +08:00
2024-12-10 16:54:13 +08:00
app.state.AUTH_TRUSTED_EMAIL_HEADER = WEBUI_AUTH_TRUSTED_EMAIL_HEADER
app.state.AUTH_TRUSTED_NAME_HEADER = WEBUI_AUTH_TRUSTED_NAME_HEADER
2025-04-19 14:58:37 +08:00
app.state.WEBUI_AUTH_SIGNOUT_REDIRECT_URL = WEBUI_AUTH_SIGNOUT_REDIRECT_URL
2025-04-11 01:35:43 +08:00
app.state.EXTERNAL_PWA_MANIFEST_URL = EXTERNAL_PWA_MANIFEST_URL
2024-06-13 12:18:53 +08:00
2025-02-16 16:11:18 +08:00
app.state.USER_COUNT = None
2025-05-27 18:39:35 +08:00
2024-12-10 16:54:13 +08:00
app.state.TOOLS = {}
2025-05-27 18:39:35 +08:00
app.state.TOOL_CONTENTS = {}
2024-12-10 16:54:13 +08:00
app.state.FUNCTIONS = {}
2025-05-27 18:39:35 +08:00
app.state.FUNCTION_CONTENTS = {}
2024-07-02 10:33:58 +08:00
2024-12-10 16:54:13 +08:00
########################################
#
# RETRIEVAL
#
########################################
2024-06-13 12:18:53 +08:00
2024-12-11 18:41:25 +08:00
app.state.config.TOP_K = RAG_TOP_K
2025-03-06 17:47:57 +08:00
app.state.config.TOP_K_RERANKER = RAG_TOP_K_RERANKER
2024-12-11 18:41:25 +08:00
app.state.config.RELEVANCE_THRESHOLD = RAG_RELEVANCE_THRESHOLD
app.state.config.HYBRID_BM25_WEIGHT = RAG_HYBRID_BM25_WEIGHT
2025-06-16 20:52:57 +08:00
2025-05-15 03:06:33 +08:00
app.state.config.ALLOWED_FILE_EXTENSIONS = RAG_ALLOWED_FILE_EXTENSIONS
2024-12-11 18:41:25 +08:00
app.state.config.FILE_MAX_SIZE = RAG_FILE_MAX_SIZE
app.state.config.FILE_MAX_COUNT = RAG_FILE_MAX_COUNT
2025-06-16 20:52:57 +08:00
app.state.config.FILE_IMAGE_COMPRESSION_WIDTH = FILE_IMAGE_COMPRESSION_WIDTH
app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT = FILE_IMAGE_COMPRESSION_HEIGHT
2024-06-13 12:18:53 +08:00
2025-02-19 13:14:58 +08:00
app.state.config.RAG_FULL_CONTEXT = RAG_FULL_CONTEXT
2025-02-27 07:42:19 +08:00
app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL = BYPASS_EMBEDDING_AND_RETRIEVAL
2024-12-11 18:41:25 +08:00
app.state.config.ENABLE_RAG_HYBRID_SEARCH = ENABLE_RAG_HYBRID_SEARCH
2025-04-13 07:33:36 +08:00
app.state.config.ENABLE_WEB_LOADER_SSL_VERIFICATION = ENABLE_WEB_LOADER_SSL_VERIFICATION
2024-06-13 12:18:53 +08:00
2024-12-11 18:41:25 +08:00
app.state.config.CONTENT_EXTRACTION_ENGINE = CONTENT_EXTRACTION_ENGINE
app.state.config.DATALAB_MARKER_API_KEY = DATALAB_MARKER_API_KEY
2025-07-23 08:49:28 +08:00
app.state.config.DATALAB_MARKER_API_BASE_URL = DATALAB_MARKER_API_BASE_URL
app.state.config.DATALAB_MARKER_ADDITIONAL_CONFIG = DATALAB_MARKER_ADDITIONAL_CONFIG
app.state.config.DATALAB_MARKER_SKIP_CACHE = DATALAB_MARKER_SKIP_CACHE
app.state.config.DATALAB_MARKER_FORCE_OCR = DATALAB_MARKER_FORCE_OCR
app.state.config.DATALAB_MARKER_PAGINATE = DATALAB_MARKER_PAGINATE
app.state.config.DATALAB_MARKER_STRIP_EXISTING_OCR = DATALAB_MARKER_STRIP_EXISTING_OCR
2025-05-29 06:36:33 +08:00
app.state.config.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION = (
DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION
)
2025-07-23 09:06:29 +08:00
app.state.config.DATALAB_MARKER_FORMAT_LINES = DATALAB_MARKER_FORMAT_LINES
app.state.config.DATALAB_MARKER_USE_LLM = DATALAB_MARKER_USE_LLM
app.state.config.DATALAB_MARKER_OUTPUT_FORMAT = DATALAB_MARKER_OUTPUT_FORMAT
2025-05-15 02:28:40 +08:00
app.state.config.EXTERNAL_DOCUMENT_LOADER_URL = EXTERNAL_DOCUMENT_LOADER_URL
app.state.config.EXTERNAL_DOCUMENT_LOADER_API_KEY = EXTERNAL_DOCUMENT_LOADER_API_KEY
2024-12-11 18:41:25 +08:00
app.state.config.TIKA_SERVER_URL = TIKA_SERVER_URL
app.state.config.DOCLING_SERVER_URL = DOCLING_SERVER_URL
app.state.config.DOCLING_DO_OCR = DOCLING_DO_OCR
app.state.config.DOCLING_FORCE_OCR = DOCLING_FORCE_OCR
app.state.config.DOCLING_OCR_ENGINE = DOCLING_OCR_ENGINE
app.state.config.DOCLING_OCR_LANG = DOCLING_OCR_LANG
app.state.config.DOCLING_PDF_BACKEND = DOCLING_PDF_BACKEND
app.state.config.DOCLING_TABLE_MODE = DOCLING_TABLE_MODE
app.state.config.DOCLING_PIPELINE = DOCLING_PIPELINE
app.state.config.DOCLING_DO_PICTURE_DESCRIPTION = DOCLING_DO_PICTURE_DESCRIPTION
app.state.config.DOCLING_PICTURE_DESCRIPTION_MODE = DOCLING_PICTURE_DESCRIPTION_MODE
2025-06-09 00:02:14 +08:00
app.state.config.DOCLING_PICTURE_DESCRIPTION_LOCAL = DOCLING_PICTURE_DESCRIPTION_LOCAL
app.state.config.DOCLING_PICTURE_DESCRIPTION_API = DOCLING_PICTURE_DESCRIPTION_API
app.state.config.DOCUMENT_INTELLIGENCE_ENDPOINT = DOCUMENT_INTELLIGENCE_ENDPOINT
app.state.config.DOCUMENT_INTELLIGENCE_KEY = DOCUMENT_INTELLIGENCE_KEY
app.state.config.MISTRAL_OCR_API_KEY = MISTRAL_OCR_API_KEY
2024-12-11 18:41:25 +08:00
app.state.config.TEXT_SPLITTER = RAG_TEXT_SPLITTER
app.state.config.TIKTOKEN_ENCODING_NAME = TIKTOKEN_ENCODING_NAME
app.state.config.CHUNK_SIZE = CHUNK_SIZE
app.state.config.CHUNK_OVERLAP = CHUNK_OVERLAP
app.state.config.RAG_EMBEDDING_ENGINE = RAG_EMBEDDING_ENGINE
app.state.config.RAG_EMBEDDING_MODEL = RAG_EMBEDDING_MODEL
app.state.config.RAG_EMBEDDING_BATCH_SIZE = RAG_EMBEDDING_BATCH_SIZE
app.state.config.RAG_RERANKING_ENGINE = RAG_RERANKING_ENGINE
2024-12-11 18:41:25 +08:00
app.state.config.RAG_RERANKING_MODEL = RAG_RERANKING_MODEL
app.state.config.RAG_EXTERNAL_RERANKER_URL = RAG_EXTERNAL_RERANKER_URL
app.state.config.RAG_EXTERNAL_RERANKER_API_KEY = RAG_EXTERNAL_RERANKER_API_KEY
2024-12-11 18:41:25 +08:00
app.state.config.RAG_TEMPLATE = RAG_TEMPLATE
app.state.config.RAG_OPENAI_API_BASE_URL = RAG_OPENAI_API_BASE_URL
app.state.config.RAG_OPENAI_API_KEY = RAG_OPENAI_API_KEY
2025-05-20 10:58:04 +08:00
app.state.config.RAG_AZURE_OPENAI_BASE_URL = RAG_AZURE_OPENAI_BASE_URL
app.state.config.RAG_AZURE_OPENAI_API_KEY = RAG_AZURE_OPENAI_API_KEY
app.state.config.RAG_AZURE_OPENAI_API_VERSION = RAG_AZURE_OPENAI_API_VERSION
2025-05-20 10:58:04 +08:00
2024-12-11 18:41:25 +08:00
app.state.config.RAG_OLLAMA_BASE_URL = RAG_OLLAMA_BASE_URL
app.state.config.RAG_OLLAMA_API_KEY = RAG_OLLAMA_API_KEY
app.state.config.PDF_EXTRACT_IMAGES = PDF_EXTRACT_IMAGES
app.state.config.YOUTUBE_LOADER_LANGUAGE = YOUTUBE_LOADER_LANGUAGE
app.state.config.YOUTUBE_LOADER_PROXY_URL = YOUTUBE_LOADER_PROXY_URL
2025-04-13 07:33:36 +08:00
app.state.config.ENABLE_WEB_SEARCH = ENABLE_WEB_SEARCH
app.state.config.WEB_SEARCH_ENGINE = WEB_SEARCH_ENGINE
app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST = WEB_SEARCH_DOMAIN_FILTER_LIST
app.state.config.WEB_SEARCH_RESULT_COUNT = WEB_SEARCH_RESULT_COUNT
app.state.config.WEB_SEARCH_CONCURRENT_REQUESTS = WEB_SEARCH_CONCURRENT_REQUESTS
2025-04-13 07:33:36 +08:00
app.state.config.WEB_LOADER_ENGINE = WEB_LOADER_ENGINE
app.state.config.WEB_LOADER_CONCURRENT_REQUESTS = WEB_LOADER_CONCURRENT_REQUESTS
2025-04-13 07:33:36 +08:00
app.state.config.WEB_SEARCH_TRUST_ENV = WEB_SEARCH_TRUST_ENV
2025-02-27 07:42:19 +08:00
app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = (
BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL
)
app.state.config.BYPASS_WEB_SEARCH_WEB_LOADER = BYPASS_WEB_SEARCH_WEB_LOADER
2024-12-11 18:41:25 +08:00
2024-12-19 10:04:56 +08:00
app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION = ENABLE_GOOGLE_DRIVE_INTEGRATION
2025-02-24 22:14:10 +08:00
app.state.config.ENABLE_ONEDRIVE_INTEGRATION = ENABLE_ONEDRIVE_INTEGRATION
2024-12-11 18:41:25 +08:00
app.state.config.SEARXNG_QUERY_URL = SEARXNG_QUERY_URL
app.state.config.YACY_QUERY_URL = YACY_QUERY_URL
app.state.config.YACY_USERNAME = YACY_USERNAME
app.state.config.YACY_PASSWORD = YACY_PASSWORD
2024-12-11 18:41:25 +08:00
app.state.config.GOOGLE_PSE_API_KEY = GOOGLE_PSE_API_KEY
app.state.config.GOOGLE_PSE_ENGINE_ID = GOOGLE_PSE_ENGINE_ID
app.state.config.BRAVE_SEARCH_API_KEY = BRAVE_SEARCH_API_KEY
app.state.config.KAGI_SEARCH_API_KEY = KAGI_SEARCH_API_KEY
app.state.config.MOJEEK_SEARCH_API_KEY = MOJEEK_SEARCH_API_KEY
2025-02-10 16:44:47 +08:00
app.state.config.BOCHA_SEARCH_API_KEY = BOCHA_SEARCH_API_KEY
2024-12-11 18:41:25 +08:00
app.state.config.SERPSTACK_API_KEY = SERPSTACK_API_KEY
app.state.config.SERPSTACK_HTTPS = SERPSTACK_HTTPS
app.state.config.SERPER_API_KEY = SERPER_API_KEY
app.state.config.SERPLY_API_KEY = SERPLY_API_KEY
app.state.config.TAVILY_API_KEY = TAVILY_API_KEY
app.state.config.SEARCHAPI_API_KEY = SEARCHAPI_API_KEY
app.state.config.SEARCHAPI_ENGINE = SEARCHAPI_ENGINE
2025-02-14 12:24:58 +08:00
app.state.config.SERPAPI_API_KEY = SERPAPI_API_KEY
app.state.config.SERPAPI_ENGINE = SERPAPI_ENGINE
2024-12-11 18:41:25 +08:00
app.state.config.JINA_API_KEY = JINA_API_KEY
app.state.config.BING_SEARCH_V7_ENDPOINT = BING_SEARCH_V7_ENDPOINT
app.state.config.BING_SEARCH_V7_SUBSCRIPTION_KEY = BING_SEARCH_V7_SUBSCRIPTION_KEY
app.state.config.EXA_API_KEY = EXA_API_KEY
app.state.config.PERPLEXITY_API_KEY = PERPLEXITY_API_KEY
app.state.config.PERPLEXITY_MODEL = PERPLEXITY_MODEL
app.state.config.PERPLEXITY_SEARCH_CONTEXT_USAGE = PERPLEXITY_SEARCH_CONTEXT_USAGE
app.state.config.SOUGOU_API_SID = SOUGOU_API_SID
app.state.config.SOUGOU_API_SK = SOUGOU_API_SK
app.state.config.EXTERNAL_WEB_SEARCH_URL = EXTERNAL_WEB_SEARCH_URL
app.state.config.EXTERNAL_WEB_SEARCH_API_KEY = EXTERNAL_WEB_SEARCH_API_KEY
app.state.config.EXTERNAL_WEB_LOADER_URL = EXTERNAL_WEB_LOADER_URL
app.state.config.EXTERNAL_WEB_LOADER_API_KEY = EXTERNAL_WEB_LOADER_API_KEY
2024-12-11 18:41:25 +08:00
2025-04-13 07:33:36 +08:00
app.state.config.PLAYWRIGHT_WS_URL = PLAYWRIGHT_WS_URL
2025-03-21 05:01:47 +08:00
app.state.config.PLAYWRIGHT_TIMEOUT = PLAYWRIGHT_TIMEOUT
app.state.config.FIRECRAWL_API_BASE_URL = FIRECRAWL_API_BASE_URL
app.state.config.FIRECRAWL_API_KEY = FIRECRAWL_API_KEY
app.state.config.TAVILY_EXTRACT_DEPTH = TAVILY_EXTRACT_DEPTH
2024-12-11 18:41:25 +08:00
2024-12-12 10:05:42 +08:00
app.state.EMBEDDING_FUNCTION = None
app.state.RERANKING_FUNCTION = None
2024-12-12 10:46:29 +08:00
app.state.ef = None
app.state.rf = None
2024-12-11 18:41:25 +08:00
app.state.YOUTUBE_LOADER_TRANSLATION = None
2024-12-12 10:05:42 +08:00
2024-12-11 18:41:25 +08:00
2024-12-25 10:39:53 +08:00
try:
app.state.ef = get_ef(
app.state.config.RAG_EMBEDDING_ENGINE,
app.state.config.RAG_EMBEDDING_MODEL,
RAG_EMBEDDING_MODEL_AUTO_UPDATE,
)
2025-08-21 19:40:56 +08:00
if (
app.state.config.ENABLE_RAG_HYBRID_SEARCH
and not app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL
):
app.state.rf = get_rf(
app.state.config.RAG_RERANKING_ENGINE,
app.state.config.RAG_RERANKING_MODEL,
app.state.config.RAG_EXTERNAL_RERANKER_URL,
app.state.config.RAG_EXTERNAL_RERANKER_API_KEY,
RAG_RERANKING_MODEL_AUTO_UPDATE,
)
else:
app.state.rf = None
2024-12-25 10:39:53 +08:00
except Exception as e:
log.error(f"Error updating models: {e}")
pass
2024-12-12 10:08:55 +08:00
app.state.EMBEDDING_FUNCTION = get_embedding_function(
app.state.config.RAG_EMBEDDING_ENGINE,
app.state.config.RAG_EMBEDDING_MODEL,
embedding_function=app.state.ef,
url=(
2024-12-12 10:46:29 +08:00
app.state.config.RAG_OPENAI_API_BASE_URL
2024-12-12 10:08:55 +08:00
if app.state.config.RAG_EMBEDDING_ENGINE == "openai"
2025-05-20 10:58:04 +08:00
else (
app.state.config.RAG_OLLAMA_BASE_URL
if app.state.config.RAG_EMBEDDING_ENGINE == "ollama"
else app.state.config.RAG_AZURE_OPENAI_BASE_URL
)
2024-12-12 10:08:55 +08:00
),
key=(
2024-12-12 10:46:29 +08:00
app.state.config.RAG_OPENAI_API_KEY
2024-12-12 10:08:55 +08:00
if app.state.config.RAG_EMBEDDING_ENGINE == "openai"
2025-05-20 10:58:04 +08:00
else (
app.state.config.RAG_OLLAMA_API_KEY
if app.state.config.RAG_EMBEDDING_ENGINE == "ollama"
else app.state.config.RAG_AZURE_OPENAI_API_KEY
)
2024-12-12 10:08:55 +08:00
),
embedding_batch_size=app.state.config.RAG_EMBEDDING_BATCH_SIZE,
azure_api_version=(
app.state.config.RAG_AZURE_OPENAI_API_VERSION
2025-05-20 10:58:04 +08:00
if app.state.config.RAG_EMBEDDING_ENGINE == "azure_openai"
else None
),
2024-12-12 10:08:55 +08:00
)
app.state.RERANKING_FUNCTION = get_reranking_function(
app.state.config.RAG_RERANKING_ENGINE,
app.state.config.RAG_RERANKING_MODEL,
reranking_function=app.state.rf,
)
2025-02-10 18:25:02 +08:00
########################################
#
2025-02-18 08:25:50 +08:00
# CODE EXECUTION
2025-02-10 18:25:02 +08:00
#
########################################
app.state.config.ENABLE_CODE_EXECUTION = ENABLE_CODE_EXECUTION
2025-02-18 08:25:50 +08:00
app.state.config.CODE_EXECUTION_ENGINE = CODE_EXECUTION_ENGINE
app.state.config.CODE_EXECUTION_JUPYTER_URL = CODE_EXECUTION_JUPYTER_URL
app.state.config.CODE_EXECUTION_JUPYTER_AUTH = CODE_EXECUTION_JUPYTER_AUTH
app.state.config.CODE_EXECUTION_JUPYTER_AUTH_TOKEN = CODE_EXECUTION_JUPYTER_AUTH_TOKEN
app.state.config.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD = (
CODE_EXECUTION_JUPYTER_AUTH_PASSWORD
)
app.state.config.CODE_EXECUTION_JUPYTER_TIMEOUT = CODE_EXECUTION_JUPYTER_TIMEOUT
2025-02-18 08:25:50 +08:00
2025-02-10 18:25:02 +08:00
app.state.config.ENABLE_CODE_INTERPRETER = ENABLE_CODE_INTERPRETER
app.state.config.CODE_INTERPRETER_ENGINE = CODE_INTERPRETER_ENGINE
2025-02-12 13:36:16 +08:00
app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE = CODE_INTERPRETER_PROMPT_TEMPLATE
2025-02-10 18:25:02 +08:00
app.state.config.CODE_INTERPRETER_JUPYTER_URL = CODE_INTERPRETER_JUPYTER_URL
app.state.config.CODE_INTERPRETER_JUPYTER_AUTH = CODE_INTERPRETER_JUPYTER_AUTH
app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN = (
CODE_INTERPRETER_JUPYTER_AUTH_TOKEN
)
app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD = (
CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD
)
app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT = CODE_INTERPRETER_JUPYTER_TIMEOUT
2024-06-13 04:34:34 +08:00
2024-12-10 16:54:13 +08:00
########################################
#
# IMAGES
#
########################################
2024-07-02 10:33:58 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.IMAGE_GENERATION_ENGINE = IMAGE_GENERATION_ENGINE
app.state.config.ENABLE_IMAGE_GENERATION = ENABLE_IMAGE_GENERATION
2025-01-16 16:13:02 +08:00
app.state.config.ENABLE_IMAGE_PROMPT_GENERATION = ENABLE_IMAGE_PROMPT_GENERATION
2024-06-10 05:53:10 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.IMAGES_OPENAI_API_BASE_URL = IMAGES_OPENAI_API_BASE_URL
app.state.config.IMAGES_OPENAI_API_VERSION = IMAGES_OPENAI_API_VERSION
2024-12-10 16:54:13 +08:00
app.state.config.IMAGES_OPENAI_API_KEY = IMAGES_OPENAI_API_KEY
2024-06-10 05:53:10 +08:00
app.state.config.IMAGES_GEMINI_API_BASE_URL = IMAGES_GEMINI_API_BASE_URL
app.state.config.IMAGES_GEMINI_API_KEY = IMAGES_GEMINI_API_KEY
2024-12-10 16:54:13 +08:00
app.state.config.IMAGE_GENERATION_MODEL = IMAGE_GENERATION_MODEL
2024-08-19 02:59:59 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL
app.state.config.AUTOMATIC1111_API_AUTH = AUTOMATIC1111_API_AUTH
app.state.config.AUTOMATIC1111_CFG_SCALE = AUTOMATIC1111_CFG_SCALE
app.state.config.AUTOMATIC1111_SAMPLER = AUTOMATIC1111_SAMPLER
app.state.config.AUTOMATIC1111_SCHEDULER = AUTOMATIC1111_SCHEDULER
app.state.config.COMFYUI_BASE_URL = COMFYUI_BASE_URL
2024-12-17 15:29:00 +08:00
app.state.config.COMFYUI_API_KEY = COMFYUI_API_KEY
2024-12-10 16:54:13 +08:00
app.state.config.COMFYUI_WORKFLOW = COMFYUI_WORKFLOW
app.state.config.COMFYUI_WORKFLOW_NODES = COMFYUI_WORKFLOW_NODES
2024-08-19 02:59:59 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.IMAGE_SIZE = IMAGE_SIZE
app.state.config.IMAGE_STEPS = IMAGE_STEPS
2024-08-19 02:59:59 +08:00
2024-12-10 16:54:13 +08:00
########################################
#
# AUDIO
#
########################################
2024-08-19 02:59:59 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.STT_ENGINE = AUDIO_STT_ENGINE
app.state.config.STT_MODEL = AUDIO_STT_MODEL
app.state.config.STT_SUPPORTED_CONTENT_TYPES = AUDIO_STT_SUPPORTED_CONTENT_TYPES
app.state.config.STT_OPENAI_API_BASE_URL = AUDIO_STT_OPENAI_API_BASE_URL
app.state.config.STT_OPENAI_API_KEY = AUDIO_STT_OPENAI_API_KEY
2024-08-19 02:59:59 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.WHISPER_MODEL = WHISPER_MODEL
2025-04-14 14:39:38 +08:00
app.state.config.WHISPER_VAD_FILTER = WHISPER_VAD_FILTER
2025-02-02 21:58:59 +08:00
app.state.config.DEEPGRAM_API_KEY = DEEPGRAM_API_KEY
2024-08-19 02:59:59 +08:00
app.state.config.AUDIO_STT_AZURE_API_KEY = AUDIO_STT_AZURE_API_KEY
app.state.config.AUDIO_STT_AZURE_REGION = AUDIO_STT_AZURE_REGION
app.state.config.AUDIO_STT_AZURE_LOCALES = AUDIO_STT_AZURE_LOCALES
app.state.config.AUDIO_STT_AZURE_BASE_URL = AUDIO_STT_AZURE_BASE_URL
app.state.config.AUDIO_STT_AZURE_MAX_SPEAKERS = AUDIO_STT_AZURE_MAX_SPEAKERS
2024-12-10 16:54:13 +08:00
app.state.config.TTS_OPENAI_API_BASE_URL = AUDIO_TTS_OPENAI_API_BASE_URL
app.state.config.TTS_OPENAI_API_KEY = AUDIO_TTS_OPENAI_API_KEY
app.state.config.TTS_ENGINE = AUDIO_TTS_ENGINE
app.state.config.TTS_MODEL = AUDIO_TTS_MODEL
app.state.config.TTS_VOICE = AUDIO_TTS_VOICE
app.state.config.TTS_API_KEY = AUDIO_TTS_API_KEY
app.state.config.TTS_SPLIT_ON = AUDIO_TTS_SPLIT_ON
2024-08-19 02:59:59 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.TTS_AZURE_SPEECH_REGION = AUDIO_TTS_AZURE_SPEECH_REGION
2025-05-06 10:08:48 +08:00
app.state.config.TTS_AZURE_SPEECH_BASE_URL = AUDIO_TTS_AZURE_SPEECH_BASE_URL
2024-12-10 16:54:13 +08:00
app.state.config.TTS_AZURE_SPEECH_OUTPUT_FORMAT = AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT
2024-08-19 02:59:59 +08:00
2024-12-10 16:54:13 +08:00
app.state.faster_whisper_model = None
app.state.speech_synthesiser = None
app.state.speech_speaker_embeddings_dataset = None
2024-08-19 02:59:59 +08:00
2024-12-10 16:54:13 +08:00
########################################
2024-06-20 16:51:39 +08:00
#
2024-12-10 16:54:13 +08:00
# TASKS
2024-06-20 16:51:39 +08:00
#
2024-12-10 16:54:13 +08:00
########################################
2024-05-30 17:04:29 +08:00
2024-06-10 05:53:10 +08:00
app.state.config.TASK_MODEL = TASK_MODEL
app.state.config.TASK_MODEL_EXTERNAL = TASK_MODEL_EXTERNAL
2024-05-30 17:04:29 +08:00
2024-05-30 13:41:51 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.ENABLE_SEARCH_QUERY_GENERATION = ENABLE_SEARCH_QUERY_GENERATION
app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION = ENABLE_RETRIEVAL_QUERY_GENERATION
2024-12-01 10:30:59 +08:00
app.state.config.ENABLE_AUTOCOMPLETE_GENERATION = ENABLE_AUTOCOMPLETE_GENERATION
app.state.config.ENABLE_TAGS_GENERATION = ENABLE_TAGS_GENERATION
app.state.config.ENABLE_TITLE_GENERATION = ENABLE_TITLE_GENERATION
2025-06-03 22:07:29 +08:00
app.state.config.ENABLE_FOLLOW_UP_GENERATION = ENABLE_FOLLOW_UP_GENERATION
2024-12-10 16:54:13 +08:00
app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE = TITLE_GENERATION_PROMPT_TEMPLATE
app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE = TAGS_GENERATION_PROMPT_TEMPLATE
2025-01-16 16:06:37 +08:00
app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE = (
IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE
)
2025-06-03 22:07:29 +08:00
app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = (
FOLLOW_UP_GENERATION_PROMPT_TEMPLATE
)
2025-01-16 16:06:37 +08:00
2024-12-10 16:54:13 +08:00
app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = (
TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE
)
2024-11-19 18:24:32 +08:00
app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE = QUERY_GENERATION_PROMPT_TEMPLATE
2024-11-29 15:53:52 +08:00
app.state.config.AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE = (
AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE
)
2024-12-10 16:54:13 +08:00
app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH = (
AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH
2024-06-11 14:40:27 +08:00
)
2024-06-06 04:57:48 +08:00
2024-12-11 19:38:45 +08:00
########################################
#
# WEBUI
#
########################################
2024-06-06 04:57:48 +08:00
2024-12-11 19:38:45 +08:00
app.state.MODELS = {}
2024-06-06 04:57:48 +08:00
2024-10-08 09:19:13 +08:00
class RedirectMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
# Check if the request is a GET request
if request.method == "GET":
path = request.url.path
query_params = dict(parse_qs(urlparse(str(request.url)).query))
2024-06-06 04:57:48 +08:00
2024-10-08 09:19:13 +08:00
# Check for the specific watch path and the presence of 'v' parameter
if path.endswith("/watch") and "v" in query_params:
# Extract the first 'v' parameter
video_id = query_params["v"][0]
2024-10-08 09:19:13 +08:00
encoded_video_id = urlencode({"youtube": video_id})
redirect_url = f"/?{encoded_video_id}"
return RedirectResponse(url=redirect_url)
2024-06-06 04:57:48 +08:00
2024-10-08 09:19:13 +08:00
# Proceed with the normal flow of other requests
response = await call_next(request)
return response
2024-06-06 04:57:48 +08:00
2024-10-08 09:19:13 +08:00
# Add the middleware to the app
if ENABLE_COMPRESSION_MIDDLEWARE:
app.add_middleware(CompressMiddleware)
2024-10-08 09:19:13 +08:00
app.add_middleware(RedirectMiddleware)
2024-09-17 08:53:30 +08:00
app.add_middleware(SecurityHeadersMiddleware)
2024-06-06 04:57:48 +08:00
@app.middleware("http")
2024-06-24 19:45:33 +08:00
async def commit_session_after_request(request: Request, call_next):
response = await call_next(request)
2024-11-23 12:11:46 +08:00
# log.debug("Commit session after request")
Session.commit()
return response
2024-06-06 04:57:48 +08:00
2024-05-30 13:03:22 +08:00
2023-11-15 08:28:51 +08:00
@app.middleware("http")
async def check_url(request: Request, call_next):
start_time = int(time.time())
2025-04-05 18:05:52 +08:00
request.state.token = get_http_authorization_cred(
request.headers.get("Authorization")
)
2024-12-12 10:53:38 +08:00
request.state.enable_api_key = app.state.config.ENABLE_API_KEY
2023-11-15 08:28:51 +08:00
response = await call_next(request)
process_time = int(time.time()) - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
2024-05-30 13:03:22 +08:00
@app.middleware("http")
async def inspect_websocket(request: Request, call_next):
if (
2024-10-21 09:38:06 +08:00
"/ws/socket.io" in request.url.path
and request.query_params.get("transport") == "websocket"
):
upgrade = (request.headers.get("Upgrade") or "").lower()
connection = (request.headers.get("Connection") or "").lower().split(",")
# Check that there's the correct headers for an upgrade, else reject the connection
# This is to work around this upstream issue: https://github.com/miguelgrinberg/python-engineio/issues/367
if upgrade != "websocket" or "upgrade" not in connection:
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={"detail": "Invalid WebSocket upgrade request"},
)
return await call_next(request)
2024-05-30 13:03:22 +08:00
2024-12-10 16:54:13 +08:00
app.add_middleware(
CORSMiddleware,
allow_origins=CORS_ALLOW_ORIGIN,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
2024-05-30 13:03:22 +08:00
2024-06-04 14:39:52 +08:00
app.mount("/ws", socket_app)
2024-05-30 13:03:22 +08:00
2024-12-12 10:36:59 +08:00
app.include_router(ollama.router, prefix="/ollama", tags=["ollama"])
app.include_router(openai.router, prefix="/openai", tags=["openai"])
2024-05-30 13:03:22 +08:00
2024-12-13 12:22:17 +08:00
app.include_router(pipelines.router, prefix="/api/v1/pipelines", tags=["pipelines"])
app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
2024-12-12 09:50:48 +08:00
app.include_router(images.router, prefix="/api/v1/images", tags=["images"])
2025-02-10 18:25:02 +08:00
2024-12-12 09:50:48 +08:00
app.include_router(audio.router, prefix="/api/v1/audio", tags=["audio"])
app.include_router(retrieval.router, prefix="/api/v1/retrieval", tags=["retrieval"])
2024-05-30 13:03:22 +08:00
2024-12-11 18:41:25 +08:00
app.include_router(configs.router, prefix="/api/v1/configs", tags=["configs"])
2024-05-30 13:03:22 +08:00
2024-12-11 18:41:25 +08:00
app.include_router(auths.router, prefix="/api/v1/auths", tags=["auths"])
app.include_router(users.router, prefix="/api/v1/users", tags=["users"])
2024-05-30 13:03:22 +08:00
2024-12-22 18:42:19 +08:00
app.include_router(channels.router, prefix="/api/v1/channels", tags=["channels"])
2024-12-11 18:41:25 +08:00
app.include_router(chats.router, prefix="/api/v1/chats", tags=["chats"])
2025-05-03 22:16:32 +08:00
app.include_router(notes.router, prefix="/api/v1/notes", tags=["notes"])
2024-05-30 13:03:22 +08:00
2024-12-11 18:41:25 +08:00
app.include_router(models.router, prefix="/api/v1/models", tags=["models"])
app.include_router(knowledge.router, prefix="/api/v1/knowledge", tags=["knowledge"])
app.include_router(prompts.router, prefix="/api/v1/prompts", tags=["prompts"])
app.include_router(tools.router, prefix="/api/v1/tools", tags=["tools"])
2024-05-30 13:03:22 +08:00
2024-12-11 18:41:25 +08:00
app.include_router(memories.router, prefix="/api/v1/memories", tags=["memories"])
app.include_router(folders.router, prefix="/api/v1/folders", tags=["folders"])
app.include_router(groups.router, prefix="/api/v1/groups", tags=["groups"])
app.include_router(files.router, prefix="/api/v1/files", tags=["files"])
app.include_router(functions.router, prefix="/api/v1/functions", tags=["functions"])
app.include_router(
evaluations.router, prefix="/api/v1/evaluations", tags=["evaluations"]
)
app.include_router(utils.router, prefix="/api/v1/utils", tags=["utils"])
2024-05-30 13:03:22 +08:00
# SCIM 2.0 API for identity management
2025-08-06 18:25:42 +08:00
if SCIM_ENABLED:
app.include_router(scim.router, prefix="/api/v1/scim/v2", tags=["scim"])
2024-05-30 13:03:22 +08:00
try:
audit_level = AuditLevel(AUDIT_LOG_LEVEL)
except ValueError as e:
logger.error(f"Invalid audit level: {AUDIT_LOG_LEVEL}. Error: {e}")
audit_level = AuditLevel.NONE
if audit_level != AuditLevel.NONE:
app.add_middleware(
AuditLoggingMiddleware,
audit_level=audit_level,
excluded_paths=AUDIT_EXCLUDED_PATHS,
max_body_size=MAX_BODY_LOG_SIZE,
)
2024-12-12 10:36:59 +08:00
##################################
#
# Chat Endpoints
#
##################################
2024-05-30 13:03:22 +08:00
2024-12-13 12:22:17 +08:00
@app.get("/api/models")
2025-08-11 04:45:59 +08:00
@app.get("/api/v1/models") # Experimental: Compatibility with OpenAI API
2025-06-28 19:12:31 +08:00
async def get_models(
request: Request, refresh: bool = False, user=Depends(get_verified_user)
):
2024-12-13 12:22:17 +08:00
def get_filtered_models(models, user):
filtered_models = []
for model in models:
if model.get("arena"):
if has_access(
user.id,
type="read",
access_control=model.get("info", {})
.get("meta", {})
.get("access_control", {}),
2024-05-25 11:29:13 +08:00
):
2024-12-13 12:22:17 +08:00
filtered_models.append(model)
continue
2025-08-13 23:18:30 +08:00
2024-12-13 12:22:17 +08:00
model_info = Models.get_model_by_id(model["id"])
if model_info:
2025-08-12 05:41:49 +08:00
if (
(user.role == "admin" and BYPASS_ADMIN_ACCESS_CONTROL)
2025-08-13 23:18:30 +08:00
or user.id == model_info.user_id
or has_access(
user.id, type="read", access_control=model_info.access_control
)
2024-12-13 12:22:17 +08:00
):
filtered_models.append(model)
2025-08-13 23:18:30 +08:00
2024-12-13 12:22:17 +08:00
return filtered_models
2024-05-29 03:04:19 +08:00
2025-06-28 23:15:52 +08:00
all_models = await get_all_models(request, refresh=refresh, user=user)
2025-03-12 04:37:30 +08:00
models = []
for model in all_models:
# Filter out filter pipelines
if "pipeline" in model and model["pipeline"].get("type", None) == "filter":
continue
2025-04-14 08:28:09 +08:00
try:
model_tags = [
tag.get("name")
for tag in model.get("info", {}).get("meta", {}).get("tags", [])
]
tags = [tag.get("name") for tag in model.get("tags", [])]
tags = list(set(model_tags + tags))
model["tags"] = [{"name": tag} for tag in tags]
except Exception as e:
log.debug(f"Error processing model tags: {e}")
model["tags"] = []
pass
2024-05-29 03:04:19 +08:00
2025-03-12 04:37:30 +08:00
models.append(model)
2024-05-30 13:18:27 +08:00
2024-12-13 12:22:17 +08:00
model_order_list = request.app.state.config.MODEL_ORDER_LIST
if model_order_list:
model_order_dict = {model_id: i for i, model_id in enumerate(model_order_list)}
# Sort models by order list priority, with fallback for those not in the list
models.sort(
2025-08-13 22:18:30 +08:00
key=lambda model: (
model_order_dict.get(model.get("id", ""), float("inf")),
(model.get("name", "") or ""),
2025-08-13 22:18:30 +08:00
)
2024-05-30 13:18:27 +08:00
)
2024-05-29 03:32:49 +08:00
2024-11-16 20:41:07 +08:00
# Filter out models that the user does not have access to
2025-08-13 23:18:30 +08:00
if (
user.role == "user"
or (user.role == "admin" and not BYPASS_ADMIN_ACCESS_CONTROL)
2025-08-13 23:18:30 +08:00
) and not BYPASS_MODEL_ACCESS_CONTROL:
2024-12-13 12:22:17 +08:00
models = get_filtered_models(models, user)
2024-05-29 03:32:49 +08:00
2024-11-23 12:11:46 +08:00
log.debug(
2025-07-31 20:17:33 +08:00
f"/api/models returned filtered models accessible to the user: {json.dumps([model.get('id') for model in models])}"
2024-11-23 12:11:46 +08:00
)
2024-05-24 16:40:48 +08:00
return {"data": models}
2024-05-29 03:32:49 +08:00
2024-11-16 11:14:24 +08:00
@app.get("/api/models/base")
2024-12-12 12:26:24 +08:00
async def get_base_models(request: Request, user=Depends(get_admin_user)):
models = await get_all_base_models(request, user=user)
2024-11-16 11:14:24 +08:00
return {"data": models}
2024-05-29 03:32:49 +08:00
2024-05-29 04:05:31 +08:00
2025-06-05 04:37:31 +08:00
##################################
# Embeddings
##################################
@app.post("/api/embeddings")
2025-08-11 04:45:59 +08:00
@app.post("/api/v1/embeddings") # Experimental: Compatibility with OpenAI API
2025-06-05 04:37:31 +08:00
async def embeddings(
request: Request, form_data: dict, user=Depends(get_verified_user)
):
"""
OpenAI-compatible embeddings endpoint.
This handler:
- Performs user/model checks and dispatches to the correct backend.
- Supports OpenAI, Ollama, arena models, pipelines, and any compatible provider.
Args:
request (Request): Request context.
form_data (dict): OpenAI-like payload (e.g., {"model": "...", "input": [...]})
user (UserModel): Authenticated user.
Returns:
dict: OpenAI-compatible embeddings response.
"""
# Make sure models are loaded in app state
if not request.app.state.MODELS:
await get_all_models(request, user=user)
# Use generic dispatcher in utils.embeddings
return await generate_embeddings(request, form_data, user)
2024-12-12 10:05:42 +08:00
@app.post("/api/chat/completions")
2025-08-11 04:45:59 +08:00
@app.post("/api/v1/chat/completions") # Experimental: Compatibility with OpenAI API
2024-12-13 12:22:17 +08:00
async def chat_completion(
2024-12-12 12:39:55 +08:00
request: Request,
2024-12-12 10:05:42 +08:00
form_data: dict,
user=Depends(get_verified_user),
):
2024-12-13 14:32:28 +08:00
if not request.app.state.MODELS:
await get_all_models(request, user=user)
2024-12-13 14:28:42 +08:00
2025-08-10 17:48:12 +08:00
model_id = form_data.get("model", None)
2025-02-13 14:56:33 +08:00
model_item = form_data.pop("model_item", {})
2024-12-19 17:00:32 +08:00
tasks = form_data.pop("background_tasks", None)
2025-02-13 14:56:33 +08:00
metadata = {}
2024-12-13 14:28:42 +08:00
try:
2025-02-13 14:56:33 +08:00
if not model_item.get("direct", False):
if model_id not in request.app.state.MODELS:
raise Exception("Model not found")
model = request.app.state.MODELS[model_id]
model_info = Models.get_model_by_id(model_id)
# Check if user has access to the model
if not BYPASS_MODEL_ACCESS_CONTROL and (
user.role != "admin" or not BYPASS_ADMIN_ACCESS_CONTROL
):
2025-02-13 14:56:33 +08:00
try:
check_model_access(user, model)
except Exception as e:
raise e
else:
model = model_item
model_info = None
request.state.direct = True
request.state.model = model
2024-05-29 03:32:49 +08:00
2025-08-10 05:29:51 +08:00
model_info_params = (
model_info.params.model_dump() if model_info and model_info.params else {}
)
# Chat Params
stream_delta_chunk_size = form_data.get("params", {}).get(
"stream_delta_chunk_size"
)
2025-08-27 21:24:16 +08:00
reasoning_tags = form_data.get("params", {}).get("reasoning_tags")
2025-08-10 05:29:51 +08:00
# Model Params
2025-08-10 05:31:07 +08:00
if model_info_params.get("stream_delta_chunk_size"):
2025-08-10 05:29:51 +08:00
stream_delta_chunk_size = model_info_params.get("stream_delta_chunk_size")
2025-08-27 21:24:16 +08:00
if model_info_params.get("reasoning_tags") is not None:
reasoning_tags = model_info_params.get("reasoning_tags")
2024-12-19 10:04:56 +08:00
metadata = {
2024-12-19 17:00:32 +08:00
"user_id": user.id,
2024-12-19 10:04:56 +08:00
"chat_id": form_data.pop("chat_id", None),
"message_id": form_data.pop("id", None),
"session_id": form_data.pop("session_id", None),
2025-05-17 03:36:33 +08:00
"filter_ids": form_data.pop("filter_ids", []),
2024-12-19 10:04:56 +08:00
"tool_ids": form_data.get("tool_ids", None),
2025-03-27 17:27:56 +08:00
"tool_servers": form_data.pop("tool_servers", None),
2024-12-19 10:04:56 +08:00
"files": form_data.get("files", None),
2025-05-14 19:22:38 +08:00
"features": form_data.get("features", {}),
"variables": form_data.get("variables", {}),
2025-03-01 22:56:24 +08:00
"model": model,
2025-02-13 14:56:33 +08:00
"direct": model_item.get("direct", False),
"params": {
"stream_delta_chunk_size": stream_delta_chunk_size,
2025-08-27 21:24:16 +08:00
"reasoning_tags": reasoning_tags,
"function_calling": (
"native"
if (
form_data.get("params", {}).get("function_calling") == "native"
2025-08-10 05:29:51 +08:00
or model_info_params.get("function_calling") == "native"
)
else "default"
),
},
2024-12-19 10:04:56 +08:00
}
2025-02-13 16:34:45 +08:00
2025-08-10 01:10:12 +08:00
if metadata.get("chat_id") and (user and user.role != "admin"):
2025-08-13 23:18:30 +08:00
if metadata["chat_id"] != "local":
chat = Chats.get_chat_by_id_and_user_id(metadata["chat_id"], user.id)
if chat is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=ERROR_MESSAGES.DEFAULT(),
)
2025-08-10 01:10:12 +08:00
2025-02-13 14:56:33 +08:00
request.state.metadata = metadata
2024-12-19 10:04:56 +08:00
form_data["metadata"] = metadata
2024-12-13 14:28:42 +08:00
except Exception as e:
2025-08-19 05:24:53 +08:00
log.debug(f"Error processing chat metadata: {e}")
2024-05-29 03:32:49 +08:00
raise HTTPException(
2024-12-13 14:28:42 +08:00
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
2024-05-29 03:32:49 +08:00
)
2025-08-19 05:24:53 +08:00
async def process_chat(request, form_data, user, metadata, model):
try:
form_data, metadata, events = await process_chat_payload(
request, form_data, user, metadata, model
)
2025-02-05 13:01:53 +08:00
2025-08-19 05:24:53 +08:00
response = await chat_completion_handler(request, form_data, user)
if metadata.get("chat_id") and metadata.get("message_id"):
try:
Chats.upsert_message_to_chat_by_id_and_message_id(
metadata["chat_id"],
metadata["message_id"],
{
"model": model_id,
},
)
except:
pass
return await process_chat_response(
request, response, form_data, user, metadata, model, events, tasks
)
except asyncio.CancelledError:
log.info("Chat processing was cancelled")
2025-08-13 22:18:30 +08:00
try:
2025-08-19 05:24:53 +08:00
event_emitter = get_event_emitter(metadata)
await event_emitter(
2025-09-01 18:14:20 +08:00
{"type": "chat:tasks:cancel"},
2025-08-13 22:18:30 +08:00
)
2025-08-19 05:24:53 +08:00
except Exception as e:
2025-08-13 22:18:30 +08:00
pass
2025-08-19 05:24:53 +08:00
except Exception as e:
log.debug(f"Error processing chat payload: {e}")
if metadata.get("chat_id") and metadata.get("message_id"):
# Update the chat message with the error
try:
Chats.upsert_message_to_chat_by_id_and_message_id(
metadata["chat_id"],
metadata["message_id"],
{
"error": {"content": str(e)},
},
)
2025-09-01 18:14:20 +08:00
event_emitter = get_event_emitter(metadata)
await event_emitter(
{
"type": "chat:message:error",
"data": {"error": {"content": str(e)}},
}
)
await event_emitter(
{"type": "chat:tasks:cancel"},
)
2025-08-19 05:24:53 +08:00
except:
pass
2025-06-16 17:45:36 +08:00
2025-08-19 05:24:53 +08:00
if (
metadata.get("session_id")
and metadata.get("chat_id")
and metadata.get("message_id")
):
# Asynchronous Chat Processing
task_id, _ = await create_task(
request.app.state.redis,
process_chat(request, form_data, user, metadata, model),
id=metadata["chat_id"],
2024-05-29 03:32:49 +08:00
)
2025-08-19 05:24:53 +08:00
return {"status": True, "task_id": task_id}
else:
return await process_chat(request, form_data, user, metadata, model)
2024-05-29 03:32:49 +08:00
2024-12-13 14:28:42 +08:00
# Alias for chat_completion (Legacy)
2024-12-13 12:22:17 +08:00
generate_chat_completions = chat_completion
generate_chat_completion = chat_completion
2024-12-12 10:05:42 +08:00
@app.post("/api/chat/completed")
2024-12-12 11:52:46 +08:00
async def chat_completed(
request: Request, form_data: dict, user=Depends(get_verified_user)
2024-05-29 03:32:49 +08:00
):
2024-05-30 13:18:27 +08:00
try:
2025-02-13 14:56:33 +08:00
model_item = form_data.pop("model_item", {})
if model_item.get("direct", False):
request.state.direct = True
request.state.model = model_item
2024-12-13 12:22:17 +08:00
return await chat_completed_handler(request, form_data, user)
2024-12-12 11:52:46 +08:00
except Exception as e:
2024-12-13 12:22:17 +08:00
raise HTTPException(
2024-12-12 11:52:46 +08:00
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
2024-05-30 13:18:27 +08:00
)
2024-05-29 03:32:49 +08:00
2024-12-12 10:05:42 +08:00
@app.post("/api/chat/actions/{action_id}")
2024-12-12 12:39:55 +08:00
async def chat_action(
request: Request, action_id: str, form_data: dict, user=Depends(get_verified_user)
):
2024-12-13 12:22:17 +08:00
try:
2025-02-13 14:56:33 +08:00
model_item = form_data.pop("model_item", {})
if model_item.get("direct", False):
request.state.direct = True
request.state.model = model_item
2024-12-13 12:22:17 +08:00
return await chat_action_handler(request, action_id, form_data, user)
2024-05-30 13:18:27 +08:00
except Exception as e:
2024-05-29 03:32:49 +08:00
raise HTTPException(
2024-12-13 12:22:17 +08:00
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
2024-05-29 03:32:49 +08:00
)
2024-12-19 17:00:32 +08:00
@app.post("/api/tasks/stop/{task_id}")
2025-06-09 00:58:31 +08:00
async def stop_task_endpoint(
request: Request, task_id: str, user=Depends(get_verified_user)
):
2024-12-19 17:00:32 +08:00
try:
2025-07-11 21:53:53 +08:00
result = await stop_task(request.app.state.redis, task_id)
2024-12-19 17:00:32 +08:00
return result
except ValueError as e:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
@app.get("/api/tasks")
2025-06-09 00:58:31 +08:00
async def list_tasks_endpoint(request: Request, user=Depends(get_verified_user)):
2025-07-11 21:53:53 +08:00
return {"tasks": await list_tasks(request.app.state.redis)}
2025-04-13 11:51:02 +08:00
@app.get("/api/tasks/chat/{chat_id}")
2025-06-09 00:58:31 +08:00
async def list_tasks_by_chat_id_endpoint(
request: Request, chat_id: str, user=Depends(get_verified_user)
):
2025-04-13 11:51:02 +08:00
chat = Chats.get_chat_by_id(chat_id)
if chat is None or chat.user_id != user.id:
return {"task_ids": []}
2025-07-11 22:14:48 +08:00
task_ids = await list_task_ids_by_item_id(request.app.state.redis, chat_id)
2025-04-13 11:51:02 +08:00
log.debug(f"Task IDs for chat {chat_id}: {task_ids}")
2025-04-13 11:51:02 +08:00
return {"task_ids": task_ids}
2024-12-19 17:00:32 +08:00
2024-06-20 16:51:39 +08:00
##################################
#
# Config Endpoints
#
##################################
2024-02-22 10:12:01 +08:00
@app.get("/api/config")
2024-08-19 22:49:40 +08:00
async def get_app_config(request: Request):
user = None
token = None
auth_header = request.headers.get("Authorization")
if auth_header:
cred = get_http_authorization_cred(auth_header)
if cred:
token = cred.credentials
if not token and "token" in request.cookies:
2024-08-19 22:49:40 +08:00
token = request.cookies.get("token")
if token:
2024-11-06 13:14:02 +08:00
try:
data = decode_token(token)
except Exception as e:
log.debug(e)
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid token",
)
2024-08-19 22:49:40 +08:00
if data is not None and "id" in data:
user = Users.get_user_by_id(data["id"])
2025-03-04 14:24:19 +08:00
user_count = Users.get_num_users()
2024-11-06 12:47:23 +08:00
onboarding = False
2025-03-04 14:24:19 +08:00
2024-11-03 19:00:28 +08:00
if user is None:
2024-11-06 12:47:23 +08:00
onboarding = user_count == 0
2024-11-03 19:00:28 +08:00
2024-02-22 10:12:01 +08:00
return {
2024-11-06 12:47:23 +08:00
**({"onboarding": True} if onboarding else {}),
2024-02-22 10:12:01 +08:00
"status": True,
2025-02-16 16:11:18 +08:00
"name": app.state.WEBUI_NAME,
2024-02-23 16:30:26 +08:00
"version": VERSION,
2024-07-01 05:48:05 +08:00
"default_locale": str(DEFAULT_LOCALE),
2024-08-19 22:49:40 +08:00
"oauth": {
"providers": {
name: config.get("name", name)
for name, config in OAUTH_PROVIDERS.items()
}
},
2024-05-27 04:02:40 +08:00
"features": {
"auth": WEBUI_AUTH,
2024-12-12 10:53:38 +08:00
"auth_trusted_header": bool(app.state.AUTH_TRUSTED_EMAIL_HEADER),
2025-07-31 20:43:37 +08:00
"enable_signup_password_confirmation": ENABLE_SIGNUP_PASSWORD_CONFIRMATION,
2024-12-12 10:53:38 +08:00
"enable_ldap": app.state.config.ENABLE_LDAP,
"enable_api_key": app.state.config.ENABLE_API_KEY,
"enable_signup": app.state.config.ENABLE_SIGNUP,
"enable_login_form": app.state.config.ENABLE_LOGIN_FORM,
2024-12-19 10:32:19 +08:00
"enable_websocket": ENABLE_WEBSOCKET_SUPPORT,
"enable_version_update_check": ENABLE_VERSION_UPDATE_CHECK,
2024-08-19 22:49:40 +08:00
**(
{
2025-02-12 15:12:00 +08:00
"enable_direct_connections": app.state.config.ENABLE_DIRECT_CONNECTIONS,
2024-12-23 12:02:14 +08:00
"enable_channels": app.state.config.ENABLE_CHANNELS,
2025-05-01 20:39:36 +08:00
"enable_notes": app.state.config.ENABLE_NOTES,
2025-04-13 07:33:36 +08:00
"enable_web_search": app.state.config.ENABLE_WEB_SEARCH,
"enable_code_execution": app.state.config.ENABLE_CODE_EXECUTION,
2025-02-10 18:28:01 +08:00
"enable_code_interpreter": app.state.config.ENABLE_CODE_INTERPRETER,
2024-12-12 11:52:46 +08:00
"enable_image_generation": app.state.config.ENABLE_IMAGE_GENERATION,
2025-02-10 18:28:01 +08:00
"enable_autocomplete_generation": app.state.config.ENABLE_AUTOCOMPLETE_GENERATION,
2024-12-12 10:53:38 +08:00
"enable_community_sharing": app.state.config.ENABLE_COMMUNITY_SHARING,
"enable_message_rating": app.state.config.ENABLE_MESSAGE_RATING,
2025-03-31 12:31:16 +08:00
"enable_user_webhooks": app.state.config.ENABLE_USER_WEBHOOKS,
2024-08-19 22:49:40 +08:00
"enable_admin_export": ENABLE_ADMIN_EXPORT,
"enable_admin_chat_access": ENABLE_ADMIN_CHAT_ACCESS,
2025-02-10 18:28:01 +08:00
"enable_google_drive_integration": app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
2025-02-24 22:14:10 +08:00
"enable_onedrive_integration": app.state.config.ENABLE_ONEDRIVE_INTEGRATION,
**(
{
"enable_onedrive_personal": app.state.config.ENABLE_ONEDRIVE_PERSONAL,
"enable_onedrive_business": app.state.config.ENABLE_ONEDRIVE_BUSINESS,
}
if app.state.config.ENABLE_ONEDRIVE_INTEGRATION
else {}
),
2024-08-19 22:49:40 +08:00
}
if user is not None
else {}
),
2024-06-08 11:18:48 +08:00
},
2024-08-19 22:49:40 +08:00
**(
{
2024-12-12 10:53:38 +08:00
"default_models": app.state.config.DEFAULT_MODELS,
"default_prompt_suggestions": app.state.config.DEFAULT_PROMPT_SUGGESTIONS,
2025-03-04 18:45:05 +08:00
"user_count": user_count,
2025-02-18 08:25:50 +08:00
"code": {
"engine": app.state.config.CODE_EXECUTION_ENGINE,
},
2024-08-19 22:49:40 +08:00
"audio": {
"tts": {
2024-12-12 11:52:46 +08:00
"engine": app.state.config.TTS_ENGINE,
"voice": app.state.config.TTS_VOICE,
"split_on": app.state.config.TTS_SPLIT_ON,
2024-08-19 22:49:40 +08:00
},
"stt": {
2024-12-12 11:52:46 +08:00
"engine": app.state.config.STT_ENGINE,
2024-08-19 22:49:40 +08:00
},
},
2024-08-27 23:05:24 +08:00
"file": {
2024-12-12 11:52:46 +08:00
"max_size": app.state.config.FILE_MAX_SIZE,
"max_count": app.state.config.FILE_MAX_COUNT,
2025-06-16 20:52:57 +08:00
"image_compression": {
"width": app.state.config.FILE_IMAGE_COMPRESSION_WIDTH,
"height": app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT,
},
2024-08-27 23:05:24 +08:00
},
2024-12-12 10:53:38 +08:00
"permissions": {**app.state.config.USER_PERMISSIONS},
"google_drive": {
"client_id": GOOGLE_DRIVE_CLIENT_ID.value,
"api_key": GOOGLE_DRIVE_API_KEY.value,
},
2025-04-14 23:27:59 +08:00
"onedrive": {
"client_id": ONEDRIVE_CLIENT_ID.value,
"sharepoint_url": ONEDRIVE_SHAREPOINT_URL.value,
"sharepoint_tenant_id": ONEDRIVE_SHAREPOINT_TENANT_ID.value,
2025-04-14 23:27:59 +08:00
},
2025-05-15 00:58:54 +08:00
"ui": {
2025-05-15 01:39:17 +08:00
"pending_user_overlay_title": app.state.config.PENDING_USER_OVERLAY_TITLE,
"pending_user_overlay_content": app.state.config.PENDING_USER_OVERLAY_CONTENT,
2025-05-15 03:53:28 +08:00
"response_watermark": app.state.config.RESPONSE_WATERMARK,
2025-05-15 00:58:54 +08:00
},
2025-03-04 18:45:05 +08:00
"license_metadata": app.state.LICENSE_METADATA,
2025-03-04 14:24:19 +08:00
**(
{
"active_entries": app.state.USER_COUNT,
}
if user.role == "admin"
else {}
),
}
2025-07-28 15:09:48 +08:00
if user is not None and (user.role in ["admin", "user"])
2025-07-12 07:39:58 +08:00
else {
**(
2025-08-14 06:27:24 +08:00
{
"ui": {
"pending_user_overlay_title": app.state.config.PENDING_USER_OVERLAY_TITLE,
"pending_user_overlay_content": app.state.config.PENDING_USER_OVERLAY_CONTENT,
}
}
if user and user.role == "pending"
else {}
2025-08-14 08:50:33 +08:00
),
**(
2025-07-12 07:39:58 +08:00
{
"metadata": {
"login_footer": app.state.LICENSE_METADATA.get(
"login_footer", ""
2025-07-31 22:45:39 +08:00
),
"auth_logo_position": app.state.LICENSE_METADATA.get(
"auth_logo_position", ""
),
2025-07-12 07:39:58 +08:00
}
}
if app.state.LICENSE_METADATA
else {}
2025-08-14 06:27:24 +08:00
),
2025-07-12 07:39:58 +08:00
}
2024-08-19 22:49:40 +08:00
),
2024-02-22 10:12:01 +08:00
}
2024-12-10 16:54:13 +08:00
class UrlForm(BaseModel):
url: str
2024-06-20 16:51:39 +08:00
2024-03-21 09:35:02 +08:00
@app.get("/api/webhook")
async def get_webhook_url(user=Depends(get_admin_user)):
return {
"url": app.state.config.WEBHOOK_URL,
2024-03-21 09:35:02 +08:00
}
@app.post("/api/webhook")
async def update_webhook_url(form_data: UrlForm, user=Depends(get_admin_user)):
app.state.config.WEBHOOK_URL = form_data.url
2024-12-12 10:53:38 +08:00
app.state.WEBHOOK_URL = app.state.config.WEBHOOK_URL
return {"url": app.state.config.WEBHOOK_URL}
2024-03-05 16:59:35 +08:00
@app.get("/api/version")
2024-08-03 21:24:26 +08:00
async def get_app_version():
2024-03-05 16:59:35 +08:00
return {
"version": VERSION,
}
2024-02-26 03:26:58 +08:00
@app.get("/api/version/updates")
2025-02-04 05:42:03 +08:00
async def get_app_latest_release_version(user=Depends(get_verified_user)):
if not ENABLE_VERSION_UPDATE_CHECK:
log.debug(
f"Version update check is disabled, returning current version as latest version"
)
return {"current": VERSION, "latest": VERSION}
2024-02-26 03:26:58 +08:00
try:
2024-09-27 20:38:56 +08:00
timeout = aiohttp.ClientTimeout(total=1)
async with aiohttp.ClientSession(timeout=timeout, trust_env=True) as session:
2024-04-10 14:03:05 +08:00
async with session.get(
2025-05-15 03:33:52 +08:00
"https://api.github.com/repos/open-webui/open-webui/releases/latest",
ssl=AIOHTTP_CLIENT_SESSION_SSL,
2024-04-10 14:03:05 +08:00
) as response:
response.raise_for_status()
data = await response.json()
latest_version = data["tag_name"]
return {"current": VERSION, "latest": latest_version[1:]}
2024-09-30 22:32:38 +08:00
except Exception as e:
log.debug(e)
2024-09-27 20:38:56 +08:00
return {"current": VERSION, "latest": VERSION}
2024-02-26 03:26:58 +08:00
2024-04-10 16:27:19 +08:00
2024-12-10 16:54:13 +08:00
@app.get("/api/changelog")
async def get_app_changelog():
return {key: CHANGELOG[key] for idx, key in enumerate(CHANGELOG) if idx < 5}
2025-06-16 14:42:34 +08:00
@app.get("/api/usage")
async def get_current_usage(user=Depends(get_verified_user)):
"""
Get current usage statistics for Open WebUI.
This is an experimental endpoint and subject to change.
"""
try:
return {"model_ids": get_models_in_use(), "user_ids": get_active_user_ids()}
except Exception as e:
log.error(f"Error getting usage statistics: {e}")
raise HTTPException(status_code=500, detail="Internal Server Error")
############################
# OAuth Login & Callback
############################
# SessionMiddleware is used by authlib for oauth
if len(OAUTH_PROVIDERS) > 0:
app.add_middleware(
SessionMiddleware,
secret_key=WEBUI_SECRET_KEY,
session_cookie="oui-session",
same_site=WEBUI_SESSION_COOKIE_SAME_SITE,
2024-06-07 16:13:42 +08:00
https_only=WEBUI_SESSION_COOKIE_SECURE,
)
@app.get("/oauth/{provider}/login")
async def oauth_login(provider: str, request: Request):
2025-02-16 16:11:18 +08:00
return await oauth_manager.handle_login(request, provider)
# OAuth login logic is as follows:
# 1. Attempt to find a user with matching subject ID, tied to the provider
# 2. If OAUTH_MERGE_ACCOUNTS_BY_EMAIL is true, find a user with the email address provided via OAuth
# - This is considered insecure in general, as OAuth providers do not always verify email addresses
# 3. If there is no user, and ENABLE_OAUTH_SIGNUP is true, create a user
2024-10-14 15:13:26 +08:00
# - Email addresses are considered unique, so we fail registration if the email address is already taken
@app.get("/oauth/{provider}/callback")
async def oauth_callback(provider: str, request: Request, response: Response):
2025-02-16 16:11:18 +08:00
return await oauth_manager.handle_callback(request, provider, response)
@app.get("/manifest.json")
async def get_manifest_json():
2025-04-11 01:35:43 +08:00
if app.state.EXTERNAL_PWA_MANIFEST_URL:
return requests.get(app.state.EXTERNAL_PWA_MANIFEST_URL).json()
else:
return {
"name": app.state.WEBUI_NAME,
"short_name": app.state.WEBUI_NAME,
2025-08-08 18:18:17 +08:00
"description": f"{app.state.WEBUI_NAME} is an open, extensible, user-friendly interface for AI that adapts to your workflow.",
2025-04-11 01:35:43 +08:00
"start_url": "/",
"display": "standalone",
"background_color": "#343541",
"icons": [
{
"src": "/static/logo.png",
"type": "image/png",
"sizes": "500x500",
"purpose": "any",
},
{
"src": "/static/logo.png",
"type": "image/png",
"sizes": "500x500",
"purpose": "maskable",
},
],
}
2024-04-10 16:27:19 +08:00
2024-05-07 08:29:16 +08:00
@app.get("/opensearch.xml")
async def get_opensearch_xml():
xml_content = rf"""
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
2025-02-16 16:11:18 +08:00
<ShortName>{app.state.WEBUI_NAME}</ShortName>
<Description>Search {app.state.WEBUI_NAME}</Description>
2024-05-07 08:29:16 +08:00
<InputEncoding>UTF-8</InputEncoding>
2024-12-26 00:50:57 +08:00
<Image width="16" height="16" type="image/x-icon">{app.state.config.WEBUI_URL}/static/favicon.png</Image>
<Url type="text/html" method="get" template="{app.state.config.WEBUI_URL}/?q={"{searchTerms}"}"/>
<moz:SearchForm>{app.state.config.WEBUI_URL}</moz:SearchForm>
2024-05-07 08:29:16 +08:00
</OpenSearchDescription>
"""
return Response(content=xml_content, media_type="application/xml")
2024-05-16 02:17:18 +08:00
@app.get("/health")
async def healthcheck():
return {"status": True}
@app.get("/health/db")
async def healthcheck_with_db():
Session.execute(text("SELECT 1;")).all()
return {"status": True}
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
@app.get("/cache/{path:path}")
async def serve_cache_file(
path: str,
user=Depends(get_verified_user),
):
file_path = os.path.abspath(os.path.join(CACHE_DIR, path))
# prevent path traversal
if not file_path.startswith(os.path.abspath(CACHE_DIR)):
raise HTTPException(status_code=404, detail="File not found")
if not os.path.isfile(file_path):
raise HTTPException(status_code=404, detail="File not found")
return FileResponse(file_path)
2024-02-24 09:12:19 +08:00
2024-10-08 09:19:13 +08:00
2024-12-18 05:52:57 +08:00
def swagger_ui_html(*args, **kwargs):
2024-12-17 02:00:51 +08:00
return get_swagger_ui_html(
*args,
**kwargs,
swagger_js_url="/static/swagger-ui/swagger-ui-bundle.js",
swagger_css_url="/static/swagger-ui/swagger-ui.css",
2024-12-18 05:51:29 +08:00
swagger_favicon_url="/static/swagger-ui/favicon.png",
2024-12-17 02:00:51 +08:00
)
2024-12-18 05:51:29 +08:00
2024-12-18 05:52:57 +08:00
applications.get_swagger_ui_html = swagger_ui_html
2024-02-24 09:12:19 +08:00
if os.path.exists(FRONTEND_BUILD_DIR):
2024-05-22 12:38:58 +08:00
mimetypes.add_type("text/javascript", ".js")
app.mount(
"/",
SPAStaticFiles(directory=FRONTEND_BUILD_DIR, html=True),
name="spa-static-files",
)
else:
log.warning(
f"Frontend build directory not found at '{FRONTEND_BUILD_DIR}'. Serving API only."
)