From d5a4ab46f49c3b99b63a28084ee7b6d92edd806d Mon Sep 17 00:00:00 2001 From: Tang Ziya Date: Tue, 14 May 2024 11:53:46 +0800 Subject: [PATCH 1/3] changed: packaging using rye and use file relative path instead of pwd relative. --- backend/config.py | 26 +- backend/open_webui/__init__.py | 47 +++ pyproject.toml | 110 ++++++ requirements-dev.lock | 680 +++++++++++++++++++++++++++++++++ requirements.lock | 680 +++++++++++++++++++++++++++++++++ 5 files changed, 1530 insertions(+), 13 deletions(-) create mode 100644 backend/open_webui/__init__.py create mode 100644 pyproject.toml create mode 100644 requirements-dev.lock create mode 100644 requirements.lock diff --git a/backend/config.py b/backend/config.py index 1a62e98bf..b44b2b64e 100644 --- a/backend/config.py +++ b/backend/config.py @@ -22,10 +22,13 @@ from constants import ERROR_MESSAGES # Load .env file #################################### +BACKEND_DIR = Path(__file__).parent # the path containing this file +BASE_DIR = BACKEND_DIR.parent # the path containing the backend/ + try: from dotenv import load_dotenv, find_dotenv - load_dotenv(find_dotenv("../.env")) + load_dotenv(find_dotenv(str(BASE_DIR / ".env"))) except ImportError: print("dotenv not installed, skipping...") @@ -87,8 +90,7 @@ WEBUI_FAVICON_URL = "https://openwebui.com/favicon.png" ENV = os.environ.get("ENV", "dev") try: - with open(f"../package.json", "r") as f: - PACKAGE_DATA = json.load(f) + PACKAGE_DATA = json.loads((BASE_DIR / "package.json").read_text()) except: PACKAGE_DATA = {"version": "0.0.0"} @@ -115,8 +117,7 @@ def parse_section(section): try: - with open("../CHANGELOG.md", "r") as file: - changelog_content = file.read() + changelog_content = (BASE_DIR / "CHANGELOG.md").read_text() except: changelog_content = "" @@ -164,12 +165,11 @@ WEBUI_VERSION = os.environ.get("WEBUI_VERSION", "v1.0.0-alpha.100") # DATA/FRONTEND BUILD DIR #################################### -DATA_DIR = str(Path(os.getenv("DATA_DIR", "./data")).resolve()) -FRONTEND_BUILD_DIR = str(Path(os.getenv("FRONTEND_BUILD_DIR", "../build"))) +DATA_DIR = Path(os.getenv("DATA_DIR", BACKEND_DIR / "data")).resolve() +FRONTEND_BUILD_DIR = Path(os.getenv("FRONTEND_BUILD_DIR", BASE_DIR / "build")).resolve() try: - with open(f"{DATA_DIR}/config.json", "r") as f: - CONFIG_DATA = json.load(f) + CONFIG_DATA = json.loads((DATA_DIR / "config.json").read_text()) except: CONFIG_DATA = {} @@ -279,11 +279,11 @@ JWT_EXPIRES_IN = PersistentConfig( # Static DIR #################################### -STATIC_DIR = str(Path(os.getenv("STATIC_DIR", "./static")).resolve()) +STATIC_DIR = Path(os.getenv("STATIC_DIR", BACKEND_DIR / "static")).resolve() -frontend_favicon = f"{FRONTEND_BUILD_DIR}/favicon.png" -if os.path.exists(frontend_favicon): - shutil.copyfile(frontend_favicon, f"{STATIC_DIR}/favicon.png") +frontend_favicon = FRONTEND_BUILD_DIR / "favicon.png" +if frontend_favicon.exists(): + shutil.copyfile(frontend_favicon, STATIC_DIR / "favicon.png") else: logging.warning(f"Frontend favicon not found at {frontend_favicon}") diff --git a/backend/open_webui/__init__.py b/backend/open_webui/__init__.py new file mode 100644 index 000000000..8f22af8ca --- /dev/null +++ b/backend/open_webui/__init__.py @@ -0,0 +1,47 @@ +import base64 +import os +import random +from pathlib import Path + +import typer +import uvicorn + +import main + +app = typer.Typer() + +KEY_FILE = Path.cwd() / ".webui_secret_key" + + +@app.command() +def serve( + host: str = "0.0.0.0", + port: int = 8080, +): + if os.getenv("WEBUI_SECRET_KEY") is None: + typer.echo( + "Loading WEBUI_SECRET_KEY from file, not provided as an environment variable." + ) + if not KEY_FILE.exists(): + typer.echo(f"Generating a new secret key and saving it to {KEY_FILE}") + KEY_FILE.write_bytes(base64.b64encode(random.randbytes(12))) + typer.echo(f"Loading WEBUI_SECRET_KEY from {KEY_FILE}") + os.environ["WEBUI_SECRET_KEY"] = KEY_FILE.read_text() + + if os.getenv("USE_CUDA_DOCKER", "false") == "true": + typer.echo( + "CUDA is enabled, appending LD_LIBRARY_PATH to include torch/cudnn & cublas libraries." + ) + LD_LIBRARY_PATH = os.getenv("LD_LIBRARY_PATH", "").split(":") + os.environ["LD_LIBRARY_PATH"] = ":".join( + LD_LIBRARY_PATH + + [ + "/usr/local/lib/python3.11/site-packages/torch/lib", + "/usr/local/lib/python3.11/site-packages/nvidia/cudnn/lib", + ] + ) + uvicorn.run(main.app, host=host, port=port, forwarded_allow_ips="*") + + +if __name__ == "__main__": + app() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..37d96b16c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,110 @@ +[project] +name = "open-webui" +description = "Open WebUI (Formerly Ollama WebUI)" +authors = [ + { name = "Timothy Jaeryang Baek", email = "jaeryang_baek@sfu.ca" } +] +license = { file = "LICENSE" } +dependencies = [ + "fastapi==0.109.2", + "uvicorn[standard]==0.22.0", + "pydantic==2.7.1", + "python-multipart==0.0.9", + + "Flask==3.0.3", + "Flask-Cors==4.0.0", + + "python-socketio==5.11.2", + "python-jose==3.3.0", + "passlib[bcrypt]==1.7.4", + + "requests==2.31.0", + "aiohttp==3.9.5", + "peewee==3.17.3", + "peewee-migrate==1.12.2", + "psycopg2-binary==2.9.9", + "PyMySQL==1.1.0", + "bcrypt==4.1.2", + + "litellm[proxy]==1.35.28", + + "boto3==1.34.95", + + "argon2-cffi==23.1.0", + "APScheduler==3.10.4", + "google-generativeai==0.5.2", + + "langchain==0.1.16", + "langchain-community==0.0.34", + "langchain-chroma==0.1.0", + + "fake-useragent==1.5.1", + "chromadb==0.4.24", + "sentence-transformers==2.7.0", + "pypdf==4.2.0", + "docx2txt==0.8", + "unstructured==0.11.8", + "Markdown==3.6", + "pypandoc==1.13", + "pandas==2.2.2", + "openpyxl==3.1.2", + "pyxlsb==1.0.10", + "xlrd==2.0.1", + "validators==0.28.1", + + "opencv-python-headless==4.9.0.80", + "rapidocr-onnxruntime==1.2.3", + + "fpdf2==2.7.8", + "rank-bm25==0.2.2", + + "faster-whisper==1.0.1", + + "PyJWT[crypto]==2.8.0", + + "black==24.4.2", + "langfuse==2.27.3", + "youtube-transcript-api==0.6.2", + "pytube", +] +readme = "README.md" +requires-python = ">= 3.11, < 3.12.0a1" +dynamic = ["version"] +classifiers = [ + "Development Status :: 4 - Beta", + "License :: OSI Approved :: MIT License", + "Topic :: Communications :: Chat", + "Topic :: Multimedia", +] + +[project.scripts] +open-webui = "open_webui:app" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.rye] +managed = true +dev-dependencies = [] + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.version] +path = "package.json" +pattern = '"version":\s*"(?P[^"]+)"' + +[tool.hatch.build.targets.wheel] +ignore-vcs = true +packages = ["backend"] +sources = ["backend"] +exclude = [ + ".dockerignore", + ".gitignore", + ".webui_secret_key", + "dev.sh", + "requirements.txt", + "start.sh", + "start_windows.bat", +] diff --git a/requirements-dev.lock b/requirements-dev.lock new file mode 100644 index 000000000..fbc90e397 --- /dev/null +++ b/requirements-dev.lock @@ -0,0 +1,680 @@ +# generated by rye +# use `rye lock` or `rye sync` to update this lockfile +# +# last locked with the following flags: +# pre: false +# features: [] +# all-features: false +# with-sources: false + +-e file:. +aiohttp==3.9.5 + # via langchain + # via langchain-community + # via litellm + # via open-webui +aiosignal==1.3.1 + # via aiohttp +annotated-types==0.6.0 + # via pydantic +anyio==4.3.0 + # via httpx + # via openai + # via starlette + # via watchfiles +apscheduler==3.10.4 + # via litellm + # via open-webui +argon2-cffi==23.1.0 + # via open-webui +argon2-cffi-bindings==21.2.0 + # via argon2-cffi +asgiref==3.8.1 + # via opentelemetry-instrumentation-asgi +attrs==23.2.0 + # via aiohttp +av==11.0.0 + # via faster-whisper +backoff==2.2.1 + # via langfuse + # via litellm + # via posthog + # via unstructured +bcrypt==4.1.2 + # via chromadb + # via open-webui + # via passlib +beautifulsoup4==4.12.3 + # via unstructured +bidict==0.23.1 + # via python-socketio +black==24.4.2 + # via open-webui +blinker==1.8.2 + # via flask +boto3==1.34.95 + # via open-webui +botocore==1.34.103 + # via boto3 + # via s3transfer +build==1.2.1 + # via chromadb +cachetools==5.3.3 + # via google-auth +certifi==2024.2.2 + # via httpcore + # via httpx + # via kubernetes + # via pulsar-client + # via requests + # via unstructured-client +cffi==1.16.0 + # via argon2-cffi-bindings + # via cryptography +chardet==5.2.0 + # via unstructured +charset-normalizer==3.3.2 + # via requests + # via unstructured-client +chroma-hnswlib==0.7.3 + # via chromadb +chromadb==0.4.24 + # via langchain-chroma + # via open-webui +click==8.1.7 + # via black + # via flask + # via litellm + # via nltk + # via peewee-migrate + # via rq + # via typer + # via uvicorn +coloredlogs==15.0.1 + # via onnxruntime +cryptography==42.0.7 + # via litellm + # via pyjwt +ctranslate2==4.2.1 + # via faster-whisper +dataclasses-json==0.6.6 + # via langchain + # via langchain-community + # via unstructured + # via unstructured-client +deepdiff==7.0.1 + # via unstructured-client +defusedxml==0.7.1 + # via fpdf2 +deprecated==1.2.14 + # via opentelemetry-api + # via opentelemetry-exporter-otlp-proto-grpc +distro==1.9.0 + # via openai +dnspython==2.6.1 + # via email-validator +docx2txt==0.8 + # via open-webui +ecdsa==0.19.0 + # via python-jose +email-validator==2.1.1 + # via pydantic +emoji==2.11.1 + # via unstructured +et-xmlfile==1.1.0 + # via openpyxl +fake-useragent==1.5.1 + # via open-webui +fastapi==0.109.2 + # via chromadb + # via fastapi-sso + # via langchain-chroma + # via litellm + # via open-webui +fastapi-sso==0.10.0 + # via litellm +faster-whisper==1.0.1 + # via open-webui +filelock==3.14.0 + # via huggingface-hub + # via torch + # via transformers +filetype==1.2.0 + # via unstructured +flask==3.0.3 + # via flask-cors + # via open-webui +flask-cors==4.0.0 + # via open-webui +flatbuffers==24.3.25 + # via onnxruntime +fonttools==4.51.0 + # via fpdf2 +fpdf2==2.7.8 + # via open-webui +frozenlist==1.4.1 + # via aiohttp + # via aiosignal +fsspec==2024.3.1 + # via huggingface-hub + # via torch +google-ai-generativelanguage==0.6.2 + # via google-generativeai +google-api-core==2.19.0 + # via google-ai-generativelanguage + # via google-api-python-client + # via google-generativeai +google-api-python-client==2.129.0 + # via google-generativeai +google-auth==2.29.0 + # via google-ai-generativelanguage + # via google-api-core + # via google-api-python-client + # via google-auth-httplib2 + # via google-generativeai + # via kubernetes +google-auth-httplib2==0.2.0 + # via google-api-python-client +google-generativeai==0.5.2 + # via open-webui +googleapis-common-protos==1.63.0 + # via google-api-core + # via grpcio-status + # via opentelemetry-exporter-otlp-proto-grpc +grpcio==1.63.0 + # via chromadb + # via google-api-core + # via grpcio-status + # via opentelemetry-exporter-otlp-proto-grpc +grpcio-status==1.62.2 + # via google-api-core +gunicorn==21.2.0 + # via litellm +h11==0.14.0 + # via httpcore + # via uvicorn + # via wsproto +httpcore==1.0.5 + # via httpx +httplib2==0.22.0 + # via google-api-python-client + # via google-auth-httplib2 +httptools==0.6.1 + # via uvicorn +httpx==0.27.0 + # via fastapi-sso + # via langfuse + # via openai +huggingface-hub==0.23.0 + # via faster-whisper + # via sentence-transformers + # via tokenizers + # via transformers +humanfriendly==10.0 + # via coloredlogs +idna==3.7 + # via anyio + # via email-validator + # via httpx + # via langfuse + # via requests + # via unstructured-client + # via yarl +importlib-metadata==7.0.0 + # via litellm + # via opentelemetry-api +importlib-resources==6.4.0 + # via chromadb +itsdangerous==2.2.0 + # via flask +jinja2==3.1.4 + # via flask + # via litellm + # via torch +jmespath==1.0.1 + # via boto3 + # via botocore +joblib==1.4.2 + # via nltk + # via scikit-learn +jsonpatch==1.33 + # via langchain + # via langchain-core +jsonpath-python==1.0.6 + # via unstructured-client +jsonpointer==2.4 + # via jsonpatch +kubernetes==29.0.0 + # via chromadb +langchain==0.1.16 + # via open-webui +langchain-chroma==0.1.0 + # via open-webui +langchain-community==0.0.34 + # via langchain + # via open-webui +langchain-core==0.1.52 + # via langchain + # via langchain-chroma + # via langchain-community + # via langchain-text-splitters +langchain-text-splitters==0.0.1 + # via langchain +langdetect==1.0.9 + # via unstructured +langfuse==2.27.3 + # via open-webui +langsmith==0.1.57 + # via langchain + # via langchain-community + # via langchain-core +litellm==1.35.28 + # via open-webui +lxml==5.2.2 + # via unstructured +markdown==3.6 + # via open-webui +markdown-it-py==3.0.0 + # via rich +markupsafe==2.1.5 + # via jinja2 + # via werkzeug +marshmallow==3.21.2 + # via dataclasses-json + # via unstructured-client +mdurl==0.1.2 + # via markdown-it-py +mmh3==4.1.0 + # via chromadb +monotonic==1.6 + # via posthog +mpmath==1.3.0 + # via sympy +multidict==6.0.5 + # via aiohttp + # via yarl +mypy-extensions==1.0.0 + # via black + # via typing-inspect + # via unstructured-client +networkx==3.3 + # via torch +nltk==3.8.1 + # via unstructured +numpy==1.26.4 + # via chroma-hnswlib + # via chromadb + # via ctranslate2 + # via langchain + # via langchain-chroma + # via langchain-community + # via onnxruntime + # via opencv-python + # via opencv-python-headless + # via pandas + # via rank-bm25 + # via rapidocr-onnxruntime + # via scikit-learn + # via scipy + # via sentence-transformers + # via shapely + # via transformers + # via unstructured +oauthlib==3.2.2 + # via fastapi-sso + # via kubernetes + # via requests-oauthlib +onnxruntime==1.17.3 + # via chromadb + # via faster-whisper + # via rapidocr-onnxruntime +openai==1.28.1 + # via litellm +opencv-python==4.9.0.80 + # via rapidocr-onnxruntime +opencv-python-headless==4.9.0.80 + # via open-webui +openpyxl==3.1.2 + # via open-webui +opentelemetry-api==1.24.0 + # via chromadb + # via opentelemetry-exporter-otlp-proto-grpc + # via opentelemetry-instrumentation + # via opentelemetry-instrumentation-asgi + # via opentelemetry-instrumentation-fastapi + # via opentelemetry-sdk +opentelemetry-exporter-otlp-proto-common==1.24.0 + # via opentelemetry-exporter-otlp-proto-grpc +opentelemetry-exporter-otlp-proto-grpc==1.24.0 + # via chromadb +opentelemetry-instrumentation==0.45b0 + # via opentelemetry-instrumentation-asgi + # via opentelemetry-instrumentation-fastapi +opentelemetry-instrumentation-asgi==0.45b0 + # via opentelemetry-instrumentation-fastapi +opentelemetry-instrumentation-fastapi==0.45b0 + # via chromadb +opentelemetry-proto==1.24.0 + # via opentelemetry-exporter-otlp-proto-common + # via opentelemetry-exporter-otlp-proto-grpc +opentelemetry-sdk==1.24.0 + # via chromadb + # via opentelemetry-exporter-otlp-proto-grpc +opentelemetry-semantic-conventions==0.45b0 + # via opentelemetry-instrumentation-asgi + # via opentelemetry-instrumentation-fastapi + # via opentelemetry-sdk +opentelemetry-util-http==0.45b0 + # via opentelemetry-instrumentation-asgi + # via opentelemetry-instrumentation-fastapi +ordered-set==4.1.0 + # via deepdiff +orjson==3.10.3 + # via chromadb + # via langsmith + # via litellm +overrides==7.7.0 + # via chromadb +packaging==23.2 + # via black + # via build + # via gunicorn + # via huggingface-hub + # via langchain-core + # via langfuse + # via marshmallow + # via onnxruntime + # via transformers + # via unstructured-client +pandas==2.2.2 + # via open-webui +passlib==1.7.4 + # via open-webui +pathspec==0.12.1 + # via black +peewee==3.17.3 + # via open-webui + # via peewee-migrate +peewee-migrate==1.12.2 + # via open-webui +pillow==10.3.0 + # via fpdf2 + # via rapidocr-onnxruntime + # via sentence-transformers +platformdirs==4.2.1 + # via black +posthog==3.5.0 + # via chromadb +proto-plus==1.23.0 + # via google-ai-generativelanguage + # via google-api-core +protobuf==4.25.3 + # via google-ai-generativelanguage + # via google-api-core + # via google-generativeai + # via googleapis-common-protos + # via grpcio-status + # via onnxruntime + # via opentelemetry-proto + # via proto-plus +psycopg2-binary==2.9.9 + # via open-webui +pulsar-client==3.5.0 + # via chromadb +pyasn1==0.6.0 + # via pyasn1-modules + # via python-jose + # via rsa +pyasn1-modules==0.4.0 + # via google-auth +pyclipper==1.3.0.post5 + # via rapidocr-onnxruntime +pycparser==2.22 + # via cffi +pydantic==2.7.1 + # via chromadb + # via fastapi + # via fastapi-sso + # via google-generativeai + # via langchain + # via langchain-core + # via langfuse + # via langsmith + # via open-webui + # via openai +pydantic-core==2.18.2 + # via pydantic +pygments==2.18.0 + # via rich +pyjwt==2.8.0 + # via litellm + # via open-webui +pymysql==1.1.0 + # via open-webui +pypandoc==1.13 + # via open-webui +pyparsing==3.1.2 + # via httplib2 +pypdf==4.2.0 + # via open-webui + # via unstructured-client +pypika==0.48.9 + # via chromadb +pyproject-hooks==1.1.0 + # via build +python-dateutil==2.9.0.post0 + # via botocore + # via kubernetes + # via pandas + # via posthog + # via unstructured-client +python-dotenv==1.0.1 + # via litellm + # via uvicorn +python-engineio==4.9.0 + # via python-socketio +python-iso639==2024.4.27 + # via unstructured +python-jose==3.3.0 + # via open-webui +python-magic==0.4.27 + # via unstructured +python-multipart==0.0.9 + # via litellm + # via open-webui +python-socketio==5.11.2 + # via open-webui +pytube==15.0.0 + # via open-webui +pytz==2024.1 + # via apscheduler + # via pandas +pyxlsb==1.0.10 + # via open-webui +pyyaml==6.0.1 + # via chromadb + # via ctranslate2 + # via huggingface-hub + # via kubernetes + # via langchain + # via langchain-community + # via langchain-core + # via litellm + # via rapidocr-onnxruntime + # via transformers + # via uvicorn +rank-bm25==0.2.2 + # via open-webui +rapidfuzz==3.9.0 + # via unstructured +rapidocr-onnxruntime==1.2.3 + # via open-webui +redis==5.0.4 + # via rq +regex==2024.5.10 + # via nltk + # via tiktoken + # via transformers +requests==2.31.0 + # via chromadb + # via google-api-core + # via huggingface-hub + # via kubernetes + # via langchain + # via langchain-community + # via langsmith + # via litellm + # via open-webui + # via posthog + # via requests-oauthlib + # via tiktoken + # via transformers + # via unstructured + # via unstructured-client + # via youtube-transcript-api +requests-oauthlib==2.0.0 + # via kubernetes +rich==13.7.1 + # via typer +rq==1.16.2 + # via litellm +rsa==4.9 + # via google-auth + # via python-jose +s3transfer==0.10.1 + # via boto3 +safetensors==0.4.3 + # via transformers +scikit-learn==1.4.2 + # via sentence-transformers +scipy==1.13.0 + # via scikit-learn + # via sentence-transformers +sentence-transformers==2.7.0 + # via open-webui +setuptools==69.5.1 + # via ctranslate2 + # via opentelemetry-instrumentation +shapely==2.0.4 + # via rapidocr-onnxruntime +shellingham==1.5.4 + # via typer +simple-websocket==1.0.0 + # via python-engineio +six==1.16.0 + # via apscheduler + # via ecdsa + # via kubernetes + # via langdetect + # via posthog + # via python-dateutil + # via rapidocr-onnxruntime + # via unstructured-client +sniffio==1.3.1 + # via anyio + # via httpx + # via openai +soupsieve==2.5 + # via beautifulsoup4 +sqlalchemy==2.0.30 + # via langchain + # via langchain-community +starlette==0.36.3 + # via fastapi +sympy==1.12 + # via onnxruntime + # via torch +tabulate==0.9.0 + # via unstructured +tenacity==8.3.0 + # via chromadb + # via langchain + # via langchain-community + # via langchain-core +threadpoolctl==3.5.0 + # via scikit-learn +tiktoken==0.6.0 + # via litellm +tokenizers==0.15.2 + # via chromadb + # via faster-whisper + # via litellm + # via transformers +torch==2.3.0 + # via sentence-transformers +tqdm==4.66.4 + # via chromadb + # via google-generativeai + # via huggingface-hub + # via nltk + # via openai + # via sentence-transformers + # via transformers +transformers==4.39.3 + # via sentence-transformers +typer==0.12.3 + # via chromadb +typing-extensions==4.11.0 + # via chromadb + # via fastapi + # via google-generativeai + # via huggingface-hub + # via openai + # via opentelemetry-sdk + # via pydantic + # via pydantic-core + # via sqlalchemy + # via torch + # via typer + # via typing-inspect + # via unstructured + # via unstructured-client +typing-inspect==0.9.0 + # via dataclasses-json + # via unstructured-client +tzdata==2024.1 + # via pandas +tzlocal==5.2 + # via apscheduler +unstructured==0.11.8 + # via open-webui +unstructured-client==0.22.0 + # via unstructured +uritemplate==4.1.1 + # via google-api-python-client +urllib3==2.2.1 + # via botocore + # via kubernetes + # via requests + # via unstructured-client +uvicorn==0.22.0 + # via chromadb + # via litellm + # via open-webui +uvloop==0.19.0 + # via uvicorn +validators==0.28.1 + # via open-webui +watchfiles==0.21.0 + # via uvicorn +websocket-client==1.8.0 + # via kubernetes +websockets==12.0 + # via uvicorn +werkzeug==3.0.3 + # via flask +wrapt==1.16.0 + # via deprecated + # via langfuse + # via opentelemetry-instrumentation + # via unstructured +wsproto==1.2.0 + # via simple-websocket +xlrd==2.0.1 + # via open-webui +yarl==1.9.4 + # via aiohttp +youtube-transcript-api==0.6.2 + # via open-webui +zipp==3.18.1 + # via importlib-metadata diff --git a/requirements.lock b/requirements.lock new file mode 100644 index 000000000..fbc90e397 --- /dev/null +++ b/requirements.lock @@ -0,0 +1,680 @@ +# generated by rye +# use `rye lock` or `rye sync` to update this lockfile +# +# last locked with the following flags: +# pre: false +# features: [] +# all-features: false +# with-sources: false + +-e file:. +aiohttp==3.9.5 + # via langchain + # via langchain-community + # via litellm + # via open-webui +aiosignal==1.3.1 + # via aiohttp +annotated-types==0.6.0 + # via pydantic +anyio==4.3.0 + # via httpx + # via openai + # via starlette + # via watchfiles +apscheduler==3.10.4 + # via litellm + # via open-webui +argon2-cffi==23.1.0 + # via open-webui +argon2-cffi-bindings==21.2.0 + # via argon2-cffi +asgiref==3.8.1 + # via opentelemetry-instrumentation-asgi +attrs==23.2.0 + # via aiohttp +av==11.0.0 + # via faster-whisper +backoff==2.2.1 + # via langfuse + # via litellm + # via posthog + # via unstructured +bcrypt==4.1.2 + # via chromadb + # via open-webui + # via passlib +beautifulsoup4==4.12.3 + # via unstructured +bidict==0.23.1 + # via python-socketio +black==24.4.2 + # via open-webui +blinker==1.8.2 + # via flask +boto3==1.34.95 + # via open-webui +botocore==1.34.103 + # via boto3 + # via s3transfer +build==1.2.1 + # via chromadb +cachetools==5.3.3 + # via google-auth +certifi==2024.2.2 + # via httpcore + # via httpx + # via kubernetes + # via pulsar-client + # via requests + # via unstructured-client +cffi==1.16.0 + # via argon2-cffi-bindings + # via cryptography +chardet==5.2.0 + # via unstructured +charset-normalizer==3.3.2 + # via requests + # via unstructured-client +chroma-hnswlib==0.7.3 + # via chromadb +chromadb==0.4.24 + # via langchain-chroma + # via open-webui +click==8.1.7 + # via black + # via flask + # via litellm + # via nltk + # via peewee-migrate + # via rq + # via typer + # via uvicorn +coloredlogs==15.0.1 + # via onnxruntime +cryptography==42.0.7 + # via litellm + # via pyjwt +ctranslate2==4.2.1 + # via faster-whisper +dataclasses-json==0.6.6 + # via langchain + # via langchain-community + # via unstructured + # via unstructured-client +deepdiff==7.0.1 + # via unstructured-client +defusedxml==0.7.1 + # via fpdf2 +deprecated==1.2.14 + # via opentelemetry-api + # via opentelemetry-exporter-otlp-proto-grpc +distro==1.9.0 + # via openai +dnspython==2.6.1 + # via email-validator +docx2txt==0.8 + # via open-webui +ecdsa==0.19.0 + # via python-jose +email-validator==2.1.1 + # via pydantic +emoji==2.11.1 + # via unstructured +et-xmlfile==1.1.0 + # via openpyxl +fake-useragent==1.5.1 + # via open-webui +fastapi==0.109.2 + # via chromadb + # via fastapi-sso + # via langchain-chroma + # via litellm + # via open-webui +fastapi-sso==0.10.0 + # via litellm +faster-whisper==1.0.1 + # via open-webui +filelock==3.14.0 + # via huggingface-hub + # via torch + # via transformers +filetype==1.2.0 + # via unstructured +flask==3.0.3 + # via flask-cors + # via open-webui +flask-cors==4.0.0 + # via open-webui +flatbuffers==24.3.25 + # via onnxruntime +fonttools==4.51.0 + # via fpdf2 +fpdf2==2.7.8 + # via open-webui +frozenlist==1.4.1 + # via aiohttp + # via aiosignal +fsspec==2024.3.1 + # via huggingface-hub + # via torch +google-ai-generativelanguage==0.6.2 + # via google-generativeai +google-api-core==2.19.0 + # via google-ai-generativelanguage + # via google-api-python-client + # via google-generativeai +google-api-python-client==2.129.0 + # via google-generativeai +google-auth==2.29.0 + # via google-ai-generativelanguage + # via google-api-core + # via google-api-python-client + # via google-auth-httplib2 + # via google-generativeai + # via kubernetes +google-auth-httplib2==0.2.0 + # via google-api-python-client +google-generativeai==0.5.2 + # via open-webui +googleapis-common-protos==1.63.0 + # via google-api-core + # via grpcio-status + # via opentelemetry-exporter-otlp-proto-grpc +grpcio==1.63.0 + # via chromadb + # via google-api-core + # via grpcio-status + # via opentelemetry-exporter-otlp-proto-grpc +grpcio-status==1.62.2 + # via google-api-core +gunicorn==21.2.0 + # via litellm +h11==0.14.0 + # via httpcore + # via uvicorn + # via wsproto +httpcore==1.0.5 + # via httpx +httplib2==0.22.0 + # via google-api-python-client + # via google-auth-httplib2 +httptools==0.6.1 + # via uvicorn +httpx==0.27.0 + # via fastapi-sso + # via langfuse + # via openai +huggingface-hub==0.23.0 + # via faster-whisper + # via sentence-transformers + # via tokenizers + # via transformers +humanfriendly==10.0 + # via coloredlogs +idna==3.7 + # via anyio + # via email-validator + # via httpx + # via langfuse + # via requests + # via unstructured-client + # via yarl +importlib-metadata==7.0.0 + # via litellm + # via opentelemetry-api +importlib-resources==6.4.0 + # via chromadb +itsdangerous==2.2.0 + # via flask +jinja2==3.1.4 + # via flask + # via litellm + # via torch +jmespath==1.0.1 + # via boto3 + # via botocore +joblib==1.4.2 + # via nltk + # via scikit-learn +jsonpatch==1.33 + # via langchain + # via langchain-core +jsonpath-python==1.0.6 + # via unstructured-client +jsonpointer==2.4 + # via jsonpatch +kubernetes==29.0.0 + # via chromadb +langchain==0.1.16 + # via open-webui +langchain-chroma==0.1.0 + # via open-webui +langchain-community==0.0.34 + # via langchain + # via open-webui +langchain-core==0.1.52 + # via langchain + # via langchain-chroma + # via langchain-community + # via langchain-text-splitters +langchain-text-splitters==0.0.1 + # via langchain +langdetect==1.0.9 + # via unstructured +langfuse==2.27.3 + # via open-webui +langsmith==0.1.57 + # via langchain + # via langchain-community + # via langchain-core +litellm==1.35.28 + # via open-webui +lxml==5.2.2 + # via unstructured +markdown==3.6 + # via open-webui +markdown-it-py==3.0.0 + # via rich +markupsafe==2.1.5 + # via jinja2 + # via werkzeug +marshmallow==3.21.2 + # via dataclasses-json + # via unstructured-client +mdurl==0.1.2 + # via markdown-it-py +mmh3==4.1.0 + # via chromadb +monotonic==1.6 + # via posthog +mpmath==1.3.0 + # via sympy +multidict==6.0.5 + # via aiohttp + # via yarl +mypy-extensions==1.0.0 + # via black + # via typing-inspect + # via unstructured-client +networkx==3.3 + # via torch +nltk==3.8.1 + # via unstructured +numpy==1.26.4 + # via chroma-hnswlib + # via chromadb + # via ctranslate2 + # via langchain + # via langchain-chroma + # via langchain-community + # via onnxruntime + # via opencv-python + # via opencv-python-headless + # via pandas + # via rank-bm25 + # via rapidocr-onnxruntime + # via scikit-learn + # via scipy + # via sentence-transformers + # via shapely + # via transformers + # via unstructured +oauthlib==3.2.2 + # via fastapi-sso + # via kubernetes + # via requests-oauthlib +onnxruntime==1.17.3 + # via chromadb + # via faster-whisper + # via rapidocr-onnxruntime +openai==1.28.1 + # via litellm +opencv-python==4.9.0.80 + # via rapidocr-onnxruntime +opencv-python-headless==4.9.0.80 + # via open-webui +openpyxl==3.1.2 + # via open-webui +opentelemetry-api==1.24.0 + # via chromadb + # via opentelemetry-exporter-otlp-proto-grpc + # via opentelemetry-instrumentation + # via opentelemetry-instrumentation-asgi + # via opentelemetry-instrumentation-fastapi + # via opentelemetry-sdk +opentelemetry-exporter-otlp-proto-common==1.24.0 + # via opentelemetry-exporter-otlp-proto-grpc +opentelemetry-exporter-otlp-proto-grpc==1.24.0 + # via chromadb +opentelemetry-instrumentation==0.45b0 + # via opentelemetry-instrumentation-asgi + # via opentelemetry-instrumentation-fastapi +opentelemetry-instrumentation-asgi==0.45b0 + # via opentelemetry-instrumentation-fastapi +opentelemetry-instrumentation-fastapi==0.45b0 + # via chromadb +opentelemetry-proto==1.24.0 + # via opentelemetry-exporter-otlp-proto-common + # via opentelemetry-exporter-otlp-proto-grpc +opentelemetry-sdk==1.24.0 + # via chromadb + # via opentelemetry-exporter-otlp-proto-grpc +opentelemetry-semantic-conventions==0.45b0 + # via opentelemetry-instrumentation-asgi + # via opentelemetry-instrumentation-fastapi + # via opentelemetry-sdk +opentelemetry-util-http==0.45b0 + # via opentelemetry-instrumentation-asgi + # via opentelemetry-instrumentation-fastapi +ordered-set==4.1.0 + # via deepdiff +orjson==3.10.3 + # via chromadb + # via langsmith + # via litellm +overrides==7.7.0 + # via chromadb +packaging==23.2 + # via black + # via build + # via gunicorn + # via huggingface-hub + # via langchain-core + # via langfuse + # via marshmallow + # via onnxruntime + # via transformers + # via unstructured-client +pandas==2.2.2 + # via open-webui +passlib==1.7.4 + # via open-webui +pathspec==0.12.1 + # via black +peewee==3.17.3 + # via open-webui + # via peewee-migrate +peewee-migrate==1.12.2 + # via open-webui +pillow==10.3.0 + # via fpdf2 + # via rapidocr-onnxruntime + # via sentence-transformers +platformdirs==4.2.1 + # via black +posthog==3.5.0 + # via chromadb +proto-plus==1.23.0 + # via google-ai-generativelanguage + # via google-api-core +protobuf==4.25.3 + # via google-ai-generativelanguage + # via google-api-core + # via google-generativeai + # via googleapis-common-protos + # via grpcio-status + # via onnxruntime + # via opentelemetry-proto + # via proto-plus +psycopg2-binary==2.9.9 + # via open-webui +pulsar-client==3.5.0 + # via chromadb +pyasn1==0.6.0 + # via pyasn1-modules + # via python-jose + # via rsa +pyasn1-modules==0.4.0 + # via google-auth +pyclipper==1.3.0.post5 + # via rapidocr-onnxruntime +pycparser==2.22 + # via cffi +pydantic==2.7.1 + # via chromadb + # via fastapi + # via fastapi-sso + # via google-generativeai + # via langchain + # via langchain-core + # via langfuse + # via langsmith + # via open-webui + # via openai +pydantic-core==2.18.2 + # via pydantic +pygments==2.18.0 + # via rich +pyjwt==2.8.0 + # via litellm + # via open-webui +pymysql==1.1.0 + # via open-webui +pypandoc==1.13 + # via open-webui +pyparsing==3.1.2 + # via httplib2 +pypdf==4.2.0 + # via open-webui + # via unstructured-client +pypika==0.48.9 + # via chromadb +pyproject-hooks==1.1.0 + # via build +python-dateutil==2.9.0.post0 + # via botocore + # via kubernetes + # via pandas + # via posthog + # via unstructured-client +python-dotenv==1.0.1 + # via litellm + # via uvicorn +python-engineio==4.9.0 + # via python-socketio +python-iso639==2024.4.27 + # via unstructured +python-jose==3.3.0 + # via open-webui +python-magic==0.4.27 + # via unstructured +python-multipart==0.0.9 + # via litellm + # via open-webui +python-socketio==5.11.2 + # via open-webui +pytube==15.0.0 + # via open-webui +pytz==2024.1 + # via apscheduler + # via pandas +pyxlsb==1.0.10 + # via open-webui +pyyaml==6.0.1 + # via chromadb + # via ctranslate2 + # via huggingface-hub + # via kubernetes + # via langchain + # via langchain-community + # via langchain-core + # via litellm + # via rapidocr-onnxruntime + # via transformers + # via uvicorn +rank-bm25==0.2.2 + # via open-webui +rapidfuzz==3.9.0 + # via unstructured +rapidocr-onnxruntime==1.2.3 + # via open-webui +redis==5.0.4 + # via rq +regex==2024.5.10 + # via nltk + # via tiktoken + # via transformers +requests==2.31.0 + # via chromadb + # via google-api-core + # via huggingface-hub + # via kubernetes + # via langchain + # via langchain-community + # via langsmith + # via litellm + # via open-webui + # via posthog + # via requests-oauthlib + # via tiktoken + # via transformers + # via unstructured + # via unstructured-client + # via youtube-transcript-api +requests-oauthlib==2.0.0 + # via kubernetes +rich==13.7.1 + # via typer +rq==1.16.2 + # via litellm +rsa==4.9 + # via google-auth + # via python-jose +s3transfer==0.10.1 + # via boto3 +safetensors==0.4.3 + # via transformers +scikit-learn==1.4.2 + # via sentence-transformers +scipy==1.13.0 + # via scikit-learn + # via sentence-transformers +sentence-transformers==2.7.0 + # via open-webui +setuptools==69.5.1 + # via ctranslate2 + # via opentelemetry-instrumentation +shapely==2.0.4 + # via rapidocr-onnxruntime +shellingham==1.5.4 + # via typer +simple-websocket==1.0.0 + # via python-engineio +six==1.16.0 + # via apscheduler + # via ecdsa + # via kubernetes + # via langdetect + # via posthog + # via python-dateutil + # via rapidocr-onnxruntime + # via unstructured-client +sniffio==1.3.1 + # via anyio + # via httpx + # via openai +soupsieve==2.5 + # via beautifulsoup4 +sqlalchemy==2.0.30 + # via langchain + # via langchain-community +starlette==0.36.3 + # via fastapi +sympy==1.12 + # via onnxruntime + # via torch +tabulate==0.9.0 + # via unstructured +tenacity==8.3.0 + # via chromadb + # via langchain + # via langchain-community + # via langchain-core +threadpoolctl==3.5.0 + # via scikit-learn +tiktoken==0.6.0 + # via litellm +tokenizers==0.15.2 + # via chromadb + # via faster-whisper + # via litellm + # via transformers +torch==2.3.0 + # via sentence-transformers +tqdm==4.66.4 + # via chromadb + # via google-generativeai + # via huggingface-hub + # via nltk + # via openai + # via sentence-transformers + # via transformers +transformers==4.39.3 + # via sentence-transformers +typer==0.12.3 + # via chromadb +typing-extensions==4.11.0 + # via chromadb + # via fastapi + # via google-generativeai + # via huggingface-hub + # via openai + # via opentelemetry-sdk + # via pydantic + # via pydantic-core + # via sqlalchemy + # via torch + # via typer + # via typing-inspect + # via unstructured + # via unstructured-client +typing-inspect==0.9.0 + # via dataclasses-json + # via unstructured-client +tzdata==2024.1 + # via pandas +tzlocal==5.2 + # via apscheduler +unstructured==0.11.8 + # via open-webui +unstructured-client==0.22.0 + # via unstructured +uritemplate==4.1.1 + # via google-api-python-client +urllib3==2.2.1 + # via botocore + # via kubernetes + # via requests + # via unstructured-client +uvicorn==0.22.0 + # via chromadb + # via litellm + # via open-webui +uvloop==0.19.0 + # via uvicorn +validators==0.28.1 + # via open-webui +watchfiles==0.21.0 + # via uvicorn +websocket-client==1.8.0 + # via kubernetes +websockets==12.0 + # via uvicorn +werkzeug==3.0.3 + # via flask +wrapt==1.16.0 + # via deprecated + # via langfuse + # via opentelemetry-instrumentation + # via unstructured +wsproto==1.2.0 + # via simple-websocket +xlrd==2.0.1 + # via open-webui +yarl==1.9.4 + # via aiohttp +youtube-transcript-api==0.6.2 + # via open-webui +zipp==3.18.1 + # via importlib-metadata From a018df2734595080112d61c28b8c3cae5f6cca05 Mon Sep 17 00:00:00 2001 From: Tang Ziya Date: Mon, 20 May 2024 11:12:03 +0800 Subject: [PATCH 2/3] infra: build --- backend/apps/web/internal/db.py | 6 ++++-- backend/config.py | 10 ++++++++-- backend/open_webui/__init__.py | 17 +++++++++++++++-- hatch_build.py | 21 +++++++++++++++++++++ pyproject.toml | 9 +++++++-- 5 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 hatch_build.py diff --git a/backend/apps/web/internal/db.py b/backend/apps/web/internal/db.py index 136e3fafc..a6051de50 100644 --- a/backend/apps/web/internal/db.py +++ b/backend/apps/web/internal/db.py @@ -1,7 +1,7 @@ from peewee import * from peewee_migrate import Router from playhouse.db_url import connect -from config import SRC_LOG_LEVELS, DATA_DIR, DATABASE_URL +from config import SRC_LOG_LEVELS, DATA_DIR, DATABASE_URL, BACKEND_DIR import os import logging @@ -18,6 +18,8 @@ else: DB = connect(DATABASE_URL) log.info(f"Connected to a {DB.__class__.__name__} database.") -router = Router(DB, migrate_dir="apps/web/internal/migrations", logger=log) +router = Router( + DB, migrate_dir=BACKEND_DIR / "apps" / "web" / "internal" / "migrations", logger=log +) router.run() DB.connect(reuse_if_open=True) diff --git a/backend/config.py b/backend/config.py index b44b2b64e..9ba059008 100644 --- a/backend/config.py +++ b/backend/config.py @@ -1,6 +1,8 @@ import os import sys import logging +import importlib.metadata +import pkgutil import chromadb from chromadb import Settings from base64 import b64encode @@ -92,7 +94,10 @@ ENV = os.environ.get("ENV", "dev") try: PACKAGE_DATA = json.loads((BASE_DIR / "package.json").read_text()) except: - PACKAGE_DATA = {"version": "0.0.0"} + try: + PACKAGE_DATA = {"version": importlib.metadata.version("open-webui")} + except importlib.metadata.PackageNotFoundError: + PACKAGE_DATA = {"version": "0.0.0"} VERSION = PACKAGE_DATA["version"] @@ -119,7 +124,8 @@ def parse_section(section): try: changelog_content = (BASE_DIR / "CHANGELOG.md").read_text() except: - changelog_content = "" + changelog_content = (pkgutil.get_data("open_webui", "CHANGELOG.md") or b"").decode() + # Convert markdown content to HTML html_content = markdown.markdown(changelog_content) diff --git a/backend/open_webui/__init__.py b/backend/open_webui/__init__.py index 8f22af8ca..1defac824 100644 --- a/backend/open_webui/__init__.py +++ b/backend/open_webui/__init__.py @@ -6,11 +6,11 @@ from pathlib import Path import typer import uvicorn -import main - app = typer.Typer() KEY_FILE = Path.cwd() / ".webui_secret_key" +if (frontend_build_dir := Path(__file__).parent / "frontend").exists(): + os.environ["FRONTEND_BUILD_DIR"] = str(frontend_build_dir) @app.command() @@ -40,8 +40,21 @@ def serve( "/usr/local/lib/python3.11/site-packages/nvidia/cudnn/lib", ] ) + import main # we need set environment variables before importing main + uvicorn.run(main.app, host=host, port=port, forwarded_allow_ips="*") +@app.command() +def dev( + host: str = "0.0.0.0", + port: int = 8080, + reload: bool = True, +): + uvicorn.run( + "main:app", host=host, port=port, reload=reload, forwarded_allow_ips="*" + ) + + if __name__ == "__main__": app() diff --git a/hatch_build.py b/hatch_build.py new file mode 100644 index 000000000..2fa9e4805 --- /dev/null +++ b/hatch_build.py @@ -0,0 +1,21 @@ +# noqa: INP001 +import shutil +import subprocess +from sys import stderr + +from hatchling.builders.hooks.plugin.interface import BuildHookInterface + + +class CustomBuildHook(BuildHookInterface): + def initialize(self, version, build_data): + super().initialize(version, build_data) + stderr.write(">>> Building Open Webui frontend\n") + npm = shutil.which("npm") + if npm is None: + raise RuntimeError( + "NodeJS `npm` is required for building Open Webui but it was not found" + ) + stderr.write("### npm install\n") + subprocess.run([npm, "install"], check=True) # noqa: S603 + stderr.write("\n### npm run build\n") + subprocess.run([npm, "run", "build"], check=True) # noqa: S603 diff --git a/pyproject.toml b/pyproject.toml index 37d96b16c..93889d8b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,6 +73,8 @@ dynamic = ["version"] classifiers = [ "Development Status :: 4 - Beta", "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", "Topic :: Communications :: Chat", "Topic :: Multimedia", ] @@ -95,9 +97,9 @@ allow-direct-references = true path = "package.json" pattern = '"version":\s*"(?P[^"]+)"' +[tool.hatch.build.hooks.custom] # keep this for reading hooks from `hatch_build.py` + [tool.hatch.build.targets.wheel] -ignore-vcs = true -packages = ["backend"] sources = ["backend"] exclude = [ ".dockerignore", @@ -107,4 +109,7 @@ exclude = [ "requirements.txt", "start.sh", "start_windows.bat", + "webui.db", + "chroma.sqlite3", ] +force-include = { "CHANGELOG.md" = "open_webui/CHANGELOG.md", build = "open_webui/frontend" } From b60989627ef1b790bb86bbfe3763bfb4efd023c7 Mon Sep 17 00:00:00 2001 From: Tang Ziya Date: Mon, 20 May 2024 16:18:31 +0800 Subject: [PATCH 3/3] add: github action --- .github/workflows/ci.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..e86fa1441 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +name: Release + +on: + push: + branches: + - main # or whatever branch you want to use + +jobs: + release: + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/open-webui + permissions: + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 18 + - uses: actions/setup-python@v5 + with: + python-version: 3.11 + - name: Build + run: | + python -m pip install --upgrade pip + pip install build + python -m build . + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1