THX-02

THX-02 is a thinking decision model. You give it a state (a message, a ticket, a document, a JSON record, an agent trace, a photo or a chart) and a set of typed questions written in plain language. It returns an answer to every question with a probability for every option, in tens of milliseconds. When it is unsure and the question calls for reasoning, it can first write a short thought and then decide.

THX-02 is the successor of THX-01 (0.3 B): 65.06 against 11.30 on the same evaluation.

  • Accurate: 65.06 on the Decision Index 0.3 public index with thinking, 63.83 without; 72.19 on the public sets of the Decision Vision Index (see Evaluation).
  • Fast: median 50 ms per request without thinking and 79 ms with self-gated thinking on one RTX PRO 6000; 129 requests per second on one RTX 4090.
  • Calibrated: every answer is a full probability distribution over the options you supplied. The model never invents an option and generates no free text unless it thinks.
  • Multimodal: text, images and charts in the same request (up to 4 images).
  • Multilingual: trained and evaluated on more than 20 languages in post-training.
  • No retraining for new tasks: the label set is part of the request.

THX-02 on an egg grading line

Quality control on an egg grading line: an open-vocabulary detector draws the boxes, THX-02 decides clean, dirty or cracked for every egg (16 eggs per frame, one RTX 4090). The detector is used for this demo only and is not part of the release. The footage is AI-generated; full-resolution MP4.

Parameters 4.5 B (decision model) + 60 M think adapter
Context trained up to 32k tokens per request
Question types choice (up to 255 options), noul (yes/no), score (ordered scale)
Precision BF16 (GPU), BF16 or FP32 (CPU)
License Apache-2.0

Contents

  1. Quickstart
  2. Demos
  3. Examples
  4. Request format
  5. Thinking
  6. Evaluation
  7. How THX-02 was trained
  8. Production API
  9. Phones and Termux
  10. Repository layout
  11. Limitations

Quickstart

The fastest way: the thx02 package from PyPI. The client has no dependencies, so it also works in Termux on Android.

pip install thx02                          # API client + the thx02 command
export HALX_API_KEY=sk-...                 # HAL-X API key (optional on the free tier, which is limited per IP)
thx02 "Salam, kartimdan iki defe pul cixilib" --choice "team=billing:charges and refunds,support:technical problems" \
      --yesno "Does the customer ask for a refund?"
from thx02 import Client, choice, noul
thx = Client()                             # api.hal-x.ai; Client(base_url="http://host:8200") for your own server
thx.decide("I was charged twice", {"team": choice("Which team?", billing="Charges", shipping="Deliveries"),
                                   "refund": noul("Does the customer ask for a refund?")}, think="auto")

API reference: https://api.hal-x.ai/docs/thx-02. To run the model yourself:

pip install "thx02[local]"                 # then: from thx02 import THX02; THX02.load("HAL-X-AI/THX-02")

Or from this repository:

hf download HAL-X-AI/THX-02 --local-dir THX-02 && cd THX-02
pip install -r requirements.txt            # add requirements-fast.txt for the compiled GPU path
from thx02 import THX02

model = THX02.load(".")                    # GPU if available; THX02.load(".", device="cpu") on CPU

out = model.decide(
    "Salam, kartimdan iki defe pul cixilib, geri qaytarin zehmet olmasa.",
    {
        "team":   {"type": "choice", "instructions": "Which team should handle this?",
                   "criteria": {"billing": "Charges and refunds", "support": "Technical problems", "sales": "Buying a product"}},
        "refund": {"type": "noul", "instructions": "Does the customer ask for a refund?"},
        "anger":  {"type": "score", "instructions": "How frustrated is the customer?", "criteria": ["calm", "annoyed", "angry"]},
    },
)
out["answers"]["team"]     # {"type": "choice", "choice": "billing", "probabilities": {"billing": 0.96, ...}, "confidence": ...}
out["answers"]["refund"]   # {"type": "noul", "noul": 0.97}

With images:

import base64
img = "data:image/png;base64," + base64.b64encode(open("chart.png", "rb").read()).decode()
model.decide("Chart of inflation and the policy rate, 2018-2025.",
             {"year": {"type": "choice", "instructions": "In which year was the real policy rate most negative?",
                       "criteria": {"2020": "2020", "2021": "2021", "2022": "2022"}}},
             images=[img], think=True)

