AI Quality Measurement
System for a male om AI-outputen er variert (ikke-repeterende) og relevant (forankret i brukerens faktiske innhold). Bygger pa eksisterende Voyage-embeddings og dekker alle 8 brukervendte AI-workloads.
For prompt-arkitektur, se AI Prompt DSL. For workload-oversikt, se AI Pipeline.
Hva vi maler
heading.anchorLabelTo uavhengige kvalitetsdimensjoner:
| Dimensjon | Sporsmal | Metode | Bra score |
|---|---|---|---|
| Variasjon | Gjentar AI-en seg for samme bruker? | Cosine similarity mellom navaerende og forrige output | Lav (< 0.65) |
| Relevans | Er outputen forankret i brukerens input? | Cosine similarity mellom output og brukerens tekst | Hoy (> 0.55) |
Arkitektur
heading.anchorLabelexecuteWorkload() → AI output ↓ measureOutputQuality() ← fire-and-forget, blokkerer aldri ↓ 1. Embed output (Voyage) 2. Hent forrige embedding (same user + workload + key) 3. Beregn variation score 4. Beregn relevance score 5. Lagre i ai_quality_scoresIntegrasjonspunkt: En hook i executeWorkload() (apps/api/src/ai/infrastructure/ai-sdk.ts). Workloads legger til quality: { userId, inputText } i options.
Kostnad: ~$0.000003 per maling. Neglisjerbart — dekkes av Voyage gratis-kvote opp til ~5000 brukere.
Database: ai_quality_scores
heading.anchorLabel| Kolonne | Type | Beskrivelse |
|---|---|---|
workload_type | text | Hvilken AI-workload (check_in_assess, pulse, batch_step_guidance_contraction, etc.) |
workload_key | text | Sub-nokkel for batch-workloads (step_1..step_5). Null for single-output |
variation_score | float | Cosine similarity til forrige output for samme bruker+workload. 0.0 = helt ulik, 1.0 = identisk. Lavere = bedre. Null = forste gang |
variation_bucket | text | excellent / good / acceptable / low / repetitive |
relevance_score | float | Cosine similarity mellom output og brukerens input. 0.0 = ingen sammenheng, 1.0 = perfekt. Hoyere = bedre. Null = ingen input |
relevance_bucket | text | excellent / good / weak / generic |
prompt_fingerprint | text | Hash som kobler til ai_workload_versions for prompt-versjon |
output_embedding | vector(512) | Voyage-embedding av AI-outputen |
input_embedding | vector(512) | Voyage-embedding av brukerens input |
session_id | uuid | Kobling til sesjon (nullable) |
impulse_id | uuid | Kobling til impuls (nullable) |
check_in_id | uuid | Kobling til sjekk-inn (nullable) |
Bucket-terskler
heading.anchorLabelVariasjon (lavere = bedre):
| Score | Bucket | Tolkning |
|---|---|---|
| 0.00 - 0.50 | excellent | Svart ulik forrige — sterk variasjon |
| 0.50 - 0.65 | good | Merkbart ulik — sunt |
| 0.65 - 0.75 | acceptable | Noe likhet, innenfor toleranse |
| 0.75 - 0.85 | low | Bekymringsverdig — dedup kan svikte |
| 0.85 - 1.00 | repetitive | Nar-identisk — undersok |
Relevans (hoyere = bedre):
| Score | Bucket | Tolkning |
|---|---|---|
| 0.70 - 1.00 | excellent | Dypt forankret i brukerens innhold |
| 0.55 - 0.70 | good | Tydelig relatert til brukerens input |
| 0.40 - 0.55 | weak | Lest tilknytning — kan kjennes generisk |
| 0.00 - 0.40 | generic | Uforankret — undersok prompten |
Dekning
heading.anchorLabelAlle 8 brukervendte workloads har quality measurement:
| Workload | Trigger | Input for relevans |
|---|---|---|
classify_enrichment | Impuls opprettet | Impulstekst |
batch_step_guidance_* | Sesjon startet | Impulstekst (5 per-step scores) |
session_summary_* | Sesjon fullfort | Impulstekst |
check_in_assess | Sjekk-inn opprettet | Sjekk-inn-tekst |
pulse | Bakgrunns-regen | Nyeste moment-tekst |
insight_narrative | Bakgrunns-regen | Nylige impulstekster |
transformation_distillation | Bakgrunns-regen | Cluster-breakthroughs |
Anti-repetisjonsmekanismer
heading.anchorLabelQuality-systemet maler effekten av 6 eksisterende mekanismer i prompt-arkitekturen:
- Variation-lag (
concept-types.ts):openingApproaches+deduplicationInstructionpa hvert session-steg - previousGuidanceOpening dedup: Forrige sesjon sin apningssetning sendes som negativ eksempel
- Produktgrense-separasjon: Pulse, Narrative og Transformations har gjensidig
forbiddenDrift - ACKNOWLEDGMENT.variety: Variasjonskrav i alle workloads via conventions
- WRITING_STYLE bans: 22 forbudte AI-ord + forbudte strukturer
- Temperature 0.8: Statistisk variasjon for sessions og pulse
Nyttige sporringer
heading.anchorLabelSiste 20 scores
heading.anchorLabelSELECT workload_type, workload_key, round(variation_score::numeric, 3) as variation, variation_bucket, round(relevance_score::numeric, 3) as relevance, relevance_bucket, created_atFROM ai_quality_scores ORDER BY created_at DESC LIMIT 20;Gjennomsnitt per workload (siste 30 dager)
heading.anchorLabelSELECT workload_type, count(*) as scores, round(avg(variation_score)::numeric, 3) as avg_variation, round(avg(relevance_score)::numeric, 3) as avg_relevanceFROM ai_quality_scoresWHERE created_at > now() - interval '30 days'GROUP BY workload_typeORDER BY avg_variation DESC;Brukere med lav variasjon (siste 7 dager)
heading.anchorLabelSELECT user_id, workload_type, count(*) as repetitive_countFROM ai_quality_scoresWHERE variation_bucket IN ('low', 'repetitive') AND created_at > now() - interval '7 days'GROUP BY user_id, workload_typeHAVING count(*) >= 3ORDER BY repetitive_count DESC;Prompt-versjon-sammenligning
heading.anchorLabelSELECT prompt_fingerprint, count(*) as scores, round(avg(variation_score)::numeric, 3) as avg_variation, round(avg(relevance_score)::numeric, 3) as avg_relevanceFROM ai_quality_scoresWHERE workload_type = 'check_in_assess'GROUP BY prompt_fingerprintORDER BY avg_relevance DESC;Filstruktur
heading.anchorLabelapps/api/src/ai/quality/├── buckets.ts # Score → bucket klassifisering├── extract.ts # Tekst-ekstraksjon fra strukturerte AI-outputs├── measure.ts # Kjernelogikk: embed → sammenlign → lagre└── index.ts # Public API + QualityConfig typeDesigndokument
heading.anchorLabelKomplett designdokument med kostnadsanalyse, rollout-plan, og fremtidige dashboards: docs/design/ai-quality-measurement-system.md