| from fastapi import FastAPI, Request |
| from fastapi.responses import HTMLResponse, StreamingResponse |
| import asyncio |
| import os |
| import uvicorn |
| import logging |
|
|
| |
| logging.getLogger("uvicorn.access").setLevel(logging.WARNING) |
|
|
| app = FastAPI(title="Dynamic Guardrail Env") |
|
|
|
|
| METRICS_FILE = "metrics.jsonl" |
|
|
| async def event_generator(request: Request): |
| if not os.path.exists(METRICS_FILE): |
| open(METRICS_FILE, "w").close() |
|
|
| with open(METRICS_FILE, "r", encoding="utf-8") as f: |
| last_pos = f.tell() |
| while True: |
| if await request.is_disconnected(): |
| break |
|
|
| try: |
| file_size = os.path.getsize(METRICS_FILE) |
| except OSError: |
| await asyncio.sleep(0.2) |
| continue |
|
|
| |
| if file_size < last_pos: |
| f.seek(0) |
| last_pos = 0 |
|
|
| f.seek(last_pos) |
| new_lines = f.readlines() |
| if not new_lines: |
| await asyncio.sleep(0.1) |
| continue |
|
|
| last_pos = f.tell() |
| for line in new_lines: |
| payload = line.strip() |
| if not payload: |
| continue |
| yield f"data: {payload}\n\n" |
|
|
| @app.get("/stream") |
| async def stream(request: Request): |
| return StreamingResponse(event_generator(request), media_type="text/event-stream") |
|
|
| @app.get("/") |
| async def get_index(): |
| ui_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "ui", "index.html") |
| if os.path.exists(ui_path): |
| with open(ui_path, "r", encoding="utf-8") as f: |
| return HTMLResponse(content=f.read()) |
| return {"detail": "Frontend not found"} |
|
|
| if __name__ == "__main__": |
| uvicorn.run("src.api.server:app", host="0.0.0.0", port=8000, log_level="warning") |
|
|