Coverage for open_webui/config.py: 75%

1172 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 05:07 +0000

1from __future__ import annotations 

2 

3import base64 

4import logging 

5import os 

6import shutil 

7import socket 

8from concurrent.futures import ThreadPoolExecutor 

9from datetime import datetime 

10from pathlib import Path 

11from typing import Optional, Union 

12from urllib.parse import urlparse 

13 

14import redis 

15import requests 

16from authlib.integrations.starlette_client import OAuth 

17from pydantic import BaseModel 

18 

19from open_webui.env import ( 

20 USE_SLIM, 

21 DATA_DIR, 

22 DATABASE_URL, 

23 ENABLE_ADMIN_CHAT_ACCESS, 

24 ENABLE_DB_MIGRATIONS, 

25 ENV, 

26 FRONTEND_BUILD_DIR, 

27 OFFLINE_MODE, 

28 OPEN_WEBUI_DIR, 

29 REDIS_KEY_PREFIX, 

30 REDIS_SENTINEL_HOSTS, 

31 REDIS_SENTINEL_PORT, 

32 REDIS_URL, 

33 WEBUI_AUTH, 

34 WEBUI_FAVICON_URL, 

35 WEBUI_NAME, 

36 log, 

37) 

38from open_webui.models.config import Config 

39from open_webui.utils.json_codec import JSONCodec 

40 

41 

42async def seed_registered_defaults(): 

43 await Config.rename_prefix('rag.web', 'web') 

44 await Config.repair_config_rows() 

45 await Config.seed_defaults(DEFAULT_CONFIG) 

46 

47 

48async def async_reset_config(): 

49 await Config.clear() 

50 

51 

52class EndpointFilter(logging.Filter): 

53 def filter(self, record: logging.LogRecord) -> bool: 

54 return record.getMessage().find('/health') == -1 

55 

56 

57logging.getLogger('uvicorn.access').addFilter(EndpointFilter()) 

58 

59#################################### 

60# Initialization 

61#################################### 

62 

63 

64def run_migrations(): 

65 log.info('Running migrations') 

66 try: 

67 from alembic import command 

68 from alembic.config import Config as AlembicConfig 

69 

70 alembic_cfg = AlembicConfig(OPEN_WEBUI_DIR / 'alembic.ini') 

71 

72 migrations_path = OPEN_WEBUI_DIR / 'migrations' 

73 alembic_cfg.set_main_option('script_location', str(migrations_path)) 

74 

75 command.upgrade(alembic_cfg, 'head') 

76 except Exception as e: 

77 log.exception(f'Error running migrations: {e}') 

78 raise 

79 

80 

81if ENABLE_DB_MIGRATIONS: 81 ↛ 85line 81 didn't jump to line 85 because the condition on line 81 was always true

82 run_migrations() 

83 

84 

85async def import_legacy_config_json(): 

86 """Migrate legacy config.json → database on first run.""" 

87 if not os.path.exists(f'{DATA_DIR}/config.json'): 87 ↛ 89line 87 didn't jump to line 89 because the condition on line 87 was always true

88 return 

89 with open(f'{DATA_DIR}/config.json', 'r') as _f: 

90 await Config.upsert(JSONCodec.loads(_f.read())) 

91 os.rename(f'{DATA_DIR}/config.json', f'{DATA_DIR}/old_config.json') 

92 

93 

94#################################### 

95# Static DIR 

96#################################### 

97 

98STATIC_DIR = Path(os.getenv('STATIC_DIR', OPEN_WEBUI_DIR / 'static')).resolve() 

99 

100try: 

101 if STATIC_DIR.exists(): 101 ↛ 111line 101 didn't jump to line 111 because the condition on line 101 was always true

102 for item in STATIC_DIR.iterdir(): 

103 if item.is_file() or item.is_symlink(): 

104 try: 

105 item.unlink() 

106 except Exception as e: 

107 pass 

108except Exception as e: 

109 pass 

110 

111for file_path in (FRONTEND_BUILD_DIR / 'static').glob('**/*'): 

112 if file_path.is_file(): 112 ↛ 111line 112 didn't jump to line 111 because the condition on line 112 was always true

113 target_path = STATIC_DIR / file_path.relative_to((FRONTEND_BUILD_DIR / 'static')) 

114 target_path.parent.mkdir(parents=True, exist_ok=True) 

115 try: 

116 shutil.copyfile(file_path, target_path) 

117 except Exception as e: 

118 logging.error(f'An error occurred: {e}') 

119 

120# LICENSE covers copied Open WebUI logo/favicon assets. 

121# Do not alter, remove, obscure, or replace them except as LICENSE permits: 

122# https://docs.openwebui.com/license. 

123frontend_favicon = FRONTEND_BUILD_DIR / 'static' / 'favicon.png' 

124 

125if frontend_favicon.exists(): 125 ↛ 131line 125 didn't jump to line 131 because the condition on line 125 was always true

126 try: 

127 shutil.copyfile(frontend_favicon, STATIC_DIR / 'favicon.png') 

128 except Exception as e: 

129 logging.error(f'An error occurred: {e}') 

130 

131frontend_splash = FRONTEND_BUILD_DIR / 'static' / 'splash.png' 

132 

133if frontend_splash.exists(): 133 ↛ 139line 133 didn't jump to line 139 because the condition on line 133 was always true

134 try: 

135 shutil.copyfile(frontend_splash, STATIC_DIR / 'splash.png') 

136 except Exception as e: 

137 logging.error(f'An error occurred: {e}') 

138 

139frontend_loader = FRONTEND_BUILD_DIR / 'static' / 'loader.js' 

140 

141if frontend_loader.exists(): 141 ↛ 150line 141 didn't jump to line 150 because the condition on line 141 was always true

142 try: 

143 shutil.copyfile(frontend_loader, STATIC_DIR / 'loader.js') 

144 except Exception as e: 

145 logging.error(f'An error occurred: {e}') 

146 

147 

148# --- Storage Provider --- 

149 

150STORAGE_PROVIDER = os.getenv('STORAGE_PROVIDER', 'local') # defaults to local, s3 

151STORAGE_LOCAL_CACHE = os.getenv('STORAGE_LOCAL_CACHE', 'true').lower() == 'true' 

152 

153S3_ACCESS_KEY_ID = os.getenv('S3_ACCESS_KEY_ID', None) 

154S3_SECRET_ACCESS_KEY = os.getenv('S3_SECRET_ACCESS_KEY', None) 

155S3_REGION_NAME = os.getenv('S3_REGION_NAME', None) 

156S3_BUCKET_NAME = os.getenv('S3_BUCKET_NAME', None) 

157S3_KEY_PREFIX = os.getenv('S3_KEY_PREFIX', None) 

158S3_ENDPOINT_URL = os.getenv('S3_ENDPOINT_URL', None) 

159S3_USE_ACCELERATE_ENDPOINT = os.getenv('S3_USE_ACCELERATE_ENDPOINT', 'false').lower() == 'true' 

160S3_ADDRESSING_STYLE = os.getenv('S3_ADDRESSING_STYLE', None) 

161S3_ENABLE_TAGGING = os.getenv('S3_ENABLE_TAGGING', 'false').lower() == 'true' 

162 

163GCS_BUCKET_NAME = os.getenv('GCS_BUCKET_NAME', None) 

164GOOGLE_APPLICATION_CREDENTIALS_JSON = os.getenv('GOOGLE_APPLICATION_CREDENTIALS_JSON', None) 

165 

166AZURE_STORAGE_ENDPOINT = os.getenv('AZURE_STORAGE_ENDPOINT', None) 

167AZURE_STORAGE_CONTAINER_NAME = os.getenv('AZURE_STORAGE_CONTAINER_NAME', None) 

168AZURE_STORAGE_KEY = os.getenv('AZURE_STORAGE_KEY', None) 

169 

170#################################### 

171# File Upload DIR 

172#################################### 

173 

174UPLOAD_DIR = DATA_DIR / 'uploads' 

175UPLOAD_DIR.mkdir(parents=True, exist_ok=True) 

176 

177 

178#################################### 

179# Cache DIR 

180#################################### 

181 

182CACHE_DIR = DATA_DIR / 'cache' 

183CACHE_DIR.mkdir(parents=True, exist_ok=True) 

184 

185 

186#################################### 

187# CUSTOM_NAME (Legacy) 

188#################################### 

189 

190# LICENSE covers this legacy Open WebUI branding path. 

191# Do not alter, remove, obscure, or replace it except as LICENSE permits: 

192# https://docs.openwebui.com/license. 

193CUSTOM_NAME = os.getenv('CUSTOM_NAME', '') 

194 

195if CUSTOM_NAME: 195 ↛ 196line 195 didn't jump to line 196 because the condition on line 195 was never true

196 try: 

197 r = requests.get(f'https://api.openwebui.com/api/v1/custom/{CUSTOM_NAME}') 

198 data = r.json() 

199 if r.ok: 

200 if 'logo' in data: 

201 WEBUI_FAVICON_URL = url = ( 

202 f'https://api.openwebui.com{data["logo"]}' if data['logo'][0] == '/' else data['logo'] 

203 ) 

204 

205 r = requests.get(url, stream=True) 

206 if r.status_code == 200: 

207 with open(f'{STATIC_DIR}/favicon.png', 'wb') as f: 

208 r.raw.decode_content = True 

209 shutil.copyfileobj(r.raw, f) 

210 

211 if 'splash' in data: 

212 url = f'https://api.openwebui.com{data["splash"]}' if data['splash'][0] == '/' else data['splash'] 

213 

214 r = requests.get(url, stream=True) 

215 if r.status_code == 200: 

216 with open(f'{STATIC_DIR}/splash.png', 'wb') as f: 

217 r.raw.decode_content = True 

218 shutil.copyfileobj(r.raw, f) 

219 

220 WEBUI_NAME = data['name'] 

221 except Exception as e: 

222 log.exception(e) 

223 pass 

224 

225 

226#################################### 

227# DIRECT CONNECTIONS 

228#################################### 

229 

230ENABLE_DIRECT_CONNECTIONS = os.getenv('ENABLE_DIRECT_CONNECTIONS', 'False').lower() == 'true' 

231ENABLE_DIRECT_INTEGRATIONS = os.getenv('ENABLE_DIRECT_INTEGRATIONS', 'False').lower() == 'true' 

232 

233#################################### 

234# OLLAMA_BASE_URL 

235#################################### 

236 

237ENABLE_OLLAMA_API = os.getenv('ENABLE_OLLAMA_API', 'True').lower() == 'true' 

238 

239OLLAMA_API_BASE_URL = os.getenv('OLLAMA_API_BASE_URL', 'http://localhost:11434/api') 

240 

241OLLAMA_BASE_URL = os.getenv('OLLAMA_BASE_URL', '') 

242if OLLAMA_BASE_URL: 242 ↛ 247line 242 didn't jump to line 247 because the condition on line 242 was always true

243 # Remove trailing slash 

244 OLLAMA_BASE_URL = OLLAMA_BASE_URL[:-1] if OLLAMA_BASE_URL.endswith('/') else OLLAMA_BASE_URL 

245 

246 

247K8S_FLAG = os.getenv('K8S_FLAG', '') 

248USE_OLLAMA_DOCKER = os.getenv('USE_OLLAMA_DOCKER', 'false') 

249 

250if OLLAMA_BASE_URL == '' and OLLAMA_API_BASE_URL != '': 250 ↛ 251line 250 didn't jump to line 251 because the condition on line 250 was never true

251 OLLAMA_BASE_URL = OLLAMA_API_BASE_URL[:-4] if OLLAMA_API_BASE_URL.endswith('/api') else OLLAMA_API_BASE_URL 

252 

253if ENV == 'prod': 253 ↛ 254line 253 didn't jump to line 254 because the condition on line 253 was never true

254 if OLLAMA_BASE_URL == '/ollama' and not K8S_FLAG: 

255 if USE_OLLAMA_DOCKER.lower() == 'true': 

256 # if you use all-in-one docker container (Open WebUI + Ollama) 

257 # with the docker build arg USE_OLLAMA=true (--build-arg="USE_OLLAMA=true") this only works with http://localhost:11434 

258 OLLAMA_BASE_URL = 'http://localhost:11434' 

259 else: 

260 OLLAMA_BASE_URL = 'http://host.docker.internal:11434' 

261 elif K8S_FLAG: 

262 OLLAMA_BASE_URL = 'http://ollama-service.open-webui.svc.cluster.local:11434' 

263 

264 

265def _resolve_ollama_base_url(url: str) -> str: 

266 """If the default Ollama port (11434) is unreachable, try the fallback port (12434).""" 

267 

268 def reachable(host: str, port: int) -> bool: 

269 try: 

270 with socket.create_connection((host, port), timeout=1.0): 

271 return True 

272 except (OSError, TimeoutError): 

273 return False 

274 

275 host = urlparse(url).hostname or 'localhost' 

276 

277 with ThreadPoolExecutor(max_workers=2) as pool: 

278 default = pool.submit(reachable, host, 11434) 

279 fallback = pool.submit(reachable, host, 12434) 

280 

281 if not default.result() and fallback.result(): 281 ↛ 282line 281 didn't jump to line 282 because the condition on line 281 was never true

282 url = url.replace(':11434', ':12434') 

283 log.info('Ollama port 11434 unreachable on %s, falling back to 12434', host) 

284 elif not default.result(): 284 ↛ 287line 284 didn't jump to line 287 because the condition on line 284 was always true

285 log.info('Ollama ports 11434 and 12434 both unreachable on %s', host) 

286 

287 return url 

288 

289 

290# Auto-resolve Ollama port when no explicit URL was provided by the user. 

291# The Dockerfile default is "/ollama" which the block above rewrites to :11434. 

292if os.getenv('OLLAMA_BASE_URL', '') in ('', '/ollama') and not os.getenv('OLLAMA_BASE_URLS', ''): 292 ↛ 296line 292 didn't jump to line 296 because the condition on line 292 was always true

293 OLLAMA_BASE_URL = _resolve_ollama_base_url(OLLAMA_BASE_URL) 

294 

295 

296OLLAMA_BASE_URLS = os.getenv('OLLAMA_BASE_URLS', '') 

297OLLAMA_BASE_URLS = OLLAMA_BASE_URLS if OLLAMA_BASE_URLS != '' else OLLAMA_BASE_URL 

298 

299OLLAMA_BASE_URLS = [url.strip() for url in OLLAMA_BASE_URLS.split(';')] 

300OLLAMA_BASE_URLS = OLLAMA_BASE_URLS 

301 

302OLLAMA_API_CONFIGS = {} 

303_ollama_api_configs = os.getenv('OLLAMA_API_CONFIGS', '') 

304if _ollama_api_configs: 304 ↛ 305line 304 didn't jump to line 305 because the condition on line 304 was never true

305 try: 

306 parsed = JSONCodec.loads(_ollama_api_configs) 

307 if isinstance(parsed, dict): 

308 OLLAMA_API_CONFIGS = parsed 

309 else: 

310 log.warning('OLLAMA_API_CONFIGS must be a JSON object, ignoring') 

311 except (JSONCodec.JSONDecodeError, TypeError): 

312 log.warning('OLLAMA_API_CONFIGS is not valid JSON, ignoring') 

313 

314#################################### 

315# OPENAI_API 

316#################################### 

317 

318 

319ENABLE_OPENAI_API = os.getenv('ENABLE_OPENAI_API', 'True').lower() == 'true' 

320 

321 

322OPENAI_API_KEY = os.getenv('OPENAI_API_KEY', '') 

323OPENAI_API_BASE_URL = os.getenv('OPENAI_API_BASE_URL', '') 

324 

325GEMINI_API_KEY = os.getenv('GEMINI_API_KEY', '') 

326GEMINI_API_BASE_URL = os.getenv('GEMINI_API_BASE_URL', '') 

327 

328 

329if OPENAI_API_BASE_URL == '': 329 ↛ 332line 329 didn't jump to line 332 because the condition on line 329 was always true

330 OPENAI_API_BASE_URL = 'https://api.openai.com/v1' 

331else: 

332 if OPENAI_API_BASE_URL.endswith('/'): 

333 OPENAI_API_BASE_URL = OPENAI_API_BASE_URL[:-1] 

334 

335OPENAI_API_KEYS = os.getenv('OPENAI_API_KEYS', '') 

336OPENAI_API_KEYS = OPENAI_API_KEYS if OPENAI_API_KEYS != '' else OPENAI_API_KEY 

337 

338OPENAI_API_KEYS = [url.strip() for url in OPENAI_API_KEYS.split(';')] 

339OPENAI_API_KEYS = OPENAI_API_KEYS 

340 

341OPENAI_API_BASE_URLS = os.getenv('OPENAI_API_BASE_URLS', '') 

342OPENAI_API_BASE_URLS = OPENAI_API_BASE_URLS if OPENAI_API_BASE_URLS != '' else OPENAI_API_BASE_URL 

343 

344OPENAI_API_BASE_URLS = [ 

345 url.strip() if url != '' else 'https://api.openai.com/v1' for url in OPENAI_API_BASE_URLS.split(';') 

346] 

347OPENAI_API_BASE_URLS = OPENAI_API_BASE_URLS 

348 

349OPENAI_API_CONFIGS = {} 

350_openai_api_configs = os.getenv('OPENAI_API_CONFIGS', '') 

351if _openai_api_configs: 351 ↛ 352line 351 didn't jump to line 352 because the condition on line 351 was never true

352 try: 

353 parsed = JSONCodec.loads(_openai_api_configs) 

354 if isinstance(parsed, dict): 

355 OPENAI_API_CONFIGS = parsed 

356 else: 

357 log.warning('OPENAI_API_CONFIGS must be a JSON object, ignoring') 

358 except (JSONCodec.JSONDecodeError, TypeError): 

359 log.warning('OPENAI_API_CONFIGS is not valid JSON, ignoring') 

360 

361# Get the actual OpenAI API key based on the base URL 

362OPENAI_API_KEY = '' 

363try: 

364 OPENAI_API_KEY = OPENAI_API_KEYS[OPENAI_API_BASE_URLS.index('https://api.openai.com/v1')] 

365except Exception: 

366 pass 

367OPENAI_API_BASE_URL = 'https://api.openai.com/v1' 

368 

369 

370#################################### 

371# MODELS 

372#################################### 

373 

374ENABLE_BASE_MODELS_CACHE = os.getenv('ENABLE_BASE_MODELS_CACHE', 'False').lower() == 'true' 

375 

376 

377#################################### 

378# TOOL_SERVERS 

379#################################### 

380 

381try: 

382 tool_server_connections = JSONCodec.loads(os.getenv('TOOL_SERVER_CONNECTIONS', '[]')) 

383except Exception as e: 

384 log.exception(f'Error loading TOOL_SERVER_CONNECTIONS: {e}') 

385 tool_server_connections = [] 

386 

387 

388TOOL_SERVER_CONNECTIONS = tool_server_connections 

389 

390OAUTH_CLIENT_TIMEOUT = os.getenv('OAUTH_CLIENT_TIMEOUT', '') 

391 

392#################################### 

393# TERMINAL_SERVER 

394#################################### 

395 

396terminal_server_connections = JSONCodec.loads(os.getenv('TERMINAL_SERVER_CONNECTIONS', '[]')) 

397 

398TERMINAL_SERVER_CONNECTIONS = terminal_server_connections 

399 

400try: 

401 TERMINAL_PROXY_HEADERS = JSONCodec.loads(os.getenv('TERMINAL_PROXY_HEADERS', '{}')) 

402except Exception: 

403 TERMINAL_PROXY_HEADERS = {} 

404 

405#################################### 

406# Code Interpreter 

407#################################### 

408 

409ENABLE_CODE_EXECUTION = os.getenv('ENABLE_CODE_EXECUTION', 'True').lower() == 'true' 

410 

411CODE_EXECUTION_ENGINE = os.getenv('CODE_EXECUTION_ENGINE', 'pyodide') 

412 

413CODE_EXECUTION_JUPYTER_URL = os.getenv('CODE_EXECUTION_JUPYTER_URL', '') 

414 

415CODE_EXECUTION_JUPYTER_AUTH = os.getenv('CODE_EXECUTION_JUPYTER_AUTH', '') 

416 

417CODE_EXECUTION_JUPYTER_AUTH_TOKEN = os.getenv('CODE_EXECUTION_JUPYTER_AUTH_TOKEN', '') 

418 

419 

420CODE_EXECUTION_JUPYTER_AUTH_PASSWORD = os.getenv('CODE_EXECUTION_JUPYTER_AUTH_PASSWORD', '') 

421 

422CODE_EXECUTION_JUPYTER_TIMEOUT = int(os.getenv('CODE_EXECUTION_JUPYTER_TIMEOUT', '60')) 

423 

424ENABLE_CODE_INTERPRETER = os.getenv('ENABLE_CODE_INTERPRETER', 'True').lower() == 'true' 

425 

426ENABLE_MEMORIES = os.getenv('ENABLE_MEMORIES', 'True').lower() == 'true' 

427ENABLE_MEMORY_SYSTEM_CONTEXT = os.getenv('ENABLE_MEMORY_SYSTEM_CONTEXT', 'True').lower() == 'true' 

428ENABLE_MEMORY_BACKGROUND_REVIEW = os.getenv('ENABLE_MEMORY_BACKGROUND_REVIEW', 'False').lower() == 'true' 

429MEMORIES_REVIEW_INTERVAL_TURNS = int(os.getenv('MEMORIES_REVIEW_INTERVAL_TURNS', '10')) 

430MEMORIES_USER_CHAR_LIMIT = int(os.getenv('MEMORIES_USER_CHAR_LIMIT', '2000')) 

431MEMORIES_CONTEXT_CHAR_LIMIT = int(os.getenv('MEMORIES_CONTEXT_CHAR_LIMIT', '2000')) 

432 

433CODE_INTERPRETER_ENGINE = os.getenv('CODE_INTERPRETER_ENGINE', 'pyodide') 

434 

435CODE_INTERPRETER_PROMPT_TEMPLATE = os.getenv('CODE_INTERPRETER_PROMPT_TEMPLATE', '') 

436 

437CODE_INTERPRETER_JUPYTER_URL = os.getenv('CODE_INTERPRETER_JUPYTER_URL', os.getenv('CODE_EXECUTION_JUPYTER_URL', '')) 

438 

439CODE_INTERPRETER_JUPYTER_AUTH = os.getenv( 

440 'CODE_INTERPRETER_JUPYTER_AUTH', 

441 os.getenv('CODE_EXECUTION_JUPYTER_AUTH', ''), 

442) 

443 

444CODE_INTERPRETER_JUPYTER_AUTH_TOKEN = os.getenv( 

445 'CODE_INTERPRETER_JUPYTER_AUTH_TOKEN', 

446 os.getenv('CODE_EXECUTION_JUPYTER_AUTH_TOKEN', ''), 

447) 

448 

449 

450CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD = os.getenv( 

451 'CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD', 

452 os.getenv('CODE_EXECUTION_JUPYTER_AUTH_PASSWORD', ''), 

453) 

454 

455CODE_INTERPRETER_JUPYTER_TIMEOUT = int( 

456 os.getenv( 

457 'CODE_INTERPRETER_JUPYTER_TIMEOUT', 

458 os.getenv('CODE_EXECUTION_JUPYTER_TIMEOUT', '60'), 

459 ) 

460) 

461 

462CODE_INTERPRETER_BLOCKED_MODULES = [ 

463 library.strip() for library in os.getenv('CODE_INTERPRETER_BLOCKED_MODULES', '').split(',') if library.strip() 

464] 

465 

466DEFAULT_CODE_INTERPRETER_PROMPT = """ 

467#### Code Interpreter 

468 

469You have access to a Python code interpreter via: `<code_interpreter type="code" lang="python"></code_interpreter>` 

470 

471- The Python shell runs directly in the user's browser for fast execution of analysis, calculations, or problem-solving. Use it in this response. 

472- You can use a wide array of libraries for data manipulation, visualization, API calls, or any computational task. Think outside the box and harness Python's full potential. 

473- **You must enclose your code within `<code_interpreter type="code" lang="python">` XML tags** and stop right away. If you don't, the code won't execute. 

474- Do NOT use triple backticks (```py ... ```) inside the XML tags — that is markdown formatting, not executable Python code. 

475- **Always print meaningful outputs** (results, tables, summaries, visuals). Avoid implicit outputs; use explicit print statements. 

476- After obtaining output, **provide a concise analysis, interpretation, or next steps** to help the user understand the findings. 

477- If results are unclear or unexpected, refine the code and re-execute. Iterate until you deliver meaningful insights. 

478- **If a link to an image, audio, or any file appears in the output, display it exactly as-is** in your response so the user can access it. Do not modify the link. 

479- Respond in the chat's primary language. Default to English if multilingual. 

480 

481Ensure the code interpreter is effectively utilized to achieve the highest-quality analysis for the user.""" 

482 

483# Appended to the code interpreter prompt only when engine is pyodide (not jupyter) 

484CODE_INTERPRETER_PYODIDE_PROMPT = """ 

485 

486##### Pyodide Environment 

487 

488- This Python environment runs via Pyodide in the browser. **Do not install packages** — `pip install`, `subprocess`, and `micropip.install()` are not available. 

489- If a required library is unavailable, use an alternative approach with available modules. Do not attempt to install anything. 

490 

491##### Persistent File System 

492 

493- User-uploaded files are available at `/mnt/uploads/`. When the user asks you to work with their files, read from this directory. 

494- You can also write output files to `/mnt/uploads/` so the user can access and download them from the file browser. 

495- The file system persists across code executions within the same session. 

496- Use `import os; os.listdir('/mnt/uploads')` to discover available files.""" 

497 

498 

499#################################### 

500# Vector Database 

501#################################### 

502 

