feat: implement AI custom tag proposals

- AI now suggests dominant notes not in the system list (Part 3: Custom Suggestions)
- Updated TagSelector to show 'Neu anlegen?' buttons for AI-proposed custom tags
- Added suggested_custom_tags to bottles table and metadata schema
- Updated TastingNoteForm to handle both system and custom AI suggestions
This commit is contained in:
2025-12-19 13:20:13 +01:00
parent b2a1d292da
commit 74916aec73
12 changed files with 216 additions and 29 deletions

69
.aiideas Normal file
View File

@@ -0,0 +1,69 @@
1. Feature: Tasting Notes Auto-Fill (Die "Tag-Matching" Strategie)
Du hast völlig recht: Wenn Gemini einfach wild Text generiert (z.B. "Grüner Granny Smith Apfel"), und deine Datenbank nur "Apfel" kennt, hast du Chaos.
Die Lösung: "Constrained Generation" (Gezwungene Auswahl)
Du fütterst Gemini nicht nur mit dem Bild, sondern auch mit deiner Master-Liste an Tags im Prompt.
Der Workflow:
Input: Bild vom Label + Deine Liste der System Tags (als JSON-String).
Frontend:
Die App empfängt die IDs.
In der UI werden diese Tags aktiviert/vorausgewählt angezeigt (z.B. farbig hinterlegt).
Der User sieht: "Vorschlag: Rauch, Vanille".
Wichtig: Der User kann sie abwählen (wenn er es nicht schmeckt) oder andere aus der Liste hinzufügen.
Das ist der "Sweet Spot". Wir kombinieren die harte Fakten-Extraktion (Metadata) mit der "halluzinierten" aber kontrollierten Sensorik (Tags).
Hier ist dein "Master Prompt", der beides erledigt.
Das Konzept der "Constrained Generation"
Wichtig: Damit Gemini nicht irgendwelche Wörter erfindet, müssen wir ihm deine Tag-Liste im Prompt mitgeben. Ich habe im Prompt einen Platzhalter {AVAILABLE_TAGS_JSON} eingefügt. Diesen musst du in deinem Code (Next.js API Route oder Edge Function) mit deiner echten Tag-Liste ersetzen, bevor du den String an Gemini schickst.
Der Prompt (Copy & Paste)
You are a master sommelier and strict database clerk.
Your task is to analyze the whisky bottle image provided.
PART 1: METADATA EXTRACTION
Extract precise metadata from the visible label text.
- If the image is NOT a whisky bottle or if you are very unsure, set "is_whisky" to false and provide a low "confidence" score.
- If a value is not visible, use null.
- Infer the 'Category' (e.g., Islay Single Malt, Bourbon, Rye) based on the Distillery if possible.
- Search specifically for a "Whiskybase ID" or "WB ID" on the label (often handwritten or small print).
- Search for "Bottle Codes" (Laser codes often on the glass).
PART 2: SENSORY ANALYSIS (AUTO-FILL)
Based on the identified bottle (using your internal knowledge about this specific release/distillery), select the most appropriate flavor tags.
CONSTRAINT: You must ONLY select tags from the following provided list. Do NOT invent new tags.
If you recognize the whisky, try to select 3-6 tags that best describe its character.
AVAILABLE TAGS LIST:
{AVAILABLE_TAGS_JSON}
PART 3: OUTPUT
Output strictly raw JSON matching the following schema (no markdown, no code blocks):
{
"name": string | null,
"distillery": string | null,
"category": string | null,
"abv": number | null,
"age": number | null,
"vintage": string | null,
"bottleCode": string | null,
"whiskybaseId": string | null,
"distilled_at": string | null,
"bottled_at": string | null,
"batch_info": string | null,
"is_whisky": boolean,
"confidence": number,
"suggested_tags": string[]
}