Skip to main content

jev-bisect

Find numeric answers with Jev through repeated higher, lower, or exactly decisions. Supply a question and bounds; the library calculates the guesses using the official TypeSafe Python SDK.

Install and run

Requires Python 3.10 or newer. Install from PyPI:

pip install jev-bisect
export TYPESAFE_API_KEY="your-typesafe-api-key"
from jev_bisect import bisect

result = bisect(
    "How many slices in a pizza?",
    min=0,
    max=100,
)
print(result.answer)
print(result.turns)

min and max are required keyword arguments and must be finite numbers with min < max. Omit last_guess or pass None to start at the midpoint. To choose the first guess, supply an override such as bisect(question, min=0, max=100, last_guess=25).

A result is returned only after Jev selects exactly. It contains answer, turns, the final state, and history. Each history entry records the state, choice, confidence, probabilities, and model version.

Configuration

from jev_bisect import SearchConfig, bisect

result = bisect(
    "What is pi?",
    min=3,
    max=4,
    config=SearchConfig(precision=0.01, max_turns=10),
)
print(result.answer)  # 3.14 if Jev makes the correct comparisons
Field Default Meaning
precision 1 Smallest search increment; a positive finite int or float.
max_turns 20 Maximum evaluated guesses; an integer from 1 through 20.

Omitting config or passing None uses these defaults. Both settings belong in SearchConfig. Each evaluated guess counts as one turn, including the initial midpoint. SDK retries are disabled for these calls.

Precision and bounds behavior

Candidates are multiples of precision measured from zero: 1 searches whole numbers, 0.01 searches hundredths, and 2.5 searches values such as 0, 2.5, and 5. Jev is instructed to round the answer to the nearest multiple before comparing, with halfway values rounded away from zero. Precision specifies search resolution, not significant digits or an error tolerance.

After higher or lower, the current guess is excluded and the next guess is the floor midpoint of the remaining candidates. For min=0, max=100 at default precision, the choices higher, lower, exactly evaluate 50, 75, and 62. Rounding down also applies to negative numbers: the first guess for min=-5, max=0 is -3.

Bounds snap inward to the candidate grid. With min=0.001, max=0.019 and precision 0.01, the only candidate is 0.01. With min=0.1, max=5.9 and precision 1, candidates are the integers 1 through 5. Any explicit last_guess must be within the bounds and a multiple of precision.

Endpoints on the grid are reachable. A valid search may narrow internally to one candidate, which still needs an exactly decision. Choose bounds that contain the rounded answer; the search does not expand them. A large range or fine precision may require more guesses than the configured limit, and Jev can make incorrect comparisons.

Guesses use exact rational arithmetic and integer candidate indexes internally. Whole-number increments, including 1.0, return integers; fractional increments return floats. Trailing zeros are not preserved.

Exceptions

Exception Condition
ValueError Invalid bounds (bisect requires min < max), config, question, model, or starting guess.
SearchExhaustedError No candidate within bounds, no possible next guess, or a candidate cannot be represented as a float at the configured precision.
MaxTurnsExceededError No exactly decision within max_turns.

Failures during the model loop include the last evaluated state and completed history; MaxTurnsExceededError also includes max_turns. Exhaustion before any evaluation has state=None and empty history. SDK errors propagate.

from jev_bisect import MaxTurnsExceededError, SearchExhaustedError, bisect

try:
    result = bisect("How many minutes are in three hours?", min=0, max=300)
except (MaxTurnsExceededError, SearchExhaustedError) as error:
    print(error)
    print(error.state, error.history)
else:
    print(result.answer)

Apply a choice yourself

advance performs one step without an API call and returns a SearchState. When last_guess is omitted, the choice applies to the bounds' midpoint. Supply the returned bounds and guess for the next step, using the same config. If the returned bounds are equal, pass last_guess to evaluate the remaining candidate: exactly returns that state, while higher or lower raises SearchExhaustedError. Without last_guess, advance requires min < max.

from jev_bisect import advance

state = advance("higher", min=0, max=100)
assert state.to_dict() == {"max": 100, "min": 51, "last_guess": 75}

state = advance("lower", min=state.min, max=state.max, last_guess=state.last_guess)
assert state.last_guess == 62

Reuse a client or pin a model

from typesafe_sdk import TypeSafeClient
from jev_bisect import bisect

with TypeSafeClient() as client:
    result = bisect(
        "How many centimeters are in three quarters of a meter?",
        min=0,
        max=100,
        client=client,
        model="jev-1.13.0",
    )

The default model is jev-latest. A supplied client remains open; otherwise, bisect creates and closes its own client on success or error.

Development

pip install -e '.[dev]'
pytest
ruff check .
python -m build

Tests use deterministic responses and a mock HTTP transport, requiring no API key or network requests.

Prepare a release

Update version in pyproject.toml for each new release, then build and check the wheel and source distribution:

pip install -e '.[dev,release]'
pytest
ruff check .
python -m build
python -m twine check --strict dist/*

These commands prepare files locally. When ready to publish, set TWINE_USERNAME=__token__ and TWINE_PASSWORD to a PyPI API token, then upload only the files for that release:

python -m twine upload dist/jev_bisect-0.1.0-py3-none-any.whl dist/jev_bisect-0.1.0.tar.gz

License

MIT; see LICENSE.

Metadata

Release files for jev-bisect 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jev-bisect 0.1.0
File Size Uploaded
jev_bisect-0.1.0.tar.gz 73.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jev-bisect 0.1.0
File Interpreter ABI Platform
jev_bisect-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 82.3 kB

Release files / jev_bisect-0.1.0.tar.gz

Download URL jev_bisect-0.1.0.tar.gz
Size 73.5 kB
Tags Source
SHA-256 checksum
How to use checksums
b0b5a872b1958bb4c0223fd3694e42010c7b2689ecff7625f1d6466823cba06b
BLAKE2b-256 checksum
How to use checksums
56c9e21e951e3a225cc96d8d08ff9c1f6dbfd2894f3d773d8b071dec51910d32
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / jev_bisect-0.1.0-py3-none-any.whl

Download URL jev_bisect-0.1.0-py3-none-any.whl
Size 8.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9fb0b959d455b7add8463cd425cddf54db113aaad8acde5ba27592d5c53abb2e
BLAKE2b-256 checksum
How to use checksums
2d58692afa4b8c2933981e96b3703d4a188dece81538cd10303e14f8433a14fe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page