Foto: Umberto / Unsplash

Del plattformen · kapittel 5

Teknologi og arkitektur

Teknologivalgene, de to parallelle dataarkitekturene og hvorfor begge finnes - med et konkret eksempel på hva den nyeste av dem gjør mulig.

Teknologivalgene

Portalen er bygget av én person. Det har styrt valgene mer enn noe annet: hvert verktøy må kunne læres, driftes og feilsøkes uten et team i ryggen. Der et stort miljø kan bære en spesialisert løsning, må dette prosjektet velge det som er godt nok og godt dokumentert.

Teknologivalg per lag, med begrunnelse
LagValgHvorfor
NettstedetNext.js med TypeScriptSidene bygges ferdig på forhånd, så en leser får statiske filer framfor å vente på at en database svarer. Typene fanger opp at en datafil har endret form.
UtseendeTailwind med egne fargeverdierVerdiene bor ett sted og brukes ved navn, slik at mørk modus og kontrastjusteringer kan gjøres samlet.
GraferRechartsGir kontroll over farger og etiketter, og lar hver graf ha en tabellutgave.
DatahentingPythonKildene har hvert sitt format. Python har verktøyene for å hente, rydde og skrive ut resultatet i en form nettstedet kan lese.
DatalagerDatabricks med Unity CatalogRådata lagres uendret og versjonert, og alle bearbeidingssteg er sporbare. Der ligger også AI-funksjonene som brukes i selve databehandlingen.
TransformasjondbtHvert steg fra rådata til ferdig tabell er en dokumentert og testet datamodell, ikke et skript noen kjørte en gang.
Lagring for nettstedetSupabasePoengsummer fra statistikkspillet og henvendelser. Lite data, enkle behov.
PubliseringNetlifyLegger ut de ferdigbygde sidene. Publisering skjer på kommando, ikke ved hver endring.
AutomatiseringGitHub ActionsKjører de 35 faste jobbene som holder portalen i gang.

To dataarkitekturer, ikke én

Portalen har to måter å behandle data på. Det er verdt å si rett ut, fordi det ellers ser ut som rot.

Den enkle veien er ett stort Python-program med én funksjon per datafil. Det henter fra kildene, rydder tallene og skriver dem som datafiler nettstedet leser når det bygges. Den driver nesten alle sidene. Datalageret tar imot de vanskelige kildene, lagrer dem før de tolkes, og bearbeider dem i testede steg.

DEN ENKLE VEIENdriver nesten alle sidene i dagKildeProgram rydderDatafil i sidenDATALAGERETfor de vanskelige kildeneKildeRådata lagresTestede steg
De to lever side om side og møtes på to punkter. Den enkle veien kom først og er rask og lett å forstå; datalageret er tyngre å sette opp, men det eneste som duger når kilden er vanskelig.

De to er ikke helt adskilt. Den ukentlige datajobben i den enkle veien leser de ferdige tabellene om arbeidsavklaringspenger og uføretrygd ut av datalageret og skriver dem som datafiler, på samme måte som tall fra et API. Feiler lesingen, beholdes forrige datafil. Chatten om de samme ytelsene spør datalageret direkte, uten å gå veien om en fil. Resten av datalageret når ikke portalen i dag.

Grunnen til at begge finnes er ærlig nok: den enkle veien kom først og virker godt nok for det den gjør. Å skrive om alt til den nye ville kostet mye og gitt leseren ingenting. Nye og vanskelige kilder bygges på den nye, og på sikt kan den ta over. Prisen er at noe gjøres to ganger: renter, valuta og foretaksdata hentes daglig inn i datalageret uten at noe der leses videre, mens portalen henter de samme tallene selv.

Hva et datalager er

Kapittel 1 sa kort hva et datalager er: data fra mange kilder samlet i sin opprinnelige form, med en katalog over hva som finnes og hvor hvert tall kom fra. Det som gjør den formen verdt bryet, er det neste.

Den viktige forskjellen er at ingenting tolkes før det er lagret. Det som kommer inn, lagres slik kilden leverte det, og de bearbeidede utgavene regnes ut fra det i egne steg framfor å rettes på plass. Oppdager vi at en beregning var feil, retter vi oppskriften og kjører stegene om igjen. Det er derfor et tall kan spores tilbake til kilden sin.

