Chapter 02 · Section II · 16 min read
Categorising transactions against your chart of accounts
A generic LLM will categorise like a generic American bookkeeper — confidently, fluently, and wrong about your firm in ways you may not notice for months.
The single most consistent way I have seen Nepali firms get burned by an LLM is not OCR mistakes and not hallucinated numbers. It is categorisation. You feed a clean, accurate list of transactions to a model, and it returns categorisations that are linguistically correct, structurally plausible, and quietly disconnected from the chart of accounts your firm actually uses. The trial balance still balances. The management accounts still print. But the picture they paint is subtly wrong — wrong enough that decisions made on top of them go a little sideways for a quarter before anyone realises why. This section is about closing that gap on purpose.
The model’s default chart is not your chart
When you ask any general-purpose LLM to categorise a transaction without telling it anything about your firm, it will reach for the chart of accounts it has seen most often. That chart is American. It has “Office Supplies,” “Meals & Entertainment,” “Software Subscriptions,” “Cost of Goods Sold,” “Marketing Expenses.” It does not have your firm’s account structure. In a Nepali context that gap can be wide.
A firm reporting under NFRS for SMEs is keeping books to a different account taxonomy than the one a Delaware C-corp would use. A firm under NAS for larger reporting has different segmentation again. A firm whose accountant has, perfectly reasonably, built a custom IRD-friendly chart over fifteen years of practice — with separate accounts for purchase from VAT-registered vs unregistered suppliers, with TDS-bearing service expense split by section of the Income Tax Act, with foreign currency revaluation accounts the firm’s bank actually uses — has a chart no model has ever seen. The model will smile and produce nonsense in a confident voice.
The fix is direct: put your chart of accounts at the top of the prompt, every time. Paste the actual account list — code and name — and instruct the model that the proposed category must be one of these, exactly, by code. If it cannot fit a transaction into the list, it must say so, not invent. This one change does more for categorisation quality than any model upgrade I have seen.
In-context examples earn their weight
A pasted chart is necessary; it is not sufficient. Models categorise by pattern, and the patterns they have learned from the open internet are not your firm’s patterns. The second move, then, is to give the model ten to twenty worked examples from your own books at the top of the prompt, ahead of the new transactions it will categorise.
The examples should be vendor → category pairs that reflect the calls you actually make. Bhatbhateni — Office Supplies (5610) for one firm; Bhatbhateni — Staff Welfare (5640) for the firm that buys monthly groceries for its hostel staff. Daraz — Office Supplies (5610) for one; Daraz — Inventory Purchases (1410) for the small retailer that drop-ships through Daraz. Surya Nepal Pvt Ltd — Sundry Creditors (2110) for the distributor; nothing for the firm with no Surya Nepal relationship. The examples carry the firm-specific information the chart alone cannot.
A short prompt that bundles both moves looks like this:
Below is our firm’s chart of accounts. Below that is a list of twenty recent transactions we categorised correctly, with the chosen account code in brackets. After that, please categorise the new transactions, choosing an account code from the chart only. If a transaction does not fit any account in the chart, mark it
UNCATEGORISED — review. Do not invent account names. For each row, return: date, narration, amount, proposed_account_code, confidence (high/medium/low), and reason in one short phrase.
The Daraz problem
A specific failure mode deserves its own name, because it accounts for a disproportionate share of categorisation pain. Call it the Daraz problem.
A vendor name like “Daraz” — or “Bhatbhateni,” “Hamrobazar,” “Foodmandu,” “Pathao” — appears on a card statement with no further context. The model sees “Daraz” and reaches for the most common interpretation in its training data: a consumer marketplace, probably an office-supplies purchase. For one firm, that is exactly right. For another — a firm whose owner has been using their company card to buy groceries that get reimbursed, or a small retailer that uses Daraz as a wholesale supplier, or a firm that buys staff uniforms there — the same vendor name implies a completely different category.
The model cannot tell which firm you are from the vendor name alone. Firm-specific context wins over global patterns, every time, when the two disagree. The fix, again, is in-context examples and a willingness to correct.
But the deeper move is this: treat every correction as a rule the model now follows, not a one-off override. When you correct Daraz → Office Supplies to Daraz → Inventory Purchases, that correction should be added to the worked-examples block at the top of every future categorisation prompt. Most teams I see lose 80% of the value of AI categorisation here — they correct the row in front of them, ship the batch, and the next month the model makes the same mistake again because no one updated the prompt. The prompt is the firm’s memory of its own categorisation logic. Maintain it like you would maintain the chart of accounts itself.
Edge cases to write rules for, not hope through
There are five edge cases where every Nepali firm’s books have specific conventions, and where a model with no instructions will guess wrong. Name them in the prompt, with the firm’s rule, before the model sees them.
1. Mixed VAT and non-VAT line items on one invoice. A wholesaler’s invoice that includes a VAT-bearing product line and an exempt agricultural product line, or a service component with TDS and a goods component without — the model has to be told to split, not to apply one VAT treatment across the whole invoice. The rule belongs in the prompt explicitly: if line items differ in VAT treatment, treat each line separately.
2. Foreign-currency settlements. A USD invoice paid in NPR at the bank’s selling rate, with the realised FX difference going to a specific revaluation or FX gain/loss account in your chart — name that account in the prompt and show one worked example. Otherwise the model will fold the FX difference into whatever expense account it picked, and your FX exposure becomes invisible.
3. Cash vs accrual timing. Many small Nepali firms keep cash books that look like accrual at year-end and cash mid-year. A model that does not know this will categorise a payment in the same period as the invoice and quietly mismatch your periods. Tell it explicitly: for our firm, expense recognition follows accrual; payment date is informational only.
4. Intercompany and related-party transactions. A payment to a sister concern is not a vendor payment; it is a related-party item that needs separate disclosure under NFRS. Models will, by default, treat it as an ordinary expense. Maintain a small list of related-party names in the prompt and instruct the model to route them to the right control accounts.
5. Round-number “rebate” or adjustment entries. A रू. ५०,००० round-number entry with a narration like adjustment or as per discussion is almost never a routine expense; it is something that needs human judgement, usually about whether it is allowable for tax. The model should be instructed to flag these for review rather than guess at a category.
The three lists you actually review
After the model runs, there are three lists worth a human’s time, and they are the same three regardless of how good the model gets.
The uncategorised list — anything the model marked UNCATEGORISED — review. These are honest; the model told you it did not know. Decide them, add the decisions to the worked-examples block for next time.
The low-confidence list — anything the model marked low or medium confidence. These are the rows where the model was guessing under uncertainty, and they are where silent mis-categorisations live.
The above-materiality list — anything above the firm’s materiality threshold, regardless of confidence. The principle is the same as in OCR: a confidently wrong call on a रू. ५,००,००० entry hurts more than a confidently wrong call on a रू. ५०० entry, and the cost of checking the large entry is small.
A practising bookkeeper who works through these three lists every batch — and updates the prompt with what they decided — will, within two or three months, end up with a categorisation engine that is markedly better than any out-of-the-box tool, because it is specifically theirs.
Check your understanding
Quick check
—A model categorises a Daraz card payment as Office Supplies. For your firm, Daraz purchases are almost always inventory you re-sell on your own storefront. What is the right response?
Quick check
—A junior on your team strips out the vendor column to save tokens and sends the model just date and amount for each transaction. The model returns categorisations with high confidence. Why is this dangerous?
What comes next
You now have books with reasonably accurate data and reasonably correct categories. The next test of any bookkeeping system is whether it agrees with the outside world — whether your bank, your customers, your suppliers, and your tax filings all reconcile against the ledger. The next section is on bank reconciliation with AI assistance: what the model can genuinely accelerate, and where the unmatched-items list still demands your full judgement.