Demos

All three recordings show real THX-02 answers on one RTX 4090; nothing was trained for these tasks.

Live classification

Live classification in 16 languages

24 customer messages in 16 languages are routed to a department, with a priority and a sentiment for each. All 24 are decided in one /v1/decide/batch call of 641 ms. A message whose top department is below 0.60 goes to a person: the vague "hey, quick question…" scored 0.38 and was sent to human review.

Screen agent

THX-02 books a flight from screenshots

Goal: "Book the cheapest flight from Baku to Istanbul on 24 October that departs before noon, for 2 adults." At every step THX-02 sees a screenshot of a mock booking site with numbered buttons and picks the next button to click (about 170 ms per step). On the results page it thinks, compares the morning flights and books 09:15 for €142 per adult instead of 06:40 for €189. Six clicks, no script.

Playing from pixels

THX-02 plays Snake

THX-02 plays Snake from screenshots only: each move is one question with the three legal moves as options (about 130 ms per move). The recording is the best of 6 games (11 apples in 89 moves); the average over the 6 games is about 7 apples.

Examples

All outputs below are real responses of THX-02 (tta=4, one RTX 4090, latency measured through the HTTP API).

Routing support tickets

One request answers four questions about a ticket: the department, the priority, whether money is asked back and whether the customer threatens to leave. The departments are plain-language descriptions in the request, so a new department needs no training.

departments = {"billing": "Charges, refunds, invoices, subscriptions",
               "technical": "Bugs, errors, app or login problems",
               "shipping": "Deliveries, tracking, lost or damaged parcels",
               "sales": "Pricing questions, upgrades, new purchases",
               "legal": "Contracts, privacy and data requests, legal threats",
               "security": "Hacked accounts, fraud, phishing"}
model.decide(ticket, {
    "department": {"type": "choice", "instructions": "Which department should handle this ticket?", "criteria": departments},
    "priority":   {"type": "score", "instructions": "How urgent is this ticket?", "criteria": ["low", "normal", "high", "urgent"]},
    "refund":     {"type": "noul", "instructions": "Is the customer asking for money back?"},
    "churn":      {"type": "noul", "instructions": "Is the customer threatening to leave or dispute the charge?"}})
Ticket Department Priority Refund Churn risk Latency
"I cancelled my trial on the 3rd but you charged my card $49 three times this week. I wrote to support last Monday and nobody answered. If this is not fixed by Friday I am disputing all three charges with my bank and closing my account." billing 0.94 urgent 0.63 yes 0.78 yes 1.00 143 ms
"Salam, sifarişim 10 gündür gəlməyib, izləmə nömrəsi də işləmir. Hədiyyə idi, şənbə günü lazımdır." (Azerbaijani: the order has not arrived in 10 days, tracking does not work, needed by Saturday) shipping 0.98 urgent 0.56 no 0.12 no 0.13 126 ms
"Біреу менің аккаунтыма кіріп, құпия сөзді өзгертіпті. Маған таныс емес құрылғыдан кіру туралы хат келді." (Kazakh: someone logged into my account from an unknown device and changed the password) security 0.99 urgent 0.65 no 0.01 no 0.02 125 ms
"你好,我们公司想把团队版从20个席位升级到150个席位,年付有没有折扣?" (Chinese: upgrade the team plan from 20 to 150 seats, is there an annual discount?) sales 0.97 normal 0.66 no 0.02 no 0.01 122 ms

Routing requests between models

THX-02 can sit in front of several LLMs and tools and send every message to the cheapest backend that can answer it.

backends = {"small": "Small fast model: chit-chat, simple rewrites, short factual answers",
            "code": "Code model: writing or fixing code and SQL",
            "reasoning": "Large reasoning model: multi-step math, planning, analysis",
            "search": "Web search: news, prices, anything after the training cutoff",
            "human": "Hand off to a human: complaints, legal or medical risk"}
model.decide(message, {"route": {"type": "choice", "instructions": "Which backend should answer this user message?",
                                 "criteria": backends}})
