feat: Switch to Mistral Large 3 (mistral-large-latest)

This commit is contained in:
2025-12-19 21:59:51 +01:00
parent 25b1378794
commit 2601a8f12f
6 changed files with 19 additions and 19 deletions

View File

@@ -65,7 +65,7 @@ export default function CameraCapture({ onImageCaptured, onAnalysisComplete, onS
const [isDiscovering, setIsDiscovering] = useState(false);
const [originalFile, setOriginalFile] = useState<File | null>(null);
const [isAdmin, setIsAdmin] = useState(false);
const [aiProvider, setAiProvider] = useState<'gemini' | 'pixtral'>('gemini');
const [aiProvider, setAiProvider] = useState<'gemini' | 'mistral'>('gemini');
React.useEffect(() => {
const checkAdmin = async () => {
@@ -364,10 +364,10 @@ export default function CameraCapture({ onImageCaptured, onAnalysisComplete, onS
Gemini
</button>
<button
onClick={() => setAiProvider('pixtral')}
className={`px-3 py-1 text-[10px] font-black uppercase tracking-widest rounded-lg transition-all ${aiProvider === 'pixtral' ? 'bg-white dark:bg-zinc-700 text-amber-600 shadow-sm' : 'text-zinc-400'}`}
onClick={() => setAiProvider('mistral')}
className={`px-3 py-1 text-[10px] font-black uppercase tracking-widest rounded-lg transition-all ${aiProvider === 'mistral' ? 'bg-white dark:bg-zinc-700 text-amber-600 shadow-sm' : 'text-zinc-400'}`}
>
Pixtral 🇪🇺
Mistral 3 🇪🇺
</button>
</div>
)}

View File

@@ -5,7 +5,7 @@ export interface PendingScan {
temp_id: string; // Used to link tasting notes before sync
imageBase64: string;
timestamp: number;
provider?: 'gemini' | 'pixtral';
provider?: 'gemini' | 'mistral';
locale?: string;
}

View File

@@ -7,7 +7,7 @@ import { createHash } from 'crypto';
import { trackApiUsage } from './track-api-usage';
import { checkCreditBalance, deductCredits } from './credit-service';
export async function analyzeBottlePixtral(base64Image: string, tags?: string[], locale: string = 'de'): Promise<AnalysisResponse & { search_string?: string }> {
export async function analyzeBottleMistral(base64Image: string, tags?: string[], locale: string = 'de'): Promise<AnalysisResponse & { search_string?: string }> {
if (!process.env.MISTRAL_API_KEY) {
return { success: false, error: 'MISTRAL_API_KEY is not configured.' };
}
@@ -66,7 +66,7 @@ Antworte AUSSCHLIESSLICH mit gültigem JSON (kein Markdown, kein Text davor/dana
}`;
const chatResponse = await client.chat.complete({
model: 'pixtral-large-latest',
model: 'mistral-large-latest',
messages: [
{
role: 'user',
@@ -81,7 +81,7 @@ Antworte AUSSCHLIESSLICH mit gültigem JSON (kein Markdown, kein Text davor/dana
});
const rawContent = chatResponse.choices?.[0].message.content;
if (!rawContent) throw new Error("Keine Antwort von Pixtral");
if (!rawContent) throw new Error("Keine Antwort von Mistral");
const jsonData = JSON.parse(rawContent as string);
@@ -104,12 +104,12 @@ Antworte AUSSCHLIESSLICH mit gültigem JSON (kein Markdown, kein Text davor/dana
await trackApiUsage({
userId: userId,
apiType: 'gemini_ai', // Keep as generic 'gemini_ai' for now or update schema later
endpoint: 'mistral/pixtral-large',
endpoint: 'mistral/mistral-large',
success: true
});
// Deduct credits
await deductCredits(userId, 'gemini_ai', 'Pixtral AI analysis');
await deductCredits(userId, 'gemini_ai', 'Mistral AI analysis');
// Store in Cache
await supabase
@@ -123,7 +123,7 @@ Antworte AUSSCHLIESSLICH mit gültigem JSON (kein Markdown, kein Text davor/dana
};
} catch (error) {
console.error('Pixtral Analysis Error:', error);
console.error('Mistral Analysis Error:', error);
// Track failed API call
try {
@@ -133,7 +133,7 @@ Antworte AUSSCHLIESSLICH mit gültigem JSON (kein Markdown, kein Text davor/dana
await trackApiUsage({
userId: session.user.id,
apiType: 'gemini_ai',
endpoint: 'mistral/pixtral-large',
endpoint: 'mistral/mistral-large',
success: false,
errorMessage: error instanceof Error ? error.message : 'Unknown error'
});
@@ -145,7 +145,7 @@ Antworte AUSSCHLIESSLICH mit gültigem JSON (kein Markdown, kein Text davor/dana
return {
success: false,
error: error instanceof Error ? error.message : 'Pixtral AI analysis failed.',
error: error instanceof Error ? error.message : 'Mistral AI analysis failed.',
};
}
}

View File

@@ -1,14 +1,14 @@
'use server';
import { analyzeBottle } from './analyze-bottle';
import { analyzeBottlePixtral } from './analyze-bottle-pixtral';
import { analyzeBottleMistral } from './analyze-bottle-mistral';
import { searchBraveForWhiskybase } from './brave-search';
import { getAllSystemTags } from './tags';
import { supabase } from '@/lib/supabase';
import { supabaseAdmin } from '@/lib/supabase-admin';
import { AnalysisResponse, BottleMetadata } from '@/types/whisky';
export async function magicScan(base64Image: string, provider: 'gemini' | 'pixtral' = 'gemini', locale: string = 'de'): Promise<AnalysisResponse & { wb_id?: string }> {
export async function magicScan(base64Image: string, provider: 'gemini' | 'mistral' = 'gemini', locale: string = 'de'): Promise<AnalysisResponse & { wb_id?: string }> {
try {
console.log('[magicScan] Starting scan process...');
if (!supabase) {
@@ -22,8 +22,8 @@ export async function magicScan(base64Image: string, provider: 'gemini' | 'pixtr
// 1. AI Analysis
let aiResponse: any;
if (provider === 'pixtral') {
aiResponse = await analyzeBottlePixtral(base64Image, tagNames, locale);
if (provider === 'mistral') {
aiResponse = await analyzeBottleMistral(base64Image, tagNames, locale);
} else {
aiResponse = await analyzeBottle(base64Image, tagNames, locale);
}