FateForge / app.py
FateForge
Deploy to HF Spaces: Vue SPA + FastAPI, Docker SDK, LLM offline fallback
c9e11de
Raw
History Blame Contribute Delete
2.05 kB
"""FateForge v2 — 入口 (HF Spaces Gradio SDK, 不可更名)。
启动:
python app.py # 默认 127.0.0.1:7860
set FATEFORGE_PORT=7861 && python app.py
"""
from __future__ import annotations
import logging
import gradio as gr
from fastapi.routing import APIRoute
from fastapi.staticfiles import StaticFiles
from starlette.routing import Mount
from fateforge.config import HOST, PORT, STATIC_DIR
from fateforge.server import cast_seed, favicon, index, read
# 压制 Gradio 内部健康检查产生的 httpx 日志噪音
logging.getLogger("httpx").setLevel(logging.WARNING)
# ── Gradio 最小化包装器 (HF Spaces 兼容; 真实 UI 是 Vue SPA) ─────────────────
with gr.Blocks(title="FateForge") as demo:
pass # 不使用 Gradio 组件 UI; Vue SPA 挂载在下方
# ── 构建带有 fateforge 路由的自定义 App ────────────────────────────────────────
from gradio.routes import App as _GradioApp # noqa: E402
_app = _GradioApp.create_app(demo)
# 将 fateforge 路由插到 Gradio 默认路由之前 (优先匹配)
_fateforge_routes: list = [
APIRoute("/", index, methods=["GET"], include_in_schema=False),
APIRoute("/favicon.ico", favicon, methods=["GET"], include_in_schema=False),
APIRoute("/api/cast/seed", cast_seed, methods=["POST"]),
APIRoute("/api/read", read, methods=["POST"]),
]
for _i, _r in enumerate(_fateforge_routes):
_app.router.routes.insert(_i, _r)
# 静态文件 (Vue SPA 的 JS/CSS/图片等), 插在 API 路由之后、Gradio 路由之前
if STATIC_DIR.exists():
_app.router.routes.insert(
len(_fateforge_routes),
Mount("/static", app=StaticFiles(directory=STATIC_DIR), name="fateforge_static"),
)
# 暴露给 ASGI workers (HF Spaces / uvicorn 直接挂载)
app = _app
if __name__ == "__main__":
demo.launch(
server_name=HOST,
server_port=PORT,
_app=_app,
)