COA Mapper v1

The first open model for chart-of-accounts mapping: given a ledger account from QuickBooks Desktop or Sage 50 (name + type), retrieve the correct target account in the client's new QuickBooks Online chart of accounts.

A 33M-parameter embedding model (BAAI/bge-small-en-v1.5, fine-tuned) — small enough to run on CPU, in a browser, or inside a migration tool.

Results — COA-Map-Bench v1

Test split of gyaanbyte/coa-mapping-synthetic: 137 mappings from 4 held-out companies (2 QuickBooks Desktop, 2 Sage 50) never seen in training. Candidates = the distinct target accounts of the same company (i.e. mapping into the client's new QBO COA). A top-1 hit implies the correct QBO type and detail type.

Method acc@1 acc@5 MRR
TF-IDF (char 2–4-grams, cosine) 0.745 0.949 0.824
bge-small-en-v1.5 zero-shot 0.796 0.956 0.868
qwen3:8b zero-shot (picks from the candidate list) 0.788 — —
coa-mapper v1 (this model) 0.883 0.964 0.924

Read the numbers honestly: the benchmark is synthetic, and account names carry strong lexical signal (TF-IDF already gets 74.5%). The fine-tune's gain lives in the hard 25% — abbreviations, near-duplicates to consolidate, dumping-ground splits, type/detail-type disambiguation. An adjudicated benchmark subset is planned for v1.1.

Try it

🧪 Live demo — runs in your browser via Transformers.js (int8 ONNX included in this repo under onnx/; nothing is uploaded).

Usage

from sentence_transformers import SentenceTransformer
m = SentenceTransformer("gyaanbyte/coa-mapper")

# Source accounts as "name (type) [system]"; targets as "name — type / detail type"
src = ["Accum Depr - Equipment (fixed asset) [quickbooks desktop]"]
targets = [
    "Accumulated Depreciation — Fixed Assets / Accumulated Depreciation",
    "Equipment — Fixed Assets / Machinery & Equipment",
    "Depreciation Expense — Other Expense / Depreciation",
]
S = m.encode(src, normalize_embeddings=True)
T = m.encode(targets, normalize_embeddings=True)
print(targets[(S @ T.T).argmax()])

In production we use it as retrieval → LLM re-rank of the top-5 → confidence threshold → human review lane: the goal is hours saved per migration at $0 reconciliation variance, not unattended automation.

Training

  • Base: BAAI/bge-small-en-v1.5 · loss: MultipleNegativesRankingLoss (in-batch negatives)
  • Data: 1,025 (source → target) pairs, train split of the dataset above
  • 4 epochs, batch 32, lr 3e-5, fp16 — 12 seconds on one RTX 5060 laptop GPU
  • Training/eval code: coa_train.py (open)

Limitations

  • Trained and evaluated on synthetic data; real ledgers are messier and more idiosyncratic
  • Target side is QuickBooks Online only; sources are QuickBooks Desktop and Sage 50
  • English, US-GAAP-oriented account structures
  • Candidate pool must be supplied (the target COA); this model does not invent accounts

Who's building this

GyaanByte Labs — accounting data-migration specialists (6+ production migrations, 200,000+ records, $0 variance). The mapper is the engine behind our migration service; the reusable parts are published openly.

Downloads last month
-
Safetensors
Model size
33.4M params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for gyaanbyte/coa-mapper

Quantized
(24)
this model

Dataset used to train gyaanbyte/coa-mapper

Space using gyaanbyte/coa-mapper 1

Evaluation results