Vi slettet utgiftsparseren vår
Dimesum slettet sin regelbaserte utgiftsparser etter at fire vanlige setninger ga pengefeil, og erstattet den med ett trinn som returnerer ett entydig tall eller ingenting.
Vi slettet en parser vi nettopp var ferdige med å skrive. Dimesums første forsøk på utgiftsføring med naturlig språk var en regelmotor, og fire vanlige setninger pensjonerte den: dinner 12-08 400 ble lest som 12 kr, ravioli 600 la et medlem ved navn Ravindra inn i delingen, kirana 500 belastet et medlem ved navn Kiran, og refund -483.50 ble en kostnad på 483,50 kr.
Å forstå en setning er modellens jobb og ingen andres. Det som erstattet regelmotoren er ett trinn kalt amount_only: ett enkelt tall, som bare returneres når teksten inneholder nøyaktig én entydig pengekandidat, og aldri en påstand om personer. To kandidater betyr ingen sum. Én regel erstattet en voksende haug med vakter.
Fire setninger gjorde slutt på regelparseren
Den slettede parseren dekket hele entitetssettet som AI-designdokumentet vårt spesifiserer: matching av medlemmer og kallenavn, et eksklusjonsleksikon, utleding av betaler, et kategorileksikon, og finjusterte konfidenser per felt. Hver av de fire feilene under hadde en åpenbar løsning. Hver løsning var en ny vakt med sitt eget blindpunkt.
| Det brukeren skrev | Det parseren gjorde | Hvorfor det skjedde |
|---|---|---|
dinner 12-08 400 | Leste beløpet som 12 kr | En leser ser en dato og en sum. Et regex ser tre tall og tar det første. |
ravioli 600 | La et medlem ved navn Ravindra inn i delingen | Uskarp kallenavn-matching scoret en rett mot en person. |
kirana 500 | Belastet et medlem ved navn Kiran | Den samme matcheren, denne gangen med et butikknavn. |
refund -483.50 | Bokførte en kostnad på 483,50 kr | Sifrene overlevde og fortegnet gjorde det ikke, så pengene pekte motsatt vei. |
To av de fire er én feil i forskjellige klær. Uskarp matching kan ikke skille en rett fra en person eller en butikk fra en person, for på tegnnivå ligner ravioli og Ravindra faktisk på hverandre. Krev en lengre prefiks-match, og du ødelegger ravi, som er tilfellet matcheren finnes for.
Hver vakt du legger til, får frem to nye formuleringer
En regelparser feiler på én bestemt måte: den svarer selvsikkert og feil. Et tomt felt koster brukeren ett trykk. En feil deling koster tillit til hovedboken, og i en app for deling av utgifter er hovedboken produktet. De fire radene over er ikke nestenbommer, de er pengefeil.
Tredemøllen er det egentlige argumentet, ikke noen enkelt defekt. Legg til en dato-vakt, og ordrenummer-tilfellet dukker opp. Legg til en ordrenummer-vakt, og rene tall dukker opp, så antall, så bordnumre. Vaktlisten vokser og konvergerer aldri, for naturlig språk har ikke noe endelig sett med formuleringer å telle opp.
Inntasting med naturlig språk er en AI-funksjon, og ingenting i Dimesum-repoet mønstermatcher den. Beslutningen falt 2026-08-20, skrevet ned sammen med de fire feilene, så ingen bygger opp vaktene igjen ved et uhell.
Det som ble levert er ett tall og en avvisning
amount_only er det degraderte trinnet fra AI-designdokumentet vårt, implementert bokstavelig. Det trinnet lyder «det enkle skjemaet med forhåndsutfylling av beløp via regex på klientsiden», så nivået returnerer et beløp og ingenting annet: ingen beskrivelse, ingen kategori, ingen betalere, ingen deltakere, ingen eksklusjoner. Det koster ingenting og ringer ingen, og derfor kjører test og CI på det.
Tvetydighet er en avvisning, ikke en omkamp
Hele regelen bor i én funksjon, extract_amount_minor. Et tall kommer tilbake bare når teksten inneholder nøyaktig én kandidat til det, så order 90210 dinner 400 og flat 402 rent 15000 returnerer tomt i stedet for å kåre en vinner. Et tall merket med valuta regnes som entydig selv ved siden av rene tall, og derfor leser split 3 ways ₹1,200 fortsatt 1 200 kr.
Et negert tall er ikke noe beløp i det hele tatt, snarere enn sin absoluttverdi. -500, minus 200 og regnskapsførerens (500) kommer alle tilbake tomme, for feltet er en kostnad, og å beholde sifrene mens fortegnet droppes peker pengene motsatt vei av teksten. Parenteser teller bare når de lukker om selve tallet, så (500 each) forblir en parentes.
Valutaen bestemmer regnestykket
Minorenheter er den eneste formen penger tar i Dimesum, så nivået konverterer med en ISO 4217-eksponenttabell i stedet for en fastkodet multiplikasjon med 100. Den japanske yenen har ingen underenhet i det hele tatt, og ×100 blåser en kvittering på ¥1 200 opp hundre ganger. Et tall finere enn valutaens minste enhet avvises i stedet for å rundes av, for å runde av et beløp noen har tastet inn er å finne opp ett.
Indiske tallord er en del av å skrive et tall, ikke en del av å forstå en setning. 1.2k, 2 lakh og 500/- løses alle opp, som 1,200. Alt over hovedbokens maksimumsbeløp kommer tilbake tomt, så et feiltastet tall tømmer ett felt i stedet for å flyte over et heltall nedstrøms.
| Felt | Regelparser (slettet) | amount_only (i drift) | Modellnivå (koblet, uten nøkkel) |
|---|---|---|---|
| Beløp | Gjettet fra flere tall | Ett entydig tall, ellers tomt | Lest i kontekst |
| Beskrivelse, kategori | Leksikon-match | Alltid null | Hentet fra setningen |
| Deltakere, eksklusjoner | Uskarp navne-matching | Alltid tomt | Løst til ekte medlems-id-er |
| Betaler | Utledet fra formulering | Alltid tomt | Navngitt, med et beløp som kan være null |
| Samlet konfidens | Finjustert per felt | Fast på 0.3 | Per parse |
| Prompt rapportert | Ingen fantes | Null, ingen prompt ble lest | Prompt-id og versjon |
Trinnet i drift passerer aldri den brukbare 0.6-porten
Parse-kontrakten vår forlater en parse under 0.6 samlet konfidens og setter brukeren tilbake til det enkle skjemaet. amount_only rapporterer 0.3 på hvert svar, og konstanten er strukturell snarere enn finjustert. Et ensomt beløp er ikke en parse, så trinnet ligger på halvparten av porten uansett hva det fant. Én konstant for hvert svar er det som holder den der: en score per tilfelle er en score noen til slutt dytter oppover.
Nivået rapporterer også ingen prompt overhodet. Både prompt_id og prompt_version kommer tilbake null, for trinnet leste ingen prompt. Å navngi en ville tilskrive hvert eval-resultat en prompt-versjon nivået aldri så, og eval-riggen er det eneste instrumentet som har lov til å forfremme et trinn til ett-trykks forslag, ved 95 % presisjon på beløp og deltakere samlet.
To ytterligere nivåer er deklarert, og ingen av dem er i drift. cheap-fast-nivået har en Groq-adapter for openai/gpt-oss-120b og ingen nøkkel; mid-nivået har ingen adapter. Å velge ett av dem feiler ved oppstart snarere enn ved brukerens første forespørsel, for en LLM fakturerer per kall, og en fakturerbar avhengighet må feile lukket.
Ingenting bokføres automatisk, så et tomt felt koster ett trykk
Et tomt felt koster så lite bare fordi ingen registrering i Dimesum kan skrive penger. En registrering lager et forslag, en person bekrefter det, og bekreftelsen er det som skaper utgiften. Brief-beslutning D5 fastsetter regelen, og .go-arch-lint.yml håndhever den: registreringskonteksten nektes enhver avhengighet av expense eller ledger, så en registrering kan ikke bokføre en journal selv ved en feil. CI feiler importen, noe vi sjekket ved å legge til en.
Registreringen beholder råteksten uansett hva parseren gjør, og navngir hvilke felter som er uløste. Klienten fremhever de tomme feltene i stedet for å vise et oppdiktet utkast, som er forskjellen mellom en parser som ikke sier noe og en som gjetter. Bekreft utleder sin utgifts-id fra forslags-id-en, så et dobbelttrykk spiller av på nytt i stedet for å belaste to ganger.
Regelen verdt å stjele
Tell vaktene dine, ikke feilene. En vaktliste som vokser hver uke forteller deg at jobben er forståelse, og forståelse hører til en modell. Neste steg for oss er å kjøre gullsettet i contracts/parse_expense/eval/ mot et ekte modellnivå, for ingenting her blir et ett-trykks forslag uten den dommen.
Vanlige spørsmål
Hvorfor slettet Dimesum den regelbaserte utgiftsparseren sin?
Dimesum slettet den fordi fire vanlige setninger ga pengefeil, og hver vakt som ble lagt til fikk frem to nye formuleringer. dinner 12-08 400 ble lest som 12 kr, ravioli 600 la til et medlem ved navn Ravindra, kirana 500 belastet et medlem ved navn Kiran, og refund -483.50 ble en kostnad på 483,50 kr. Å forstå en setning er modellens jobb.
Hva returnerer amount_only-nivået egentlig?
amount_only-nivået returnerer ett tall og ingenting annet. Det svarer med et beløp bare når teksten inneholder nøyaktig én entydig pengekandidat, og det navngir aldri en deltaker, en betaler, en beskrivelse eller en kategori. To kandidater betyr ikke noe beløp i det hele tatt. Alt annet i parse-kontrakten venter på et modellnivå.
Hvorfor rapporterer amount_only 0.3 i konfidens i stedet for en ekte score?
0.3 er strukturell, ikke finjustert. Parse-kontrakten vår forlater en parse under 0.6 og setter brukeren tilbake til det enkle skjemaet, og et ensomt beløp er ikke en parse, så trinnet ligger på halvparten av den porten uansett hva det fant. Én fast konstant for hvert svar hindrer at en score per tilfelle senere dyttes oppover.
Kan en registrering med naturlig språk skrive til hovedboken uten et menneske?
Nei. En registrering lager et forslag, og en person bekrefter det, i tråd med Brief-beslutning D5. Regelen håndheves i .go-arch-lint.yml, som nekter registreringskonteksten enhver avhengighet av expense eller ledger, så CI feiler importen hvis en registrering noen gang strekker seg etter en journal. Å bekrefte er det som skaper utgiften.
Hva skjer med utgiftsføring med naturlig språk når ingen modellnivåer er tilgjengelige?
Dimesum degraderer til amount_only og viser tomme felter. cheap-fast-nivået er koblet til Groqs openai/gpt-oss-120b og leveres uten nøkkel, og mid-nivået har ingen adapter, så å velge ett av dem feiler ved oppstart snarere enn ved brukerens første forespørsel. Registreringen beholder råteksten uansett.
Populære innlegg
- Append-only-hovedbok for eksakte delte saldoer8 min lesing
- Hvorfor redigering må gjenta hele fordelingen8 min lesing
- Seks pengefeil i utgiftsdeling med flere valutaer8 min lesing
- Gjør opp: rydd felles utgifter på færre overføringer5 min lesing
- Slik deler du en regning når én rett ikke ble delt9 min lesing