Impulse AI Docs
Intern dokumentasjon
Hopp til innhold

AI Pipeline

Dokumentasjon av Impulse AI sin AI-pipeline — fra workload-registrering og modellvalg til prompt-design og kostnadsovervaking. All AI-funksjonalitet drives av Anthropic Claude (via Vercel AI SDK) for tekstgenerering og Voyage AI for embedding-generering.

Arkitekturoversikt

heading.anchorLabel
apps/api/src/ai/
├── infrastructure/ # AI SDK, Anthropic-konfigurasjon, Voyage-klient
│ ├── ai-sdk.ts # executeWorkload() -- eneste chokepoint for alle AI-kall
│ ├── anthropic/
│ │ └── config.ts # Modell-IDer, priser, timeouts, token-grenser
│ ├── voyage/
│ │ ├── client.ts # Voyage AI HTTP-klient
│ │ └── embedding.ts # Embedding-tjeneste (generering + sok)
│ ├── access/ # Tier-validering + kostnadstaksjekk
│ ├── tracking/
│ │ ├── tracker.ts # trackUsage() -- brukssporing til ai_usage
│ │ └── fingerprint.ts # Prompt-fingerprinting + versjonsregistrering
│ └── safety/ # Innholdsvalidering
├── registry/
│ ├── workloads.ts # Konfigurasjon for registrerte workloads
│ └── types.ts # SubscriptionTier, WorkloadConfig, ModelTier
├── shared/
│ ├── prompt-builder.ts # PromptStructure DSL + buildPrompt()
│ ├── conventions.ts # Tone, vokabular, grammatikk, skrivestil
│ ├── concept-types.ts # Formula/Bottling-monstre
│ ├── person-context.ts # AI-personalisering (opt-in)
│ ├── static-labels.ts # Statiske stegnavn (fallback)
│ └── schemas/ # Zod-skjemaer (single source of truth)
├── impulses/
│ └── classification/ # Impulsklassifisering og anrikning
├── sessions/
│ ├── step-guidance.ts # 5-stegs veiledningsgenerering (batch + enkelt)
│ └── session-summary.ts # Oppsummeringsgenerering
├── check-ins/
│ └── assessment/ # Sjekk-inn AI-vurdering
└── insights/
├── pulse.ts # Pulsanalyse (rask regenerering)
├── narrative.ts # Narrativ innsikt (dypere analyse)
├── embedding-analytics.ts # Embedding-basert monstergjenkjenning
└── transformation-distillation.ts # Transformasjonsekstrakt

AI-konfigurasjon er sentralisert i apps/api/src/ai/infrastructure/anthropic/config.ts. Alle modell-tier defaulter til Claude Sonnet 4.6, med mulighet for override via miljøvariabler.

Tre modell-tier

heading.anchorLabel
TierStandard modellFormaalOverride-variabelDoppler-verdi
fastclaude-haiku-4-5Strukturert klassifisering der presisjon > prosekvalitetAI_MODEL_FASTclaude-haiku-4-5
balancedclaude-sonnet-4-6Brukervennlig kreativ tekst der sprakkvalitet ER produktetAI_MODEL_BALANCEDclaude-sonnet-4-6
qualityclaude-sonnet-4-6Hoyinnsats langform-innhold som krever dyp resonneringAI_MODEL_QUALITYclaude-sonnet-4-6

Alle tre miljøvariabler styres via Doppler (dev/stg/prd). Kode-default er Sonnet for alle tier — Haiku aktiveres via Doppler.

Konfigurasjon

heading.anchorLabel
export const AI_CONFIG = {
models: {
fast: process.env.AI_MODEL_FAST || 'claude-sonnet-4-6',
balanced: process.env.AI_MODEL_BALANCED || 'claude-sonnet-4-6',
quality: process.env.AI_MODEL_QUALITY || 'claude-sonnet-4-6',
},
tokenLimits: {
classification: 1024, // Impulsanrikning
guidance: 500, // Sesjonsveiledning
insight: 1500, // Innsiktgenerering
summary: 3000, // Sesjonsdokument
},
temperature: {
classification: 0.4, // Balansert for anrikningskvalitet
guidance: 0.7, // Moderat for naturlig sprak
creative: 0.8, // Hoy for dokumentgenerering
},
defaultTimeout: 30000, // 30 sekunder
longRunningTimeout: 60000, // 60 sekunder
maxRetries: 3,
}

