Spaces:
Running
Running
File size: 3,888 Bytes
ee29c8c d7b7cac ee29c8c d7b7cac ee29c8c d7b7cac ee29c8c d7b7cac | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | ---
title: NoExit
emoji: πͺ
colorFrom: gray
colorTo: red
sdk: static
pinned: false
license: mit
---
# NoExit
A real-time, text-driven 2D game built in Unity where the player is locked in a room with two AI-generated characters who remember everything you tell them.
Inspired by Sartre's *Huis Clos* β there is no exit.
---
## Gameplay
Type freely to converse with two characters whose names, backstories, and personalities are generated at runtime. Every piece of personal information the player reveals is silently extracted and stored β and the characters will bring it up again.
- Type text to talk; press **Enter** to submit
- Press **Enter** again to dismiss a dialogue box
- Arrow keys move the player character
- Point and click movement
---
## Technical Architecture
### Engine & Rendering
- **Unity 2D** (Universal Render Pipeline)
- **TextMeshPro** for all UI text
- **Light2D** for atmosphere and reactive flicker effects
- WebGL build served via Hugging Face Spaces
---
### AI Pipeline
All AI calls route through Hugging Face Spaces β no API keys are exposed to the client.
#### Dialogue Model
**Endpoint:** `jejunepixels-noexit-proxy.hf.space/chat`
A proxy Space that forwards chat completion requests. Includes automatic retry logic (up to 2 retries, 10s delay) to handle cold starts.
#### Personal Information Extractor
Scans every line of dialogue β from both the player and the characters β for personally identifying information using a small LLM. Two switchable backends:
| Backend | Endpoint | Model |
|---|---|---|
| Custom FastAPI | `jejunepixels-qwen3-4B-info-extractor-fastapi.hf.space/extract` | Qwen3 4B |
| HF Gradio Space | `jejunepixels-qwen3-0-6b-info-extractor-api.hf.space/extract` | Qwen3 0.6B |
Returns extracted information as a string, or `"none"` if nothing personal was found.
---
### Character Generation
At game start, two characters are generated procedurally via sequential LLM calls: first a name, then a full backstory and personality description using that name. The resulting description becomes each character's permanent system prompt for all future dialogue.
---
### Addressing System
Once a character has accumulated personal information about the player, an LLM routing call (capped at 10 tokens) decides which character should respond to the next player message β Character 1, Character 2, or both. Falls back to both responding after 3 failed attempts.
---
### Reactive Events
A timer-based event system fires unprompted questions at the player during pauses in conversation. If the player has revealed personal information, the question targets a specific piece of what was shared. Otherwise it asks a generic get-to-know-you question. Each fired event schedules the next one randomly.
---
### Dialogue Display
- Words reveal one by one with a typewriter effect
- Up to 3 dialogue boxes can be active simultaneously
- AABB overlap detection repositions boxes to prevent collisions
- Player input is locked while any dialogue is displaying
- When personal information is detected, the scene lighting flickers
---
### Data Logging
Every AI interaction is logged locally in JSONL format using `system / user / assistant` triplet structure, across four separate files for dialogue, info extraction, addressing decisions, and character generation. Intended for fine-tuning and analysis.
---
## Configurable Parameters
| Parameter | Description |
|---|---|
| Dialogue model | Model ID used for character dialogue and addressing |
| Info model | Model ID used for information extraction |
| Temperature | Separate values for dialogue and character generation |
| Max dialogue tokens | Token cap per character response (default: 150) |
| Max addressing tokens | Token cap for routing decisions (default: 10) |
| Info extractor backend | Toggle between Qwen3 4B (FastAPI) and 0.6B (Gradio) |
|