Vi slettede vores udgiftsparser
Vores regelparser holdt en uge, før fire almindelige sætninger og én afvisningsregel afsluttede den.
Vi slettede en parser, vi lige var færdige med at skrive. Dimesums første forsøg på at fortolke udgifter i naturligt sprog var en regelmotor, og fire helt almindelige sætninger pensionerede den: dinner 12-08 400 blev aflæst som 12 kr, ravioli 600 satte et medlem ved navn Ravindra ind i delingen, kirana 500 debiterede et medlem ved navn Kiran, og refund -483.50 blev til en debitering på 483,50 kr.
At forstå en sætning er modellens opgave og ingen andens. Det, der erstattede regelmotoren, er ét trin kaldet amount_only: ét enkelt tal, som kun returneres, når teksten indeholder præcis én utvetydig beløbskandidat, og aldrig en påstand om personer. To kandidater betyder intet beløb. Én regel erstattede en voksende bunke af vagter.
Fire sætninger gjorde ende på regelparseren
Den slettede parser dækkede hele det sæt af entiteter, som vores AI-designdokument angiver: matchning af medlemmer og kaldenavne, et ekskluderingsleksikon, udledning af betaler, et kategorileksikon og konfidenser justeret pr. felt. Hver af de fire fejl nedenfor havde en oplagt løsning. Hver løsning var en ny vagt med sin egen blinde vinkel.
| Hvad brugeren skrev | Hvad parseren gjorde | Hvorfor det skete |
|---|---|---|
dinner 12-08 400 | Aflæste beløbet som 12 kr | En læser ser en dato og et samlet beløb. En regex ser tre tal og tager det første. |
ravioli 600 | Satte et medlem ved navn Ravindra ind i delingen | Fuzzy-matchning af kaldenavne scorede en ret op mod en person. |
kirana 500 | Debiterede et medlem ved navn Kiran | Samme matcher, denne gang med et butiksnavn. |
refund -483.50 | Bogførte en debitering på 483,50 kr | Cifrene overlevede, men fortegnet gjorde ikke, så pengene pegede den modsatte vej. |
To af de fire er én og samme fejl i forskelligt tøj. Fuzzy-matchning kan ikke skelne en ret fra en person eller en butik fra en person, for på tegnniveau ligner ravioli og Ravindra faktisk hinanden. Kræv et længere præfiksmatch, og du ødelægger ravi, som er præcis det tilfælde, matcheren findes for.
Hver vagt, du tilføjer, afslører to nye formuleringer
En regelparser fejler på én bestemt måde: den svarer selvsikkert og forkert. Et tomt felt koster brugeren ét tryk. En forkert deling koster tilliden til regnskabet, og i en app til deling af udgifter er regnskabet produktet. De fire rækker ovenfor er ikke tætte skud forbi, de er pengefejl.
Trædemøllen er det egentlige argument, ikke nogen enkelt defekt. Tilføj en datovagt, og ordrenummertilfældet dukker op. Tilføj en ordrenummervagt, og der kommer bare tal, så mængder, så bordnumre. Listen af vagter vokser og konvergerer aldrig, for naturligt sprog har ikke et endeligt sæt formuleringer at opremse.
Indtastning i naturligt sprog er en AI-funktion, og intet i Dimesum-repoet mønstermatcher den. Beslutningen faldt 2026-08-20, nedskrevet sammen med de fire fejl, så ingen genopbygger vagterne ved et uheld.
Det, der blev leveret, er ét tal og en afvisning
amount_only er det nedgraderede trin fra vores AI-designdokument, implementeret bogstaveligt. Det trin lyder "den simple formular med forudfyldt beløbsregex på klientsiden", så laget returnerer et beløb og intet andet: ingen beskrivelse, ingen kategori, ingen betalere, ingen deltagere, ingen ekskluderinger. Det koster intet og kalder ingen, hvilket er grunden til, at test og CI kører på det.
Tvetydighed er en afvisning, ikke en afgørelse
Hele reglen bor i én funktion, extract_amount_minor. Et beløb kommer kun tilbage, når teksten indeholder præcis én kandidat til det, så order 90210 dinner 400 og flat 402 rent 15000 returnerer tomt i stedet for at kåre en vinder. Et valutamærket beløb tæller som utvetydigt, selv ved siden af bare tal, hvilket er grunden til, at split 3 ways 1.200 kr stadig aflæses som 1.200 kr.
Et negeret beløb er slet intet beløb frem for dets absolutte værdi. -500, minus 200 og revisorens (500) kommer alle tomme tilbage, for feltet er en debitering, og at beholde cifrene og droppe fortegnet peger pengene den modsatte vej af teksten. Parenteser tæller kun, når de lukker om selve beløbet, så (500 each) forbliver en parentesbemærkning.
Valutaen bestemmer regnestykket
Mindre enheder er den eneste form penge har i Dimesum, så laget konverterer med en ISO 4217-eksponenttabel frem for en hårdkodet multiplikation med 100. Den japanske yen har slet ingen underenhed, og ×100 oppuster en kvittering på ¥1.200 hundrede gange. Et beløb finere end valutaens mindste enhed afvises frem for at blive rundet, for at runde et beløb, som nogen har skrevet, er at opfinde et.
Indiske talord er en del af at skrive et beløb, ikke en del af at forstå en sætning. 1.2k, 2 lakh og 500/- opløses alle, ligesom 1,200. Alt over regnskabets maksimale beløb kommer tomt tilbage, så et fejlindtastet beløb tømmer ét felt i stedet for at overflow'e et heltal længere nede.
| Felt | Regelparser (slettet) | amount_only (aktiv) | Modeltrin (forbundet, uden nøgle) |
|---|---|---|---|
| Beløb | Gættet ud fra flere tal | Ét utvetydigt beløb, ellers tomt | Aflæst i kontekst |
| Beskrivelse, kategori | Leksikonmatch | Altid null | Udtrukket fra sætningen |
| Deltagere, ekskluderinger | Fuzzy navnematchning | Altid tomt | Opløst til rigtige medlems-id'er |
| Betaler | Udledt af formuleringen | Altid tomt | Navngivet, med et beløb der kan være null |
| Samlet konfidens | Justeret pr. felt | Fast på 0.3 | Pr. parse |
| Rapporteret prompt | Fandtes ikke | Null, ingen prompt blev læst | Prompt-id og version |
Det aktive trin passerer aldrig 0.6-brugbarhedsgrænsen
Vores parse-kontrakt opgiver en parse under 0.6 i samlet konfidens og sender brugeren ned til den simple formular. amount_only rapporterer 0.3 på hvert svar, og konstanten er strukturel snarere end justeret. Et enligt beløb er ikke en parse, så trinnet ligger på halvdelen af grænsen, uanset hvad det fandt. Én konstant for hvert svar er det, der holder det dér: en score pr. tilfælde er en score, nogen før eller siden skubber opad.
Laget rapporterer også slet ingen prompt. Både prompt_id og prompt_version kommer null tilbage, for trinnet læste ingen prompt. At navngive en ville tilskrive hvert eval-resultat en promptversion, laget aldrig så, og eval-riggen er det eneste instrument, der må forfremme et trin til et ét-tryks-forslag, ved 95 % præcision på beløb og deltagere tilsammen.
To yderligere lag er erklæret, og ingen af dem er aktive. cheap-fast-laget har en Groq-adapter til openai/gpt-oss-120b og ingen nøgle; mellemlaget har ingen adapter. At vælge et af dem fejler ved opstart frem for ved brugerens første forespørgsel, for en LLM afregner pr. kald, og en afregningsbar afhængighed skal fejle lukket.
Intet bogføres automatisk, så et tomt felt koster ét tryk
Et tomt felt koster så lidt netop fordi ingen registrering i Dimesum kan skrive penge. En registrering skaber et forslag, en person bekræfter det, og bekræftelsen er det, der skaber udgiften. Brief-beslutning D5 fastslår reglen, og .go-arch-lint.yml håndhæver den: indtagelseskonteksten nægtes enhver afhængighed af udgift eller regnskab, så en registrering kan ikke bogføre en journal, end ikke ved en fejl. CI får importen til at fejle, hvilket vi tjekkede ved at tilføje en.
Registreringen beholder den rå tekst, uanset hvad parseren gør, og navngiver hvilke felter der er uafklarede. Klienten fremhæver de tomme felter frem for at vise et opfundet udkast, hvilket er forskellen på en parser, der intet siger, og en, der gætter. Bekræftelsen udleder sit udgifts-id fra forslags-id'et, så et dobbelttryk afspiller igen i stedet for at debitere to gange.
Reglen værd at stjæle
Tæl dine vagter, ikke dine fejl. En liste af vagter, der vokser hver uge, fortæller dig, at opgaven er forståelse, og forståelse hører til hos en model. Vores næste skridt er at køre den gyldne mængde i contracts/parse_expense/eval/ mod et rigtigt modeltrin, for intet her bliver et ét-tryks-forslag uden den dom.
Ofte stillede spørgsmål
Hvorfor slettede Dimesum sin regelbaserede udgiftsparser?
Dimesum slettede den, fordi fire almindelige sætninger frembragte pengefejl, og hver tilføjet vagt afslørede to nye formuleringer. dinner 12-08 400 blev aflæst som 12 kr, ravioli 600 tilføjede et medlem ved navn Ravindra, kirana 500 debiterede et medlem ved navn Kiran, og refund -483.50 blev til en debitering på 483,50 kr. At forstå en sætning er modellens opgave.
Hvad returnerer amount_only-trinnet egentlig?
amount_only-trinnet returnerer ét tal og intet andet. Det svarer med et beløb kun når teksten indeholder præcis én utvetydig beløbskandidat, og det navngiver aldrig en deltager, en betaler, en beskrivelse eller en kategori. To kandidater betyder slet intet beløb. Alt andet i parse-kontrakten venter på et modeltrin.
Hvorfor rapporterer amount_only 0.3 i konfidens i stedet for en rigtig score?
De 0.3 er strukturelle, ikke justerede. Vores parse-kontrakt opgiver en parse under 0.6 og sender brugeren ned til den simple formular, og et enligt beløb er ikke en parse, så trinnet ligger på halvdelen af den grænse, uanset hvad det fandt. Én fast konstant for hvert svar forhindrer, at en score pr. tilfælde senere skubbes opad.
Kan en registrering i naturligt sprog skrive til regnskabet uden et menneske?
Nej. En registrering skaber et forslag, og en person bekræfter det, jf. Brief-beslutning D5. Reglen håndhæves i .go-arch-lint.yml, som nægter indtagelseskonteksten enhver afhængighed af udgift eller regnskab, så CI får importen til at fejle, hvis en registrering nogensinde rækker ud efter en journal. Bekræftelsen er det, der skaber udgiften.
Hvad sker der med fortolkning af udgifter i naturligt sprog, når intet modeltrin er tilgængeligt?
Dimesum degraderer til amount_only og viser tomme felter. cheap-fast-trinnet er forbundet til Groqs openai/gpt-oss-120b og leveres uden nøgle, og mellemtrinnet har ingen adapter, så det at vælge et af dem fejler ved opstart frem for ved brugerens første forespørgsel. Registreringen beholder den rå tekst uanset hvad.
Populære indlæg
- Append-only-hovedbog for præcise delte balancer8 min læsning
- Derfor skal en redigering angive fordelingen igen8 min læsning
- Seks pengefejl i udgiftsdeling på tværs af valutaer8 min læsning
- Gør op: ryd fælles udgifter med færre overførsler5 min læsning
- Del regningen når én ret ikke blev delt8 min læsning