Automated GL coding & invoice routing (Beta)
Task: given an invoice's text (sender, product, description) and its company, predict three things a finance team would otherwise fill in by hand:
- Processor โ which employee should handle it
- Acceptor โ who approves it
- GL code โ the accounting category (32 codes)
Processor and acceptor are company-scoped cross-table link predictions (invoice โ employee). The corpus is Zipf-distributed, so invoice volume concentrates on the large companies: a test invoice's company has ~157 employees on average (the candidate pool), of which only ~9 are plausible acceptors in that company's history. That high-cardinality, company-scoped link is exactly the kind of target plain bag-of-features models handle poorly. Aito predicts each field independently from the invoice text and company alone โ the targets are never inputs.
Methods. Aito is measured with both engines โ v1 (rep1 / TableDb,
/api/v1) and v2 (rep2 / CollectionDb, /api/v2) โ from the
InvoiceRoutingEvaluation booktest. Baselines are a tuned scikit-learn Random
Forest, LightGBM (with a company-local class-index encoding) and FLAML
AutoML, all scored on the identical 200-row held-out test set with
company-scoped candidate masking for the link targets; reproduction scripts and
method notes live in benchmarks/invoice-routing/.
Top-1 accuracy (10k training rows, 200-row test)
| Target | RF | LightGBM | FLAML | Aito v1 | Aito v2 |
|---|---|---|---|---|---|
| GL code (32 classes) | 53.0% | 32.0% | 67.0% | 66.5% | 68.5% |
| Processor (high-cardinality link) | 8.0% | 4.5% | 17.0% | 10.5% | 19.5% |
| Acceptor (link) | 29.0% | 42.5% | 59.5% | 27.5% | 68.5% |
<sub>Provenance: dataset invoice-routing (InvoiceData synthetic, Zipf) ยท scale
10k train / 200 test ยท Aito from booktest InvoiceRoutingEvaluation
compare-* (v1 = rep1, v2 = rep2) ยท RF / LightGBM / FLAML from the Python
baselines in benchmarks/invoice-routing. Every figure is a build-time
metric token resolved from a committed metrics.json โ nothing here is
hand-typed.</sub>
Read honestly โ Aito v2 tops every row, but not every margin is decisive:
- GL code โ Aito v2 wins narrowly (68.5% vs FLAML's 67.0%), with Aito v1 (66.5%) just behind FLAML, and the tree models beaten decisively (RF 53.0% / LightGBM 32.0%). The field-level priors carry the low-cardinality target well โ with no training. The v2-vs-FLAML margin is inside the n=200 noise band; call it a tie at the top.
- Processor โ the hard cross-table target, where the tree models nearly collapse (RF 8.0%, LightGBM's local-index encoding 4.5%). Aito v2 (19.5%) now edges FLAML AutoML (17.0%), with Aito v1 (10.5%) third โ again a small margin on a small test set, so read it as parity-or-better.
- Acceptor โ the clearest Aito win, and a reversal of this page's earlier baseline (where FLAML led and Aito trailed badly). Aito v2 reaches 68.5%, clearly ahead of FLAML (59.5%) and LightGBM (42.5%); v1 (27.5%) still trails, which is the engine gap, not the task ceiling. From text + company alone the acceptor remains genuinely under-determined, so a ceiling below 100% is inherent โ but within that ceiling v2 now converts its rank advantage (below) into top-1.
What changed: earlier published baselines of this suite had FLAML as the strongest method on the two link targets. The engine's scoring redesign โ mediation-aware link scoring plus property-based inference over the linked row's fields โ closed exactly that gap, and the re-baselined booktest snapshots now put Aito v2 first on all three targets. FLAML AutoML remains the strongest baseline โ closest on every row โ and what it costs to get there (a per-target hyperparameter search) is the training-time row.
v1 vs v2: the rank story
Mean rank of the true candidate shows where the accuracy comes from. On the link-heavy targets, v2's cross-table link priors rank the true candidate consistently higher than v1 โ and both engines' ranks improved further under the scoring redesign:
| Target | v1 mean rank | v2 mean rank |
|---|---|---|
| Acceptor | 2.2 | 1.8 |
| Processor | 114.5 | 35.5 |
| GL code | 4.3 | 3.7 |
<sub>Provenance: mean rank of the true candidate (lower is better) from the
same InvoiceRoutingEvaluation compare-* snapshots. Acceptor/processor are
ranked within the invoice's company (~157 employees on average); GL code within
the 32 codes.</sub>
For acceptor, v2 puts the correct employee at rank 1.8 on average โ near the top of the ~9 plausible acceptors โ with v1 close behind at 2.2 (both a large improvement over this page's earlier baseline, where v1 ranked the true acceptor in the mid-20s). For processor, the gap between engines is still wide: v2 reaches rank 35.5 out of the ~157-employee company pool, ~3ร better than v1's 114.5. Earlier baselines showed this rank advantage without a top-1 advantage โ the signal was there but the final tie-break wasn't. The scoring redesign converted the ranks into top-1 wins; processor's mean rank says there is still headroom left on the hardest target.
The number that isn't accuracy: training time
| Method | Time to absorb new data (update the model) |
|---|---|
| Aito (v1 or v2) | 0 s โ incremental; new rows are queryable immediately |
| Random Forest | 2 s (full refit) |
| LightGBM | 576 s (full refit) |
| FLAML AutoML | 398 s (budgeted search, per target) |
<sub>Provenance: trainSeconds from the Python baseline result files
(benchmarks/invoice-routing/results/*.json); Aito's 0 s is architectural โ
rows are queryable on insert with no fit step.</sub>
This is the part a top-1 table hides. Every baseline needs a retraining
pipeline to absorb new invoices; Aito absorbs them on insert, with a $why
explanation behind every prediction. FLAML, the closest baseline, pays
~398 s of search
per target and must be re-run when the data changes โ and on this baseline
it still trails Aito v2 on all three targets. On a workload where routings
change weekly, "0 s, explainable, and at-or-above the tuned baselines" is the
whole trade.
How to read this
- Aito v2 leads top-1 on all three targets โ with no training and full
$whyexplanations. But grade the margins honestly: acceptor (~9pp over FLAML) is the substantive win; GL code (~1.5pp) and processor (~2.5pp) are inside the n=200 noise band โ read those as "at least parity with a tuned AutoML search". - The jump is the scoring redesign, not a new corpus: mediation-aware link scoring plus property-based inference over the linked row's fields is what moved the link targets (earlier baselines of this page had FLAML ahead on both). The same redesign also lifted the rank story on both engines.
- Acceptor top-1 remains partly intrinsic: text + company under-determines who approves, so a ceiling below 100% is inherent, not just a model gap.
- Statistics: n=200 test set (95% CI โ ยฑ7pp at 50%), single synthetic-data seed. Read the direction โ which method handles which target โ as the durable signal; treat individual cells as point estimates.
- Same corpus family, larger scale: the Performance benchmark runs this same InvoiceData corpus family across a 1k โ 10M scaling ladder, measuring accuracy, rank and latency at each point โ so if the two pages show different accuracy, it's scale and engine tuning, not a different dataset. The baselines on this page exist only at this 10k point; they have not been run at 1M or 10M, so nothing on either page claims that the tree/AutoML methods plateau while Aito keeps climbing. That cross-method comparison at scale is still to be done.
Generated. Aito's figures are interpolated at docs-build time from the
InvoiceRoutingEvaluation compare-* booktest snapshots, and the RF /
LightGBM / FLAML figures from the committed Python baseline result files
(benchmarks/invoice-routing/results/*.json) โ both via metrics.json files
the docs generator produces. They update whenever the evaluation is
re-baselined and can't silently drift; nothing on this page is hand-typed.
Multi-scale accuracy for Aito now lives on the
performance page's scaling ladder
(1k โ 10M); running the baselines at those scales is still a follow-up.