dimesum

Startseite / Blog / Technik

Technik

Wir haben unseren Ausgaben-Parser gelöscht

· 8 Min. Lesezeit ·

Unser Regel-Parser hielt eine Woche, dann ersetzte eine einzige Verweigerungsregel den ganzen Stapel von Absicherungen, weil vier normale Sätze Geld der falschen Person zuordneten.

Wir haben einen Parser gelöscht, den wir gerade fertiggestellt hatten. Dimesums erster Versuch, Ausgaben in natürlicher Sprache zu erfassen, war eine Regel-Engine, und vier ganz normale Sätze haben sie ausgemustert: dinner 12-08 400 wurde als €12 gelesen, ravioli 600 brachte ein Mitglied namens Ravindra in die Aufteilung, kirana 500 belastete ein Mitglied namens Kiran, und refund -483.50 wurde zu einer Belastung von €483.50.

Einen Satz zu verstehen ist die Aufgabe des Modells und keiner anderen Komponente. Was die Regel-Engine ersetzt hat, ist eine einzige Stufe namens amount_only: eine einzelne Zahl, die nur zurückgegeben wird, wenn der Text genau einen eindeutigen Geldkandidaten enthält, und nie eine Aussage über Personen. Zwei Kandidaten bedeuten keinen Betrag. Eine Regel ersetzte einen wachsenden Stapel von Absicherungen.

Vier Sätze beendeten den Regel-Parser

Der gelöschte Parser deckte die gesamte Entitätsmenge ab, die unser KI-Design-Dokument vorgibt: Abgleich von Mitgliedern und Spitznamen, ein Ausschluss-Lexikon, Zahler-Ableitung, ein Kategorie-Lexikon und feinjustierte Konfidenzen pro Feld. Jeder der vier folgenden Fehler hatte eine offensichtliche Korrektur. Jede Korrektur war eine neue Absicherung mit ihrem eigenen blinden Fleck.

Die vier Fehler, die Dimesums Regel-Parser ausmusterten, aufgezeichnet 2026-08-20 in docs/tech/10-ai-design.md.
Was eingegeben wurdeWas der Parser tatWarum es passierte
dinner 12-08 400Las den Betrag als €12Ein Mensch sieht ein Datum und eine Summe. Ein Regex sieht drei Zahlen und nimmt die erste.
ravioli 600Setzte ein Mitglied namens Ravindra in die AufteilungDer unscharfe Spitznamen-Abgleich verrechnete ein Gericht mit einer Person.
kirana 500Belastete ein Mitglied namens KiranDerselbe Abgleich, diesmal mit einem Ladennamen.
refund -483.50Buchte eine Belastung von €483.50Die Ziffern überlebten, das Vorzeichen nicht, sodass das Geld in die entgegengesetzte Richtung zeigte.

Zwei der vier sind ein Fehler in unterschiedlicher Kleidung. Ein unscharfer Abgleich kann ein Gericht nicht von einer Person und einen Laden nicht von einer Person unterscheiden, denn auf Zeichenebene sehen sich ravioli und Ravindra tatsächlich ähnlich. Verlange einen längeren Präfix-Treffer, und du zerstörst ravi, genau den Fall, für den der Abgleich existiert.

Jede Absicherung bringt zwei weitere Formulierungen zutage

Ein Regel-Parser scheitert in einer bestimmten Form: Er antwortet selbstsicher und falsch. Ein leeres Feld kostet die Nutzerin einen Tipp. Eine falsche Aufteilung kostet Vertrauen ins Hauptbuch, und in einer App zum Aufteilen von Geld ist das Hauptbuch das Produkt. Die vier Zeilen oben sind keine Beinahe-Treffer, sie sind Geldfehler.

