malkuth-2b / README.md
dhtocks's picture
add pipeline_tag
37ae167 verified
|
Raw History Blame Contribute Delete
4.9 kB
---
base_model: empero-ai/Qwen3.8-2B-Distill
base_model_relation: adapter
library_name: peft
pipeline_tag: zero-shot-classification
license: cc-by-nc-4.0
language: [en, ko, ja, zh, de, fr, es, hi, ar, th]
tags: [decision-model, classification, calibration, kev, system-one, lora, pointer-head]
---
# Malkuth-2B
A small multilingual decision model for classification, with a focus on Korean.
Given a text, a question, and a set of criteria, Malkuth returns probabilities over the possible choices instead of
generating text.
Malkuth-2B is a LoRA adapter trained on [Kev](https://github.com/jaredpalmer/kev) and built on a frozen
`empero-ai/Qwen3.8-2B-Distill`. It has 17.9M trainable parameters and a 65 MB adapter.
It supports three question types:
- `choice`: select one of up to 255 options
- `noul`: yes or no
- `score`: select an ordered level
Multiple questions can be evaluated against the same input. Questions are evaluated independently, so they cannot see
each other's answers. Probabilities are temperature-calibrated on a held-out validation split.
Malkuth is served through Kev and works with the TypeSafe System One API. The companion model is
[dhtocks/malkuth-4b](https://huggingface.co/dhtocks/malkuth-4b) (4B). Code, training mixes and evaluation live in
[newfull5/malkuth](https://github.com/newfull5/malkuth).
## Usage
```bash
git clone https://github.com/jaredpalmer/kev.git kev && cd kev && uv sync --extra serve
uv run --extra serve python -m kev.serve --run dhtocks/malkuth-2b --port 8009
```
The official `typesafe-sdk` works against the local server with a `base_url` change.
```python
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient
client = TypeSafeClient(api_key="local", base_url="http://127.0.0.1:8009", model="kev-latest")
r = client.system_one(
state="Shoes arrived two weeks late and in the wrong size. I also see two charges on my card.",
questions={
"team": Choice(instructions="Which team should handle this?",
criteria={"billing": "Charges and invoices", "shipping": "Delivery problems",
"returns": "Exchanges and wrong items"}),
"escalate": Noul(instructions="Does this need urgent human attention?"),
"urgency": Score(instructions="How urgent is this ticket?", criteria=["low", "normal", "high"]),
},
)
print(r.choices["team"].choice, r.choices["team"].probabilities)
```
## Evaluation
29 suites and about 129,000 questions. Every model answered the same items. Jev was measured through its API.
- **held-out**: the nine datasets we did not train on
- **all**: all 29 suites, ten of which we trained on
- **Brier**: quality of the probabilities, lower is better
| Model | Accuracy (held-out) | Accuracy (all) | Brier (held-out) |
|---|---:|---:|---:|
| Jev API | **0.754** ±0.0042 | 0.790 | **0.355** |
| Malkuth-4B | 0.724 ±0.0044 | **0.794** | 0.385 |
| Malkuth-2B | 0.703 ±0.0044 | 0.765 | 0.412 |
| Kev-9B | 0.700 ±0.0046 | 0.737 | 0.407 |
| Kev-4B | 0.686 ±0.0046 | 0.720 | 0.407 |
| Kev-0.8B | 0.589 ±0.0050 | 0.584 | 0.539 |
| Laya (best of four) | 0.544 ±0.0044 | 0.507 | 0.654 |
On the five Korean suites:
| Suite | Jev | Malkuth-4B | Malkuth-2B | Kev-9B | Kev-4B |
|---|---:|---:|---:|---:|---:|
| `klue_nli` | **0.936** | 0.912 | 0.832 | 0.882 | 0.866 |
| `klue_ynat` | 0.724 | **0.852** | 0.824 | 0.758 | 0.728 |
| `nsmc` | 0.850 | **0.878** | 0.862 | 0.856 | 0.806 |
| `kobest` | 0.903 | **0.904** | 0.819 | 0.850 | 0.809 |
| `kold` | 0.806 | **0.820** | 0.768 | 0.602 | 0.654 |
| mean | 0.844 | **0.873** | 0.821 | 0.790 | 0.773 |
Four of these five contributed their train splits to our mix, so this table is in-distribution for Malkuth.
Latency on one A100 80GB in bf16, median of 20 requests. The second number is a repeated input served from the prefix
cache. Six questions take 23 ms on a new input and 16 ms on a repeated one.
Per-dataset scores and calibration analysis are in
[docs/evaluation.md](https://github.com/newfull5/malkuth/blob/main/docs/evaluation.md).
## Training data
89,791 labelled requests from 20 public sources. 62,400 `choice`, 24,790 `noul` and 7,401 `score` questions, across ten
core languages with five Korean-only sources.
Built by [`tools/build_train_mix.py`](https://github.com/newfull5/malkuth/blob/main/tools/build_train_mix.py).
Per-source licences are in
[docs/benchmarks.md](https://github.com/newfull5/malkuth/blob/main/docs/benchmarks.md).
## License
- Weights: research use only. Two of the twenty training sources are non-commercial: XNLI (CC-BY-NC-4.0) and
RACE ("non-commercial research purpose only"). `sms_spam` and `tweet_sentiment_multilingual` state no licence.
- Code: Apache-2.0, same as Kev and the Qwen bases.
## Citation
```bibtex
@misc{malkuth2026,
title={Malkuth: multilingual System One decision models},
author={Saechan Oh},
year={2026}
}
```