chore: initial import
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
# Tandoor AI Web Import 1.1
|
||||
|
||||
Lokale Weboberfläche für den kontrollierten Import von Rezeptseiten:
|
||||
|
||||
```text
|
||||
URL
|
||||
→ sichere Webseitenextraktion
|
||||
→ OpenAI Structured Output
|
||||
→ Vorschau und bearbeitbares JSON
|
||||
→ intelligente Tandoor-Zuordnung
|
||||
→ bewusster API-Import
|
||||
→ Nachprüfung oder Rollback
|
||||
```
|
||||
|
||||
## Funktionen
|
||||
|
||||
- vollständige URLs sowie Eingaben ohne `https://`
|
||||
- `.html`, `.php`, Query-Parameter und normale Unterpfade
|
||||
- bevorzugte Auswertung von JSON-LD/Schema.org-Rezeptdaten
|
||||
- Vereinheitlichung im Stil der bereits überarbeiteten Tandoor-Rezepte
|
||||
- Komponenten als eigene Schritte, ohne unnötige Zerstückelung
|
||||
- bearbeitbares JSON und Live-Vorschau
|
||||
- jedes Food erhält immer ein Zuordnungs-Dropdown
|
||||
- Tandoor-Foods werden einmal geladen und lokal bewertet
|
||||
- exakte Treffer, Singular/Plural, Teilwörter und ähnliche Schreibweisen
|
||||
- `Kartoffeln` findet beispielsweise `Kartoffel`
|
||||
- Treffer werden nach Qualität sortiert und vorausgewählt
|
||||
- alternative Suche über ein Eingabefeld je Food und Unit
|
||||
- bewusstes Anlegen eines neuen Foods oder einer neuen Unit
|
||||
- Dublettenprüfung vor dem Rezeptimport
|
||||
- Verifikation nach dem Import
|
||||
- Rollback des Rezepts und der in diesem Lauf neu angelegten Stammdaten
|
||||
- optionaler HTTP-Basic-Schutz
|
||||
- Schutz vor SSRF über localhost und private Quelladressen
|
||||
|
||||
OpenAI erhält ausschließlich extrahierte Rezeptdaten und die Quell-URL. Der
|
||||
Tandoor-Token bleibt vollständig im lokalen Backend.
|
||||
|
||||
## Installation mit Docker
|
||||
|
||||
```bash
|
||||
unzip tandoor-ai-web-import-v1.1.zip
|
||||
cd tandoor-ai-web-import-v1.1
|
||||
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
Mindestens eintragen:
|
||||
|
||||
```dotenv
|
||||
OPENAI_API_KEY=sk-...
|
||||
OPENAI_MODEL=gpt-5.5
|
||||
|
||||
TANDOOR_URL=https://kitchen.d-razz.de
|
||||
TANDOOR_TOKEN=DEIN_TANDOOR_TOKEN
|
||||
TANDOOR_AUTH_SCHEME=Bearer
|
||||
|
||||
APP_USERNAME=michael
|
||||
APP_PASSWORD=EIN_STARKES_PASSWORT
|
||||
```
|
||||
|
||||
Start:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Weboberfläche:
|
||||
|
||||
```text
|
||||
http://DEIN-SERVER:8091
|
||||
```
|
||||
|
||||
## Lokaler Start ohne Docker
|
||||
|
||||
Unter Debian oder Ubuntu gegebenenfalls zuerst:
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install python3-venv
|
||||
```
|
||||
|
||||
Dann:
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install -r requirements.txt
|
||||
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
|
||||
uvicorn app.main:app \
|
||||
--env-file .env \
|
||||
--host 127.0.0.1 \
|
||||
--port 8091
|
||||
```
|
||||
|
||||
Für den lokalen Betrieb wird `DATA_DIR=./data` relativ zum Projektordner
|
||||
aufgelöst. Ohne gesetzte Variable fällt die Anwendung ebenfalls automatisch
|
||||
auf `<Projekt>/data` zurück.
|
||||
|
||||
## Bedienung
|
||||
|
||||
1. Rezept-URL eintragen und **URL analysieren** drücken.
|
||||
2. Vorschau und Warnungen prüfen.
|
||||
3. Im Tab **Zuordnungen** jedes vorausgewählte Food kontrollieren.
|
||||
4. Im Dropdown bei Bedarf einen anderen vorhandenen Eintrag wählen.
|
||||
5. Alternativ einen anderen Suchbegriff eintragen und **Suchen** drücken.
|
||||
6. Existiert nichts Passendes, im Dropdown **Neu anlegen** auswählen.
|
||||
7. **Änderungen prüfen** drücken.
|
||||
8. Erst bei freiem Importstatus **In Tandoor importieren** drücken.
|
||||
|
||||
## Zuordnungslogik
|
||||
|
||||
Die Anwendung lädt die verfügbaren Foods und Units aus Tandoor und bewertet
|
||||
jeden Eintrag. Dabei werden berücksichtigt:
|
||||
|
||||
```text
|
||||
exakter Name
|
||||
Pluralname
|
||||
Singular-/Pluralvarianten
|
||||
Teilworttreffer
|
||||
allgemeine Zeichenähnlichkeit
|
||||
vorhandene Properties als kleiner Tie-Breaker
|
||||
```
|
||||
|
||||
Eine ähnliche Zuordnung wird nicht unsichtbar entschieden. Sie erscheint immer
|
||||
als sichtbare Vorauswahl im Dropdown und zusätzlich als Warnung.
|
||||
|
||||
## Neue Foods und Units
|
||||
|
||||
Die Analyse und Validierung schreiben nichts nach Tandoor. Erst beim finalen
|
||||
Import werden ausdrücklich mit **Neu anlegen** markierte Objekte über folgende
|
||||
API-Endpunkte erstellt:
|
||||
|
||||
```text
|
||||
POST /api/food/
|
||||
POST /api/unit/
|
||||
```
|
||||
|
||||
Danach werden die zurückgegebenen IDs in den Rezept-Payload eingesetzt. Schlägt
|
||||
der Rezeptimport oder die Nachprüfung fehl, versucht die Anwendung das neue
|
||||
Rezept und die in diesem Lauf neu erstellten Stammdaten wieder zu entfernen.
|
||||
|
||||
## Verzeichnis `data/runs`
|
||||
|
||||
Jeder Durchlauf wird nachvollziehbar gespeichert:
|
||||
|
||||
```text
|
||||
data/runs/<RUN-ID>/
|
||||
├── 01-source.json
|
||||
├── 02-openai-metadata.json
|
||||
├── 03-ai-recipe.json
|
||||
├── 04-resolution.json
|
||||
├── 05-edited-recipe.json
|
||||
├── 06-edited-resolution.json
|
||||
├── 07-import-validation.json
|
||||
└── 08-import-result.json
|
||||
```
|
||||
|
||||
Die Dateien enthalten keine API-Token.
|
||||
|
||||
## Sicherheitsoptionen
|
||||
|
||||
Private und lokale Rezeptquellen sind standardmäßig blockiert:
|
||||
|
||||
```dotenv
|
||||
ALLOW_PRIVATE_SOURCE_URLS=false
|
||||
```
|
||||
|
||||
TLS-Prüfungen sollten aktiviert bleiben:
|
||||
|
||||
```dotenv
|
||||
SOURCE_VERIFY_TLS=true
|
||||
TANDOOR_VERIFY_TLS=true
|
||||
```
|
||||
|
||||
Ohne `APP_PASSWORD` ist die Oberfläche ungeschützt. Für einen über das lokale
|
||||
Gerät hinaus erreichbaren Dienst sollte ein Passwort oder ein Reverse Proxy
|
||||
mit Authentifizierung verwendet werden.
|
||||
|
||||
## Test
|
||||
|
||||
```bash
|
||||
python tests/selftest.py
|
||||
python tests/integration_mock.py
|
||||
```
|
||||
|
||||
## Grenzen
|
||||
|
||||
- Stark JavaScript-basierte Seiten ohne serverseitiges HTML können zu wenig
|
||||
Inhalt liefern.
|
||||
- Paywalls, Login-Seiten und Bot-Schutz werden nicht umgangen.
|
||||
- Neu erzeugte Foods enthalten zunächst die für den Rezeptimport nötigen
|
||||
Stammdaten wie Name und optionalen Pluralnamen, aber keine erfundenen
|
||||
Nährwerte oder Properties.
|
||||
- Die KI erzeugt nur das Zwischenformat. Ausschließlich das lokale Backend
|
||||
besitzt Tandoor-Schreibrechte.
|
||||
Reference in New Issue
Block a user