The most loved feature in Shiguang Ledger is one-sentence bookkeeping: type “taxi 35 yesterday” and it figures out the date, category and amount. Plenty of people assume a large language model is behind it. It isn’t. It’s a rule-based parser of about 200 lines that runs on the phone, fully offline.
Why not an LLM
Logging an expense is frequent and low-stakes. If a call takes half a second longer, costs a fraction of a cent, or needs a connection, people get annoyed. Financial notes are also sensitive, so I’d rather they never leave the device.
Three layers
- Amount. Find the number that looks most like a price, and cope with forms like “28.5”, “twenty-eight” written out, or “two hundred bucks”.
- Date. Turn “yesterday”, “last Friday” or “the night before last” into a real date, defaulting to today.
- Category. A word list of just over 300 entries, matched longest-first. Anything unmatched goes under “Other”, and the parser remembers how the user files it later.
export function parse(input: string, now = new Date()) {
const amount = extractAmount(input);
const date = extractDate(input, now);
const category = matchCategory(input) ?? learned.get(input) ?? "Other";
return { amount, date, category, note: input.trim() };
}
The biggest lesson
Learning matters more than recognizing. Once someone corrects a category, the same phrase is right the next time. After three months accuracy went from 82% to 94%, and the credit goes to users’ own habits rather than a cleverer algorithm.
Mini programs have strict package size limits, and the whole parser minifies to under 8KB. For me that is its best feature.