Most B2B portals are quietly held together by people who read, cross-check, and re-type. A request comes in and someone sorts it. A signed contract is uploaded and someone compares it, page by page, against the original. A closing document arrives and someone keys the number, date, amount, and tax into the ERP by hand. None of this is glamorous, and most of it is the kind of work that a model can prepare well enough that a person only has to decide.
This piece is drawn from a real B2B contractor portal that UpSystems (our parent) reviewed for a client under NDA. The portal is a Django/REST/Celery stack that integrates with an ERP and an external analytics system. What follows is a design and a projection, not a deployed, measured outcome — but it is grounded in a system we looked at closely, and in one finding that would have paid for the project on its own.
The hard constraint shaping everything: contractor data never leaves the network. No cloud APIs. Open-weight models run on the company's own GPUs, served through a local OpenAI-compatible endpoint (vLLM), so every request, log, and document stays inside the perimeter. Data sovereignty is not a feature here; it is the reason the architecture exists.
Seven tasks you can actually hand to a model
The useful framing is not "automate the portal" but "for each repetitive step, what does the model prepare, and what stays a human decision?" Seven candidates stood out.
- Triaging incoming requests. Auto-assign topic, queue, and urgency; draft replies to common questions; summarize the non-standard ones; OCR scanned attachments. The human sends or edits.
- Checking signed contracts. OCR the uploaded signed scan and compare it against the portal's original, flagging discrepancies with page and location, and filtering out the "wrong file / missing last page" cases before a person ever opens them. The human accepts or rejects.
- Extracting data from closing documents (acts). Pull number, date, amount, tax, basis, and the linked contract as structured fields. The human handles the low-confidence and mismatch cases.
- Pre-checking submitted forms. At submission time, catch missing fields, wrong units, outliers versus other participants or past periods, and internal contradictions — explained in plain language to the submitter, so the form reaches the expert already clean. The human still does the substantive judgment.
- Drafting schemas for new forms. From a text spec or last year's form, produce a draft JSON schema the portal can render. The human reviews and approves.
- Catalog assistance. A contractor describes a need in their own words; the model suggests items from the live pricelist and explains constraints (mutually exclusive, bundled). The human places the order.
- Nightly reconciliation of portal vs ERP. Each night, compare contracts, amounts, tax rates, and statuses, and produce a morning report of discrepancies. The human fixes.
That last one is worth pausing on. In the portal we reviewed, a tax rate had been hard-coded in two places and the two had drifted apart — sending one number to generated documents and a different one to the accounting system, across hundreds of contracts. Nobody had noticed. A read-only nightly reconciliation would have caught it on the first night. That is the whole argument for starting with the boring, low-risk task: the payoff is not always speed, sometimes it is finding the thing quietly costing you money.
Whose load this lifts
In every case the model prepares and the human decides. The model never writes to the ERP, never signs or rejects a contract, and never exports to an external system on its own. It gets read access, and its output lands in front of a person.
| Role | Routine prep the cascade takes on |
|---|---|
| Support | Request sorting, draft replies, catalog questions |
| Legal | First-pass scan checks, obvious-error filtering |
| Expert | Catching gaps, typos, and unit errors before review |
| Forms specialist | Draft schemas from specs or prior forms |
| Accounting / admins | Manual field entry, ERP mismatch hunting |
The on-prem model stack: a cost cascade
The economics only work if you do not run a heavyweight model on every request. The design is a cascade — cheap and fast first, heavy only when needed.
- Qwen3 vision-language (~27B, FP8) for triage: handles text and images together, long context, Apache-2.0, with adjustable reasoning depth so you spend compute only where the case is hard.
- PaddleOCR-VL, a sub-1B document specialist that beats far larger general models on parsing and returns text, tables, and block coordinates — exactly what the contract-comparison and act-extraction steps need.
- gpt-oss-120b (Mixture-of-Experts, 117B total / 5.1B active, fits one 80GB GPU, Apache-2.0) for the hard multi-step checks and tool use that the smaller models should not attempt.
Hardware is two NVIDIA RTX PRO 6000 Blackwell cards (96GB), served by vLLM behind an OpenAI-compatible API inside the network. Extraction uses JSON-schema-constrained generation so structured outputs are actually structured; prefix caching amortizes the shared parts of prompts; models get read access only; and request logs stay inside the perimeter.
The honest downsides
Open-weight models are weaker than the best cloud models on hard reasoning, which is precisely why hard cases escalate to the heavy model and then to a human. Two GPUs in one box is not high availability. You are now operating this infrastructure yourself. And you should measure quality against a reference set of roughly 100 real cases before launch, then run the first months in suggest-only mode — the model proposes, a human confirms — until the numbers earn more autonomy. The best place to start is nightly ERP reconciliation plus form pre-checks: both read-only, both low blast radius, both measurable within weeks.
What this does to payroll
Note: The table below is a projection built from illustrative assumptions, not a measured client result. We have not deployed this system and cut anyone's payroll. The percentages are hypothetical inputs chosen to be plausible, shown so you can argue with the model and substitute your own numbers.
Model the effect one role at a time: what share of that role's time goes to routine prep, and how much of that prep the cascade can realistically remove (with the human still deciding).
| Role | Time on routine prep (illustrative) | Share the cascade removes | Net time freed |
|---|---|---|---|
| Support | ~60% | ~50% | ~30% of the role |
| Legal (scan checks) | ~40% | ~55% | ~22% |
| Expert | ~30% | ~40% | ~12% |
| Forms specialist | ~35% | ~50% | ~18% |
| Accounting / admins | ~55% | ~55% | ~30% |
Averaged across the affected roles, this lands at roughly a quarter to a third of their routine hours taken off their plate. On a lean team of six to eight people, that is the equivalent of about 1.5 to 2 full-time roles' worth of routine work — which converts to payroll savings only if that freed time is actually reduced or redeployed. If the hours go straight back into more contracts handled, higher-quality review, or faster turnaround, you get capacity instead of savings. Both are real outcomes; they are just not the same line on the budget, and the design does not decide which one you take. The system augments people — the model prepares, the human decides — it does not replace a team wholesale.
Takeaway: The value is not one dramatic automation. It is a dozen small, read-only preparations that arrive already checked, plus a nightly reconciliation that catches the expensive silent errors. Start where the blast radius is smallest, measure against real cases, and let the numbers decide how much you hand over.
Where LLMDeploy fits
This is exactly the kind of system we build: an on-prem cascade of open-weight models — cheap and fast first, heavy only when the case demands it — served inside your own network on your own GPUs, with structured outputs, read-only access, and logs that never leave the perimeter. If you have a portal, an ERP, and people quietly re-typing between them, the pattern above is a starting point, and a measured reference set is how you find out what it is worth on your data rather than on ours.