fix: enhance PDF parsing and retry logic; improve reproducibility and AI filtering
Test Suite / test (24.15.0) (push) Has been cancelled

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Nils-Johan Gynther
2026-05-03 22:29:37 +02:00
parent 2dc8aa4fb4
commit bf4e1d48bf
2 changed files with 16 additions and 8 deletions
+6 -3
View File
@@ -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)
+10 -5
View File
@@ -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