Das eigentliche Argument ist die Tretmühle, nicht ein einzelner Defekt. Füge eine Datums-Absicherung hinzu, und der Bestellnummern-Fall kommt. Füge eine Bestellnummern-Absicherung hinzu, und es kommen bloße Zahlen, dann Mengen, dann Tischnummern. Die Liste der Absicherungen wächst und konvergiert nie, denn natürliche Sprache hat keine endliche Menge an aufzählbaren Formulierungen.

Vorher und nachher: ein wachsender Stapel von Absicherungen, ersetzt durch eine einzige Verweigerungsregel VORHER: REGEL-PARSER (GELÖSCHT) dinner 12-08 400 Betrags-Regex Datums-Absicherung Bestellnummern-Absicherung Spitznamen-Abgleich Ausschluss-Lexikon liest €12 und bucht ihn Jede Korrektur brachte zwei weitere Formulierungen zutage. NACHHER: amount_only dinner 12-08 400 genau ein eindeutiger Geldkandidat? nein, drei Zahlen Betrag bleibt leer ja, eine Zahl in Cent zurückgegeben Die Stufe sagt nichts über Personen, also kann sie kein Geld der falschen Person zuordnen.
Der gelöschte Parser beantwortete jeden Satz. Die Stufe, die ihn ersetzte, antwortet mit einer Zahl oder mit nichts.
Die Entscheidung, mit Datum

Eingabe in natürlicher Sprache ist eine KI-Funktion, und nichts im Dimesum-Repository entspricht ihrem Muster. Die Entscheidung fiel am 2026-08-20, festgehalten zusammen mit den vier Fehlern, damit niemand die Absicherungen versehentlich neu aufbaut.

Was ausgeliefert wurde, ist eine Zahl und eine Verweigerung

amount_only ist die heruntergestufte Stufe unseres KI-Design-Dokuments, wörtlich umgesetzt. Diese Stufe lautet „das einfache Formular mit clientseitiger Betrags-Regex-Vorbefüllung“, also gibt die Stufe einen Betrag zurück und sonst nichts: keine Beschreibung, keine Kategorie, keine Zahler, keine Beteiligten, keine Ausschlüsse. Sie kostet nichts und ruft keinen Dienst auf, weshalb Test und CI auf ihr laufen.

Mehrdeutigkeit ist eine Verweigerung, kein Stichentscheid

Die gesamte Regel steckt in einer Funktion, extract_amount_minor. Eine Zahl kommt nur zurück, wenn der Text genau einen Kandidaten dafür enthält, sodass order 90210 dinner 400 und flat 402 rent 15000 leer zurückkommen, statt einen Gewinner zu wählen. Eine mit Währung markierte Zahl gilt selbst neben bloßen Zahlen als eindeutig, weshalb split 3 ways €1,200 weiterhin €1,200 liest.

Eine negierte Zahl ist gar kein Betrag, nicht ihr Absolutwert. -500, minus 200 und das buchhalterische (500) kommen alle leer zurück, denn das Feld ist eine Belastung, und die Ziffern zu behalten und das Vorzeichen fallen zu lassen zeigt das Geld in die entgegengesetzte Richtung zum Text. Klammern zählen nur, wenn sie um die Zahl selbst schließen, sodass (500 each) ein Klammerzusatz bleibt.

Wie amount_only zwischen einer Zahl und keiner Antwort entscheidet sammle jede Zahl, die Geld sein könnte keine gefunden, oder eine davon negativ vorzeichenbehaftet? nein genau eine mit Währung markierte Zahl, etwa €1,200 oder 500/-? nein gar keine Markierung, und genau eine bloße Zahl? ja amount_minor: ganzzahlige Untereinheiten, über den ISO-4217-Exponenten ja nein kein Betrag das Feld bleibt leer ja
Drei Fragen, zwei davon enden leer. Die Wahl zwischen zwei plausiblen Beträgen erzeugte das €12-Abendessen.

Die Währung bestimmt die Arithmetik

