Repository navigation
Document usage-based billing and the 5.0.x function - #3
Closed
seihyun-jeong wants to merge 78 commits into
Closed
seihyun-jeong wants to merge 78 commits into
seihyun-jeong wants to merge 78 commits into
Conversation
3 tasks done
The guide told every reader that use "is limited to problems requiring at most 20 qubits, unless a license is obtained granting a higher limit". For a usage-based user there is no qubit limit at all, and the way past 20 is to pass function_size="l", not to email sales. The tutorial said the same thing about FeP-NO needing a license for 44 qubits. The guide now opens that part with a table a reader can find themselves in: without a token, or with one. Qubits, what you pay, and whether the size is checked differ between the two, and most readers are in the first column. Trial access is a line under the table rather than a third column, because a column nobody is in slows down the one thing the table is for. Two sections follow it, for the first column: the s/m/l sizes with their fees, and estimate_only, which sizes a problem and returns without running it. Licensing becomes Licensed use and speaks to the second column only. Fees are in resource units, with a link for what a resource unit costs. Our rates were derived at $25 per RU, but that figure is the royalty per RU a user spends, not a price anyone is charged, and the model may still be adjusted — one number here would be wrong somewhere, and wrong about money. Also: the request-access form is no longer how anyone starts, so it goes from Get started and Next steps; the main example and all four tutorial runs name their size; the response fields that were never documented (energy_variance, energy_history, function_version and metadata.resource_usage) are described, with a note that everything which grows with the problem is in the results file instead; and failures are documented as carrying a code, a message and a solution, with the seven codes the function returns. The API reference gains estimate_only, a section on function_size as a platform argument, the two missing output rows and the estimate's own output table. Checked with the repository's own spelling, markdown, internal-link and prettier checks, and by rendering all three pages in the local preview. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dropping it from Get started was right: requesting access was the first instruction a usage-based reader got, for something they never need. But a license still has to be asked for, and the form is how, so it belongs in Licensed use rather than gone. In Next steps it reads "if you need one" — in a list of recommendations an unqualified link reads as something everyone has to do. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The sentence told the reader to authenticate and then, mid-clause, assumed they already had, which sends them back through it. The code below takes no token, so saving the key is the step that matters, and saying so is both shorter and the thing the reader actually does. The key is still required either way. Both links are kept; the one that hung on "saved your account" now hangs on "to your local environment". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The form is titled "request access to the function", so a link labelled "request a license" makes the reader stop and check they clicked the right thing. It now reads "request access and a license", which covers both what they are asking for and what they will see. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Moving the request form out of Get started put it 68% down the page, so someone who needs a license had to read most of a guide written for people who do not. Get started now says in one line how runs are billed and links the two sections, before the step that sets up the key. The signpost goes above that step, not below it: the sentence ends in "as follows:" and the code cell has to be what follows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
It answered a question from our own review of the 4.0.0 docs, where the reviewer asked how putting results_file_name inside job.result() helps when job.result() was the thing returning an empty dictionary. That is worth knowing internally; a reader of the guide only needs to know where the data is, which the two lists already say. It also sat between the h5 file and "This file contains", leaving the reference three paragraphs from what it referred to. That list now names the results file itself. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
"Not checked" described what our code does, not what the reader has to do, and it did not pair with "Required" in the other column. The two cells now answer the same question. The clause about CPU and memory stays: a license run skips the size check entirely, so nothing tells a reader their 44-qubit job is running on the resources for 20. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The tutorial was written when a license was the only way to run the function, and Setup still said you needed one. Adding the size argument to the four run() calls did not fix that: it left notes about sizes and licenses bolted onto Part 1 and Part 2, saying the same thing late and twice. The wrapper library forwards everything except the token, and routes every other attribute to the function it wraps, so a licensed run differs from a usage-based one in the two lines that load the function and nowhere else. Setup now shows both and gives a four-row table of what actually differs, including that running the whole tutorial is six runs at "m" and three at "l" — 18 resource units, which the tutorial never mentioned while asking the reader to execute it. The licensed variant is a fenced block rather than a code cell: this notebook is run top to bottom, and a second load cell would replace hivqe with a wrapper around a token the reader does not have. Part 1 and Part 2 now state their size and leave the explaining to Setup. Also removes a duplicated cell: the 5,110-character geometry_1_75 block appeared twice in a row. That duplicate is in the published tutorial upstream too, so a reader today sees the same block twice and cannot tell whether the two differ. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A reader at this point is about to execute cells and already knows whether they hold a license. The table made them find their column, read four rows across and assemble their own instructions out of it. Two blocks, each complete, let them read only theirs and stop. The comparison table in the guide stays: there the reader's job is to work out which kind of user they are, and comparing the two is how they find out. Here the job is to run the thing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The 5,110-character geometry_1_75 block appears twice in a row, upstream as well as here, so a reader of the published tutorial sees the same block twice. Removing it is right but it is not part of documenting usage-based billing, and it is being discussed separately. Restored from main unchanged, cell id included, so this part of the file does not appear in the diff at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The 134-line geometry_1_75 block is defined twice in a row in Part 2, byte for byte identical, differing only in cell id. Running the notebook is unaffected — the second assignment just repeats the first — so the cost falls entirely on whoever reads it and has to work out whether the two blocks differ. It has been there since the tutorial was added to this repository in cc50fd0 (2025-04-15), where the file arrives as a single addition with no prior history, so it came in with the notebook rather than from any edit here. Twenty-five commits have passed over it since, including our own tutorial fix in 326fbbe. The copy kept is the first, which is the one the markdown above it introduces. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
str_geometries meant three different things, hivqe_result three, and rhf_result, casci_result, molecule_options and hivqe_options two each. Run top to bottom the notebook is correct, but notebooks are not read or run that way: going back to Part 1's plotting cell after Part 2 draws Part 1's classical reference against Part 2's HI-VQE energies, about a thousand hartree apart, with no error to say so. Going back to Part 1's submission loop would submit Li2S geometries with Part 2's 631g* basis and 22 active orbitals, which costs money. Part 1 keeps the plain names. The 34-geometry grid in its Step 4 becomes ref_geometries, since only the classical reference uses it. Everything Part 2 owns takes a _fepno suffix. Renames were applied per cell rather than globally, and checked by walking the code cells in order and resolving every name each one reads against what earlier cells define: no name is undefined before or after, so nothing lost its reference. The plotting cells' own temporaries (hf_energy, distance and the rest) are recomputed from the dictionaries in each cell and are left alone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Part 2's results cell assigns three literal energies with no cell above it to say why, right after three cells that collect the real ones. A reader who waited for their own jobs sees their values replaced and no reason given. They are there so Step 4 works without waiting, which is also why the classical reference in Step 4 is provided rather than computed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
It had a top-level section of its own between Inputs and Outputs, which no reader scanning Inputs for what they can pass would find: they would conclude the argument does not exist. Every other function API reference in this repository is Inputs and Outputs, with one exception that adds Error handling, so a third section is also not the shape of these pages. It is now an Attribute among the others, with "m" as its documented default the way the other arguments carry theirs. Whose argument it is survives as a clause; it changes nothing about how a reader passes it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The next cell tells the reader to check they have access to the function, and until now the answer to "I don't" was the request-access form, which is for licenses. What they actually need is Qiskit Functions access enabled on their instance, which they do themselves when they create it, and which IBM's own guide documents. The sentence goes before the step that saves the key, so the paragraph ending in "as follows:" is still the one the code cell follows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Part 1 had a fourth heading, "Plotting the dissociation curve", that Part 2 does not: its plot sits inside Step 4, where it belongs, since Step 4 is already "post-process and compare with classical methods" and the plot is that comparison. In the contents the two parts looked like different procedures. Only the heading line is gone; the two sentences under it say what the plot shows and stay where they were. The "Step 2 and 3" numbering stays. Other tutorials in this repository number the four pattern steps separately because their reader optimizes a circuit and then executes it; here one function call does both, so splitting it would leave an empty step. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The first example read a saved API key; the licensed example passed the key and the instance inline. Both work, and which you use has nothing to do with holding a license — but having one shape in the usage-based example and the other in the licensed one made it look as though it did, and left a reader wondering whether a license needs an explicit token or instance. Now the only difference between the two examples is the line that wraps the function, which is the only difference there is. It also leaves one meaning of "token" in that cell: the HI-VQE license token, rather than that and the IBM API key together. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
IBM reserved 4630-4639 for this function. The four failures that used to report 1219 are not about the reader's IBM credentials, which is what 1219 says, and not about their license token being wrong either: we cannot read it at our end. The table now says so, and says the reader did nothing wrong. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
seihyun-jeong
force-pushed
the
docs/usage-based-billing-5.0.x
branch
from
October 7, 2026 01:02
791ae36 to
454169f
Compare
In 4.0.0 the result no longer carries "states" or "eigenvector". They are written to an HDF5 results file instead, alongside "final_energy", "final_energy_variance" and "energy_history". The result names that file in "results_file_name". - API reference: drop "states" and "eigenvector" from the result table, add "results_file_name", and point "energy_variance" at the states in the results file. - Guide: show the 4.0.0 result, list what the results file holds, and add examples that create a QiskitServerless client, download the file and read it with h5py. Add a Changelog section that starts at 4.0.0. - Tutorial: install h5py, and download and read the results file for each calculation. Co-authored-by: Shane McFarthing <shane.mcfarthing@gmail.com> Co-authored-by: Rowan Pellow-Jarman <rowanpellow@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 7, 2026
b4e5a46 renamed Part 2's option dictionaries to molecule_options_fepno and hivqe_options_fepno. The rename also changed the keyword names in the three FeP-NO run() calls, so they passed molecule_options_fepno= and hivqe_options_fepno=. The function does not accept those names. Its input check (qiskit_functions/ runner.py, "Check that all arguments the user supplied are recognized") rejects any unknown argument with InputValidationError, code 1221, in every released version from 4.0.1 to 5.0.2. All of Part 2 would therefore fail before anything ran. The keywords are back to molecule_options= and hivqe_options=. The values keep Part 2's own dictionaries. Checked every run() call in the tutorial and the guide against the function's accepted arguments and option names. All nine match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The guide downloaded the results file with serverless.file_download(results_file_name, function) and then opened results_file_name. That fails with FileNotFoundError: without target_name, qiskit-serverless saves the file as downloaded_<8 hex>_<name> (qiskit_serverless/core/files.py, 0.36.0). The comment above the call, "saved ... under the same name", was wrong for the same reason. Pass target_name=results_file_name so the file lands under the name the next line opens, and make the comment say what the call does. The tutorial still asks for the path by hand and is left alone for now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The guide downloaded the results file with serverless.file_download(results_file_name, function) and then opened results_file_name. That fails with FileNotFoundError: without target_name, qiskit-serverless saves the file as downloaded_<8 hex>_<name> (qiskit_serverless/core/files.py, 0.36.0). The comment above the call, "saved ... under the same name", was wrong for the same reason. Pass target_name=results_file_name so the file lands under the name the next line opens, and make the comment say what the call does. The tutorial still asks for the path by hand and is left alone for now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The licensed-use example passed backend_name="ibm_torino". Current qiskit-ibm-catalog checks backend access before it submits a job, so on an instance without ibm_torino the example stops with "Backend 'ibm_torino' is not available or you do not have access to it". It now passes backend_name, as the rest of the guide does, with a comment giving the 14 qubits that H2O in STO-3G needs (7 orbitals). The example also built its catalog from token and instance placeholders, unlike "Get started", which uses the saved account. It now does the same: QiskitFunctionsCatalog(channel="ibm_quantum_platform"). Checked against production 4.0.0 from a test instance. With a placeholder licence token, the job reaches the function and is refused with TokenNotFoundError (1201), as expected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Readers only need estimate_size, but the full estimator took up most of the billing section. The code cell is unchanged and still runs; it is now shown only when the reader opens it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The section listed every option that shapes the active space. Readers need the rule and an example; the size estimator handles the options. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Production goes from 4.0.0 straight to 5.0.x, so the entry lists what changed since 4.0.0. Fixes for problems only -dev ever had are dropped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tutorial said function_size was passed through and not checked on a license. Since 5.0.3 every run is checked, and the size sets the compute the run uses, which a licensed run pays for as classical compute time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only line breaks change: the code parses to the same tree as the function's hivqe_chemistry_size_estimator.py. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A rejected argument gets an exception describing what failed; for an unknown name it does not name the argument. - active_orbitals indexes the orbitals of the basis, not the qubits. - A licensed run is checked against its size and pays for the compute the size sets, but is not charged the per-execution fee. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Every run passed backend_name="", which the argument schema refuses. Setup now picks a backend with enough qubits for Part 2. - Part 1 freezes five orbitals, so its active space is (10o,12e), not (10o,10e) with six frozen; the CASCI reference matches (10o,12e). - 18.0 RU is the per-execution fees; QPU and compute time come on top. - Results files are downloaded under their own names, and the reading example opens one of them instead of a placeholder path. - Drop a stale output of the FeP-NO geometry cell, and the old qiskit-ibm-runtime pin. - Fix typos, and spell HI-VQE as the guide does, in the title too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The title is listed in docs/tutorials/index.mdx and _toc.json, which are not ours to change for a spelling. The body keeps HI-VQE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The published guide, tutorial and API reference still describe the 4.0.0
function. None of the three mentions
function_size,estimate_only,resource_usageor the error codes, and the guide tells every reader their use"is limited to problems requiring at most 20 qubits, unless a license is
obtained granting a higher limit".
For a usage-based user there is no qubit limit at all, and the way past 20 is to
pass
function_size="l", not to email sales. Someone who only had to choose asize sends an enquiry instead. The tutorial said the same thing about FeP-NO
needing a license for 44 qubits.
What a reader sees now
The guide gains a Limits and billing section before the licensing
material, opening with a table a reader can find themselves in: without a
token, or with one. Qubits, what they pay, and whether the size is checked
differ between the two, and the table says which column most people are in.
Trial access is a line underneath rather than a third column. Two sections
follow it for the first column — the
s/m/lsizes with their fees, andestimate_only, which sizes a problem and returns without running it. The oldLicensing section becomes Licensed use and speaks only to the second
column.
Fees are given in resource units, with a link for what a unit costs. Our rates
were derived at $25 per RU, but that figure is the royalty per RU a user
spends, not a price anyone is charged; what a user pays depends on their plan,
and the model may still be adjusted. One number here would be wrong somewhere,
and wrong about money.
The tutorial splits the two kinds of reader once, in Setup, because that is
the only place they differ: the wrapper library forwards everything except the
token, so a licensed run and a usage-based one differ in the two lines that
load the function and nowhere else. Each gets its own short block of
instructions rather than a table to read across. It also states, for the first
time, that running the whole tutorial is six runs at
"m"and three at"l"—18 resource units — which it had been asking readers to execute without
mentioning.
The API reference gains
estimate_onlyandfunction_sizeas arguments,the two output keys that were missing, and a table for what an estimate
returns.
Also fixed while in here
These are pre-existing and not about billing, each in its own commit:
the tutorial, identical, which is also true of the published version
upstream.
str_geometriesmeant three different things andhivqe_resultthree.Running the notebook top to bottom was correct, but going back to Part 1's
plot after Part 2 drew Part 1's classical reference against Part 2's HI-VQE
energies, about a thousand hartree apart, with no error. Each part now has
its own names.
parts looked like different procedures.
look as though a license needs an explicit token and instance.
in Licensed use, where a license is actually asked for.
now points at enabling Qiskit Functions access on the instance.
Checks
The repository's own spelling, markdown, internal-link and prettier checks
pass, and all three pages render in the local preview. The notebook renames
were verified by walking the code cells in order and resolving every name each
one reads against what earlier cells define: no name is undefined before or
after the change.
Not in this PR
loop. Folding it would change code a reader executes, and verifying that
needs a real run — 44 qubits three times, on an instance with QPU access.
request for a reserved block is waiting on the reply, so the numbers may
move.
Note for review
mainholds the 4.0.0 documentation work, which has not gone upstream toQiskit/documentationyet, so this branch must not be merged into it untilthat does — otherwise the two sets cannot be separated for the upstream PR.
🤖 Generated with Claude Code