""" ForensicAI 2nd Brain — Hugging Face Space Interactive morphic simulation UI + GPT Action API endpoints. """ from __future__ import annotations import base64, hashlib, os from pathlib import Path from typing import Optional from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import HTMLResponse, Response, JSONResponse from fastapi.staticfiles import StaticFiles from pydantic import BaseModel, Field import brain as brain_store from simulation import generate_forensic_image, generate_case_heatmap, CASE_TYPES SIMS_DIR = Path("/tmp/forensic_sims") SIMS_DIR.mkdir(parents=True, exist_ok=True) app = FastAPI(title="ForensicAI 2nd Brain", version="1.0.0") app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]) app.mount("/sims", StaticFiles(directory=str(SIMS_DIR)), name="sims") # ── Interactive UI ───────────────────────────────────────────────────────────── HTML = """ ForensicAI · 2nd Brain
⬡ FORENSICAI · 2ND BRAIN GENERATION 001
BRAIN STATE
SESSIONS0
ANALYSES0
EVIDENCE ITEMS0
AVG CONFIDENCE0.70
DOMINANT CASE
CASE ACTIVITY
SIM PARAMETERS
FEED RATE0.0370
KILL RATE0.0600
GRID120 × 120
CASE INTELLIGENCE LOG
Awaiting data…
  MORPHIC ENGINE ACTIVE f=0.0370 k=0.0600
""" # ── Models ──────────────────────────────────────────────────────────────────── class SimulateRequest(BaseModel): dominant_case: str = Field("default") evidence_confidence: float = Field(0.70, ge=0.0, le=1.0) case_complexity: float = Field(0.50, ge=0.0, le=1.0) out_size: int = Field(512, ge=128, le=1024) class BrainUpdateRequest(BaseModel): case_type: Optional[str] = None confidence: Optional[float] = None complexity: Optional[float] = None n_evidence: int = Field(0, ge=0) insight: Optional[str] = None # ── Endpoints ───────────────────────────────────────────────────────────────── @app.get("/", response_class=HTMLResponse) def index(): return HTML @app.get("/health") def health(): return {"status": "ok", "service": "forensicai-2nd-brain"} @app.get("/brain") def get_brain(): return JSONResponse(brain_store.load()) @app.post("/brain/update") def update_brain(body: BrainUpdateRequest): state = brain_store.update( case_type=body.case_type, confidence=body.confidence, complexity=body.complexity, n_evidence=body.n_evidence, insight=body.insight, ) return JSONResponse(state) @app.post("/simulate") def simulate(body: SimulateRequest): state = brain_store.load() png = generate_forensic_image( dominant_case=body.dominant_case if body.dominant_case != "default" else state["dominant_case"], evidence_confidence=body.evidence_confidence, session_count=state["session_count"], pattern_generation=state["pattern_generation"], case_complexity=body.case_complexity, out_size=body.out_size, ) return { "image_b64": base64.b64encode(png).decode(), "mime": "image/png", "pattern_generation": state["pattern_generation"], "feed_rate": state["feed_rate"], "kill_rate": state["kill_rate"], "dominant_case": state["dominant_case"], "display_hint": "Render image_b64 as: ![sim](data:image/png;base64,{image_b64})", } @app.get("/brain/visualize/b64") def brain_visualize_b64(): state = brain_store.load() png = generate_case_heatmap( case_history=[], confidence_history=state["confidence_history"], case_frequency=state["case_frequency"], out_size=512, ) return { "image_b64": base64.b64encode(png).decode(), "mime": "image/png", "display_hint": "Render as: ![brain](data:image/png;base64,{image_b64})", } @app.post("/brain/reset") def reset_brain(): return JSONResponse(brain_store.reset())