Message Route Latency
"Write a SQL query that returns the top 5 customers by revenue in the last 90 days from orders(customer_id, amount, created_at)." code 1.00 140 ms
"What is the EUR to USD exchange rate right now?" search 0.94 120 ms
"A train leaves at 9:40 and travels 340 km at 85 km/h, with a 25-minute stop halfway. When does it arrive?" reasoning 0.95 120 ms
"thanks, that was helpful!" small 0.98 120 ms

The examples below compare a direct answer with think=True, return_thoughts=True.

Reading a chart

Inflation and policy rate

model.decide("Chart of Country X: CPI inflation and the central bank policy rate, 2018-2025.",
             {"most_negative": {"type": "choice",
                                "instructions": "Real policy rate = policy rate minus inflation. "
                                                "In which year was the real policy rate most negative?",
                                "criteria": {"2020": "2020", "2021": "2021", "2022": "2022", "2023": "2023"}}},
             images=[chart], think=True, return_thoughts=True)
2020 2021 2022 2023 latency
direct 0.38 0.34 0.24 0.04 0.46 s
thinking 0.19 0.67 0.12 0.02 1.46 s

Thought:

To find the most negative real policy rate, calculate (Policy Rate - Inflation) for each year: 2018: 2.4 - 2.4 = 0.0; 2019: 1.6 - 1.8 = -0.2; 2020: 0.1 - 1.2 = -1.1; 2021: 0.1 - 4.7 = -4.6; 2022: 4.3 - 8.0 = -3.7; 2023: 5.3 - 4.1 = 1.2; 2024: 4.4 - 2.9 = 1.5; 2025: 3.9 - 2.7 = 1.2. The most negative value is -4.6 in 2021.

The direct read sees "low rate, rising inflation" and leans to 2020. With thinking, THX-02 reads both series off the chart, subtracts year by year and moves to the correct year.

Price elasticity and revenue

State: "A cafe raised the price of a latte from $4.00 to $5.00. Daily sales fell from 300 cups to 200 cups."

Question Direct Thinking
Is demand elastic, unit elastic or inelastic (midpoint method)? elastic 0.57 elastic 0.78
What happened to daily revenue? same 0.76 (wrong) down 0.53

Thought for the revenue question:

  1. Calculate original revenue: $4.00 x 300 cups = $1,200. 2. Calculate new revenue: $5.00 x 200 cups = $1,000.
  2. Compare: $1,000 is less than $1,200. 4. Conclusion: Revenue decreased.

Central bank decision

State: "Monthly brief: headline CPI 5.2% y/y (target 2%), core CPI 4.6% and rising for 3 months, unemployment 3.4% (near a 50-year low), wage growth 6.1%, GDP growth 2.8% annualized, the currency fell 7% against the dollar this quarter. Policy rate is 4.25%."

Question Type Direct Thinking
What should the central bank do at the next meeting? choice hike 0.90 hike 0.94
How hawkish should the statement be? score hawkish 0.87 hawkish 0.90
Is the economy already in recession? yes/no no 0.98 no 0.98

All three questions are answered in one request in 121 ms without thinking.

Loan policy check

State: "Applicant: monthly net income $4,200; rent $1,500; car loan $450/month; credit card minimum payments $250/month; requesting a personal loan with a $600/month payment. Bank policy: total debt payments (including rent) must not exceed 50% of net income."

pass fail latency
direct 0.40 0.60 116 ms
thinking 0.20 0.80 850 ms
  1. Total current monthly debt payments: $1,500 + $450 + $250 = $2,200. 2. Add the requested loan: $2,800.
  2. 50% of net income: $2,100. 4. $2,800 > $2,100: the ratio exceeds the 50% threshold.

The direct answer is already right; thinking turns a hesitant 0.60 into a confident 0.80 that can be acted on.

Quality control from a camera

The video at the top of this card runs one request per egg crop with the question {"quality": {"type": "choice", "criteria": {"clean": ..., "dirty": ..., "cracked": ...}}} through /v1/decide/batch: 16 eggs per frame are decided in about 320 ms on one GPU, without any training on eggs.

Request format

