detection 100 % · FPR 36 % · F1 0.96
the model learned to flag everything.
v2 · Analyzer (principled retrain)
detection 99.3 % · FPR 6.7 % · F1 0.99
same detection, FPR collapsed 5×.
Scammer LoRA (0.5B + GRPO)
best-of-8 bypass 93.75 % vs rules
beats 70B+ frontier LLMs at evasion.
Once the demo is live, you'll see eight tabs: Replay, Live Q&A, You vs Analyzer, 🎭 Trained Scammer, Adversary Lab, v1↔v2 toggle, 🔴 Red-team it yourself, and Leaderboard.
"""
@app.get("/demo/preview", response_class=HTMLResponse, include_in_schema=False)
def demo_preview() -> HTMLResponse:
"""Static fallback that renders instantly while Gradio /demo/ warms up.
Self-redirects to /demo/ once that route returns 200."""
return HTMLResponse(_DEMO_PREVIEW_HTML)
# ---------------------------------------------------------------------------
# Mount the Gradio demo at /demo. Lazy-import so importing server.app stays
# cheap for tools that only want the FastAPI app (the existing test suite).
# ---------------------------------------------------------------------------
def _mount_demo() -> None:
"""Mount the Gradio demo at /demo. Lazy imports keep the OpenEnv API
alive even if `gradio` is not installed (e.g. in a slim runtime image)."""
import gradio as gr # type: ignore[import-not-found]
from server.demo_ui import build_app as _build_demo, _build_theme, CUSTOM_CSS
demo_blocks = _build_demo()
gr.mount_gradio_app(
app,
demo_blocks,
path="/demo",
theme=_build_theme(),
css=CUSTOM_CSS,
)
# Mount on import so uvicorn picks it up without a separate startup hook.
# Failures here must not crash the OpenEnv API surface — log full traceback
# and continue so /reset, /step, /state, /eval, /diagnose still serve.
try:
_mount_demo()
except (ImportError, ModuleNotFoundError) as _demo_err:
import logging
logging.getLogger("chakravyuh.app").error(
"Gradio not installed; /demo route disabled. Error: %s", _demo_err
)
except Exception:
import logging
logging.getLogger("chakravyuh.app").exception(
"Unexpected failure mounting Gradio demo at /demo — /demo will 404 "
"but other OpenEnv routes remain healthy. See traceback above."
)
def main() -> None:
import uvicorn
uvicorn.run(
app,
host=os.getenv("HOST", "0.0.0.0"),
port=int(os.getenv("PORT", "8000")),
)
if __name__ == "__main__":
main()