feat: Update README and next steps with Mistral AI model details and parsing rules for receipts

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Nils-Johan Gynther
2026-05-03 10:02:31 +02:00
parent 841d098405
commit 5879712a7f
2 changed files with 56 additions and 200 deletions
+18 -3
View File
@@ -20,8 +20,9 @@ Tolkar Markdown-recept till strukturerat JSON utan databas.
### Kvittoparsning (`POST /api/receipt-import/parse`)
- Bild (JPEG/PNG/WebP/HEIC/HEIF) eller PDF
- Mistral AI vision med retry-logik (3 försök vid 503/429)
- Returnerar `ParsedReceiptItem[]`
- **Modell:** `mistral-small-2603` (vision-kapabel) med retry-logik (3 försök vid 503/429)
- Returnerar `ParsedReceiptItem[]` med fälten `rawName`, `quantity`, `unit`, `price`, `brand`, `origin`
- Inbyggda regler i AI-prompten styr tolkning av `quantity`/`unit` (se nedan)
### Health (`GET /api/health`)
Används av Docker-healthcheck i `recipe-app/compose.yml`. Returnerar `{ status: "ok" }`.
@@ -77,7 +78,21 @@ src/
**Viktigt:** Backend har _INGEN_ databaskonfiguration — stateless service.
---
## Kvittoparsning — regler för quantity och unit
Följande regler är inbyggda i AI-prompten och styr hur Mistral tolkar mängd och enhet per produkt:
| Typ | Regel | Exempel |
|---|---|---|
| **Lösvikt** (kött, ost, frukt/grönt vägt i kassan) | `quantity` = faktisk vikt från kvittot, `unit` = `kg`/`g` | `BLANDFÄRS 20%` 0.997 kg → `quantity=0.997, unit="kg"` |
| **Förpackad vara med storlek i namn** (mejeri, dryck, konserver) | `quantity` = antal förpackningar, `unit` = `"förp"` | `MJÖLK 1,5L` × 3 → `quantity=3, unit="förp"` |
| **Multipack** (`NxYg`/`NxYml` i namn) | `quantity=1`, `unit="förp"` — räkna inte upp N | `BACON 3X120G``quantity=1, unit="förp"` |
| **Förpackat innehåll** (bröd, kex, chips) | `quantity` = antal förpackningar, `unit` = `"förp"` | `BRIOCHE SESAM` × 2 → `quantity=2, unit="förp"` |
| **Lösa styckvaror** (enstaka frukt/bröd per st) | `quantity` = antal, `unit` = `"st"` | `BANAN` × 1 → `quantity=1, unit="st"` |
Tillåtna enheter: `st`, `kg`, `g`, `l`, `dl`, `cl`, `ml`, `förp`, `pak`, `burk`, `flaska`
---
@@ -145,7 +160,7 @@ docker exec importer-api wget -qO- http://localhost:3001/api/health
- **Node.js** 22-alpine — Runtime (Alpine Linux)
- **pdf-parse** — PDF text extraction
- **tesseract.js** — OCR (bild och skannade PDFs, svenska + engelska)
- **@mistralai/mistralai** — AI-kvittoparsning
- **@mistralai/mistralai** — AI-kvittoparsning (`mistral-small-2603`)
- **multer** — Multipart file upload handling
- **Ingen databas** — Stateless service
+38 -197
View File
@@ -1,8 +1,8 @@
# Plan för vidareutveckling av Microservice Importer
## Status (2026-04-30) — Integrerad med recipe-app
## Status (2026-05-03) — Driftsatt och integrerad med recipe-app
`microservice-importer` är nu driftsatt som intern tjänst (`importer-api`) i `recipe-app/compose.yml`. Alla tre importflöden är delegerade:
`microservice-importer` körs som intern tjänst (`importer-api`) i `recipe-app/compose.yml`. Alla importflöden är delegerade och driftsatta.
| Endpoint | Funktion | Status |
|---|---|---|
@@ -28,21 +28,49 @@ cd /opt/containers/recipe-app && git pull && ./deploy.sh
---
## Återstående / Möjliga nästa steg
## Nästa steg
### Hög prioritet
- **Kvittoimport Fas 6b** — Granskningssteg och bulk-spara i Flutter-klienten (logiken är klar i backend)
- **Kvittoimport Fas 6b** — Granskningssteg och bulk-spara i Flutter-klienten (backend-logiken är klar)
### Medel prioritet
- **Fler webbplats-parsers** — Lägg till specifika parsers för t.ex. Arla, Tasteline, Köket.se
- **Fler webbplats-parsers** — Specifika parsers för t.ex. Tasteline, Köket.se, Arla
- **Swagger/OpenAPI** — Automatisk API-dokumentation via `@nestjs/swagger`
- **Testtäckning** — Enhetstester för parsers och receipt-parsing-service
- **Testtäckning** — Enhetstester för parsers och `receipt-parsing.service.ts`
### Låg prioritet / Framtida
- **Caching** — Cacha skrapade sidor för att minska belastning på externa webbplatser
- **Puppeteer** — Hantera JavaScript-renderade sidor
- **Puppeteer** — Hantera JavaScript-renderade receptsidor
- **Word-dokument** — Stöd för `.docx`-import
- **Centraliserad loggning** — Prometheus/Grafana eller liknande
---
## 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.
### Möjlig optimering: AI sist i pipeline
Eftersom tjänsten redan har OCR (Tesseract) och regelbaserad parsning (regex för `NxYg`, `Ydl`, `Y kg` etc.) finns möjlighet att omstrukturera kvittopipelinen:
```
Bild/PDF → OCR/pdf-parse → Regelbaserad parsning → AI (för rader som inte lösts ut)
```
**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
- Möjlighet att använda en mindre/billigare modell för enklare tolkningsuppgifter
### Modellval för olika deluppgifter
| Uppgift | Rekommenderad modell | Motivering |
|---|---|---|
| Kvittoparsning (hela bilden, nuläge) | `mistral-small-2603` | Vision-förmåga krävs för bild-input |
| Tolka OCR-text (textbaserad input) | `mistral-small-latest` eller mindre | Enklare uppgift när text redan extraherats |
| Kategorisering av enskild produktrad | `open-mistral-nemo` (7B) | Klassificering, ej vision — kan vara mycket liten |
**OBS:** För bild-input (JPEG/PNG/HEIC/WebP) krävs alltid en vision-kapabel modell. Optimering med mindre modell är bara möjlig när Tesseract/pdf-parse redan har extraherat text.
---
@@ -50,193 +78,6 @@ cd /opt/containers/recipe-app && git pull && ./deploy.sh
- Tjänsten är **helt stateless** — ingen databas, ingen session
- Kommunicerar **aldrig direkt** med internet-klienter — exponeras bara på `recipe-internal`-nätverket
- `MISTRAL_API_KEY` injiceras via env (samma nyckel som recipe-api använder)
- `MISTRAL_API_KEY` injiceras via env (samma nyckel som `recipe-api` använder)
- Alpine Docker-image: systempaket `tesseract-ocr`, `tesseract-ocr-data-swe`, `tesseract-ocr-data-eng` installerade via `apk`
---
## 1. Förbättra befintliga funktioner
### a. PDF-import och konvertering
- **OCR-implementering**: Slutför OCR-stödet för skannade PDF-filer. Använd bibliotek som Tesseract.js för att extrahera text från bilder.
- **Förbättrad metadatahantering**: Lägg till stöd för fler metadatafält, såsom författare, nyckelord och språk.
- **Förbättrad felhantering**: Utöka felmeddelanden för att ge tydligare feedback vid problem med PDF-filer.
### b. Webb-skrapning
- **Utöka stöd för webbplatser**: Lägg till specifika parsers för fler populära receptwebbplatser.
- **Förbättrad robusthet**: Hantera dynamiskt innehåll och JavaScript-renderade sidor med verktyg som Puppeteer.
- **Caching**: Implementera caching för att minska belastningen på extern webbplatser och förbättra prestanda.
---
## 2. Lägga till nya funktioner
### a. Stöd för fler dokumentformat
- **Word-dokument**: Lägg till stöd för att importera och konvertera `.docx`-filer till Markdown.
- **Bildfiler**: Implementera OCR för att extrahera text från bilder (t.ex. `.jpg`, `.png`).
### b. Databasintegration
- **Lokal databas**: Lägg till stöd för att spara konverterade dokument och metadata i en databas (t.ex. PostgreSQL eller MongoDB).
- **Sökfunktion**: Implementera en sökfunktion för att enkelt hitta sparade dokument.
### c. Användarautentisering
- **Inloggning**: Lägg till autentisering för att skydda API:et och möjliggöra användarspecifika dokument.
- **Rollbaserad åtkomst**: Implementera roller för att styra åtkomst till olika funktioner.
---
## 3. Optimera arkitekturen
### a. Backend
- **Modulär struktur**: Se till att varje funktion är tydligt separerad i moduler för att underlätta underhåll och skalning.
- **Prestandaoptimering**: Använd caching och asynkron bearbetning för att förbättra prestandan vid stora filuppladdningar.
### b. Frontend
- **Förbättrad användarupplevelse**: Lägg till en förhandsgranskning av konverterade dokument innan de sparas.
- **Responsiv design**: Säkerställ att gränssnittet fungerar bra på mobila enheter.
---
## 4. Testning och kvalitetssäkring
### a. Enhetstestning
- **Backend**: Skriv enhetstester för alla tjänster och parsers.
- **Frontend**: Testa komponenter och API-anrop.
### b. Integrationstestning
- **API-tester**: Verifiera att alla API-endpoints fungerar som förväntat.
- **E2E-tester**: Testa hela flödet från filuppladdning till visning av konverterat dokument.
### c. Säkerhetstestning
- **Säkerhetsgranskning**: Kontrollera att API:et är skyddat mot vanliga säkerhetshot, såsom SQL-injektioner och CSRF-attacker.
---
## 5. Dokumentation och användarstöd
### a. API-dokumentation
- **Swagger/OpenAPI**: Lägg till automatiskt genererad API-dokumentation för att underlätta integration med andra system.
### b. Användarhandbok
- **Installationsguide**: Uppdatera `README.md` med tydliga instruktioner för installation och användning.
- **Felsökningsguide**: Lägg till vanliga problem och lösningar.
---
## 6. Skalbarhet och drift
### a. Containerisering
- **Docker**: Se till att alla tjänster är korrekt containeriserade för enkel distribution.
- **Orkestrering**: Använd Kubernetes för att hantera skalning och hög tillgänglighet.
---
## 7. Långsiktigt mål: Kvittoimport som strukturerade poster (Fas 6b)
### Status (2026-04-30)
**Backend (`recipe-api`) är redan implementerat!** `ReceiptImportController` och `ReceiptImportService` finns redan och använder **Mistral AI** för att parsa kvitton till strukturerade `ParsedReceiptItem[]` direkt. Det finns inget behov av att flytta denna logik till Microservice Importer — det som återstår är granskningssteg och bulk-spara i Flutter-klienten.
Detta avsnitt gäller nu som referens för om man i framtiden vill isolera kvittoparsning som en fristående microservice.
### Bakgrund
Detta var ursprungligen planerat som ett långsiktigt mål: att flytta kvittoparsning från `recipe-api` till **Microservice Importer** för bättre modularitet. Logiken är nu implementerad i `recipe-api` med Mistral AI och fungerar. En framtida refaktorering till microservice kan göras om skalbarhetsbehov uppstår.
### Mål
- **Microservice Importer** tar emot en kvittofil (PDF eller bild) och returnerar strukturerade poster:
```json
{
"items": [
{ "rawName": "GURKA SVERIGE ST", "quantity": 1, "price": 16.90 },
{ "rawName": "DRUVOR RÖDA 500G", "quantity": 1, "price": 39.90 }
],
"source": "pdf"
}
```
- **`recipe-api`** fungerar som proxy och vidarebefordrar filen till microservicen och returnerar strukturerade `items` till klienten.
- **Flutter-klienten** tar emot strukturerade `items` direkt och behöver inte längre parsa markdown på klientsidan.
### Implementation
#### Steg 1: Parser i Microservice Importer
- Implementera en kvittoparser som extraherar produktrader ur OCR-text från PDF/bild.
- Tolka kvantitet och pris ur varje rad med regex (t.ex. `GURKA SVERIGE ST 16,90`).
- Hantera svenska kvittoformat (Willys, ICA, Coop etc.).
- Returnera strukturerade `items[]` via ett eget API-endpoint, t.ex. `POST /parse-receipt`.
#### Steg 2: Integration med recipe-api
- `recipe-api`/`/receipt-import` anropar Microservice Importer vid filuppladdning.
- Returnerar `{ items: [...], source: "pdf" }` till klienten i stället för `{ markdown: "..." }`.
#### Steg 3: Uppdatera Flutter-klienten
- Ta bort den tillfälliga markdown-parsningen i `ImportRepository`.
- Hantera strukturerade `items` direkt från API-svaret.
#### Steg 4: Granskningssteg och bulk-spara
- Visa importerade produkter i ett granskningssteg där användaren kan korrigera namn, kvantitet och pris.
- Implementera bulk-spara för att spara alla godkända poster till pantry/inventarie.
### b. Övervakning och loggning
- **Loggning**: Implementera centraliserad loggning för att enkelt kunna felsöka problem.
- **Övervakning**: Använd verktyg som Prometheus och Grafana för att övervaka prestanda och tillgänglighet.
---
## 7. Framtida utökningar
### a. AI-integration
- **Automatisk sammanfattning**: Använd NLP för att automatiskt sammanfatta konverterade dokument.
- **Smart kategorisering**: Klassificera dokument baserat på innehåll.
### b. Integration med molntjänster
- **Molnupladdning**: Lägg till stöd för att ladda upp dokument till molntjänster som Google Drive eller Dropbox.
---
## Optimering av AI-användning i Importfunktionen
För att optimera användningen av AI i importfunktionen, särskilt med tanke på att använda så små Mistral-modeller som möjligt, kan vi strukturera processen på följande sätt:
### Nuvarande Process
1. **Bild/PDF → OCR (Tesseract)**: Bilder och PDF:er bearbetas med Tesseract för att extrahera text.
2. **Regelbaserad Parsning**: Reguljära uttryck används för att identifiera mängd, enhet och produktnamn.
3. **AI-baserad Parsning (Mistral)**: Mistral AI används för att tolka kvittot och returnera strukturerad data.
### Förbättringsförslag
#### 1. Använd AI efter Regelbaserad Parsning
- **Fördelar**: Regelbaserad parsning kan hantera de flesta enkla fall (t.ex. "TUC ORIGINAL 100G").
- **Implementering**: Kör regelbaserad parsning först. Om regelbaserad parsning inte kan tolka en rad, skicka den till AI för vidare analys.
#### 2. Använd AI efter OCR och PDF-parsning
- **Fördelar**: AI kan användas för att förbättra kvaliteten på texten som extraherats av Tesseract eller `pdf-parse`.
- **Implementering**: Kör OCR och PDF-parsning först. Skicka den extraherade texten till AI för att förbättra kvaliteten. Använd den förbättrade texten för regelbaserad parsning.
#### 3. Använd Olika Mistral-modeller för Olika Uppgifter
- **Fördelar**: Små modeller kan användas för enkla uppgifter, medan större modeller kan användas för komplexa uppgifter.
- **Förslag på Modeller**:
- **`mistral-tiny`**: För att förbättra OCR-resultat och enkla tolkningar.
- **`mistral-small`**: För att tolka komplexa kvittorader där regelbaserad parsning misslyckas.
- **`mistral-medium`**: För att hantera mycket komplexa fall eller när hög precision krävs.
#### 4. Implementera Caching
- **Fördelar**: Minskar antalet AI-anrop genom att cacha resultat för vanliga produkter och kvittorader.
- **Implementering**: Cacha resultat från AI för vanliga produkter och kvittorader. Använd cachade resultat när samma produkt eller kvittorad dyker upp igen.
### Förslag på Arbetsflöde
1. **OCR och PDF-parsning**: Kör Tesseract eller `pdf-parse` för att extrahera text.
2. **Regelbaserad Parsning**: Använd reguljära uttryck för att tolka mängd, enhet och produktnamn.
3. **AI för Förbättring av Textkvalitet** (valfritt): Skicka den extraherade texten till en liten Mistral-modell (t.ex. `mistral-tiny`) för att förbättra kvaliteten.
4. **AI för Komplexa Fall**: Om regelbaserad parsning misslyckas, skicka raden till en större Mistral-modell (t.ex. `mistral-small` eller `mistral-medium`) för tolkning.
5. **Caching**: Cacha resultat från AI för att undvika upprepade anrop.
Genom att strukturera processen på detta sätt kan vi optimera AI-användningen och använda så små modeller som möjligt, samtidigt som vi bibehåller precisionen.
---
## Prioriteringsförslag
1. **OCR-implementering** (hög prioritet)
2. **Databasintegration** (medel prioritet)
3. **Användarautentisering** (medel prioritet)
4. **Stöd för fler dokumentformat** (låg prioritet)
5. **AI-integration** (framtida utökning)
- Host-port 3001 är upptagen av `wetty` på servern — `importer-api` exponeras aldrig till host