Skip to content

Document usage-based billing and the 5.0.x function - #3

Closed
seihyun-jeong wants to merge 78 commits into
mainfrom
docs/usage-based-billing-5.0.x
Closed

seihyun-jeong wants to merge 78 commits into
mainfrom
docs/usage-based-billing-5.0.x

Conversation

@seihyun-jeong

Copy link
Copy Markdown
Collaborator

The published guide, tutorial and API reference still describe the 4.0.0
function. None of the three mentions function_size, estimate_only,
resource_usage or 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 a
size 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/l sizes with their fees, and
estimate_only, which sizes a problem and returns without running it. The old
Licensing 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_only and function_size as 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:

  • A cell containing 134 lines of FeP-NO coordinates appeared twice in a row in
    the tutorial, identical, which is also true of the published version
    upstream.
  • str_geometries meant three different things and hivqe_result three.
    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.
  • Part 1 had a fourth heading that Part 2 did not, so in the contents the two
    parts looked like different procedures.
  • The guide's two examples built the catalog two different ways, which made it
    look as though a license needs an explicit token and instance.
  • The request-access form was the first instruction a new reader got. It is now
    in Licensed use, where a license is actually asked for.
  • Nothing said what to do when the function does not appear in the catalog. It
    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

  • Part 2 submits three nearly identical copy-pasted blocks where Part 1 uses a
    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.
  • The error codes are what 5.0.2 returns today. The list has gone to IBM and a
    request for a reserved block is waiting on the reply, so the numbers may
    move.

Note for review

main holds the 4.0.0 documentation work, which has not gone upstream to
Qiskit/documentation yet, so this branch must not be merged into it until
that does — otherwise the two sets cannot be separated for the upstream PR.

🤖 Generated with Claude Code

seihyun-jeong and others added 18 commits October 7, 2026 10:02
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
seihyun-jeong force-pushed the docs/usage-based-billing-5.0.x branch from 791ae36 to 454169f Compare October 7, 2026 01:02
@seihyun-jeong
seihyun-jeong changed the base branch from main to docs/hivqe-changelog October 7, 2026 01:02
Base automatically changed from docs/hivqe-changelog to main October 7, 2026 01:09
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>
seihyun-jeong and others added 4 commits October 7, 2026 11:51
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>
seihyun-jeong and others added 28 commits October 15, 2026 10:42
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>
@seihyun-jeong

Copy link
Copy Markdown
Collaborator Author

Superseded by #14, the review copy of what goes to IBM. The 5.0.x docs are reviewed there from now on; please leave review comments on #14.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant