What did we lock in? Let the model read the contract and code do the math
"Our computing bill went up on October 1 and I did not decide that." Founders who rent GPUs by the hour hear a version of this every time a provider changes its price list, and the honest answer to "how much will it cost us?" is "it depends on which of our agreements moves." Finding out is a document problem: the answer is spread across order forms, commitment letters and invoices. It is also a good place to see where a model belongs in a finance workflow, and where it does not.
Start with what happened. Nebius lists its on-demand prices per GPU-hour, the price of renting one GPU for one hour. From October 1, 2026, its pricing page shows the H100 at $4.50, up from $3.85; the H200 at $5.40, up from $4.50; the B200 at $8.50, up from $7.15; and the B300 at $9.50, up from $7.85. That is a rise of about 16.9 percent on the H100, 20 percent on the H200, 18.9 percent on the B200 and 21 percent on the B300. The same page says that from October 8, 2026, preemptible pricing on those platforms switches to dynamic spot pricing that "can change during use as often as every 15 minutes." It says nothing about signed commitments. A price list tells you what a stranger pays. Your bill depends on what you signed.
Computing agreements come in roughly three kinds. Pay-as-you-go moves whenever the list moves. A short commitment fixes a rate for some months in return for a minimum. A long commitment usually has the lowest rate and the longest obligation: you owe it whether the machines run or sit idle. To know your exposure you need, for every agreement, four facts: the rate, whether it is fixed or floating, the end date, and the minimum owed. Those facts live in prose and tables, in PDFs nobody has opened since signing. Reading them is what models are good at. Multiplying them is not.
Step one: extraction into a typed schema. Give a model each agreement and ask for structured output against a schema, not a summary. Something like:
agreement_id, provider, gpu_type
rate_per_gpu_hour_cents (integer)
rate_kind (fixed | floating)
gpus_covered (integer)
term_end_date (date, or null)
minimum_commitment_cents (integer, or null)
source (document, page, and the exact quoted text, for every field above)
Two rules make the output usable. First, every field carries a pointer to where it came from, down to the quoted words, so a reviewer can check the field against the page in seconds instead of rereading the contract. Second, a missing fact is null, never a plausible guess. A model asked to fill every field will invent an end date; a schema that allows null, and a reviewer who sees which fields are null, will not.
Step two: validation in code. Before anything is computed, plain code checks the extraction: the types parse, the enums are legal, dates are real dates, a fixed rate has an end date, a minimum is not negative, the quoted source text actually appears in the document. A record that fails goes to a person with the reason attached. This is the same discipline good document-intake pipelines use for invoices: a field the model could not read is recorded as missing, never as a pass.
Step three: the math in deterministic code, in integer cents. The exposure calculation is a pure function of the validated fields: for each floating line, GPUs times hours times the change in rate. It runs in integer cents or decimal arithmetic, never binary floating point. Python's documentation puts the reason plainly: in binary floating point 0.1 + 0.1 + 0.1 - 0.3 is not zero, and "for this reason, decimal is preferred in accounting applications which have strict equality invariants." Every output figure carries the list of fields it was computed from, so each number traces back through the schema to a quoted line in a signed document. Run the same inputs tomorrow and you get the same answer to the cent, which no prompt can promise.
Step four: a person reads the result. The output is a table and its sources, not a decision. Renewing, moving workloads or renegotiating is a judgment that belongs to a person.
The split is the point. Equipment systems built this way already work like this: a model reads invoices and plates into fields, and depreciation is computed by the ledger's own code, never by the model. A model doing arithmetic in prose is slow to check and sometimes wrong in ways that look right. A model filling fields that code then multiplies is fast to check and wrong only in ways a reviewer can see.
Here is the arithmetic on an invented team. It runs 64 H100s all month, about 730 hours. If everything is pay-as-you-go, the rise is 65 cents an hour, so the code computes 64 times 730 times 65 cents: 3,036,800 cents, which is $30,368 more a month, or $364,416 over a year. Now suppose the extraction finds that 40 of those GPUs sit under a 12-month agreement with rate_kind "fixed" at the old rate, ending next August. Only 24 GPUs float: 24 times 730 times 65 cents is $11,388 a month, 37.5 percent of the first answer. Same team, same GPUs. The difference is one field in one contract, and the table shows which page it came from. The same function answers the next question in milliseconds: if the list moves another 20 percent next quarter, which lines change and by how much?
A word on the books. Rented computing is a bill, recorded in the month you use it. Only hardware you own goes on your equipment list, where it loses value on paper month by month. A long commitment can sometimes count as a lease, and that call belongs to your accountant, so ask when you sign.
What to do on Monday. Write the schema above for your own computing agreements, and fill it by hand for your three largest, with the page and quote for every field. Then write the exposure function in code, in cents, with a test that recomputes this post's example ($30,368 and $11,388). Run it against a 20 percent rise in every floating rate. If any field had to be left null, that is the question to put to the provider or your finance lead before the next renewal.
General information, not tax advice. Your accountant knows your situation.
Sources:
Python documentation, "decimal: Decimal fixed-point and floating-point arithmetic"
