midnight_mystery / docs /ARCHITECTURE.md
lcpizani's picture
Add full app: pages, assets, backend, config
811d960
|
Raw
History Blame Contribute Delete
7.84 kB

Architecture & Judging Coverage β€” Midnight Mystery with Detective Shawn

This document does two jobs:

  1. Explains how the system is built (for technical judges and future contributors).
  2. Maps the build to the Build Small judging surface so the submission collects as many "ways to win" as possible.

1. System overview

                          main.py (FastAPI)
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚                       β”‚                            β”‚
  Gradio: onboarding      Gradio: game               Gradio: case-closed
   (custom noir form)   (HUD + iframe map)            (reveal + debrief)
        β”‚                       β”‚                            β”‚
        β–Ό                       β–Ό                            β–Ό
  case_generator        Phaser 3 (game.html)         debrief service
   (5-pass pipeline)     β‡… postMessage / fetch              β”‚
        β”‚                       β”‚                            β”‚
        β–Ό                       β–Ό                            β–Ό
        └──────── backend/routers (case Β· interrogation Β· forensic) β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                    inference_client (HF Serverless / Ollama)
                                β”‚
              Qwen3.5-9B (text)        FLUX.2-klein-4B (portraits)
  • Three Gradio apps, one FastAPI host. Each page is its own gr.Blocks mounted via gr.mount_gradio_app, so onboarding, the game, and the reveal are independent and each fully custom-styled.
  • Phaser ⇄ backend bridge. The map is a self-contained Phaser scene in an iframe. It talks to FastAPI with fetch and postMessage β€” movement, clue discovery, and interrogation all flow over HTTP.
  • State. A Pydantic CaseFile holds the entire game; an in-memory store keyed by case_id carries it across requests. A complete hardcoded SEED_CASE is the guaranteed fallback.

2. The generation pipeline (the centerpiece)

A single small text model is driven through five narrow passes. Splitting the work keeps a 9B model reliable: each prompt is small, each output is validated, each failure is recoverable.

Pass Input Output Guarantee
0 Β· Roster victim, scene, count, difficulty cast (name, occupation, archetype, role) exactly one culprit; fixed cast for later passes
1 Β· Story Bible roster + setting the hidden ground truth (how/why/when, motive) the truth is written once and never sent to suspects
2 Β· Souls story + one cast member per-suspect "soul": voice, alibi, reveal rules, crack progression runs in parallel (asyncio); each has a validator + fallback
3 Β· Evidence story + soul summaries + map rooms clues anchored to real locations + soul write-backs β‰₯2 solvable paths; clues land on real clue_anchors
4 Β· Briefing public fields only police dossier lines structurally cannot leak the culprit

Why this wins points: it's a concrete, defensible answer to "can a small model do something hard?" β€” yes, if you decompose the task, validate each step, and constrain it to a real world (the map manifest). It's not prompt-and-pray.

Live systems layered on top

  • Emotional state machine (state_mutator, interrogation_pipeline): trust / anxiety / defensiveness per suspect; crack thresholds scale with lying_skill (1–10). State is rendered into natural-language instructions so the model enacts pressure instead of describing it.
  • Knowledge gate (knowledge_gate): suspects can only reveal authorized facts; everything else is forbidden context.
  • Prompt-injection defense: known injection patterns are caught and deflected in character by archetype.
  • Reactive world (patrol, alertness): suspects patrol their zones; a stealth/alertness layer escalates suspects and can warn the culprit.
  • Forensics (forensic_lab): clue analysis that can detect contradictions against interrogation transcripts.
  • Debrief (debrief): the model grades the playthrough and narrates the resolution.

3. Small-model compliance (the hard requirement)

Component Model Params < 32B?
Case generation Qwen/Qwen3.5-9B ~9B βœ…
Interrogation / debrief / forensics Qwen/Qwen3.5-9B ~9B βœ…
Portraits black-forest-labs/FLUX.2-klein ~4B βœ…

Rule check: "each model's parameter count must stay below 32B." Largest single model here is ~9B. Comfortably compliant β€” and the narrative of the project is precisely "look how much one small model can carry."

⚠️ Consistency fix before submitting: model names are stated inconsistently across the repo. inference_client.py (the source of truth) defaults to Qwen3.5-9B + FLUX.2-klein-4B, but DEPLOYMENT.md lists Qwen3-14B + Mistral-Small-24B + FLUX, and the onboarding CTA still says "Qwen-2.5-7B". Pick the real set, then make README, DEPLOYMENT.md, the onboarding CTA, and the demo VO all agree. Judges will notice a mismatch.


4. Judging-surface coverage

The field guide describes ~29 ways to win across track placements, Community Choice, sponsor prizes, the Custom-UI category, and stackable bonus badges. This project is strongest where it leans into being AI-native and visually distinct.

Target Why this build qualifies Action to lock it in
Thousand Token Wood (track placement) Couldn't exist without AI; the model is the game Lead the README + video with this framing βœ…
Custom UI badge Zero default-Gradio surfaces β€” bespoke noir CSS, Phaser map, custom loader Show the UI prominently in the video; tag custom-ui
OpenBMB / small-model sponsor Whole pitch is "one 9B model runs a game" State param counts everywhere; confirm sponsor tag slug
Community Choice Shareable, novel hook ("name a victim, AI writes the murder") Strong social clip; post early for votes
"Most badges stacked" Genuinely spans creativity + UI + small-model + agentic Add every honestly applicable badge tag
Full-package App + demo video + social post all exist and align Ship all three; keep them consistent

Submission checklist (hard requirements)

  • Deployed as a Gradio app in the official build-small-hackathon HF org
  • Demo video showing the app working (see DEMO_VIDEO_SCRIPT.md)
  • Social post created and linked from the README (see SOCIAL_POST.md)
  • README YAML tags for the track + every badge being claimed
  • All models verified < 32B and named consistently everywhere
  • Submitted before June 15, 23:59 UTC

5. Pre-submission risk list

  1. Theme consistency. The game is now Detective Shawn (human noir). Sweep for leftover pet/animal copy in user-facing strings (onboarding hints reference "animals in the neighbourhood"; portrait assets are animal placeholders). Anything a judge sees must match the shipped theme.
  2. Model-name drift. See Β§3 warning β€” unify before recording the video.
  3. Inference reliability during judging. The seed-case fallback covers a hard outage, but verify the Space's HF_TOKEN/provider and that portraits degrade gracefully. The demo video is your insurance β€” record it on a known-good run.
  4. First-paint impression. Onboarding is the most-judged screen after the video. It's already strong; make sure fonts load on the Space (Google Fonts CDN reachable) so the noir look survives deployment.