Field Type Meaning
state string or JSON what the decision is about
questions object 1 to 64 named questions
images list of data URIs or base64 optional, up to 4
think false, "auto", true see Thinking; default false
tta 1 or 4 option-order averaging for choice questions; 4 is more accurate and about 2x slower

Question types:

Type Fields Answer
choice instructions, criteria: {key: description} (1 to 255) choice, probabilities, confidence
noul instructions noul = probability of yes
score instructions, criteria: ordered list of labels probabilities per level, expected score

Write the criteria as short descriptions of what each option means; THX-02 reads them, so a new label set needs no training. Several questions about the same state can go in one request.

Thinking

Most decisions are recognition: the answer is visible in the state. Some need a step of work first: a calculation, a comparison of two numbers on a chart, a chain of conditions in a contract. For those, THX-02 can think.

How it works.

  1. THX-02 reads every question directly and gets a probability distribution p0 (one forward pass, no text generated).
  2. A self-gate decides whether thinking is worth it. The model answers a second, internal yes/no question about the request: does this need step-by-step work (calculation, logic, code tracing, multi-hop reasoning) rather than recognition? Thinking starts only when the direct answer is unsure (top probability below tau) and the gate says yes.
  3. The thinker, the same network with a 60 M-parameter think adapter, writes a short note of at most a few dozen words: only the facts or the calculation that decide the answer.
  4. THX-02 reads the question again with the note attached and gets p1. The final answer mixes both reads, so a wrong note cannot override a confident direct read:

p  =  α p0+(1−α) p1,think  ⟺  max⁡kp0(k)<τ  ∧  g≥γp \;=\; \alpha\,p_0 + (1-\alpha)\,p_1, \qquad \text{think} \iff \max_k p_0(k) < \tau \;\wedge\; g \ge \gamma

where $g$ is the gate probability, $\tau = 0.6$, $\gamma = 0.2$ and $\alpha = 0.7$ in "auto" mode.

Thinking budget. The note is capped in tokens, which bounds the latency of a request:

Mode When it thinks Note budget Mixing Typical latency
think=False never 0 p0 40 to 90 ms
think="auto" unsure (tau 0.6) and the gate says reasoning helps (gate 0.2) 96 tokens alpha 0.7 median 79 ms; 0.3 to 1 s when it thinks
think=True almost always (tau 0.97, no gate) 320 tokens alpha 0.5 0.5 to 2 s

"auto" is the setting behind the Decision Index score. True is for interactive use, where seeing the reasoning matters more than speed. return_thoughts=True returns the note in answer["thought"]. Thoughts work with images: the thinker reads the chart or photo, writes down the values it needs and computes.

Where it helps. On the Decision Index sample, thinking raised GSM8K by 25.2 points, ANLI by 6.1, CRUXEval by 5.1, GPQA Diamond by 4.3 and ARC-Challenge by 3.4, and the Knowledge and Reasoning area by 3.6 points overall. It costs one to three points on tasks that are matters of taste or recognition (color preference, Habermas consensus, WinoGrande); the gate keeps most of those questions on the direct path.

Where thinking changes the answer

Running the thinker. Thoughts come from a vLLM server built from the files in thinker/:

python -m thx02.build_thinker --model . --out thinker-merged
vllm serve thinker-merged --served-model-name thx02-thinker --max-model-len 8192 \
    --speculative-config '{"method":"mtp","num_speculative_tokens":3}'      # add --quantization fp8 on 24 GB GPUs
model = THX02.load(".", thinker_url="http://127.0.0.1:8000")
model.decide(state, questions, think="auto")

Without a thinker, think is ignored and THX-02 answers directly.

Evaluation

The Decision Index 0.3 public index covers 37 benchmarks in five areas (knowledge and reasoning, language understanding, retrieval and classification, tools and automation, arts and human taste). Every benchmark is chance-corrected (0 = random guessing, 100 = perfect) and unanswered requests count as wrong.

Decision Index 0.3