Untereinheiten sind die einzige Darstellung, die Geld in Dimesum annimmt, also rechnet die Stufe mit einer ISO-4217-Exponententabelle um, statt fest mit 100 zu multiplizieren. Der japanische Yen hat überhaupt keine Untereinheit, und ×100 bläht einen Beleg über ¥1,200 um das Hundertfache auf. Eine Zahl feiner als die kleinste Einheit der Währung wird verweigert statt gerundet, denn einen Betrag zu runden, den jemand eingetippt hat, heißt einen zu erfinden.

Indische Zahlwörter gehören zum Schreiben einer Zahl, nicht zum Verstehen eines Satzes. 1.2k, 2 lakh und 500/- lösen sich alle auf, ebenso wie 1,200. Alles jenseits des Höchstbetrags des Hauptbuchs kommt leer zurück, sodass eine falsch eingetippte Zahl ein Feld leert, statt später eine Ganzzahl überlaufen zu lassen.

Was jede Parse-Stufe behaupten darf, Stand 29. August 2026.
FeldRegel-Parser (gelöscht)amount_only (aktiv)Modellstufe (angebunden, ohne Schlüssel)
BetragAus mehreren Zahlen geratenEine eindeutige Zahl, sonst leerIm Kontext gelesen
Beschreibung, KategorieLexikon-TrefferImmer nullAus dem Satz extrahiert
Beteiligte, AusschlüsseUnscharfer NamensabgleichImmer leerZu echten Mitglieds-IDs aufgelöst
ZahlerAus der Formulierung abgeleitetImmer leerBenannt, mit einem nullbaren Betrag
GesamtkonfidenzPro Feld feinjustiertFest auf 0.3Pro Parse
Gemeldeter PromptEs gab keinenNull, es wurde kein Prompt gelesenPrompt-ID und -Version

Die aktive Stufe erreicht nie die Nutzbarkeitsschwelle von 0.6

Unser Parse-Vertrag verwirft einen Parse unter 0.6 Gesamtkonfidenz und leitet die Nutzerin auf das einfache Formular. amount_only meldet bei jeder Antwort 0.3, und die Konstante ist strukturell bedingt, nicht feinjustiert. Ein einzelner Betrag ist kein Parse, also liegt die Stufe bei der Hälfte der Schwelle, egal was sie gefunden hat. Eine Konstante für jede Antwort ist es, die sie dort hält: Ein fallbezogener Wert ist ein Wert, den irgendwann jemand nach oben schiebt.

Die Stufe meldet außerdem gar keinen Prompt. Sowohl prompt_id als auch prompt_version kommen null zurück, denn die Stufe hat keinen Prompt gelesen. Einen zu nennen würde jedes Eval-Ergebnis einer Prompt-Version zuschreiben, die die Stufe nie gesehen hat, und die Eval-Umgebung ist das einzige Instrument, das eine Stufe zu einem Ein-Tipp-Vorschlag befördern darf, bei 95% Präzision auf Betrag und Beteiligten zusammen.

Zwei weitere Stufen sind deklariert, und keine ist aktiv. Die Stufe cheap-fast hat einen Groq-Adapter für openai/gpt-oss-120b und keinen Schlüssel; die mittlere Stufe hat keinen Adapter. Die Auswahl beider scheitert beim Start statt bei der ersten Anfrage einer Nutzerin, denn ein LLM rechnet pro Aufruf ab, und eine abrechenbare Abhängigkeit muss geschlossen scheitern.

Nichts wird automatisch gebucht, also kostet ein leeres Feld einen Tipp

Ein leeres Feld kostet nur deshalb so wenig, weil keine Erfassung in Dimesum Geld schreiben kann. Eine Erfassung erstellt einen Vorschlag, ein Mensch bestätigt ihn, und die Bestätigung ist es, was die Ausgabe erzeugt. Brief-Entscheidung D5 nennt die Regel, und .go-arch-lint.yml setzt sie durch: Dem Erfassungskontext wird jede Abhängigkeit von expense oder ledger verweigert, sodass eine Erfassung selbst versehentlich kein Journal buchen kann. CI lässt den Import scheitern, was wir geprüft haben, indem wir einen hinzufügten.

