feat: granular performance tracking and cache hit indicators for AI scans
This commit is contained in:
@@ -68,6 +68,11 @@ export async function analyzeBottleMistral(input: any): Promise<AnalysisResponse
|
||||
return {
|
||||
success: true,
|
||||
data: cachedResult.result as any,
|
||||
perf: {
|
||||
apiDuration: 0,
|
||||
parseDuration: 0,
|
||||
uploadSize: buffer.length
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -76,9 +81,11 @@ export async function analyzeBottleMistral(input: any): Promise<AnalysisResponse
|
||||
const base64Data = buffer.toString('base64');
|
||||
const mimeType = file.type || 'image/webp';
|
||||
const dataUrl = `data:${mimeType};base64,${base64Data}`;
|
||||
const uploadSize = buffer.length;
|
||||
|
||||
const prompt = getSystemPrompt(tags.length > 0 ? tags.join(', ') : 'Keine Tags verfügbar', locale);
|
||||
|
||||
const startApi = performance.now();
|
||||
const chatResponse = await client.chat.complete({
|
||||
model: 'mistral-large-latest',
|
||||
messages: [
|
||||
@@ -93,7 +100,9 @@ export async function analyzeBottleMistral(input: any): Promise<AnalysisResponse
|
||||
responseFormat: { type: 'json_object' },
|
||||
temperature: 0.1
|
||||
});
|
||||
const endApi = performance.now();
|
||||
|
||||
const startParse = performance.now();
|
||||
const rawContent = chatResponse.choices?.[0].message.content;
|
||||
if (!rawContent) throw new Error("Keine Antwort von Mistral");
|
||||
|
||||
@@ -121,6 +130,7 @@ export async function analyzeBottleMistral(input: any): Promise<AnalysisResponse
|
||||
if (jsonData.vintage) jsonData.vintage = parseInt(jsonData.vintage);
|
||||
|
||||
const validatedData = BottleMetadataSchema.parse(jsonData);
|
||||
const endParse = performance.now();
|
||||
|
||||
// Track usage
|
||||
await trackApiUsage({
|
||||
@@ -141,7 +151,12 @@ export async function analyzeBottleMistral(input: any): Promise<AnalysisResponse
|
||||
return {
|
||||
success: true,
|
||||
data: validatedData,
|
||||
search_string: searchString
|
||||
search_string: searchString,
|
||||
perf: {
|
||||
apiDuration: endApi - startApi,
|
||||
parseDuration: endParse - startParse,
|
||||
uploadSize: uploadSize
|
||||
}
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
|
||||
@@ -60,7 +60,6 @@ export async function analyzeBottle(input: any): Promise<AnalysisResponse> {
|
||||
|
||||
// 4. Hash für Cache erstellen (direkt vom Buffer -> sehr schnell)
|
||||
const imageHash = createHash('sha256').update(buffer).digest('hex');
|
||||
|
||||
// Cache Check
|
||||
const { data: cachedResult } = await supabase
|
||||
.from('vision_cache')
|
||||
@@ -69,7 +68,15 @@ export async function analyzeBottle(input: any): Promise<AnalysisResponse> {
|
||||
.maybeSingle();
|
||||
|
||||
if (cachedResult) {
|
||||
return { success: true, data: cachedResult.result as any };
|
||||
return {
|
||||
success: true,
|
||||
data: cachedResult.result as any,
|
||||
perf: {
|
||||
apiDuration: 0,
|
||||
parseDuration: 0,
|
||||
uploadSize: buffer.length
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 5. Für Gemini vorbereiten
|
||||
@@ -77,10 +84,12 @@ export async function analyzeBottle(input: any): Promise<AnalysisResponse> {
|
||||
// extrem effizient. Das Problem vorher war der JSON Parser von Next.js.
|
||||
const base64Data = buffer.toString('base64');
|
||||
const mimeType = file.type || 'image/webp'; // Fallback
|
||||
const uploadSize = buffer.length;
|
||||
|
||||
const instruction = getSystemPrompt(tags.length > 0 ? tags.join(', ') : 'No tags available', locale);
|
||||
|
||||
// API Call
|
||||
const startApi = performance.now();
|
||||
const result = await geminiModel.generateContent([
|
||||
{
|
||||
inlineData: {
|
||||
@@ -90,7 +99,9 @@ export async function analyzeBottle(input: any): Promise<AnalysisResponse> {
|
||||
},
|
||||
{ text: instruction },
|
||||
]);
|
||||
const endApi = performance.now();
|
||||
|
||||
const startParse = performance.now();
|
||||
const responseText = result.response.text();
|
||||
|
||||
// JSON Parsing der ANTWORT (das ist klein, das schafft der N100 locker)
|
||||
@@ -111,6 +122,7 @@ export async function analyzeBottle(input: any): Promise<AnalysisResponse> {
|
||||
if (!jsonData) throw new Error('Keine Daten in der KI-Antwort gefunden.');
|
||||
|
||||
const validatedData = BottleMetadataSchema.parse(jsonData);
|
||||
const endParse = performance.now();
|
||||
|
||||
// 6. Tracking & Credits (bleibt gleich)
|
||||
await trackApiUsage({
|
||||
@@ -132,7 +144,12 @@ export async function analyzeBottle(input: any): Promise<AnalysisResponse> {
|
||||
return {
|
||||
success: true,
|
||||
data: validatedData,
|
||||
search_string: searchString
|
||||
search_string: searchString,
|
||||
perf: {
|
||||
apiDuration: endApi - startApi,
|
||||
parseDuration: endParse - startParse,
|
||||
uploadSize: uploadSize
|
||||
}
|
||||
} as any;
|
||||
|
||||
} catch (error) {
|
||||
|
||||
@@ -79,7 +79,8 @@ export async function magicScan(input: any): Promise<AnalysisResponse & { wb_id?
|
||||
console.log(`[Magic Scan] Cache Hit for ${searchString}: ${cacheHit.wb_id}`);
|
||||
return {
|
||||
...aiResponse,
|
||||
wb_id: cacheHit.wb_id
|
||||
wb_id: cacheHit.wb_id,
|
||||
perf: aiResponse.perf
|
||||
};
|
||||
}
|
||||
|
||||
@@ -106,13 +107,15 @@ export async function magicScan(input: any): Promise<AnalysisResponse & { wb_id?
|
||||
|
||||
return {
|
||||
...aiResponse,
|
||||
wb_id: braveResult.id
|
||||
wb_id: braveResult.id,
|
||||
perf: aiResponse.perf
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...aiResponse,
|
||||
wb_id: undefined
|
||||
wb_id: undefined,
|
||||
perf: aiResponse.perf
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user