[PR #7657] feat : Add Transaction Categorization with an ML Model #56620

Open
opened 2026-05-01 04:36:22 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/actualbudget/actual/pull/7657
Author: @espoirMur
Created: 4/29/2026
Status: 🔄 Open

Base: masterHead: apply-ml-categorization


📝 Commits (9)

📊 Changes

20 files changed (+1009 additions, -29 deletions)

View changed files

ml-models/classifier.onnx (+0 -0)
ml-models/classifier_classes.npy (+0 -0)
📝 package.json (+1 -0)
📝 packages/desktop-client/package.json (+4 -1)
📝 packages/desktop-client/src/components/Modals.tsx (+4 -0)
packages/desktop-client/src/components/modals/MLCategorizationModal.tsx (+274 -0)
📝 packages/desktop-client/src/components/transactions/SelectedTransactionsButton.tsx (+20 -2)
📝 packages/desktop-client/src/modals/modalsSlice.ts (+7 -0)
packages/desktop-client/src/workers/ml-categorization.client.ts (+101 -0)
packages/desktop-client/src/workers/ml-categorization.worker.ts (+261 -0)
📝 packages/desktop-client/vite.config.mts (+15 -1)
📝 packages/loot-core/src/platform/server/asyncStorage/index.ts (+58 -23)
📝 packages/loot-core/src/platform/server/fs/index.ts (+4 -0)
📝 packages/loot-core/src/server/accounts/sync.ts (+4 -0)
📝 packages/sync-server/docker-compose.yml (+1 -1)
📝 packages/sync-server/docker/alpine.Dockerfile (+1 -0)
📝 packages/sync-server/docker/ubuntu.Dockerfile (+1 -0)
📝 packages/sync-server/src/app.ts (+29 -1)
tsconfig.tsnode.json (+8 -0)
📝 yarn.lock (+216 -0)

📄 Description

Description

Yes!

So thank you for this amazing product, I was working with it for a couple of day and I notice for some of my transaction the rules are not being apply correctly.

I though It would be nicer to have a ML model that is trained on the notes to predict the category of the other upcoming notes.

My ideas was to have it categorize the transaction after the rules are applied, all the transaction that are left at that stage , you can select them and apply the ML Categorization to it.

So I vibe coded this stuff, I am not a front end engineer, I did javascript a long time ago.

Approach! (Overview of the Architecture)

  • I start with an ONNX pipeline that is trained for trasnsaction classification.

  • The ML Inference uses a web worker which is the same approach used by the database operations(I think.. 🤔).

The ML models and the class files are served via http(They are not big models, I didn't want to go with big model as small models can perform inference here). I don't need a big model that requires a GPU for this that is why I am using (WASM).
The inference is done both on the main thread and the server backend thread.
I am thinking we can load the model in the local storage and leave it there. But that for the future.

When you select all uncategorized transaction, it open a modal that show the predicted transaction by the model, the user can check the transaction and validate them. (But this seems to be like double work). I am thinking of showing the predicted categories on the same page as the uncategorized transaction and forget about the modal, please let me know what you guys think of this.

How to Test

  1. Start sync server: yarn start:server-dev (serves model files on port 5006)
  2. Start web frontend: yarn start (port 3001)
  3. Open app, go to an account with uncategorized transactions
  4. Select transactions → "Predict with ML"
  5. Review predictions in modal → edit if needed → "Apply Predictions"

Let me know what you think I will share more instruction on how to test later, and fix the remaining bugs.

Testing

Checklist

  • Release notes added (see link above)
  • No obvious regressions in affected areas
  • Self-review has been performed - I understand what each change in the code does and why it is needed

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/actualbudget/actual/pull/7657 **Author:** [@espoirMur](https://github.com/espoirMur) **Created:** 4/29/2026 **Status:** 🔄 Open **Base:** `master` ← **Head:** `apply-ml-categorization` --- ### 📝 Commits (9) - [`242d082`](https://github.com/actualbudget/actual/commit/242d08273116ebf29a862b3c22c7358a998fd901) updtate docker image - [`c5fa082`](https://github.com/actualbudget/actual/commit/c5fa082558ba1b48437337e310541546a3b309b7) Merge branch 'master' of https://github.com/actualbudget/actual - [`495adac`](https://github.com/actualbudget/actual/commit/495adac138bddb58b87898cdc61f2ce854ed2e03) add ml transaction rule - [`5c82da8`](https://github.com/actualbudget/actual/commit/5c82da8e94a6e9df266b2aa3d10076eae3cc9079) wip integrate ml model - [`0ec33b7`](https://github.com/actualbudget/actual/commit/0ec33b79d730dfc9f0f2ac82e9496aba12a2e6b8) fix the prediction flow - [`ac14387`](https://github.com/actualbudget/actual/commit/ac1438736996e249ad7428253b926438cf954742) kimi implementation of service workers - [`55c113d`](https://github.com/actualbudget/actual/commit/55c113dd191d90b9682db42af31f4ed2bfc8a9d5) fix the output thing - [`0a375c4`](https://github.com/actualbudget/actual/commit/0a375c4207e7d84842e8b87f5cb2e500d05c393f) fix the modal the modal works now correctly. - [`a819fd2`](https://github.com/actualbudget/actual/commit/a819fd261611fcbd177cc4bc71ba2be1419a2202) apply the feedback from the ai ### 📊 Changes **20 files changed** (+1009 additions, -29 deletions) <details> <summary>View changed files</summary> ➕ `ml-models/classifier.onnx` (+0 -0) ➕ `ml-models/classifier_classes.npy` (+0 -0) 📝 `package.json` (+1 -0) 📝 `packages/desktop-client/package.json` (+4 -1) 📝 `packages/desktop-client/src/components/Modals.tsx` (+4 -0) ➕ `packages/desktop-client/src/components/modals/MLCategorizationModal.tsx` (+274 -0) 📝 `packages/desktop-client/src/components/transactions/SelectedTransactionsButton.tsx` (+20 -2) 📝 `packages/desktop-client/src/modals/modalsSlice.ts` (+7 -0) ➕ `packages/desktop-client/src/workers/ml-categorization.client.ts` (+101 -0) ➕ `packages/desktop-client/src/workers/ml-categorization.worker.ts` (+261 -0) 📝 `packages/desktop-client/vite.config.mts` (+15 -1) 📝 `packages/loot-core/src/platform/server/asyncStorage/index.ts` (+58 -23) 📝 `packages/loot-core/src/platform/server/fs/index.ts` (+4 -0) 📝 `packages/loot-core/src/server/accounts/sync.ts` (+4 -0) 📝 `packages/sync-server/docker-compose.yml` (+1 -1) 📝 `packages/sync-server/docker/alpine.Dockerfile` (+1 -0) 📝 `packages/sync-server/docker/ubuntu.Dockerfile` (+1 -0) 📝 `packages/sync-server/src/app.ts` (+29 -1) ➕ `tsconfig.tsnode.json` (+8 -0) 📝 `yarn.lock` (+216 -0) </details> ### 📄 Description <!-- Thank you for submitting a pull request! Make sure to follow the instructions to write release notes for your PR — it should only take a minute or two: https://github.com/actualbudget/docs#writing-good-release-notes. Try running yarn generate:release-notes *before* pushing your PR for an interactive experience. --> ## Description Yes! So thank you for this amazing product, I was working with it for a couple of day and I notice for some of my transaction the rules are not being apply correctly. I though It would be nicer to have a ML model that is trained on the notes to predict the category of the other upcoming notes. My ideas was to have it categorize the transaction after the rules are applied, all the transaction that are left at that stage , you can select them and apply the ML Categorization to it. So I vibe coded this stuff, I am not a front end engineer, I did javascript a long time ago. #### Approach! (Overview of the Architecture) - I start with an ONNX pipeline that is trained for trasnsaction classification. - The ML Inference uses a web worker which is the same approach used by the database operations(I think.. 🤔). The ML models and the class files are served via http(They are not big models, I didn't want to go with big model as small models can perform inference here). I don't need a big model that requires a GPU for this that is why I am using (WASM). The inference is done both on the main thread and the server backend thread. I am thinking we can load the model in the local storage and leave it there. But that for the future. When you select all uncategorized transaction, it open a modal that show the predicted transaction by the model, the user can check the transaction and validate them. (But this seems to be like double work). I am thinking of showing the predicted categories on the same page as the uncategorized transaction and forget about the modal, please let me know what you guys think of this. ## How to Test 1. Start sync server: `yarn start:server-dev` (serves model files on port 5006) 2. Start web frontend: `yarn start` (port 3001) 3. Open app, go to an account with uncategorized transactions 4. Select transactions → "Predict with ML" 5. Review predictions in modal → edit if needed → "Apply Predictions" ## Related issue(s) Let me know what you think I will share more instruction on how to test later, and fix the remaining bugs. <!-- e.g. Fixes #123, Relates to #456 --> ## Testing <!-- What did you test? How can we reproduce the issue you are fixing or how can we test the feature you built? --> ## Checklist - [ ] Release notes added (see link above) - [ ] No obvious regressions in affected areas - [ ] Self-review has been performed - I understand what each change in the code does and why it is needed <!--- actual-bot-sections ---> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-05-01 04:36:22 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/actual#56620