- Gemini-adapter bakom AamosClient-interface (AAMOS_MODE=gemini) - Serversida/worker: hämtar bild, anropar Gemini, mappar mot canonical_ingredients - Kostnad/tokens bokförs i ai_usage_counters; global dagsbudget via BudgetStore - Redis-backed budget i worker, in-memory i tester - Migration 0019: ai_cost_usd_microcents - Hermetiska tester med inspelad fixture; separat pnpm eval:scan - docs/09 uppdaterad ärligt: AAMOS-status, Gemini-flöde, säkerhet/kostnad - REQUIRE_REAL=1 stödjer AAMOS_MODE=gemini; deploy-grind uppdaterad
6.2 KiB
Del 9 – AI-integration (AAMOS + Gemini-lärar-tier)
Uppdaterad 2026-08-08 efter scouting: AAMOS Core v1 är autentiseringsmässigt nåbar men saknar konfigurerad matmodell (
/v1/detectfaller tillbaka på YuNet ansiktsdetektering). Tills vidare används Gemini 2.5 Flash som lärar-tier för kylskåpsskanning, bakom sammaAamosClient-gränssnitt. AAMOS/prod rörs inte.
Appen når AI uteslutande via backend (beslut 2026-08-02). Mobilappen har aldrig direktkontakt och innehåller inga AI-hemligheter (spec §31, §61.13).
Kontraktet (packages/ai-contracts)
Appen definierar ett versionerat, Zod-validerat kontrakt per uppgiftstyp. Input valideras FÖRE nätverksanropet, output valideras EFTER – ett svar som bryter kontraktet behandlas som fel och når aldrig användardata. Modeller, prompts och leverantörer kan bytas fritt bakom kontraktet ("Food API ska få stabila kontrakt oavsett modell").
┌─────────┐ signed image URL ┌──────────┐ AamosClient ┌─────────────────┐
│ App │ ───────────────────→ │ Food API │ ───────────────→│ Worker adapter │
└─────────┘ └──────────┘ └─────────────────┘
│
┌──────────────────┬──────────┴──────────┐
│ AAMOS_MODE=http │ AAMOS_MODE=gemini │
│ HttpAamosClient │ GeminiAamosClient │
│ → AAMOS Core v1 │ → Gemini 2.5 Flash │
└──────────────────┴─────────────────────┘
createAamosClient() väljer adapter utifrån AAMOS_MODE. Inga anropare behöver
ändras. App→Food API→leverantörsgränsen är oförändrad.
AAMOS Core v1-status
Reella endpoints (ingen /v1/tasks fiktion):
POST /v1/detect POST /v1/verify POST /v1/compare
POST /v1/segment POST /v1/classify POST /v1/authenticate
POST /v1/score POST /v1/explain POST /v1/extract
POST /v1/track GET /v1/health
Scouting 2026-08-08 visade:
amos-core.servicepå server-2 anroparhttp://localhost:3207.- Värdport
3207ägs avaamos-identity-rust, inte AI-inferens. - AI-inferenscontainern
amos-ai-inference:latestexponerar värdport 3209. - Port mismatch gör att AAMOS Core aldrig når inferens.
- Även efter hypotetisk port-fix saknas
FOOD/GROCERY/VISION_MODELkonfiguration i.env.amos-core;/v1/detectdefaultar tillyunet.
Beslut: rör inte AAMOS-prod. AAMOS kan återaktiveras i framtiden när en
matmodell finns konfigurerad, via HttpAamosClient.
Gemini-lärar-tier (Skiva 1)
Aktiveras med AAMOS_MODE=gemini + GEMINI_API_KEY. Endast workern anropar
Gemini; API:et når aldrig nyckeln.
Hanterade uppgiftstyper
ANALYZE_FRIDGE_IMAGEANALYZE_PANTRY_IMAGE
Övriga task types (READ_RECEIPT, READ_NUTRITION_LABEL, etc.) svarar
failed i Skiva 1 och faller tillbaka på appens befintliga flöden.
Flöde
- App laddar upp bild → Food API skapar
scan_job(statusqueued). - Workern plockar jobbet, hämtar bilden från lagring (S3/mock).
GeminiAamosClientskickar bilden + svensk livsmedelsprompt tillgenerativelanguage.googleapis.com/v1beta/models/{GEMINI_MODEL}:generateContent.- Gemini svarar med JSON: produkt, varumärke, kvantitet, enhet, kategori, bäst-före/sista-förbruk (om läsbart), konfidens, imageQualityIssues.
- Workern mappar detekterade namn mot
canonical_ingredients(mjuk matchning). - Resultatet sparas i
scan_jobssomawaiting_confirmation. - Användaren granskar och bekräftar i appen. Aldrig auto-commit.
- AI är aldrig facit för allergener/näring — mjölkprincipen orörd.
Kostnadskontroll
scan_jobs.costUsdlagrar verklig kostnad per anrop.ai_usage_counters.ai_cost_usd_microcentsackumulerar månadskostnad per användare (utan PII).- Hushållskvoten
aiScansrespekteras (befintlig entitlements-logik). - Global dagsbudget
GEMINI_DAILY_BUDGET_USDviaBudgetStore. Workern använder Redis-backed budget; tester använder in-memory budget. När budgeten är förbrukad nekar adaptern nya anrop. - Loggning: status, latens, tokens, kostnad, taskType. Ingen bild, inget fritext, inga PII-fält.
Säkerhet
- Nyckeln finns i
.envpå workerservrar (SSM i produktion) och checkas aldrig in. - App/API validerar att
AAMOS_MODE=geminikräverGEMINI_API_KEYi produktion. REQUIRE_REAL=1i deploy-grinden gör att start failar om nyckel saknas.
Routing & specialister (framtida)
Skiva 2 kommer lägga premium-eskaleringsstier (Gemini Pro / GPT-4o / Claude) internt i adaptern vid låg konfidens, med eval/guldset som beslutar billig vs dyr modell. Fram till dess: Gemini 2.5 Flash för allt i Skiva 1.
Feedback → träning (Skiva 3)
Varje användarkorrigering i granska-flödet sparas som ai_corrections
(AI-utdata + korrigering + modell/promptversion + samtyckessnapshot).
Veckojobbet BUILD_TRAINING_SAMPLE exporterar endast rader där
anonymized_improvement = granted vid korrigeringstillfället; bilder kräver
separat image_training-samtycke. Personligt minne är aldrig träningsdata (§32).
Evals (spec §34)
pnpm test: hermetiska tester med inspelad Gemini-fixture, når aldrig nätet.pnpm --filter @app/worker eval:scan: live-eval mot litet guldset. Rapporterar precision, recall, kostnad, latens. KräverAAMOS_MODE=gemini+ nyckel.- Regel: ingen modell-/promptändring tas i produktion utan grön eval.
Lägen
AAMOS_MODE |
Användning |
|---|---|
mock |
dev/test utan nätverk. Produkten vägrar starta i mock. |
http |
Riktig AAMOS Core när matmodell finns. |
gemini |
Gemini 2.5 Flash som lärar-tier för kylskåpsskanning (Skiva 1). |