Model Size Decision Index 0.3 Knowledge Language Retrieval Tools Arts Median latency
THX-02, thinking (auto) 4.5 B 65.06 51.4 68.7 67.3 82.9 53.6 79 ms
THX-02, direct 4.5 B 63.83 47.8 67.3 67.0 83.0 54.7 50 ms
Sieve-31B * 31 B 62.52 49.9 65.6 69.5 78.7 43.5
Verdin-4B * 4.2 B 58.29 35.3 66.1 64.3 85.6 35.5
H2O-Lightning-4B * 4.7 B 57.86
d3-flash * 8.4 B 57.79 43.3 60.6 64.2 76.0 41.9
Cerno 4B v1.1 * 4.2 B 57.60 34.5 63.0 65.9 82.9 40.6
CoCo-Decision-4B v2.3 * 4.2 B 55.38 34.8 63.2 59.9 76.8 40.2
d3-mini * 4.5 B 54.90 39.8 57.8 63.6 72.0 37.7
d1-3B 3.1 B 48.19 22.3 58.3 49.6 74.2 38.8 19 ms **
THX-01 0.3 B 11.30 2.3 9.0 22.7 18.6 4.4 9 ms **

Rows without a star were measured by us with the official Decision Index 0.3 kit and scorers on the same stratified sample of 6,018 requests from the public suite (about 117 requests per benchmark). THX-02 was measured on one RTX PRO 6000; rows marked ** on one RTX 4090 (the index does not depend on the GPU, latency does). Rows marked * are the public index published by the authors on the full public suite (140,178 requests), taken from their result files on Hugging Face (index.json of each run; H2O-Lightning-4B reports the overall index only). For reference, the published full-suite index of d1-3B is 48.99, close to our 48.19 on the sample.

The public index is not the leaderboard Full score, which adds the maintainers' private tests. Per-benchmark sampling error on 117 requests is several points; compare areas and the overall index rather than single benchmarks. THX-02 uses option-order averaging (tta=4) and joint reads for facet-style requests in these runs.

Decision Index by area

Vision

The Decision Vision Index 0.3 scores image understanding: spatial relations and depth (CV-Bench), multi-image perception (BLINK), real-world photos (RealWorldQA), scientific charts (CharXiv), infographics, web navigation from screenshots (Mind2Web), key-information extraction from receipts and forms (CORD, FUNSD), meme moderation, and exam questions rendered inside the image (R-Bench-M, MMMU-Pro vision).

Decision Vision Index

Benchmark THX-02
Public vision index 72.19
CV-Bench 78.8
BLINK 56.5
RealWorldQA 64.8
CharXiv 78.9
InfographicVQA 94.5
Mind2Web 89.7
KIE (CORD + FUNSD) 92.9
Moderation (Hateful Memes) 53.8
R-Bench-M 25.3
MMMU-Pro vision 36.0

All 11,410 public requests of the ten available sets, one question per request, no thinking. Winoground, the eleventh set, is gated on Hugging Face and was not run, so the index here averages ten sets.

Speed

Speed

Throughput was measured with production-size requests (111 tokens: support tickets, refunds, model routing, frustration scores in four languages) on one RTX 4090 in BF16: 129 requests per second in-process with the compiled packed path and 105 requests per second through the HTTP API with 64 concurrent clients (p50 615 ms at that load). Several GPUs scale linearly: start one worker per GPU (see Production API).

How THX-02 was trained

THX-02 was post-trained in five stages. Every stage was kept only if it raised the index on a held-out tuning split.

Where the points came from

Every training stage optimises the same objective. For a question with options $k$, target distribution $q$ (teacher, gold or a blend) and model distribution $p_\theta$, the loss is a strictly proper scoring rule plus a KL anchor to the model the stage starts from:

L(θ)  =  −(∑kqklog⁡pθ(k)  +  12 Ssph(pθ,q)  −  1score RPS(pθ,q))  +  β KL(pθ0 ∥ pθ)\mathcal{L}(\theta) \;=\; -\Big(\sum_k q_k \log p_\theta(k) \;+\; \tfrac12\, S_{\mathrm{sph}}(p_\theta, q) \;-\; \mathbb{1}_{\text{score}}\,\mathrm{RPS}(p_\theta, q)\Big) \;+\; \beta\, \mathrm{KL}\big(p_{\theta_0} \,\|\, p_\theta\big)

$S_{\mathrm{sph}}$ is the spherical score, $\mathrm{RPS}$ the ranked probability score (for ordered score questions only) and $\theta_0$ the starting weights, read with the adapter switched off. Because the rule is proper, reporting honest probabilities is the only way to maximise it. Fine-tuned weights are then interpolated with the starting weights (WiSE-FT):