To forbehold hører med. Rådataene er ikke et arkiv: for tabellene fra SSB, rente- og valutaseriene og konkurslista erstattes innholdet ved hver henting, mens NAVs notater og de daglige tellingene av foretak legges til og blir liggende. Og ikke alt bygges på nytt hver gang. Stegene der en språkmodell leser dokumenter, behandler bare nye dokumenter, fordi hvert kall trekker fra en begrenset kvote. Fram til september 2026 manglet de den begrensningen og leste alle notatene på nytt ved hver kjøring. Den måneden var kvoten brukt opp på åtte dager. Retter vi tolkningen der, må vi be om en full omkjøring med vilje.

Prisen er at det er tyngre å komme i gang enn å hente et tall rett fra et API og skrive det inn på en side. Det er nettopp derfor portalen har to dataarkitekturer og ikke én: den enkle veien bærer fortsatt det meste, og datalageret brukes der det faktisk gir noe den enkle veien ikke kan.

Lagdelingen: rå, ryddet, ferdig

I datalageret går tallene gjennom navngitte lag, og hvert lag har én jobb. Regelen er at innhentingen ikke regner og ikke tolker. Den velger hvilke tabeller og inndelinger som skal hentes, og avviser data med feil form, men det som kommer inn, lagres som det kom. All logikk ligger i stegene etterpå, der den kan leses, testes og kjøres om igjen.

01 RÅDATASlik kilden publiserte det.Aldri redigert.02 RYDDET17 datamodeller. Kolonnenavnog datatyper gjort ensartede.03 BEARBEIDET15 datamodeller. Her skjerregnearbeidet, og her tolkesdokumentene.04 FERDIG6 datamodeller. Tabellene altannet leser fra.
Ingenting tolkes ved innhenting. Det som kommer inn, lagres som det kom, og all logikk ligger i steg som kan leses, testes og kjøres om igjen.

Et ord om ordet: en datamodell er en oppskrift på hvordan én tabell regnes ut fra en annen. Den har ingenting med en språkmodell å gjøre, som er det vi mener når vi skriver om AI lenger ned. Vi skriver alltid ut hele ordet, nettopp fordi de to ellers glir sammen.

Til sammen 38 datamodeller. Alle har en beskrivelse og minst én automatisk test, men testene er ujevnt fordelt: de fleste sjekker at et felt ikke er tomt eller har en gyldig verdi, og én at summen av delene stemmer med totalen. Tallene språkmodellen henter ut av NAVs notater, har ingen test i datalageret som sier fra om et urimelig tall.

Avhengighetsgraf med tre ryddede tabeller til venstre som peker inn i én ferdig tabell i midten, og videre til en nøkkeltallsvisning til høyre. Hvert kort lister kolonnene i tabellen.
Veien én tabell tar gjennom datalageret: tre ryddede tabeller slås sammen til én ferdig tabell, som igjen gir nøkkeltallene. Hvert steg har en beskrivelse og minst én test som sier fra hvis et tall blir urimelig.

Et eksempel: fra PDF til tall

NAV har i mange år publisert notater om arbeidsavklaringspenger, kvartalsvis fram til 2022 og som årsnotat siden. De inneholder tall som er verdt å følge over tid - hvor mange som mottar ytelsen, hvilke diagnoser som dominerer, hvordan utviklingen går. Notatene er PDF-er. Vil du se utviklingen over ti år, må du åpne dusinvis av dokumenter og skrive av tallene for hånd.

Her gjør datalageret noe den enkle veien ikke kan: en språkmodell leser dokumentet i selve databehandlingen, henter ut de konkrete tallene i strukturert form, og skriver i tillegg et kort sammendrag på norsk. Resultatet er én rad per notat, i en tabell du kan spørre på tvers av.

Det interessante er ikke at det virker, men hva det krevde. Notatene bruker to ulike definisjoner av «antall» om hverandre: de som mottar ytelsen, og det bredere antallet registrert med nedsatt arbeidsevne. Forskjellen er titusener av mennesker. En tolkning som blander dem, gir et tall som ser riktig ut og er feil. Å lære tolkningen å skille konsekvent var mer arbeid enn å få den til å lese dokumentet i det hele tatt.