503VECTOR_DB = os.getenv('VECTOR_DB', 'pgvector' if USE_SLIM else 'chroma') 

504 

505# Chroma 

506CHROMA_DATA_PATH = f'{DATA_DIR}/vector_db' 

507 

508if VECTOR_DB == 'chroma' and not USE_SLIM: 508 ↛ 528line 508 didn't jump to line 528 because the condition on line 508 was always true

509 import chromadb 

510 

511 CHROMA_TENANT = os.getenv('CHROMA_TENANT', chromadb.DEFAULT_TENANT) 

512 CHROMA_DATABASE = os.getenv('CHROMA_DATABASE', chromadb.DEFAULT_DATABASE) 

513 CHROMA_HTTP_HOST = os.getenv('CHROMA_HTTP_HOST', '') 

514 CHROMA_HTTP_PORT = int(os.getenv('CHROMA_HTTP_PORT', '8000')) 

515 CHROMA_CLIENT_AUTH_PROVIDER = os.getenv('CHROMA_CLIENT_AUTH_PROVIDER', '') 

516 CHROMA_CLIENT_AUTH_CREDENTIALS = os.getenv('CHROMA_CLIENT_AUTH_CREDENTIALS', '') 

517 # Comma-separated list of header=value pairs 

518 CHROMA_HTTP_HEADERS = os.getenv('CHROMA_HTTP_HEADERS', '') 

519 if CHROMA_HTTP_HEADERS: 519 ↛ 520line 519 didn't jump to line 520 because the condition on line 519 was never true

520 CHROMA_HTTP_HEADERS = dict([pair.split('=') for pair in CHROMA_HTTP_HEADERS.split(',')]) 

521 else: 

522 CHROMA_HTTP_HEADERS = None 

523 CHROMA_HTTP_SSL = os.getenv('CHROMA_HTTP_SSL', 'false').lower() == 'true' 

524# this uses the model defined in the Dockerfile ENV variable. If you dont use docker or docker based deployments such as k8s, the default embedding model will be used (sentence-transformers/all-MiniLM-L6-v2) 

525 

526 

527# MariaDB Vector (mariadb-vector) 

528MARIADB_VECTOR_DB_URL = os.getenv('MARIADB_VECTOR_DB_URL', '').strip() 

529 

530MARIADB_VECTOR_INITIALIZE_MAX_VECTOR_LENGTH = int( 

531 os.getenv('MARIADB_VECTOR_INITIALIZE_MAX_VECTOR_LENGTH', '1536').strip() or '1536' 

532) 

533 

534# Distance strategy: 

535# - cosine => vec_distance_cosine(...) 

536# - euclidean => vec_distance_euclidean(...) 

537MARIADB_VECTOR_DISTANCE_STRATEGY = os.getenv('MARIADB_VECTOR_DISTANCE_STRATEGY', 'cosine').strip().lower() 

538 

539# HNSW M parameter (MariaDB VECTOR INDEX ... M=<int>) 

540MARIADB_VECTOR_INDEX_M = int(os.getenv('MARIADB_VECTOR_INDEX_M', '8').strip() or '8') 

541 

542# Pooling (MariaDB-Vector) 

543MARIADB_VECTOR_POOL_SIZE = os.getenv('MARIADB_VECTOR_POOL_SIZE', None) 

544 

545if MARIADB_VECTOR_POOL_SIZE != None: 545 ↛ 546line 545 didn't jump to line 546 because the condition on line 545 was never true

546 try: 

547 MARIADB_VECTOR_POOL_SIZE = int(MARIADB_VECTOR_POOL_SIZE) 

548 except Exception: 

549 MARIADB_VECTOR_POOL_SIZE = None 

550 

551MARIADB_VECTOR_POOL_MAX_OVERFLOW = os.getenv('MARIADB_VECTOR_POOL_MAX_OVERFLOW', 0) 

552 

553if MARIADB_VECTOR_POOL_MAX_OVERFLOW == '': 553 ↛ 554line 553 didn't jump to line 554 because the condition on line 553 was never true

554 MARIADB_VECTOR_POOL_MAX_OVERFLOW = 0 

555else: 

556 try: 

557 MARIADB_VECTOR_POOL_MAX_OVERFLOW = int(MARIADB_VECTOR_POOL_MAX_OVERFLOW) 

558 except Exception: 

559 MARIADB_VECTOR_POOL_MAX_OVERFLOW = 0 

560 

561MARIADB_VECTOR_POOL_TIMEOUT = os.getenv('MARIADB_VECTOR_POOL_TIMEOUT', 30) 

562 

563if MARIADB_VECTOR_POOL_TIMEOUT == '': 563 ↛ 564line 563 didn't jump to line 564 because the condition on line 563 was never true

564 MARIADB_VECTOR_POOL_TIMEOUT = 30 

565else: 

566 try: 

567 MARIADB_VECTOR_POOL_TIMEOUT = int(MARIADB_VECTOR_POOL_TIMEOUT) 

568 except Exception: 

569 MARIADB_VECTOR_POOL_TIMEOUT = 30 

570 

571MARIADB_VECTOR_POOL_RECYCLE = os.getenv('MARIADB_VECTOR_POOL_RECYCLE', 3600) 

572 

573if MARIADB_VECTOR_POOL_RECYCLE == '': 573 ↛ 574line 573 didn't jump to line 574 because the condition on line 573 was never true

574 MARIADB_VECTOR_POOL_RECYCLE = 3600 

575else: 

576 try: 

577 MARIADB_VECTOR_POOL_RECYCLE = int(MARIADB_VECTOR_POOL_RECYCLE) 

578 except Exception: 

579 MARIADB_VECTOR_POOL_RECYCLE = 3600 

580 

581ENABLE_MARIADB_VECTOR = True 

582if VECTOR_DB == 'mariadb-vector': 582 ↛ 583line 582 didn't jump to line 583 because the condition on line 582 was never true

583 if not MARIADB_VECTOR_DB_URL: 

584 ENABLE_MARIADB_VECTOR = False 

585 else: 

586 try: 

587 parsed = urlparse(MARIADB_VECTOR_DB_URL) 

588 scheme = (parsed.scheme or '').lower() 

589 # Require official driver so VECTOR binds as float32 bytes correctly 

590 if scheme != 'mariadb+mariadbconnector': 

591 ENABLE_MARIADB_VECTOR = False 

592 except Exception: 

593 ENABLE_MARIADB_VECTOR = False 

594 

595 

596# Milvus 

597MILVUS_URI = os.getenv('MILVUS_URI', f'{DATA_DIR}/vector_db/milvus.db') 

598MILVUS_DB = os.getenv('MILVUS_DB', 'default') 

599MILVUS_TOKEN = os.getenv('MILVUS_TOKEN', None) 

600MILVUS_INDEX_TYPE = os.getenv('MILVUS_INDEX_TYPE', 'HNSW') 

601MILVUS_METRIC_TYPE = os.getenv('MILVUS_METRIC_TYPE', 'COSINE') 

602MILVUS_HNSW_M = int(os.getenv('MILVUS_HNSW_M', '16')) 

603MILVUS_HNSW_EFCONSTRUCTION = int(os.getenv('MILVUS_HNSW_EFCONSTRUCTION', '100')) 

604MILVUS_IVF_FLAT_NLIST = int(os.getenv('MILVUS_IVF_FLAT_NLIST', '128')) 

605MILVUS_DISKANN_MAX_DEGREE = int(os.getenv('MILVUS_DISKANN_MAX_DEGREE', '56')) 

606MILVUS_DISKANN_SEARCH_LIST_SIZE = int(os.getenv('MILVUS_DISKANN_SEARCH_LIST_SIZE', '100')) 

607ENABLE_MILVUS_MULTITENANCY_MODE = os.getenv('ENABLE_MILVUS_MULTITENANCY_MODE', 'false').lower() == 'true' 

608# Hyphens not allowed, need to use underscores in collection names 

609MILVUS_COLLECTION_PREFIX = os.getenv('MILVUS_COLLECTION_PREFIX', 'open_webui') 

610 

611# Qdrant 

612QDRANT_URI = os.getenv('QDRANT_URI', None) 

613QDRANT_API_KEY = os.getenv('QDRANT_API_KEY', None) 

614QDRANT_ON_DISK = os.getenv('QDRANT_ON_DISK', 'false').lower() == 'true' 

615QDRANT_PREFER_GRPC = os.getenv('QDRANT_PREFER_GRPC', 'false').lower() == 'true' 

616QDRANT_GRPC_PORT = int(os.getenv('QDRANT_GRPC_PORT', '6334')) 

617QDRANT_TIMEOUT = int(os.getenv('QDRANT_TIMEOUT', '5')) 

618QDRANT_HNSW_M = int(os.getenv('QDRANT_HNSW_M', '16')) 

619ENABLE_QDRANT_MULTITENANCY_MODE = os.getenv('ENABLE_QDRANT_MULTITENANCY_MODE', 'true').lower() == 'true' 

620QDRANT_COLLECTION_PREFIX = os.getenv('QDRANT_COLLECTION_PREFIX', 'open-webui') 

621 

622WEAVIATE_HTTP_HOST = os.getenv('WEAVIATE_HTTP_HOST', '') 

623WEAVIATE_GRPC_HOST = os.getenv('WEAVIATE_GRPC_HOST', '') 

624WEAVIATE_HTTP_PORT = int(os.getenv('WEAVIATE_HTTP_PORT', '8080')) 

625WEAVIATE_GRPC_PORT = int(os.getenv('WEAVIATE_GRPC_PORT', '50051')) 

626WEAVIATE_API_KEY = os.getenv('WEAVIATE_API_KEY') 

627WEAVIATE_HTTP_SECURE = os.getenv('WEAVIATE_HTTP_SECURE', 'false').lower() == 'true' 

628WEAVIATE_GRPC_SECURE = os.getenv('WEAVIATE_GRPC_SECURE', 'false').lower() == 'true' 

629WEAVIATE_SKIP_INIT_CHECKS = os.getenv('WEAVIATE_SKIP_INIT_CHECKS', 'false').lower() == 'true' 

630 

631# OpenSearch 

632OPENSEARCH_URI = os.getenv('OPENSEARCH_URI', 'https://localhost:9200') 

633OPENSEARCH_SSL = os.getenv('OPENSEARCH_SSL', 'true').lower() == 'true' 

634OPENSEARCH_CERT_VERIFY = os.getenv('OPENSEARCH_CERT_VERIFY', 'false').lower() == 'true' 

635OPENSEARCH_USERNAME = os.getenv('OPENSEARCH_USERNAME', None) 

636OPENSEARCH_PASSWORD = os.getenv('OPENSEARCH_PASSWORD', None) 

637 

638# ElasticSearch 

639ELASTICSEARCH_URL = os.getenv('ELASTICSEARCH_URL', 'https://localhost:9200') 

640ELASTICSEARCH_CA_CERTS = os.getenv('ELASTICSEARCH_CA_CERTS', None) 

641ELASTICSEARCH_API_KEY = os.getenv('ELASTICSEARCH_API_KEY', None) 

642ELASTICSEARCH_USERNAME = os.getenv('ELASTICSEARCH_USERNAME', None) 

643ELASTICSEARCH_PASSWORD = os.getenv('ELASTICSEARCH_PASSWORD', None) 

644ELASTICSEARCH_CLOUD_ID = os.getenv('ELASTICSEARCH_CLOUD_ID', None) 

645SSL_ASSERT_FINGERPRINT = os.getenv('SSL_ASSERT_FINGERPRINT', None) 

646ELASTICSEARCH_INDEX_PREFIX = os.getenv('ELASTICSEARCH_INDEX_PREFIX', 'open_webui_collections') 

647# Pgvector 

648PGVECTOR_DB_URL = os.getenv('PGVECTOR_DB_URL', DATABASE_URL) 

649if not USE_SLIM and VECTOR_DB == 'pgvector' and not PGVECTOR_DB_URL.startswith('postgres'): 649 ↛ 650line 649 didn't jump to line 650 because the condition on line 649 was never true

650 raise ValueError( 

651 'Pgvector requires setting PGVECTOR_DB_URL or using Postgres with vector extension as the primary database.' 

652 ) 

653PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH = int(os.getenv('PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH', '1536')) 

654 

655PGVECTOR_USE_HALFVEC = os.getenv('PGVECTOR_USE_HALFVEC', 'false').lower() == 'true' 

656 

657if PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH > 2000 and not PGVECTOR_USE_HALFVEC: 657 ↛ 658line 657 didn't jump to line 658 because the condition on line 657 was never true

658 raise ValueError( 

659 'PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH is set to ' 

660 f'{PGVECTOR_INITIALIZE_MAX_VECTOR_LENGTH}, which exceeds the 2000 dimension limit of the ' 

661 "'vector' type. Set PGVECTOR_USE_HALFVEC=true to enable the 'halfvec' " 

662 'type required for high-dimensional embeddings.' 

663 ) 

664 

665PGVECTOR_CREATE_EXTENSION = os.getenv('PGVECTOR_CREATE_EXTENSION', 'true').lower() == 'true' 

666PGVECTOR_PGCRYPTO = os.getenv('PGVECTOR_PGCRYPTO', 'false').lower() == 'true' 

667PGVECTOR_PGCRYPTO_KEY = os.getenv('PGVECTOR_PGCRYPTO_KEY', None) 

668if PGVECTOR_PGCRYPTO and not PGVECTOR_PGCRYPTO_KEY: 668 ↛ 669line 668 didn't jump to line 669 because the condition on line 668 was never true

669 raise ValueError('PGVECTOR_PGCRYPTO is enabled but PGVECTOR_PGCRYPTO_KEY is not set. Please provide a valid key.') 

670 

671 

672PGVECTOR_POOL_SIZE = os.getenv('PGVECTOR_POOL_SIZE', None) 

673 

674if PGVECTOR_POOL_SIZE != None: 674 ↛ 675line 674 didn't jump to line 675 because the condition on line 674 was never true

675 try: 

676 PGVECTOR_POOL_SIZE = int(PGVECTOR_POOL_SIZE) 

677 except Exception: 

678 PGVECTOR_POOL_SIZE = None 

679 

680PGVECTOR_POOL_MAX_OVERFLOW = os.getenv('PGVECTOR_POOL_MAX_OVERFLOW', 0) 

681 

682if PGVECTOR_POOL_MAX_OVERFLOW == '': 682 ↛ 683line 682 didn't jump to line 683 because the condition on line 682 was never true

683 PGVECTOR_POOL_MAX_OVERFLOW = 0 

684else: 

685 try: 

686 PGVECTOR_POOL_MAX_OVERFLOW = int(PGVECTOR_POOL_MAX_OVERFLOW) 

687 except Exception: 

688 PGVECTOR_POOL_MAX_OVERFLOW = 0 

689 

690PGVECTOR_POOL_TIMEOUT = os.getenv('PGVECTOR_POOL_TIMEOUT', 30) 

691 

692if PGVECTOR_POOL_TIMEOUT == '': 692 ↛ 693line 692 didn't jump to line 693 because the condition on line 692 was never true

693 PGVECTOR_POOL_TIMEOUT = 30 

694else: 

695 try: 

696 PGVECTOR_POOL_TIMEOUT = int(PGVECTOR_POOL_TIMEOUT) 

697 except Exception: 

698 PGVECTOR_POOL_TIMEOUT = 30 

699 

700PGVECTOR_POOL_RECYCLE = os.getenv('PGVECTOR_POOL_RECYCLE', 3600) 

701 

702if PGVECTOR_POOL_RECYCLE == '': 702 ↛ 703line 702 didn't jump to line 703 because the condition on line 702 was never true

703 PGVECTOR_POOL_RECYCLE = 3600 

704else: 

705 try: 

706 PGVECTOR_POOL_RECYCLE = int(PGVECTOR_POOL_RECYCLE) 

707 except Exception: 

708 PGVECTOR_POOL_RECYCLE = 3600 

709 

710PGVECTOR_INDEX_METHOD = os.getenv('PGVECTOR_INDEX_METHOD', '').strip().lower() 

711if PGVECTOR_INDEX_METHOD not in ('ivfflat', 'hnsw', ''): 711 ↛ 712line 711 didn't jump to line 712 because the condition on line 711 was never true

712 PGVECTOR_INDEX_METHOD = '' 

713 

714PGVECTOR_HNSW_M = os.getenv('PGVECTOR_HNSW_M', 16) 

715 

716if PGVECTOR_HNSW_M == '': 716 ↛ 717line 716 didn't jump to line 717 because the condition on line 716 was never true

717 PGVECTOR_HNSW_M = 16 

718else: 

719 try: 

720 PGVECTOR_HNSW_M = int(PGVECTOR_HNSW_M) 

721 except Exception: 

722 PGVECTOR_HNSW_M = 16 

723 

724PGVECTOR_HNSW_EF_CONSTRUCTION = os.getenv('PGVECTOR_HNSW_EF_CONSTRUCTION', 64) 

725 

726if PGVECTOR_HNSW_EF_CONSTRUCTION == '': 726 ↛ 727line 726 didn't jump to line 727 because the condition on line 726 was never true

727 PGVECTOR_HNSW_EF_CONSTRUCTION = 64 

728else: 

729 try: 

730 PGVECTOR_HNSW_EF_CONSTRUCTION = int(PGVECTOR_HNSW_EF_CONSTRUCTION) 

731 except Exception: 

732 PGVECTOR_HNSW_EF_CONSTRUCTION = 64 

733 

734PGVECTOR_IVFFLAT_LISTS = os.getenv('PGVECTOR_IVFFLAT_LISTS', 100) 

735 

736if PGVECTOR_IVFFLAT_LISTS == '': 736 ↛ 737line 736 didn't jump to line 737 because the condition on line 736 was never true

737 PGVECTOR_IVFFLAT_LISTS = 100 

738else: 

739 try: 

740 PGVECTOR_IVFFLAT_LISTS = int(PGVECTOR_IVFFLAT_LISTS) 

741 except Exception: 

742 PGVECTOR_IVFFLAT_LISTS = 100 

743 

744PGVECTOR_ITERATIVE_SCAN = os.getenv('PGVECTOR_ITERATIVE_SCAN', 'relaxed_order').strip().lower() 

745if PGVECTOR_ITERATIVE_SCAN not in ('off', 'relaxed_order', 'strict_order'): 745 ↛ 746line 745 didn't jump to line 746 because the condition on line 745 was never true

746 PGVECTOR_ITERATIVE_SCAN = 'relaxed_order' 

747 

748# openGauss 

749OPENGAUSS_DB_URL = os.getenv('OPENGAUSS_DB_URL', DATABASE_URL) 

750 

751OPENGAUSS_INITIALIZE_MAX_VECTOR_LENGTH = int(os.getenv('OPENGAUSS_INITIALIZE_MAX_VECTOR_LENGTH', '1536')) 

752 

753OPENGAUSS_POOL_SIZE = os.getenv('OPENGAUSS_POOL_SIZE', None) 

754 

755if OPENGAUSS_POOL_SIZE != None: 755 ↛ 756line 755 didn't jump to line 756 because the condition on line 755 was never true

756 try: 

757 OPENGAUSS_POOL_SIZE = int(OPENGAUSS_POOL_SIZE) 

758 except Exception: 

759 OPENGAUSS_POOL_SIZE = None 

760 

761OPENGAUSS_POOL_MAX_OVERFLOW = os.getenv('OPENGAUSS_POOL_MAX_OVERFLOW', 0) 

762 

763if OPENGAUSS_POOL_MAX_OVERFLOW == '': 763 ↛ 764line 763 didn't jump to line 764 because the condition on line 763 was never true

764 OPENGAUSS_POOL_MAX_OVERFLOW = 0 

765else: 

766 try: 

767 OPENGAUSS_POOL_MAX_OVERFLOW = int(OPENGAUSS_POOL_MAX_OVERFLOW) 

768 except Exception: 

769 OPENGAUSS_POOL_MAX_OVERFLOW = 0 

770 

771OPENGAUSS_POOL_TIMEOUT = os.getenv('OPENGAUSS_POOL_TIMEOUT', 30) 

772 

773if OPENGAUSS_POOL_TIMEOUT == '': 773 ↛ 774line 773 didn't jump to line 774 because the condition on line 773 was never true

774 OPENGAUSS_POOL_TIMEOUT = 30 

775else: 

776 try: 

777 OPENGAUSS_POOL_TIMEOUT = int(OPENGAUSS_POOL_TIMEOUT) 

778 except Exception: 

779 OPENGAUSS_POOL_TIMEOUT = 30 

780 

781OPENGAUSS_POOL_RECYCLE = os.getenv('OPENGAUSS_POOL_RECYCLE', 3600) 

782 

783if OPENGAUSS_POOL_RECYCLE == '': 783 ↛ 784line 783 didn't jump to line 784 because the condition on line 783 was never true

784 OPENGAUSS_POOL_RECYCLE = 3600 

785else: 

786 try: 

787 OPENGAUSS_POOL_RECYCLE = int(OPENGAUSS_POOL_RECYCLE) 

788 except Exception: 

789 OPENGAUSS_POOL_RECYCLE = 3600 

790 

791# Pinecone 

792PINECONE_API_KEY = os.getenv('PINECONE_API_KEY', None) 

793PINECONE_ENVIRONMENT = os.getenv('PINECONE_ENVIRONMENT', None) 

794PINECONE_INDEX_NAME = os.getenv('PINECONE_INDEX_NAME', 'open-webui-index') 

795PINECONE_DIMENSION = int(os.getenv('PINECONE_DIMENSION', 1536)) # or 3072, 1024, 768 

796PINECONE_METRIC = os.getenv('PINECONE_METRIC', 'cosine') 

797PINECONE_CLOUD = os.getenv('PINECONE_CLOUD', 'aws') # or "gcp" or "azure" 

798 

799# ORACLE23AI (Oracle23ai Vector Search) 

800 

801ORACLE_DB_USE_WALLET = os.getenv('ORACLE_DB_USE_WALLET', 'false').lower() == 'true' 

802ORACLE_DB_USER = os.getenv('ORACLE_DB_USER', None) # 

803ORACLE_DB_PASSWORD = os.getenv('ORACLE_DB_PASSWORD', None) # 

804ORACLE_DB_DSN = os.getenv('ORACLE_DB_DSN', None) # 

805ORACLE_WALLET_DIR = os.getenv('ORACLE_WALLET_DIR', None) 

806ORACLE_WALLET_PASSWORD = os.getenv('ORACLE_WALLET_PASSWORD', None) 

807ORACLE_VECTOR_LENGTH = os.getenv('ORACLE_VECTOR_LENGTH', 768) 

808 

809ORACLE_DB_POOL_MIN = int(os.getenv('ORACLE_DB_POOL_MIN', 2)) 

810ORACLE_DB_POOL_MAX = int(os.getenv('ORACLE_DB_POOL_MAX', 10)) 

811ORACLE_DB_POOL_INCREMENT = int(os.getenv('ORACLE_DB_POOL_INCREMENT', 1)) 

812 

813 

814if not USE_SLIM and VECTOR_DB == 'oracle23ai': 814 ↛ 815line 814 didn't jump to line 815 because the condition on line 814 was never true

815 if not ORACLE_DB_USER or not ORACLE_DB_PASSWORD or not ORACLE_DB_DSN: 

816 raise ValueError('Oracle23ai requires setting ORACLE_DB_USER, ORACLE_DB_PASSWORD, and ORACLE_DB_DSN.') 

817 if ORACLE_DB_USE_WALLET and (not ORACLE_WALLET_DIR or not ORACLE_WALLET_PASSWORD): 

818 raise ValueError( 

819 'Oracle23ai requires setting ORACLE_WALLET_DIR and ORACLE_WALLET_PASSWORD when using wallet authentication.' 

820 ) 

821 

822log.info('VECTOR_DB: %s', VECTOR_DB) 

823 

824# S3 Vector 

825S3_VECTOR_BUCKET_NAME = os.getenv('S3_VECTOR_BUCKET_NAME', None) 

826S3_VECTOR_REGION = os.getenv('S3_VECTOR_REGION', None) 

827 

828# Valkey Vector Store 

829VALKEY_URL = os.getenv('VALKEY_URL', '') 

830VALKEY_COLLECTION_PREFIX = os.getenv('VALKEY_COLLECTION_PREFIX', 'open_webui') 

831VALKEY_INDEX_TYPE = os.getenv('VALKEY_INDEX_TYPE', 'HNSW').upper() 

832VALKEY_DISTANCE_METRIC = os.getenv('VALKEY_DISTANCE_METRIC', 'COSINE').upper() 

833VALKEY_HNSW_M = int(os.getenv('VALKEY_HNSW_M', '16')) 

834VALKEY_HNSW_EF_CONSTRUCTION = int(os.getenv('VALKEY_HNSW_EF_CONSTRUCTION', '200')) 

835VALKEY_HNSW_EF_RUNTIME = int(os.getenv('VALKEY_HNSW_EF_RUNTIME', '10')) 

836 

837#################################### 

838# Information Retrieval (RAG) 

839#################################### 

840 

841 

842# If configured, Google Drive will be available as an upload option. 

843ENABLE_GOOGLE_DRIVE_INTEGRATION = os.getenv('ENABLE_GOOGLE_DRIVE_INTEGRATION', 'False').lower() == 'true' 

844 

845GOOGLE_DRIVE_CLIENT_ID = os.getenv('GOOGLE_DRIVE_CLIENT_ID', '') 

846 

847GOOGLE_DRIVE_API_KEY = os.getenv('GOOGLE_DRIVE_API_KEY', '') 

848 

849ENABLE_ONEDRIVE_INTEGRATION = os.getenv('ENABLE_ONEDRIVE_INTEGRATION', 'False').lower() == 'true' 

850 

851 

