Quickstart¶
Install¶
pip install "polyjev[all]" # library + server + Claude + Gemini
pip install polyjev # library with OpenAI-compatible backends only
pip install "polyjev[hf]" # + in-process Hugging Face models (torch)
Try it without any key or GPU using the built-in fake model:
polyjev ask fake/demo '{"ticket": "Everything is down before our demo"}' \
--noul "urgent=Does the customer need a reply within the hour?" \
--choice "team=Which team owns this?|billing,outage,feature" \
--score "tone=How angry is the customer?|calm,annoyed,furious"
Pick a model¶
A model is a provider/model id, or a name from your config.
| you have | model id | notes |
|---|---|---|
| an Anthropic key | anthropic/claude-opus-5 |
ANTHROPIC_API_KEY |
| an OpenAI key | openai/gpt-5.6-luna |
OPENAI_API_KEY |
| a Gemini key | gemini/gemini-3.8-flash |
GEMINI_API_KEY |
| a vLLM server | vllm/<served-name> |
VLLM_BASE_URL=http://host:8000/v1 |
| Ollama | ollama/qwen3:8b |
local on :11434 |
| a GPU in this process | hf/Qwen/Qwen3-4B-Instruct-2507 |
pip install "polyjev[hf]" |
| any OpenAI-compatible API | openai-compatible/<model> |
set base_url in config |
Library¶
import polyjev as pj
from enum import Enum
class Team(Enum):
BILLING = "billing"
OUTAGE = "outage"
FEATURE = "feature"
judge = pj.Polyjev("vllm/local")
d = judge.decide(
{"ticket": "Everything is down and we have a demo at noon."},
{
"urgent": pj.Noul("Does the customer need a reply within the hour?"),
"team": pj.Choice("Which team owns this?", Team, {Team.OUTAGE: "service down"}),
"tone": pj.Score("How angry is the customer?", ["calm", "annoyed", "furious"]),
# asked only if "urgent" came out yes, with that answer in its prompt
"page": pj.Noul("Should we page on-call?", ask_if={"urgent": [True]}),
},
)
d["urgent"].p # probability of yes
d["team"].value # Team.OUTAGE (Enum in -> Enum out)
d["team"].probabilities # {Team.BILLING: p1, Team.OUTAGE: p2, Team.FEATURE: p3}, summing to 1
d["tone"].level, d["tone"].expected, d["tone"].confidence
d["page"] # None when skipped
d.to_jev() # the exact Jev response JSON
d.usage, d.diagnostics
Async, batches and images:
async with pj.Polyjev("anthropic/claude-opus-5") as judge:
d = await judge.adecide(state, questions, images=["photo.jpg"])
results = await judge.adecide_many(states, questions, concurrency=16,
on_result=lambda i, r: print(i), return_exceptions=True)
Useful options on decide (the same as Jev's request extensions):
samples ("auto" or a count), auto_max, auto_threshold, think (a thought
budget in tokens), instructions (shared context), ask (answer a subset),
sequential, seed, and strategy to force a read strategy.
Server¶
pip install "polyjev[server]"
polyjev serve --model vllm/local --playground # http://localhost:8011
curl -s localhost:8011/v1/systemone -H 'content-type: application/json' -d @examples/requests/readme_example.json
Or from Python, against any Jev-compatible server:
remote = pj.Remote("http://localhost:8011")
d = remote.decide(state, questions) # same typed answers
Config file¶
polyjev.yaml names your models, sets what jev-latest means and configures
the server. See examples/polyjev.example.yaml.
default_model: local
models:
local:
provider: vllm
model: local
base_url: http://gpu-node:8000/v1
extra_body: {chat_template_kwargs: {enable_thinking: false}}
claude: {provider: anthropic, model: claude-opus-5, params: {output_config: {effort: low}}}
server:
api_key: ${POLYJEV_API_KEY:-}
playground: true
judge = pj.Polyjev(config="polyjev.yaml") # or set POLYJEV_CONFIG
judge.decide(state, questions, model="claude")