mellontoken
Client for the mellontoken gateway.
import mellontoken
answer = await mellontoken.ask("Summarise this tender in one line.")
parsed = await mellontoken.ask(document_text, schema=DocExtraction)
full = await mellontoken.ask_full(document_text, schema=DocExtraction)
full.cost_usd # "0.00059550"
full.model # the model that actually served it
Letting the gateway pick the model
answer = await mellontoken.ask(prompt, model="auto")
answer = await mellontoken.ask(prompt, model="auto", tier="high") # bound the spend
full = await mellontoken.ask_full(prompt, model="auto")
full.route.model_slug # what it picked
full.route.task # the grid row it read
full.route.explanation # why, in a paragraph you can argue with
One command. model="auto" makes the gateway classify the prompt on three axes
(task, effort, capability), read the resulting grid cell, and serve the answer from
whatever that cell names — and ask_full reports the decision on Answer.route, so
routing is legible after the fact without a second call to ask about it.
Those three classifier calls are billed, per call. They cost roughly $0.005 against
a completion's dollars and land on the ledger as kind=classifier rows, so the
spend is visible rather than hidden. A service sending the same shape of prompt a
thousand times should read full.route.model_slug once and then name that slug:
the decision is a property of the workload, not of each call.
tier= bounds what the router may spend and outranks the effort classifier, because
a tier is a statement about your budget rather than a property of the text. Set it
per call, or once via MELLONTOKEN_TIER. It is only read on the auto path — with a
named model it is logged as ignored rather than silently dropped.
A router that resolves nothing is not an error. route.model_slug is None when
the capability gate rejected every candidate in the cell; ask logs the explanation
and falls back to MELLONTOKEN_MODEL, which is what the gateway's own advice is —
keep your own model. The one case that raises is MELLONTOKEN_MODEL=auto as well,
where there is no own model to keep.
Configuration
From the environment:
| variable | default |
|---|---|
MELLONTOKEN_BASE_URL |
https://dev.mellontoken.internal.techmellon.com/api/v1 |
MELLONTOKEN_API_KEY |
— required |
MELLONTOKEN_MODEL |
gemini-3.7-flash (or auto) |
MELLONTOKEN_TIER |
— (the effort classifier judges it) |
MELLONTOKEN_MAX_TOKENS |
32000 |
MELLONTOKEN_TIMEOUT |
600 |
or in code:
mellontoken.configure(base_url="http://gateway:8000/api/v1", api_key=key, model="gpt-5.6-luna")
MELLONTOKEN_API_KEY is the only variable most callers set. The default base
URL is the dev gateway, which resolves on the internal network only — from outside
it, set MELLONTOKEN_BASE_URL yourself. Running the stack locally, that is
http://localhost:8000/api/v1, or http://host.docker.internal:8000/api/v1 from
inside a container, where localhost is the container rather than the host.
What ask does that a bare HTTP call does not
- Sends the schema twice, as
response_formatand as prompt text. The request field is only honoured where the provider can enforce it; Gemini accepts a schema it will then ignore, and the field names in the prompt are what stop it inventingcol_idxforcol. - Reads JSON out of a fenced reply, and wraps a bare list under the schema's single array field when that is unambiguous.
- Retries the shape, not the wire. A 401/402/403/404 is final — a key, a budget, a permission, a missing model — and raises immediately. A reply that did not parse is retried three times.
- Logs the cost of every call, which is the reason to route through the gateway
at all:
mellon.cost_usdis the only per-call price any provider path reports. - Resolves
model="auto"before sending anything.autois a request for a decision, not a catalogue slug, and the completion endpoint would 404 it. Resolved once perask, outside the retry loop: a reply that did not parse is a reason to ask the same model again, not to pay three classifiers for the same decision again.
Install
Built from this directory, which lives in the gateway's own repo so the client and the endpoint version together:
uv build # -> dist/mellontoken-0.1.0-py3-none-any.whl
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mellontoken-0.2.0.tar.gz.
File metadata
- Download URL: mellontoken-0.2.0.tar.gz
- Upload date:
- Size: 10.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55dbf4f9ae05cd9af89f17f5c2c05a49acb5e192673ea575923500897a172791
|
|
| MD5 |
24e556edb05f3a5dbe491e6d2d940c20
|
|
| BLAKE2b-256 |
34513b618d7a72c4973cf2bb2a690626893852afdadeeccb3ac3980dbaf69b9e
|
File details
Details for the file mellontoken-0.2.0-py3-none-any.whl.
File metadata
- Download URL: mellontoken-0.2.0-py3-none-any.whl
- Upload date:
- Size: 11.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f6c40163090df27f99c8889661f352f313db7c625a663960aebb9cc21075185
|
|
| MD5 |
868a5de59ee4cb6739275934b8f32adc
|
|
| BLAKE2b-256 |
712765be3ab7dbb7913d7e59d8a96dc93ac303d9feb6d1ca10659c7816195ef3
|