Målet er at tall tolkningen ikke klarer å lese sikkert, blir stående tomme framfor å bli gjettet. Det holder ikke alltid. Andelen kvinner blant mottakerne av uføretrygd kom ut som rundt tolv prosent i en rekke notater, mens den reelle andelen ligger nær seksti. Tolkningen hadde plukket en andel av befolkningen framfor av mottakerne. Tallet hadde etikett, periode og kilde som alle andre, og ble først oppdaget da noen testet portalens verktøysett for agenter. Nå forkastes verdier som ikke kan være en andel av mottakerne, og den samme påstanden fjernes fra sammendragene. Et hull er ærlig. Et gjettet tall i en statistikkportal er det ikke, og det ser ut akkurat som et riktig. Hva som faktisk kontrolleres i tekst skrevet av en språkmodell, står i kapitlet om drift.

Resultatet når portalen ved at den ukentlige datajobben leser den ferdige tabellen og skriver den som en datafil. Kapitlet om erfaringer går nærmere inn på hva slikt arbeid faktisk koster.

Flere flater mot de samme tabellene

Når de ferdige tabellene først ligger der, kan flere ting lese dem. Portalen er den mest synlige flaten, men ikke den eneste - og heller ikke den første.

Et spørreverktøy på norsk

En egen app, som kjører utenfor datalageret, der du stiller spørsmålet i vanlig språk og får både spørringen og svaret tilbake som tabell. Den er lesetilgang bare, med en øvre grense på hvor mye den kan hente. Dette var faktisk prosjektets aller første del, bygget før portalen fantes.

Oversikter over datalageret

Sammendrag og oversiktsvisninger som leser de samme ferdige tabellene, blant annet et automatisk skrevet sammendrag av hva hver datakilde inneholder.

Spørsmål i vanlig språk

Egne rom der man kan spørre om tallene på norsk uten å kunne spørrespråk. Chatten på portalen bruker begge, bak passord.

Portalen selv

Sidene du leser nå. To av dem, om arbeidsavklaringspenger og uføretrygd, viser tall fra de ferdige tabellene, og chatten om de samme ytelsene spør dem direkte. Resten av portalen henter tallene sine utenom datalageret.

Poenget er at grunnarbeidet gjøres én gang. Å tolke ti år med dokumenter er dyrt; å lese den ferdige tabellen fra en ny flate er nesten gratis. Det er hele begrunnelsen for å ha et datalager framfor å hente rett til hver enkelt visning.

Hva gratisversjonen setter grenser for

Datalageret kjører på gratisversjonen av plattformen. For et prosjekt med én person og uten inntekter er det et bevisst valg, og vilkåret om at den ikke skal brukes kommersielt, passer portalen. Prisen er et sett grenser. Noen av dem stopper det vi gjerne ville bygget videre, andre gjør bare driften skjørere. Grensene er sjekket mot leverandørens oversikt og egne målinger i september 2026.

Stopper videre utvikling

GrenseHva det betyr for oss
Kunnskapsassistenten støttes ikke, og søketjenesten mangler direkte vektortilgangDen ferdige kunnskapsassistenten over NAVs notater kan ikke brukes. Semantisk søk måtte i så fall bygges for hånd, og det er ikke prøvd. I dag besvares spørsmål om hva notatene skriver, med tekstsøk.
Funksjoner i datalageret kom ikke ut på internett da vi prøvdeEt verktøy som slår opp live i SSB, kan ikke bygges som funksjon slik kontoen er satt opp i dag. Navneoppslag virket, men tilkoblingene ut ga tidsavbrudd mot alle adressene vi prøvde.
Utgående internett er begrenset, og kontoinnstillingene er stengtLeverandøren oppgir at en konto som er verifisert med LinkedIn, får utgående internett, men om det også gjelder funksjonene, er ikke prøvd. Andre innstillinger på kontonivå kan ikke endres.
Fordeleren mellom spørrerommene var låst til én språkmodell, og den var ikke tilgjengeligEn ferdig agent som skulle sende hvert spørsmål til riktig rom, kom aldri i drift. Chatten på portalen avgjør selv hvilket rom som skal spørres.
Høyst tre apper, og de stoppes etter et døgnEn egen tjener for agentverktøy kan ikke kjøre fast inne i datalageret.

Gjør driften skjørere