852ONEDRIVE_CLIENT_ID = os.getenv('ONEDRIVE_CLIENT_ID', '') 

853ONEDRIVE_CLIENT_ID_PERSONAL = os.getenv('ONEDRIVE_CLIENT_ID_PERSONAL', ONEDRIVE_CLIENT_ID) 

854ONEDRIVE_CLIENT_ID_BUSINESS = os.getenv('ONEDRIVE_CLIENT_ID_BUSINESS', ONEDRIVE_CLIENT_ID) 

855 

856ENABLE_ONEDRIVE_PERSONAL = os.getenv('ENABLE_ONEDRIVE_PERSONAL', 'True').lower() == 'true' and bool( 

857 ONEDRIVE_CLIENT_ID_PERSONAL 

858) 

859ENABLE_ONEDRIVE_BUSINESS = os.getenv('ENABLE_ONEDRIVE_BUSINESS', 'True').lower() == 'true' and bool( 

860 ONEDRIVE_CLIENT_ID_BUSINESS 

861) 

862 

863ONEDRIVE_SHAREPOINT_URL = os.getenv('ONEDRIVE_SHAREPOINT_URL', '') 

864 

865ONEDRIVE_SHAREPOINT_TENANT_ID = os.getenv('ONEDRIVE_SHAREPOINT_TENANT_ID', '') 

866 

867# RAG Content Extraction 

868CONTENT_EXTRACTION_ENGINE = os.getenv('CONTENT_EXTRACTION_ENGINE', '').lower() 

869 

870content_extraction_supported_media_mime_types = os.getenv('CONTENT_EXTRACTION_SUPPORTED_MEDIA_MIME_TYPES') 

871CONTENT_EXTRACTION_SUPPORTED_MEDIA_MIME_TYPES = ( 

872 [mime_type.strip() for mime_type in content_extraction_supported_media_mime_types.split(',') if mime_type.strip()] 

873 if content_extraction_supported_media_mime_types is not None 

874 else None 

875) 

876 

877DATALAB_MARKER_API_KEY = os.getenv('DATALAB_MARKER_API_KEY', '') 

878 

879DATALAB_MARKER_API_BASE_URL = os.getenv('DATALAB_MARKER_API_BASE_URL', '') 

880 

881DATALAB_MARKER_ADDITIONAL_CONFIG = os.getenv('DATALAB_MARKER_ADDITIONAL_CONFIG', '') 

882 

883DATALAB_MARKER_USE_LLM = os.getenv('DATALAB_MARKER_USE_LLM', 'false').lower() == 'true' 

884 

885DATALAB_MARKER_SKIP_CACHE = os.getenv('DATALAB_MARKER_SKIP_CACHE', 'false').lower() == 'true' 

886 

887DATALAB_MARKER_FORCE_OCR = os.getenv('DATALAB_MARKER_FORCE_OCR', 'false').lower() == 'true' 

888 

889DATALAB_MARKER_PAGINATE = os.getenv('DATALAB_MARKER_PAGINATE', 'false').lower() == 'true' 

890 

891DATALAB_MARKER_STRIP_EXISTING_OCR = os.getenv('DATALAB_MARKER_STRIP_EXISTING_OCR', 'false').lower() == 'true' 

892 

893DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION = ( 

894 os.getenv('DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION', 'false').lower() == 'true' 

895) 

896 

897DATALAB_MARKER_FORMAT_LINES = os.getenv('DATALAB_MARKER_FORMAT_LINES', 'false').lower() == 'true' 

898 

899DATALAB_MARKER_OUTPUT_FORMAT = os.getenv('DATALAB_MARKER_OUTPUT_FORMAT', 'markdown') 

900 

901MINERU_API_MODE = os.getenv('MINERU_API_MODE', 'local') 

902 

903MINERU_API_URL = os.getenv('MINERU_API_URL', 'http://localhost:8000') 

904 

905MINERU_API_TIMEOUT = os.getenv('MINERU_API_TIMEOUT', '300') 

906 

907MINERU_API_KEY = os.getenv('MINERU_API_KEY', '') 

908 

909mineru_params = os.getenv('MINERU_PARAMS', '') 

910try: 

911 mineru_params = JSONCodec.loads(mineru_params) 

912except JSONCodec.JSONDecodeError: 

913 mineru_params = {} 

914 

915MINERU_PARAMS = mineru_params 

916 

917MINERU_FILE_EXTENSIONS = [ext.strip() for ext in os.getenv('MINERU_FILE_EXTENSIONS', 'pdf').split(',') if ext.strip()] 

918 

919EXTERNAL_DOCUMENT_LOADER_URL = os.getenv('EXTERNAL_DOCUMENT_LOADER_URL', '') 

920 

921EXTERNAL_DOCUMENT_LOADER_API_KEY = os.getenv('EXTERNAL_DOCUMENT_LOADER_API_KEY', '') 

922 

923external_document_loader_headers = os.getenv('EXTERNAL_DOCUMENT_LOADER_HEADERS', '') 

924try: 

925 external_document_loader_headers = JSONCodec.loads(external_document_loader_headers) 

926except JSONCodec.JSONDecodeError: 

927 external_document_loader_headers = {} 

928if not isinstance(external_document_loader_headers, dict): 928 ↛ 929line 928 didn't jump to line 929 because the condition on line 928 was never true

929 external_document_loader_headers = {} 

930 

931EXTERNAL_DOCUMENT_LOADER_HEADERS = external_document_loader_headers 

932 

933TIKA_SERVER_URL = os.getenv('TIKA_SERVER_URL', 'http://tika:9998') 

934 

935TIKA_SERVER_VERSION = os.getenv('TIKA_SERVER_VERSION', '3') 

936 

937DOCLING_SERVER_URL = os.getenv('DOCLING_SERVER_URL', 'http://docling:5001') 

938 

939DOCLING_API_KEY = os.getenv('DOCLING_API_KEY', '') 

940 

941docling_params = os.getenv('DOCLING_PARAMS', '') 

942try: 

943 docling_params = JSONCodec.loads(docling_params) 

944except JSONCodec.JSONDecodeError: 

945 docling_params = {} 

946 

947DOCLING_PARAMS = docling_params 

948 

949DOCUMENT_INTELLIGENCE_ENDPOINT = os.getenv('DOCUMENT_INTELLIGENCE_ENDPOINT', '') 

950 

951DOCUMENT_INTELLIGENCE_KEY = os.getenv('DOCUMENT_INTELLIGENCE_KEY', '') 

952 

953DOCUMENT_INTELLIGENCE_MODEL = os.getenv('DOCUMENT_INTELLIGENCE_MODEL', 'prebuilt-layout') 

954 

955MISTRAL_OCR_API_BASE_URL = os.getenv('MISTRAL_OCR_API_BASE_URL', 'https://api.mistral.ai/v1') 

956 

957MISTRAL_OCR_API_KEY = os.getenv('MISTRAL_OCR_API_KEY', '') 

958 

959MISTRAL_OCR_USE_BASE64 = os.getenv('MISTRAL_OCR_USE_BASE64', 'False').lower() == 'true' 

960 

961PADDLEOCR_VL_BASE_URL = os.getenv('PADDLEOCR_VL_BASE_URL', 'http://localhost:8080') 

962 

963PADDLEOCR_VL_TOKEN = os.getenv('PADDLEOCR_VL_TOKEN', '') 

964 

965BYPASS_EMBEDDING_AND_RETRIEVAL = os.getenv('BYPASS_EMBEDDING_AND_RETRIEVAL', 'False').lower() == 'true' 

966 

967 

968RAG_TOP_K = int(os.getenv('RAG_TOP_K', '3')) 

969RAG_TOP_K_RERANKER = int(os.getenv('RAG_TOP_K_RERANKER', '3')) 

970RAG_RELEVANCE_THRESHOLD = float(os.getenv('RAG_RELEVANCE_THRESHOLD', '0.0')) 

971RAG_HYBRID_BM25_WEIGHT = float(os.getenv('RAG_HYBRID_BM25_WEIGHT', '0.5')) 

972 

973ENABLE_RAG_HYBRID_SEARCH = os.getenv('ENABLE_RAG_HYBRID_SEARCH', '').lower() == 'true' 

974 

975ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS = ( 

976 os.getenv('ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS', 'False').lower() == 'true' 

977) 

978 

979RAG_FULL_CONTEXT = os.getenv('RAG_FULL_CONTEXT', 'False').lower() == 'true' 

980 

981RAG_FILE_MAX_COUNT = int(os.getenv('RAG_FILE_MAX_COUNT')) if os.getenv('RAG_FILE_MAX_COUNT') else None 

982 

983RAG_FILE_MAX_SIZE = int(os.getenv('RAG_FILE_MAX_SIZE')) if os.getenv('RAG_FILE_MAX_SIZE') else None 

984 

985ENABLE_KNOWLEDGE_FILE_RETENTION = os.getenv('ENABLE_KNOWLEDGE_FILE_RETENTION', 'False').lower() == 'true' 

986 

987RAG_FILE_CONTENT_SEARCH_MAX_CHARS = int(os.getenv('RAG_FILE_CONTENT_SEARCH_MAX_CHARS', str(64 * 1024 * 1024))) 

988 

989FILE_IMAGE_COMPRESSION_WIDTH = ( 

990 int(os.getenv('FILE_IMAGE_COMPRESSION_WIDTH')) if os.getenv('FILE_IMAGE_COMPRESSION_WIDTH') else None 

991) 

992 

993FILE_IMAGE_COMPRESSION_HEIGHT = ( 

994 int(os.getenv('FILE_IMAGE_COMPRESSION_HEIGHT')) if os.getenv('FILE_IMAGE_COMPRESSION_HEIGHT') else None 

995) 

996 

997 

998RAG_ALLOWED_FILE_EXTENSIONS = [ 

999 ext.strip() for ext in os.getenv('RAG_ALLOWED_FILE_EXTENSIONS', '').split(',') if ext.strip() 

1000] 

1001 

1002RAG_EMBEDDING_ENGINE = os.getenv('RAG_EMBEDDING_ENGINE', '') 

1003 

1004PDF_EXTRACT_IMAGES = os.getenv('PDF_EXTRACT_IMAGES', 'False').lower() == 'true' 

1005 

1006PDF_LOADER_MODE = os.getenv('PDF_LOADER_MODE', 'page') 

1007 

1008RAG_EMBEDDING_MODEL = os.getenv('RAG_EMBEDDING_MODEL', 'sentence-transformers/all-MiniLM-L6-v2') 

1009log.info('Embedding model set: %s', RAG_EMBEDDING_MODEL) 

1010 

1011RAG_TOKENIZER_MODEL = os.getenv('RAG_TOKENIZER_MODEL', '') 

1012 

1013RAG_EMBEDDING_MODEL_AUTO_UPDATE = ( 

1014 not OFFLINE_MODE and os.getenv('RAG_EMBEDDING_MODEL_AUTO_UPDATE', 'True').lower() == 'true' 

1015) 

1016 

1017RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE = os.getenv('RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE', 'True').lower() == 'true' 

1018 

1019RAG_EMBEDDING_BATCH_SIZE = int( 

1020 os.getenv('RAG_EMBEDDING_BATCH_SIZE') or os.getenv('RAG_EMBEDDING_OPENAI_BATCH_SIZE', '1') 

1021) 

1022 

1023ENABLE_ASYNC_EMBEDDING = os.getenv('ENABLE_ASYNC_EMBEDDING', 'True').lower() == 'true' 

1024 

1025RAG_EMBEDDING_CONCURRENT_REQUESTS = int(os.getenv('RAG_EMBEDDING_CONCURRENT_REQUESTS', '0')) 

1026 

1027RAG_EMBEDDING_QUERY_PREFIX = os.getenv('RAG_EMBEDDING_QUERY_PREFIX', None) 

1028 

1029RAG_EMBEDDING_CONTENT_PREFIX = os.getenv('RAG_EMBEDDING_CONTENT_PREFIX', None) 

1030 

1031RAG_EMBEDDING_PREFIX_FIELD_NAME = os.getenv('RAG_EMBEDDING_PREFIX_FIELD_NAME', None) 

1032 

1033RAG_RERANKING_ENGINE = os.getenv('RAG_RERANKING_ENGINE', '') 

1034 

1035RAG_RERANKING_MODEL = os.getenv('RAG_RERANKING_MODEL', '') 

1036if RAG_RERANKING_MODEL != '': 1036 ↛ 1037line 1036 didn't jump to line 1037 because the condition on line 1036 was never true

1037 log.info('Reranking model set: %s', RAG_RERANKING_MODEL) 

1038 

1039 

1040RAG_RERANKING_MODEL_AUTO_UPDATE = ( 

1041 not OFFLINE_MODE and os.getenv('RAG_RERANKING_MODEL_AUTO_UPDATE', 'True').lower() == 'true' 

1042) 

1043 

1044RAG_RERANKING_MODEL_TRUST_REMOTE_CODE = os.getenv('RAG_RERANKING_MODEL_TRUST_REMOTE_CODE', 'True').lower() == 'true' 

1045 

1046RAG_RERANKING_BATCH_SIZE = int(os.getenv('RAG_RERANKING_BATCH_SIZE', '32')) 

1047 

1048RAG_EXTERNAL_RERANKER_URL = os.getenv('RAG_EXTERNAL_RERANKER_URL', '') 

1049 

1050RAG_EXTERNAL_RERANKER_API_KEY = os.getenv('RAG_EXTERNAL_RERANKER_API_KEY', '') 

1051 

1052RAG_EXTERNAL_RERANKER_TIMEOUT = os.getenv('RAG_EXTERNAL_RERANKER_TIMEOUT', '') 

1053 

1054 

1055RAG_TEXT_SPLITTER = os.getenv('RAG_TEXT_SPLITTER', '') 

1056 

1057ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER = os.getenv('ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER', 'True').lower() == 'true' 

1058 

1059 

1060TIKTOKEN_CACHE_DIR = os.getenv('TIKTOKEN_CACHE_DIR', f'{CACHE_DIR}/tiktoken') 

1061TIKTOKEN_ENCODING_NAME = os.getenv('TIKTOKEN_ENCODING_NAME', 'cl100k_base') 

1062 

1063 

1064CHUNK_SIZE = int(os.getenv('CHUNK_SIZE', '1000')) 

1065 

1066CHUNK_MIN_SIZE_TARGET = int(os.getenv('CHUNK_MIN_SIZE_TARGET', '0')) 

1067 

1068CHUNK_OVERLAP = int(os.getenv('CHUNK_OVERLAP', '100')) 

1069 

1070DEFAULT_RAG_TEMPLATE = """### Task: 

1071Respond to the user query using the provided context, incorporating inline citations in the format [id] **only when the <source> tag includes an explicit id attribute** (e.g., <source id="1">). 

1072 

1073### Guidelines: 

1074- If you don't know the answer, clearly state that. 

1075- If uncertain, ask the user for clarification. 

1076- Respond in the same language as the user's query. 

1077- If the context is unreadable or of poor quality, inform the user and provide the best possible answer. 

1078- If the answer isn't present in the context but you possess the knowledge, explain this to the user and provide the answer using your own understanding. 

1079- **Only include inline citations using [id] (e.g., [1], [2]) when the <source> tag includes an id attribute.** 

1080- Do not cite if the <source> tag does not contain an id attribute. 

1081- Do not use XML tags in your response. 

1082- Ensure citations are concise and directly related to the information provided. 

1083 

1084### Example of Citation: 

1085If the user asks about a specific topic and the information is found in a source with a provided id attribute, the response should include the citation like in the following example: 

1086* "According to the study, the proposed method increases efficiency by 20% [1]." 

1087 

1088### Output: 

1089Provide a clear and direct response to the user's query, including inline citations in the format [id] only when the <source> tag with id attribute is present in the context. 

1090 

1091<context> 

1092{{CONTEXT}} 

1093</context> 

1094""" 

1095 

1096RAG_TEMPLATE = os.getenv('RAG_TEMPLATE', DEFAULT_RAG_TEMPLATE) 

1097 

