Introcuced a Free LLM for easier food input

This commit is contained in:
2026-07-30 09:06:25 +02:00
parent 5196ff0194
commit c40a142da2
8 changed files with 272 additions and 7 deletions
+27 -4
View File
@@ -11,7 +11,7 @@ KalorienTracker/
└── docker-compose.yml
```
- **Backend** (`backend/`): FastAPI-API mit JWT-Login, Produktsuche (lokale DB → Fallback auf Open Food Facts, Ergebnis wird lokal gecacht), Logging von Mahlzeiten inkl. Tagesübersicht, Historie (Tage/Wochen/Monate) und selbst gesetzten Tageszielen. Mehrbenutzerfähig: jeder registrierte Nutzer sieht nur seine eigenen Tagebuch-Einträge, Ziele und privaten Rezepte, während alle Lebensmittel (Barcode-Produkte) in einer gemeinsamen Datenbank für alle Nutzer verfügbar sind. Jeder Endpunkt außer Registrierung/Login verlangt ein gültiges JWT.
- **Backend** (`backend/`): FastAPI-API mit JWT-Login, Produktsuche (lokale DB → Fallback auf Open Food Facts, Ergebnis wird lokal gecacht), Logging von Mahlzeiten inkl. Tagesübersicht, Historie (Tage/Wochen/Monate) und selbst gesetzten Tageszielen. Optional eine KI-Nährwertschätzung aus Freitext über ein OpenAI-kompatibles LLM-Gateway. Mehrbenutzerfähig: jeder registrierte Nutzer sieht nur seine eigenen Tagebuch-Einträge, Ziele und privaten Rezepte, während alle Lebensmittel (Barcode-Produkte) in einer gemeinsamen Datenbank für alle Nutzer verfügbar sind. Jeder Endpunkt außer Registrierung/Login verlangt ein gültiges JWT.
- **Frontend** (`frontend/`): React-SPA mit Kamera-Barcode-Scanner (`html5-qrcode`), Dashboard mit Fortschrittsbalken für Kalorien/Protein/Carbs/Fett, Formular für manuell angelegte Produkte, Historie-Seite mit Trend-Grafiken (Recharts), Kalenderwochen- und Monatsdurchschnitt, Settings-Seite für eigene Tagesziele, umschaltbarer Dark Mode (folgt standardmäßig der Systemeinstellung, per Klick auf das Sonne/Mond-Icon umschaltbar, Wahl bleibt gespeichert).
## Setup
@@ -74,15 +74,38 @@ Läuft auf `http://localhost:5173` und spricht per CORS direkt mit dem Backend a
1. Registrieren / einloggen.
2. Auf „Barcode scannen“ tippen, Kamera auf den Barcode halten. Falls die Live-Erkennung hakt (z. B. schlechtes Licht oder Fokus), per „Stattdessen Foto aufnehmen“ ein einzelnes scharfes Foto aufnehmen — das Bild wird einmalig ausgewertet und danach verworfen, nie gespeichert oder hochgeladen.
3. Produkt gefunden → Mahlzeit (Frühstück/Mittagessen/Abendessen/Snacks, per Uhrzeit vorausgewählt) + Menge in Gramm eingeben → „Hinzufügen“. Angezeigt werden Kalorien, Carbs, Protein, Fett sowie Zucker, Ballaststoffe, gesättigte Fettsäuren und Salz pro 100g.
4. Produkt nicht gefunden (404) → Name + Nährwerte pro 100g manuell eintragen (die vier Zusatz-Nährwerte sind optional) → wird angelegt und direkt geloggt.
4. Produkt nicht gefunden (404) → Name + Nährwerte pro 100g manuell eintragen (die vier Zusatz-Nährwerte sind optional) → wird angelegt und direkt geloggt. Alternativ oben im Formular kurz beschreiben, was es war (z. B. „Currywurst mit Pommes“) und auf „Schätzen“ tippen — dann füllt eine KI alle Nährwerte und die übliche Portionsgröße als **Vorschlag** aus, den man vor dem Speichern prüfen und korrigieren kann.
5. Alternativ „Mahlzeit hinzufügen“ tippen, um ohne Scan nach einem Produkt zu suchen (z. B. „Döner“ vom Essen gehen) oder ein neues anzulegen. Die Suche schlägt zuerst die zuletzt selbst verwendeten Produkte vor (inkl. der zuletzt genutzten Menge) — auch wenn sie ursprünglich per Barcode gescannt wurden.
6. Dashboard zeigt die Tagessumme aus Kalorien, Protein, Carbs und Fett als Fortschrittsbalken gegen die eigenen Ziele, plus eine Zeile mit den restlichen Nährwerten (Zucker/Ballaststoffe/ges. Fett/Salz, ohne eigenes Ziel), sowie die Einträge gruppiert nach Frühstück/Mittagessen/Abendessen/Snacks. Jeder Eintrag lässt sich über die Stift-/Papierkorb-Icons nachträglich in Menge/Mahlzeit bearbeiten oder löschen.
7. Unter „Ziele“ lassen sich die eigenen Tagesziele für Kalorien, Protein, Carbs und Fett festlegen (Default: 2000 kcal / 100 g Protein / 250 g Carbs / 70 g Fett).
8. Unter „Historie“ gibt es einen Kalorien-Trend und einen Makro-Trend (Carbs/Protein/Fett) als Grafik über die letzten 30 Tage, eine Wochenübersicht mit echten Kalenderwochen-Durchschnitten (Montag–Sonntag) sowie den Monatsdurchschnitt (jeweils nur über Tage mit Einträgen gemittelt) und eine Liste der letzten 30 Tage — ein Tag antippen zeigt die geloggten Einträge dieses Tages, ebenfalls nach Mahlzeit gruppiert.
9. Unter „Kochbuch“ lassen sich eigene Gerichte aus bereits bekannten Produkten zusammenstellen (Name, Zubereitung, Zutaten mit Menge, bei Bedarf direkt per Scan oder manuellem Formular neu angelegt) — die Nährwerte pro 100g werden automatisch aus den Zutaten berechnet. Ein Gericht taucht danach wie ein normales Produkt in der Suche auf (mit „Gericht“-Badge) und lässt sich genauso mengenbasiert loggen, bearbeiten oder löschen — praktisch für Rezepte, die man öfter kocht, oder als Inspiration. Rezepte sind privat und nur für den Ersteller sichtbar, lassen sich aber über „Teilen“ auf der Detailseite gezielt mit anderen registrierten Nutzern teilen (diese können das Rezept dann ansehen und loggen, aber nicht bearbeiten oder löschen).
## KI-Nährwertschätzung (optional)
Die Schätzfunktion spricht ein **OpenAI-kompatibles** Chat-Gateway an und wird rein über
`backend/.env` konfiguriert:
```
LLM_API_URL=https://ki-toolbox.scc.kit.edu/api/v1
LLM_API_KEY=dein-key
LLM_MODEL=kit.mistral-small-4-119b-a8b
```
Ohne gesetzten `LLM_API_KEY` ist das Feature einfach deaktiviert (der Endpunkt antwortet mit
`503`) — die restliche App funktioniert unverändert, Nährwerte lassen sich weiterhin manuell
eintragen. Weil die Konfiguration rein OpenAI-kompatibel ist, funktioniert genauso jedes andere
Gateway (OpenAI selbst, ein lokaler Ollama-Server mit OpenAI-API, …) durch bloßes Ändern von
`LLM_API_URL`/`LLM_MODEL`.
Als Default ist `kit.mistral-small-4-119b-a8b` gesetzt: In einem Vergleich der frei verfügbaren
`kit.*`-Modelle lieferte es als einziges durchgängig valides JSON **und** war mit ~4 s pro
Anfrage etwa drei- bis viermal schneller als die Alternativen (`kit.gpt-oss-120b` und
`kit.gemma4-31b-it` waren langsamer bzw. unzuverlässiger, `kit.qwen3.5-397b-A17b` lieferte
gar keinen verwertbaren Inhalt).
## Tech-Stack
- Backend: FastAPI, SQLModel, SQLite, JWT (python-jose), passlib/bcrypt, httpx
- Frontend: React, Vite, TailwindCSS, react-router-dom, axios, html5-qrcode
- Backend: FastAPI, SQLModel, SQLite, JWT (python-jose), passlib/bcrypt, httpx, openai (LLM-Client)
- Frontend: React, Vite, TailwindCSS, react-router-dom, axios, html5-qrcode, recharts
- Deployment: Docker, nginx (Reverse Proxy + Static Hosting)