- NVIDIA Nemotron on Nebius Token Factory powers the AI layer through one thin client with the OpenAI-compatible API. Roles map to model IDs in
.env, so models swap without code changes.- Nemotron 3 Ultra explains errors, proposes repair operations and answers chat questions.
- Nemotron 3.5 Lightning, with thinking switched off, copies fields out of PDFs and transcribed scans.
- Nemotron 3 Super is configured as a swappable alternative.
- The one non-NVIDIA step: MiniCPM-V-4.5 on Token Factory reads scanned pages, because no Nemotron vision model was available on my key. It only transcribes. Nemotron does the rest.
- Deterministic validation decides. The model never declares an invoice valid. For an invoice $I$, a rule such as BR-CO-15 is checked by code:
$$\text{TaxInclusive}(I) = \text{TaxExclusive}(I) + \text{VAT}(I)$$
The model only explains and repairs what the validators found. It proposes small edit operations, never a new document. Code applies them and re-validates, and totals are computed by code.
- Grounding. Explanations get only the validator message and the official rule text (1,105 rule texts extracted from ANAF's files). Chat searches those rules offline first, then Tavily on official domains only. Code flags any factual sentence without a valid citation.
- Synthetic data only. I generated 100 invoices with 28 kinds of planted errors (wrong VAT id, missing mandatory fields, bad totals, wrong country codes and more), plus 52 PDFs and 13 degraded scans. No real client data.
- Stack. Python, FastAPI,
lxmlandsaxonche(XSLT 2.0) for validation, a plain HTML, CSS and JS front end with no build step, Docker, hosted on Render (free tier). 165 automated tests run with a fake model, so no key is needed. - Tavily is called at runtime for the cited-source chat answers and an "any newer CIUS-RO release?" check. Only the user's question is sent, with CIFs, CNPs, IBANs and emails removed.
Results
| Check | Result |
|---|---|
| Our verdict vs ANAF's offline validator, 100 synthetic invoices | 100 of 100 same verdict |
| Repair with Nemotron 3 Ultra, 28 invoices | 18 fixed and re-validated, 8 correctly asked for a missing fact, median 2.7 s |
| PDF extraction with Nemotron 3.5 Lightning, 52 PDFs | 97.2% of fields correct, 51 of 52 same verdict, median 2.8 s |
| Scans, 13 synthetic | 97.4% of fields correct, 8 of 11 misreads flagged by checksum checks |
Challenges
- Models don't know Romanian e-invoicing. Asked what an e-Factura needs before ANAF accepts it, Nemotron Ultra, Super and Lightning all wrongly said a qualified digital signature, and Ultra invented a "CIUS-PT" profile. This is why validators come first.
- Memory leaks even when told not to. In chat, with search results that didn't answer the question, Ultra listed outdated VAT rates (19%, 9%, 5%) from memory. Prompts alone did not fix it. I added a code check that flags uncited factual sentences, and the assistant now asks when a question is ambiguous.
- Changing rules. I grounded the tool in the official schemas and rule files instead of model memory, and recorded versions and hashes of every vendored file.
- Matching ANAF exactly. Cross-checking with ANAF's own validator showed two gaps in mine. The standard ISO Schematron compiler silently skips rules on XML attributes, so I patched the compiled XSLT. ANAF also checks seller and buyer identifiers outside the Schematron.
- Fast models are sloppy with formats. Lightning returned Romanian number formats ("2.054,66") despite instructions. Extraction accuracy went from 89.7% to 97.2% once number parsing and address splitting moved into code.
- Scans. Vision models can misread a digit in an IBAN or CUI, and grounding can't catch it because the transcription is the only text. IBAN, CUI and postal-code checks catch most of these, and every scanned value is marked "please verify".
- Live ANAF access. Real submission needs OAuth2 and a qualified digital certificate, so it is out of scope. The app exports the corrected XML for you to send through your usual channel.
- Engineering surprise.
saxoncheobjects are bound to the thread that created them, which crashed FastAPI worker threads until all Schematron work ran on one dedicated thread.
What I learned
- Ask the model to copy, and do conversions in code. Models are good at reading and explaining, and unreliable at formats and arithmetic.
- Hybrid systems work best for compliance: rules engines for correctness, LLMs for communication.
- Thinking off matters. Lightning with
enable_thinking: falseanswered in about 1.3 s, versus a truncated 800-token monologue with it on. - Token Factory made model sizing easy. One endpoint served everything from fast extraction to heavy reasoning. The docs gaps (regional base URL, model IDs that differ from the cookbook, undocumented thinking switch) are logged in
FEEDBACK.md.
What's next
- Live ANAF submission through a certified integration
- Exempt, reverse-charge and zero-rated VAT categories, and credit notes from PDFs
- SAF-T (D406) checks
- Import from popular Romanian accounting software
- A Nemotron vision model for scans, when one is available
- A pilot with real small businesses and their accountants
Log in or sign up for Devpost to join the conversation.