Files
Cibello-app/docs/30-sökrobusthet-matvaror.md
T
Sven (AAMOS AI) 9197d93a92 feat(inventory): naturlig-språklig fritextsökning med FoodTwin-fakta, trust-hedge och i18n ×12
- Nytt endpoint GET /v1/inventory/natural-search.
- Robust matchning med unaccent + pg_trgm similarity mot display_name,
  brand och kanoniska ingrediensnamn (sv/en).
- Svar byggs deterministiskt från faktisk data: lagringsplats + sublocation
  om registrerad, trust-state-hedge från befintlig trust-motor.
- Server-sidan i18n-katalog för 12 språk.
- Tester för svensk träff och noll-träff på flera språk.
- Design-dokument docs/30-sökrobusthet-matvaror.md.
2026-08-08 05:53:06 +07:00

71 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")?