Alle AI-kall gar gjennom executeWorkload() i ai-sdk.ts — det eneste chokepoint-et for AI-operasjoner. Workloads sender konfigurasjon direkte til executeWorkload().

Alle workloads

heading.anchorLabel
WorkloadKategoriModellMaks tokensTempKostnad/kall
classify_enrichmentimpulseSonnet4000.4~$0.006
classify_analyticalimpulseHaiku10240.2~$0.002
check_in_assesscheck_inSonnet5120.4~$0.006
batch_step_guidance_*sessionSonnet25000.8~$0.007
step_guidance_*sessionSonnet5000.8~$0.005
session_summary_*sessionSonnet8000.7~$0.012
insight_narrativeinsightSonnet2500.7~$0.006
pulseinsightSonnet2500.8~$0.005
transformation_distillationinsightSonnet1200.6~$0.005

Formula/Bottling — konseptuell integritet

heading.anchorLabel

Arkitektonisk separasjon av HVA (concept) fra HVORDAN (style) i prompt-design:

LagFormaalEndringsrisiko
Formula (Concept)Hva feltet betyr — essence, pakrevde elementer, forbudt driftLast — forretningskritisk moat
Bottling (Style)Hvordan det leveres — tone, formuleringTrygt a iterere
VariationFreshness — roterbare apninger, dedupliseringsreglerDynamisk

Definert i concept-types.ts, brukt i sesjonssteg-definisjonene (step-guidance.ts).

Impulsklassifisering

heading.anchorLabel

Nar en bruker fanger en impuls, kjores to AI-workloads asynkront via BullMQ:

1. Analytisk klassifisering (classify_analytical)

heading.anchorLabel

Strukturert analyse med classification, confidence, lag og omrader. Bruker fast-tier.

Output:

  • Classification (contraction/expansion) med confidence score
  • Primaert og sekundaert transformasjonslag
  • Relevante livsomrader med relevans-score
  • Innholdsvalidering (valid/low_confidence/gibberish)

2. Kreativ anrikning (classify_enrichment)

heading.anchorLabel

Brukervennlig tekst: tittel, sammendrag og sesjonshook. Bruker balanced-tier.

Output:

  • Tittel (3-8 ord)
  • Sammendrag (3-5 setninger, empatisk)
  • Sesjonshook (kort invitasjon til prosessering)

Begge resultater kombineres i impulses.ai_analysis JSONB-kolonnen.

Sesjonsveiledning

heading.anchorLabel

Steg-for-steg AI-veiledning (guidance)

heading.anchorLabel

Hver av de 5 sesjonsstegene far personlig AI-veiledning basert pa brukerens impuls.

Prompt-spesifikasjoner:

EgenskapVerdi
Lengde50-80 ord, 4-6 setninger
ToneVarm-direkte (“klok venn”)
StilFlytende prosa, ingen punktlister
TilnærmingInvitasjoner (“Legg merke til…”, “Kjenn…”) — IKKE kommandoer
SprakBrukerens sprakpreferanse eller detektert fra impulstekst

Forbudte monstre:

  • Sporsmaalstegn i veiledningstekst
  • Sjekklister eller sekvensielle instruksjoner
  • Klinisk/terapeutisk sprak
  • Tall, vurderinger, skalaer

Contraction-steg

heading.anchorLabel
StegFormaalKjernemekanisme
C1: FeelSomatisk bevissthetApent invitasjon til a kjenne kroppen
C2: OwnErkjenn energi-investering”Jeg innrommer at jeg nyter folelsen av a tenke at…”
C3: ShiftTilstand definerer virkelighet”Din tilstand definerer din virkelighet” (MA vaere med)
C4: EnvisionVisualiser ny tilstandKroppsforankring — forankre ny folelse i kroppen
C5: ReleaseSlipp og affirmerPersonlig affirmering + slipp gammel moenster

Expansion-steg

heading.anchorLabel
StegFormaalKjernemekanisme
E1: FeelKjenn intensjonenKroppen som sannhetsdetektor — baerer dette ekte energi?
E2: OwnKlar motivasjonApent sporsmaal “Hvorfor er dette viktig for deg?”
E3: ShiftTilstand definerer virkelighetIdentisk med C3 (bevisst designvalg)
E4: EnvisionIdentitetsvisjon”Se hvem du ER nar dette allerede er sant”
E5: ReleaseSlipp med tillitLosrivelse med overveldende selvtillit

Sesjonoppsummering (summary)

heading.anchorLabel

