Startseite / Blog / Technik
TechnikWir haben unseren Ausgaben-Parser gelöscht
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.
| Was eingegeben wurde | Was der Parser tat | Warum es passierte |
|---|---|---|
dinner 12-08 400 | Las den Betrag als €12 | Ein Mensch sieht ein Datum und eine Summe. Ein Regex sieht drei Zahlen und nimmt die erste. |
ravioli 600 | Setzte ein Mitglied namens Ravindra in die Aufteilung | Der unscharfe Spitznamen-Abgleich verrechnete ein Gericht mit einer Person. |
kirana 500 | Belastete ein Mitglied namens Kiran | Derselbe Abgleich, diesmal mit einem Ladennamen. |
refund -483.50 | Buchte eine Belastung von €483.50 | Die 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.
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.
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.
| Feld | Regel-Parser (gelöscht) | amount_only (aktiv) | Modellstufe (angebunden, ohne Schlüssel) |
|---|---|---|---|
| Betrag | Aus mehreren Zahlen geraten | Eine eindeutige Zahl, sonst leer | Im Kontext gelesen |
| Beschreibung, Kategorie | Lexikon-Treffer | Immer null | Aus dem Satz extrahiert |
| Beteiligte, Ausschlüsse | Unscharfer Namensabgleich | Immer leer | Zu echten Mitglieds-IDs aufgelöst |
| Zahler | Aus der Formulierung abgeleitet | Immer leer | Benannt, mit einem nullbaren Betrag |
| Gesamtkonfidenz | Pro Feld feinjustiert | Fest auf 0.3 | Pro Parse |
| Gemeldeter Prompt | Es gab keinen | Null, es wurde kein Prompt gelesen | Prompt-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.
Beliebte Beiträge
- Append-only-Ledger für geteilte Ausgaben8 Min. Lesezeit
- Warum das Ändern einer Ausgabe die Aufteilung neu setzt8 Min. Lesezeit
- Sechs Geldfehler bei Ausgaben in mehreren Währungen8 Min. Lesezeit
- Abrechnen: Gruppenausgaben mit wenigen Überweisungen5 Min. Lesezeit
- Rechnung aufteilen, wenn ein Gericht nicht geteilt wurde9 Min. Lesezeit