Files
Cibello-app/docs/09-aamos-integration.md
T
Claude 3ed12b274d docs(09): modell 2.5 Flash -> 3.5 Flash Lite (matcha koden)
Arkitekturdoc sa fortfarande Gemini 2.5 Flash; koden kor gemini-3.5-flash-lite. ASCII-boxen forkortad till 3.5 Flash for att halla radbredden. scale-batch.sh RORDES EJ (medvetet val?).
2026-08-17 18:44:43 +00:00

130 lines
6.4 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.
# 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 3.5 Flash Lite** 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 3.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 3.5 Flash Lite 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 3.5 Flash Lite som lärar-tier för kylskåpsskanning (Skiva 1). |