Eine Märchen-Schreib-App für Grundschulkinder (Klasse 1-4), die personalisierte Geschichten mit Wörtern aus dem Grundwortschatz generiert.
- Personalisierte Geschichten: Der Nutzer gibt Thema, Personen/Tiere, Ort und Stimmung ein
- Zufalls-Generator: Automatische Vorschläge für alle Parameter
- Grundwortschatz-Integration: Geschichten enthalten Wörter aus dem Grundwortschatz der Klassen 1-4
- Buchlayout: Ansprechende Darstellung im Buchformat mit vergilbtem Papier-Look
- Seitenblätter-Animation: Geschichten erscheinen mit einer 3D-Blätter-Animation
- Flexible AI-Provider: Unterstützt alle OpenAI-kompatiblen APIs (OpenAI, Mistral, Together AI, etc.) plus Ollama (Cloud & Local)
- Missbrauchsschutz: Rate Limiting, Cost Control und Request-Validierung ohne Login
- Single-Container: Frontend und Backend in einem Container für einfaches Deployment
- Docker und Docker Compose
- AI Provider: OpenAI-compatible API Key (OpenAI, Mistral, Together AI, etc.) ODER Ollama (Cloud/Local)
- Repository klonen und in das Verzeichnis wechseln:
cd mAIrchen- Umgebungsvariablen konfigurieren:
cp .env.example .env.env-Datei bearbeiten und AI Provider konfigurieren:
Option A: OpenAI-compatible API (Standard - Mistral AI als Default)
AI_PROVIDER=openai
OPENAI_API_KEY=your-api-key
OPENAI_BASE_URL=https://api.mistral.ai/v1 # Default: Mistral AI
OPENAI_MODEL=mistral-small-latest # Default: mistral-small-latestUnterstützte OpenAI-kompatible Provider:
- Mistral AI (mistral-small-latest, mistral-large-latest) - Default
- OpenAI (gpt-4o-mini, gpt-4o, etc.)
- Together AI
- Anyscale Endpoints
- OpenRouter
- Azure OpenAI
- Jeder andere Provider mit OpenAI-kompatibler API
Option B: Ollama Cloud
AI_PROVIDER=ollama-cloud
OLLAMA_API_KEY=your-ollama-api-key
OLLAMA_MODEL=llama3.2:3bOption C: Ollama Lokal (kostenlos) ⭐ Empfohlen für Entwicklung
AI_PROVIDER=ollama-local
OLLAMA_BASE_URL=http://host.docker.internal:11434/v1
OLLAMA_MODEL=gemma3:latest # Beste Balance: Schnell & gute QualitätEmpfohlene Ollama-Modelle für Kindergeschichten:
gemma3:latest- 🏆 Beste Wahl (7.5s, sehr gute Qualität)gemma3n:latest- Etwas langsamer, exzellente Qualität (14.9s)llama3.2:3b- Klein und schnell, gute Basisqualitätgemma3:27b- Beste Qualität, aber langsam (38s)
- Container bauen & starten:
docker-compose up --build -dDie App ist nun verfügbar unter:
- Frontend: http://localhost
- API Info: http://localhost/api (zeigt aktiven Provider & Modell)
- API Stats: http://localhost/api/stats (Monitoring)
- Health Check: http://localhost/health
Alle API-Endpoints sind über Port 80 (HTTP) erreichbar:
Zeigt aktiven AI-Provider und Modell:
curl http://localhost/api{
"message": "mAIrchen API - Märchen für Kinder",
"ai_provider": "openai",
"model": "mistral-small-latest"
}Monitoring und Nutzungsstatistiken:
curl http://localhost/api/stats{
"global_requests_today": 42,
"global_limit": 1000,
"estimated_cost_today": 0.0,
"daily_budget": 5.0,
"budget_remaining": 5.0,
"rate_limit_per_ip": 10,
"active_ips": 8
}Generiert eine personalisierte Geschichte:
curl -X POST http://localhost/api/generate-story \
-H "Content-Type: application/json" \
-d '{
"thema": "Freundschaft",
"personen_tiere": "Ein kleiner Igel",
"ort": "im Wald",
"stimmung": "herzlich",
"laenge": 3,
"klassenstufe": "34"
}'Zufällige Vorschläge für alle Parameter:
curl http://localhost/api/randomDie API ist über Port 80 erreichbar, aber durch mehrere Schutzebenen gesichert:
- Rate Limiting: 10 Anfragen/h pro IP, 1000/Tag global (IP-basiert)
- Request-Validierung: Max 15 Min Story-Länge, 200 Zeichen pro Feld
- Cost Control: Max 5€/Tag Budget mit automatischem Stop
- CORS-Schutz: Nur erlaubte Origins (konfigurierbar)
- Nginx Reverse Proxy: Backend nur intern erreichbar (127.0.0.1:8000)
- Keine User-Accounts erforderlich - Privacy-Friendly!
- Backend läuft nur auf
127.0.0.1:8000(nicht von außen erreichbar) - Nginx auf Port 80 leitet Anfragen an Backend weiter
- Rate Limiting prüft jede Anfrage anhand der IP-Adresse
- CORS verhindert Zugriff von fremden Websites
Details: SECURITY.md
Frontend und Backend laufen in einem Docker-Container:
- Nginx serviert das Frontend (Port 80)
- Go Backend (Gin Framework) läuft auf Port 8000 (intern)
- Nginx fungiert als Reverse Proxy für
/api/*Requests
- Go-basierte REST API mit Gin Framework
- OpenAI-kompatibler Client (go-openai)
- Modular aufgebaute Package-Struktur:
pkg/config- Provider-Konfigurationpkg/data- Eingebettete Grundwortschatz-Datenpkg/prompt- Prompt-Generierungpkg/story- Story-Generierungpkg/analysis- Grundwortschatz-Analyse
- Flexible AI-Provider-Konfiguration über Umgebungsvariablen
- Rate Limiting & Cost Tracking
- Endpunkte:
GET /- API Info (Provider & Modell)GET /api/random- Zufällige VorschlägePOST /api/generate-story- Geschichte generierenGET /api/stats- Monitoring & StatistikenGET /health- Health Check
- Vanilla HTML/CSS/JavaScript
- Responsive Design
- 3D-Seitenblätter-Animation
- Buchlayout mit vergilbtem Papier-Effekt
- Automatische API-URL-Erkennung (funktioniert im Netzwerk)
mAIrchen/
├── .env.example # Umgebungsvariablen Template
├── .gitignore # Git Ignore Datei
├── README.md # Diese Datei
├── docker-compose.yml # Container Orchestrierung
├── backend/
│ ├── main.go # Go Backend (Gin)
│ ├── go.mod, go.sum # Go Dependencies
│ └── pkg/
│ ├── config/ # Provider-Konfiguration
│ ├── data/ # Grundwortschatz (embedded gws.md)
│ ├── prompt/ # Prompt-Generierung
│ ├── story/ # Story-Generierung
│ └── analysis/ # Grundwortschatz-Analyse
├── frontend/
│ ├── index.html # Haupt-HTML
│ ├── styles.css # Styling & Animationen
│ ├── app.js # JavaScript Logik
│ └── nginx.conf # Frontend Nginx Config
├── tools/
│ └── model_comparison.go # Benchmark-Tool für Model-Vergleiche
└── docker/
├── Dockerfile # Multi-Stage Build (Go + Nginx)
├── nginx-combined.conf # Nginx Konfiguration
└── start-go.sh # Container Start-Script
- App im Browser öffnen (http://localhost)
- Eingabefelder ausfüllen:
- Thema (z.B. "Freundschaft")
- Personen/Tiere (z.B. "Ein kleiner Hase")
cd backend
# Dependencies installieren
go mod download
# Umgebungsvariablen setzen
export AI_PROVIDER=ollama-cloud
export OLLAMA_API_KEY=your-key
export OLLAMA_MODEL=ministral-3:8b-cloud
# Backend starten
go run main.gocd backend
# Alle Tests
go test ./...
# Mit Coverage
go test ./... -cover
# Verbose Output
go test ./... -vcd backend
golangci-lint runDas Frontend benötigt das Backend auf Port 8000:
cd frontend
python -m http.server 8080Dann im Browser: http://localhost:8080
docker-compose up --build -dVergleicht verschiedene AI-Modelle für Kindergeschichten:
cd tools
go run model_comparison.go
```n im Browser: http://localhost:8080
### Container neu bauen nach Änderungen
```bash
docker-compose --env-file .env -f docker/docker-compose.yml build
docker-compose --env-file .env -f docker/docker-compose.yml up -dGET /api/randomPOST /api/generate-story
Content-Type: application/json
{
"thema": "Abenteuer",
"personen_tiere": "Ein mutiger Fuchs",
"ort": "im Wald",
"stimmung": "spannend"
}Umgebungsvariablen in .env:
AI_PROVIDER:openai,ollama-cloudoderollama-local(Standard: openai)
OPENAI_API_KEY: Ihr API SchlüsselOPENAI_BASE_URL: API Basis-URL (Standard: https://api.openai.com/v1)OPENAI_MODEL: Modell (Standard: gpt-4o-mini)
Beispiele für verschiedene Provider:
# Mistral AI (Default)
OPENAI_BASE_URL=https://api.mistral.ai/v1
OPENAI_MODEL=mistral-small-latest
# OpenAI
OPENAI_BASE_URL=https://api.openai.com/v1
OPENAI_MODEL=gpt-4o-mini
# Together AI
OPENAI_BASE_URL=https://api.together.xyz/v1
OPENAI_MODEL=meta-llama/Llama-3.2-3B-Instruct-Turbo
# OpenRouter
OPENAI_BASE_URL=https://openrouter.ai/api/v1
OPENAI_MODEL=meta-llama/llama-3.2-3b-instructOLLAMA_API_KEY: Ihr Ollama Cloud API SchlüsselOLLAMA_MODEL: Modell (Standard: llama3.2:3b)
OLLAMA_BASE_URL: URL zu lokaler Ollama-Instanz (Standard: http://host.docker.internal:11434/v1)OLLAMA_MODEL: Modell (Empfohlen: gemma3:latest)
ALLOWED_ORIGINS: Erlaubte CORS Origins (Standard: http://localhost,http://localhost:80)RATE_LIMIT_PER_IP: Anfragen pro Stunde pro IP (Standard: 10)GLOBAL_DAILY_LIMIT: Max Anfragen pro Tag (Standard: 1000)MAX_STORY_LENGTH: Max Story-Länge in Minuten (Standard: 15)MAX_DAILY_COST: Max Kosten pro Tag in Euro (Standard: 5.0)
Wichtig: Die .env Datei ist in .gitignore und wird nicht ins Repository committed!
Die API ist durch mehrere Sicherheitsebenen geschützt:
- Backend nur auf localhost: Das FastAPI-Backend lauscht nur auf
127.0.0.1:8000und ist von außen nicht direkt erreichbar - Nginx als einziger Zugangspunkt: Nur Nginx kann auf das Backend zugreifen und fungiert als Reverse Proxy
- CORS-Einschränkung: Nur erlaubte Origins (konfiguriert via
ALLOWED_ORIGINS) können API-Requests durchführen
In der Produktion sollten Sie ALLOWED_ORIGINS auf Ihre echte Domain(s) setzen:
# In .env
ALLOWED_ORIGINS=https://mairchen.de,https://www.mairchen.deDies verhindert, dass andere Websites Ihre API nutzen können, auch wenn sie die URL kennen. Das Frontend kann weiterhin von Client-Geräten auf die API zugreifen, da die Requests über Ihren Server laufen.
Die App ist von anderen Geräten im Netzwerk erreichbar:
- Finde die IP-Adresse deines Computers:
ifconfig(Mac/Linux) oderipconfig(Windows) - Öffne auf einem anderen Gerät:
http://<deine-ip>
Das Frontend nutzt automatisch die richtige URL für API-Requests.
# Auf dem Server
git clone [email protected]:sebastiansucker/mAIrchen.git
cd mAIrchen
cp .env.example .env
# .env bearbeiten und API-Key eintragen
docker-compose up --build -dDas Projekt nutzt GitHub Actions für automatisierte Tests und Builds:
- golangci-lint: Läuft bei jedem Pull Request und Push auf
main - Unit Tests: Alle Packages haben vollständige Test-Coverage
- Docker Build: Automatischer Build und Push zu GitHub Container Registry
# Backend Tests
cd backend
go test ./pkg/... -v
# Mit Coverage Report
go test ./pkg/... -cover -coverprofile=coverage.out
go tool cover -html=coverage.out
```ker run -d -p 80:80 \
-e MISTRAL_API_KEY=your-key \
-e MISTRAL_BASE_URL=https://api.mistral.ai/v1 \
-e MISTRAL_MODEL=mistral-small-latest \
--name mairchen-app \
ghcr.io/sebastiansucker/mairchen:latestMit Docker Compose und GitHub Registry:
services:
app:
image: ghcr.io/sebastiansucker/mairchen:latest
container_name: mairchen-app
ports:
- "80:80"
environment:
- MISTRAL_API_KEY=${MISTRAL_API_KEY}
- MISTRAL_BASE_URL=${MISTRAL_BASE_URL:-https://api.mistral.ai/v1}
- MISTRAL_MODEL=${MISTRAL_MODEL:-mistral-small-latest}
restart: unless-stopped# Auf dem Server
git clone [email protected]:sebastiansucker/mAIrchen.git
cd mAIrchen
cp .env.example .env
# .env bearbeiten und API-Key eintragen
docker-compose --env-file .env -f docker/docker-compose.yml up -d