feat: Replace Nebius with Pixtral AI for bottle scanning
This commit is contained in:
125
.aiideas
125
.aiideas
@@ -1,46 +1,123 @@
|
||||
3. Timeline & "Flight Recorder" (Reihenfolge-Logik)
|
||||
Hier ist der Code, um Pixtral Large (das europäische Flaggschiff-Modell von Mistral) direkt in deine Next.js App zu integrieren.
|
||||
|
||||
Ziel: Die Geschichte des Abends rekonstruieren. Analyse des Konsumverhaltens.
|
||||
Feature: Die Timeline-Ansicht
|
||||
Damit kannst du einen direkten "A/B-Test" gegen Gemini 3 Flash fahren.
|
||||
1. Vorbereitung
|
||||
|
||||
Statt einer einfachen Liste, eine vertikale Zeitstrahl-Ansicht.
|
||||
Du brauchst das Mistral SDK und einen API Key von console.mistral.ai.
|
||||
Bash
|
||||
|
||||
14:00 Uhr: Start der Session "Whisky Herbst".
|
||||
npm install @mistralai/mistralai
|
||||
|
||||
14:15 Uhr: Glenfiddich 12 (Mild, Start).
|
||||
Füge deinen Key in die .env ein (nicht NEXT_PUBLIC_!): MISTRAL_API_KEY=dein_key_hier
|
||||
2. Der Code (Server Action)
|
||||
|
||||
15:30 Uhr: Laphroaig Cask Strength (Der Gaumen-Killer).
|
||||
Erstelle eine neue Datei, z.B. app/actions/scan-mistral.ts.
|
||||
TypeScript
|
||||
|
||||
16:00 Uhr: Auchentoshan (Schmeckt nach nichts mehr, weil Laphroaig davor war).
|
||||
'use server'
|
||||
|
||||
Analyse & Warnungen (Smart Features):
|
||||
import { Mistral } from '@mistralai/mistralai';
|
||||
|
||||
Der "Palette-Checker":
|
||||
const client = new Mistral({ apiKey: process.env.MISTRAL_API_KEY });
|
||||
|
||||
Wenn der User einen extrem rauchigen Whisky (80ppm) loggt und 10 Minuten später einen milden Lowlander eintragen will.
|
||||
export async function scanWithPixtral(base64Image: string, mimeType: string) {
|
||||
// Pixtral braucht das Bild als Data-URL
|
||||
const dataUrl = `data:${mimeType};base64,${base64Image}`;
|
||||
|
||||
Warnung (lustig): "Achtung! Du hast gerade eine Torfbombe getrunken. Warte lieber noch 10 Min oder trink Wasser, sonst schmeckst du den nächsten nicht!"
|
||||
try {
|
||||
const chatResponse = await client.chat.complete({
|
||||
model: 'pixtral-large-latest', // Das beste Modell (Stand Dez 2025)
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Du bist ein Whisky-Experte und OCR-Spezialist.
|
||||
Analysiere dieses Etikett präzise.
|
||||
|
||||
Antworte AUSSCHLIESSLICH mit gültigem JSON (kein Markdown, kein Text davor/danach):
|
||||
{
|
||||
"distillery": "Name der Brennerei (z.B. Lagavulin)",
|
||||
"name": "Exakter Name/Edition (z.B. 16 Year Old)",
|
||||
"vintage": "Jahrgang oder null",
|
||||
"age": "Alter oder null (z.B. 16)",
|
||||
"abv": "Alkoholgehalt (z.B. 43%)",
|
||||
"search_query": "site:whiskybase.com [Brennerei] [Name] [Alter]"
|
||||
}`
|
||||
},
|
||||
{
|
||||
type: 'image_url',
|
||||
imageUrl: dataUrl
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
responseFormat: { type: 'json_object' }, // Erzwingt JSON (wichtig!)
|
||||
temperature: 0.1 // Niedrig = präziser, weniger Halluzinationen
|
||||
});
|
||||
|
||||
ABV-Kurve:
|
||||
const rawContent = chatResponse.choices?.[0].message.content;
|
||||
|
||||
if (!rawContent) throw new Error("Keine Antwort von Pixtral");
|
||||
|
||||
Ein Liniendiagramm am Ende der Session: Wie hat sich der Alkoholgehalt entwickelt?
|
||||
// JSON parsen
|
||||
return JSON.parse(rawContent as string);
|
||||
|
||||
Ideal: Langsamer Anstieg.
|
||||
} catch (error) {
|
||||
console.error("Pixtral Error:", error);
|
||||
return null; // Fallback auslösen
|
||||
}
|
||||
}
|
||||
|
||||
Gefährlich: Zick-Zack.
|
||||
3. Der "A/B-Switcher" (So nutzt du beides)
|
||||
|
||||
Time-Stamping:
|
||||
In deiner Haupt-Logik (app/actions/scan.ts) kannst du jetzt einfach umschalten oder Pixtral als Fallback nutzen, wenn Gemini zickt (oder andersrum).
|
||||
TypeScript
|
||||
|
||||
Nutze nicht nur created_at (Upload Zeit), sondern speichere explizit tasted_at.
|
||||
'use server'
|
||||
import { scanWithGemini } from './scan-gemini'; // Deine bestehende Funktion
|
||||
import { scanWithPixtral } from './scan-mistral';
|
||||
|
||||
Warum? Wenn du 3 Stunden offline warst und dann online gehst, haben alle 5 Whiskys das gleiche created_at (Upload-Zeitpunkt). Du brauchst den Zeitpunkt, an dem der Button gedrückt wurde (lokale Handy-Zeit).
|
||||
export async function scanBottle(formData: FormData) {
|
||||
// ... Bild zu Base64 konvertieren ...
|
||||
const base64 = "...";
|
||||
const mime = "image/jpeg";
|
||||
|
||||
Zusammenfassung für die Session-Logik:
|
||||
// STRATEGIE A: Der "Qualitäts-Check"
|
||||
// Wir nutzen standardmäßig Gemini, aber Pixtral als EU-Option
|
||||
|
||||
let result;
|
||||
const useEuModel = process.env.USE_EU_MODEL === 'true'; // Schalter in .env
|
||||
|
||||
Das Datenmodell muss wissen:
|
||||
if (useEuModel) {
|
||||
console.log("🇪🇺 Nutze Pixtral (Mistral AI)...");
|
||||
result = await scanWithPixtral(base64, mime);
|
||||
} else {
|
||||
console.log("🇺🇸 Nutze Gemini 3 Flash...");
|
||||
result = await scanWithGemini(base64, mime);
|
||||
}
|
||||
|
||||
session_start (Zeitstempel)
|
||||
// Wenn das erste Modell versagt (null zurückgibt), versuche das andere
|
||||
if (!result) {
|
||||
console.log("⚠️ Erster Versuch fehlgeschlagen, starte Fallback...");
|
||||
result = useEuModel
|
||||
? await scanWithGemini(base64, mime)
|
||||
: await scanWithPixtral(base64, mime);
|
||||
}
|
||||
|
||||
session_end (Zeitstempel)
|
||||
// ... weiter mit Supabase Caching & Brave Search ...
|
||||
return result;
|
||||
}
|
||||
|
||||
Innerhalb der Session: Relative Zeit ("Dram Nr. 3, +45min nach Start").
|
||||
Pixtral vs. Gemini 3 Flash (Dein Check)
|
||||
|
||||
Achte beim Testen auf diese Feinheiten:
|
||||
|
||||
Helle Schrift auf dunklem Grund: Hier ist Gemini oft aggressiver und liest besser. Pixtral ist manchmal vorsichtiger.
|
||||
|
||||
Schreibschrift (Signatory Vintage Abfüllungen): Pixtral Large ist hier erstaunlich gut, fast besser als Gemini, da es Handschrift extrem gut kann.
|
||||
|
||||
JSON-Struktur: Dank responseFormat: { type: 'json_object' } sollten beide Modelle sehr sauberen Code liefern.
|
||||
|
||||
Wenn Pixtral Large für dich ähnlich gut funktioniert wie Gemini 3 Flash, hast du den großen Vorteil: Daten bleiben in Europa (Server in Frankreich/EU). Das ist ein starkes Marketing-Argument ("We love Whisky & Privacy").
|
||||
Reference in New Issue
Block a user