Skip to content

Latest commit

 

History

History
86 lines (69 loc) · 3.24 KB

File metadata and controls

86 lines (69 loc) · 3.24 KB

Python API

Install JEV MLX using the quick start, then set JEV_MLX_MODEL to a verified local checkpoint. See model compatibility.

Make a decision

import os
from jev_mlx import Candidate, DecisionRequest, MLXDecisionEngine

engine = MLXDecisionEngine(os.environ["JEV_MLX_MODEL"])
request = DecisionRequest(
    state={"view": "library", "visible_titles": ["Amber Maps", "Cloud Songs"]},
    utterance="Play the first one",
    candidates=(
        Candidate("play.amber", "Play the visible course Amber Maps"),
        Candidate("play.cloud", "Play the visible course Cloud Songs"),
        Candidate("close.library", "Close the course library"),
    ),
    state_version=3,
)
result = engine.decide(request)
print(result.to_dict())

Results report candidate_id, status, raw_selected_id, raw_scores, scores, margin, state_version, model, timing, cache, request_id, and selected_value. Only status == "selected" carries an executable candidate ID. no_match means no applicable choice; abstain means clarification or more evidence is needed. Sessions can also return stale.

raw_scores are candidate-token logits. scores are a softmax restricted to the supplied candidates plus __no_match__ and __abstain__; they are not calibrated probabilities of correctness. margin is the raw top-minus-runner-up logit gap. The default rejection threshold is 0.0, which rejects exact ties. Select any other threshold using development data and report its limitations.

Boolean choices preserve typed values, including False:

question = DecisionRequest.boolean(
    state={"player_status": "paused"},
    utterance="Is playback paused?",
    question="Is the player currently paused?",
)
answer = engine.decide(question)
if answer.status == "selected":
    print(answer.selected_value)  # A Python bool, not a string.

Keep decisions aligned with application state

DecisionSession snapshots state before inference. Updates during inference mark the result stale. Execution checks the current version again, verifies that the result was issued intact by this session, and consumes it once.

from jev_mlx import DecisionSession

session = DecisionSession(
    engine,
    state={"view": "notes"},
    candidates=(Candidate("close.notes", "Close the open notes window"),),
)
session.prewarm()  # Optional: computes prefix state, never a final answer.
decision = session.decide("Close it")

def apply_action(candidate):
    # Apply your application action here, then record its state atomically.
    version = session.update_state({"view": "desktop"}, candidates=())
    return {"executed": candidate.id, "state_version": version}

if decision.status == "selected":
    print(session.execute(decision, apply_action))

Call update_state for every relevant state or candidate change. Callbacks run under the session's state lock and may update it reentrantly. Callback failure consumes authorization too, preventing accidental replay of a partial effect. These checks prevent stale and replayed execution; they do not establish whether the model understood the user.

See the architecture for validation limits, cache boundaries, result semantics, and execution guarantees.