| """GLiNER 2.5 demo server — identical for every demo. |
| |
| Serves the static page, answers /api/ready, and POSTs {text, ...} to /api/infer, |
| which it delegates to model.infer(). All demo-specific logic lives in model.py. |
| |
| python app.py # local dev on :7860 |
| """ |
|
|
| import os |
| import threading |
| import time |
|
|
| from flask import Flask, request, send_from_directory |
|
|
| import model |
|
|
| APP_DIR = os.path.dirname(os.path.abspath(__file__)) |
| STATIC = os.path.join(APP_DIR, "static") |
|
|
| _LOCK = threading.Lock() |
|
|
| print(f"[boot] {model.DEMO['title']} — mock={model.MOCK}", flush=True) |
| model.warmup() |
| print("[boot] ready", flush=True) |
|
|
| app = Flask(__name__) |
|
|
|
|
| @app.route("/") |
| def index(): |
| return send_from_directory(STATIC, "index.html") |
|
|
|
|
| @app.route("/<path:name>") |
| def static_file(name): |
| if name in ("brand.css", "strip.js", "favicon.svg"): |
| return send_from_directory(STATIC, name) |
| return ("not found", 404) |
|
|
|
|
| @app.route("/api/config") |
| def config(): |
| """Demo content for the page: title, subtitle, example chips. No results.""" |
| return {k: v for k, v in model.DEMO.items() if k != "internal"} |
|
|
|
|
| @app.route("/api/ready") |
| def ready(): |
| return {"ready": True} |
|
|
|
|
| @app.route("/api/infer", methods=["POST"]) |
| def infer(): |
| data = request.get_json(silent=True) or {} |
| t0 = time.perf_counter() |
| with _LOCK: |
| out = model.infer(data) |
| out["ms"] = round((time.perf_counter() - t0) * 1000) |
| return out |
|
|
|
|
| if __name__ == "__main__": |
| app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)), threaded=True) |
|
|