1098RAG_OPENAI_API_BASE_URL = os.getenv('RAG_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL) 

1099RAG_OPENAI_API_KEY = os.getenv('RAG_OPENAI_API_KEY', OPENAI_API_KEY) 

1100 

1101RAG_AZURE_OPENAI_BASE_URL = os.getenv('RAG_AZURE_OPENAI_BASE_URL', '') 

1102RAG_AZURE_OPENAI_API_KEY = os.getenv('RAG_AZURE_OPENAI_API_KEY', '') 

1103RAG_AZURE_OPENAI_API_VERSION = os.getenv('RAG_AZURE_OPENAI_API_VERSION', '') 

1104 

1105RAG_OLLAMA_BASE_URL = os.getenv('RAG_OLLAMA_BASE_URL', OLLAMA_BASE_URL) 

1106 

1107RAG_OLLAMA_API_KEY = os.getenv('RAG_OLLAMA_API_KEY', '') 

1108 

1109 

1110ENABLE_LOCAL_WEB_FETCH = ( 

1111 os.getenv( 

1112 'ENABLE_LOCAL_WEB_FETCH', 

1113 os.getenv('ENABLE_RAG_LOCAL_WEB_FETCH', 'False'), 

1114 ).lower() 

1115 == 'true' 

1116) 

1117# Deprecated compatibility alias; use ENABLE_LOCAL_WEB_FETCH for new deployments. 

1118ENABLE_RAG_LOCAL_WEB_FETCH = ENABLE_LOCAL_WEB_FETCH 

1119 

1120 

1121# Operators extend this through WEB_FETCH_FILTER_LIST. 

1122DEFAULT_WEB_FETCH_FILTER_LIST = [ 

1123 '!169.254.169.254', 

1124 '!fd00:ec2::254', 

1125 '!metadata.google.internal', 

1126 '!metadata.azure.com', 

1127 '!100.100.100.200', 

1128 '!168.63.129.16', # Azure platform channel, reachable from every Azure VM 

1129 '!192.88.99.0/24', # 6to4 relay anycast, deprecated by RFC 7526 

1130 '!224.0.0.0/4', # IPv4 multicast 

1131 '!::ffff:0:0:0/96', # IPv4-translated (SIIT, RFC 2765), never routed 

1132 '!64:ff9b:1::/48', # NAT64 local-use prefix, RFC 8215, not a public destination 

1133 '!100:0:0:1::/64', # dummy prefix, RFC 9780 

1134 '!2001:1::1', # PCP anycast, RFC 7723, answered by the local network's own edge device 

1135 '!2001:1::2', # TURN anycast, RFC 8155, likewise 

1136 '!2001:20::/28', # ORCHIDv2, RFC 7343, never routed 

1137 '!2001:30::/28', # DRIP, RFC 9374, never routed 

1138 '!5f00::/16', # SRv6 SIDs, RFC 9602, internal to one segment routing domain 

1139 '!fec0::/10', # IPv6 site-local, deprecated by RFC 3879 

1140 '!ff00::/8', # IPv6 multicast 

1141] 

1142 

1143web_fetch_filter_list = os.getenv('WEB_FETCH_FILTER_LIST', '') 

1144if web_fetch_filter_list == '': 1144 ↛ 1147line 1144 didn't jump to line 1147 because the condition on line 1144 was always true

1145 web_fetch_filter_list = [] 

1146else: 

1147 web_fetch_filter_list = [item.strip() for item in web_fetch_filter_list.split(',') if item.strip()] 

1148 

1149WEB_FETCH_FILTER_LIST = list(set(DEFAULT_WEB_FETCH_FILTER_LIST + web_fetch_filter_list)) 

1150 

1151 

1152YOUTUBE_LOADER_LANGUAGE = os.getenv('YOUTUBE_LOADER_LANGUAGE', 'en').split(',') 

1153 

1154YOUTUBE_LOADER_PROXY_URL = os.getenv('YOUTUBE_LOADER_PROXY_URL', '') 

1155 

1156 

1157#################################### 

1158# Web Search 

1159#################################### 

1160 

1161ENABLE_WEB_SEARCH = os.getenv('ENABLE_WEB_SEARCH', 'False').lower() == 'true' 

1162 

1163ENABLE_WEB_SEARCH_CONFIRMATION = os.getenv('ENABLE_WEB_SEARCH_CONFIRMATION', 'False').lower() == 'true' 

1164 

1165WEB_SEARCH_CONFIRMATION_CONTENT = os.getenv( 

1166 'WEB_SEARCH_CONFIRMATION_CONTENT', 

1167 'Your query will be sent to the configured web search provider.', 

1168) 

1169 

1170WEB_SEARCH_ENGINE = os.getenv('WEB_SEARCH_ENGINE', '') 

1171 

1172BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = ( 

1173 os.getenv('BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL', 'False').lower() == 'true' 

1174) 

1175 

1176 

1177BYPASS_WEB_SEARCH_WEB_LOADER = os.getenv('BYPASS_WEB_SEARCH_WEB_LOADER', 'False').lower() == 'true' 

1178 

1179WEB_SEARCH_RESULT_COUNT = int(os.getenv('WEB_SEARCH_RESULT_COUNT', '3')) 

1180 

1181 

1182try: 

1183 web_search_domain_filter_list = JSONCodec.loads(os.getenv('WEB_SEARCH_DOMAIN_FILTER_LIST', '[]')) 

1184except Exception as e: 

1185 web_search_domain_filter_list = [ 

1186 # "wikipedia.com", 

1187 # "wikimedia.org", 

1188 # "wikidata.org", 

1189 # "!stackoverflow.com", 

1190 ] 

1191 

1192# You can provide a list of your own websites to filter after performing a web search. 

1193# This ensures the highest level of safety and reliability of the information sources. 

1194WEB_SEARCH_DOMAIN_FILTER_LIST = web_search_domain_filter_list 

1195 

1196WEB_SEARCH_CONCURRENT_REQUESTS = int(os.getenv('WEB_SEARCH_CONCURRENT_REQUESTS', '0')) 

1197 

1198WEB_FETCH_MAX_CONTENT_LENGTH = ( 

1199 int(os.getenv('WEB_FETCH_MAX_CONTENT_LENGTH')) if os.getenv('WEB_FETCH_MAX_CONTENT_LENGTH') else None 

1200) 

1201 

1202WEB_LOADER_ENGINE = os.getenv('WEB_LOADER_ENGINE', '') 

1203 

1204 

1205WEB_LOADER_CONCURRENT_REQUESTS = int(os.getenv('WEB_LOADER_CONCURRENT_REQUESTS', '10')) 

1206 

1207WEB_LOADER_TIMEOUT = os.getenv('WEB_LOADER_TIMEOUT', '') 

1208 

1209 

1210ENABLE_WEB_LOADER_SSL_VERIFICATION = os.getenv('ENABLE_WEB_LOADER_SSL_VERIFICATION', 'True').lower() == 'true' 

1211 

1212WEB_SEARCH_TRUST_ENV = os.getenv('WEB_SEARCH_TRUST_ENV', 'True').lower() == 'true' 

1213 

1214 

1215OLLAMA_CLOUD_WEB_SEARCH_API_KEY = os.getenv('OLLAMA_CLOUD_API_KEY', '') 

1216 

1217SEARXNG_QUERY_URL = os.getenv('SEARXNG_QUERY_URL', '') 

1218OPENSERP_BASE_URL = os.getenv('OPENSERP_BASE_URL', 'http://localhost:7000') 

1219 

1220SEARXNG_LANGUAGE = os.getenv('SEARXNG_LANGUAGE', 'all') 

1221 

1222YACY_QUERY_URL = os.getenv('YACY_QUERY_URL', '') 

1223 

1224YACY_USERNAME = os.getenv('YACY_USERNAME', '') 

1225 

1226YACY_PASSWORD = os.getenv('YACY_PASSWORD', '') 

1227 

1228GOOGLE_PSE_API_KEY = os.getenv('GOOGLE_PSE_API_KEY', '') 

1229 

1230GOOGLE_PSE_ENGINE_ID = os.getenv('GOOGLE_PSE_ENGINE_ID', '') 

1231 

1232BRAVE_SEARCH_API_KEY = os.getenv('BRAVE_SEARCH_API_KEY', '') 

1233 

1234BRAVE_SEARCH_CONTEXT_TOKENS = int(os.getenv('BRAVE_SEARCH_CONTEXT_TOKENS', '8192')) 

1235 

1236KAGI_SEARCH_API_KEY = os.getenv('KAGI_SEARCH_API_KEY', '') 

1237 

1238MOJEEK_SEARCH_API_KEY = os.getenv('MOJEEK_SEARCH_API_KEY', '') 

1239 

1240BOCHA_SEARCH_API_KEY = os.getenv('BOCHA_SEARCH_API_KEY', '') 

1241 

1242SERPSTACK_API_KEY = os.getenv('SERPSTACK_API_KEY', '') 

1243 

1244SERPSTACK_HTTPS = os.getenv('SERPSTACK_HTTPS', 'True').lower() == 'true' 

1245 

1246SERPER_API_KEY = os.getenv('SERPER_API_KEY', '') 

1247 

1248SERPLY_API_KEY = os.getenv('SERPLY_API_KEY', '') 

1249 

1250SERPHOUSE_API_KEY = os.getenv('SERPHOUSE_API_KEY', '') 

1251 

1252SERPHOUSE_DOMAIN = os.getenv('SERPHOUSE_DOMAIN', 'google.com') 

1253 

1254DDGS_BACKEND = os.getenv('DDGS_BACKEND', 'auto') 

1255 

1256JINA_API_KEY = os.getenv('JINA_API_KEY', '') 

1257 

1258JINA_API_BASE_URL = os.getenv('JINA_API_BASE_URL', '') 

1259 

1260SEARCHAPI_API_KEY = os.getenv('SEARCHAPI_API_KEY', '') 

1261 

1262SEARCHAPI_ENGINE = os.getenv('SEARCHAPI_ENGINE', '') 

1263 

1264SERPAPI_API_KEY = os.getenv('SERPAPI_API_KEY', '') 

1265 

1266SERPAPI_ENGINE = os.getenv('SERPAPI_ENGINE', '') 

1267 

1268BING_SEARCH_V7_ENDPOINT = os.getenv('BING_SEARCH_V7_ENDPOINT', 'https://api.bing.microsoft.com/v7.0/search') 

1269 

1270BING_SEARCH_V7_SUBSCRIPTION_KEY = os.getenv('BING_SEARCH_V7_SUBSCRIPTION_KEY', '') 

1271 

1272AZURE_AI_SEARCH_API_KEY = os.getenv('AZURE_AI_SEARCH_API_KEY', '') 

1273 

1274AZURE_AI_SEARCH_ENDPOINT = os.getenv('AZURE_AI_SEARCH_ENDPOINT', '') 

1275 

1276AZURE_AI_SEARCH_INDEX_NAME = os.getenv('AZURE_AI_SEARCH_INDEX_NAME', '') 

1277 

1278EXA_API_KEY = os.getenv('EXA_API_KEY', '') 

1279EXA_MAX_CONTENT_LENGTH = int(os.environ['EXA_MAX_CONTENT_LENGTH']) if os.getenv('EXA_MAX_CONTENT_LENGTH') else None 

1280if EXA_MAX_CONTENT_LENGTH is not None and EXA_MAX_CONTENT_LENGTH <= 0: 1280 ↛ 1281line 1280 didn't jump to line 1281 because the condition on line 1280 was never true

1281 raise ValueError('EXA_MAX_CONTENT_LENGTH must be a positive integer or unset') 

1282 

1283PERPLEXITY_API_KEY = os.getenv('PERPLEXITY_API_KEY', '') 

1284 

1285PERPLEXITY_MODEL = os.getenv('PERPLEXITY_MODEL', 'sonar') 

1286 

1287PERPLEXITY_SEARCH_CONTEXT_USAGE = os.getenv('PERPLEXITY_SEARCH_CONTEXT_USAGE', 'medium') 

1288 

1289PERPLEXITY_SEARCH_API_URL = os.getenv('PERPLEXITY_SEARCH_API_URL', 'https://api.perplexity.ai/search') 

1290 

1291MICROSOFT_WEB_IQ_API_BASE_URL = os.getenv('MICROSOFT_WEB_IQ_API_BASE_URL', 'https://api.microsoft.ai/v3') 

1292 

1293MICROSOFT_WEB_IQ_API_KEY = os.getenv('MICROSOFT_WEB_IQ_API_KEY', '') 

1294 

1295MICROSOFT_WEB_IQ_LANGUAGE = os.getenv('MICROSOFT_WEB_IQ_LANGUAGE', 'en') 

1296 

1297SOUGOU_API_SID = os.getenv('SOUGOU_API_SID', '') 

1298 

1299SOUGOU_API_SK = os.getenv('SOUGOU_API_SK', '') 

1300 

1301TAVILY_API_KEY = os.getenv('TAVILY_API_KEY', '') 

1302 

1303TAVILY_EXTRACT_DEPTH = os.getenv('TAVILY_EXTRACT_DEPTH', 'basic') 

1304 

1305STAAN_API_KEY = os.getenv('STAAN_API_KEY', '') 

1306 

1307STAAN_MARKET = os.getenv('STAAN_MARKET', 'en-us') 

1308 

1309STAAN_MAX_SNIPPETS = int(os.getenv('STAAN_MAX_SNIPPETS', '0')) 

1310 

1311PLAYWRIGHT_WS_URL = os.getenv('PLAYWRIGHT_WS_URL', '') 

1312 

1313PLAYWRIGHT_TIMEOUT = int(os.getenv('PLAYWRIGHT_TIMEOUT', '10000')) 

1314 

1315FIRECRAWL_API_KEY = os.getenv('FIRECRAWL_API_KEY', '') 

1316 

1317FIRECRAWL_API_BASE_URL = os.getenv('FIRECRAWL_API_BASE_URL', 'https://api.firecrawl.dev') 

1318 

1319FIRECRAWL_TIMEOUT = os.getenv('FIRECRAWL_TIMEOUT', '') 

1320 

1321EXTERNAL_WEB_SEARCH_URL = os.getenv('EXTERNAL_WEB_SEARCH_URL', '') 

1322 

1323EXTERNAL_WEB_SEARCH_API_KEY = os.getenv('EXTERNAL_WEB_SEARCH_API_KEY', '') 

1324 

1325EXTERNAL_WEB_LOADER_URL = os.getenv('EXTERNAL_WEB_LOADER_URL', '') 

1326 

1327EXTERNAL_WEB_LOADER_API_KEY = os.getenv('EXTERNAL_WEB_LOADER_API_KEY', '') 

1328 

1329YANDEX_WEB_SEARCH_URL = os.getenv('YANDEX_WEB_SEARCH_URL', '') 

1330 

1331YANDEX_WEB_SEARCH_API_KEY = os.getenv('YANDEX_WEB_SEARCH_API_KEY', '') 

1332 

1333YANDEX_WEB_SEARCH_CONFIG = os.getenv('YANDEX_WEB_SEARCH_CONFIG', '') 

1334 

1335YOUCOM_API_KEY = os.getenv('YOUCOM_API_KEY', os.getenv('YDC_API_KEY', '')) 

1336 

1337LINKUP_API_KEY = os.getenv('LINKUP_API_KEY', '') 

1338 

1339linkup_search_params = os.getenv('LINKUP_SEARCH_PARAMS', '') 

1340try: 

1341 linkup_search_params = JSONCodec.loads(linkup_search_params) 

1342except JSONCodec.JSONDecodeError: 

1343 linkup_search_params = {} 

1344 

1345LINKUP_SEARCH_PARAMS = linkup_search_params 

1346 

1347#################################### 

1348# Images 

1349#################################### 

1350 

1351ENABLE_IMAGE_GENERATION = os.getenv('ENABLE_IMAGE_GENERATION', '').lower() == 'true' 

1352 

1353IMAGE_GENERATION_ENGINE = os.getenv('IMAGE_GENERATION_ENGINE', 'openai') 

1354 

1355IMAGE_GENERATION_MODEL = os.getenv('IMAGE_GENERATION_MODEL', '') 

1356 

1357# Regex pattern for models that support IMAGE_SIZE = "auto". 

1358IMAGE_AUTO_SIZE_MODELS_REGEX_PATTERN = os.getenv('IMAGE_AUTO_SIZE_MODELS_REGEX_PATTERN', '^gpt-image') 

1359 

1360# Regex pattern for models that return URLs instead of base64 data. 

1361IMAGE_URL_RESPONSE_MODELS_REGEX_PATTERN = os.getenv('IMAGE_URL_RESPONSE_MODELS_REGEX_PATTERN', '^gpt-image') 

1362 

1363IMAGE_SIZE = os.getenv('IMAGE_SIZE', '512x512') 

1364 

1365IMAGE_STEPS = int(os.getenv('IMAGE_STEPS', 50)) 

1366 

1367ENABLE_IMAGE_PROMPT_GENERATION = os.getenv('ENABLE_IMAGE_PROMPT_GENERATION', 'true').lower() == 'true' 

1368 

1369AUTOMATIC1111_BASE_URL = os.getenv('AUTOMATIC1111_BASE_URL', '') 

1370AUTOMATIC1111_API_AUTH = os.getenv('AUTOMATIC1111_API_AUTH', '') 

1371 

1372automatic1111_params = os.getenv('AUTOMATIC1111_PARAMS', '') 

1373try: 

1374 automatic1111_params = JSONCodec.loads(automatic1111_params) 

1375except JSONCodec.JSONDecodeError: 

1376 automatic1111_params = {} 

1377 

1378AUTOMATIC1111_PARAMS = automatic1111_params 

1379 

1380COMFYUI_BASE_URL = os.getenv('COMFYUI_BASE_URL', '') 

1381 

1382COMFYUI_API_KEY = os.getenv('COMFYUI_API_KEY', '') 

1383 

1384COMFYUI_DEFAULT_WORKFLOW = """ 

1385{ 

1386 "3": { 

1387 "inputs": { 

1388 "seed": 0, 

1389 "steps": 20, 

1390 "cfg": 8, 

1391 "sampler_name": "euler", 

1392 "scheduler": "normal", 

1393 "denoise": 1, 

1394 "model": [ 

1395 "4", 

1396 0 

1397 ], 

1398 "positive": [ 

1399 "6", 

1400 0 

1401 ], 

1402 "negative": [ 

1403 "7", 

1404 0 

1405 ], 

1406 "latent_image": [ 

1407 "5", 

1408 0 

1409 ] 

1410 }, 

1411 "class_type": "KSampler", 

1412 "_meta": { 

1413 "title": "KSampler" 

1414 } 

1415 }, 

1416 "4": { 

1417 "inputs": { 

1418 "ckpt_name": "model.safetensors" 

1419 }, 

1420 "class_type": "CheckpointLoaderSimple", 

1421 "_meta": { 

1422 "title": "Load Checkpoint" 

1423 } 

1424 }, 

1425 "5": { 

1426 "inputs": { 

1427 "width": 512, 

1428 "height": 512, 

1429 "batch_size": 1 

1430 }, 

1431 "class_type": "EmptyLatentImage", 

1432 "_meta": { 

1433 "title": "Empty Latent Image" 

1434 } 

1435 }, 

1436 "6": { 

1437 "inputs": { 

1438 "text": "Prompt", 

1439 "clip": [ 

1440 "4", 

1441 1 

1442 ] 

1443 }, 

1444 "class_type": "CLIPTextEncode", 

1445 "_meta": { 

1446 "title": "CLIP Text Encode (Prompt)" 

1447 } 

1448 }, 

1449 "7": { 

1450 "inputs": { 

1451 "text": "", 

1452 "clip": [ 

1453 "4", 

1454 1 

1455 ] 

1456 }, 

1457 "class_type": "CLIPTextEncode", 

1458 "_meta": { 

1459 "title": "CLIP Text Encode (Prompt)" 

1460 } 

1461 }, 

1462 "8": { 

1463 "inputs": { 

1464 "samples": [ 

1465 "3", 

1466 0 

1467 ], 

1468 "vae": [ 

1469 "4", 

1470 2 

1471 ] 

1472 }, 

1473 "class_type": "VAEDecode", 

1474 "_meta": { 

1475 "title": "VAE Decode" 

1476 } 

1477 }, 

1478 "9": { 

1479 "inputs": { 

1480 "filename_prefix": "ComfyUI", 

1481 "images": [ 

1482 "8", 

1483 0 

1484 ] 

1485 }, 

1486 "class_type": "SaveImage", 

1487 "_meta": { 

1488 "title": "Save Image" 

1489 } 

1490 } 

1491} 

1492""" 

1493 

1494 

1495COMFYUI_WORKFLOW = os.getenv('COMFYUI_WORKFLOW', COMFYUI_DEFAULT_WORKFLOW) 

1496 

1497comfyui_workflow_nodes = os.getenv('COMFYUI_WORKFLOW_NODES', '') 

1498try: 

1499 comfyui_workflow_nodes = JSONCodec.loads(comfyui_workflow_nodes) 

1500except JSONCodec.JSONDecodeError: 

1501 comfyui_workflow_nodes = [] 

1502 

1503COMFYUI_WORKFLOW_NODES = comfyui_workflow_nodes 

1504 

1505IMAGES_OPENAI_API_BASE_URL = os.getenv('IMAGES_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL) 

1506IMAGES_OPENAI_API_VERSION = os.getenv('IMAGES_OPENAI_API_VERSION', '') 

1507 

1508IMAGES_OPENAI_API_KEY = os.getenv('IMAGES_OPENAI_API_KEY', OPENAI_API_KEY) 

1509 

1510images_openai_params = os.getenv('IMAGES_OPENAI_PARAMS', '') 

1511try: 

1512 images_openai_params = JSONCodec.loads(images_openai_params) 

1513except JSONCodec.JSONDecodeError: 

1514 images_openai_params = {} 

1515 

1516 

1517IMAGES_OPENAI_API_PARAMS = images_openai_params 

1518 

1519 

1520IMAGES_GEMINI_API_BASE_URL = os.getenv('IMAGES_GEMINI_API_BASE_URL', GEMINI_API_BASE_URL) 

1521IMAGES_GEMINI_API_KEY = os.getenv('IMAGES_GEMINI_API_KEY', GEMINI_API_KEY) 

1522 

1523IMAGES_GEMINI_ENDPOINT_METHOD = os.getenv('IMAGES_GEMINI_ENDPOINT_METHOD', '') 

1524 

1525ENABLE_IMAGE_EDIT = os.getenv('ENABLE_IMAGE_EDIT', '').lower() == 'true' 

1526 

1527IMAGE_EDIT_ENGINE = os.getenv('IMAGE_EDIT_ENGINE', 'openai') 

1528 

1529IMAGE_EDIT_MODEL = os.getenv('IMAGE_EDIT_MODEL', '') 

1530 

1531IMAGE_EDIT_SIZE = os.getenv('IMAGE_EDIT_SIZE', '') 

1532 

1533ENABLE_OPENAI_IMAGE_EDIT_NORMALIZATION = os.getenv('ENABLE_OPENAI_IMAGE_EDIT_NORMALIZATION', 'true').lower() == 'true' 

1534 

1535IMAGES_EDIT_OPENAI_API_BASE_URL = os.getenv('IMAGES_EDIT_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL) 

1536IMAGES_EDIT_OPENAI_API_VERSION = os.getenv('IMAGES_EDIT_OPENAI_API_VERSION', '') 

1537 

1538IMAGES_EDIT_OPENAI_API_KEY = os.getenv('IMAGES_EDIT_OPENAI_API_KEY', OPENAI_API_KEY) 

1539 

1540IMAGES_EDIT_GEMINI_API_BASE_URL = os.getenv('IMAGES_EDIT_GEMINI_API_BASE_URL', GEMINI_API_BASE_URL) 

1541IMAGES_EDIT_GEMINI_API_KEY = os.getenv('IMAGES_EDIT_GEMINI_API_KEY', GEMINI_API_KEY) 

1542 

1543 

1544IMAGES_EDIT_COMFYUI_BASE_URL = os.getenv('IMAGES_EDIT_COMFYUI_BASE_URL', '') 

1545IMAGES_EDIT_COMFYUI_API_KEY = os.getenv('IMAGES_EDIT_COMFYUI_API_KEY', '') 

1546 

1547IMAGES_EDIT_COMFYUI_WORKFLOW = os.getenv('IMAGES_EDIT_COMFYUI_WORKFLOW', '') 

1548 

1549images_edit_comfyui_workflow_nodes = os.getenv('IMAGES_EDIT_COMFYUI_WORKFLOW_NODES', '') 

1550try: 

1551 images_edit_comfyui_workflow_nodes = JSONCodec.loads(images_edit_comfyui_workflow_nodes) 

1552except JSONCodec.JSONDecodeError: 

1553 images_edit_comfyui_workflow_nodes = [] 

1554 

1555IMAGES_EDIT_COMFYUI_WORKFLOW_NODES = images_edit_comfyui_workflow_nodes 

1556 

1557#################################### 

1558# Audio 

1559#################################### 

1560 

1561# Transcription 

1562WHISPER_MODEL = os.getenv('WHISPER_MODEL', 'base') 

1563 

1564WHISPER_COMPUTE_TYPE = os.getenv('WHISPER_COMPUTE_TYPE', 'int8') 

1565WHISPER_MODEL_DIR = os.getenv('WHISPER_MODEL_DIR', f'{CACHE_DIR}/whisper/models') 

1566WHISPER_MODEL_AUTO_UPDATE = not OFFLINE_MODE and os.getenv('WHISPER_MODEL_AUTO_UPDATE', '').lower() == 'true' 

1567 

1568WHISPER_VAD_FILTER = os.getenv('WHISPER_VAD_FILTER', 'False').lower() == 'true' 

1569 

1570WHISPER_MULTILINGUAL = os.getenv('WHISPER_MULTILINGUAL', 'False').lower() == 'true' 

1571 

1572WHISPER_LANGUAGE = os.getenv('WHISPER_LANGUAGE', '').lower() or None 

1573 

1574# Add Deepgram configuration 

1575DEEPGRAM_API_KEY = os.getenv('DEEPGRAM_API_KEY', '') 

1576 

1577# ElevenLabs configuration 

1578ELEVENLABS_API_BASE_URL = os.getenv('ELEVENLABS_API_BASE_URL', 'https://api.elevenlabs.io') 

1579 

1580AUDIO_STT_OPENAI_API_BASE_URL = os.getenv('AUDIO_STT_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL) 

1581 

1582AUDIO_STT_OPENAI_API_KEY = os.getenv('AUDIO_STT_OPENAI_API_KEY', OPENAI_API_KEY) 

1583 

1584AUDIO_STT_OPENAI_API_REQUEST_FORMAT = os.getenv('AUDIO_STT_OPENAI_API_REQUEST_FORMAT', 'multipart') 

1585 

1586AUDIO_STT_ENGINE = os.getenv('AUDIO_STT_ENGINE', '') 

1587 

1588AUDIO_STT_MODEL = os.getenv('AUDIO_STT_MODEL', '') 

1589 

1590AUDIO_STT_SUPPORTED_CONTENT_TYPES = [ 

1591 content_type.strip() 

1592 for content_type in os.getenv('AUDIO_STT_SUPPORTED_CONTENT_TYPES', '').split(',') 

1593 if content_type.strip() 

1594] 

1595 

1596AUDIO_STT_ALLOWED_EXTENSIONS = [ 

1597 ext.strip() 

1598 for ext in os.getenv( 

1599 'AUDIO_STT_ALLOWED_EXTENSIONS', 

1600 'mp3,wav,m4a,webm,ogg,flac,mp4,mpga,mpeg', 

1601 ).split(',') 

1602 if ext.strip() 

1603] 

1604 

1605AUDIO_STT_AZURE_API_KEY = os.getenv('AUDIO_STT_AZURE_API_KEY', '') 

1606 

1607AUDIO_STT_AZURE_REGION = os.getenv('AUDIO_STT_AZURE_REGION', '') 

1608 

1609AUDIO_STT_AZURE_LOCALES = os.getenv('AUDIO_STT_AZURE_LOCALES', '') 

1610 

1611AUDIO_STT_AZURE_BASE_URL = os.getenv('AUDIO_STT_AZURE_BASE_URL', '') 

1612 

1613AUDIO_STT_AZURE_MAX_SPEAKERS = os.getenv('AUDIO_STT_AZURE_MAX_SPEAKERS', '') 

1614 

1615AUDIO_STT_MISTRAL_API_KEY = os.getenv('AUDIO_STT_MISTRAL_API_KEY', '') 

1616 

1617AUDIO_STT_MISTRAL_API_BASE_URL = os.getenv('AUDIO_STT_MISTRAL_API_BASE_URL', 'https://api.mistral.ai/v1') 

1618 

1619AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS = os.getenv('AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS', 'false').lower() == 'true' 

1620 

1621AUDIO_TTS_OPENAI_API_BASE_URL = os.getenv('AUDIO_TTS_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL) 

1622AUDIO_TTS_OPENAI_API_KEY = os.getenv('AUDIO_TTS_OPENAI_API_KEY', OPENAI_API_KEY) 

1623 

1624audio_tts_openai_params = os.getenv('AUDIO_TTS_OPENAI_PARAMS', '') 

1625try: 

1626 audio_tts_openai_params = JSONCodec.loads(audio_tts_openai_params) 

1627except JSONCodec.JSONDecodeError: 

1628 audio_tts_openai_params = {} 

1629 

1630AUDIO_TTS_OPENAI_PARAMS = audio_tts_openai_params 

1631 

1632 

1633AUDIO_TTS_API_KEY = os.getenv('AUDIO_TTS_API_KEY', '') 

1634 

1635AUDIO_TTS_ENGINE = os.getenv('AUDIO_TTS_ENGINE', '') 

1636 

1637 

1638AUDIO_TTS_MODEL = os.getenv('AUDIO_TTS_MODEL', 'tts-1') 

1639 

1640AUDIO_TTS_VOICE = os.getenv('AUDIO_TTS_VOICE', 'alloy') 

1641 

1642AUDIO_TTS_SPLIT_ON = os.getenv('AUDIO_TTS_SPLIT_ON', 'punctuation') 

1643 

1644AUDIO_TTS_AZURE_SPEECH_REGION = os.getenv('AUDIO_TTS_AZURE_SPEECH_REGION', '') 

1645 

1646AUDIO_TTS_AZURE_SPEECH_BASE_URL = os.getenv('AUDIO_TTS_AZURE_SPEECH_BASE_URL', '') 

1647 

1648AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT = os.getenv( 

1649 'AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT', 'audio-24khz-160kbitrate-mono-mp3' 

1650) 

1651 

1652AUDIO_TTS_MISTRAL_API_KEY = os.getenv('AUDIO_TTS_MISTRAL_API_KEY', '') 

1653 

1654AUDIO_TTS_MISTRAL_API_BASE_URL = os.getenv('AUDIO_TTS_MISTRAL_API_BASE_URL', 'https://api.mistral.ai/v1') 

1655 

1656#################################### 

1657# WEBUI 

1658#################################### 

1659 

1660 

1661WEBUI_URL = os.getenv('WEBUI_URL', '') 

1662 

1663 

1664ENABLE_SIGNUP = False if not WEBUI_AUTH else os.getenv('ENABLE_SIGNUP', 'True').lower() == 'true' 

1665 

1666ENABLE_LOGIN_FORM = os.getenv('ENABLE_LOGIN_FORM', 'True').lower() == 'true' 

1667 

1668ENABLE_PASSWORD_CHANGE_FORM = os.getenv('ENABLE_PASSWORD_CHANGE_FORM', 'True').lower() == 'true' 

1669 

1670ENABLE_PASSWORD_AUTH = os.getenv('ENABLE_PASSWORD_AUTH', 'True').lower() == 'true' 

1671 

1672DEFAULT_LOCALE = os.getenv('DEFAULT_LOCALE', '') 

1673 

1674DEFAULT_MODELS = os.getenv('DEFAULT_MODELS', None) 

1675 

1676DEFAULT_PINNED_MODELS = os.getenv('DEFAULT_PINNED_MODELS', None) 

1677 

1678# None uses the frontend's localized defaults; an empty list disables suggestions. 

1679try: 

1680 DEFAULT_PROMPT_SUGGESTIONS = JSONCodec.loads(os.getenv('DEFAULT_PROMPT_SUGGESTIONS', 'null')) 

1681except Exception as e: 

1682 log.exception(f'Error loading DEFAULT_PROMPT_SUGGESTIONS: {e}') 

1683 DEFAULT_PROMPT_SUGGESTIONS = None 

1684 

1685DEFAULT_PROMPT_SUGGESTIONS_I18N = {} 

1686 

1687try: 

1688 model_order_list = JSONCodec.loads(os.getenv('MODEL_ORDER_LIST', '[]')) 

1689except Exception as e: 

1690 log.exception(f'Error loading MODEL_ORDER_LIST: {e}') 

1691 model_order_list = [] 

1692 

1693MODEL_ORDER_LIST = model_order_list 

1694 

1695try: 

1696 default_model_metadata = JSONCodec.loads(os.getenv('DEFAULT_MODEL_METADATA', '{}')) 

1697except Exception as e: 

1698 log.exception(f'Error loading DEFAULT_MODEL_METADATA: {e}') 

1699 default_model_metadata = {} 

1700 

1701DEFAULT_MODEL_METADATA = default_model_metadata 

1702 

1703try: 

1704 default_model_params = JSONCodec.loads(os.getenv('DEFAULT_MODEL_PARAMS', '{}')) 

1705except Exception as e: 

1706 log.exception(f'Error loading DEFAULT_MODEL_PARAMS: {e}') 

1707 default_model_params = {} 

1708 

1709DEFAULT_MODEL_PARAMS = default_model_params 

1710 

1711 

1712try: 

1713 default_interface_settings = JSONCodec.loads(os.getenv('DEFAULT_INTERFACE_SETTINGS', '{}')) 

1714except Exception as e: 

1715 log.exception(f'Error loading DEFAULT_INTERFACE_SETTINGS: {e}') 

1716 default_interface_settings = {} 

1717 

1718DEFAULT_INTERFACE_SETTINGS = default_interface_settings if isinstance(default_interface_settings, dict) else {} 

1719 

1720DEFAULT_USER_ROLE = os.getenv('DEFAULT_USER_ROLE', 'pending') 

1721 

1722DEFAULT_GROUP_ID = os.getenv('DEFAULT_GROUP_ID', '') 

1723 

1724PENDING_USER_OVERLAY_TITLE = os.getenv('PENDING_USER_OVERLAY_TITLE', '') 

1725 

1726PENDING_USER_OVERLAY_CONTENT = os.getenv('PENDING_USER_OVERLAY_CONTENT', '') 

1727 

1728 

1729RESPONSE_WATERMARK = os.getenv('RESPONSE_WATERMARK', '') 

1730 

1731IFRAME_CSP = os.getenv('IFRAME_CSP', '') 

1732 

1733USER_PERMISSIONS_WORKSPACE_MODELS_ACCESS = ( 

1734 os.getenv('USER_PERMISSIONS_WORKSPACE_MODELS_ACCESS', 'False').lower() == 'true' 

1735) 

1736 

1737USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ACCESS = ( 

1738 os.getenv('USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ACCESS', 'False').lower() == 'true' 

1739) 

1740 

1741USER_PERMISSIONS_WORKSPACE_PROMPTS_ACCESS = ( 

1742 os.getenv('USER_PERMISSIONS_WORKSPACE_PROMPTS_ACCESS', 'False').lower() == 'true' 

1743) 

1744 

1745USER_PERMISSIONS_WORKSPACE_TOOLS_ACCESS = ( 

1746 os.getenv('USER_PERMISSIONS_WORKSPACE_TOOLS_ACCESS', 'False').lower() == 'true' 

1747) 

1748 

1749USER_PERMISSIONS_WORKSPACE_SKILLS_ACCESS = ( 

1750 os.getenv('USER_PERMISSIONS_WORKSPACE_SKILLS_ACCESS', 'False').lower() == 'true' 

1751) 

1752 

1753USER_PERMISSIONS_WORKSPACE_MODELS_IMPORT = ( 

1754 os.getenv('USER_PERMISSIONS_WORKSPACE_MODELS_IMPORT', 'False').lower() == 'true' 

1755) 

1756 

1757USER_PERMISSIONS_WORKSPACE_MODELS_EXPORT = ( 

1758 os.getenv('USER_PERMISSIONS_WORKSPACE_MODELS_EXPORT', 'False').lower() == 'true' 

1759) 

1760 

1761USER_PERMISSIONS_WORKSPACE_PROMPTS_IMPORT = ( 

1762 os.getenv('USER_PERMISSIONS_WORKSPACE_PROMPTS_IMPORT', 'False').lower() == 'true' 

1763) 

1764 

1765USER_PERMISSIONS_WORKSPACE_PROMPTS_EXPORT = ( 

1766 os.getenv('USER_PERMISSIONS_WORKSPACE_PROMPTS_EXPORT', 'False').lower() == 'true' 

1767) 

1768 

1769USER_PERMISSIONS_WORKSPACE_TOOLS_IMPORT = ( 

1770 os.getenv('USER_PERMISSIONS_WORKSPACE_TOOLS_IMPORT', 'False').lower() == 'true' 

1771) 

1772 

1773USER_PERMISSIONS_WORKSPACE_TOOLS_EXPORT = ( 

1774 os.getenv('USER_PERMISSIONS_WORKSPACE_TOOLS_EXPORT', 'False').lower() == 'true' 

1775) 

1776 

1777USER_PERMISSIONS_WORKSPACE_SKILLS_IMPORT = ( 

1778 os.getenv('USER_PERMISSIONS_WORKSPACE_SKILLS_IMPORT', 'False').lower() == 'true' 

1779) 

1780 

1781USER_PERMISSIONS_WORKSPACE_SKILLS_EXPORT = ( 

1782 os.getenv('USER_PERMISSIONS_WORKSPACE_SKILLS_EXPORT', 'False').lower() == 'true' 

1783) 

1784 

1785 

1786USER_PERMISSIONS_WORKSPACE_MODELS_ALLOW_SHARING = ( 

1787 os.getenv('USER_PERMISSIONS_WORKSPACE_MODELS_ALLOW_SHARING', 'False').lower() == 'true' 

1788) 

1789 

1790USER_PERMISSIONS_WORKSPACE_MODELS_ALLOW_PUBLIC_SHARING = ( 

1791 os.getenv('USER_PERMISSIONS_WORKSPACE_MODELS_ALLOW_PUBLIC_SHARING', 'False').lower() == 'true' 

1792) 

1793 

1794USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ALLOW_SHARING = ( 

1795 os.getenv('USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ALLOW_SHARING', 'False').lower() == 'true' 

1796) 

1797 

1798USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ALLOW_PUBLIC_SHARING = ( 

1799 os.getenv('USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ALLOW_PUBLIC_SHARING', 'False').lower() == 'true' 

1800) 

1801 

1802USER_PERMISSIONS_WORKSPACE_PROMPTS_ALLOW_SHARING = ( 

1803 os.getenv('USER_PERMISSIONS_WORKSPACE_PROMPTS_ALLOW_SHARING', 'False').lower() == 'true' 

1804) 

1805 

1806USER_PERMISSIONS_WORKSPACE_PROMPTS_ALLOW_PUBLIC_SHARING = ( 

1807 os.getenv('USER_PERMISSIONS_WORKSPACE_PROMPTS_ALLOW_PUBLIC_SHARING', 'False').lower() == 'true' 

1808) 

1809 

1810 

1811USER_PERMISSIONS_WORKSPACE_TOOLS_ALLOW_SHARING = ( 

1812 os.getenv('USER_PERMISSIONS_WORKSPACE_TOOLS_ALLOW_SHARING', 'False').lower() == 'true' 

1813) 

1814 

1815USER_PERMISSIONS_WORKSPACE_TOOLS_ALLOW_PUBLIC_SHARING = ( 

1816 os.getenv('USER_PERMISSIONS_WORKSPACE_TOOLS_ALLOW_PUBLIC_SHARING', 'False').lower() == 'true' 

1817) 

1818 

1819USER_PERMISSIONS_WORKSPACE_SKILLS_ALLOW_SHARING = ( 

1820 os.getenv('USER_PERMISSIONS_WORKSPACE_SKILLS_ALLOW_SHARING', 'False').lower() == 'true' 

1821) 

1822 

1823USER_PERMISSIONS_WORKSPACE_SKILLS_ALLOW_PUBLIC_SHARING = ( 

1824 os.getenv('USER_PERMISSIONS_WORKSPACE_SKILLS_ALLOW_PUBLIC_SHARING', 'False').lower() == 'true' 

1825) 

1826 

1827 

1828USER_PERMISSIONS_NOTES_ALLOW_SHARING = os.getenv('USER_PERMISSIONS_NOTES_ALLOW_SHARING', 'False').lower() == 'true' 

1829 

1830USER_PERMISSIONS_NOTES_ALLOW_PUBLIC_SHARING = ( 

1831 os.getenv('USER_PERMISSIONS_NOTES_ALLOW_PUBLIC_SHARING', 'False').lower() == 'true' 

1832) 

1833 

1834USER_PERMISSIONS_FOLDERS_ALLOW_SHARING = os.getenv('USER_PERMISSIONS_FOLDERS_ALLOW_SHARING', 'False').lower() == 'true' 

1835 

1836 

1837USER_PERMISSIONS_CALENDAR_ALLOW_PUBLIC_SHARING = ( 

1838 os.getenv('USER_PERMISSIONS_CALENDAR_ALLOW_PUBLIC_SHARING', 'False').lower() == 'true' 

1839) 

1840 

1841USER_PERMISSIONS_ACCESS_GRANTS_ALLOW_USERS = ( 

1842 os.getenv('USER_PERMISSIONS_ACCESS_GRANTS_ALLOW_USERS', 'True').lower() == 'true' 

1843) 

1844USER_PERMISSIONS_ACCESS_GRANTS_ALLOW_GROUPS = ( 

1845 os.getenv('USER_PERMISSIONS_ACCESS_GRANTS_ALLOW_GROUPS', 'True').lower() == 'true' 

1846) 

1847 

1848 

1849USER_PERMISSIONS_CHAT_CONTROLS = os.getenv('USER_PERMISSIONS_CHAT_CONTROLS', 'True').lower() == 'true' 

1850 

1851USER_PERMISSIONS_CHAT_VALVES = os.getenv('USER_PERMISSIONS_CHAT_VALVES', 'True').lower() == 'true' 

1852 

1853USER_PERMISSIONS_CHAT_SYSTEM_PROMPT = os.getenv('USER_PERMISSIONS_CHAT_SYSTEM_PROMPT', 'True').lower() == 'true' 

1854 

1855USER_PERMISSIONS_CHAT_PARAMS = os.getenv('USER_PERMISSIONS_CHAT_PARAMS', 'True').lower() == 'true' 

1856 

1857USER_PERMISSIONS_CHAT_FILE_UPLOAD = os.getenv('USER_PERMISSIONS_CHAT_FILE_UPLOAD', 'True').lower() == 'true' 

1858 

1859USER_PERMISSIONS_CHAT_WEB_UPLOAD = os.getenv('USER_PERMISSIONS_CHAT_WEB_UPLOAD', 'True').lower() == 'true' 

1860 

1861USER_PERMISSIONS_CHAT_DELETE = os.getenv('USER_PERMISSIONS_CHAT_DELETE', 'True').lower() == 'true' 

1862 

1863USER_PERMISSIONS_CHAT_DELETE_MESSAGE = os.getenv('USER_PERMISSIONS_CHAT_DELETE_MESSAGE', 'True').lower() == 'true' 

1864 

1865USER_PERMISSIONS_CHAT_CONTINUE_RESPONSE = os.getenv('USER_PERMISSIONS_CHAT_CONTINUE_RESPONSE', 'True').lower() == 'true' 

1866 

1867USER_PERMISSIONS_CHAT_REGENERATE_RESPONSE = ( 

1868 os.getenv('USER_PERMISSIONS_CHAT_REGENERATE_RESPONSE', 'True').lower() == 'true' 

1869) 

1870 

1871USER_PERMISSIONS_CHAT_RATE_RESPONSE = os.getenv('USER_PERMISSIONS_CHAT_RATE_RESPONSE', 'True').lower() == 'true' 

1872 

1873USER_PERMISSIONS_CHAT_EDIT = os.getenv('USER_PERMISSIONS_CHAT_EDIT', 'True').lower() == 'true' 

1874 

1875USER_PERMISSIONS_CHAT_SHARE = os.getenv('USER_PERMISSIONS_CHAT_SHARE', 'True').lower() == 'true' 

1876 

1877USER_PERMISSIONS_CHAT_ALLOW_PUBLIC_SHARING = ( 

1878 os.getenv('USER_PERMISSIONS_CHAT_ALLOW_PUBLIC_SHARING', 'False').lower() == 'true' 

1879) 

1880 

1881USER_PERMISSIONS_CHAT_ALLOW_OPEN_SHARING = ( 

1882 os.getenv('USER_PERMISSIONS_CHAT_ALLOW_OPEN_SHARING', 'False').lower() == 'true' 

1883) 

1884 

1885USER_PERMISSIONS_CHAT_EXPORT = os.getenv('USER_PERMISSIONS_CHAT_EXPORT', 'True').lower() == 'true' 

1886 

1887USER_PERMISSIONS_CHAT_IMPORT = os.getenv('USER_PERMISSIONS_CHAT_IMPORT', 'True').lower() == 'true' 

1888 

1889USER_PERMISSIONS_CHAT_STT = os.getenv('USER_PERMISSIONS_CHAT_STT', 'True').lower() == 'true' 

1890 

1891USER_PERMISSIONS_CHAT_TTS = os.getenv('USER_PERMISSIONS_CHAT_TTS', 'True').lower() == 'true' 

1892 

1893USER_PERMISSIONS_CHAT_CALL = os.getenv('USER_PERMISSIONS_CHAT_CALL', 'True').lower() == 'true' 

1894 

1895USER_PERMISSIONS_CHAT_MULTIPLE_MODELS = os.getenv('USER_PERMISSIONS_CHAT_MULTIPLE_MODELS', 'True').lower() == 'true' 

1896 

1897USER_PERMISSIONS_CHAT_TEMPORARY = os.getenv('USER_PERMISSIONS_CHAT_TEMPORARY', 'True').lower() == 'true' 

1898 

1899USER_PERMISSIONS_CHAT_TEMPORARY_ENFORCED = ( 

1900 os.getenv('USER_PERMISSIONS_CHAT_TEMPORARY_ENFORCED', 'False').lower() == 'true' 

1901) 

1902 

1903 

1904USER_PERMISSIONS_FEATURES_DIRECT_TOOL_SERVERS = ( 

1905 os.getenv('USER_PERMISSIONS_FEATURES_DIRECT_TOOL_SERVERS', 'False').lower() == 'true' 

1906) 

1907 

1908USER_PERMISSIONS_FEATURES_WEB_SEARCH = os.getenv('USER_PERMISSIONS_FEATURES_WEB_SEARCH', 'True').lower() == 'true' 

1909 

1910USER_PERMISSIONS_FEATURES_IMAGE_GENERATION = ( 

1911 os.getenv('USER_PERMISSIONS_FEATURES_IMAGE_GENERATION', 'True').lower() == 'true' 

1912) 

1913 

1914USER_PERMISSIONS_FEATURES_CODE_INTERPRETER = ( 

1915 os.getenv('USER_PERMISSIONS_FEATURES_CODE_INTERPRETER', 'True').lower() == 'true' 

1916) 

1917 

1918USER_PERMISSIONS_FEATURES_FOLDERS = os.getenv('USER_PERMISSIONS_FEATURES_FOLDERS', 'True').lower() == 'true' 

1919 

1920USER_PERMISSIONS_FEATURES_NOTES = os.getenv('USER_PERMISSIONS_FEATURES_NOTES', 'True').lower() == 'true' 

1921 

1922USER_PERMISSIONS_FEATURES_CHANNELS = os.getenv('USER_PERMISSIONS_FEATURES_CHANNELS', 'True').lower() == 'true' 

1923 

1924USER_PERMISSIONS_FEATURES_API_KEYS = os.getenv('USER_PERMISSIONS_FEATURES_API_KEYS', 'False').lower() == 'true' 

1925 

1926USER_PERMISSIONS_FEATURES_MEMORIES = os.getenv('USER_PERMISSIONS_FEATURES_MEMORIES', 'True').lower() == 'true' 

1927 

1928USER_PERMISSIONS_FEATURES_AUTOMATIONS = os.getenv('USER_PERMISSIONS_FEATURES_AUTOMATIONS', 'False').lower() == 'true' 

1929 

1930USER_PERMISSIONS_FEATURES_CALENDAR = os.getenv('USER_PERMISSIONS_FEATURES_CALENDAR', 'True').lower() == 'true' 

1931 

1932USER_PERMISSIONS_FEATURES_USER_WEBHOOKS = ( 

1933 os.getenv('USER_PERMISSIONS_FEATURES_USER_WEBHOOKS', 'False').lower() == 'true' 

1934) 

1935 

1936 

1937USER_PERMISSIONS_SETTINGS_INTERFACE = os.getenv('USER_PERMISSIONS_SETTINGS_INTERFACE', 'True').lower() == 'true' 

1938 

1939 

1940DEFAULT_USER_PERMISSIONS = { 

1941 'workspace': { 

1942 'models': USER_PERMISSIONS_WORKSPACE_MODELS_ACCESS, 

1943 'knowledge': USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ACCESS, 

1944 'prompts': USER_PERMISSIONS_WORKSPACE_PROMPTS_ACCESS, 

1945 'tools': USER_PERMISSIONS_WORKSPACE_TOOLS_ACCESS, 

1946 'skills': USER_PERMISSIONS_WORKSPACE_SKILLS_ACCESS, 

1947 'models_import': USER_PERMISSIONS_WORKSPACE_MODELS_IMPORT, 

1948 'models_export': USER_PERMISSIONS_WORKSPACE_MODELS_EXPORT, 

1949 'prompts_import': USER_PERMISSIONS_WORKSPACE_PROMPTS_IMPORT, 

1950 'prompts_export': USER_PERMISSIONS_WORKSPACE_PROMPTS_EXPORT, 

1951 'tools_import': USER_PERMISSIONS_WORKSPACE_TOOLS_IMPORT, 

1952 'tools_export': USER_PERMISSIONS_WORKSPACE_TOOLS_EXPORT, 

1953 'skills_import': USER_PERMISSIONS_WORKSPACE_SKILLS_IMPORT, 

1954 'skills_export': USER_PERMISSIONS_WORKSPACE_SKILLS_EXPORT, 

1955 }, 

1956 'sharing': { 

1957 'models': USER_PERMISSIONS_WORKSPACE_MODELS_ALLOW_SHARING, 

1958 'public_models': USER_PERMISSIONS_WORKSPACE_MODELS_ALLOW_PUBLIC_SHARING, 

1959 'knowledge': USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ALLOW_SHARING, 

1960 'public_knowledge': USER_PERMISSIONS_WORKSPACE_KNOWLEDGE_ALLOW_PUBLIC_SHARING, 

1961 'prompts': USER_PERMISSIONS_WORKSPACE_PROMPTS_ALLOW_SHARING, 

1962 'public_prompts': USER_PERMISSIONS_WORKSPACE_PROMPTS_ALLOW_PUBLIC_SHARING, 

1963 'tools': USER_PERMISSIONS_WORKSPACE_TOOLS_ALLOW_SHARING, 

1964 'public_tools': USER_PERMISSIONS_WORKSPACE_TOOLS_ALLOW_PUBLIC_SHARING, 

1965 'skills': USER_PERMISSIONS_WORKSPACE_SKILLS_ALLOW_SHARING, 

1966 'public_skills': USER_PERMISSIONS_WORKSPACE_SKILLS_ALLOW_PUBLIC_SHARING, 

1967 'notes': USER_PERMISSIONS_NOTES_ALLOW_SHARING, 

1968 'public_notes': USER_PERMISSIONS_NOTES_ALLOW_PUBLIC_SHARING, 

1969 'folders': USER_PERMISSIONS_FOLDERS_ALLOW_SHARING, 

1970 'public_chats': USER_PERMISSIONS_CHAT_ALLOW_PUBLIC_SHARING, 

1971 'open_chats': USER_PERMISSIONS_CHAT_ALLOW_OPEN_SHARING, 

1972 'public_calendars': USER_PERMISSIONS_CALENDAR_ALLOW_PUBLIC_SHARING, 

1973 }, 

1974 'access_grants': { 

1975 'allow_users': USER_PERMISSIONS_ACCESS_GRANTS_ALLOW_USERS, 

1976 'allow_groups': USER_PERMISSIONS_ACCESS_GRANTS_ALLOW_GROUPS, 

1977 }, 

1978 'chat': { 

1979 'controls': USER_PERMISSIONS_CHAT_CONTROLS, 

1980 'valves': USER_PERMISSIONS_CHAT_VALVES, 

1981 'system_prompt': USER_PERMISSIONS_CHAT_SYSTEM_PROMPT, 

1982 'params': USER_PERMISSIONS_CHAT_PARAMS, 

1983 'file_upload': USER_PERMISSIONS_CHAT_FILE_UPLOAD, 

1984 'web_upload': USER_PERMISSIONS_CHAT_WEB_UPLOAD, 

1985 'delete': USER_PERMISSIONS_CHAT_DELETE, 

1986 'delete_message': USER_PERMISSIONS_CHAT_DELETE_MESSAGE, 

1987 'continue_response': USER_PERMISSIONS_CHAT_CONTINUE_RESPONSE, 

1988 'regenerate_response': USER_PERMISSIONS_CHAT_REGENERATE_RESPONSE, 

1989 'rate_response': USER_PERMISSIONS_CHAT_RATE_RESPONSE, 

1990 'edit': USER_PERMISSIONS_CHAT_EDIT, 

1991 'share': USER_PERMISSIONS_CHAT_SHARE, 

1992 'export': USER_PERMISSIONS_CHAT_EXPORT, 

1993 'import': USER_PERMISSIONS_CHAT_IMPORT, 

1994 'stt': USER_PERMISSIONS_CHAT_STT, 

1995 'tts': USER_PERMISSIONS_CHAT_TTS, 

1996 'call': USER_PERMISSIONS_CHAT_CALL, 

1997 'multiple_models': USER_PERMISSIONS_CHAT_MULTIPLE_MODELS, 

1998 'temporary': USER_PERMISSIONS_CHAT_TEMPORARY, 

1999 'temporary_enforced': USER_PERMISSIONS_CHAT_TEMPORARY_ENFORCED, 

2000 }, 

2001 'features': { 

2002 # General features 

2003 'api_keys': USER_PERMISSIONS_FEATURES_API_KEYS, 

2004 'notes': USER_PERMISSIONS_FEATURES_NOTES, 

2005 'folders': USER_PERMISSIONS_FEATURES_FOLDERS, 

2006 'channels': USER_PERMISSIONS_FEATURES_CHANNELS, 

2007 'direct_tool_servers': USER_PERMISSIONS_FEATURES_DIRECT_TOOL_SERVERS, 

2008 # Chat features 

2009 'web_search': USER_PERMISSIONS_FEATURES_WEB_SEARCH, 

2010 'image_generation': USER_PERMISSIONS_FEATURES_IMAGE_GENERATION, 

2011 'code_interpreter': USER_PERMISSIONS_FEATURES_CODE_INTERPRETER, 

2012 'memories': USER_PERMISSIONS_FEATURES_MEMORIES, 

2013 'automations': USER_PERMISSIONS_FEATURES_AUTOMATIONS, 

2014 'calendar': USER_PERMISSIONS_FEATURES_CALENDAR, 

2015 'webhooks': USER_PERMISSIONS_FEATURES_USER_WEBHOOKS, 

2016 }, 

2017 'settings': { 

2018 'interface': USER_PERMISSIONS_SETTINGS_INTERFACE, 

2019 }, 

2020} 

2021 

2022USER_PERMISSIONS = DEFAULT_USER_PERMISSIONS 

2023 

2024ENABLE_FOLDERS = os.getenv('ENABLE_FOLDERS', 'True').lower() == 'true' 

2025 

2026FOLDER_MAX_FILE_COUNT = os.getenv('FOLDER_MAX_FILE_COUNT', '') 

2027 

2028ENABLE_CHANNELS = os.getenv('ENABLE_CHANNELS', 'False').lower() == 'true' 

2029 

2030CHANNEL_MODEL_RESPONSE_MODE = os.getenv('CHANNEL_MODEL_RESPONSE_MODE', 'thread') 

2031 

2032ENABLE_CALENDAR = os.getenv('ENABLE_CALENDAR', 'True').lower() == 'true' 

2033 

2034ENABLE_AUTOMATIONS = os.getenv('ENABLE_AUTOMATIONS', 'True').lower() == 'true' 

2035 

2036ENABLE_SUBAGENTS = os.getenv('ENABLE_SUBAGENTS', 'False').lower() == 'true' 

2037SUBAGENTS_BACKGROUND_ENABLED = os.getenv('SUBAGENTS_BACKGROUND_ENABLED', 'False').lower() == 'true' 

2038SUBAGENTS_MAX_CONCURRENT = int(os.getenv('SUBAGENTS_MAX_CONCURRENT', '20')) 

2039SUBAGENTS_MAX_ASYNC = int(os.getenv('SUBAGENTS_MAX_ASYNC', '20')) 

2040SUBAGENTS_MAX_ITERATIONS = int(os.getenv('SUBAGENTS_MAX_ITERATIONS', '30')) 

2041SUBAGENTS_MAX_OUTPUT = int(os.getenv('SUBAGENTS_MAX_OUTPUT', '30000')) 

2042SUBAGENTS_SYSTEM_PROMPT = os.getenv('SUBAGENTS_SYSTEM_PROMPT', '') 

2043 

2044AUTOMATION_MAX_COUNT = os.getenv('AUTOMATION_MAX_COUNT', '') 

2045 

2046AUTOMATION_MIN_INTERVAL = os.getenv('AUTOMATION_MIN_INTERVAL', '') 

2047 

2048AUTOMATION_AUTH_TOKEN_EXPIRES_IN = os.getenv('AUTOMATION_AUTH_TOKEN_EXPIRES_IN', '1h') 

2049 

2050ENABLE_NOTES = os.getenv('ENABLE_NOTES', 'True').lower() == 'true' 

2051 

2052ENABLE_USER_STATUS = os.getenv('ENABLE_USER_STATUS', 'True').lower() == 'true' 

2053 

2054ENABLE_EVALUATION_ARENA_MODELS = os.getenv('ENABLE_EVALUATION_ARENA_MODELS', 'True').lower() == 'true' 

2055try: 

2056 evaluation_arena_models = JSONCodec.loads(os.getenv('EVALUATION_ARENA_MODELS', '[]')) 

2057 if not isinstance(evaluation_arena_models, list) or not all( 2057 ↛ 2060line 2057 didn't jump to line 2060 because the condition on line 2057 was never true

2058 isinstance(model, dict) for model in evaluation_arena_models 

2059 ): 

2060 raise ValueError('EVALUATION_ARENA_MODELS must be a JSON list of objects') 

2061except Exception as e: 

2062 log.exception(f'Error loading EVALUATION_ARENA_MODELS: {e}') 

2063 evaluation_arena_models = [] 

2064 

2065EVALUATION_ARENA_MODELS = evaluation_arena_models 

2066 

2067DEFAULT_ARENA_MODEL = { 

2068 'id': 'arena-model', 

2069 'name': 'Arena Model', 

2070 'meta': { 

2071 # LICENSE covers this Open WebUI fallback logo. 

2072 # Do not alter, remove, obscure, or replace it except as LICENSE permits: 

2073 # https://docs.openwebui.com/license. 

2074 'profile_image_url': '/favicon.png', 

2075 'description': 'Submit your questions to anonymous AI chatbots and vote on the best response.', 

2076 'model_ids': None, 

2077 }, 

2078} 

2079 

2080WEBHOOK_URL = os.getenv('WEBHOOK_URL', '') 

2081 

2082ENABLE_ADMIN_EXPORT = os.getenv('ENABLE_ADMIN_EXPORT', 'True').lower() == 'true' 

2083 

2084ENABLE_ADMIN_WORKSPACE_CONTENT_ACCESS = os.getenv('ENABLE_ADMIN_WORKSPACE_CONTENT_ACCESS', 'True').lower() == 'true' 

2085 

2086BYPASS_ADMIN_ACCESS_CONTROL = ( 

2087 os.getenv( 

2088 'BYPASS_ADMIN_ACCESS_CONTROL', 

2089 os.getenv('ENABLE_ADMIN_WORKSPACE_CONTENT_ACCESS', 'True'), 

2090 ).lower() 

2091 == 'true' 

2092) 

2093 

2094ENABLE_ADMIN_ANALYTICS = os.getenv('ENABLE_ADMIN_ANALYTICS', 'True').lower() == 'true' 

2095 

2096ENABLE_COMMUNITY_SHARING = os.getenv('ENABLE_COMMUNITY_SHARING', 'True').lower() == 'true' 

2097 

2098ENABLE_MESSAGE_RATING = os.getenv('ENABLE_MESSAGE_RATING', 'True').lower() == 'true' 

2099 

2100ENABLE_USER_WEBHOOKS = os.getenv('ENABLE_USER_WEBHOOKS', 'False').lower() == 'true' 

2101 

2102# FastAPI / AnyIO settings 

2103THREAD_POOL_SIZE = os.getenv('THREAD_POOL_SIZE', None) 

2104THREAD_POOL_THREAD_NAME_PREFIX = os.getenv('THREAD_POOL_THREAD_NAME_PREFIX', '') 

2105 

2106if THREAD_POOL_SIZE is not None and isinstance(THREAD_POOL_SIZE, str): 2106 ↛ 2107line 2106 didn't jump to line 2107 because the condition on line 2106 was never true

2107 try: 

2108 THREAD_POOL_SIZE = int(THREAD_POOL_SIZE) 

2109 except ValueError: 

2110 log.warning(f'THREAD_POOL_SIZE is not a valid integer: {THREAD_POOL_SIZE}. Defaulting to None.') 

2111 THREAD_POOL_SIZE = None 

2112 

2113 

2114def validate_cors_origin(origin): 

2115 parsed_url = urlparse(origin) 

2116 

2117 # Check if the scheme is either http or https, or a custom scheme 

2118 schemes = ['http', 'https'] + CORS_ALLOW_CUSTOM_SCHEME 

2119 if parsed_url.scheme not in schemes: 

2120 raise ValueError( 

2121 f"Invalid scheme in CORS_ALLOW_ORIGIN: '{origin}'. Only 'http' and 'https' and CORS_ALLOW_CUSTOM_SCHEME are allowed." 

2122 ) 

2123 

2124 # Ensure that the netloc (domain + port) is present, indicating it's a valid URL 

2125 if not parsed_url.netloc: 

2126 raise ValueError(f"Invalid URL structure in CORS_ALLOW_ORIGIN: '{origin}'.") 

2127 

2128 

2129# For production, you should only need one host as 

2130# fastapi serves the svelte-kit built frontend and backend from the same host and port. 

2131# To test CORS_ALLOW_ORIGIN locally, you can set something like 

2132# CORS_ALLOW_ORIGIN=http://localhost:5173;http://localhost:8080 

2133# in your .env file depending on your frontend port, 5173 in this case. 

2134CORS_ALLOW_ORIGIN = os.getenv('CORS_ALLOW_ORIGIN', '*').split(';') 

2135 

2136# Allows custom URL schemes (e.g., app://) to be used as origins for CORS. 

2137# Useful for local development or desktop clients with schemes like app:// or other custom protocols. 

2138# Provide a semicolon-separated list of allowed schemes in the environment variable CORS_ALLOW_CUSTOM_SCHEMES. 

2139CORS_ALLOW_CUSTOM_SCHEME = os.getenv('CORS_ALLOW_CUSTOM_SCHEME', '').split(';') 

2140 

2141if CORS_ALLOW_ORIGIN == ['*']: 2141 ↛ 2146line 2141 didn't jump to line 2146 because the condition on line 2141 was always true

2142 log.warning("\n\nWARNING: CORS_ALLOW_ORIGIN IS SET TO '*' - NOT RECOMMENDED FOR PRODUCTION DEPLOYMENTS.\n") 

2143else: 

2144 # You have to pick between a single wildcard or a list of origins. 

2145 # Doing both will result in CORS errors in the browser. 

2146 for origin in CORS_ALLOW_ORIGIN: 

2147 validate_cors_origin(origin) 

2148 

2149 

2150class BannerModel(BaseModel): 

2151 i18n: dict[str, dict[str, str]] | None = None 

2152 id: str 

2153 type: str 

2154 title: str | None = None 

2155 content: str 

2156 dismissible: bool 

2157 timestamp: int 

2158 

2159 

2160try: 

2161 banners = JSONCodec.loads(os.getenv('WEBUI_BANNERS', '[]')) 

2162 banners = [BannerModel(**banner) for banner in banners] 

2163except Exception as e: 

2164 log.exception(f'Error loading WEBUI_BANNERS: {e}') 

2165 banners = [] 

2166 

2167WEBUI_BANNERS = banners 

2168 

2169 

2170SHOW_ADMIN_DETAILS = os.getenv('SHOW_ADMIN_DETAILS', 'true').lower() == 'true' 

2171 

2172ADMIN_EMAIL = os.getenv('ADMIN_EMAIL', None) 

2173 

2174 

2175#################################### 

2176# TASKS 

2177#################################### 

2178 

2179 

2180TASK_MODEL = os.getenv('TASK_MODEL', '') 

2181 

2182TASK_MODEL_EXTERNAL = os.getenv('TASK_MODEL_EXTERNAL', '') 

2183 

2184try: 

2185 task_model_params = JSONCodec.loads(os.getenv('TASK_MODEL_PARAMS', '{}')) 

2186except Exception as e: 

2187 log.exception(f'Error loading TASK_MODEL_PARAMS: {e}') 

2188 task_model_params = {} 

2189 

2190TASK_MODEL_PARAMS = task_model_params 

2191 

2192CONTEXT_COMPACTION_MODEL = os.getenv('CONTEXT_COMPACTION_MODEL', '') 

2193 

2194ENABLE_CONTEXT_COMPACTION = os.getenv('ENABLE_CONTEXT_COMPACTION', 'False').lower() == 'true' 

2195 

2196ENABLE_TOOL_PERMISSIONS = os.getenv('ENABLE_TOOL_PERMISSIONS', 'False').lower() == 'true' 

2197 

2198CONTEXT_COMPACTION_TOKEN_THRESHOLD = int(os.getenv('CONTEXT_COMPACTION_TOKEN_THRESHOLD', '80000')) 

2199 

2200_CONTEXT_COMPACTION_TOKEN_CAP = os.getenv('CONTEXT_COMPACTION_TOKEN_CAP') 

2201CONTEXT_COMPACTION_TOKEN_CAP = int(_CONTEXT_COMPACTION_TOKEN_CAP) if _CONTEXT_COMPACTION_TOKEN_CAP else None 

2202 

2203CONTEXT_COMPACTION_RETENTION_PERCENTAGE = min( 

2204 50, max(10, int(os.getenv('CONTEXT_COMPACTION_RETENTION_PERCENTAGE', '40'))) 

2205) 

2206 

2207CONTEXT_COMPACTION_PROMPT_TEMPLATE = os.getenv('CONTEXT_COMPACTION_PROMPT_TEMPLATE', '') 

2208 

2209TITLE_GENERATION_PROMPT_TEMPLATE = os.getenv('TITLE_GENERATION_PROMPT_TEMPLATE', '') 

2210 

2211DEFAULT_TITLE_GENERATION_PROMPT_TEMPLATE = """### Task: 

2212Generate a concise title summarizing the chat history. 

2213### Guidelines: 

2214- The title should clearly represent the main theme or subject of the conversation. 

2215- Keep it short: 2-4 words is best. 

2216- Do not use emojis, quotation marks, or special formatting. 

2217- Write the title in the chat's primary language; default to English if multilingual. 

2218- Prioritize accuracy over creativity. 

2219- Your entire response must consist solely of the JSON object, without any introductory or concluding text. 

2220- The output must be a single, raw JSON object, without any markdown code fences or other encapsulating text. 

2221- Ensure no conversational text, affirmations, or explanations precede or follow the raw JSON output, as this will cause direct parsing failure. 

2222### Output: 

2223JSON format: { "title": "your concise title here" } 

2224### Examples: 

2225- { "title": "Stock Trends" }, 

2226- { "title": "Chocolate Chip Cookies" }, 

2227- { "title": "Music Streaming" }, 

2228- { "title": "Remote Work" } 

2229### Chat History: 

2230<chat_history> 

2231{{MESSAGES:END:2}} 

2232</chat_history>""" 

2233 

2234TAGS_GENERATION_PROMPT_TEMPLATE = os.getenv('TAGS_GENERATION_PROMPT_TEMPLATE', '') 

2235 

2236DEFAULT_TAGS_GENERATION_PROMPT_TEMPLATE = """### Task: 

2237Generate 1-3 broad tags categorizing the main themes of the chat history, along with 1-3 more specific subtopic tags. 

2238 

2239### Guidelines: 

2240- Start with high-level domains (e.g. Science, Technology, Philosophy, Arts, Politics, Business, Health, Sports, Entertainment, Education) 

2241- Consider including relevant subfields/subdomains if they are strongly represented throughout the conversation 

2242- If content is too short (less than 3 messages) or too diverse, use only ["General"] 

2243- Use the chat's primary language; default to English if multilingual 

2244- Prioritize accuracy over specificity 

2245 

2246### Output: 

2247JSON format: { "tags": ["tag1", "tag2", "tag3"] } 

2248 

2249### Chat History: 

2250<chat_history> 

2251{{MESSAGES:END:6}} 

2252</chat_history>""" 

2253 

2254IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE = os.getenv('IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE', '') 

2255 

2256DEFAULT_IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE = """### Task: 

2257Generate a detailed prompt for am image generation task based on the given language and context. Describe the image as if you were explaining it to someone who cannot see it. Include relevant details, colors, shapes, and any other important elements. 

2258 

2259### Guidelines: 

2260- Be descriptive and detailed, focusing on the most important aspects of the image. 

2261- Avoid making assumptions or adding information not present in the image. 

2262- Use the chat's primary language; default to English if multilingual. 

2263- If the image is too complex, focus on the most prominent elements. 

2264 

2265### Output: 

2266Strictly return in JSON format: 

2267{ 

2268 "prompt": "Your detailed description here." 

2269} 

2270 

2271### Chat History: 

2272<chat_history> 

2273{{MESSAGES:END:6}} 

2274</chat_history>""" 

2275 

2276 

2277FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = os.getenv('FOLLOW_UP_GENERATION_PROMPT_TEMPLATE', '') 

2278 

2279DEFAULT_FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = """### Task: 

2280Suggest 3-5 relevant follow-up questions or prompts that the user might naturally ask next in this conversation as a **user**, based on the chat history, to help continue or deepen the discussion. 

2281### Guidelines: 

2282- Write all follow-up questions from the user’s point of view, directed to the assistant. 

2283- Make questions concise, clear, and directly related to the discussed topic(s). 

2284- Only suggest follow-ups that make sense given the chat content and do not repeat what was already covered. 

2285- If the conversation is very short or not specific, suggest more general (but relevant) follow-ups the user might ask. 

2286- Use the conversation's primary language; default to English if multilingual. 

2287- Response must be a JSON object with a "follow_ups" key containing an array of strings, no extra text or formatting. 

2288### Output: 

2289JSON format: { "follow_ups": ["Question 1?", "Question 2?", "Question 3?"] } 

2290### Chat History: 

2291<chat_history> 

2292{{MESSAGES:END:6}} 

2293</chat_history>""" 

2294 

2295ENABLE_FOLLOW_UP_GENERATION = os.getenv('ENABLE_FOLLOW_UP_GENERATION', 'True').lower() == 'true' 

2296 

2297ENABLE_TAGS_GENERATION = os.getenv('ENABLE_TAGS_GENERATION', 'True').lower() == 'true' 

2298 

2299ENABLE_TITLE_GENERATION = os.getenv('ENABLE_TITLE_GENERATION', 'True').lower() == 'true' 

2300 

2301 

2302ENABLE_SEARCH_QUERY_GENERATION = os.getenv('ENABLE_SEARCH_QUERY_GENERATION', 'True').lower() == 'true' 

2303 

2304ENABLE_RETRIEVAL_QUERY_GENERATION = os.getenv('ENABLE_RETRIEVAL_QUERY_GENERATION', 'True').lower() == 'true' 

2305 

2306 

2307QUERY_GENERATION_PROMPT_TEMPLATE = os.getenv('QUERY_GENERATION_PROMPT_TEMPLATE', '') 

2308 

2309DEFAULT_QUERY_GENERATION_PROMPT_TEMPLATE = """### Task: 

2310Analyze the chat history to determine the necessity of generating search queries, in the given language. By default, **prioritize generating 1-3 broad and relevant search queries** unless it is absolutely certain that no additional information is required. The aim is to retrieve comprehensive, updated, and valuable information even with minimal uncertainty. If no search is unequivocally needed, return an empty list. 

2311 

2312### Guidelines: 

2313- Respond **EXCLUSIVELY** with a JSON object. Any form of extra commentary, explanation, or additional text is strictly prohibited. 

2314- When generating search queries, respond in the format: { "queries": ["query1", "query2"] }, ensuring each query is distinct, concise, and relevant to the topic. 

2315- If and only if it is entirely certain that no useful results can be retrieved by a search, return: { "queries": [] }. 

2316- Err on the side of suggesting search queries if there is **any chance** they might provide useful or updated information. 

2317- Be concise and focused on composing high-quality search queries, avoiding unnecessary elaboration, commentary, or assumptions. 

2318- Today's date is: {{CURRENT_DATE}}. 

2319- Always prioritize providing actionable and broad queries that maximize informational coverage. 

2320 

2321### Output: 

2322Strictly return in JSON format:  

2323{ 

2324 "queries": ["query1", "query2"] 

2325} 

2326 

2327### Chat History: 

2328<chat_history> 

2329{{MESSAGES:END:6}} 

2330</chat_history> 

2331""" 

2332 

2333ENABLE_AUTOCOMPLETE_GENERATION = os.getenv('ENABLE_AUTOCOMPLETE_GENERATION', 'False').lower() == 'true' 

2334 

2335AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH = int(os.getenv('AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH', '-1')) 

2336 

2337AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE = os.getenv('AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE', '') 

2338 

2339 

2340DEFAULT_AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE = """### Task: 

2341You are an autocompletion system. Continue the text in `<text>` based on the **completion type** in `<type>` and the given language.  

2342 

2343### **Instructions**: 

23441. Analyze `<text>` for context and meaning.  

23452. Use `<type>` to guide your output:  

2346 - **General**: Provide a natural, concise continuation.  

2347 - **Search Query**: Complete as if generating a realistic search query.  

23483. Start as if you are directly continuing `<text>`. Do **not** repeat, paraphrase, or respond as a model. Simply complete the text.  

23494. Ensure the continuation: 

2350 - Flows naturally from `<text>`.  

2351 - Avoids repetition, overexplaining, or unrelated ideas.  

23525. If unsure, return: `{ "text": "" }`.  

2353 

2354### **Output Rules**: 

2355- Respond only in JSON format: `{ "text": "<your_completion>" }`. 

2356 

2357### **Examples**: 

2358#### Example 1:  

2359Input:  

2360<type>General</type>  

2361<text>The sun was setting over the horizon, painting the sky</text>  

2362Output:  

2363{ "text": "with vibrant shades of orange and pink." } 

2364 

2365#### Example 2:  

2366Input:  

2367<type>Search Query</type>  

2368<text>Top-rated restaurants in</text>  

2369Output:  

2370{ "text": "New York City for Italian cuisine." }  

2371 

2372--- 

2373### Context: 

2374<chat_history> 

2375{{MESSAGES:END:6}} 

2376</chat_history> 

2377<type>{{TYPE}}</type>  

2378<text>{{PROMPT}}</text>  

2379#### Output: 

2380""" 

2381 

2382 

2383VOICE_MODE_PROMPT_TEMPLATE = os.getenv('VOICE_MODE_PROMPT_TEMPLATE', '') 

2384 

2385ENABLE_VOICE_MODE_PROMPT = os.getenv('ENABLE_VOICE_MODE_PROMPT', 'True').lower() == 'true' 

2386 

2387DEFAULT_VOICE_MODE_PROMPT_TEMPLATE = """You are a friendly, concise voice assistant. 

2388 

2389Everything you say will be spoken aloud. 

2390Keep responses short, clear, and natural. 

2391 

2392STYLE: 

2393- Use simple words and short sentences. 

2394- Sound warm and conversational. 

2395- Avoid long explanations, lists, or complex phrasing. 

2396 

2397BEHAVIOR: 

2398- Give the quickest helpful answer first. 

2399- Offer extra detail only if needed. 

2400- Ask for clarification only when necessary. 

2401 

2402VOICE OPTIMIZATION: 

2403- Break information into small, easy-to-hear chunks. 

2404- Avoid dense wording or anything that sounds like reading text. 

2405 

2406ERROR HANDLING: 

2407- If unsure, say so briefly and offer options. 

2408- If something is unsafe or impossible, decline kindly and suggest a safe alternative. 

2409 

2410Stay consistent, helpful, and easy to listen to.""" 

2411 

2412TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = os.getenv('TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE', '') 

2413 

2414 

2415DEFAULT_TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = """Available Tools: {{TOOLS}} 

2416 

2417Your task is to choose and return the correct tool(s) from the list of available tools based on the query. Follow these guidelines: 

2418 

2419- Return only the JSON object, without any additional text or explanation. 

2420 

2421- If no tools match the query, return an empty array:  

2422 { 

2423 "tool_calls": [] 

2424 } 

2425 

2426- If one or more tools match the query, construct a JSON response containing a "tool_calls" array with objects that include: 

2427 - "name": The tool's name. 

2428 - "parameters": A dictionary of required parameters and their corresponding values. 

2429 

2430The format for the JSON response is strictly: 

2431{ 

2432 "tool_calls": [ 

2433 {"name": "toolName1", "parameters": {"key1": "value1"}}, 

2434 {"name": "toolName2", "parameters": {"key2": "value2"}} 

2435 ] 

2436}""" 

2437 

2438 

2439DEFAULT_EMOJI_GENERATION_PROMPT_TEMPLATE = """Your task is to reflect the speaker's likely facial expression through a fitting emoji. Interpret emotions from the message and reflect their facial expression using fitting, diverse emojis (e.g., 😊, 😢, 😡, 😱). 

2440 

2441Message: ```{{prompt}}```""" 

2442 

2443DEFAULT_MOA_GENERATION_PROMPT_TEMPLATE = """You have been provided with a set of responses from various models to the latest user query: "{{prompt}}" 

2444 

2445Your task is to synthesize these responses into a single, high-quality response. It is crucial to critically evaluate the information provided in these responses, recognizing that some of it may be biased or incorrect. Your response should not simply replicate the given answers but should offer a refined, accurate, and comprehensive reply to the instruction. Ensure your response is well-structured, coherent, and adheres to the highest standards of accuracy and reliability. 

2446 

2447Responses from models: {{responses}}""" 

2448 

2449 

2450#################################### 

2451# Auth 

2452#################################### 

2453 

2454ENABLE_API_KEYS = os.getenv('ENABLE_API_KEYS', 'False').lower() == 'true' 

2455 

2456ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS = ( 

2457 os.getenv( 

2458 'ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS', 

2459 os.getenv('ENABLE_API_KEY_ENDPOINT_RESTRICTIONS', 'False'), 

2460 ).lower() 

2461 == 'true' 

2462) 

2463 

2464API_KEYS_ALLOWED_ENDPOINTS = os.getenv('API_KEYS_ALLOWED_ENDPOINTS', os.getenv('API_KEY_ALLOWED_ENDPOINTS', '')) 

2465 

2466JWT_EXPIRES_IN = os.getenv('JWT_EXPIRES_IN', '4w') 

2467 

2468if JWT_EXPIRES_IN == '-1': 2468 ↛ 2469line 2468 didn't jump to line 2469 because the condition on line 2468 was never true

2469 log.warning( 

2470 "⚠️ SECURITY WARNING: JWT_EXPIRES_IN is set to '-1'\n" 

2471 ' See: https://docs.openwebui.com/reference/env-configuration\n' 

2472 ) 

2473 

2474#################################### 

2475# OAuth config 

2476#################################### 

2477 

2478# Master switch for OAuth/OIDC sign-in. Defaults to enabled so existing 

2479# deployments that already have a provider configured keep working; admins can 

2480# turn it off to disable OAuth login without clearing their provider settings. 

2481ENABLE_OAUTH = os.getenv('ENABLE_OAUTH', 'True').lower() == 'true' 

2482 

2483ENABLE_OAUTH_SIGNUP = os.getenv('ENABLE_OAUTH_SIGNUP', 'False').lower() == 'true' 

2484 

2485OAUTH_AUTO_REDIRECT = os.getenv('OAUTH_AUTO_REDIRECT', 'False').lower() == 'true' 

2486 

2487OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE = os.getenv('OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE', 'False').lower() == 'true' 

2488 

2489 

2490OAUTH_MERGE_ACCOUNTS_BY_EMAIL = os.getenv('OAUTH_MERGE_ACCOUNTS_BY_EMAIL', 'False').lower() == 'true' 

2491 

2492OAUTH_PROVIDERS = {} 

2493 

2494GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID', '') 

2495 

2496GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET', '') 

2497 

2498 

2499GOOGLE_OAUTH_SCOPE = os.getenv('GOOGLE_OAUTH_SCOPE', 'openid email profile') 

2500 

2501GOOGLE_REDIRECT_URI = os.getenv('GOOGLE_REDIRECT_URI', '') 

2502 

2503GOOGLE_OAUTH_AUTHORIZE_PARAMS = {} 

2504_google_oauth_authorize_params = os.getenv('GOOGLE_OAUTH_AUTHORIZE_PARAMS', '') 

2505if _google_oauth_authorize_params: 2505 ↛ 2506line 2505 didn't jump to line 2506 because the condition on line 2505 was never true

2506 try: 

2507 _parsed = JSONCodec.loads(_google_oauth_authorize_params) 

2508 if isinstance(_parsed, dict): 

2509 GOOGLE_OAUTH_AUTHORIZE_PARAMS = _parsed 

2510 else: 

2511 log.warning('GOOGLE_OAUTH_AUTHORIZE_PARAMS must be a JSON object, ignoring') 

2512 except (JSONCodec.JSONDecodeError, TypeError): 

2513 log.warning('GOOGLE_OAUTH_AUTHORIZE_PARAMS is not valid JSON, ignoring') 

2514 

2515MICROSOFT_CLIENT_ID = os.getenv('MICROSOFT_CLIENT_ID', '') 

2516 

2517MICROSOFT_CLIENT_SECRET = os.getenv('MICROSOFT_CLIENT_SECRET', '') 

2518 

2519MICROSOFT_CLIENT_TENANT_ID = os.getenv('MICROSOFT_CLIENT_TENANT_ID', '') 

2520 

2521MICROSOFT_CLIENT_LOGIN_BASE_URL = os.getenv('MICROSOFT_CLIENT_LOGIN_BASE_URL', 'https://login.microsoftonline.com') 

2522 

2523MICROSOFT_CLIENT_PICTURE_URL = os.getenv( 

2524 'MICROSOFT_CLIENT_PICTURE_URL', 

2525 'https://graph.microsoft.com/v1.0/me/photo/$value', 

2526) 

2527 

2528 

2529MICROSOFT_OAUTH_SCOPE = os.getenv('MICROSOFT_OAUTH_SCOPE', 'openid email profile') 

2530 

2531MICROSOFT_REDIRECT_URI = os.getenv('MICROSOFT_REDIRECT_URI', '') 

2532 

2533GITHUB_CLIENT_ID = os.getenv('GITHUB_CLIENT_ID', '') 

2534 

2535GITHUB_CLIENT_SECRET = os.getenv('GITHUB_CLIENT_SECRET', '') 

2536 

2537GITHUB_CLIENT_SCOPE = os.getenv('GITHUB_CLIENT_SCOPE', 'user:email') 

2538 

2539GITHUB_CLIENT_REDIRECT_URI = os.getenv('GITHUB_CLIENT_REDIRECT_URI', '') 

2540 

2541OAUTH_CLIENT_ID = os.getenv('OAUTH_CLIENT_ID', '') 

2542 

2543OAUTH_CLIENT_SECRET = os.getenv('OAUTH_CLIENT_SECRET', '') 

2544 

2545OPENID_PROVIDER_URL = os.getenv('OPENID_PROVIDER_URL', '') 

2546 

2547OPENID_END_SESSION_ENDPOINT = os.getenv('OPENID_END_SESSION_ENDPOINT', '') 

2548 

2549OPENID_REDIRECT_URI = os.getenv('OPENID_REDIRECT_URI', '') 

2550 

2551OAUTH_SCOPES = os.getenv('OAUTH_SCOPES', 'openid email profile') 

2552 

2553OAUTH_TIMEOUT = os.getenv('OAUTH_TIMEOUT', '') 

2554 

2555OAUTH_TOKEN_ENDPOINT_AUTH_METHOD = os.getenv('OAUTH_TOKEN_ENDPOINT_AUTH_METHOD', None) 

2556 

2557OAUTH_CODE_CHALLENGE_METHOD = os.getenv('OAUTH_CODE_CHALLENGE_METHOD', None) 

2558 

2559OAUTH_PROVIDER_NAME = os.getenv('OAUTH_PROVIDER_NAME', 'SSO') 

2560 

2561OAUTH_SUB_CLAIM = os.getenv('OAUTH_SUB_CLAIM', None) 

2562 

2563OAUTH_USERNAME_CLAIM = os.getenv('OAUTH_USERNAME_CLAIM', 'name') 

2564 

2565 

2566OAUTH_PICTURE_CLAIM = os.getenv('OAUTH_PICTURE_CLAIM', 'picture') 

2567 

2568OAUTH_EMAIL_CLAIM = os.getenv('OAUTH_EMAIL_CLAIM', 'email') 

2569 

2570OAUTH_GROUPS_CLAIM = os.getenv('OAUTH_GROUPS_CLAIM', os.getenv('OAUTH_GROUP_CLAIM', 'groups')) 

2571 

2572FEISHU_CLIENT_ID = os.getenv('FEISHU_CLIENT_ID', '') 

2573 

2574FEISHU_CLIENT_SECRET = os.getenv('FEISHU_CLIENT_SECRET', '') 

2575 

2576FEISHU_OAUTH_SCOPE = os.getenv('FEISHU_OAUTH_SCOPE', 'contact:user.base:readonly') 

2577 

2578FEISHU_REDIRECT_URI = os.getenv('FEISHU_REDIRECT_URI', '') 

2579 

2580ENABLE_OAUTH_ROLE_MANAGEMENT = os.getenv('ENABLE_OAUTH_ROLE_MANAGEMENT', 'False').lower() == 'true' 

2581 

2582ENABLE_OAUTH_GROUP_MANAGEMENT = os.getenv('ENABLE_OAUTH_GROUP_MANAGEMENT', 'False').lower() == 'true' 

2583 

2584ENABLE_OAUTH_GROUP_CREATION = os.getenv('ENABLE_OAUTH_GROUP_CREATION', 'False').lower() == 'true' 

2585 

2586 

2587oauth_group_default_share = os.getenv('OAUTH_GROUP_DEFAULT_SHARE', 'true').strip().lower() 

2588OAUTH_GROUP_DEFAULT_SHARE = 'members' if oauth_group_default_share == 'members' else oauth_group_default_share == 'true' 

2589 

2590 

2591OAUTH_BLOCKED_GROUPS = os.getenv('OAUTH_BLOCKED_GROUPS', '[]') 

2592 

2593OAUTH_GROUPS_SEPARATOR = os.getenv('OAUTH_GROUPS_SEPARATOR', ';') 

2594 

2595OAUTH_ROLES_CLAIM = os.getenv('OAUTH_ROLES_CLAIM', 'roles') 

2596 

2597OAUTH_ROLES_SEPARATOR = os.getenv('OAUTH_ROLES_SEPARATOR', ',') 

2598 

2599OAUTH_ALLOWED_ROLES = [ 

2600 role.strip() 

2601 for role in os.getenv('OAUTH_ALLOWED_ROLES', f'user{OAUTH_ROLES_SEPARATOR}admin').split(OAUTH_ROLES_SEPARATOR) 

2602 if role 

2603] 

2604 

2605OAUTH_ADMIN_ROLES = [ 

2606 role.strip() for role in os.getenv('OAUTH_ADMIN_ROLES', 'admin').split(OAUTH_ROLES_SEPARATOR) if role 

2607] 

2608 

2609OAUTH_ALLOWED_DOMAINS = [domain.strip() for domain in os.getenv('OAUTH_ALLOWED_DOMAINS', '*').split(',')] 

2610 

2611OAUTH_UPDATE_PICTURE_ON_LOGIN = os.getenv('OAUTH_UPDATE_PICTURE_ON_LOGIN', 'False').lower() == 'true' 

2612 

2613OAUTH_UPDATE_NAME_ON_LOGIN = os.getenv('OAUTH_UPDATE_NAME_ON_LOGIN', 'False').lower() == 'true' 

2614 

2615OAUTH_UPDATE_EMAIL_ON_LOGIN = os.getenv('OAUTH_UPDATE_EMAIL_ON_LOGIN', 'False').lower() == 'true' 

2616 

2617OAUTH_ACCESS_TOKEN_REQUEST_INCLUDE_CLIENT_ID = ( 

2618 os.getenv('OAUTH_ACCESS_TOKEN_REQUEST_INCLUDE_CLIENT_ID', 'False').lower() == 'true' 

2619) 

2620 

2621OAUTH_AUDIENCE = os.getenv('OAUTH_AUDIENCE', '') 

2622 

2623OAUTH_AUTHORIZE_PARAMS = {} 

2624_oauth_authorize_params = os.getenv('OAUTH_AUTHORIZE_PARAMS', '') 

2625if _oauth_authorize_params: 2625 ↛ 2626line 2625 didn't jump to line 2626 because the condition on line 2625 was never true

2626 try: 

2627 _parsed = JSONCodec.loads(_oauth_authorize_params) 

2628 if isinstance(_parsed, dict): 

2629 OAUTH_AUTHORIZE_PARAMS = _parsed 

2630 else: 

2631 log.warning('OAUTH_AUTHORIZE_PARAMS must be a JSON object, ignoring') 

2632 except (JSONCodec.JSONDecodeError, TypeError): 

2633 log.warning('OAUTH_AUTHORIZE_PARAMS is not valid JSON, ignoring') 

2634 

2635 

2636def oauth_client_kwargs(scope: str, **kwargs): 

2637 client_kwargs = { 

2638 'scope': scope, 

2639 **kwargs, 

2640 **({'timeout': int(OAUTH_TIMEOUT)} if OAUTH_TIMEOUT else {}), 

2641 } 

2642 

2643 if OAUTH_CODE_CHALLENGE_METHOD == 'S256': 

2644 client_kwargs['code_challenge_method'] = 'S256' 

2645 elif OAUTH_CODE_CHALLENGE_METHOD: 

2646 raise Exception( 

2647 'Code challenge methods other than "%s" not supported. Given: "%s"' % ('S256', OAUTH_CODE_CHALLENGE_METHOD) 

2648 ) 

2649 

2650 return client_kwargs 

2651 

2652 

2653def load_oauth_providers(): 

2654 OAUTH_PROVIDERS.clear() 

2655 if GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET: 2655 ↛ 2657line 2655 didn't jump to line 2657 because the condition on line 2655 was never true

2656 

2657 def google_oauth_register(oauth: OAuth): 

2658 client = oauth.register( 

2659 name='google', 

2660 client_id=GOOGLE_CLIENT_ID, 

2661 client_secret=GOOGLE_CLIENT_SECRET, 

2662 server_metadata_url='https://accounts.google.com/.well-known/openid-configuration', 

2663 client_kwargs=oauth_client_kwargs(GOOGLE_OAUTH_SCOPE), 

2664 redirect_uri=GOOGLE_REDIRECT_URI, 

2665 **({'authorize_params': GOOGLE_OAUTH_AUTHORIZE_PARAMS} if GOOGLE_OAUTH_AUTHORIZE_PARAMS else {}), 

2666 ) 

2667 return client 

2668 

2669 OAUTH_PROVIDERS['google'] = { 

2670 'register': google_oauth_register, 

2671 } 

2672 

2673 if MICROSOFT_CLIENT_ID and MICROSOFT_CLIENT_SECRET and MICROSOFT_CLIENT_TENANT_ID: 2673 ↛ 2675line 2673 didn't jump to line 2675 because the condition on line 2673 was never true

2674 

2675 def microsoft_oauth_register(oauth: OAuth): 

2676 client = oauth.register( 

2677 name='microsoft', 

2678 client_id=MICROSOFT_CLIENT_ID, 

2679 client_secret=MICROSOFT_CLIENT_SECRET, 

2680 server_metadata_url=f'{MICROSOFT_CLIENT_LOGIN_BASE_URL}/{MICROSOFT_CLIENT_TENANT_ID}/v2.0/.well-known/openid-configuration?appid={MICROSOFT_CLIENT_ID}', 

2681 client_kwargs=oauth_client_kwargs(MICROSOFT_OAUTH_SCOPE), 

2682 redirect_uri=MICROSOFT_REDIRECT_URI, 

2683 ) 

2684 return client 

2685 

2686 OAUTH_PROVIDERS['microsoft'] = { 

2687 'picture_url': MICROSOFT_CLIENT_PICTURE_URL, 

2688 'register': microsoft_oauth_register, 

2689 } 

2690 

2691 if GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET: 2691 ↛ 2693line 2691 didn't jump to line 2693 because the condition on line 2691 was never true

2692 

2693 def github_oauth_register(oauth: OAuth): 

2694 client = oauth.register( 

2695 name='github', 

2696 client_id=GITHUB_CLIENT_ID, 

2697 client_secret=GITHUB_CLIENT_SECRET, 

2698 access_token_url='https://github.com/login/oauth/access_token', 

2699 authorize_url='https://github.com/login/oauth/authorize', 

2700 api_base_url='https://api.github.com', 

2701 userinfo_endpoint='https://api.github.com/user', 

2702 client_kwargs=oauth_client_kwargs(GITHUB_CLIENT_SCOPE), 

2703 redirect_uri=GITHUB_CLIENT_REDIRECT_URI, 

2704 ) 

2705 return client 

2706 

2707 OAUTH_PROVIDERS['github'] = { 

2708 'register': github_oauth_register, 

2709 'sub_claim': 'id', 

2710 } 

2711 

2712 if OAUTH_CLIENT_ID and (OAUTH_CLIENT_SECRET or OAUTH_CODE_CHALLENGE_METHOD) and OPENID_PROVIDER_URL: 2712 ↛ 2714line 2712 didn't jump to line 2714 because the condition on line 2712 was never true

2713 

2714 def oidc_oauth_register(oauth: OAuth): 

2715 client = oauth.register( 

2716 name='oidc', 

2717 client_id=OAUTH_CLIENT_ID, 

2718 client_secret=OAUTH_CLIENT_SECRET, 

2719 server_metadata_url=OPENID_PROVIDER_URL, 

2720 client_kwargs=oauth_client_kwargs( 

2721 OAUTH_SCOPES, 

2722 **( 

2723 {'token_endpoint_auth_method': OAUTH_TOKEN_ENDPOINT_AUTH_METHOD} 

2724 if OAUTH_TOKEN_ENDPOINT_AUTH_METHOD 

2725 else {} 

2726 ), 

2727 ), 

2728 redirect_uri=OPENID_REDIRECT_URI, 

2729 ) 

2730 return client 

2731 

2732 OAUTH_PROVIDERS['oidc'] = { 

2733 'name': OAUTH_PROVIDER_NAME, 

2734 'register': oidc_oauth_register, 

2735 } 

2736 

2737 if FEISHU_CLIENT_ID and FEISHU_CLIENT_SECRET: 2737 ↛ 2739line 2737 didn't jump to line 2739 because the condition on line 2737 was never true

2738 

2739 def feishu_oauth_register(oauth: OAuth): 

2740 client = oauth.register( 

2741 name='feishu', 

2742 client_id=FEISHU_CLIENT_ID, 

2743 client_secret=FEISHU_CLIENT_SECRET, 

2744 access_token_url='https://open.feishu.cn/open-apis/authen/v2/oauth/token', 

2745 authorize_url='https://accounts.feishu.cn/open-apis/authen/v1/authorize', 

2746 api_base_url='https://open.feishu.cn/open-apis', 

2747 userinfo_endpoint='https://open.feishu.cn/open-apis/authen/v1/user_info', 

2748 client_kwargs={ 

2749 'scope': FEISHU_OAUTH_SCOPE, 

2750 **({'timeout': int(OAUTH_TIMEOUT)} if OAUTH_TIMEOUT else {}), 

2751 }, 

2752 redirect_uri=FEISHU_REDIRECT_URI, 

2753 ) 

2754 return client 

2755 

2756 OAUTH_PROVIDERS['feishu'] = { 

2757 'register': feishu_oauth_register, 

2758 'sub_claim': 'user_id', 

2759 } 

2760 

2761 configured_providers = [] 

2762 if GOOGLE_CLIENT_ID: 2762 ↛ 2763line 2762 didn't jump to line 2763 because the condition on line 2762 was never true

2763 configured_providers.append('Google') 

2764 if MICROSOFT_CLIENT_ID: 2764 ↛ 2765line 2764 didn't jump to line 2765 because the condition on line 2764 was never true

2765 configured_providers.append('Microsoft') 

2766 if GITHUB_CLIENT_ID: 2766 ↛ 2767line 2766 didn't jump to line 2767 because the condition on line 2766 was never true

2767 configured_providers.append('GitHub') 

2768 if FEISHU_CLIENT_ID: 2768 ↛ 2769line 2768 didn't jump to line 2769 because the condition on line 2768 was never true

2769 configured_providers.append('Feishu') 

2770 

2771 if configured_providers and not OPENID_PROVIDER_URL and not OPENID_END_SESSION_ENDPOINT: 2771 ↛ 2772line 2771 didn't jump to line 2772 because the condition on line 2771 was never true

2772 provider_list = ', '.join(configured_providers) 

2773 log.warning( 

2774 f'⚠️ OAuth providers configured ({provider_list}) but OPENID_PROVIDER_URL not set - logout will not work!' 

2775 ) 

2776 log.warning( 

2777 f"Set OPENID_PROVIDER_URL to your OAuth provider's OpenID Connect discovery endpoint," 

2778 f' or set OPENID_END_SESSION_ENDPOINT to a custom logout URL to fix logout functionality.' 

2779 ) 

2780 

2781 

2782load_oauth_providers() 

2783 

2784#################################### 

2785# LDAP 

2786#################################### 

2787 

2788ENABLE_LDAP = os.getenv('ENABLE_LDAP', 'false').lower() == 'true' 

2789 

2790LDAP_SERVER_LABEL = os.getenv('LDAP_SERVER_LABEL', 'LDAP Server') 

2791 

2792LDAP_SERVER_HOST = os.getenv('LDAP_SERVER_HOST', 'localhost') 

2793 

2794LDAP_SERVER_PORT = int(os.getenv('LDAP_SERVER_PORT', '389')) 

2795 

2796LDAP_ATTRIBUTE_FOR_MAIL = os.getenv('LDAP_ATTRIBUTE_FOR_MAIL', 'mail') 

2797 

2798LDAP_ATTRIBUTE_FOR_USERNAME = os.getenv('LDAP_ATTRIBUTE_FOR_USERNAME', 'uid') 

2799 

2800LDAP_APP_DN = os.getenv('LDAP_APP_DN', '') 

2801 

2802LDAP_APP_PASSWORD = os.getenv('LDAP_APP_PASSWORD', '') 

2803 

2804LDAP_SEARCH_BASE = os.getenv('LDAP_SEARCH_BASE', '') 

2805 

2806LDAP_SEARCH_FILTERS = os.getenv('LDAP_SEARCH_FILTER', os.getenv('LDAP_SEARCH_FILTERS', '')) 

2807 

2808LDAP_USE_TLS = os.getenv('LDAP_USE_TLS', 'True').lower() == 'true' 

2809 

2810LDAP_CA_CERT_FILE = os.getenv('LDAP_CA_CERT_FILE', '') 

2811 

2812LDAP_VALIDATE_CERT = os.getenv('LDAP_VALIDATE_CERT', 'True').lower() == 'true' 

2813 

2814LDAP_CIPHERS = os.getenv('LDAP_CIPHERS', 'ALL') 

2815 

2816ENABLE_LDAP_GROUP_MANAGEMENT = os.getenv('ENABLE_LDAP_GROUP_MANAGEMENT', 'False').lower() == 'true' 

2817 

2818ENABLE_LDAP_GROUP_CREATION = os.getenv('ENABLE_LDAP_GROUP_CREATION', 'False').lower() == 'true' 

2819 

2820LDAP_ATTRIBUTE_FOR_GROUPS = os.getenv('LDAP_ATTRIBUTE_FOR_GROUPS', 'memberOf') 

2821 

2822DEFAULT_CONFIG = { 

2823 'direct.enable': ENABLE_DIRECT_CONNECTIONS, 

2824 'direct.integrations.enable': ENABLE_DIRECT_INTEGRATIONS, 

2825 'ollama.enable': ENABLE_OLLAMA_API, 

2826 'ollama.base_urls': OLLAMA_BASE_URLS, 

2827 'ollama.api_configs': OLLAMA_API_CONFIGS, 

2828 'openai.enable': ENABLE_OPENAI_API, 

2829 'openai.api_keys': OPENAI_API_KEYS, 

2830 'openai.api_base_urls': OPENAI_API_BASE_URLS, 

2831 'openai.api_configs': OPENAI_API_CONFIGS, 

2832 'models.base_models_cache': ENABLE_BASE_MODELS_CACHE, 

2833 'tool_server.connections': TOOL_SERVER_CONNECTIONS, 

2834 'oauth.client.timeout': OAUTH_CLIENT_TIMEOUT, 

2835 'terminal_server.connections': TERMINAL_SERVER_CONNECTIONS, 

2836 'code_execution.enable': ENABLE_CODE_EXECUTION, 

2837 'code_execution.engine': CODE_EXECUTION_ENGINE, 

2838 'code_execution.jupyter.url': CODE_EXECUTION_JUPYTER_URL, 

2839 'code_execution.jupyter.auth': CODE_EXECUTION_JUPYTER_AUTH, 

2840 'code_execution.jupyter.auth_token': CODE_EXECUTION_JUPYTER_AUTH_TOKEN, 

2841 'code_execution.jupyter.auth_password': CODE_EXECUTION_JUPYTER_AUTH_PASSWORD, 

2842 'code_execution.jupyter.timeout': CODE_EXECUTION_JUPYTER_TIMEOUT, 

2843 'code_interpreter.enable': ENABLE_CODE_INTERPRETER, 

2844 'memories.enable': ENABLE_MEMORIES, 

2845 'memories.system_context.enable': ENABLE_MEMORY_SYSTEM_CONTEXT, 

2846 'memories.background_review.enable': ENABLE_MEMORY_BACKGROUND_REVIEW, 

2847 'memories.review_interval_turns': MEMORIES_REVIEW_INTERVAL_TURNS, 

2848 'memories.user_char_limit': MEMORIES_USER_CHAR_LIMIT, 

2849 'memories.context_char_limit': MEMORIES_CONTEXT_CHAR_LIMIT, 

2850 'code_interpreter.engine': CODE_INTERPRETER_ENGINE, 

2851 'code_interpreter.prompt_template': CODE_INTERPRETER_PROMPT_TEMPLATE, 

2852 'code_interpreter.jupyter.url': CODE_INTERPRETER_JUPYTER_URL, 

2853 'code_interpreter.jupyter.auth': CODE_INTERPRETER_JUPYTER_AUTH, 

2854 'code_interpreter.jupyter.auth_token': CODE_INTERPRETER_JUPYTER_AUTH_TOKEN, 

2855 'code_interpreter.jupyter.auth_password': CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD, 

2856 'code_interpreter.jupyter.timeout': CODE_INTERPRETER_JUPYTER_TIMEOUT, 

2857 'google_drive.enable': ENABLE_GOOGLE_DRIVE_INTEGRATION, 

2858 'google_drive.client_id': GOOGLE_DRIVE_CLIENT_ID, 

2859 'google_drive.api_key': GOOGLE_DRIVE_API_KEY, 

2860 'onedrive.enable': ENABLE_ONEDRIVE_INTEGRATION, 

2861 'onedrive.sharepoint_url': ONEDRIVE_SHAREPOINT_URL, 

2862 'onedrive.sharepoint_tenant_id': ONEDRIVE_SHAREPOINT_TENANT_ID, 

2863 'rag.content_extraction_engine': CONTENT_EXTRACTION_ENGINE, 

2864 'rag.content_extraction.supported_media_mime_types': CONTENT_EXTRACTION_SUPPORTED_MEDIA_MIME_TYPES, 

2865 'rag.datalab_marker_api_key': DATALAB_MARKER_API_KEY, 

2866 'rag.datalab_marker_api_base_url': DATALAB_MARKER_API_BASE_URL, 

2867 'rag.datalab_marker_additional_config': DATALAB_MARKER_ADDITIONAL_CONFIG, 

2868 'rag.datalab_marker_use_llm': DATALAB_MARKER_USE_LLM, 

2869 'rag.datalab_marker_skip_cache': DATALAB_MARKER_SKIP_CACHE, 

2870 'rag.datalab_marker_force_ocr': DATALAB_MARKER_FORCE_OCR, 

2871 'rag.datalab_marker_paginate': DATALAB_MARKER_PAGINATE, 

2872 'rag.datalab_marker_strip_existing_ocr': DATALAB_MARKER_STRIP_EXISTING_OCR, 

2873 'rag.datalab_marker_disable_image_extraction': DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION, 

2874 'rag.datalab_marker_format_lines': DATALAB_MARKER_FORMAT_LINES, 

2875 'rag.datalab_marker_output_format': DATALAB_MARKER_OUTPUT_FORMAT, 

2876 'rag.mineru_api_mode': MINERU_API_MODE, 

2877 'rag.mineru_api_url': MINERU_API_URL, 

2878 'rag.mineru_api_timeout': MINERU_API_TIMEOUT, 

2879 'rag.mineru_api_key': MINERU_API_KEY, 

2880 'rag.mineru_params': MINERU_PARAMS, 

2881 'rag.mineru_file_extensions': MINERU_FILE_EXTENSIONS, 

2882 'rag.external_document_loader_url': EXTERNAL_DOCUMENT_LOADER_URL, 

2883 'rag.external_document_loader_api_key': EXTERNAL_DOCUMENT_LOADER_API_KEY, 

2884 'rag.external_document_loader_headers': EXTERNAL_DOCUMENT_LOADER_HEADERS, 

2885 'rag.tika_server_url': TIKA_SERVER_URL, 

2886 'rag.tika_server_version': TIKA_SERVER_VERSION, 

2887 'rag.docling_server_url': DOCLING_SERVER_URL, 

2888 'rag.docling_api_key': DOCLING_API_KEY, 

2889 'rag.docling_params': DOCLING_PARAMS, 

2890 'rag.document_intelligence_endpoint': DOCUMENT_INTELLIGENCE_ENDPOINT, 

2891 'rag.document_intelligence_key': DOCUMENT_INTELLIGENCE_KEY, 

2892 'rag.document_intelligence_model': DOCUMENT_INTELLIGENCE_MODEL, 

2893 'rag.mistral_ocr_api_base_url': MISTRAL_OCR_API_BASE_URL, 

2894 'rag.mistral_ocr_api_key': MISTRAL_OCR_API_KEY, 

2895 'rag.mistral_ocr_use_base64': MISTRAL_OCR_USE_BASE64, 

2896 'rag.paddleocr_vl_base_url': PADDLEOCR_VL_BASE_URL, 

2897 'rag.paddleocr_vl_token': PADDLEOCR_VL_TOKEN, 

2898 'rag.bypass_embedding_and_retrieval': BYPASS_EMBEDDING_AND_RETRIEVAL, 

2899 'rag.top_k': RAG_TOP_K, 

2900 'rag.top_k_reranker': RAG_TOP_K_RERANKER, 

2901 'rag.relevance_threshold': RAG_RELEVANCE_THRESHOLD, 

2902 'rag.hybrid_bm25_weight': RAG_HYBRID_BM25_WEIGHT, 

2903 'rag.enable_hybrid_search': ENABLE_RAG_HYBRID_SEARCH, 

2904 'rag.enable_hybrid_search_enriched_texts': ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS, 

2905 'rag.full_context': RAG_FULL_CONTEXT, 

2906 'rag.file.max_count': RAG_FILE_MAX_COUNT, 

2907 'rag.file.max_size': RAG_FILE_MAX_SIZE, 

2908 'file.image_compression_width': FILE_IMAGE_COMPRESSION_WIDTH, 

2909 'file.image_compression_height': FILE_IMAGE_COMPRESSION_HEIGHT, 

2910 'rag.file.allowed_extensions': RAG_ALLOWED_FILE_EXTENSIONS, 

2911 'rag.embedding_engine': RAG_EMBEDDING_ENGINE, 

2912 'rag.pdf_extract_images': PDF_EXTRACT_IMAGES, 

2913 'rag.pdf_loader_mode': PDF_LOADER_MODE, 

2914 'rag.embedding_model': RAG_EMBEDDING_MODEL, 

2915 'rag.tokenizer_model': RAG_TOKENIZER_MODEL, 

2916 'rag.embedding_batch_size': RAG_EMBEDDING_BATCH_SIZE, 

2917 'rag.enable_async_embedding': ENABLE_ASYNC_EMBEDDING, 

2918 'rag.embedding_concurrent_requests': RAG_EMBEDDING_CONCURRENT_REQUESTS, 

2919 'rag.reranking_engine': RAG_RERANKING_ENGINE, 

2920 'rag.reranking_model': RAG_RERANKING_MODEL, 

2921 'rag.reranking_batch_size': RAG_RERANKING_BATCH_SIZE, 

2922 'rag.external_reranker_url': RAG_EXTERNAL_RERANKER_URL, 

2923 'rag.external_reranker_api_key': RAG_EXTERNAL_RERANKER_API_KEY, 

2924 'rag.external_reranker_timeout': RAG_EXTERNAL_RERANKER_TIMEOUT, 

2925 'rag.text_splitter': RAG_TEXT_SPLITTER, 

2926 'rag.enable_markdown_header_text_splitter': ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER, 

2927 'rag.tiktoken_encoding_name': TIKTOKEN_ENCODING_NAME, 

2928 'rag.chunk_size': CHUNK_SIZE, 

2929 'rag.chunk_min_size_target': CHUNK_MIN_SIZE_TARGET, 

2930 'rag.chunk_overlap': CHUNK_OVERLAP, 

2931 'rag.template': RAG_TEMPLATE, 

2932 'rag.openai.api_base_url': RAG_OPENAI_API_BASE_URL, 

2933 'rag.openai.api_key': RAG_OPENAI_API_KEY, 

2934 'rag.azure_openai.base_url': RAG_AZURE_OPENAI_BASE_URL, 

2935 'rag.azure_openai.api_key': RAG_AZURE_OPENAI_API_KEY, 

2936 'rag.azure_openai.api_version': RAG_AZURE_OPENAI_API_VERSION, 

2937 'rag.ollama.base_url': RAG_OLLAMA_BASE_URL, 

2938 'rag.ollama.api_key': RAG_OLLAMA_API_KEY, 

2939 'rag.youtube_loader_language': YOUTUBE_LOADER_LANGUAGE, 

2940 'rag.youtube_loader_proxy_url': YOUTUBE_LOADER_PROXY_URL, 

2941 'web.search.enable': ENABLE_WEB_SEARCH, 

2942 'web.search.confirmation.enable': ENABLE_WEB_SEARCH_CONFIRMATION, 

2943 'web.search.confirmation.content': WEB_SEARCH_CONFIRMATION_CONTENT, 

2944 'web.search.engine': WEB_SEARCH_ENGINE, 

2945 'web.search.bypass_embedding_and_retrieval': BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL, 

2946 'web.search.bypass_web_loader': BYPASS_WEB_SEARCH_WEB_LOADER, 

2947 'web.search.result_count': WEB_SEARCH_RESULT_COUNT, 

2948 'web.search.domain.filter_list': WEB_SEARCH_DOMAIN_FILTER_LIST, 

2949 'web.search.concurrent_requests': WEB_SEARCH_CONCURRENT_REQUESTS, 

2950 'web.fetch.max_content_length': WEB_FETCH_MAX_CONTENT_LENGTH, 

2951 'web.loader.engine': WEB_LOADER_ENGINE, 

2952 'web.loader.concurrent_requests': WEB_LOADER_CONCURRENT_REQUESTS, 

2953 'web.loader.timeout': WEB_LOADER_TIMEOUT, 

2954 'web.loader.ssl_verification': ENABLE_WEB_LOADER_SSL_VERIFICATION, 

2955 'web.search.trust_env': WEB_SEARCH_TRUST_ENV, 

2956 'web.search.ollama_cloud_api_key': OLLAMA_CLOUD_WEB_SEARCH_API_KEY, 

2957 'web.search.searxng_query_url': SEARXNG_QUERY_URL, 

2958 'web.search.openserp_base_url': OPENSERP_BASE_URL, 

2959 'web.search.searxng_language': SEARXNG_LANGUAGE, 

2960 'web.search.yacy_query_url': YACY_QUERY_URL, 

2961 'web.search.yacy_username': YACY_USERNAME, 

2962 'web.search.yacy_password': YACY_PASSWORD, 

2963 'web.search.google_pse_api_key': GOOGLE_PSE_API_KEY, 

2964 'web.search.google_pse_engine_id': GOOGLE_PSE_ENGINE_ID, 

2965 'web.search.brave_search_api_key': BRAVE_SEARCH_API_KEY, 

2966 'web.search.brave_search_context_tokens': BRAVE_SEARCH_CONTEXT_TOKENS, 

2967 'web.search.kagi_search_api_key': KAGI_SEARCH_API_KEY, 

2968 'web.search.mojeek_search_api_key': MOJEEK_SEARCH_API_KEY, 

2969 'web.search.bocha_search_api_key': BOCHA_SEARCH_API_KEY, 

2970 'web.search.serpstack_api_key': SERPSTACK_API_KEY, 

2971 'web.search.serpstack_https': SERPSTACK_HTTPS, 

2972 'web.search.serper_api_key': SERPER_API_KEY, 

2973 'web.search.serply_api_key': SERPLY_API_KEY, 

2974 'web.search.serphouse_api_key': SERPHOUSE_API_KEY, 

2975 'web.search.serphouse_domain': SERPHOUSE_DOMAIN, 

2976 'web.search.ddgs_backend': DDGS_BACKEND, 

2977 'web.search.jina_api_key': JINA_API_KEY, 

2978 'web.search.jina_api_base_url': JINA_API_BASE_URL, 

2979 'web.search.searchapi_api_key': SEARCHAPI_API_KEY, 

2980 'web.search.searchapi_engine': SEARCHAPI_ENGINE, 

2981 'web.search.serpapi_api_key': SERPAPI_API_KEY, 

2982 'web.search.serpapi_engine': SERPAPI_ENGINE, 

2983 'web.search.bing_search_v7_endpoint': BING_SEARCH_V7_ENDPOINT, 

2984 'web.search.bing_search_v7_subscription_key': BING_SEARCH_V7_SUBSCRIPTION_KEY, 

2985 'web.search.azure_ai_search_api_key': AZURE_AI_SEARCH_API_KEY, 

2986 'web.search.azure_ai_search_endpoint': AZURE_AI_SEARCH_ENDPOINT, 

2987 'web.search.azure_ai_search_index_name': AZURE_AI_SEARCH_INDEX_NAME, 

2988 'web.search.exa_api_key': EXA_API_KEY, 

2989 'web.search.exa_max_content_length': EXA_MAX_CONTENT_LENGTH, 

2990 'web.search.perplexity_api_key': PERPLEXITY_API_KEY, 

2991 'web.search.perplexity_model': PERPLEXITY_MODEL, 

2992 'web.search.perplexity_search_context_usage': PERPLEXITY_SEARCH_CONTEXT_USAGE, 

2993 'web.search.perplexity_search_api_url': PERPLEXITY_SEARCH_API_URL, 

2994 'web.search.microsoft_web_iq_api_base_url': MICROSOFT_WEB_IQ_API_BASE_URL, 

2995 'web.search.microsoft_web_iq_api_key': MICROSOFT_WEB_IQ_API_KEY, 

2996 'web.search.microsoft_web_iq_language': MICROSOFT_WEB_IQ_LANGUAGE, 

2997 'web.search.sougou_api_sid': SOUGOU_API_SID, 

2998 'web.search.sougou_api_sk': SOUGOU_API_SK, 

2999 'web.search.tavily_api_key': TAVILY_API_KEY, 

3000 'web.search.tavily_extract_depth': TAVILY_EXTRACT_DEPTH, 

3001 'web.search.staan_api_key': STAAN_API_KEY, 

3002 'web.search.staan_market': STAAN_MARKET, 

3003 'web.search.staan_max_snippets': STAAN_MAX_SNIPPETS, 

3004 'web.loader.playwright_ws_url': PLAYWRIGHT_WS_URL, 

3005 'web.loader.playwright_timeout': PLAYWRIGHT_TIMEOUT, 

3006 'web.loader.firecrawl_api_key': FIRECRAWL_API_KEY, 

3007 'web.loader.firecrawl_api_url': FIRECRAWL_API_BASE_URL, 

3008 'web.loader.firecrawl_timeout': FIRECRAWL_TIMEOUT, 

3009 'web.search.external_web_search_url': EXTERNAL_WEB_SEARCH_URL, 

3010 'web.search.external_web_search_api_key': EXTERNAL_WEB_SEARCH_API_KEY, 

3011 'web.loader.external_web_loader_url': EXTERNAL_WEB_LOADER_URL, 

3012 'web.loader.external_web_loader_api_key': EXTERNAL_WEB_LOADER_API_KEY, 

3013 'web.search.yandex_web_search_url': YANDEX_WEB_SEARCH_URL, 

3014 'web.search.yandex_web_search_api_key': YANDEX_WEB_SEARCH_API_KEY, 

3015 'web.search.yandex_web_search_config': YANDEX_WEB_SEARCH_CONFIG, 

3016 'web.search.youcom_api_key': YOUCOM_API_KEY, 

3017 'web.search.linkup_api_key': LINKUP_API_KEY, 

3018 'web.search.linkup_search_params': LINKUP_SEARCH_PARAMS, 

3019 'image_generation.enable': ENABLE_IMAGE_GENERATION, 

3020 'image_generation.engine': IMAGE_GENERATION_ENGINE, 

3021 'image_generation.model': IMAGE_GENERATION_MODEL, 

3022 'image_generation.size': IMAGE_SIZE, 

3023 'image_generation.steps': IMAGE_STEPS, 

3024 'image_generation.prompt.enable': ENABLE_IMAGE_PROMPT_GENERATION, 

3025 'image_generation.automatic1111.base_url': AUTOMATIC1111_BASE_URL, 

3026 'image_generation.automatic1111.api_auth': AUTOMATIC1111_API_AUTH, 

3027 'image_generation.automatic1111.api_params': AUTOMATIC1111_PARAMS, 

3028 'image_generation.comfyui.base_url': COMFYUI_BASE_URL, 

3029 'image_generation.comfyui.api_key': COMFYUI_API_KEY, 

3030 'image_generation.comfyui.workflow': COMFYUI_WORKFLOW, 

3031 'image_generation.comfyui.nodes': COMFYUI_WORKFLOW_NODES, 

3032 'image_generation.openai.api_base_url': IMAGES_OPENAI_API_BASE_URL, 

3033 'image_generation.openai.api_version': IMAGES_OPENAI_API_VERSION, 

3034 'image_generation.openai.api_key': IMAGES_OPENAI_API_KEY, 

3035 'image_generation.openai.params': IMAGES_OPENAI_API_PARAMS, 

3036 'image_generation.gemini.api_base_url': IMAGES_GEMINI_API_BASE_URL, 

3037 'image_generation.gemini.api_key': IMAGES_GEMINI_API_KEY, 

3038 'image_generation.gemini.endpoint_method': IMAGES_GEMINI_ENDPOINT_METHOD, 

3039 'images.edit.enable': ENABLE_IMAGE_EDIT, 

3040 'images.edit.engine': IMAGE_EDIT_ENGINE, 

3041 'images.edit.model': IMAGE_EDIT_MODEL, 

3042 'images.edit.size': IMAGE_EDIT_SIZE, 

3043 'images.edit.openai.api_base_url': IMAGES_EDIT_OPENAI_API_BASE_URL, 

3044 'images.edit.openai.api_version': IMAGES_EDIT_OPENAI_API_VERSION, 

3045 'images.edit.openai.api_key': IMAGES_EDIT_OPENAI_API_KEY, 

3046 'images.edit.gemini.api_base_url': IMAGES_EDIT_GEMINI_API_BASE_URL, 

3047 'images.edit.gemini.api_key': IMAGES_EDIT_GEMINI_API_KEY, 

3048 'images.edit.comfyui.base_url': IMAGES_EDIT_COMFYUI_BASE_URL, 

3049 'images.edit.comfyui.api_key': IMAGES_EDIT_COMFYUI_API_KEY, 

3050 'images.edit.comfyui.workflow': IMAGES_EDIT_COMFYUI_WORKFLOW, 

3051 'images.edit.comfyui.nodes': IMAGES_EDIT_COMFYUI_WORKFLOW_NODES, 

3052 'audio.stt.whisper_model': WHISPER_MODEL, 

3053 'audio.stt.deepgram.api_key': DEEPGRAM_API_KEY, 

3054 'audio.stt.openai.api_base_url': AUDIO_STT_OPENAI_API_BASE_URL, 

3055 'audio.stt.openai.api_key': AUDIO_STT_OPENAI_API_KEY, 

3056 'audio.stt.openai.api_request_format': AUDIO_STT_OPENAI_API_REQUEST_FORMAT, 

3057 'audio.stt.engine': AUDIO_STT_ENGINE, 

3058 'audio.stt.model': AUDIO_STT_MODEL, 

3059 'audio.stt.supported_content_types': AUDIO_STT_SUPPORTED_CONTENT_TYPES, 

3060 'audio.stt.allowed_extensions': AUDIO_STT_ALLOWED_EXTENSIONS, 

3061 'audio.stt.azure.api_key': AUDIO_STT_AZURE_API_KEY, 

3062 'audio.stt.azure.region': AUDIO_STT_AZURE_REGION, 

3063 'audio.stt.azure.locales': AUDIO_STT_AZURE_LOCALES, 

3064 'audio.stt.azure.base_url': AUDIO_STT_AZURE_BASE_URL, 

3065 'audio.stt.azure.max_speakers': AUDIO_STT_AZURE_MAX_SPEAKERS, 

3066 'audio.stt.mistral.api_key': AUDIO_STT_MISTRAL_API_KEY, 

3067 'audio.stt.mistral.api_base_url': AUDIO_STT_MISTRAL_API_BASE_URL, 

3068 'audio.stt.mistral.use_chat_completions': AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS, 

3069 'audio.tts.openai.api_base_url': AUDIO_TTS_OPENAI_API_BASE_URL, 

3070 'audio.tts.openai.api_key': AUDIO_TTS_OPENAI_API_KEY, 

3071 'audio.tts.openai.params': AUDIO_TTS_OPENAI_PARAMS, 

3072 'audio.tts.api_key': AUDIO_TTS_API_KEY, 

3073 'audio.tts.engine': AUDIO_TTS_ENGINE, 

3074 'audio.tts.model': AUDIO_TTS_MODEL, 

3075 'audio.tts.voice': AUDIO_TTS_VOICE, 

3076 'audio.tts.split_on': AUDIO_TTS_SPLIT_ON, 

3077 'audio.tts.azure.speech_region': AUDIO_TTS_AZURE_SPEECH_REGION, 

3078 'audio.tts.azure.speech_base_url': AUDIO_TTS_AZURE_SPEECH_BASE_URL, 

3079 'audio.tts.azure.speech_output_format': AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT, 

3080 'audio.tts.mistral.api_key': AUDIO_TTS_MISTRAL_API_KEY, 

3081 'audio.tts.mistral.api_base_url': AUDIO_TTS_MISTRAL_API_BASE_URL, 

3082 'webui.url': WEBUI_URL, 

3083 'ui.enable_signup': ENABLE_SIGNUP, 

3084 'ui.enable_login_form': ENABLE_LOGIN_FORM, 

3085 'ui.enable_password_change_form': ENABLE_PASSWORD_CHANGE_FORM, 

3086 'ui.default_locale': DEFAULT_LOCALE, 

3087 'ui.default_models': DEFAULT_MODELS, 

3088 'ui.default_pinned_models': DEFAULT_PINNED_MODELS, 

3089 'ui.default_interface_settings': DEFAULT_INTERFACE_SETTINGS, 

3090 'ui.i18n': {}, 

3091 'ui.prompt_suggestions': DEFAULT_PROMPT_SUGGESTIONS, 

3092 'ui.prompt_suggestions_i18n': DEFAULT_PROMPT_SUGGESTIONS_I18N, 

3093 'ui.model_order_list': MODEL_ORDER_LIST, 

3094 'models.default_metadata': DEFAULT_MODEL_METADATA, 

3095 'models.default_params': DEFAULT_MODEL_PARAMS, 

3096 'ui.default_user_role': DEFAULT_USER_ROLE, 

3097 'ui.default_group_id': DEFAULT_GROUP_ID, 

3098 'ui.pending_user_overlay_title': PENDING_USER_OVERLAY_TITLE, 

3099 'ui.pending_user_overlay_content': PENDING_USER_OVERLAY_CONTENT, 

3100 'ui.watermark': RESPONSE_WATERMARK, 

3101 'user.permissions': USER_PERMISSIONS, 

3102 'folders.enable': ENABLE_FOLDERS, 

3103 'folders.max_file_count': FOLDER_MAX_FILE_COUNT, 

3104 'channels.enable': ENABLE_CHANNELS, 

3105 'channels.model_response_mode': CHANNEL_MODEL_RESPONSE_MODE, 

3106 'calendar.enable': ENABLE_CALENDAR, 

3107 'automations.enable': ENABLE_AUTOMATIONS, 

3108 'subagents.enable': ENABLE_SUBAGENTS, 

3109 'subagents.background_enabled': SUBAGENTS_BACKGROUND_ENABLED, 

3110 'subagents.max_concurrent': SUBAGENTS_MAX_CONCURRENT, 

3111 'subagents.max_async': SUBAGENTS_MAX_ASYNC, 

3112 'subagents.max_iterations': SUBAGENTS_MAX_ITERATIONS, 

3113 'subagents.max_output': SUBAGENTS_MAX_OUTPUT, 

3114 'subagents.system_prompt': SUBAGENTS_SYSTEM_PROMPT, 

3115 'automations.max_count': AUTOMATION_MAX_COUNT, 

3116 'automations.min_interval': AUTOMATION_MIN_INTERVAL, 

3117 'automations.auth_token_expires_in': AUTOMATION_AUTH_TOKEN_EXPIRES_IN, 

3118 'notes.enable': ENABLE_NOTES, 

3119 'users.enable_status': ENABLE_USER_STATUS, 

3120 'evaluation.arena.enable': ENABLE_EVALUATION_ARENA_MODELS, 

3121 'evaluation.arena.models': EVALUATION_ARENA_MODELS, 

3122 'webhook_url': WEBHOOK_URL, 

3123 'ui.enable_community_sharing': ENABLE_COMMUNITY_SHARING, 

3124 'ui.enable_message_rating': ENABLE_MESSAGE_RATING, 

3125 'ui.enable_user_webhooks': ENABLE_USER_WEBHOOKS, 

3126 'ui.banners': WEBUI_BANNERS, 

3127 'auth.admin.show': SHOW_ADMIN_DETAILS, 

3128 'auth.admin.email': ADMIN_EMAIL, 

3129 'task.model.default': TASK_MODEL, 

3130 'task.model.external': TASK_MODEL_EXTERNAL, 

3131 'task.model.params': TASK_MODEL_PARAMS, 

3132 'chat.context_compaction.model': CONTEXT_COMPACTION_MODEL, 

3133 'chat.context_compaction.enable': ENABLE_CONTEXT_COMPACTION, 

3134 'chat.context_compaction.token_threshold': CONTEXT_COMPACTION_TOKEN_THRESHOLD, 

3135 'chat.context_compaction.token_cap': CONTEXT_COMPACTION_TOKEN_CAP, 

3136 'chat.context_compaction.retention_percentage': CONTEXT_COMPACTION_RETENTION_PERCENTAGE, 

3137 'chat.context_compaction.prompt_template': CONTEXT_COMPACTION_PROMPT_TEMPLATE, 

3138 'chat.tool_permissions.enable': ENABLE_TOOL_PERMISSIONS, 

3139 'task.title.prompt_template': TITLE_GENERATION_PROMPT_TEMPLATE, 

3140 'task.tags.prompt_template': TAGS_GENERATION_PROMPT_TEMPLATE, 

3141 'task.image.prompt_template': IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE, 

3142 'task.follow_up.prompt_template': FOLLOW_UP_GENERATION_PROMPT_TEMPLATE, 

3143 'task.follow_up.enable': ENABLE_FOLLOW_UP_GENERATION, 

3144 'task.tags.enable': ENABLE_TAGS_GENERATION, 

3145 'task.title.enable': ENABLE_TITLE_GENERATION, 

3146 'task.query.search.enable': ENABLE_SEARCH_QUERY_GENERATION, 

3147 'task.query.retrieval.enable': ENABLE_RETRIEVAL_QUERY_GENERATION, 

3148 'task.query.prompt_template': QUERY_GENERATION_PROMPT_TEMPLATE, 

3149 'task.autocomplete.enable': ENABLE_AUTOCOMPLETE_GENERATION, 

3150 'task.autocomplete.input_max_length': AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH, 

3151 'task.autocomplete.prompt_template': AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE, 

3152 'task.voice.prompt_template': VOICE_MODE_PROMPT_TEMPLATE, 

3153 'task.voice.prompt.enable': ENABLE_VOICE_MODE_PROMPT, 

3154 'task.tools.prompt_template': TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE, 

3155 'auth.enable_api_keys': ENABLE_API_KEYS, 

3156 'auth.api_key.endpoint_restrictions': ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS, 

3157 'auth.api_key.allowed_endpoints': API_KEYS_ALLOWED_ENDPOINTS, 

3158 'auth.jwt_expiry': JWT_EXPIRES_IN, 

3159 'oauth.enable': ENABLE_OAUTH, 

3160 'oauth.enable_signup': ENABLE_OAUTH_SIGNUP, 

3161 'oauth.auto_redirect': OAUTH_AUTO_REDIRECT, 

3162 'oauth.refresh_token.include_scope': OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE, 

3163 'oauth.merge_accounts_by_email': OAUTH_MERGE_ACCOUNTS_BY_EMAIL, 

3164 'oauth.google.client_id': GOOGLE_CLIENT_ID, 

3165 'oauth.google.client_secret': GOOGLE_CLIENT_SECRET, 

3166 'oauth.google.scope': GOOGLE_OAUTH_SCOPE, 

3167 'oauth.google.redirect_uri': GOOGLE_REDIRECT_URI, 

3168 'oauth.microsoft.client_id': MICROSOFT_CLIENT_ID, 

3169 'oauth.microsoft.client_secret': MICROSOFT_CLIENT_SECRET, 

3170 'oauth.microsoft.tenant_id': MICROSOFT_CLIENT_TENANT_ID, 

3171 'oauth.microsoft.login_base_url': MICROSOFT_CLIENT_LOGIN_BASE_URL, 

3172 'oauth.microsoft.picture_url': MICROSOFT_CLIENT_PICTURE_URL, 

3173 'oauth.microsoft.scope': MICROSOFT_OAUTH_SCOPE, 

3174 'oauth.microsoft.redirect_uri': MICROSOFT_REDIRECT_URI, 

3175 'oauth.github.client_id': GITHUB_CLIENT_ID, 

3176 'oauth.github.client_secret': GITHUB_CLIENT_SECRET, 

3177 'oauth.github.scope': GITHUB_CLIENT_SCOPE, 

3178 'oauth.github.redirect_uri': GITHUB_CLIENT_REDIRECT_URI, 

3179 'oauth.client_id': OAUTH_CLIENT_ID, 

3180 'oauth.client_secret': OAUTH_CLIENT_SECRET, 

3181 'oauth.provider_url': OPENID_PROVIDER_URL, 

3182 'oauth.end_session_endpoint': OPENID_END_SESSION_ENDPOINT, 

3183 'oauth.redirect_uri': OPENID_REDIRECT_URI, 

3184 'oauth.scopes': OAUTH_SCOPES, 

3185 'oauth.timeout': OAUTH_TIMEOUT, 

3186 'oauth.token_endpoint_auth_method': OAUTH_TOKEN_ENDPOINT_AUTH_METHOD, 

3187 'oauth.code_challenge_method': OAUTH_CODE_CHALLENGE_METHOD, 

3188 'oauth.provider_name': OAUTH_PROVIDER_NAME, 

3189 'oauth.sub_claim': OAUTH_SUB_CLAIM, 

3190 'oauth.username_claim': OAUTH_USERNAME_CLAIM, 

3191 'oauth.picture_claim': OAUTH_PICTURE_CLAIM, 

3192 'oauth.email_claim': OAUTH_EMAIL_CLAIM, 

3193 'oauth.group_claim': OAUTH_GROUPS_CLAIM, 

3194 'oauth.feishu.client_id': FEISHU_CLIENT_ID, 

3195 'oauth.feishu.client_secret': FEISHU_CLIENT_SECRET, 

3196 'oauth.feishu.scope': FEISHU_OAUTH_SCOPE, 

3197 'oauth.feishu.redirect_uri': FEISHU_REDIRECT_URI, 

3198 'oauth.enable_role_mapping': ENABLE_OAUTH_ROLE_MANAGEMENT, 

3199 'oauth.enable_group_mapping': ENABLE_OAUTH_GROUP_MANAGEMENT, 

3200 'oauth.enable_group_creation': ENABLE_OAUTH_GROUP_CREATION, 

3201 'oauth.group_default_share': OAUTH_GROUP_DEFAULT_SHARE, 

3202 'oauth.blocked_groups': OAUTH_BLOCKED_GROUPS, 

3203 'oauth.roles_claim': OAUTH_ROLES_CLAIM, 

3204 'oauth.allowed_roles': OAUTH_ALLOWED_ROLES, 

3205 'oauth.admin_roles': OAUTH_ADMIN_ROLES, 

3206 'oauth.allowed_domains': OAUTH_ALLOWED_DOMAINS, 

3207 'oauth.update_picture_on_login': OAUTH_UPDATE_PICTURE_ON_LOGIN, 

3208 'oauth.update_name_on_login': OAUTH_UPDATE_NAME_ON_LOGIN, 

3209 'oauth.update_email_on_login': OAUTH_UPDATE_EMAIL_ON_LOGIN, 

3210 'oauth.audience': OAUTH_AUDIENCE, 

3211 'ldap.enable': ENABLE_LDAP, 

3212 'ldap.server.label': LDAP_SERVER_LABEL, 

3213 'ldap.server.host': LDAP_SERVER_HOST, 

3214 'ldap.server.port': LDAP_SERVER_PORT, 

3215 'ldap.server.attribute_for_mail': LDAP_ATTRIBUTE_FOR_MAIL, 

3216 'ldap.server.attribute_for_username': LDAP_ATTRIBUTE_FOR_USERNAME, 

3217 'ldap.server.app_dn': LDAP_APP_DN, 

3218 'ldap.server.app_password': LDAP_APP_PASSWORD, 

3219 'ldap.server.users_dn': LDAP_SEARCH_BASE, 

3220 'ldap.server.search_filter': LDAP_SEARCH_FILTERS, 

3221 'ldap.server.use_tls': LDAP_USE_TLS, 

3222 'ldap.server.ca_cert_file': LDAP_CA_CERT_FILE, 

3223 'ldap.server.validate_cert': LDAP_VALIDATE_CERT, 

3224 'ldap.server.ciphers': LDAP_CIPHERS, 

3225 'ldap.group.enable_management': ENABLE_LDAP_GROUP_MANAGEMENT, 

3226 'ldap.group.enable_creation': ENABLE_LDAP_GROUP_CREATION, 

3227 'ldap.server.attribute_for_groups': LDAP_ATTRIBUTE_FOR_GROUPS, 

3228} 

3229 

3230 

3231ENABLE_PERSISTENT_CONFIG = os.getenv('ENABLE_PERSISTENT_CONFIG', 'True').lower() == 'true' 

3232ENABLE_OAUTH_PERSISTENT_CONFIG = os.getenv('ENABLE_OAUTH_PERSISTENT_CONFIG', 'False').lower() == 'true' 

3233 

3234Config.configure( 

3235 defaults=DEFAULT_CONFIG, 

3236 enable_persistent=ENABLE_PERSISTENT_CONFIG, 

3237 enable_oauth_persistent=ENABLE_OAUTH_PERSISTENT_CONFIG, 

3238)