museclient¶
Cached, budget-capped calls to Meta’s Muse Spark (muse-spark-1.3-contributor by
default) for structured JSON answers.
Install¶
From GitHub (not on PyPI), Python 3.12+:
uv add "museclient @ git+https://github.com/gojiplus/museclient"
Meta ships no client of its own and documents the OpenAI SDK pointed at
https://api.meta.ai/v1; museclient sends requests that way and adds the cap,
cache and ledger.
Use¶
from museclient import Client
client = Client(cap_usd=2, workdir="data/muse") # rates read from the provider
answer = client.complete(
[{"role": "user", "content": "..."}],
schema={
"type": "object",
"properties": {...},
"required": [...],
"additionalProperties": False,
},
max_completion_tokens=8000,
reasoning_effort="low",
)
print(client.spend()) # {'reported_usd': ..., 'exposure_usd': ..., 'cap_usd': 2.0}
What it guarantees:
No double payment. Each request is keyed by a hash of its body; asking again returns the stored answer.
A hard cap. Before sending, the call’s worst case (input bytes as a token bound, plus all of
max_completion_tokens) is reserved against the cap, across every call in the workdir. A call that would pass the cap is refused unsent.No silent paid retries. The SDK’s retries are off. A call that times out or loses its connection may have been charged; it is recorded as
unknown_outcomeand refused untilClient.abandon(call_id)sets it aside, keeping its reserve in the ledger.Checked answers. A truncated response (
finish_reason != "stop") or one that fails the JSON schema raises, after its usage is recorded.Listed prices. Rates come from the provider’s model listing; the client refuses a model that is not listed or not priced in USD.
The key is read from MUSE_API_KEY or MODEL_API_KEY, else
~/.config/muse/auth.json (providers.meta.api_key) or
~/.config/local_elections/haryana_ocr.toml (meta.api_key). It is never written to
the workdir.
Each call leaves request.json, response.json, accounting.json and answer.json
under workdir/calls/<id>/.
Adapted from the judge service in notnews/rd_images and the pricing check in appeler/pranaam.