# 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/detect` faller tillbaka på YuNet > ansiktsdetektering). Tills vidare används **Gemini 2.5 Flash** som > lärar-tier för kylskåpsskanning, bakom samma `AamosClient`-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): ```text 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.service` på server-2 anropar `http://localhost:3207`. - Värdport `3207` ägs av `aamos-identity-rust`, inte AI-inferens. - AI-inferenscontainern `amos-ai-inference:latest` exponerar **värdport 3209**. - Port mismatch gör att AAMOS Core aldrig når inferens. - Även efter hypotetisk port-fix saknas `FOOD`/`GROCERY`/`VISION_MODEL` konfiguration i `.env.amos-core`; `/v1/detect` defaultar till `yunet`. **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_IMAGE` - `ANALYZE_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 1. App laddar upp bild → Food API skapar `scan_job` (status `queued`). 2. Workern plockar jobbet, hämtar bilden från lagring (S3/mock). 3. `GeminiAamosClient` skickar bilden + svensk livsmedelsprompt till `generativelanguage.googleapis.com/v1beta/models/{GEMINI_MODEL}:generateContent`. 4. Gemini svarar med JSON: produkt, varumärke, kvantitet, enhet, kategori, bäst-före/sista-förbruk (om läsbart), konfidens, imageQualityIssues. 5. Workern mappar detekterade namn mot `canonical_ingredients` (mjuk matchning). 6. Resultatet sparas i `scan_jobs` som `awaiting_confirmation`. 7. Användaren granskar och bekräftar i appen. Aldrig auto-commit. 8. AI är aldrig facit för allergener/näring — mjölkprincipen orörd. ### Kostnadskontroll - `scan_jobs.costUsd` lagrar verklig kostnad per anrop. - `ai_usage_counters.ai_cost_usd_microcents` ackumulerar månadskostnad per användare (utan PII). - Hushållskvoten `aiScans` respekteras (befintlig entitlements-logik). - Global dagsbudget `GEMINI_DAILY_BUDGET_USD` via `BudgetStore`. 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 `.env` på workerservrar (SSM i produktion) och checkas aldrig in. - App/API validerar att `AAMOS_MODE=gemini` kräver `GEMINI_API_KEY` i produktion. - `REQUIRE_REAL=1` i 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äver `AAMOS_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). |