From 3a4d73da18928c9ddf607570f5e8a3705803f125 Mon Sep 17 00:00:00 2001 From: Nils-Johan Gynther Date: Sun, 3 May 2026 07:36:27 +0200 Subject: [PATCH] feat: Enhance quantity rules for receipt parsing and update prompt structure --- .../receipt-parsing.service.ts | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/backend/src/receipt-parsing/receipt-parsing.service.ts b/backend/src/receipt-parsing/receipt-parsing.service.ts index b480ecd..098c356 100644 --- a/backend/src/receipt-parsing/receipt-parsing.service.ts +++ b/backend/src/receipt-parsing/receipt-parsing.service.ts @@ -10,27 +10,44 @@ const MISTRAL_API_URL = 'https://api.mistral.ai/v1/chat/completions'; const RECEIPT_IMPORT_MODEL = 'mistral-small-2603'; const MAX_RETRIES = 3; +const QUANTITY_RULES = ` +Regler för quantity och unit: +1. LÖSVIKT (chark, kött, ost, frukt/grönt vägt på kassabandet): quantity=faktisk vikt/volym från kvittot, unit=kg/g/l etc. + Exempel: "BLANDFÄRS 20%" köpt 0.997 kg → quantity=0.997, unit="kg" +2. FÖRPACKAD VARA med storlek i namnet (mejeri, dryck, konserver, flingor): quantity=antal köpta förpackningar, unit="förp". + Exempel: "VISPGRÄDDE 5DL" köpt 1 → quantity=1, unit="förp" + Exempel: "MJÖLK 1,5L" köpt 3 → quantity=3, unit="förp" +3. MULTIPACK (NxYg/NxYml i namnet = flera innerförpackningar ihopsatta till ett ytteremballage): quantity=1, unit="förp". Räkna INTE upp N som quantity. + Exempel: "BACON 3X120G" (ett storpack med tre 120g-paket, ett köp på kvittot) → quantity=1, unit="förp" + Exempel: "YOGHURT 4X150G" → quantity=1, unit="förp" +4. FÖRPACKAT INNEHÅLL (bröd, kex, chips — förpackning med flera enheter inuti): quantity=antal köpta förpackningar, unit="förp". + Exempel: "BRIOCHE SESAM" (förpackning med hamburgerbröd) köpt 2 → quantity=2, unit="förp" + Exempel: "CORNFLAKES 500G" köpt 1 → quantity=1, unit="förp" +5. LÖSA STYCKVAROR (enstaka frukt, enstaka bröd köpt i lösvikt per styck): quantity=antal, unit="st". + Exempel: "BANAN" köpt 1 st löst → quantity=1, unit="st" +`; + const IMAGE_PROMPT = `Du är en kvittoläsare. Analysera detta kvitto och returnera ENDAST en JSON-array med alla köpta varor. Varje vara ska ha följande fält: - "rawName": varans namn som det står på kvittot (sträng) -- "quantity": antal eller mängd som ett tal (t.ex. 1, 2, 0.5) +- "quantity": antal köpta enheter som ett tal - "unit": enhet — välj ett av: "st", "kg", "g", "l", "dl", "cl", "ml", "förp", "pak", "burk", "flaska" - "price": pris i SEK som ett tal, eller null - "brand": märke eller leverantör om det tydligt framgår av varunamnet (t.ex. "Arla", "ICA", "Oatly"), annars null - "origin": ursprungsland om det framgår av varunamnet (t.ex. "Brasilien", "Sverige", "Italien"), annars null - +${QUANTITY_RULES} Returnera BARA JSON-arrayen utan markdown-formatering.`; const TEXT_PROMPT = (text: string) => `Du är en kvittoläsare. Nedan följer rå text från ett kvitto. Analysera texten och returnera ENDAST en JSON-array med alla köpta varor. Varje vara ska ha följande fält: - "rawName": varans namn som det står på kvittot (sträng) -- "quantity": antal eller mängd som ett tal (t.ex. 1, 2, 0.5) +- "quantity": antal köpta enheter som ett tal - "unit": enhet — välj ett av: "st", "kg", "g", "l", "dl", "cl", "ml", "förp", "pak", "burk", "flaska" - "price": pris i SEK som ett tal, eller null - "brand": märke eller leverantör om det tydligt framgår av varunamnet (t.ex. "Arla", "ICA", "Oatly"), annars null - "origin": ursprungsland om det framgår av varunamnet (t.ex. "Brasilien", "Sverige", "Italien"), annars null - +${QUANTITY_RULES} Returnera BARA JSON-arrayen utan markdown-formatering. Kvittotext: