Download code/decision_engine_v6r.py from fdemelo/jegue: direct link, hf CLI and curl.
- Browser
- Download file 4.77 kB
-
https://huggingface.co/fdemelo/jegue/resolve/main/code/decision_engine_v6r.py
- Command line
-
hf download hf://fdemelo/jegue/code/decision_engine_v6r.py
-
curl -L -o decision_engine_v6r.py https://huggingface.co/fdemelo/jegue/resolve/main/code/decision_engine_v6r.py
4.77 kB
| """Decision Index engine with a learned router between the two v6 levels: every question gets the direct slot pass first; the router head (tools/router_fit_final.py, | |
| CKPT/router-direct-brief.npz: P(direct wrong) x P(brief right | direct wrong) from the direct pass pooled slot hidden state + confidence) decides per question whether the brief | |
| rationale path (BriefSlotEngine) is run instead. Per-option (parallel) and non-choice questions stay direct. Escalated questions of a request are batched through the brief path together. | |
| python -m decision_index run --engine decision_engine_v6r:RoutedSlotEngine --option model=Qwen/Qwen3.5-9B --option run=RUN --option ckpt=final [--option tau=0.02] ... | |
| Options: those of BriefSlotEngine (context is fixed to brief for the escalated path), tau (override of the stored threshold; `inf` = never escalate, `-inf` = always). | |
| """ | |
| import os | |
| import sys | |
| HERE = os.path.dirname(os.path.abspath(__file__)) | |
| sys.path.insert(0, HERE) | |
| import numpy as np # noqa: E402 | |
| import torch # noqa: E402 | |
| import answer_slot as AS # noqa: E402 | |
| from decision_engine_dense import DenseSlotEngine # noqa: E402 | |
| from decision_engine_v6 import BriefSlotEngine # noqa: E402 | |
| def _lg(p): | |
| p = np.clip(p, 1e-4, 1 - 1e-4) | |
| return np.log(p / (1 - p)) | |
| class RoutedSlotEngine(BriefSlotEngine): | |
| name = "dense-slot-routed" | |
| latency = ("In-process request wall time (Hugging Face path): direct slot pass for every question, router head, and the brief path (batched rationale generation + adapted slot pass) " | |
| "only for the questions the router escalates. Not the board latency path; see tools/vllm_requests_0f.py for decode timing.") | |
| def __init__(self, tau=None, **options): | |
| options["context"] = "brief" | |
| options.setdefault("temperature", "none") | |
| super().__init__(**options) | |
| run, ck = options["run"], options.get("ckpt", "best") | |
| blob = np.load(os.path.join(ck if os.path.isdir(ck) else os.path.join(run, ck), "router-direct-brief.npz")) | |
| self.knots = blob["knots"]; self.tau = float(blob["tau"]) if tau in (None, "") else float(tau) | |
| self.W = {p: {k: blob[f"{p}_{k}"] for k in ("mh", "sh", "mc", "sc", "w")} for p in ("w", "f")} | |
| self.provenance.update({"router": f"direct->brief head, tau {self.tau}"}) | |
| def _score(self, pooled, conf, k): | |
| x = _lg(np.array([conf], dtype=np.float64)) | |
| C = np.concatenate([x[:, None], np.maximum(0, x[:, None] - self.knots[None]), np.log([[float(k)]]), np.log([[float(k)]]) * x[:, None]], 1) | |
| h = pooled.double().cpu().numpy()[None] | |
| f = lambda M: float(np.clip((np.concatenate([(h - M["mh"]) / M["sh"], (C - M["mc"]) / M["sc"], np.ones((1, 1))], 1) @ M["w"])[0], 0, 1)) | |
| return f(self.W["w"]) * f(self.W["f"]) | |
| def __call__(self, state, questions): | |
| answers, raw, esc = {}, {}, {} | |
| tokens = 0 | |
| try: | |
| for qid, q in questions.items(): | |
| keys, r = self._render(state, q) | |
| logits, pooled = self._logits(r, None) | |
| p = torch.softmax(logits, -1).cpu().numpy().astype(np.float64) | |
| p = p / p.sum() | |
| score = None | |
| if q["type"] == "choice" and AS.slot_mode(r["qtype"], len(keys)) != "parallel": | |
| score = self._score(pooled, float(p.max()), len(keys)) | |
| if score >= self.tau: | |
| esc[qid] = q | |
| raw[qid] = {"routed": "brief", "router_score": round(score, 5), "direct_conf": round(float(p.max()), 4)} | |
| continue | |
| probs = dict(zip(keys, (float(x) for x in p))) | |
| answers[qid] = {"type": "choice", "choice": max(keys, key=lambda x: probs[x]), "probabilities": probs} if q["type"] == "choice" else {"type": "noul", "noul": probs["true"]} | |
| raw[qid] = {"routed": "direct", "router_score": None if score is None else round(score, 5), "prompt_tokens": len(r["ids"]), "direct_conf": round(float(p.max()), 4)} | |
| tokens += len(r["ids"]) | |
| except torch.OutOfMemoryError: | |
| torch.cuda.empty_cache() | |
| try: | |
| from decision_index.engines.base import Unsupported | |
| except ImportError: | |
| from engine_base import Unsupported | |
| raise Unsupported("out of memory on a long prompt") | |
| if esc: | |
| resp_b, raw_b = BriefSlotEngine.__call__(self, state, esc) | |
| answers.update(resp_b["answers"]); tokens += resp_b["usage"]["input_tokens"] | |
| for qid, v in raw_b.items(): | |
| raw[qid].update(v) | |
| return {"model": self.model_id, "answers": {qid: answers[qid] for qid in questions}, "usage": {"input_tokens": tokens}}, raw | |