8.5 KiB
Del 28 – Lärande-loop (ai_corrections → ai_training_bank)
Ingen AI är facit. Varje skanning där användaren granskar förslag blir ett träningsexempel — om hon samtycker. Detta dokument beskriver datakontraktet, samtyckesgätning och GDPR-radering.
Översikt
App → skanna → worker → AI-förslag → app (awaiting_confirmation)
↓
användaren granskar varje item
↓
POST /v1/scans/:id/confirm
↓
ai_corrections (ett rad per item)
↓
BUILD_TRAINING_SAMPLE (scheduler, 1×/vecka)
↓
ai_training_bank (cibello-ägt dataset)
ai_training_bank är den consenteda platsen för rikare data
(bildreferens, förslag, korrigering). Analytics får aldrig innehålla PII
eller råa bilder (se §56/§58).
Datakontrakt per skanning
Varje rad i ai_corrections representerar ett item från en skanning:
| Fält | Innehåll |
|---|---|
scanJobId |
Källskanningen (scan_jobs.id). |
taskType |
T.ex. ANALYZE_FRIDGE_IMAGE, READ_RECEIPT. |
aiOutput |
Hela AI-raw-resultatet från scan_jobs.result. |
proposal |
Det specifika AI-förslag item:et kom från (detectedName, canonicalIngredientId, brand, estimatedQuantity, unit, bestBeforeDate, confidence, requiresConfirmation). |
userCorrection |
{ action: "accept" | "edit" | "reject" | "add", corrected?: {...} } |
corrected (inbäddad) |
Användarens slutgiltiga värden vid accept/edit/add: displayName, canonicalIngredientId, brand, quantity, unit, bestBeforeDate, useByDate. |
imageS3Key |
Första lagrade bildnyckeln från skanningen, endast om image_training-samtycke fanns vid bekräftelsen. Annars null. |
modelVersion / promptVersion |
Vilken modell och prompt som producerade förslaget. |
consentSnapshot |
{ anonymized_improvement: "granted"|"denied", image_training: "granted"|"denied", ... } som JSON vid bekräftelsetillfället. |
createdAt |
Tidsstämpel för bekräftelsen. |
Åtgärder som sparas
accept— positivt exempel. AI-förslaget var korrekt nog att användaren accepterade det oförändrat.edit— användaren ändrade något (namn, kvantitet, enhet, datum …).add— AI missade item:et helt; användaren lade till det manuellt.reject— AI hittade något som inte finns; användaren kastade det.
Alla fyra åtgärder sparas. Bara accept/edit/add leder till att ett
inventory_items-rad skapas; reject gör det inte.
ai_training_bank
När BUILD_TRAINING_SAMPLE kör (veckoschema i worker) bankas rader med
anonymized_improvement = granted till ai_training_bank:
| Fält | Innehåll |
|---|---|
correctionId |
Referens till ai_corrections.id (cascade delete). |
scanJobId |
Källskanningen. |
version |
Dataset-version, t.ex. v1. Bumpar när formatet ändras. |
taskType |
Samma som källan. |
imageS3Key |
Kopierad från ai_corrections.image_s3_key (kan vara null). |
proposal |
AI-förslaget för just det item:et. |
action |
Användarens åtgärd. |
corrected |
Slutgiltiga värden, eller null vid reject. |
modelVersion / promptVersion |
Spårbarhet till modell/prompt. |
consentSnapshot |
Kopia av samtyckesläget. |
exportedAt |
När raden bankades. |
Banken ägs av cibello och är versionerad. Ingen extern leverantör
anropas under exporten — jobbet får aldrig kasta på grund av att
AAMOS_MODE=gemini saknar EXPORT_TRAINING_SAMPLE-stöd.
Samtycke
Två separata samtycken styr vad som sparas och var:
anonymized_improvement— krävs för att överhuvudtaget banka tillai_training_bank. Utan detta lämnasai_correctionskvar men raderna exporteras inte.image_training— krävs för attimageS3Keyska sparas. Utan samtycke sparas endast textparet (proposal,corrected) ochimageS3Keyärnull.
Samtyckessnapshoten sparas per rad så att framtida ändringar av användarens samtycke inte påverkar redan bankade data.
Retention
ai_corrections: behålls så länge användarkontot finns. Underlättar support och debugging.ai_training_bank: behålls så länge användarkontot finns, om inte användaren återkallar samtycke — då raderas endast rader därconsentSnapshot.anonymized_improvement = "denied"(i praktiken exporteras de aldrig).- Träningsbilder (
image_s3_key): raderas senast 90 dagar efter att de bankats tillai_training_bank, om användaren inte aktivt valt att spara sina bidrag längre. För användare som samtycker till långtidslagring (t.ex. för att förbättra modellen över tid) kan bilderna behållas så länge kontot finns, men aldrig längre än vad användaren samtyckt till. Vid återkallatimage_training-samtycke raderas bilderna inom 30 dagar. - Bilder som endast ingår i råa
scan_jobs(inte bankade som träningsdata): raderas enligt samma 90-dagarspolicy eller när skanningen tas bort, beroende på vilket som inträffar först.
GDPR / kontoradering
DELETE /v1/me soft-deletar (anonymiserar) users-raden för att
bevara referensintegritet i aggregat. Därför fyras inte FK-cascade
från users till ai_corrections eller scan_jobs. Istället sker
raderingen explicit:
- Saml alla distinkta bildnycklar för användaren:
ai_corrections.image_s3_keyai_training_bank.image_s3_key(via join motai_corrections)scan_jobs.s3_keys
- Radera varje nyckel i objektlagring med
storage.deleteObject. S3-fel loggas och påverkar inte fortsatt radering. - Radera
ai_correctionsföruserId.ai_training_bankförsvinner automatiskt viacorrection_id ON DELETE CASCADE. - Radera
scan_jobsföruserId(även denna cascade fyrar inte vid soft-delete). - Fortsätt med hård radering av övrig persondata och anonymisera användarposten.
Verifiera alltid att kontoraderingstestet kontrollerar både
ai_corrections, ai_training_bank, scan_jobs och att inga
överblivna bildnycklar finns kvar i S3/mock-lagringen.
Inget PII i analytics
Träningsdatan (rikare bild+förslag+korrigering) finns endast i
ai_corrections/ai_training_bank under samtycke. Analytics-events som
AI_CORRECTED innehåller endast scanJobId, taskType och field
(åtgärd), aldrig bilder, namn eller detaljerade värden.