Etter fullfort sesjon genererer quality-tier en komplett oppsummering med:

  • Tittel og sammendrag
  • Utgangspunkt og ny forstaelse
  • Gjennombrudd (lista)
  • Neste steg (handlingsanbefalinger)
  • Steg-for-steg prosessgjennomgang
  • Refleksjon

Sjekk-inn vurdering

heading.anchorLabel

BE->DO->RECEIVE filosofi

heading.anchorLabel

Sjekk-inn-funksjonen (check_in_assess) vurderer brukerens navaerende tilstand basert pa BE->DO->RECEIVE-rammeverket:

  • BE (vaere): Endre indre tilstand
  • DO (gjore): Handle fra riktig tilstand
  • RECEIVE (motta): Motta det du onsker

Vurderingens jobb: Avsløre hva brukerens GJORING (DO) skaper i deres VAEREN (BE) — tilstanden de ikke kan se fordi de er inni den.

KlassifiseringFargeBeskrivelse
Positive.brandBrukeren er i en god tilstand
Contraction.classContractionSammentrekning oppdaget — kan konverteres til impuls
Expansion.classExpansionUtvidelse oppdaget — kan konverteres til impuls

Contraction/expansion-sjekk-inn kan konverteres til impulser via convertToImpulse-funksjonen, som kobler den nye impulsen til sjekk-innen via source_check_in_id.

Innsiktgenerering

heading.anchorLabel

Innsikter genereres i to faser:

Pulse (rask regenerering)

heading.anchorLabel

pulse.ts genererer raske oppdateringer nar nye impulser fanges. Bruker quality-tier.

Narrative (dypere analyse)

heading.anchorLabel

narrative.ts genererer dypere narrative innsikter basert pa embedding-analytics. Krever at impulse-embedding er ferdig for denne kjores (to-fase regenerering).

Embedding-basert analytikk

heading.anchorLabel

embedding-analytics.ts bruker Voyage AI embeddings og pgvector for:

  • Omradefordeling (hvilke livsomrader dominerer)
  • Lagfordeling (fysisk, emosjonell, mental, spirituell)
  • Balanse mellom contraction og expansion
  • Semantisk klynging av lignende impulser

Transformasjons-destillering

heading.anchorLabel

transformation-distillation.ts ekstra vekstmonstre fra fullforte sesjoner for dypere innsikter.

Embedding-arkitektur

heading.anchorLabel

Embedding-generering bruker Voyage AI (voyage-3-lite) for 512-dimensjonale vektorer.

EgenskapVerdi
Modellvoyage-3-lite
Dimensjoner512
Lagringpgvector vector(512)
LikhetsmatriseCosine similarity
Standard terskel0.7

Hva embeddes?

heading.anchorLabel
InnholdstypeTabellKolonne
Impulstekstimpulsesembedding
Sesjonsrefleksjon + nokkelfunnsessionsembedding
Sjekk-inn-innholdcheck_insembedding

To-fase regenerering

heading.anchorLabel

Nar en ny impuls fanges, kjores embedding og innsiktregenerering i sekvens:

  1. Embedding-fase: embedImpulse genererer vektor via Voyage AI
  2. Regen-fase: Narrative-innsikter regenereres ETTER embedding er komplett

AI SDK-integrasjon

heading.anchorLabel

Impulse AI bruker Vercel AI SDK (@ai-sdk/anthropic) som tynt lag over Anthropic API.

Hva AI SDK handterer

heading.anchorLabel
  • Zod-til-JSON-Schema konvertering
  • Responsvalidering mot skjema
  • Anthropic prompt caching (via cache_control pa system-meldinger)
  • Automatisk retry pa HTTP-feil (429, 500, 503)

Hva vi handterer selv

heading.anchorLabel
  • Timeout-retry: AI SDK retrier ikke pa AbortError — vi implementerer egen retry (2 ekstra forsok)
  • Auto-tracking: Nar tracking er satt i options, kalles trackUsage() automatisk med tokens, kostnad, varighet og fingerprint
  • Prompt fingerprinting: SHA-256 hash av system prompt + modell + temperatur + maxTokens — lagres med hvert kall
  • Versjonsregistrering: Forste gang en ny fingerprint dukker opp, lagres full konfig-snapshot i ai_workload_versions
  • Tier-validering: Sjekk av abonnement + kostnadstaksjekk for AI-tilgang
  • Cache-splitting: System prompts splittes i statisk (cached) og dynamisk (per-bruker) del
