- engine/llm.py: Ollama /api/chat client with OpenAI-style tool schema
- engine/reasoning.py: LLM path with 4-tier validation:
1. tool exists in registry
2. tool passes location-gating
3. args parse cleanly
4. otherwise fall back to rule-based engine
- env vars: EMERGENCE_LLM_{URL,MODEL,TIMEOUT,ENABLED}
- Default model: llama3.2:3b (best speed/quality tradeoff for tool use)
- 11 new mock tests in tests/test_llm.py (no network)
- smoke_test_llm.py: live smoke against real Ollama
- README: 'LLM Integration' section with model table + setup
Live-verified: 4/4 decisions via llama3.2:3b in 1-3s, character-consistent
('facilitate honest debate', 'work together', 'urgency and collaboration').
14 KiB
Emergence-Mini
Ein minimaler, lauffähiger Klon von Emergence-World. Kein LLM nötig, keine externen API-Keys, alles lokal in Python + SQLite.
Was es kann
- 4 Agenten (Anchor, Flora, Lovely, Spark) auf einem 240×240-Grid
- 14 Orte (Town Hall, Library, Plaza, Park, Cafe, 4 Häuser, ...)
- 15 Tools (Navigation, Kommunikation, Memory, Blog, Billboard, Town Hall, ...)
- Round-Robin-Turn-Manager mit Reactive Triggern
- Needs-Decay: Energy, Knowledge, Influence
- Constitution mit 5 Artikeln, amendment-fähig via 70%-Voting
- Live-View im Browser (Canvas + WebSocket)
- Persistenz via SQLite
- 50+ automatisierte End-to-End-Tests, grün
Was es bewusst NICHT kann (im Vergleich zum Original)
- Keine echten LLMs (regelbasierte Reasoning-Engine statt Claude/Gemini/GPT/Grok)
- Kein 3D-Frontend (2D-Canvas statt React Three Fiber)
- Kein PostgreSQL (SQLite ist ausreichend)
- Kein Multi-Model-Vergleich
- Kein Google Cloud TTS
- Kein 15-Tage-Real-Time-Sync (Ticks laufen alle 2 Sekunden)
- Kein Vector-Store für Memory-Search
- Keine AWI-Metrics (9 Indikatoren) — wäre nur mit 15-Tage-Daten sinnvoll
- Keine echten Persönlichkeits-LLM-Prompts (Traits sind deterministisch regelbasiert)
Quickstart
git clone https://github.com/Jeuners/emergence-mini-dilles.git
cd emergence-mini-dilles
pip install -r requirements.txt
./run.sh
# Browser auf http://127.0.0.1:8080
Optional mit LLM-Reasoning (empfohlen):
# Ollama lokal starten (falls nicht bereits laufend)
ollama serve &
# Modell ziehen (einmalig, ~2 GB)
ollama pull llama3.2:3b
# Emergence-Mini mit LLM starten
./run.sh
Optional mit Tests:
python3 -m pytest tests/ -v # 80+ Unit + Integration Tests
python3 smoke_test.py # End-to-End Smoke Test (regelbasiert)
python3 smoke_test_llm.py # Live-LLM-Test (braucht Ollama)
Endpoints
| Method | Path | Beschreibung |
|---|---|---|
GET |
/api/state |
Kompletter Snapshot (Agenten, Landmarks, Constitution, Tick) |
GET |
/api/agents |
Liste der aktiven Agenten |
GET |
/api/landmarks |
Liste aller Orte |
GET |
/api/proposals |
Aktive + vergangene Proposals |
GET |
/api/constitution |
Aktuelle Verfassung |
GET |
/api/events |
Letzte 100 Events |
GET |
/api/memories/{id} |
Memory eines Agenten |
GET |
/api/blogs |
Veröffentlichte Blog-Posts |
POST |
/api/turn/{id} |
Tool manuell auslösen (Body: {"tool": "...", "args": {...}}) |
WS |
/ws |
Live-Stream (snapshot + action + tick) |
GET |
/ |
Single-Page-Live-View |
Architektur
emergence-mini-dilles/
├── server.py FastAPI + WebSocket entry
├── engine/
│ ├── db.py SQLite persistence + schema migration
│ ├── world.py 240×240 grid + landmarks + hearing range
│ ├── agents.py Agent state, personality, position
│ ├── needs.py Energy/Knowledge/Influence decay
│ ├── tools.py Tool registry + handlers + location-gating
│ ├── reasoning.py Decision engine (LLM + rule-based fallback)
│ ├── llm.py Ollama client + OpenAI-style tool schema
│ ├── governance.py Constitution + Town Hall voting (70% threshold)
│ └── turn.py Round-robin + reactive triggers
├── data/
│ └── constitution.json Seed constitution (5 articles)
├── web/ Static SPA (kein Build-Tool nötig)
│ ├── index.html
│ ├── style.css
│ └── app.js Canvas-Renderer + WebSocket-Client
├── tests/
│ ├── conftest.py
│ ├── test_db.py
│ ├── test_world.py
│ ├── test_agents.py
│ ├── test_tools.py
│ ├── test_governance.py
│ ├── test_reasoning.py
│ ├── test_llm.py
│ └── test_api.py
├── smoke_test.py End-to-End Live-Test (regelbasiert, 50+ Checks)
├── smoke_test_llm.py Live-LLM-Test gegen echtes Ollama-Modell
├── requirements.txt
├── run.sh Startet uvicorn auf Port 8080
└── .gitignore
Daten-Modell
| Tabelle | Zweck |
|---|---|
world_state |
Key/Value für Tick, Bootstrap-Flags |
agents |
4 Agenten, alle Needs als REAL, Mood, Alive-Flag |
landmarks |
14 Orte, (x, y) auf 240×240-Grid |
memories |
Long-term Memory pro Agent |
relationships |
Affinity-Matrix zwischen Agenten |
events |
Append-only Event-Log (Proposals, Posts, Ticks) |
proposals |
Town-Hall-Vorschläge + Status + Applied-Flag |
votes |
Pro Agent eine Stimme pro Proposal |
bills |
Blog-Posts |
constitution |
Versionierte Verfassung (jede Änderung = neue Row) |
turn_log |
Append-only Tool-Call-Log |
Sicherheitsmodell
Der Server lauscht auf 127.0.0.1:8080 — nicht auf 0.0.0.0. Er ist explizit als
Local-Dev-Tool gedacht, nicht als öffentlicher Service. Für Produktion:
- Reverse-Proxy mit Auth davor (z. B. Caddy mit Basic-Auth)
uvicornhintergunicorn+systemd- DB regelmäßig sichern
LLM Integration
Emergence-Mini unterstützt lokale LLMs via Ollama als Reasoning-Engine. Ohne LLM läuft die regelbasierte Engine (deterministisch, schnell, gut für Tests). Mit LLM werden die Agenten emergent, character-stimmig und nicht-reproduzierbar — wie im Original.
Setup
# 1. Ollama installieren (falls nicht vorhanden)
# macOS: brew install ollama
# Linux: curl -fsSL https://ollama.com/install.sh | sh
# Windows: https://ollama.com/download
# 2. Ollama starten
ollama serve
# 3. Modell ziehen (einmalig, ~2 GB für 3B, ~5 GB für 7B)
ollama pull llama3.2:3b
# 4. Emergence-Mini starten (LLM wird automatisch erkannt)
./run.sh
Konfiguration via Umgebungsvariablen
| Variable | Default | Beschreibung |
|---|---|---|
EMERGENCE_LLM_ENABLED |
1 |
0 erzwingt regelbasierte Engine |
EMERGENCE_LLM_URL |
http://127.0.0.1:11434 |
Ollama-Server |
EMERGENCE_LLM_MODEL |
llama3.2:3b |
Modell-Name (siehe unten) |
EMERGENCE_LLM_TIMEOUT |
30 |
Request-Timeout in Sekunden |
Beispiel mit größerem Modell:
EMERGENCE_LLM_MODEL=qwen2.5-coder:7b ./run.sh
Empfohlene Modelle
| Modell | Größe | Stärke | Schwäche |
|---|---|---|---|
llama3.2:3b ⭐ |
2.0 GB | Schnell, gute Tool-Use-Fähigkeit, niedriger RAM-Bedarf | Kurze Antworten |
gemma3:latest |
3.3 GB | Bewährt, gute Reasoning-Qualität | Mittel-schnell |
qwen2.5-coder:7b |
4.7 GB | Exzellent für strukturierte Aufgaben | Höherer RAM-Bedarf |
qwen3.5:latest |
6.6 GB | Neueste Generation, multimodal | Langsamer |
gemma4:latest |
9.6 GB | Bestes Reasoning | Langsam, hoher RAM |
Für die meisten Setups ist llama3.2:3b der beste Kompromiss: ~1-3s Latenz pro Decision, 4-8 GB RAM, deterministische Tool-Calls.
Modelle ohne brauchbare Tool-Use-Fähigkeit (z.B. moondream,
nomic-embed-text) werden zwar nicht crashen, aber das System fällt auf
die regelbasierte Engine zurück.
Wie es funktioniert
Pro Agent-Turn:
- Engine sammelt Personality-Traits, aktuellen State (Energy, Knowledge, Influence, Credits), Position und sichtbare Tools (gefiltert nach Location-Gating).
- Baut einen System-Prompt mit dieser Kontext-Information.
- Sendet
/api/chatan Ollama mit Tool-Schema im OpenAI-Format. - Validiert die Antwort: Tool muss existieren, Location muss passen.
- Bei Validierungs-Fehler oder Verbindungs-Problemen: Fallback zur regelbasierten Engine, damit die Simulation nie hängt.
Die get_last_decision()-Funktion in engine.reasoning exponiert den
Modus (llm, rule, fallback:...) und die Latenz. Im Live-View ist
das via WebSocket sichtbar (im rationale-Feld).
Eigene System-Prompts
Die Persona-Beschreibung lebt in engine/reasoning.py:_build_system_prompt.
Du kannst sie für deinen Use-Case anpassen (z.B. spezifischere Regeln,
andere Tool-Beschreibungen, anderer Ton).
Tests
- Mock-Tests in
tests/test_llm.pyprüfen Schema-Generierung, Response-Parsing, Fallback-Pfade. 11 Tests, alle ohne Netzwerk. - Live-Smoke in
smoke_test_llm.pyruft das echte Modell 4× auf und meldet Mode + Latenz pro Decision.
Security
Emergence-Mini ist ein lokales Dev-Tool. Es ist nicht für den öffentlichen Einsatz vorbereitet. Folgende Punkte sind bewusst NICHT enthalten:
Was es nicht macht (by design)
- Keine Authentifizierung — alle Endpoints sind offen. Der Server bindet nur auf
127.0.0.1, das setzt einen lokalen Nutzer voraus. - Keine Rate-Limits —
POST /api/turn/{id}kann endlos gefeuert werden. Ein Angreifer mit Loop-Zugriff könnte die DB mit Rows fluten. - Keine Input-Validierung — Tool-Args werden ohne JSON-Schema geprüft. Falsche
Typen führen zu
KeyError/TypeErrorim Handler, nicht zu 400. - Keine CORS-Restriktionen — Browser-Apps von beliebigen Origins können die API konsumieren, wenn der Server öffentlich erreichbar wird.
- Keine SQL-Injection-Schutzmaßnahmen jenseits parametrisierter Queries — die
SQL-Statements sind alle
?-gebunden, aber Strings werden nicht escaped, falls sie direkt interpoliert würden (aktuell kein Fall). - Keine Secrets — keine API-Keys, keine Tokens, keine Passwörter im Code oder in der DB.
- Kein Logging sensibler Daten — der
turn_logenthält nur Tool-Name + Args. Kein Memory-Inhalt, keine persönlichen Daten.
Hardening-Checkliste vor Public Deploy
# 1. Auf 0.0.0.0 nur hinter Reverse-Proxy erlauben
# 2. Auth-Layer hinzufügen (z. B. via Caddy + Basic-Auth oder oauth2-proxy)
# 3. Schema-Validierung pro Tool-Endpoint
# 4. Rate-Limiting (z. B. slowapi)
# 5. CORS-Whitelist
# 6. HTTPS terminieren
# 7. DB-Backups in separaten Storage
# 8. Monitoring (z. B. Prometheus-Endpoint)
Verletzliche Annahmen
| Annahme | Risiko |
|---|---|
| Loopback-only Binding | Bei 0.0.0.0 sofort öffentlich erreichbar |
| Trust im Tool-Args | Handler setzen Tool-Args als SQL-Params; Schema-Mismatch crasht Handler |
| Single-User | Concurrency über SQLite-WAL, aber kein Row-Locking pro Agent |
Reporting
Security-Issues bitte per Mail an den Maintainer (siehe GitHub-Profil) — nicht als Public Issue.
Tests
Test-Suite ausführen
# Alle Unit + Integration Tests
python3 -m pytest tests/ -v
# Nur Smoke-Test (End-to-End inkl. Live-Server)
python3 smoke_test.py
# Mit Coverage
pip install coverage
python3 -m coverage run -m pytest tests/
python3 -m coverage report
Was getestet wird
| Test | Was |
|---|---|
test_db.py |
Schema-Erstellung, World-State-Get/Set, Event-Log |
test_world.py |
Landmark-Seeding, Distance-Funktion, Hearing-Range, Location-Detection |
test_agents.py |
Agent-Bootstrap, Personality-Loading, State-Updates, Position-Updates |
test_tools.py |
Alle 15 Tool-Handler, Location-Gating, Fehler-Pfade |
test_governance.py |
70%-Threshold, Auto-Reject, Constitution-Amendment-Apply |
test_reasoning.py |
Decision-Engine für alle Personality-Types, Edge-Cases |
test_llm.py |
Ollama-Client, Tool-Schema, Mock-Tests für LLM-Pfad, Fallbacks |
test_api.py |
Alle HTTP-Endpoints, WebSocket, POST /api/turn |
Smoke-Test-Details
smoke_test.py läuft 14 Sektionen mit 50+ Assertions ohne externen Server:
- Bootstrap (DB, 14 Landmarks, 4 Agenten, 15 Tools)
- Agent-State (Needs, Personality, Home-Position)
- Tools: Navigation (
go_to_place, Position-Update) - Tools: Communication (
say_to_agent, Speak-Events) - Tools: Memory (Persistenz in
memories-Tabelle) - Tools: Blog (Knowledge-Boost, Bill-Eintrag)
- Tools: Billboard (Location-Gating verifiziert)
- Town Hall: Proposal + 4× Vote → accepted, Constitution wächst von 5 auf 6 Artikel
- Energy-System: Recharge +50%, Credits -1
- Reasoning-Engine: Round läuft, Tool-Selection funktioniert
- Needs-Decay: Energy sinkt über mehrere Ticks
- Reactive Triggers:
speak_to_alltriggert Listener - Persistenz: Proposals, Memories, Bills, Turn-Log vorhanden
- Live-Server: Startet uvicorn auf Port 8090, testet alle REST-Endpoints + POST + WS
Bekannte Test-Lücken
- Keine Concurrency-Tests (mehrere parallele
force_turn-Calls) - Keine Last-Tests (1000+ Ticks in kurzer Zeit)
- Keine Fuzz-Tests für Tool-Args
- Keine Frontend-Tests (Canvas-Renderer, WebSocket-Client sind ungetestet)
CI-Integration
GitHub Actions Template (nicht enthalten, easy nachzurüsten):
# .github/workflows/test.yml
name: tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- run: pip install -r requirements.txt
- run: python3 -m pytest tests/ -v
- run: python3 smoke_test.py
Lizenz
Emergence-Mini ist inspiriert vom CC-BY-NC-4.0-Original von Emergence AI. Dieser Klon: MIT für nicht-kommerzielle Nutzung, ohne Gewähr.
Die LLM-Integration erwartet eine lokale Ollama-Instanz und nutzt Ollamas OpenAI-kompatible Tool-Calling-API. Ollama selbst ist MIT-lizenziert. Die Modelle (llama3.2, qwen, gemma) unterliegen ihren eigenen Lizenzen — bitte vor kommerzieller Nutzung prüfen.
Quell-Repo: https://github.com/EmergenceAI/Emergence-World (Doku, Profile, Landmarks, Constitution, Tool-Katalog)