θ  =  θ0+λ (θft−θ0)\theta \;=\; \theta_0 + \lambda\,(\theta_{\mathrm{ft}} - \theta_0)

1. Distillation from a larger decision model. A 27 B decision model served through an API labelled 361,610 requests with full probability distributions: train splits of public decision benchmarks (never their test items), reasoning and knowledge sets (MMLU auxiliary train, MedMCQA, GSM8K, ARC, HellaSwag, WinoGrande, CommonsenseQA, OpenBookQA), tool-use and routing data, and our own multilingual synthetic decisions. THX-02 was trained on 165k of them with a proper scoring reward on the teacher's distribution (85 percent teacher, 15 percent gold label) and a KL anchor to its starting weights, with LoRA (rank 32) on all attention, linear-attention and MLP projections plus the readout head. The fine-tuned weights were then interpolated with the starting weights (WiSE-FT, 0.7), which kept the gains and recovered the few tasks that drifted.

2. Disagreement distillation. The model was run over all 361k teacher-labelled requests and compared with the teacher question by question. Only requests where the two disagreed and the teacher matched the gold label were kept (56.6k), plus 15 percent ordinary requests as anchors (99.5k in total). Requests where the teacher was wrong and the model right were dropped: the teacher is far from perfect on some tasks (23 percent on ChessBench, 51 percent on Habermas consensus). The two distilled models were merged as task vectors (0.4 each).

Distillation

3. Inference-time structure. Two choices that need no training were tuned on the held-out split: option-order averaging (each choice question read with its options in four orders, geometric mean) and joint reads for facet-style requests (several questions that apply the same criteria to different items, such as select-all candidates or aspect/sentiment pairs, are read in one pass).

4. Learning to think. Candidate thoughts for 30k reasoning-heavy training requests (math word problems, science and medical multiple choice, logic, natural-language inference, fact verification) were written by a larger language model, three per request. Each thought was then tested on THX-02 itself: the model read the question with and without the thought, and the thought was kept only if it raised the probability of the correct answer. 10,129 of 29,990 survived. The think adapter (LoRA, rank 32) was trained on these self-verified thoughts plus 15k earlier short thoughts that keep the multilingual style, so it learns to write notes that help THX-02 decide, not notes that merely sound plausible. The gate threshold, tau and alpha were tuned on the held-out split and confirmed on the evaluation sample. The final think adapter was trained after stage 5, on the stage-5 model, with 9,875 further self-verified thoughts from the stage-5 reasoning tasks (code execution, logic puzzles, causal questions, science and math) added to these, so its notes are short and the gate fires rarely on easy questions.

Learning to think

5. Targeted skills. After stage 4 the evaluation showed where the points were missing: code execution, logic puzzles, causal inference, long narrative reasoning, multi-answer questions, harmony, chess, graduate-level science, reasoning-heavy retrieval and several vision skills. Stage 5 built new training data for exactly these skills:

  • Procedural tasks with exact answers. Python functions executed in a sandbox (the answer is the real output), logic puzzles and causal questions solved by a program (causal graphs with every quantity computed exactly from the structural model), long narratives whose facts come from a simulation and are checked against the text, chess positions labelled by a deep engine search, and harmony questions generated from real chord progressions.
  • Knowledge and math. Commercially licensed science, medicine and math question sets with verified answers, converted to multiple choice; items whose answer came from model votes were kept only where a larger decision model agreed. Everything was deduplicated against the benchmark test sets with exact and 13-gram matching.
  • Tools and retrieval. Tool catalogs from open function-calling sets turned into retrieval and selection questions with hard negatives, and retrieval questions where the relevant document shares the reasoning, not the words.
  • Vision. Rendered charts, receipts, invoices and forms in nine languages, 3D scenes for depth, counting and multi-view questions, compositional image-caption matching and exam questions inside images; plus real receipts, photos, depth maps and web screenshots from commercially licensed train splits, checked against every evaluation image by exact and perceptual hashes.
  • Languages. 14k requests translated into Azerbaijani, Russian, Chinese, Kazakh, Uzbek, Kyrgyz, Japanese and Spanish with the answers preserved.

