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:
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user