fuzzyif
Natural-language conditions in Python if statements, judged by Jev, TypeSafe AI's System One model. Jev does not generate text; it returns probabilities and choices, so calls are fast and cheap.
from fuzzyif import fuzzy, fuzzy_match
msg = "After I enter my password the screen goes blank."
if fuzzy("Is this message urgent?", msg):
notify_oncall(msg)
kind = fuzzy_match(msg, {
"bug": "a bug report",
"howto": "a how-to question",
"other": "anything else",
})
Install
pip install fuzzyif
No runtime dependencies; standard library only. Python 3.10+.
Does it work on real code?
Two well-known projects, patched by script, judged by their own test suites.
| project | what the if ladder decided |
before → after | project's own tests |
|---|---|---|---|
| Ansible | which of 52 Linux distributions this host is, from /etc/*-release files |
786 → 450 lines, 84 if/elif removed, 2 fuzzy_match calls added |
65 / 90 fixtures pass; distribution 90 / 90, os_family 89 / 90. The 25 failures are version-string extraction conventions, which fuzzy-if does not try to do |
| Django | which settings and headers to redact on the debug 500 page | one substring regex → one question | 109 / 110 pass; the one failure asserts API_URL must be redacted |
The lesson from both: fuzzy-if replaces the if ladder that decides what
something is. It does not replace the code that extracts a substring, and it
should not be put in front of anything you would not send to an API (passwords,
personal data).
API key
Resolved in this order:
fuzzyif.configure(api_key="...")- Environment variable
TYPESAFE_API_KEY - File
~/.config/typesafe/api_key
Functions
| Function | Question type | Returns |
|---|---|---|
fuzzy(question, text, threshold=0.5) |
yes/no | bool |
prob(question, text) |
yes/no | float in 0..1 |
fuzzy_batch(text, [q1, q2, ...]) |
several yes/no in one request | list[float] |
fuzzy_match(text, {key: description}) |
pick one | chosen key (or (key, probs) with with_probs=True) |
fuzzy_score(text, question, [level0, level1, ...]) |
ordered scale | expected index as float |
fuzzy vs fuzzy_match
fuzzy() answers each question independently. Stacking several fuzzy() calls in if / elif is not exclusive: when two questions both cross the threshold, the first branch wins even if the second is more likely. When you want exactly one of several labels, use fuzzy_match(); it compares all options in one request.
Errors
API failures raise APIError by default. Pass default= to return a fallback instead:
if fuzzy("Is this spam?", msg, default=False):
...
Be careful with negations: if not fuzzy(..., default=False) lets everything through during an outage.
Empty text and out-of-range thresholds raise ValueError.
Testing
mock() answers from a mapping instead of the API. Values can be a number, a {text: value} dict, or a callable.
import fuzzyif
with fuzzyif.mock({
"Is this message urgent?": {"server down": 0.95, "team dinner": 0.1},
"bug|howto|other": lambda t: "bug" if "error" in t else "other",
}):
...
The mock key for fuzzy_match is the sorted choice keys joined with |.
Performance
- One keep-alive HTTPS connection per thread.
- LRU cache in front of every call (
cache_size, default 1024). The same question and text never hit the API twice. fuzzy_batchandfuzzy_matchsend one request for several judgements.- Retries with backoff on 429 and 5xx (
max_retries, default 3);Retry-Afteris honoured.
Configuration
fuzzyif.configure(model="jev-latest", timeout=10.0, cache_size=1024, max_retries=3)
configure() clears the cache.
Metadata
Release files for fuzzyif 0.2.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 | |
|---|---|---|---|
| fuzzyif-0.2.0.tar.gz | 17.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fuzzyif-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.1 kB
Release files / fuzzyif-0.2.0.tar.gz
| Download URL | fuzzyif-0.2.0.tar.gz |
|---|---|
| Size | 17.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d5790ad84efa27b4ae2f4149ae952c82dd50525adc09a467099540acc43e2269
|
|
BLAKE2b-256 checksum How to use checksums |
d094436e4d35bd03e3d50c0cfb0441f7f267d3e66d47d8b5224d9ef9c81c3c5b
|
| 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 19, 2026.
Transparency logRelease files / fuzzyif-0.2.0-py3-none-any.whl
| Download URL | fuzzyif-0.2.0-py3-none-any.whl |
|---|---|
| Size | 13.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a586594dd691d1617cc656d261756d8207d980eb239c314a820527f6a16400a8
|
|
BLAKE2b-256 checksum How to use checksums |
30032534119b466cee2b90712dd00e8d668633555c79ffc5ccce0e9b22b397ac
|
| 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 19, 2026.
Transparency log