From bf4e1d48bf1344c225574d972abb6de14510c774 Mon Sep 17 00:00:00 2001 From: Nils-Johan Gynther Date: Sun, 3 May 2026 22:29:37 +0200 Subject: [PATCH] fix: enhance PDF parsing and retry logic; improve reproducibility and AI filtering Co-authored-by: Copilot --- README.md | 9 ++++++--- next_steps_MSImporter.md | 15 ++++++++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 2ab3b25..4019dbd 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,10 @@ Detta dokument är för systemadministratörer och utvecklare som driftar eller - Parserstödet för brödrelaterade produkter och guardrails mot felkategorisering har utökats. - Integrationen med klienten för kvitto-session är fortfarande stateless i denna tjänst; ingen serverlagring av användarsession infördes. - Kvittokategorisering: nya regler för pasta, grädde, ägg, juice, godis, och potatis samt justerad AI-guardrail. -- Testinfrastruktur: parametriserade enhetstester för kvittoimport (18 testfall) och CI/CD-pipeline med automatiserad testkörning på push. - +- Testinfrastruktur: parametriserade enhetstester för kvittoimport (18 testfall) och CI/CD-pipeline med automatiserad testkörning på push.- **PDF-fix:** `pdf-parse` importeras nu med `require()` (CJS-kompatibilitet). `pdfjs-dist/legacy/build/pdf.js` används som fallback för att undvika `DOMMatrix is not defined` i Node.js-miljö. +- **Retry-förbättring:** Mistral 429/503 → väntar `3000 * attempt` ms innan nytt försök. +- **Reproducerbart bygge:** `package-lock.json` spåras i git; Dockerfile kör `npm ci`. +- **AI-skippning för icke-produktrader:** `looksLikeReceiptProductLine()` filtrerar PDF-rader utan siffra (header/footer/butiksinformation) — dessa skickas inte till Mistral. ## Viktigt!! Kod- och byggpraxis! Säkerställ att inga absoluta Windows-sökvägar används i koden, för att stödja bygg och drift på Linux/Ubuntu @@ -32,7 +34,8 @@ Tolkar Markdown-recept till strukturerat JSON utan databas. ### Kvittoparsning (`POST /api/receipt-import/parse`) - Bild (JPEG/PNG/WebP/HEIC/HEIF) eller PDF -- **Modell:** `mistral-small-2603` (vision-kapabel) med retry-logik (3 försök vid 503/429) +- **Bild:** `mistral-small-2603` (vision-kapabel) med retry-logik (3 försök, `3000 * attempt` ms fördröjning vid 429/503) +- **PDF:** `pdf-parse` → fallback `pdfjs-dist/legacy` → regelbaserad parsning → AI enbart för rader med namntext + siffra - Returnerar `ParsedReceiptItem[]` med fälten `rawName`, `quantity`, `unit`, `price`, `brand`, `origin` - Inbyggda regler i AI-prompten styr tolkning av `quantity`/`unit` (se nedan) diff --git a/next_steps_MSImporter.md b/next_steps_MSImporter.md index ea5a520..eb8b569 100644 --- a/next_steps_MSImporter.md +++ b/next_steps_MSImporter.md @@ -10,6 +10,10 @@ Detta dokument riktar sig till utvecklare och driftansvariga för microservice-i - Klientens granskningsflöde och sessionpersistens i Flutter är implementerat, vilket minskar avbrott mellan parse och spara. - Kvittokategorisering: nya regler för pasta, grädde, ägg, juice, godis, och potatis samt justerad AI-guardrail. - Testinfrastruktur: parametriserade enhetstester för kvittoimport (18 testfall) och CI/CD-pipeline med automatiserad testkörning på push. +- **PDF-parsning stabiliserad:** `pdf-parse` använder nu `require()` för CJS-kompatibilitet; `pdfjs-dist/legacy/build/pdf.js` används som fallback för att undvika `DOMMatrix`-fel i Node.js-miljö. +- **Retry-logik förbättrad:** Mistral-anrop vid 429/503 väntar nu `3000 * attempt` ms (3s, 6s, 9s) i stället för fast 1s. +- **Reproducerbart bygge:** `package-lock.json` är nu spårat i repot; Dockerfile använder `npm ci`. +- **AI-optimering implementerad:** `looksLikeReceiptProductLine()` filtrerar bort PDF-rader utan siffra (header/footer/butiksinformation) innan Mistral-anrop. Minskar drastiskt antal onödiga AI-anrop vid kvittoimport. ## Status (2026-05-03) — Driftsatt och integrerad med recipe-app @@ -43,7 +47,6 @@ cd /opt/containers/recipe-app && git pull && ./deploy.sh ### Hög prioritet - **Kvittoimport Fas 6b** — Granskningssteg och bulk-spara i Flutter-klienten (backend-logiken är klar) -- **Node.js versionsparitet** — Lås samma Node-version i lokal utveckling, Docker-image och CI-runner för att eliminera miljödrift mellan build och runtime. ### Medel prioritet - **Fler webbplats-parsers** — Specifika parsers för t.ex. Tasteline, Köket.se, Arla @@ -59,16 +62,18 @@ cd /opt/containers/recipe-app && git pull && ./deploy.sh ## AI-optimering: Mistral-modell och pipeline -**Nuläge:** `mistral-small-2603` används för kvittoparsning. Modellen tar emot hela kvittobilden/PDF-texten och returnerar strukturerad JSON. +**Nuläge:** `mistral-small-2603` används för bildinput (vision). För PDF-flödet extraheras text först via `pdf-parse`/`pdfjs-dist`; sedan regelbaserad parsning; sedan AI enbart för återstående rader. -### Möjlig optimering: AI sist i pipeline +### Implementerad optimering: AI sist i pipeline (PDF) -Eftersom tjänsten redan har OCR (Tesseract) och regelbaserad parsning (regex för `NxYg`, `Ydl`, `Y kg` etc.) finns möjlighet att omstrukturera kvittopipelinen: +Kvittopipelinen för PDF ser nu ut: ``` -Bild/PDF → OCR/pdf-parse → Regelbaserad parsning → AI (för rader som inte lösts ut) +PDF → pdf-parse / pdfjs-dist → preprocessPdfLines → isIgnoredReceiptLine → ruleBasedParseLine → looksLikeReceiptProductLine → AI ``` +**`looksLikeReceiptProductLine(line)`** filtrerar bort rader som saknar siffra (butiksnamn, datum, välkomsttext m.m.) innan Mistral-anropet. Enbart rader med namnliknande text OCH minst ett tal skickas till AI. + **Fördelar:** - Regelbaserad parsning hanterar standardfall gratis och snabbt (t.ex. "MJÖLK 1,5L", "BLANDFÄRS 997G") - AI anropas bara för rader som regelverket inte kan tolka entydigt