hunch
Jev as a column primitive.
Jev is TypeSafe’s System One model: you send state and typed questions, and you get labels, scores, and yes/no probabilities back. hunch is a small Python layer on that API. Code owns the table and the side effects. Jev only judges. An optional LLM role may propose strings; it never closes.
import hunch
from hunch import ask, over, rate
jev = hunch.connect() # TYPESAFE_API_KEY
@over(prospects, "JOB_TITLE")
def classify(title):
function = ask(
title,
"what business function does this title state?",
among=functions,
by=function_rules,
)
level = ask(
title,
"what level of rank does this title state?",
among=levels,
by=seniority_rules,
)
seniority = level.on(
sure=level.top,
torn=lambda: ask(
title,
"which of these two fits better?",
among=level.top2,
by=seniority_rules,
).top,
lost=lambda: (
"Individual Contributor"
if title.feels("a rank word governing a product, program, or account rather than people")
else "review"
),
)
keep = rate(
title,
"How important is this account?",
["disposable", "nice to have", "should keep", "must keep"],
)
return {
"function": function.top,
"function_shape": function.shape,
"seniority": seniority,
"seniority_shape": level.shape,
"keep": keep.level,
}
results = classify.run(jev)
Independent ask / rate / feels calls on the same value go in one Jev request. @over classifies each distinct value once, caches it, and left-joins onto the frame.
Install
pip install hunch-jev
# or from a clone:
pip install -e ".[dev]"
Requires Python 3.10+. Set TYPESAFE_API_KEY. Do not put keys in source.
pytest
Verbs
| Call | Jev primitive | You get |
|---|---|---|
ask(state, question, among=..., by=...) |
Choice | .top, .top2, .p, .confidence, .shape |
rate(state, question, levels) |
Score | .score, .level, .shape |
value.feels("...") |
Noul | truthy when P(yes) ≥ 0.5 |
.shape is your policy on the distribution, not a Jev field:
| Shape | Meaning |
|---|---|
sure |
One option dominates |
torn |
Two options are close |
lost |
Flat or weak evidence |
Cutoffs live on ShapePolicy. Confidence is how peaked the distribution is, not whether the label is true.
connect(cache="~/.cache/hunch") persists answers on disk. jev.usage reports calls, cache hits, tokens, and the model name.
LLM roles
A role may only propose text or a list of labels. ask still decides.
from hunch import ask, draft, openrouter, role
jev = hunch.connect(llm=openrouter()) # OPENROUTER_API_KEY
taxonomist = role(
"Propose 8–16 kebab-case folder names. Include junk. No review pile.",
emit=list[str],
)
with jev.session():
taxonomy = draft(listing, taxonomist).labels
folder = ask(name, "which folder?", among=taxonomy)
hunch.openai, hunch.cerebras, and hunch.openrouter are OpenAI-compatible adapters. via= on a role overrides llm= on connect(). A role stops after max_loops (default 5) in one session.
Example
examples/organize_downloads.py files a Downloads folder: one LLM taxonomy, then Jev assigns each loose file, then the script moves. Destination folders are skipped on later runs. --dry-run prints the plan.
What this is not
Jev does not invent labels. among= is the whole set of allowed answers. Roles invent candidates; they have no tools and do not move files. Open-ended writing and multi-step agents are out of scope.
License
MIT. Jev and TypeSafe are typesafe.ai; this library is not affiliated.
Release files for hunch-jev 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hunch_jev-0.1.0.tar.gz | 19.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hunch_jev-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.5 kB
Release files / hunch_jev-0.1.0.tar.gz
| Download URL | hunch_jev-0.1.0.tar.gz |
|---|---|
| Size | 19.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
081e74c30a5d8a70a33ca258bf2549887cadc695960bb4f2985a09b3519f97f3
|
|
BLAKE2b-256 checksum How to use checksums |
db5a53bd46cc86a063c568fbfe7faeaa58ff217cc710ba144f9c61ea38c04a7c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 20, 2026.
Transparency logRelease files / hunch_jev-0.1.0-py3-none-any.whl
| Download URL | hunch_jev-0.1.0-py3-none-any.whl |
|---|---|
| Size | 17.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9654497ae953709b923a5c1001d11a1735fc89492dc1690cdbf51bd7e18949ff
|
|
BLAKE2b-256 checksum How to use checksums |
b0cf6381f2fdc6751a8a09e9f659123bea829f1a5880e1f5bc05c188ef0d234a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 20, 2026.
Transparency log