GrenseHva det betyr for oss
Rettferdig bruk uten oppgitt tak. Går forbruket over, stenges all beregning resten av dagen, i verste fall resten av månedenInnhenting, datamodeller og spørsmål i datalageret stopper samtidig. Det har skjedd to ganger på to måneder. I slutten av august sto en automatisk overvåking ingen hadde slått på, for en del av forbruket. I september var overforbruket vårt eget: stegene som lar en språkmodell lese NAVs notater, leste alle notatene på nytt ved hver kjøring. Begge gangene viste sidene som bygger på datalageret, tallene fra forrige henting. Taket er ikke oppgitt, så det kan bare leses av i ettertid.
Ett SQL-lager i minste størrelse, som ikke kan endresStopp etter ti minutter uten bruk er låst. Hver gang lageret vekkes, står det oppe i minst ti minutter, så mange små og spredte spørsmål koster mer enn noen få store.
Funksjoner som slås på av seg selvAutomatisk kvalitetsovervåkning og målejobber for sporing kom uten at noen ba om dem, og brukte om lag to femtedeler av beregningen i august. De må oppdages og slås av for hånd.
Høyst fem jobbsteg samtidigJobbene i datalageret kan ikke kjøre mange steg samtidig. Det har ikke vært en flaskehals hittil, fordi det meste av innhentingen kjører utenfor datalageret.

Virker likevel

HvaHvorfor det betyr noe
Spørsmål i vanlig språkDriver chatten om arbeidsavklaringspenger og uføretrygd.
Styrte nøkkeltallEt nøkkeltall kan defineres én gang og leses likt av flatene i datalageret.
Språkmodeller i selve databehandlingenLeser NAVs PDF-er og henter ut tallene, som i eksemplet lenger opp.
Notatbøker med internettInnhentingen som kjører inne i datalageret, når SSB denne veien.
Tilkoblinger til agentverktøy over nettInnstillingen finnes, så datalageret kan kobles til et verktøy som ligger utenfor, med nøkkel. Den er ikke prøvd ende til ende, men er den gjenstående veien for live oppslag.

Hva det betyr i praksis, ble tydelig da vi ville la en agent i datalageret slå opp direkte i SSBs statistikkbank. Notatbøkene når SSB, men de kjører som planlagte jobber, ikke som noe en agent kan kalle midt i et svar. Funksjonene, som kan kalles slik, kom ikke ut på nett, og en egen tjener inne i datalageret stoppes etter et døgn. To veier står igjen: å verifisere kontoen og se om funksjonene da når ut, eller et verktøy som ligger utenfor og som datalageret kobler seg til. Ingen av dem er prøvd ennå.

Hvorfor utleggingen er et bevisst valg

De fleste nettsteder legges ut på nytt hver gang koden endrer seg. Dette gjør ikke det, og det er med vilje. Verken en kodeendring eller en datajobb som skriver nye tall, legger noe ut av seg selv. Utleggingen er én egen jobb, og alt annet må bestille den: den daglige og den ukentlige datajobben gjør det hver gang de har kjørt, publiseringen av en artikkel gjør det, den månedlige oppdateringen av disse sidene gjør det når tallene er endret, og den kan startes for hånd.

Jobben bygger nettstedet og laster det opp i samme steg, og regnes som vellykket først når vertstjenesten bekrefter at det er denne utgaven som er publisert. Deretter hentes forsiden, kildesiden og tre seksjonssider, og én av filene sidene trenger for å se riktige ut. Svarer noe av det ikke, rulles nettstedet tilbake til forrige utgave, og det opprettes en sak. Bare én utlegging kjører om gangen, og en som er i gang, avbrytes aldri.

Formen har en historie. Tidligere ba jobbene vertstjenesten om en ny utlegging og leste svaret «mottatt» som «publisert». I september 2026 ble fire slike bestillinger på rad borte i vertstjenestens kø, og nettstedet sto to døgn uten ny utlegging mens alle jobbene var grønne. Nå måles publiseringen, ikke bestillingen.

Prisen er at en kodeendring ikke er synlig før neste utlegging, i praksis senest morgenen etter, når den daglige datajobben har kjørt. Hver utlegging trekker også fra en fast kvote hos vertstjenesten, og den daglige jobben bestiller en selv om ingen tall er endret. Hvordan utleggingen overvåkes, står i kapitlet om drift.

Se det i portalen

Se hvordan denne siden henger sammen med restenNabolagskartet viser sidene, begrepene og kildene den er koblet til