From 67c9de8efd5241a2aaa345fbdeddb283099d70de Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 29 Jun 2026 04:42:59 -0500 Subject: [PATCH] refac --- backend/open_webui/config.py | 154 +++++++++++++++------------- backend/open_webui/main.py | 8 +- backend/open_webui/models/config.py | 36 ++++++- 3 files changed, 123 insertions(+), 75 deletions(-) diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index a277510454..7222a478e9 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -38,6 +38,7 @@ from open_webui.models.config import Config async def seed_registered_defaults(): + await Config.rename_prefix('rag.web', 'web') await Config.repair_flattened_dict_configs() await Config.seed_defaults(DEFAULT_CONFIG) @@ -1063,11 +1064,18 @@ YOUTUBE_LOADER_PROXY_URL = os.getenv('YOUTUBE_LOADER_PROXY_URL', '') #################################### -# Web Search (RAG) +# Web Search #################################### ENABLE_WEB_SEARCH = os.getenv('ENABLE_WEB_SEARCH', 'False').lower() == 'true' +ENABLE_WEB_SEARCH_CONFIRMATION = os.getenv('ENABLE_WEB_SEARCH_CONFIRMATION', 'False').lower() == 'true' + +WEB_SEARCH_CONFIRMATION_CONTENT = os.getenv( + 'WEB_SEARCH_CONFIRMATION_CONTENT', + 'Web Search may send your query and retrieved page content to external services.', +) + WEB_SEARCH_ENGINE = os.getenv('WEB_SEARCH_ENGINE', '') BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = os.getenv('BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL', 'False').lower() == 'true' @@ -2764,77 +2772,79 @@ DEFAULT_CONFIG = { 'rag.ollama.api_key': RAG_OLLAMA_API_KEY, 'rag.youtube_loader_language': YOUTUBE_LOADER_LANGUAGE, 'rag.youtube_loader_proxy_url': YOUTUBE_LOADER_PROXY_URL, - 'rag.web.search.enable': ENABLE_WEB_SEARCH, - 'rag.web.search.engine': WEB_SEARCH_ENGINE, - 'rag.web.search.bypass_embedding_and_retrieval': BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL, - 'rag.web.search.bypass_web_loader': BYPASS_WEB_SEARCH_WEB_LOADER, - 'rag.web.search.result_count': WEB_SEARCH_RESULT_COUNT, - 'rag.web.search.domain.filter_list': WEB_SEARCH_DOMAIN_FILTER_LIST, - 'rag.web.search.concurrent_requests': WEB_SEARCH_CONCURRENT_REQUESTS, - 'rag.web.fetch.max_content_length': WEB_FETCH_MAX_CONTENT_LENGTH, - 'rag.web.loader.engine': WEB_LOADER_ENGINE, - 'rag.web.loader.concurrent_requests': WEB_LOADER_CONCURRENT_REQUESTS, - 'rag.web.loader.timeout': WEB_LOADER_TIMEOUT, - 'rag.web.loader.ssl_verification': ENABLE_WEB_LOADER_SSL_VERIFICATION, - 'rag.web.search.trust_env': WEB_SEARCH_TRUST_ENV, - 'rag.web.search.ollama_cloud_api_key': OLLAMA_CLOUD_WEB_SEARCH_API_KEY, - 'rag.web.search.searxng_query_url': SEARXNG_QUERY_URL, - 'rag.web.search.searxng_language': SEARXNG_LANGUAGE, - 'rag.web.search.yacy_query_url': YACY_QUERY_URL, - 'rag.web.search.yacy_username': YACY_USERNAME, - 'rag.web.search.yacy_password': YACY_PASSWORD, - 'rag.web.search.google_pse_api_key': GOOGLE_PSE_API_KEY, - 'rag.web.search.google_pse_engine_id': GOOGLE_PSE_ENGINE_ID, - 'rag.web.search.brave_search_api_key': BRAVE_SEARCH_API_KEY, - 'rag.web.search.brave_search_context_tokens': BRAVE_SEARCH_CONTEXT_TOKENS, - 'rag.web.search.kagi_search_api_key': KAGI_SEARCH_API_KEY, - 'rag.web.search.mojeek_search_api_key': MOJEEK_SEARCH_API_KEY, - 'rag.web.search.bocha_search_api_key': BOCHA_SEARCH_API_KEY, - 'rag.web.search.serpstack_api_key': SERPSTACK_API_KEY, - 'rag.web.search.serpstack_https': SERPSTACK_HTTPS, - 'rag.web.search.serper_api_key': SERPER_API_KEY, - 'rag.web.search.serply_api_key': SERPLY_API_KEY, - 'rag.web.search.serphouse_api_key': SERPHOUSE_API_KEY, - 'rag.web.search.serphouse_domain': SERPHOUSE_DOMAIN, - 'rag.web.search.ddgs_backend': DDGS_BACKEND, - 'rag.web.search.jina_api_key': JINA_API_KEY, - 'rag.web.search.jina_api_base_url': JINA_API_BASE_URL, - 'rag.web.search.searchapi_api_key': SEARCHAPI_API_KEY, - 'rag.web.search.searchapi_engine': SEARCHAPI_ENGINE, - 'rag.web.search.serpapi_api_key': SERPAPI_API_KEY, - 'rag.web.search.serpapi_engine': SERPAPI_ENGINE, - 'rag.web.search.bing_search_v7_endpoint': BING_SEARCH_V7_ENDPOINT, - 'rag.web.search.bing_search_v7_subscription_key': BING_SEARCH_V7_SUBSCRIPTION_KEY, - 'rag.web.search.azure_ai_search_api_key': AZURE_AI_SEARCH_API_KEY, - 'rag.web.search.azure_ai_search_endpoint': AZURE_AI_SEARCH_ENDPOINT, - 'rag.web.search.azure_ai_search_index_name': AZURE_AI_SEARCH_INDEX_NAME, - 'rag.web.search.exa_api_key': EXA_API_KEY, - 'rag.web.search.perplexity_api_key': PERPLEXITY_API_KEY, - 'rag.web.search.perplexity_model': PERPLEXITY_MODEL, - 'rag.web.search.perplexity_search_context_usage': PERPLEXITY_SEARCH_CONTEXT_USAGE, - 'rag.web.search.perplexity_search_api_url': PERPLEXITY_SEARCH_API_URL, - 'rag.web.search.microsoft_web_iq_api_base_url': MICROSOFT_WEB_IQ_API_BASE_URL, - 'rag.web.search.microsoft_web_iq_api_key': MICROSOFT_WEB_IQ_API_KEY, - 'rag.web.search.microsoft_web_iq_language': MICROSOFT_WEB_IQ_LANGUAGE, - 'rag.web.search.sougou_api_sid': SOUGOU_API_SID, - 'rag.web.search.sougou_api_sk': SOUGOU_API_SK, - 'rag.web.search.tavily_api_key': TAVILY_API_KEY, - 'rag.web.search.tavily_extract_depth': TAVILY_EXTRACT_DEPTH, - 'rag.web.loader.playwright_ws_url': PLAYWRIGHT_WS_URL, - 'rag.web.loader.playwright_timeout': PLAYWRIGHT_TIMEOUT, - 'rag.web.loader.firecrawl_api_key': FIRECRAWL_API_KEY, - 'rag.web.loader.firecrawl_api_url': FIRECRAWL_API_BASE_URL, - 'rag.web.loader.firecrawl_timeout': FIRECRAWL_TIMEOUT, - 'rag.web.search.external_web_search_url': EXTERNAL_WEB_SEARCH_URL, - 'rag.web.search.external_web_search_api_key': EXTERNAL_WEB_SEARCH_API_KEY, - 'rag.web.loader.external_web_loader_url': EXTERNAL_WEB_LOADER_URL, - 'rag.web.loader.external_web_loader_api_key': EXTERNAL_WEB_LOADER_API_KEY, - 'rag.web.search.yandex_web_search_url': YANDEX_WEB_SEARCH_URL, - 'rag.web.search.yandex_web_search_api_key': YANDEX_WEB_SEARCH_API_KEY, - 'rag.web.search.yandex_web_search_config': YANDEX_WEB_SEARCH_CONFIG, - 'rag.web.search.youcom_api_key': YOUCOM_API_KEY, - 'rag.web.search.linkup_api_key': LINKUP_API_KEY, - 'rag.web.search.linkup_search_params': LINKUP_SEARCH_PARAMS, + 'web.search.enable': ENABLE_WEB_SEARCH, + 'web.search.confirmation.enable': ENABLE_WEB_SEARCH_CONFIRMATION, + 'web.search.confirmation.content': WEB_SEARCH_CONFIRMATION_CONTENT, + 'web.search.engine': WEB_SEARCH_ENGINE, + 'web.search.bypass_embedding_and_retrieval': BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL, + 'web.search.bypass_web_loader': BYPASS_WEB_SEARCH_WEB_LOADER, + 'web.search.result_count': WEB_SEARCH_RESULT_COUNT, + 'web.search.domain.filter_list': WEB_SEARCH_DOMAIN_FILTER_LIST, + 'web.search.concurrent_requests': WEB_SEARCH_CONCURRENT_REQUESTS, + 'web.fetch.max_content_length': WEB_FETCH_MAX_CONTENT_LENGTH, + 'web.loader.engine': WEB_LOADER_ENGINE, + 'web.loader.concurrent_requests': WEB_LOADER_CONCURRENT_REQUESTS, + 'web.loader.timeout': WEB_LOADER_TIMEOUT, + 'web.loader.ssl_verification': ENABLE_WEB_LOADER_SSL_VERIFICATION, + 'web.search.trust_env': WEB_SEARCH_TRUST_ENV, + 'web.search.ollama_cloud_api_key': OLLAMA_CLOUD_WEB_SEARCH_API_KEY, + 'web.search.searxng_query_url': SEARXNG_QUERY_URL, + 'web.search.searxng_language': SEARXNG_LANGUAGE, + 'web.search.yacy_query_url': YACY_QUERY_URL, + 'web.search.yacy_username': YACY_USERNAME, + 'web.search.yacy_password': YACY_PASSWORD, + 'web.search.google_pse_api_key': GOOGLE_PSE_API_KEY, + 'web.search.google_pse_engine_id': GOOGLE_PSE_ENGINE_ID, + 'web.search.brave_search_api_key': BRAVE_SEARCH_API_KEY, + 'web.search.brave_search_context_tokens': BRAVE_SEARCH_CONTEXT_TOKENS, + 'web.search.kagi_search_api_key': KAGI_SEARCH_API_KEY, + 'web.search.mojeek_search_api_key': MOJEEK_SEARCH_API_KEY, + 'web.search.bocha_search_api_key': BOCHA_SEARCH_API_KEY, + 'web.search.serpstack_api_key': SERPSTACK_API_KEY, + 'web.search.serpstack_https': SERPSTACK_HTTPS, + 'web.search.serper_api_key': SERPER_API_KEY, + 'web.search.serply_api_key': SERPLY_API_KEY, + 'web.search.serphouse_api_key': SERPHOUSE_API_KEY, + 'web.search.serphouse_domain': SERPHOUSE_DOMAIN, + 'web.search.ddgs_backend': DDGS_BACKEND, + 'web.search.jina_api_key': JINA_API_KEY, + 'web.search.jina_api_base_url': JINA_API_BASE_URL, + 'web.search.searchapi_api_key': SEARCHAPI_API_KEY, + 'web.search.searchapi_engine': SEARCHAPI_ENGINE, + 'web.search.serpapi_api_key': SERPAPI_API_KEY, + 'web.search.serpapi_engine': SERPAPI_ENGINE, + 'web.search.bing_search_v7_endpoint': BING_SEARCH_V7_ENDPOINT, + 'web.search.bing_search_v7_subscription_key': BING_SEARCH_V7_SUBSCRIPTION_KEY, + 'web.search.azure_ai_search_api_key': AZURE_AI_SEARCH_API_KEY, + 'web.search.azure_ai_search_endpoint': AZURE_AI_SEARCH_ENDPOINT, + 'web.search.azure_ai_search_index_name': AZURE_AI_SEARCH_INDEX_NAME, + 'web.search.exa_api_key': EXA_API_KEY, + 'web.search.perplexity_api_key': PERPLEXITY_API_KEY, + 'web.search.perplexity_model': PERPLEXITY_MODEL, + 'web.search.perplexity_search_context_usage': PERPLEXITY_SEARCH_CONTEXT_USAGE, + 'web.search.perplexity_search_api_url': PERPLEXITY_SEARCH_API_URL, + 'web.search.microsoft_web_iq_api_base_url': MICROSOFT_WEB_IQ_API_BASE_URL, + 'web.search.microsoft_web_iq_api_key': MICROSOFT_WEB_IQ_API_KEY, + 'web.search.microsoft_web_iq_language': MICROSOFT_WEB_IQ_LANGUAGE, + 'web.search.sougou_api_sid': SOUGOU_API_SID, + 'web.search.sougou_api_sk': SOUGOU_API_SK, + 'web.search.tavily_api_key': TAVILY_API_KEY, + 'web.search.tavily_extract_depth': TAVILY_EXTRACT_DEPTH, + 'web.loader.playwright_ws_url': PLAYWRIGHT_WS_URL, + 'web.loader.playwright_timeout': PLAYWRIGHT_TIMEOUT, + 'web.loader.firecrawl_api_key': FIRECRAWL_API_KEY, + 'web.loader.firecrawl_api_url': FIRECRAWL_API_BASE_URL, + 'web.loader.firecrawl_timeout': FIRECRAWL_TIMEOUT, + 'web.search.external_web_search_url': EXTERNAL_WEB_SEARCH_URL, + 'web.search.external_web_search_api_key': EXTERNAL_WEB_SEARCH_API_KEY, + 'web.loader.external_web_loader_url': EXTERNAL_WEB_LOADER_URL, + 'web.loader.external_web_loader_api_key': EXTERNAL_WEB_LOADER_API_KEY, + 'web.search.yandex_web_search_url': YANDEX_WEB_SEARCH_URL, + 'web.search.yandex_web_search_api_key': YANDEX_WEB_SEARCH_API_KEY, + 'web.search.yandex_web_search_config': YANDEX_WEB_SEARCH_CONFIG, + 'web.search.youcom_api_key': YOUCOM_API_KEY, + 'web.search.linkup_api_key': LINKUP_API_KEY, + 'web.search.linkup_search_params': LINKUP_SEARCH_PARAMS, 'image_generation.enable': ENABLE_IMAGE_GENERATION, 'image_generation.engine': IMAGE_GENERATION_ENGINE, 'image_generation.model': IMAGE_GENERATION_MODEL, diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index 166ee55b3d..aa93d27328 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -1867,7 +1867,9 @@ async def get_app_config(request: Request): 'calendar.enable', 'automations.enable', 'notes.enable', - 'rag.web.search.enable', + 'web.search.enable', + 'web.search.confirmation.enable', + 'web.search.confirmation.content', 'code_execution.enable', 'code_interpreter.enable', 'image_generation.enable', @@ -1933,7 +1935,9 @@ async def get_app_config(request: Request): 'enable_calendar': config.get('calendar.enable'), 'enable_automations': config.get('automations.enable'), 'enable_notes': config.get('notes.enable'), - 'enable_web_search': config.get('rag.web.search.enable'), + 'enable_web_search': config.get('web.search.enable'), + 'enable_web_search_confirmation': config.get('web.search.confirmation.enable'), + 'web_search_confirmation_content': config.get('web.search.confirmation.content'), 'enable_code_execution': config.get('code_execution.enable'), 'enable_code_interpreter': config.get('code_interpreter.enable'), 'enable_image_generation': config.get('image_generation.enable'), diff --git a/backend/open_webui/models/config.py b/backend/open_webui/models/config.py index 9e971e2c74..86d325c894 100644 --- a/backend/open_webui/models/config.py +++ b/backend/open_webui/models/config.py @@ -25,7 +25,7 @@ DICT_CONFIG_KEY_ALIASES = { 'ollama.api_configs': ('OLLAMA_API_CONFIGS',), 'rag.mineru_params': ('MINERU_PARAMS',), 'rag.docling_params': ('DOCLING_PARAMS',), - 'rag.web.search.linkup_search_params': ('LINKUP_SEARCH_PARAMS',), + 'web.search.linkup_search_params': ('LINKUP_SEARCH_PARAMS',), 'image_generation.automatic1111.api_params': ('AUTOMATIC1111_PARAMS',), 'image_generation.openai.params': ('IMAGES_OPENAI_API_PARAMS',), 'audio.tts.openai.params': ('AUDIO_TTS_OPENAI_PARAMS',), @@ -240,6 +240,40 @@ class Config(Base): await db.commit() log.info('Seeded %d new config defaults', new_count) + @staticmethod + async def rename_prefix(old_prefix: str, new_prefix: str) -> None: + """Move persisted config keys from one dotted prefix to another.""" + if not Config.PERSISTENT_ENABLED: + return + + async with get_async_db() as db: + result = await db.execute(select(Config).where(Config.key.like(f'{old_prefix}.%'))) + rows = result.scalars().all() + if not rows: + return + + now = int(time.time()) + moved_count = 0 + deleted_count = 0 + for row in rows: + new_key = f'{new_prefix}.{row.key.removeprefix(f"{old_prefix}.")}' + existing = await db.get(Config, new_key) + if existing is None: + db.add(Config(key=new_key, value=row.value, updated_at=now)) + moved_count += 1 + else: + deleted_count += 1 + await db.delete(row) + + await db.commit() + log.info( + 'Renamed %d config keys from %s.* to %s.*; deleted %d old duplicates', + moved_count, + old_prefix, + new_prefix, + deleted_count, + ) + @staticmethod async def repair_flattened_dict_configs() -> None: """Reassemble dict config values flattened by the per-key migration."""