"""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() # one inference at a time: CPU threads beat concurrency print(f"[boot] {model.DEMO['title']} — mock={model.MOCK}", flush=True) model.warmup() # load model / validate fixtures before first request print("[boot] ready", flush=True) app = Flask(__name__) @app.route("/") def index(): return send_from_directory(STATIC, "index.html") @app.route("/") 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)