Show HN: jev-bisect – Find answers with Jev via higher, lower, or A new Python library, jev-bisect, lets developers find numeric answers by having the Jev model make repeated higher, lower, or exactly decisions, using the official TypeSafe Python SDK. The package requires Python 3.10 or newer, installs via pip, and exposes a bisect function taking a question plus required min and max bounds, with a SearchConfig offering a default precision of 1 and max_turns of 20. Results are returned only after Jev selects exactly and include answer, turns, final state, and history recording state, choice, confidence, probabilities, and model version. 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 https://docs.typesafe.ai/sdk/python . Requires Python 3.10 or newer. Install from PyPI: pip install jev-bisect export TYPESAFE API KEY="your-typesafe-api-key" python 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. python 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. 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. | 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. python 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 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 . python 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 python 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 https://docs.typesafe.ai/models . A supplied client remains open; otherwise, bisect creates and closes its own client on success or error. 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. 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 MIT; see LICENSE https://github.com/mkly/jev-bisect/blob/main/LICENSE .