File size: 2,970 Bytes
8a2dcce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4fcfcad
 
 
 
 
 
52a68d1
8a2dcce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
"""
Flask application entrypoint.

At this stage of the build (Layer 1), only the database and authentication
are wired up so this layer can be tested in isolation. Chat/RAG/agent
routes will be added in later layers.
"""
# http://127.0.0.1:7860/


import os
import threading

# Some corporate proxies / VPNs set HTTP_PROXY / HTTPS_PROXY, which makes
# Gradio's internal "is localhost reachable" check fail even for 127.0.0.1.
os.environ["NO_PROXY"] = "127.0.0.1,localhost," + os.environ.get("NO_PROXY", "")
os.environ["no_proxy"] = os.environ["NO_PROXY"]

# --- Workaround for a gradio_client bug (gradio 4.44.1 + newer pydantic) ---
# When a schema (or a nested value like `additionalProperties`) is a plain
# bool (True/False) rather than a dict, gradio_client's schema walker either
# crashes with "TypeError: argument of type 'bool' is not iterable" or raises
# "APIInfoParseError: Cannot parse schema True". This happens while Gradio
# builds the page's embedded API info, unconditionally, on every request to
# "/" - so it can't be avoided via show_api=False. Patch both entry points.
import gradio_client.utils as _gc_utils

_orig_get_type = _gc_utils.get_type
_orig_json_schema_to_python_type = _gc_utils._json_schema_to_python_type

import spaces

@spaces.GPU(duration=1)
def _warmup():
    return True

# _warmup()

def _safe_get_type(schema):
    if isinstance(schema, bool):
        return "Any"
    return _orig_get_type(schema)


def _safe_json_schema_to_python_type(schema, defs=None):
    if isinstance(schema, bool):
        return "Any"
    return _orig_json_schema_to_python_type(schema, defs)


_gc_utils.get_type = _safe_get_type
_gc_utils._json_schema_to_python_type = _safe_json_schema_to_python_type
# --- end workaround ---

from flask import Flask

import config
from auth.db import init_db
from auth.routes import auth_bp
from chat_routes import chat_bp
from ui.layout import build_ui


def create_app():
    app = Flask(__name__)

    app.config["SECRET_KEY"] = config.SECRET_KEY
    app.config["SQLALCHEMY_DATABASE_URI"] = config.SQLALCHEMY_DATABASE_URI
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = config.SQLALCHEMY_TRACK_MODIFICATIONS

    init_db(app)

    app.register_blueprint(auth_bp)
    app.register_blueprint(chat_bp)

    @app.route("/health")
    def health():
        return {"status": "ok"}

    return app


if __name__ == "__main__":
    flask_app = create_app()

    # Run the Flask REST API (auth + chat endpoints) on a background thread.
    api_thread = threading.Thread(
        target=lambda: flask_app.run(port=5000, debug=False, use_reloader=False),
        daemon=True,
    )
    api_thread.start()

    # Gradio UI is the main process. Its callbacks call into Flask
    # in-process via app_context() (see ui/callbacks.py) rather than HTTP.
    demo = build_ui(flask_app)
    demo.queue().launch(
        server_name="0.0.0.0",
        server_port=7860,
        show_api=False,
        inbrowser=False,
    )