Coverage for open_webui/__init__.py: 30%
54 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 05:07 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 05:07 +0000
1import base64
2import os
3import random
4import sys
5from pathlib import Path
6from typing import Annotated
8import typer
9import uvicorn
11app = typer.Typer()
13KEY_FILE = Path.cwd() / '.webui_secret_key'
14DEFAULT_SECRET_KEY_LENGTH = 24
17def version_callback(value: bool) -> None:
18 if value:
19 from open_webui.env import VERSION
21 # LICENSE covers this Open WebUI CLI identifier.
22 # Do not alter, remove, obscure, or replace it except as LICENSE permits:
23 # https://docs.openwebui.com/license.
24 typer.echo(f'Open WebUI version: {VERSION}')
25 raise typer.Exit()
28@app.command()
29def main(
30 version: Annotated[bool | None, typer.Option('--version', callback=version_callback)] = None,
31):
32 pass
35@app.command()
36def serve(
37 host: str = '0.0.0.0',
38 port: int = 8080,
39):
40 os.environ['FROM_INIT_PY'] = 'true'
41 if os.getenv('WEBUI_SECRET_KEY') is None:
42 typer.echo('Loading WEBUI_SECRET_KEY from file, not provided as an environment variable.')
43 if not KEY_FILE.exists():
44 key_length = int(os.getenv('WEBUI_SECRET_KEY_LENGTH', DEFAULT_SECRET_KEY_LENGTH))
45 if key_length < 1:
46 raise ValueError('WEBUI_SECRET_KEY_LENGTH must be a positive integer')
47 typer.echo(f'Generating a new secret key and saving it to {KEY_FILE}')
48 KEY_FILE.write_bytes(base64.b64encode(random.randbytes(key_length)))
49 typer.echo(f'Loading WEBUI_SECRET_KEY from {KEY_FILE}')
50 os.environ['WEBUI_SECRET_KEY'] = KEY_FILE.read_text()
52 if os.getenv('USE_CUDA_DOCKER', 'false') == 'true':
53 typer.echo('CUDA is enabled, appending LD_LIBRARY_PATH to include torch/cudnn & cublas libraries.')
54 LD_LIBRARY_PATH = os.getenv('LD_LIBRARY_PATH', '').split(':')
55 os.environ['LD_LIBRARY_PATH'] = ':'.join(
56 LD_LIBRARY_PATH
57 + [
58 '/usr/local/lib/python3.11/site-packages/torch/lib',
59 '/usr/local/lib/python3.11/site-packages/nvidia/cudnn/lib',
60 ]
61 )
62 try:
63 import torch
65 assert torch.cuda.is_available(), 'CUDA not available'
66 typer.echo('CUDA seems to be working')
67 except Exception as e:
68 typer.echo(
69 'Error when testing CUDA but USE_CUDA_DOCKER is true. '
70 'Resetting USE_CUDA_DOCKER to false and removing '
71 f'LD_LIBRARY_PATH modifications: {e}'
72 )
73 os.environ['USE_CUDA_DOCKER'] = 'false'
74 os.environ['LD_LIBRARY_PATH'] = ':'.join(LD_LIBRARY_PATH)
76 import open_webui.main # noqa: F401
77 from open_webui.env import UVICORN_WORKERS, UVICORN_WS_PER_MESSAGE_DEFLATE
79 # On Windows, uvicorn's default loop factory hardcodes ProactorEventLoop,
80 # which is incompatible with psycopg v3 async. Setting loop='none' lets
81 # asyncio.run() respect the WindowsSelectorEventLoopPolicy set in db.py.
82 loop = 'none' if sys.platform == 'win32' else 'auto'
84 uvicorn.run(
85 'open_webui.main:app',
86 host=host,
87 port=port,
88 forwarded_allow_ips='*',
89 workers=UVICORN_WORKERS,
90 ws_per_message_deflate=UVICORN_WS_PER_MESSAGE_DEFLATE,
91 loop=loop,
92 )
95@app.command()
96def dev(
97 host: str = '0.0.0.0',
98 port: int = 8080,
99 reload: bool = True,
100):
101 from open_webui.env import UVICORN_WS_PER_MESSAGE_DEFLATE
103 uvicorn.run(
104 'open_webui.main:app',
105 host=host,
106 port=port,
107 reload=reload,
108 forwarded_allow_ips='*',
109 ws_per_message_deflate=UVICORN_WS_PER_MESSAGE_DEFLATE,
110 )
113if __name__ == '__main__': 113 ↛ 114line 113 didn't jump to line 114 because the condition on line 113 was never true
114 app()