tomngdev
/

Tacit-9B / README.md
tomngdev's picture morriszjm's picture
Duplicate from morriszjm/Tacit-9B
7011843
|
Raw History Blame Contribute Delete
4.33 kB
---
license: apache-2.0
base_model: Qwen/Qwen3.5-9B
library_name: transformers
tags:
- decision-making
- self-distillation
- anyjev
---
# Tacit-9B (preview)
Tacit-9B makes typed decisions (choose an option, answer yes/no, or pick an ordered level) in a
single forward pass, returning a probability over the options. It is built on
[Qwen/Qwen3.5-9B](https://huggingface.co/Qwen/Qwen3.5-9B) with AnyJev self-distillation: the base model wrote its own
decision problems, answered them with its reasoning on, and learned to give those answers in one
forward pass. No human labels, external datasets or other models were used.
## Results
Accuracy in one forward pass on the full test sets, with the same prompt and readout for both
models.
| benchmark | Qwen3.5-9B | Tacit-9B | difference |
|---|---|---|---|
| JevBench (public set, 231) | 0.805 | 0.823 | +1.7 pts |
| bev-decision (test split, 46,320) | 0.680 | 0.725 | +4.5 pts |
## Usage
```python
from transformers.dynamic_module_utils import get_class_from_dynamic_module
Tacit = get_class_from_dynamic_module("tacit_decision.Tacit", "morriszjm/Tacit-9B")
# one forward per decision
tacit = Tacit.from_pretrained("morriszjm/Tacit-9B")
# or: send low-confidence decisions to the model's own reasoning
tacit = Tacit.from_pretrained("morriszjm/Tacit-9B", adaptive=True, tau=0.5, max_cot_share=0.2)
# or: the same on vLLM (pip install vllm), for throughput
tacit = Tacit.from_pretrained("morriszjm/Tacit-9B", engine="vllm", adaptive=True)
d = tacit.decide(state="Customer: my package was due last Monday and it still has not arrived.",
question="What does the customer want?",
options=["track_order", "cancel_order", "refund", "change_address"])
print(d["answer"], d["probs"], d["route"]) # route: "one_forward" or "cot"
```
`kind` is `"choice"` (default), `"yes_no"`, or `"score"` (`options` are ordered levels, lowest
first); `decide_batch([...])` takes a list of such dicts.
| argument | default | meaning |
|---|---|---|
| `adaptive` | `False` | send low-confidence decisions to the model's own reasoning (thinking on) |
| `tau` | `0.5` | a decision is low-confidence when the log-probability gap between its top two options is below `tau` |
| `max_cot_share` | `0.2` | at most this share of the last `cot_window` decisions goes to reasoning; `None` removes the cap |
| `cot_window` | `1000` | how many recent decisions the cap counts; `None` counts every decision since loading |
| `cot_max_tokens` | `8192` | reasoning budget of one decision |
| `engine` | `"transformers"` | `"vllm"` runs vLLM in this process; `"server"` uses a running `vllm serve` (see below) |
| `base_url` | `None` | `engine="server"`: the server's `/v1` URL |
| `vllm_kwargs` | `None` | passed to `vllm.LLM`, e.g. `dict(gpu_memory_utilization=0.85, max_model_len=32768)` |
An escalated decision's answer is read from the label distribution after the reasoning, so it also
comes with probabilities. Without `adaptive`, nothing is generated. On vLLM the labels are read from
the top 20 log-probabilities of the full vocabulary (a label outside them counts as 0). The checkpoint also loads as a
plain causal LM (`AutoModelForCausalLM`, vLLM); `tacit_decision.py` holds the prompt it was trained
with.
## Serving with vLLM
```bash
vllm serve morriszjm/Tacit-9B --host 127.0.0.1 --port 8000
```
```python
tacit = Tacit.from_pretrained("morriszjm/Tacit-9B", engine="server",
base_url="http://127.0.0.1:8000/v1", adaptive=True)
```
Only the tokenizer loads on the client. For many clients sharing one cap, run the HTTP gateway that
ships in this repo in front of the server:
```bash
hf download morriszjm/Tacit-9B tacit_decision.py --local-dir .
python tacit_decision.py serve --model morriszjm/Tacit-9B --upstream http://127.0.0.1:8000/v1 --adaptive --port 8100
curl -s 127.0.0.1:8100/v1/decide -H 'Content-Type: application/json' -d '{"state": "Customer: my package has not arrived.", "question": "What does the customer want?", "options": ["track_order", "refund"]}'
```
On Hopper GPUs vLLM compiles this model's gated-delta-rule kernel with `nvcc` on first use, so the serving machine needs the CUDA toolkit (`engine="vllm"` in Python switches to a Triton kernel by itself).
Apache-2.0, as is the base model by the Qwen team.