fix: update documentation status and enhance technical description for microservice importer
Test Suite / test (24.15.0) (push) Has been cancelled
Test Suite / test (24.15.0) (push) Has been cancelled
This commit is contained in:
+35
-60
@@ -1,21 +1,21 @@
|
||||
# Plan för vidareutveckling av Microservice Importer
|
||||
|
||||
## Dokumentstatus (2026-05-03)
|
||||
## Dokumentstatus (2026-05-10)
|
||||
|
||||
Detta dokument riktar sig till utvecklare och driftansvariga för microservice-importer.
|
||||
Detta dokument riktar sig till utvecklare och driftansvariga för microservice-importer. Teknisk referens finns i [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md).
|
||||
|
||||
### Senast avklarat i angränsande flöden
|
||||
- Regelbaserad kvittotolkning har stärkts för multipack/enheter och svårare radformat.
|
||||
- Bröd-/rostbrödklassning har utökade guardrails för att minska felaktig kategorisering.
|
||||
- Regelbaserad kvittotolkning har stärkts för multipack, enheter och svårare radformat.
|
||||
- Bröd- och rostbrödklassning har utökade guardrails för att minska felaktig kategorisering.
|
||||
- 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.
|
||||
- Kvittokategorisering: nya regler för pasta, grädde, ägg, juice, godis och potatis samt justerad AI-guardrail.
|
||||
- Testinfrastruktur: parametriserade enhetstester för kvittoimport och CI/CD-pipeline med automatiserad testkörning på push.
|
||||
- PDF-parsning stabiliserad med `require()` och `pdfjs-dist/legacy/build/pdf.js` som fallback.
|
||||
- Retry-logik förbättrad för 429/503.
|
||||
- Reproducerbart bygge via `package-lock.json` och `npm ci`.
|
||||
- `looksLikeReceiptProductLine()` filtrerar bort PDF-rader utan siffra innan Mistral-anrop.
|
||||
|
||||
## Status (2026-05-03) — Driftsatt och integrerad med recipe-app
|
||||
## Status (2026-05-10) — Driftsatt och integrerad med recipe-app
|
||||
|
||||
`microservice-importer` körs som intern tjänst (`importer-api`) i `recipe-app/compose.yml`. Alla importflöden är delegerade och driftsatta.
|
||||
|
||||
@@ -51,7 +51,7 @@ cd /opt/containers/recipe-app && git pull && ./deploy.sh
|
||||
### Medel prioritet
|
||||
- **Fler webbplats-parsers** — Specifika parsers för t.ex. Tasteline, Köket.se, Arla
|
||||
- **Swagger/OpenAPI** — Automatisk API-dokumentation via `@nestjs/swagger`
|
||||
- **Testtäckning** — Utökad enhetstesttäckning för parsers och `receipt-parsing.service.ts` (18 testfall för kvittoimport)
|
||||
- **Testtäckning** — Utökad enhetstesttäckning för parsers och `receipt-parsing.service.ts`
|
||||
|
||||
### Låg prioritet / Framtida
|
||||
- **Caching** — Cacha skrapade sidor för att minska belastning på externa webbplatser
|
||||
@@ -62,77 +62,52 @@ cd /opt/containers/recipe-app && git pull && ./deploy.sh
|
||||
|
||||
## AI-optimering: Mistral-modell och pipeline
|
||||
|
||||
**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.
|
||||
Nuläget är att `mistral-small-2603` används för bildinput (vision). För PDF-flödet extraheras text först via `pdf-parse` eller `pdfjs-dist`; därefter körs regelbaserad parsning och AI bara för kvarvarande rader.
|
||||
|
||||
### Implementerad optimering: AI sist i pipeline (PDF)
|
||||
|
||||
Kvittopipelinen för PDF ser nu ut:
|
||||
|
||||
```
|
||||
```text
|
||||
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
|
||||
- Möjlighet att använda en mindre/billigare modell för enklare tolkningsuppgifter
|
||||
`looksLikeReceiptProductLine(line)` filtrerar bort rader som saknar siffra innan Mistral-anropet. Enbart rader med namnliknande text och minst ett tal skickas till AI.
|
||||
|
||||
### 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 |
|
||||
| Kvittoparsning (hela bilden) | `mistral-small-2603` | Vision-förmåga krävs för bild-input |
|
||||
| Tolka OCR-text | `mistral-small-latest` eller mindre | Enklare uppgift när text redan extraherats |
|
||||
| Kategorisering av enskild produktrad | `open-mistral-nemo` (7B) | Klassificering utan vision |
|
||||
|
||||
**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.
|
||||
För bild-input krävs alltid en vision-kapabel modell.
|
||||
|
||||
---
|
||||
|
||||
## Framtida förbättringar
|
||||
|
||||
### Schemalagd Uppdatering av Kategorier
|
||||
- **Mål:** Implementera en schemalagd uppdatering av kategorierna en gång i veckan för att säkerställa att cachen alltid är uppdaterad.
|
||||
- **Metod:** Använda `cron` för att schemalägga ett anrop till `POST /receipt-import/refresh-categories` en gång i veckan.
|
||||
- Schemalagd uppdatering av kategorier om det visar sig nödvändigt igen.
|
||||
|
||||
---
|
||||
## Nuvarande implementering
|
||||
|
||||
## Nuvarande Implementering
|
||||
|
||||
### Manuell Uppdatering av Kategorier
|
||||
- **Mål:** Låta användaren manuellt uppdatera kategorierna via Flutter-UI.
|
||||
- **Implementering:**
|
||||
- En knapp i Flutter-UI:n som låter användaren trigga uppdateringen.
|
||||
- Anropa `POST /receipt-import/refresh-categories` från Flutter-UI:n när användaren klickar på knappen.
|
||||
|
||||
```dart
|
||||
// Exempel på hur du kan anropa endpointen från Flutter
|
||||
Future<void> refreshCategories() async {
|
||||
final response = await http.post(
|
||||
Uri.parse('http://YOUR_API_URL/receipt-import/refresh-categories'),
|
||||
headers: {'Authorization': 'Bearer YOUR_JWT_TOKEN'},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Kategorier har uppdaterats.')),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Misslyckades med att uppdatera kategorier.')),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
- Ingen separat manuell kategoriuppdatering via Flutter-UI finns längre.
|
||||
- Kvittoparsningen använder i stället nuvarande regler, retry-logik och filtrering i backend.
|
||||
|
||||
---
|
||||
|
||||
## Arkitektur-noteringar
|
||||
|
||||
- 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)
|
||||
- Alpine Docker-image: systempaket `tesseract-ocr`, `tesseract-ocr-data-swe`, `tesseract-ocr-data-eng` installerade via `apk`
|
||||
- Host-port 3001 är upptagen av `wetty` på servern — `importer-api` exponeras aldrig till host
|
||||
- Tjänsten är helt stateless och saknar databas
|
||||
- Den exponeras bara på `recipe-internal`-nätverket
|
||||
- `MISTRAL_API_KEY` injiceras via env
|
||||
- Alpine Docker-image använder `tesseract-ocr`, `tesseract-ocr-data-swe`, `tesseract-ocr-data-eng`
|
||||
- Host-port 3001 är upptagen av `wetty`, så `importer-api` exponeras aldrig till host
|
||||
|
||||
## Referenser
|
||||
|
||||
- [README.md](README.md)
|
||||
- [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md)
|
||||
|
||||
## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR.
|
||||
|
||||
Reference in New Issue
Block a user