unit tests fixin
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 35s
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 35s
This commit is contained in:
@@ -86,20 +86,64 @@ export const extractItemsFromReceiptImage = async (
|
||||
* @returns A promise that resolves to the extracted core data.
|
||||
*/
|
||||
export const extractCoreDataFromFlyerImage = async (
|
||||
_imagePaths: { path: string; mimetype: string }[],
|
||||
_masterItems: MasterGroceryItem[]
|
||||
imagePaths: { path: string; mimetype: string }[],
|
||||
masterItems: MasterGroceryItem[]
|
||||
): Promise<{
|
||||
store_name: string;
|
||||
valid_from: string | null;
|
||||
valid_to: string | null;
|
||||
items: Omit<FlyerItem, 'id' | 'created_at' | 'flyer_id'>[];
|
||||
}> => {
|
||||
// This function's logic is now handled by the backend API endpoint in `src/routes/ai.ts`.
|
||||
// The actual Gemini call logic is complex and has been moved there to keep this file clean
|
||||
// and demonstrate the architectural separation. For the purpose of this fix, we can
|
||||
// assume the backend correctly implements the Gemini call.
|
||||
// This function is now a placeholder to show where the logic *would* live.
|
||||
throw new Error("extractCoreDataFromFlyerImage is a server-side function and should be called from a backend route.");
|
||||
// 1. Construct the detailed prompt for the AI.
|
||||
const prompt = `
|
||||
Analyze the provided flyer image(s). Your task is to extract key information and a list of all sale items.
|
||||
|
||||
First, identify the following core details for the entire flyer:
|
||||
- "store_name": The name of the grocery store (e.g., "Walmart", "No Frills").
|
||||
- "valid_from": The start date of the sale period in YYYY-MM-DD format. If not present, use null.
|
||||
- "valid_to": The end date of the sale period in YYYY-MM-DD format. If not present, use null.
|
||||
|
||||
Second, extract each individual sale item. For each item, provide:
|
||||
- "item": The name of the product (e.g., "Coca-Cola Classic").
|
||||
- "price_display": The sale price as a string (e.g., "$2.99", "2 for $5.00").
|
||||
- "price_in_cents": The primary numeric price converted to cents (e.g., for "$2.99", use 299). If a price is "2 for $5.00", use 500. If no price, use null.
|
||||
- "quantity": A string describing the quantity or weight for the price (e.g., "12x355mL", "500g", "each").
|
||||
- "master_item_id": From the provided master list, find the best matching item and return its ID. If no good match is found, use null.
|
||||
- "category_name": The most appropriate category for the item (e.g., "Beverages", "Meat & Seafood").
|
||||
|
||||
Here is the master list of grocery items to help with matching:
|
||||
${JSON.stringify(masterItems)}
|
||||
|
||||
Return a single, valid JSON object with the keys "store_name", "valid_from", "valid_to", and "items". The "items" key should contain an array of the extracted item objects.
|
||||
Do not include any other text, explanations, or markdown formatting.
|
||||
`;
|
||||
|
||||
// 2. Convert all uploaded image files into the format required by the Gemini API.
|
||||
const imageParts = await Promise.all(
|
||||
imagePaths.map(file => serverFileToGenerativePart(file.path, file.mimetype))
|
||||
);
|
||||
|
||||
// 3. Make the API call to Gemini.
|
||||
const response = await model.generateContent({
|
||||
model: 'gemini-1.5-flash',
|
||||
contents: [{ parts: [{ text: prompt }, ...imageParts] }]
|
||||
});
|
||||
|
||||
const text = response.text;
|
||||
|
||||
// 4. Clean and parse the AI's response.
|
||||
const jsonMatch = text?.match(/\{[\s\S]*\}/);
|
||||
if (!jsonMatch) {
|
||||
logger.error("AI response for flyer processing did not contain a valid JSON object.", { responseText: text });
|
||||
throw new Error('AI response did not contain a valid JSON object.');
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(jsonMatch[0]);
|
||||
} catch (e) {
|
||||
logger.error("Failed to parse JSON from AI response in extractCoreDataFromFlyerImage", { responseText: text, error: e });
|
||||
throw new Error('Failed to parse structured data from the AI response.');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user