// Workload med cache-splitting og auto-tracking
const system = buildSplitPrompt(promptConfig); // { static, dynamic }
const result = await executeWorkload(OutputSchema, {
prompt: userPrompt,
system, // string eller { static, dynamic }
maxTokens: 500,
temperature: 0.7,
workloadType: 'check_in_assess',
tracking: {
userId,
impulseId,
metadata: (r) => ({
outcome: r.data.outcome,
contentLength: input.content.length,
}),
},
});

Prompt Caching

heading.anchorLabel

Anthropic tilbyr prompt caching som reduserer input-kostnaden med opptil 90% for gjentatte system-instruksjoner. Vi bruker dette med en cache-splitting arkitektur som separerer statisk og dynamisk innhold.

Hver AI-workload sitt system prompt splittes i to deler:

DelInnholdCaching
Statisk prefixRolle, konsepter, konvensjoner, eksempler, grammatikkreglerCached med cache_control: ephemeral (5 min TTL)
Dynamisk suffixPersonContext, impulsehistorikk, energiniva, temporaltAldri cached — varierer per bruker/request

Vercel AI SDK sender disse som to separate system-meldinger til Anthropic. Den statiske delen er identisk for alle brukere av samme workload-type, sa cache-treff er hoy.

prompt-builder.ts
export function buildSplitPrompt(config: PromptStructure): SplitSystemPrompt {
return {
static: buildPrompt({ ...config, personContext: undefined, dynamicContext: undefined }),
dynamic: renderDynamicParts(config), // personContext + dynamicContext
};
}

Cache-okonomi (5m TTL)

heading.anchorLabel
OperasjonPris vs. standard inputSonnet-pris per MTok
Standard input1.00x$3.00
Cache write1.25x (+25%)$3.75
Cache read0.10x (-90%)$0.30

Break-even: 2 requests med samme statiske prefix innen 5 minutter.

Cache auto-fornyes ved treff — med jevn trafikk utloper cachen aldri.

Adaptiv cache-aktivering

heading.anchorLabel

Ikke alle workloads har nok trafikk til a rettferdiggjore cache-write-premien. Modulen cache-strategy.ts sporer request-frekvens per workload-type og aktiverer caching kun nar det lonner seg.

StrategiWorkloadsOppforsel
alwaysCacheclassify_enrichment, classify_analytical, check_in_assessmentAlltid cachet — hoy frekvens, burst-monster
adaptivbatch_step_guidance_*, session_summary_*, pulse, narrative, distillationCacher nar >= 2 requests innen 5 min
neverCachename_validationAldri cachet — for sjelden og liten

Statisk/dynamisk split per workload

heading.anchorLabel
WorkloadStatisk (cached)Dynamisk (ikke cached)
EnrichmentKonsepter, eksempler, konvensjonerEnergeticLevel, priorContext
AnalyticalKlassifiseringskonsepterAvailableAreas
Check-inCHECK_IN_CONCEPTS, eksemplerImpulseHistory
Step Guidance5 steg-definisjonerPreviousGuidanceOpenings
Session SummarySUMMARY_CONCEPTS, konvensjoner(personContext via separat felt)
Pulse/Narrative/DistillationKonsepter, eksempler(personContext via separat felt)

Cache-metrikkene lagres i ai_usage-tabellen:

KolonneBeskrivelse
cache_read_tokensTokens lest fra cache (90% rabatt)
cache_write_tokensTokens skrevet til cache (25% premium)
service_tierAnthropic service tier (standard/priority/batch)
inference_geoGeografisk region for inferens
-- Cache hit rate per workload
SELECT
workload_type,
COUNT(*) as calls,
SUM(CASE WHEN cache_read_tokens > 0 THEN 1 ELSE 0 END) as cache_hits,
ROUND(100.0 * SUM(CASE WHEN cache_read_tokens > 0 THEN 1 ELSE 0 END) / COUNT(*), 1) as hit_rate_pct,
SUM(cache_read_tokens) as total_cached_tokens
FROM ai_usage
WHERE created_at > NOW() - INTERVAL '24 hours'
GROUP BY workload_type
ORDER BY calls DESC;

Kostnadsmodell

heading.anchorLabel

Priser per modell

heading.anchorLabel
ModellInput (per 1M tokens)Output (per 1M tokens)
claude-sonnet-4-6$3.00$15.00
claude-haiku-4-5$1.00$5.00

Estimert kostnad per brukerhandling

