File size: 3,081 Bytes
2aa8b3a
 
 
 
 
 
 
 
 
 
 
c0e055b
 
 
 
 
 
 
2aa8b3a
 
 
 
 
 
 
 
 
 
 
 
 
 
c0e055b
 
 
 
 
 
 
 
 
 
 
 
2f38578
2aa8b3a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2f38578
 
 
 
 
 
 
 
 
 
 
 
 
2aa8b3a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Entrypoint for the Distinct server on HuggingFace Spaces.

This version is optimized for Spaces execution, where the Gradio app
must be available at module level.
"""

from __future__ import annotations

import os
import sys

try:
    # ZeroGPU hardware: the `spaces` package must be imported before gradio,
    # and startup fails unless at least one @spaces.GPU function exists.
    import spaces  # type: ignore[import-not-found]
except ImportError:  # not on ZeroGPU (local dev, CPU Space)
    spaces = None  # type: ignore[assignment]

from distinct_protocol.netpolicy import announce_bind, launch_kwargs
from distinct_server.auth_routes import attach as attach_auth
from distinct_server.identity import NotConfigured, refuse_mocked_oauth
from distinct_server.presentation import CSS, HEAD
from distinct_server.ui import build_app, distinct_theme

# Build the app at module level for Spaces
demo = build_app()

# Apply presentation settings
demo.css = CSS
demo.theme = distinct_theme()
demo.head = HEAD

if spaces is not None:

    @spaces.GPU
    def _zerogpu_presence() -> str:
        """Satisfy ZeroGPU's startup check.

        Distinct's GPU work happens on distributed worker machines, not in
        this Space, but ZeroGPU hardware refuses to start an app that
        declares no @spaces.GPU function.
        """
        return "ok"

# HuggingFace Spaces runs this file as a script, so __main__ executes there too.
if __name__ == "__main__":
    try:
        refuse_mocked_oauth()
    except NotConfigured as reason:
        print(f"distinct: {reason}", file=sys.stderr)
        raise SystemExit(2) from None

    served = demo.queue(default_concurrency_limit=16, max_size=256)
    presentation = {
        "show_error": os.environ.get("DISTINCT_SHOW_ERRORS") == "1",
        "theme": distinct_theme(),
        "css": CSS,
        "head": HEAD,
    }

    on_spaces = os.environ.get("SYSTEM") == "spaces" and bool(os.environ.get("SPACE_ID"))
    if on_spaces:
        # On Spaces the platform dictates the bind: gradio reads
        # GRADIO_SERVER_NAME (0.0.0.0) and GRADIO_SERVER_PORT (7860) from the
        # environment. Never apply the local-dev network policy here — binding
        # 127.0.0.1 makes the Space unreachable and it hangs at "Preparing".
        served.launch(**presentation)
        raise SystemExit(0)

    # Local development path
    network = launch_kwargs()
    announce_bind(str(network["server_name"]), int(network["server_port"]))

    import fastapi
    import gradio as gr
    import uvicorn

    api = fastapi.FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
    if attach_auth(api):
        print(
            "distinct: sign-in at /auth/login, callback at /auth/callback.",
            file=sys.stderr,
            flush=True,
        )
        mounted = gr.mount_gradio_app(api, served, path="/", **presentation)
        uvicorn.run(
            mounted,
            host=str(network["server_name"]),
            port=int(network["server_port"]),
        )
    else:
        served.launch(**presentation, **network)