Die Erfassung behält den Rohtext, egal was der Parser tut, und benennt, welche Felder ungelöst sind. Der Client hebt diese leeren Felder hervor, statt einen erfundenen Entwurf zu zeigen, was der Unterschied ist zwischen einem Parser, der nichts sagt, und einem, der rät. Bestätigen leitet seine Ausgaben-ID aus der Vorschlags-ID ab, sodass ein doppelter Tipp erneut abspielt, statt zweimal zu belasten.

Die Regel, die es zu übernehmen lohnt

Zähle deine Absicherungen, nicht deine Fehler. Eine Liste von Absicherungen, die jede Woche wächst, sagt dir, dass die Aufgabe Verständnis ist, und Verständnis gehört einem Modell. Unser nächster Schritt ist, den Goldstandard-Satz in contracts/parse_expense/eval/ gegen eine echte Modellstufe laufen zu lassen, denn nichts hier wird zu einem Ein-Tipp-Vorschlag ohne dieses Urteil.

Häufige Fragen

Warum hat Dimesum seinen regelbasierten Ausgaben-Parser gelöscht?

Dimesum hat ihn gelöscht, weil vier ganz normale Sätze zu Geldfehlern führten und jede neue Absicherung zwei weitere Formulierungen zutage brachte. dinner 12-08 400 wurde als €12 gelesen, ravioli 600 fügte ein Mitglied namens Ravindra hinzu, kirana 500 belastete ein Mitglied namens Kiran, und refund -483.50 wurde zu einer Belastung von €483.50. Einen Satz zu verstehen ist Aufgabe des Modells.

Was gibt die amount_only-Stufe tatsächlich zurück?

Die Stufe amount_only gibt genau eine Zahl zurück und sonst nichts. Sie nennt einen Betrag nur, wenn der Text genau einen eindeutigen Geldkandidaten enthält, und sie nennt nie eine beteiligte Person, einen Zahler, eine Beschreibung oder eine Kategorie. Zwei Kandidaten bedeuten gar keinen Betrag. Alles Weitere im Parse-Vertrag wartet auf eine Modellstufe.

Warum meldet amount_only eine Konfidenz von 0.3 statt eines echten Werts?

Die 0.3 sind strukturell bedingt, nicht feinjustiert. Unser Parse-Vertrag verwirft einen Parse unter 0.6 und leitet die Nutzerin auf das einfache Formular, und ein einzelner Betrag ist kein Parse, also liegt die Stufe bei der Hälfte dieser Schwelle, egal was sie gefunden hat. Eine feste Konstante für jede Antwort verhindert, dass ein fallbezogener Wert später nach oben geschoben wird.

Kann eine Erfassung per natürlicher Sprache ohne Mensch ins Hauptbuch schreiben?

Nein. Eine Erfassung erstellt einen Vorschlag, und ein Mensch bestätigt ihn, gemäß Brief-Entscheidung D5. Die Regel wird in .go-arch-lint.yml durchgesetzt, die dem Erfassungskontext jede Abhängigkeit von expense oder ledger verweigert, sodass CI den Import scheitern lässt, falls eine Erfassung je nach einem Journal greift. Das Bestätigen ist es, was die Ausgabe erzeugt.

Was passiert bei der Ausgabenerkennung, wenn keine Modellstufe verfügbar ist?

Dimesum fällt auf amount_only zurück und zeigt leere Felder. Die Stufe cheap-fast ist an Groqs openai/gpt-oss-120b angebunden und wird ohne Schlüssel ausgeliefert, und die mittlere Stufe hat keinen Adapter, sodass die Auswahl beider beim Start scheitert statt bei der ersten Anfrage einer Nutzerin. Die Erfassung behält den Rohtext in beiden Fällen.