heading.anchorLabel
HandlingWorkloadsEstimert kostnad
Fange en impulsenrichment + analytical (parallelt)~$0.008
Sjekk-inncheck_in_assess~$0.006
Sjekk-inn med konverteringassess + enrichment + analytical~$0.014
Full sesjon (5 steg batch)batch_step_guidance + summary~$0.019
Impuls + full sesjonklassifisering + guidance + summary~$0.027
Innsiktregenereringnarrative + pulse + distillation~$0.016

Typisk aktiv bruker: ~$0.55/mnd (4-9% av revenue).

Cache-bevisst kostnadsberegning

heading.anchorLabel

calculateAICost() i ai-cost-service.ts tar hensyn til cache-metrikkene:

// Tokens fordeles pa tre kategorier med ulike priser
const standardInput = promptTokens - cacheRead - cacheWrite;
const inputCost = (standardInput / 1M) * pricing.input; // 1.00x
const cacheWriteCost = (cacheWrite / 1M) * pricing.input * 1.25; // 1.25x
const cacheReadCost = (cacheRead / 1M) * pricing.input * 0.10; // 0.10x

Kostnadsovervaking

heading.anchorLabel

All AI-bruk logges automatisk i ai_usage-tabellen (via auto-tracking i executeWorkload):

  • workload_type: Type operasjon
  • model: Modell brukt
  • prompt_tokens / completion_tokens: Tokenforbruk
  • cache_read_tokens / cache_write_tokens: Cache-metrikkene
  • estimated_cost: Cache-bevisst beregnet kostnad i USD
  • duration_ms: Tidsforbruk
  • prompt_fingerprint: Hash av prompt-konfigurasjon
  • service_tier: Anthropic service tier
  • inference_geo: Inferensregion
  • user_id, impulse_id, session_id: Kontekstkobling

Prompt-versjonering

heading.anchorLabel

Tabellen ai_workload_versions lagrer en konfig-snapshot forste gang en ny fingerprint dukker opp. Dette gir sporbarhet uten manuell versjonering:

-- Se versjonshistorikk for et workload
SELECT fingerprint, first_seen, model
FROM ai_workload_versions
WHERE workload_type = 'classify_enrichment'
ORDER BY first_seen DESC;
-- Se nar en prompt-endring ble deployet
SELECT prompt_fingerprint, count(*), min(created_at)
FROM ai_usage
WHERE workload_type = 'guidance'
GROUP BY prompt_fingerprint;

Cache-ytelse (verifisert apr 2026)

heading.anchorLabel

Malinger fra staging med reelle brukerdata viser faktisk besparelse per workload-type:

WorkloadUten cacheMed cache-hitBesparelseCachede tokens
pulse$0.0122$0.005456%~2 695 av ~3 700
classify_enrichment$0.0127$0.005656%~2 495 av ~3 060
insight_narrative$0.0139$0.006851%~2 803 av ~4 000
session_summary_*$0.0177$0.010242%~2 659 av ~3 560
batch_step_guidance_*$0.0198$0.013631%~2 842 av ~3 500
classify_analytical (Haiku)$0.0040$0.00400%Under Haiku-minimum

System-promptene utgjor 70-82% av total prompt og er identiske pa tvers av brukere. Cache-write skjer pa forste kall, etterfølgende kall innen 5 min far cache-read (90% rabatt).

Observert write/read-kjede (staging)

heading.anchorLabel
17:52:06 batch_step_guidance cache_write=2842 cost=$0.023
17:53:17 batch_step_guidance cache_read=2842 cost=$0.013 (71s senere)
17:53:33 batch_step_guidance cache_read=2842 cost=$0.014 (87s senere)

Skaleringseffekt

heading.anchorLabel

Cache-hitrate oker med brukervolum (flere samtidige brukere = varmere cache):

SkalaCache-hitrate (est.)AI-kostnad/bruker/mndAI % av revenueArlig besparelse vs. uten cache
Uten cache0%$1.2016.9%
1 000 brukere~50%$0.9513.4%~$3 000
5 000 brukere~75%$0.8311.7%~$22 000
10 000 brukere~85%$0.7710.9%~$50 000

Rate Limiting

heading.anchorLabel

AI-bruk begrenses per bruker basert pa abonnementstier:

EgenskapVerdi
HTTP rate limit100 req/min (global), 20 req/min (AI-endepunkter)
ImpulskvoterTelles via impulse-quota-service mot subscription_config

Kvoter for impulsfangst og sjekk-inn konfigureres via subscription_config-tabellen.