Gå til hovedindhold

248 noter og ingen søgefunktion der duer. Løsningen var ikke bedre søgning

Indsendt af Lennart den
248 noter og ingen søgefunktion der duer. Løsningen var ikke bedre søgning

Jeg har 248 noter i min vidensbase. Research på virksomheder, tilbud jeg har sendt, oplæg jeg har holdt, mails jeg har skrevet, blogudkast, strateginoter.

I lang tid var mit eneste værktøj til at finde noget i dem fritekstsøgning. Det virker fint til "hvor var det nu jeg skrev om prompt injection". Det virker slet ikke til det spørgsmål, jeg faktisk har brug for at stille en mandag morgen:

Hvilke tilbud har jeg sendt, som ikke er besvaret, og hvad skal jeg følge op på først?

Det er ikke et søgespørgsmål. Det er et databasespørgsmål. Og forskellen mellem de to er værd at forstå, hvis man overhovedet skal have gavn af AI i sin egen dokumentbunke.

Søgning finder dokumenter. Forespørgsler finder svar

Når du søger, beder du om dokumenter, der ligner din tekst. Du får en liste, og så læser du den igennem. Arbejdet med at finde svaret ligger stadig hos dig.

Når du forespørger, beder du om en beregning: filtrér på noget, sortér på noget andet, tæl, læg sammen. Svaret kommer ud som svar.

Grunden til at næsten ingen kan forespørge i deres egne dokumenter er banal. De fakta, man vil forespørge på, står inde i prosaen. Beløbet på tilbuddet står i en sætning. Datoen står i et afsnit under "Vilkår". Kundens navn står i overskriften. Alt sammen fuldstændig læsbart for et menneske, og fuldstændig ubrugeligt til at filtrere på.

Løsningen er ikke en bedre søgemaskine. Løsningen er at flytte de få fakta, man rent faktisk vil regne på, ud af prosaen og op i et felt.

Hvad et felt er

Mine noter er almindelige markdown-filer. Øverst i filen står en lille blok, der kaldes frontmatter:

---
type: tilbud
customer: REDACTED
amount: 8000
status: sendt
sent: 2026-08-04
follow_up: 2026-08-21
valid_until: 2026-09-01
---

Nedenunder står tilbuddet som prosa: baggrund, leverance, pris, forudsætninger, vilkår. Det er dét, kunden får som PDF. Frontmatteren kommer aldrig med ud af huset.

Værktøjet, jeg bruger, hedder iwe. Det er et kommandolinjeværktøj, der behandler en mappe med markdown-filer som en graf med en forespørgselsmotor ovenpå. Ingen server, ingen database, ingen cloud. Bare filerne og et program, der kan læse dem struktureret.

Og så kan jeg spørge:

iwe find --filter 'type: tilbud, status: sendt' \
         --project 'customer,amount,sent,follow_up' \
         --sort 'follow_up:1'

Der er tre ting i den kommando, og de er hele pointen:

  • --filter vælger hvilke dokumenter, der er med. Her: alle tilbud med status sendt.
  • --project vælger hvilke felter, jeg vil se. Ikke hele noten, kun de fire kolonner.
  • --sort bestemmer rækkefølgen. Her efter opfølgningsdato, så det mest presserende ligger øverst.

Det er de samme tre operationer, enhver database i verden bygger på. Forskellen er, at datagrundlaget er de dokumenter, jeg alligevel skriver.

Filtre der kan mere end lighedstegn

Filteret er ikke bare "felt er lig med værdi". Det har operatorer:

# Alle rigtige leads — testdata og noter om mig selv falder ud
iwe find --filter 'type: dossier, status: {$nin: [eksempel, egen]}' \
         --project 'name,company,role,status'

# Hvor mange er der egentlig?
iwe count --filter 'type: dossier, status: {$nin: [eksempel, egen]}'

Den sidste svarer 2. Ikke en liste jeg skal tælle. Et tal.

$nin betyder "ikke blandt disse". Der er tilsvarende $gt, $in, $exists og resten af det sædvanlige repertoire. Det, der gør det brugbart i praksis, er, at værdierne er kontrollerede: status må være kold, varm, i-dialog, kunde, tabt, eksempel eller egen, og intet andet. Det håndhæves af et skema, som jeg har skrevet om før. Uden det ordforråd rammer et filter på status: varm ikke de noter, hvor der kom til at stå Varm eller varmt lead.

Det er den ubehagelige del af at gøre dokumenter til data. Man skal blive enig med sig selv om ordene, før man kan regne på dem.

Grafen er også forespørgbar

Noterne linker til hinanden, og de links er data på lige fod med felterne:

iwe find --referenced-by MOC-salg     # hvad salgs-oversigten peger på
iwe find --references profil/REDACTED   # alt der nævner den kunde
iwe find --roots                      # hvad der ikke er linket ind fra noget

Den sidste er den mest brugbare til vedligehold. Noter, ingen linker til, er noter, ingen finder igen. De er ikke nødvendigvis dårlige, men de er usynlige, og det er værd at vide hvilke det er.

