makepad/libs/ai/hub/python/rig_skintokens.py
Admin e37c263b9c ai backbone: the hub era — makepad_ai deleted, every backend is a hub pipe; machine residency elections, job leases, ETA placement; the store only stores; creator pipelines run in the app (aicore)
Squashed from work:
- asset-ai: FastH3 4-step fast video backend; clip keyframes on the wire
- asset-ui: loop video chains — text→image→video that ends where it began
- h3: safetensors -> pruned-Q4_K GGUF quantizer for the 24GB DiT tiers
- h3_quant_gguf verify: row-error gates calibrated to the measured Q4_K floor
- asset-ai realtime: the feedback loop — the source anchors, the drifted frame inits
- asset-ai realtime: a feedback loop survives a resize and travels by default
- asset-ai realtime: the feedback loop frees itself from the feed handshake and pauses for its listener
- asset-ai realtime: the outbound encode leaves the loop's critical path
- asset-ai ocr: the ocr domain — Chandra 2 at page resolution, and the tower goes planner-owned
- llm slots: a lane can hold an image span — embedding prefill and a rope cursor of its own
- vision tower on CUDA: the encode leg gets its two missing kernels
- llm/ocr: one M-RoPE grid encoder for both image paths, and a livelock made an error
- vision tower on CUDA: the f16 GEMM keeps the precision it was throwing away
- live: a feed that moves box takes its trip with it — one seed image
- vision tower on CUDA: the tiled attention becomes bit-exact, and tensor cores go
- llm prefill on CUDA: the MMA attention kernel gets the tile a 4-to-1 model needs
- asset-ai ocr: the CUDA encode lane joins the integration — vision-parity sits beside run's three arms, and the kernels
- Merge branch 'ocr-perf-integration' into work
- asset-ai: the live anchor can follow the trip, and text leaves the 5090
- asset-ai: the camera moves the world, and the world starts still
- asset-import: the EA strategy classics, in the one 2D contract
- rtsmap: one seeded generator for tiled strategy maps
- asset-ui: one card for the strategy classics, with a pack dropdown
- asset-ai: music3 reference-audio path, ocr/h3 backends, registry
- asset: mp4 sample index for range-streaming, chat tools, import profiles
- cnc: tiberium is twelve growth frames, not twelve empty variants
- platform: native file and save dialogs, in-house on all three desktops
- chat: the scan holds out for a lane home
- chat: a full home queues you — take the free lane
- chat: the preload has a percentage, and the boundless cap stops showing
- llm cuda: the 32x2 attention tile — even GQA ratios stay on MMA
- sa3 gets a bake path: the sfx model's tables precomputed by a diffusion-side bin
- sqlite_query: anti-join regression test
- td import: HARV's second frame block is its harvesting cycle, not a turret
- asset-ui: sprite enhancement runs on the 32B dev DiT — distillation, not the prompt, was the ceiling
- ai-hub: makepad-asset-ai becomes makepad-ai-hub at libs/ai/hub, the chat pane becomes makepad-chat-ui, the service bin
- asset-ui: test health fixtures grow the realtime field they were born without
- ai-hub: one home at ~/.makepad — weights/ run/ cache/ logs/, the service cache migrates from ai_content by a single re
- ai-hub: subprocess workers die with the node — process groups everywhere, PDEATHSIG on linux, one KILL_ON_JOB_CLOSE Jo
- ai-hub: the hub object — AiHub::in_process, pipes vocabulary, and the local LLM engine generalized out of mpfiles (aic
- strict-json: the dependency-free JSON module gets its own crate; asset-client re-exports it so nothing downstream move
- ai-hub: the machine layer — node entries, the 0600 machine token, and the residency election that IS the lock (aicore
- ai-hub: MPHUB1 — the fabric beacon only dedicated nodes can send (aicore §4)
- ai-hub: job leases — work lives only while it is renewed (aicore §8)
- asset-creator: the pipeline library is born — specs, the deps gate, and the derived-state law (aicore §9)
- ai-hub: RAM residency facts — the CPU-side twin of residency.rs (aicore §3)
- ai-hub: ETA placement primitives — relative GPU throughput, the four-term estimate, and an observable breakdown (aicor
- ai-hub: leases go live on the wire — origin fields on submit, /job/<id>/keepalive, /bye, and the reaper that cancels w
- ai-hub: the chat providers move in — fleet qwen, openai, grok, claude/codex/grok CLIs, the responses driver, and the w
- asset-creator: the engine — one pipeline run against the hub, deps-gated, spliced, cancellable, resumable-by-construct
- ai-hub: the machine node mode — --machine binds loopback, registers in ~/.makepad/run, and exits on its own once idle
- asset-creator: makepad-creator-run — the detached client for runs that must outlive a window (aicore §9)
- ai-hub: a native Claude Messages-API provider — API-key or Claude Code OAuth, bounded SSE streaming, injected tools (a
- route + converse: off makepad_ai — the Agent seam moves to converse, route's cloud dispatcher rides the hub's Claude p
- asset-creator: the preset tables move in — fifteen chain-policy constants shared by every creator app (aicore §9 / P6)
- makepad_ai is deleted — every backend is a hub pipe, the agent seam lives with its consumers (aicore §14, decided 2026
- ai-hub: loads hold the machine residency election — set_model_state claims on Loaded and publishes the service port (a
- ai-hub: chats run the machine election — route to a serving holder, wait on a loading one, claim and publish when open
- ai-hub: pick_for_domain_eta — ETA-ranked placement over the shared hard-filter core (aicore §6 / P4)
- asset-creator: the engine picks a provider per stage at dispatch time — a chain's later stages see fresh fleet state (
- ai-hub: the fabric secret gates the service HTTP surface — bearer on everything but /health and the ticketed peer path
- vj: DREAM runs execute in the app — pipelines.rs becomes the run it used to watch (aicore §9 / F1)
- asset-creator: the runner — generate one thing and put it in the catalog, one implementation for every surface (aicore
- chat-ui: the session runs in the app — no broker anywhere on the chat path (aicore P8 / F5)
- asset-store: assets.query is a first-class query endpoint — the bounded SQL surface outlives the broker (aicore P8 / F
- asset-creator: CreatorTools — the chat tool pack for a store that only stores (aicore §9 / P8)
- asset-store: the shrink — the store stores (aicore P7)
- importer + asset-server host: the coordination era ends (aicore P7)
- store config purge + asset-ui goes fleet-direct; the derive protocol gets its route proof (aicore P7)
- client + chat dispatcher: the dead wire comes out (aicore P7/P8)
- ai-hub: 0.3.0 — the health version says which era a node runs
- ai-hub: the default fleet is 'gen' — apps hear the LAN without env plumbing
- ai-hub: the preload note percents the prefill, not the job bar
- ai-hub: conversations keep their KV — the wire mirror, the lane identity, the in-turn dynamic context (aicore §7)
- ai-hub: an open-think model is thinking from its first token
- libs: the zero-warning sweep — stitch casts say what they mean, xatlas keeps upstream's surface quietly
- zero-warning sweep, round two — the first full-workspace pass
- zero-warning sweep, round three — the model lanes and the deep examples
- zero-warning sweep, round four — the last stragglers
- zero-warning sweep, round five — vj and chat-ui
- zero-warning sweep, round six — three cascades

Co-authored-by: Claude <info@makepad.nl>
2026-09-01 16:46:31 +02:00

128 lines
4.6 KiB
Python

#!/usr/bin/env python
"""rig_skintokens.py <in.glb> <out.glb> — the rig domain's box script.
Wraps the SkinTokens one-pass auto-rigger (C:\\ai\\SkinTokens, venv_st): mesh
GLB in, skinned GLB out, --use_transfer keeps the input texture. Runs under
the SAME interpreter the service template names (venv_st python), calling
SkinTokens' demo.py as a subprocess with its repo dir as cwd (it spawns its
own bpy_server).
Protocol (subproc_img.rs): progress lines "@P <frac 0..1> <stage>" on
stdout; anything else passes through to the service log. Non-zero exit or a
missing/invalid output file fails the job. An optional params sidecar sits
at <in.glb>.json ({"seed": N}). Upstream enables stochastic sampling and
beam search but exposes no seed flag, so this wrapper seeds Python, NumPy and
Torch before executing demo.py. Upstream's SkinVAE condition encoder also
constructs ``np.random.default_rng(None)``; that generator ignores the legacy
global NumPy seed and otherwise draws fresh OS entropy on every request. The
bootstrap maps only the ``None`` case to the request seed while preserving
explicit seeds (the Michelangelo encoder deliberately uses seed 0). That
makes a request reproducible and gives the native port a fixed oracle instead
of a moving target. The released demo also forgets to put the complete
TokenRig module in eval mode (only its VAE is switched), leaving
Michelangelo's FPS random start enabled. The bootstrap wraps the imported
model factory and applies ``eval()`` before demo inference.
Env knobs:
SKINTOKENS_DIR repo dir (default C:\\ai\\SkinTokens)
SKINTOKENS_ARGS extra demo.py args, whitespace-split
"""
import json
import os
import subprocess
import sys
def progress(frac, stage):
print("@P %.3f %s" % (frac, stage), flush=True)
def main():
if len(sys.argv) != 3:
print("usage: rig_skintokens.py <in.glb> <out.glb>", flush=True)
return 2
in_glb = os.path.abspath(sys.argv[1])
out_glb = os.path.abspath(sys.argv[2])
repo = os.environ.get("SKINTOKENS_DIR", r"C:\ai\SkinTokens")
params = {}
try:
with open(in_glb + ".json", "r", encoding="utf-8") as f:
params = json.load(f)
except OSError:
pass
print("rig: params %r" % (params,), flush=True)
progress(0.02, "skintokens: starting")
seed = int(params.get("seed", 0)) & 0xFFFFFFFF
bootstrap = (
"import random,runpy;"
f"seed={seed};random.seed(seed);"
"import numpy as np;np.random.seed(seed);"
"_make_rng=np.random.default_rng;"
"np.random.default_rng=lambda value=None:_make_rng(seed if value is None else value);"
"import torch;torch.manual_seed(seed);torch.cuda.manual_seed_all(seed);"
"import src.server.spec as _spec;_get_model=_spec.get_model;"
"_spec.get_model=lambda *args,**kwargs:_get_model(*args,**kwargs).eval();"
"runpy.run_path('demo.py',run_name='__main__')"
)
cmd = [
sys.executable,
"-c",
bootstrap,
"--input", in_glb,
"--output", out_glb,
"--use_transfer",
]
extra = os.environ.get("SKINTOKENS_ARGS", "").split()
cmd.extend(extra)
print("rig: run %r (cwd %s)" % (cmd, repo), flush=True)
progress(0.10, "skintokens: model load + autoregressive rig")
child = subprocess.Popen(
cmd,
cwd=repo,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1,
)
# Stream child output into the service log; nudge the fraction along on
# recognizable phase lines (SkinTokens prints per-stage banners).
frac = 0.10
for line in child.stdout:
line = line.rstrip("\r\n")
low = line.lower()
for needle, at in (
("load", 0.20),
("skeleton", 0.40),
("skin", 0.60),
("transfer", 0.75),
("export", 0.85),
):
if needle in low and at > frac:
frac = at
progress(frac, "skintokens: " + needle)
break
print("st| " + line, flush=True)
code = child.wait()
if code != 0:
print("rig: demo.py exit %d" % code, flush=True)
return 1
# Output contract: a GLB that actually carries a skin.
try:
with open(out_glb, "rb") as f:
head = f.read(64 * 1024 * 1024)
except OSError as e:
print("rig: output missing: %s" % e, flush=True)
return 1
if head[:4] != b"glTF" or b'"skins"' not in head:
print("rig: output is not a rigged GLB", flush=True)
return 1
progress(0.98, "skintokens: done")
return 0
if __name__ == "__main__":
sys.exit(main())