Architecture deep-dive, extension points, testing, and contribution conventions. If you're just running it, start with the User guide.
jeviathan/ # the package (pure Python; deps: fastapi, uvicorn, httpx, pydantic, PyYAML, numpy)
main.py # entrypoint: app = create_app(); uvicorn runner
config.py # Profile dataclasses + load_profile() (JEVIATHAN_PROFILE / .yaml path)
api/systemone.py # FastAPI app factory: /health, /v1/models, POST /v1/systemone
engine/systemone_engine.py# the decision pass: validate -> compile -> complete -> parse -> calibrate -> derive
compiler/prompt_compiler.py # request -> prompt; answer JSON parsing (CompileError), expected_options()
backends/base.py # DecisionBackend interface + BackendError
backends/openai_backend.py # OpenAI-compatible chat-completions client (httpx)
confidence/derive.py # argmax, distribution_confidence, score_expectation
calibration/calibrator.py # Platt fit (a,b), ECE, load_eval_rows()
calibration/cli.py # `python -m jeviathan.calibration.cli fit ...`
schemas/typesafe.py # Pydantic models mirroring the TypeSafe System One contract
profiles/ # laptop-4050.yaml, laptop-4050-logprob.yaml, rtx5090.yaml
scripts/ # manage.py (daemon layer), setup*.ps1/.sh (installers), transformers_server.py (NF4 shim)
evals/ # labeled eval JSONL for calibration fits
calibration/ # fit artifacts (*.json); raw dumps (raw-*.jsonl, gitignored)
tests/ # pytest suite (mock backend; no GPU needed)
examples/ # end-user example scripts (e.g. Brave Search grounding triage)
SystemOneEngine.system_one(req) is the whole decision pass:
- Validate limits —
statesize, question count, options-per-choice againstprofile.limits; violations raiseEngineValidationError(→ HTTP 422). - Compile prompt —
compile_request()renders state + questions into a single scoring prompt (SCORING_SYSTEM_PROMPT); the logprob strategy additionally compiles per-option prefix messages viacompile_scoring_user_message(). - Backend completion —
OpenAICompatibleBackend(or your injected backend). Malformed model JSON triggers up toMAX_CORRECTIVE_RETRIES = 2corrective retries, mirroring TypeSafe's adapter behaviour; still bad →CompileError(→ HTTP 502). - Parse + normalize —
parse_answers()extracts per-question distributions and normalizes them to sum to 1. - Calibrate — if the profile enables calibration and an artifact loads, apply Platt
(a,b)per question type; otherwise pass through. - Derive typed answers —
confidence/derive.py:argmaxfor choice/noul,score_expectation(probability-weighted level index) for score,distribution_confidencefor the confidence field. Output is TypeSafe-shaped (schemas/typesafe.py).
one_shot: one completion returns all answers as JSON.logprob: per-option prefix scoring — each option's label is prefilled as an assistant message and scored vialogprobsin a single forward pass (the shim implements this: last message with roleassistant= prefill;"logprobs": true→choices[0].logprobs.contentcarries per-token{token, logprob, bytes, top_logprobs}). The engine falls back toone_shotautomatically when the server can't do prefill+logprobs. Scoring calls cap generation at 32 tokens so a stray largemax_tokenscan't burn GPU time on tokens nobody reads.
config.py loads profiles/<name>.yaml (or any .yaml path) into dataclasses; env overrides apply after load:
backend: # type, base_url, model, api_key?, timeout_s=120, max_retries=3
sampling: # temperature=0.0, top_p=1.0, max_tokens=2048, strategy: one_shot|logprob
calibration:# enabled=false, path=null
limits: # max_questions=64, max_options_per_choice=255, max_state_chars=32000Selection order: explicit load_profile(name) → JEVIATHAN_PROFILE env → default laptop-4050. Runtime overrides: JEVIATHAN_BASE_URL, JEVIATHAN_MODEL. The setup scripts persist a tier pointer in .jeviathan_profile (gitignored) for convenience.
Implement the DecisionBackend interface (backends/base.py) — completion + close, raising BackendError on transport failure — then inject it:
from jeviathan.config import load_profile
from jeviathan.engine.systemone_engine import SystemOneEngine
engine = SystemOneEngine(load_profile("rtx5090"), backend=MyBackend(...))The OpenAI-compatible client is the reference implementation; any server speaking chat/completions works out of the box (Ollama, vLLM, the NF4 shim). For the logprob strategy your backend must support assistant-prefill + per-token logprobs as described in §2.
- Schema (
schemas/typesafe.py): addMyQuestion(BaseModel)withtype: Literal["my_type"], and extend the discriminatedQuestionunion; add the matchingAnswervariant to theAnswerunion. - Engine: handle the new type in
_validate_limits()(if it has its own limits) and in answer derivation (argmax / expectation / custom). - Compiler (
compiler/prompt_compiler.py): teachcompile_request()how to render it, andexpected_options()what options a valid answer may take;parse_answers()must accept the new shape. - Calibration (
calibration/cli.py::_row_pairs): define how a gold label maps to(p_correct, correct)pairs for your type (choice: probability of the gold option; score: proximity-weighted expectation; noul: p vs 1-p). - Tests: add cases in
tests/test_engine.py+tests/test_compiler.pywith the mock backend.
Strategies are selected by profile.sampling.strategy. Add your branch alongside one_shot/logprob in the engine's completion path, keep the one_shot fallback for servers that can't support it, and add a dedicated test module (see tests/test_logprob_strategy.py).
python -m pytest tests/ -q # ~35 tests; mock backend transport — no GPU, no networkconftest.py/helpers.pyprovide the mock OpenAI-compatible transport (scripted completions + logprobs) and profile fixtures.test_compiler.py— prompt rendering/round-trip and answer parsing edge cases.test_confidence.py— argmax / expectation / confidence math.test_engine.py— full decision pass, limits validation (422 paths), corrective retries (502 path).test_logprob_strategy.py— prefill/logprobs scoring and the one_shot fallback.
Run a single file: python -m pytest tests/test_engine.py -v. New behaviour gets a test before it lands; keep the suite GPU-free so CI stays cheap.
- License: Apache-2.0 (see
LICENSE). Keep new files under it; model weights are licensed separately and never committed. - Naming discipline: the project is spelled JEVIATHAN (j-e-v-i-a-t-h-a-n, with the 'a') everywhere — package dir, env vars (
JEVIATHAN_*), aliases, docs. Terminal fonts can make it look like "jevithan"; verify names programmatically when in doubt. - PowerShell 5.1 gotcha:
.ps1files must stay pure ASCII (no em-dashes/unicode) — BOM-less UTF-8 is read as the system ANSI code page and corrupts parsing.scripts/*.ps1are enforced to be ASCII; keep it that way. manage.pystays stdlib-only so it runs anywhere Python does (it's the ops layer, not the app).- No machine-specific paths in tracked files: local weights dirs resolve via
--model-dir>$JEVIATHAN_MODEL_DIR>.jeviathan_model_dir(gitignored); keep docs using placeholders. - Commits: imperative subject, specific file adds (never
git add -A— the working tree carries unrelated WIP and tracked noise).
- TriniGard (closed-source) consumes Jeviathan through an adapter (
core/adapters/jeviathan.py) behind its verification engine; the seam is the System One API, so the two evolve independently. - Ops runbook for agents:
skills/jeviathan-ops/SKILL.md.