Der er også en statistikudgang, som spytter hele basen ud som en tabel:

iwe stats --format csv | from csv
  | sort-by incomingEdgesCount --reverse
  | where words < 300
  | select key title words incomingEdgesCount

Det er en Nushell-pipeline, og den finder de noter, mange andre henviser til, men som selv er tynde. Det er min prioriteringsliste: centralt placeret og underudviklet på samme tid. Jeg har aldrig kunnet stille det spørgsmål til en dokumentmappe før.

Skrivning er også en forespørgsel

Den del, folk oftest overser: forespørgselssproget virker også, når man skal ændre noget.

iwe update -k tilbud/REDACTED-terminal-forloeb --set status=accepteret

Det ser ud som en bekvemmelighed. Det er en sikkerhedsforanstaltning. Kommandoen validerer op mod skemaet, før den skriver, og den skriver atomisk. Åbner jeg i stedet filen og retter i hånden, kan jeg skrive accepted, Accepteret eller accepterert, og ingen siger noget. Fejlen dukker først op om tre uger, når noten er væk fra en liste, den burde have stået på.

Og det gælder ikke kun frontmatter. Man kan operere på blokke inde i teksten — udskifte en sektion, indsætte et afsnit efter en bestemt overskrift, slette en liste — med et udtryk frem for en tekstsøgning:

iwe update -k tilbud/REDACTED-terminal-forloeb \
  --replace '{ $header: Pris, content: "..." }' --expect 1

--expect 1 er vagten. Rammer udtrykket nul dokumenter eller sytten, sker der ingenting, og jeg får det at vide. Det er dét, en tekstsøg-og-erstat aldrig har kunnet give mig.

Hvad det har med AI at gøre

Her kommer koblingen, som er hele grunden til at jeg gider skrive det her ned.

Jeg skriver en stor del af mit materiale sammen med en sprogmodel. Tilbud, oplæg, udkast til breve, dette indlæg. Modellen er god til prosa. Den er også god til at læse prosa og finde mønstre i den.

Men den er dårlig til at garantere noget. Spørger jeg en model "hvilke af mine tilbud er ubesvarede", læser den sig igennem det, den kan nå, og giver mig et plausibelt svar. Plausibelt er ikke det samme som rigtigt, og forskellen viser sig præcis dér, hvor det gør ondt: i det tilbud, den overså.

Arbejdsdelingen, der virker for mig, ser sådan ud:

Modellen skriver brødteksten. Forespørgslen leverer fakta. Når jeg skal have et overblik, kalder jeg ikke på modellens hukommelse. Jeg kører en forespørgsel og giver modellen resultatet. Så arbejder den videre på noget, der er sandt, i stedet for på noget, der lyder rigtigt.

Det er også derfor felterne er få. Der er ikke tredive felter på en tilbudsnote. Der er syv, og de er valgt efter ét kriterium: kan jeg forestille mig at ville filtrere eller sortere på det? Alt andet må stå i prosaen, hvor det hører hjemme. En note, der er gjort til et regneark, er ikke længere en note, nogen gider læse.

Fra note til publiceret artikel

Sidste led, og det er det, der lukker cirklen. Indlægget her ligger som en note i samme base. Da det var færdigt, gik det ud sådan her:

open --raw blog-73.md | str trim
  | drupal article-with-image "248 noter og ingen søgefunktion der duer"

Kommandoen sender brødteksten til hjemmesiden gennem sidens API, får en model til at koge indlægget ned til ét visuelt budskab, genererer et billede ud fra det, sætter logoet på og hænger billedet på artiklen. Til sidst svarer den med den URL, artiklen fik, og den URL skriver jeg tilbage i notens frontmatter.

Så er noten både kilden og kvitteringen. Næste gang jeg vil vide, hvad jeg har udgivet om det her emne, er det ikke noget, jeg skal huske. Det er noget, jeg kan spørge om.

Det, en SMV skal tage med

Man behøver ikke iwe, og man behøver ikke markdown. Men de tre erkendelser bag flytter noget for enhver virksomhed, der drukner i dokumenter:

Beslut hvilke fem fakta pr. dokumenttype du vil regne på. Ikke tredive. Fem. Kunde, beløb, status, dato, ansvarlig er som regel nok til at komme meget langt.

Bliv enig om ordene, før du automatiserer. En statuskolonne med atten stavemåder er værre end ingen statuskolonne, fordi den ser ud som om, den virker.

Lad sprogmodellen skrive og analysere. Lad noget deterministisk svare på "hvor mange" og "hvilke". De to ting er forskellige opgaver, og de fleste skuffelser over AI i virksomheder stammer fra at give den første slags værktøj den anden slags opgave.

Det tog mig en formiddag at give syv dokumenttyper felter og skema. 32 af mine 248 noter er nu typede. Det er de 32, jeg kan stille spørgsmål til om morgenen i stedet for at lede.