shisa-de
A Python client for Shisa DE-1, a model for classification and typed decisions. Use it through the hosted Shisa Platform or a local OpenAI-compatible server serving DE-1.
Give it text, images, or structured data and a set of labels or questions. It returns answers, probabilities, and request usage—not generated prose. The client loads only the tokenizer; model weights stay on the server.
Benchmark snapshot
| Benchmark | Shisa DE-1 | Jev |
|---|---|---|
| JevBench standard accuracy | 98.6% | 98.6% |
| JevBench hard accuracy | 64.9% | 73.0% |
| AG News accuracy | 89.5% | 90.0% |
| Median latency | 20 ms (local) | 223 ms (hosted) |
Install
Requires Python 3.10 or newer.
pip install shisa-de
For development, see Development. Release notes are in CHANGELOG.md.
Use the Shisa Platform
Get an API key from platform.shisa.ai and set it in your environment:
export SHISA_API_KEY="your-api-key"
No endpoint or model argument is needed:
from shisa_de import DecisionModel
with DecisionModel() as de:
result = de.classify(
"WINNER! Claim your free prize now!",
{"intent": ["spam", "ham"]},
)
print(result["intent"]) # spam
The defaults are model shisa-ai/shisa-de-1 at
https://api.shisa.ai/openai. The tokenizer is loaded lazily from Hugging Face
when first needed, so the first call may require a download. Nothing is fetched
at import time. PyTorch and a local GPU are not required for the client.
Check your setup from the command line:
shisa-de doctor
shisa-de ask --state 'WINNER! Claim your free prize now!' --labels spam,ham
doctor checks model-list access, the model ID, and the tokenizer's answer
boundary. ask makes an actual decision request.
Probability-scored questions
Pass probability=True when the distribution, rather than just the winning
label, is the result you need:
from shisa_de import DecisionModel, Noul
with DecisionModel() as de:
result = de.decide(
{"forecast": "Rain is expected tomorrow afternoon."},
{"rain": Noul("Will it rain tomorrow?")},
probability=True,
calibrated=False,
)
p_yes = result["rain"]
distribution = result.answers["rain"].probabilities
The flag applies to every question in the call, including each label in a multi-label head. It requires one logical read per question and rejects choices above 26 options before any requests are sent: overflow's finalist scores are not a distribution over all original options. Missing-letter recovery can still require extra HTTP requests at the same answer position.
decide, its system_one alias, and classify accept this flag, defaulting to
False. Direct questions already use a single read with thinking disabled;
this SDK has no read-twice or thinking policy. The flag records caller intent in
result.meta["probability"] and enforces the single-read restriction. It is not
sent as a server parameter and does not change prompts or answer shapes.
include_probabilities=True only changes the classify dict view; it does not
set probability intent.
Calibration remains independent. The example requests raw logprob-derived
probabilities with calibrated=False; omitting it retains the default text
calibration. The flag neither applies a forecasting-specific scale nor selects
a label-smoothed checkpoint. The bundled temperatures are not a validated fit
for a different adapter; validate calibration for your serving model and task.
Image calls also accept the flag and retain their uncalibrated default.
Use a local server
First start an OpenAI-compatible server with DE-1 loaded. See the DE-1 model card for serving guidance. Then point this client at it:
from shisa_de import DecisionModel
with DecisionModel.from_endpoint(
"http://127.0.0.1:8021/v1",
model="shisa-ai/shisa-de-1",
api_key="", # no authentication; do not use a key from the environment
) as de:
result = de.classify(
"I was charged twice. Please refund the duplicate payment.",
{"intent": ["refund_request", "order_status", "cancel_order"]},
)
print(result["intent"])
Both a server root URL and a URL ending in /v1 are accepted. For an
authenticated local server, pass its key as api_key="your-local-key".
If the server uses an alias for the model, pass that alias as model= and
tokenizer="shisa-ai/shisa-de-1" to keep using the checkpoint's tokenizer.
For text, the server needs /v1/completions with logprobs and
prompt_logprobs; doctor also needs /v1/models. vLLM supports these.
See the readout contract for the exact requests.
For the CLI, use --base-url or set SHISA_DE_ENDPOINT. In a shell without
hosted credentials:
export SHISA_DE_ENDPOINT=http://127.0.0.1:8021/v1
shisa-de doctor
shisa-de ask --state 'Please refund my duplicate payment.' --labels refund_request,order_status
Configuration precedence
| Setting | Resolution order |
|---|---|
| Endpoint | base_url= / CLI --base-url, then SHISA_DE_ENDPOINT, then the hosted default |
| API key | api_key=, then SHISA_DE_API_KEY, then SHISA_API_KEY |
| Model | model= / CLI --model, otherwise shisa-ai/shisa-de-1 |
| Tokenizer | tokenizer= / CLI --tokenizer, otherwise the model ID |
An explicit api_key="" disables authentication. Otherwise, environment keys
are used for local endpoints too. Leave SHISA_DE_ENDPOINT and
SHISA_DE_API_KEY unset to use the hosted defaults with only SHISA_API_KEY.
Classify with labels
Each named label set is a separate question. Labels can be plain strings or a mapping from labels to descriptions:
from shisa_de import DecisionModel
with DecisionModel() as de:
result = de.classify(
{"subject": "Charged twice", "body": "Please refund the duplicate charge."},
{"intent": {
"refund_request": "The customer wants money returned",
"order_status": "The customer wants a delivery update",
}},
include_probabilities=True,
)
print(result["intent"]["label"])
print(result["intent"]["probabilities"])
print(result.usage)
Use include_confidence=True for a label and confidence without the full
probability map. The default result maps each head name directly to its label.
Other label-set forms:
| Form | Behavior |
|---|---|
["a", "b"] |
Choose one label; derive the question from the head name |
{"a": "description", "b": "description"} |
Choose one label using its description |
{"labels": ["a", "b"], "prompt": "Which applies?"} |
Supply your own question |
{"labels": ["a", "b"], "multi_label": True, "cls_threshold": 0.5} |
Ask yes/no for each label; return labels above the threshold |
{"levels": ["low", "medium", "high"]} |
Choose a level on an ordered scale |
Wide text label sets
Requires shisa-de>=0.2.0: DecisionModel handles
27–676 text choice options with balanced chunks and a final choice among each
chunk's winner. Ordinary choices with up to 26 options keep their direct path.
from shisa_de import Choice, DecisionModel
with DecisionModel(max_logprobs=40) as de: # requires server support for top-k 40
result = de.decide("Route this support request", {
"route": Choice("Which queue applies?", {
f"queue_{i}": f"Support queue {i}" for i in range(77)
}),
})
answer = result.answers["route"]
print(answer.choice, answer.finalists, answer.requests)
print(answer.strategy) # finalist-top1
The returned full-key map contains final-round scores on finalists and zero on
eliminated options. These scores are conditional on finalist selection, not
calibrated probabilities over all labels. Overflow answers have
calibrated=False and confidence=None. Explicit calibrated=True is rejected
for overflow; omit it to keep ordinary text heads calibrated in a mixed call.
include_probabilities=True also exposes the strategy and score semantics for
wide classify heads.
Use DecisionModel(overflow="error") for strict rejection above 26. Image and
ordered-score overflow are unsupported. Live quality testing covered up to
151 options; 676 is a tested structural limit, not a quality guarantee. Option
order can change the answer. See the overflow contract
for the algorithm, cost, provenance and held-out evidence.
Classify images
Pass a local image path, an HTTP(S) image URL, or a base64 image data URL as
image=. The same API works with the Shisa Platform and a local DE-1 server
with vision enabled:
from shisa_de import DecisionModel
with DecisionModel() as de:
result = de.classify(
{},
{"animal": ["cat", "dog", "bird"]},
image="photo.jpg",
include_probabilities=True,
)
print(result["animal"]["label"])
print(result["animal"]["probabilities"])
decide(..., image="photo.jpg") supports typed questions about an image too.
Local files are uploaded; URLs are fetched by the server. Supported formats: PNG, JPEG, and WebP. Image probabilities are uncalibrated by default.
The server must support images and token logprobs on /v1/chat/completions.
If an option is missing from the returned logprobs, the client raises an error.
For larger label sets on a local server, raise its --max-logprobs and set
DecisionModel(image_top_logprobs=128) to match.
shisa-de ask --image photo.jpg --labels cat,dog,bird --prompt 'What animal is shown?'
Ask typed questions
decide supports yes/no probabilities (Noul), named choices (Choice), and
ordered scores (Score):
from shisa_de import Choice, DecisionModel, Noul, Score
with DecisionModel() as de:
result = de.decide(
"Reply with your full card number and CVV to claim your prize.",
{
"is_spam": Noul("Is this message spam?"),
"asks_for": Choice("What does the sender want?", {
"card_details": "Payment card details",
"callback": "A support callback",
"nothing": "Nothing; it is routine",
}),
"risk": Score("How risky is acting on this message?", [
"Safe", "Suspicious", "Dangerous",
]),
},
)
print(dict(result))
print(result.answers["asks_for"].probabilities)
print(result.answers["risk"].level)
print(result.usage)
Noulreturns the probability of yes.Choicereturns the selected option key.Scorereturns the probability-weighted, zero-based position in the scale. The most likely level is available asresult.answers[name].level.
Each question has at most 26 options. Each question costs one request; text
questions add a fallback request for each option missing from the top logprobs.
Multi-label classification asks one question per label. Questions run
concurrently; max_workers= controls concurrency. result.usage records the
request and token counts.
Probabilities and calibration
Text calls apply the bundled temperature scaling by default; image calls return
raw probabilities. Pass calibrated=False for raw text probabilities too.
Each answer records calibrated and temperature; result.meta records the
readout version and calibration identity. See the readout documentation
for the scoring and calibration details.
Development
git clone https://github.com/shisa-ai/shisa-de.git
cd shisa-de
python -m pip install -e '.[dev]'
python -m pytest tests/
Offline tests use a stub tokenizer and mock HTTP transport. Live tests spend real API requests and are opt-in:
SHISA_DE_LIVE=1 python -m pytest tests/test_live.py -v
Live tests use the same endpoint and API-key environment variables as the
client. shisa-de explain --labels spam,ham prints the prompt, token slots,
logprobs, and final distribution for a live request.
License
This client library is licensed under Apache 2.0. See the model card for the model's license and usage requirements.
Metadata
Release files for shisa-de 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| shisa_de-0.2.1.tar.gz | 93.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| shisa_de-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 130.2 kB
Release files / shisa_de-0.2.1.tar.gz
| Download URL | shisa_de-0.2.1.tar.gz |
|---|---|
| Size | 93.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ed116634191a507b8e396b2003fe6d568ba80b891bbccce2e7712eb901f0ce88
|
|
BLAKE2b-256 checksum How to use checksums |
2f27851242e67edaa2aa5a8d385857477d7a442a6c6fc04e69cea56463ef1f99
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency logRelease files / shisa_de-0.2.1-py3-none-any.whl
| Download URL | shisa_de-0.2.1-py3-none-any.whl |
|---|---|
| Size | 37.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2c2823bc6195d3352d28511a1c010e8c7ea92dd6af8b4fcb68975acdbf742fb6
|
|
BLAKE2b-256 checksum How to use checksums |
509b582d576bb3e977f6b8c50072fa5041a01a581df9f763da30c58e9c8a1a9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency log