DEV Community

Koustubh
Koustubh

Posted on

Hishob (हिशोब): A Private Money Dashboard With a Local AI That Finds Where It Goes

Part of gharasathi, a private household AI. Start here for all the series. This one follows on from gharasathi: Building a Household AI, which set out the idea on a $200 mini PC. This one is about the part I use every week: money.

Hishob (हिशोब) is Marathi for "accounts", as in keeping account of things. It's the money dashboard of gharasathi, and its job is simple to state: show me where the household's money goes, and point at the places where we're paying more than we need to.

What changed since the first series

The first series ran everything on a 6 GB mini PC with a 3B model, and part 2 ended with "a better LLM requires better hardware". That hardware arrived: a Mac Studio (M3 Ultra, 96 GB unified memory). It now hosts most of the household's private services:

  • Immich: our photo library, off iCloud and Google Photos (a post of its own later)
  • Nextcloud: documents, plus the bills and statements this series is about
  • llama.cpp serving Qwen3.5-122B-A10B: the model behind everything "AI" here
  • A k3d cluster running the gharasathi services

The mini PC still runs the media server and other services with little to do. The finance stack moved because the model had to be big enough to reason about money, and close enough to the data that nothing has to leave the house.

The architecture

Hishob architecture

As before, every service has a Marathi name:

Service Meaning What it does
aapla-dhan (Go) "our wealth" Syncs bank accounts through Australia's Consumer Data Right into Neo4j. I start each sync by hand, about once a week.
aapla-patrakar (Go) "our reporter" Reads bills and statements from labelled Gmail folders and a Nextcloud drop folder, and files the PDFs.
aapla-olakh (Go) "our recognition" Hand-written PDF parsers that pull out fields and check each document's own arithmetic.
aapla-hushar (Python, FastAPI, LangGraph) "our clever one" Rule-based detectors, the overnight AI analyst, and anna, the chat assistant.
aapla-hishob (React) "our accounts" The dashboard.

Only two things reach outside the house, and both only read: the bank feed (through an accredited CDR intermediary) and Gmail over IMAP. All inference runs on the Mac Studio.

All the accounts, not just one

Most budgeting apps see a single transaction account. Hishob sees the whole household balance sheet, pulled through Australia's Consumer Data Right (open banking): read-only, consented per account, and revocable from the bank's app.

Account Type What it adds
Everyday account transaction Day-to-day spending, bills, salary
Offset account transaction, offsets the loan Savings that reduce mortgage interest every day
Home loan mortgage Balance, repayments, and the interest actually charged

Having all three in one graph is what makes the dashboard more than a spending tracker:

  • Spending is counted once. Moving money between our own accounts, or into the offset, isn't spending. Mortgage principal counts as saving (it builds equity), and mortgage interest counts as a real cost.
  • Interest is connected to cash. With the offset balance and the interest charged side by side, the effect is visible: in the months the offset held the most cash, interest per day fell by about a fifth. A rule flags cash sitting in the everyday account that could be reducing interest instead.
  • The mortgage can be modelled. Balance, offset, repayments and an estimated rate all come from the data, so "what if we kept $10k more in the offset?" is a calculation, not a guess.
  • Refunds and reversed debits are matched to the original payment instead of looking like extra income and extra spending.
  • No fake "complete" months. Each bank feed syncs separately. The dashboard only treats data as complete up to the oldest account's last transaction, so one lagging feed can't make a month look cheap.

How the data gets in: semi-automatic, on purpose

Hishob isn't fully automatic, and that's deliberate. Each kind of data comes in the way that keeps the most control in our hands.

Data How it arrives Who does what
Bank transactions Pulled once a week I start the sync by hand. Nothing touches the bank feed unless I ask.
Bills and statements Forwarded to a dedicated mailbox Gmail filters label each one by type (gharasathi/utilities, gharasathi/childcare). The nightly job reads only those labels, read-only, and the parsers take it from there.
Anything else Dropped into a Nextcloud folder The same nightly job picks it up and files it.

So the routine is: forward a bill when it arrives, and press sync once a week. Everything after that, from parsing and filing to matching, the rules and the analyst, runs overnight on its own.

One graph: the bank and the paperwork

Everything lands in a Neo4j knowledge graph, so a debit, the bill it paid and the line on that bill are connected, not just sitting in separate tables.

Hishob knowledge graph

  • The bank side: each Account (everyday, offset, home loan) is the SOURCE_OF its Transactions, about 1,900 of them so far.
  • The paperwork side: an email HAS_ARTIFACT a PDF, the PDF is PARSED_AS a Document, and the document ASSERTS Facts (usage, unit rates, the subsidy, the absence count). Each fact is EVIDENCED_BY the PDF it came from. A bill also creates an Obligation: an amount, a due date, and who it's OWED_TO.
  • The join: code matches each obligation to the transaction that paid it, on the exact amount within a date window. For now that match is computed when the data is read; writing it back into the graph as an edge is next.

