Skip to main content

hugpy_core

hugpy's central interface: console API, auth, planner (verdicts per model x worker), the DB relay, the arms (video, oracle, help) and, today, the call router. Service on ae: 7002_hugpy_api (port 7002, user solcatcher). Its DB is hugpy_core; each box's front door writes hugpy_wrapper.call_log.

Design record: toolserver instructions/hugpy/design/call-flow-router-2026-10-06.

How a call flows (today)

client
  |
  v
CORE  :7002   (interface + router in one process)
  |  1. logs its own call row (hop core)
  |  2. picks a worker: a box where the model is loaded (residents table),
  |     else the best-ranked box for the pair's verdict
  v
WORKER AGENT  (hugpy_worker, one per box)
  |  3. logs its row (hop worker)
  |  4. model not on this box? pull it from central INSIDE the call
  |     -> its own row (hop central-pull) = the cold-load measurement
  v
WRAPPER FRONT DOOR  (fitevict, :7016 on ae; owns the GPU)
  |  5. logs its row (hop wrapper)
  |  6. place: same contract loaded? reuse. else evict-to-fit + load
  |     (llama-server or a task child, localhost-only ports)
  v
ENGINE  (llama-server / task child)
  |  7. serves
  ^
  back up the same path; each hop closes its own row.
  binaries in and out -> content-addressed blob store, rows keep pointers.