Targeted-skills data

About 700k candidate requests were scored by the stage-4 model itself. A request was kept if the model got it wrong or put less than 0.8 on the correct answer, plus a quarter as many easy requests as anchors, which left 161k. Where a larger decision model agreed with the correct answer, the target is half its distribution and half the gold label; otherwise the gold label alone. Together with 70k requests replayed from stages 1 and 2, the model was trained for one pass (231k requests, 5,256 updates, LoRA rank 32, learning rate $5\cdot10^{-5}$ with cosine decay, $\beta = 0.3$) starting from the stage-4 model, and interpolated with it at $\lambda = 0.7$.

Targeted-skills training

The largest gains of stage 5 on the Decision Index sample (direct reads): harmony +37.6 points, long narrative reasoning +12.8, BBH +8.5, aspect-sentiment extraction +7.8, CLadder +5.1, select-all questions +4.3, CRUXEval +3.4. A few benchmarks moved down by three to five points (Habermas consensus, BRIGHT, FinEntity, GSM8K without thinking), within or near the sampling error of 117 requests.

Production API

pip install -r requirements-fast.txt
THX_API_KEY=change-me thx02-serve --model . --gpus 0,1,2,3 --port 8200 --thinker-url http://127.0.0.1:8000

One worker per GPU listens on the same port (SO_REUSEPORT) and batches all incoming requests into packed forward passes (up to 64 requests per pass, 4 ms collection window). The compiled CUDA-graph path is used by default; --no-fast switches to the reference path. --default-tta 4 raises accuracy at about half the throughput.

curl -s localhost:8200/v1/decide -H "Authorization: Bearer change-me" -H "Content-Type: application/json" -d '{
  "state": "My package says delivered but I never got it, order 48213.",
  "questions": {"team": {"type": "choice", "instructions": "Which team?",
                "criteria": {"billing": "Charges", "support": "Technical", "shipping": "Deliveries"}}},
  "think": "auto"}'
Endpoint Body Result
POST /v1/decide one request {"model", "answers", "latency_ms"}
POST /v1/decide/batch {"items": [request, ...]} (up to 1,024) {"results": [...]}
GET /health status, uptime, batches served
GET /v1/models model id and whether thinking is available

Phones and Termux

THX-02 runs from Android (Termux) or any terminal:

pkg install -y python tmux && pip install thx02
tmux new -s thx                            # keeps the session alive across app switches (detach: Ctrl-b d)
thx02 --yesno "Is this message a scam?"    # interactive: paste messages, get decisions
  • API mode: pip install thx02 (no dependencies) talks to api.hal-x.ai or your own thx02 serve. mobile/thx.py is the same client as a single file, for phones without pip.
  • Local mode: runs the model on the phone CPU inside an Ubuntu userland (bash mobile/install_termux.sh --local). It needs an aarch64 phone with 12 GB of RAM or more; on an 8-thread server CPU it takes 0.6 s per short request and 7.6 GB of memory in BF16.

See mobile/README.md.

Repository layout

Path Content
config.json THX-02 configuration (THXDecisionModel), thinking presets, backbone configuration
model.safetensors, readout.safetensors decision weights and readout head
thinker/ think adapter, multi-token-prediction head and configuration for the vLLM thinker
thx02/ Python package: model, request protocol, compiled fast path, runtime, HTTP server
mobile/ Termux installer, single-file client and local runner (or simply pip install thx02)
assets/ charts in this card

Limitations

  • Scores are on a 6,018-request sample of the public Decision Index suite; the full public suite and the private leaderboard tests have not been run yet. The vision index averages ten of the eleven public sets (Winoground is gated).
  • Thinking needs a GPU server for the thinker. On CPU and on phones THX-02 answers directly.
  • The probabilities are calibrated on the training distribution; on a very different domain, check a few hundred labelled examples before acting on the confidence alone.
  • Notes written while thinking can contain mistakes. They are inputs to the decision, not explanations to show to end users without review.

License

Apache-2.0. See LICENSE and NOTICE.

Downloads last month
-
Safetensors
Model size
5B params
Tensor type
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support