The graph is what lets anna answer "what did this debit pay for?" by walking from the transaction to the bill and quoting the line, instead of guessing from a merchant name. Postgres keeps the original records, and the graph is the connected view the assistant and the analyst query.

A small ontology, not a pile of nodes

Those labels and relationship names aren't ad hoc. They form a small ontology: a fixed vocabulary of the kinds of things in a household and the ways they can relate. Only the listed relationships are allowed, so nothing like a generic LINKED_TO edge. Three things follow from that:

  • The model can query it reliably. With a short, known list of node types and relationships, the Cypher that anna writes stays predictable: there's one way to say "this document asserts this fact", not five.
  • Evidence is part of the structure. Every Fact points to the PDF it came from. A link the system guessed, such as a document mentioning an organisation, carries a confidence and a status, so it can be confirmed or rejected instead of being treated as true.
  • It isn't specific to money. Communication → Artifact → Document → Fact → Entity describes any household paperwork. The schema already defines entity types such as Person, Property, Policy, Vehicle and Event, so an insurance renewal or a medical letter fits the same shape without a redesign.

What the dashboard shows

Hishob overview with amounts hidden

Every dollar figure in these screenshots is hidden with the dashboard's own "Hide $" switch. Percentages and charts stay visible, so I can show the dashboard without showing our finances.

  • The month so far against a typical month for the same number of days. Comparing the 14th of the month with a whole previous month made every month look cheap until the last week.
  • Six months of spending by category, with income as a line and one-off payments marked rather than counted.
  • What changed against the usual, and which merchants drove it.
  • Bills & statements: every utility bill and childcare statement, matched to the bank debit that paid it (part 3).
  • Things anna noticed: the part that matters most, covered next.

The star of the show: "Things anna noticed" and Explain

Charts tell you what happened. The bottom of the dashboard tells you what to do about it.

Every morning there is a short, ranked list of findings. Some come from deterministic rules (a price rise, a bill that wasn't paid, a subsidy gap) and some from the overnight AI analyst. Each one carries its evidence: the transactions, or the exact line from a bill. Each one has two buttons:

  • Explain: anna, the assistant running on the local model, reads the finding, pulls the underlying data with her tools and explains it in plain words: what happened, the evidence, and what to do.
  • Resolve: "not an issue". The finding disappears, and the overnight editor learns to rank similar ones lower.

Under every explanation there's a box for follow-up questions, so it reads like a conversation with someone who has all the statements open in front of them.

Three things it caught, with our own data:

"Did we pay that bill twice?" No. The same energy bill amount left our account twice, a week apart. On the bank feed alone, that looks exactly like a double charge. Hishob had the bill itself (read from email, part 3) and matched it to the bank. The first debit was returned by the bank, and the second was the real payment: one bill, paid once. The finding said so in one line.

Childcare subsidy we didn't know we were losing. Australia's Child Care Subsidy covers up to 42 absent days per child per year, and our statements showed we went past it. Explain walked through it: the statement's own count showed the limit was passed in February, and every absent day after that was charged the full fee. My follow-up, "how many absence days have we used this year, and what would one more cost?", got this year's count and the price of an extra day. Now a rule warns us before we reach the limit.

Advice that changed when I gave it context. A finding suggested negotiating the mortgage rate. My follow-up added what the data couldn't know: the loan is on a fixed rate, and our loan-to-value ratio means a new lender would charge Lenders Mortgage Insurance (LMI). The answer changed: refinancing would mean paying LMI again, and repricing a fixed loan means break costs. The real lever was keeping more cash in the offset account. Part 2 shows how this context now reaches the analyst every night.

None of this needed a cloud service. The question, the statements and the answer all stayed on a machine in the house.

How it runs: overnight, like a colleague who reads everything

Nightly pipeline

  1. 01:30: new bills and statements are read and filed.
  2. Hourly: about twenty deterministic detectors run, but only when the data has changed. They cover recurring charges, price rises, duplicates, offset balance, unpaid or returned bills, and childcare subsidy gaps.
  3. 02:30: the AI analyst reads exact "fact packs" built by code and writes findings, which are then fact-checked (part 2).
  4. Morning: the dashboard and anna show the results.

The rule that shaped everything: code counts, the model explains

The first series learned this on a 3B model, and it still holds at 122B. The model never adds up money. Code computes every total, average and match. The model gets those exact figures and does the part code is bad at: noticing that two things are related, explaining why, and suggesting what to do. A fact-checker then rejects any finding that contains a dollar figure or percentage that doesn't trace back to the data.

Part 2 covers how that works with Qwen on the Mac Studio. Part 3 covers bills and statements, which turned out to hold the most valuable findings.

What's next in this series

  • Part 2: Running Qwen3.5-122B on a Mac Studio as a household finance analyst, and keeping it honest
  • Part 3: Reading bills and statements without AI, and what they revealed

Money is just where it starts. Once the data stays home, a capable model runs next to it, and the ontology has room for more than money, the possibilities are wide open. Any part of household life that leaves a record can get the same treatment: code does the counting, and the model explains.

Top comments (0)