From 5879712a7fc89ac19946d25a924b3b7c758c409b Mon Sep 17 00:00:00 2001 From: Nils-Johan Gynther Date: Sun, 3 May 2026 10:02:31 +0200 Subject: [PATCH] feat: Update README and next steps with Mistral AI model details and parsing rules for receipts Co-authored-by: Copilot --- README.md | 21 +++- next_steps_MSImporter.md | 235 +++++++-------------------------------- 2 files changed, 56 insertions(+), 200 deletions(-) diff --git a/README.md b/README.md index 00f6fb8..176f149 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/next_steps_MSImporter.md b/next_steps_MSImporter.md index 5d06e8d..626c58f 100644 --- a/next_steps_MSImporter.md +++ b/next_steps_MSImporter.md @@ -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) \ No newline at end of file +- Host-port 3001 är upptagen av `wetty` på servern — `importer-api` exponeras aldrig till host