Files
Cibello-app/docs/30-sökrobusthet-matvaror.md
T
Sven (AAMOS AI) c32a7e33c7
CI / Typecheck, test & build (push) Failing after 2s
ci: trigga på master + formatfix inför Gitea Actions
2026-08-13 17:25:14 +07:00

75 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sökrobusthet för matvaror i hushållslagret
> Målbild: användaren kan ställa en fritextfråga om vad som finns hemma och få ett svar som känns mänskligt, visar exakt lagring (FoodTwin) och ärligt berättar hur säker appen är utan att hitta på något.
## Befintliga motorer
### Sökmotor: `/v1/inventory`
- Enkel `ILIKE` mot `inventory_items.display_name` och `brand`.
- Inga synonymer, ingen fonetisk matchning, ingen felstavningstolerans.
- Filtrering på `storage_location_id`, `expiry_status`, paginering.
### Förbättrad sökmotor: `/v1/inventory/natural-search`
- Kombinerar `unaccent(...) ILIKE unaccent(...)` med PostgreSQL `pg_trgm`-similarity.
- Söker även mot kanoniska ingrediensnamn (`name_sv`, `name_en`).
- Sorterar på `GREATEST(similarity(...))`.
- Returnerar både strukturerade träffar och ett naturligt-språkligt svar.
### Trust-motor (`@app/inventory-engine`)
- `computeTrust(...)` ger `trustState` (`trusted`/`decaying`/`stale`/`unverified`) och `trustScore` 0100.
- Baserat på `confidence`, `verifiedByUser`, ålder och förruttnelseprofil.
- Används redan i `/v1/inventory` och vid skanning/konsumtion.
### FoodTwin-data
- `storage_locations`: namn, typ, sublocations.
- `inventory_items`: `storage_location_id`, `sublocation`, kvantitet, enhet, `trust_state`.
- `canonical_ingredients`: kanoniskt namn, synonymer, hållbarhetsriktlinjer.
## Svarsformat
`GET /v1/inventory/natural-search?q=mjölk&languageTag=sv-SE`
```json
{
"query": "mjölk",
"response": "Jag hittade **Mjölk** i Kylen (mellanmålshyllan). Jag är ganska säker på att den finns kvar.",
"items": [
{
"id": "...",
"displayName": "Mjölk",
"quantity": 1,
"unit": "LITER",
"locationName": "Kylen",
"locationType": "fridge",
"sublocation": "mellanmålshyllan",
"trustState": "trusted",
"trustScore": 95
}
]
}
```
## i18n
Server-sidan använder en minimal katalog i `apps/api/src/lib/inventorySearchResponse.ts`.
Stödja språk (12): sv, en, da, de, es, fi, fr, it, nb, nl, pl, pt.
Vid okänt språk faller vi tillbaka till engelska och sedan svenska.
## Hårda regler
1. **Inga påhittade fakta.** Om sublocation saknas visas inte "på hylla X".
2. **Trust-hedge måste matcha `trustState`.** `stale` ger en osäker formulering; `trusted` ger en trygg.
3. **Noll träffar** ska erkänna det och erbjuda att lägga till.
4. **Flera träffar** ska lista dem med lagring och peka på listan för trust-score.
## Nästa steg / öppna frågor
- Ska vi också söka i `canonical_ingredients.aliases` (array)? Kräver en `unnest`/`CROSS JOIN LATERAL` eller en trigram-index på en materialiserad vy.
- Ska vi lägga till fonetisk matchning (`fuzzystrmatch`) för vanliga felstavningar?
- Ska svaret också inkludera hållbarhetsstatus för träffarna?
- Behövs en separat vector/embedding-sökning för semantiska matchningar (t.ex. "mjölkprodukter")?