A refusal (won't fit, pull failed, load failed) returns up the path as data. Nothing re-routes it to another box today.

Where it is going (operator direction 2026-10-06)

client
  |
  v
ROUTER  (own package/process; behind core's address, so callers see one address)
  |  a. reads the residents view (derived from call_log the moment a row changes)
  |     and the static verdicts. Nothing else.
  |  b. model loaded on a box with matching settings?
  |        -> proxy straight to that box's FRONT DOOR (skip the worker agent)
  |  c. not loaded anywhere?
  |        -> pick a box whose verdict says it can run
  |        -> that box's worker agent pulls if missing (cold load measured)
  |  d. static verdict says impossible on that box?
  |        -> refuse here: one row, reason + verdict pointer, try the next box
  |  e. the box refuses (live room, load failure)?
  |        -> bounce back: try the next box, one row per decision
  v
WRAPPER FRONT DOOR  (thin when the model is loaded: reuse, forward, measure, log)
  v
ENGINE

CORE  (interface: console, auth, planner/verdicts, arms, help) - not on the hot path

Rules behind it:

  • One row per decision, written by the hop that made it. Core never forwards a call it knows is impossible just to have it logged further down.
  • A model missing from a box is not a refusal: the pull happens inside the call and is the cold-load measurement.
  • With no core/router in front, the wrapper is first: it serves or refuses (the reason as data). Bounce-back is the job of whatever router/core is in front.
  • A changed pair setting on a loaded model evicts and reloads it when idle.

Benchmark call-log history

POST /llm/benchmark/run opens a core call-log row before validation or planning. Accepted runs keep that row pending until their asynchronous outcome is known. Rejected plans retain their constraint reasons in the core response and error. The response and X-Hugpy-Request-Id expose its request ID.

Benchmark history/status read call_log; the JSON state and run archives are no longer read or written. Existing files are left intact as legacy evidence and are not converted into invented historical call records. Grading entries store call pointers and verdicts. History resolves answers and measurements from the referenced execution records. Each benchmark inference core row points back to the orchestration row, and its execution pointer identifies the wrapper row. Pending benchmark rows from a previous core process are marked interrupted.

The brain (failure auto-evaluation)

Ruling: toolserver instructions/hugpy/brain/brain-established-2026-10-06. A brain lives in core: always present, callable, and it evaluates every model-load failure automatically. hugpy-agent, when installed, adds features and access on top (the agent-station TUI); without it, this brain does the work.

  • Event: a hugpy_wrapper.residents row whose load_error changes fires pg_notify('model_rows'); brain.ensure() (started by app.main) listens and evaluates it. No polling.
  • Classify: rules first, from the legacy taxonomy (hard_load_failure, vram_fit, engine_unavailable, unreachable, vision_needs_slot, missing_dependency, other), plus pip-shaped signals (pip install X, No module named 'x', transformers' "requires the following packages").
  • Infer: the brain model is asked only when the rules leave something open (class other, or an import name with no package name, e.g. cv2 → opencv-python). The call goes through core's own /v1/chat/completions with metadata.intent = "brain-evaluate", so it is a call_log row. The brain never overrules a class the rules determined.
  • Record: every evaluation is a Help ticket (help_tickets, kind load-failure), de-duplicated per model/worker/error via occurrences.
  • Call it: POST /llm/brain/evaluate {error, worker?, model_key?, file?}; GET /llm/brain shows the model, policy and listener state.

Which model is the brain. The static hugpy-brain model group (see Model groups below) holds the models the brain may run on, in priority order. When the group is empty it fills itself from the grades: every model whose latest verdicts pass the threshold in each listed grader category (default coding 3/3 + logic 3/3 of the hugpy-native-v2 suite's easy/medium/hard tiers), best first. Resolution: the Settings selection (brain.model) → HUGPY_BRAIN_MODEL → the group's first servable member → the best-graded servable model (flagged below threshold). The Help chat uses the same brain (after HUGPY_HELP_MODEL).

Auto-implement gate. Every evaluation carries auto: {eligible, why}. A fix may be implemented without approval only when brain.auto_fix is ticked and it is a pip fix with named packages; a fix read literally off the error needs nothing more, a fix a model inferred also needs that model to meet the threshold. Otherwise it waits for operator approval.

Settings → Policies → Brain (settings_policies):

key meaning
brain.model the brain's model; unset = automatic (first servable hugpy-brain member)
brain.auto auto-evaluate load failures (default on)
brain.auto_fix the auto-implement tick box (default on)
brain.threshold {grader category: tiers that must pass}, default {"coding": 3, "logic": 3}

Not automated yet (same ruling, next step): the venv ladder for missing_dependency — existing env profiles → a new overlay profile → an isolated profile — each candidate test-loaded, then designated (model_workers.env_profile); auto decides whether that happens on its own. Never pip-install into a shared venv.

Model groups (Priority groups panel)

model_groups.py + sql/019_model_groups.sql: the panel's groups are rows in hugpy_core.model_groups (record shape lifted from legacy comms/priority_groups.py: ordered members, ordered workers, enabled), plus static (cannot be deleted or renamed), role and source (operator | auto). GET/POST /llm/model-groups, PUT/PATCH/DELETE /llm/model-groups/<id>. One structural rule, as before: a model key may be in at most one enabled routing group. Role groups (hugpy-brain, role brain) never route, may be empty, and sit outside that rule. Core's request routing does not walk priority groups yet; the list payload says so (routing: false) and resolve answers that honestly. allocate returns 501 (not lifted).

Verdicts priced at the pair's ctx and KV type

planner.refresh_worker passes each pair's user_settings to measured_verdict.price: the verdict is priced at the pair's ctx_pct (k% of the trained window, floored to 1024) and kv_cache_type (f16 / q8_0 / q4_0). A knob write that touches either re-plans that worker at once (modeldb.pair_knobs → planner.replan), so the console's Memory distribution follows the knobs.

The fix ladder (missing dependencies) — fix_ladder.py

Operator design: try every environment on the box that may already fit, else the box's worker base + the new pip install, else keep that new (broken) install attributed and leave the ticket for the operator. Candidates, best first: BUILT profiles whose frozen lock holds every needed package, then DECLARED-but-unbuilt ones whose manifest holds them (the box builds on the test load). Each candidate is attributed (model_workers.env_profile) and test-loaded (envprofiles.run_test, an env-test call, 10 min cap); a failure is reverted, and its log tail (call_log.response_meta.load_log_tail) is read for the next missing package (transformers' "requires the X library" wording included). The new environment is auto-<model> (worker base + packages, up to 3 rounds). Starts on its own when the evaluation is auto-eligible, else on ✓ approve; a core restart resumes it once its worker re-registers. Progress lives on the ticket (detail.ladder). First real fix: Qwen3.5-0.8B on computron → its vision profile (pillow + the box-pinned torchvision).

Allocation determinations

A benchmark lane refused because the worker does not hold the model goes to the brain (brain.constraint_and_file): on another online worker → reroute; in central's catalog → pull (ACTIVATE, automatic when the gate allows, else "✓ pull" on the allocation ticket); nowhere → not available.

Grader tok/s

/llm/model-metrics2 rows carry a throughput block per worker × quant × alloc and /llm/models/<m>/metrics carries worker_averages (Σ tokens / Σ generation seconds over every recorded call), both from the call log. The Grader tab showed "no calls recorded" everywhere because the rows had only a bare tok/s number and worker_averages was a fixed [].

Metadata

Release files for hugpy-core 0.1.68

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

Source distribution (sdist)

Source distribution for hugpy-core 0.1.68
File Size Uploaded
hugpy_core-0.1.68.tar.gz 200.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hugpy-core 0.1.68
File Interpreter ABI Platform
hugpy_core-0.1.68-py3-none-any.whl Python 3 none any Details

Total release size: 399.0 kB

Release files / hugpy_core-0.1.68.tar.gz

Download URL hugpy_core-0.1.68.tar.gz
Size 200.4 kB
Tags Source
SHA-256 checksum
How to use checksums
498a4e56a8451979b6b8666a4b8a0557f909c5aa2e08a8c3228ab3b388ace175
BLAKE2b-256 checksum
How to use checksums
87e15190f3ee6a90088b4b6c7d954c7b32594817a2e4e9fd677bf2ca57574c12
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.12

Release files / hugpy_core-0.1.68-py3-none-any.whl

Download URL hugpy_core-0.1.68-py3-none-any.whl
Size 198.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d3baed76ba63c9defd16ef0937fd91d395e7d11cac5315ab059cb15d707fc031
BLAKE2b-256 checksum
How to use checksums
bf906d9a2f6b658c476042c6da4aa9d7a4ea89dfec22b7c5b95dcbd745a0c79b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.12

Release history Release notifications | RSS feed

0.4.46

2 release files

0.4.45

2 release files

0.4.44

2 release files

0.4.43

2 release files

0.4.42

2 release files

0.4.41

2 release files

0.4.28

2 release files

0.4.27

2 release files

0.4.26

2 release files

This release

0.1.68 This release

2 release files

0.1.9

1 release file

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

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