Pusula

An open-source AI decision engine for Turkish. Pusula is Decision 3.0 (vllm-sr/d3) fine-tuned on Turkish decision data. For each message, typed questions (for example, how a request should be routed, how urgent it is, whether a human should take over, or whether it contains a prompt injection) are answered with a probability for every option in a single forward pass, without text generation.

Doğru karar, doğru yön.

Version v2.0 (31 October 2026); earlier weights remain available as revisions v1.0 and v1.0-onizleme
Base model vllm-sr/d3 (26B, Apache-2.0)
This repository LoRA adapter (rank 32) + code readout, ~0.9 GB
Language Turkish
Training data Specially curated Turkish data: synthetic messages generated for this project across NACE Rev. 2.1 sectors and ESCO occupations; the starting adapter (v1.0) was also trained on customer messages licensed from a commercial partner
Interface Same request and answer format as d3's /v1/systemone

Results

Accuracy (%). Evaluation labels were assigned blind and independently by two annotators (Claude Opus 5.5 and Claude Sonnet 5.5) with adjudication, under the published labeling policy; the real customer messages were labeled blind by Claude under the same policy. Evaluation labels are used exclusively for evaluation. In v2.0, the evaluation sets were extended to the 20 templates; the 1.0 models and Decision 3.0 were therefore evaluated again on the same sets, and their scores differ from those published with v1.0. The MASSIVE and OffensEval scores of Decision 3.0 and Pusula 1.0 are those of the v1.0 release.

Evaluation Questions Decision 3.0 Pusula 1.0 Pusula 2.0
Real customer messages (500 held-out, licensed) 7,500 84.0 88.5 90.6
Long customer complaints (500 held-out, licensed) 4,500 81.5 88.1 88.3
Turkish Decision Benchmark (2,194 messages) 19,861 88.5 92.6 92.0
Gold test set (757 held-out messages) 11,355 86.3 90.5 92.1
Custom questions in unseen sectors 400 92.8 91.2 93.5
Missing information (eksik_bilgi) 99 98.0 96.0 98.0
Sales opportunity (satis_firsati) 100 97.0 97.0 97.0
Life and safety (can_guvenligi) 120 100.0 100.0 100.0
Insults and hate speech (hakaret) 114 93.0 93.0 95.6
Fraud (dolandiricilik) 97 99.0 100.0 100.0
Source grounding of agent answers (kaynaga_dayanma) 100 93.0 93.0 98.0
AI agent questions (templates 17-20) 300 96.8 97.5 97.8
Personal data in e-mails 150 95.3 98.7 100.0
Hidden instructions in documents 400 100.0 100.0 100.0
Long documents (about 12,000 characters) 120 100.0 100.0 100.0
MASSIVE tr-TR, 60-way intent, zero-shot (human-written) 2,974 85.3 85.2 85.2
OffensEval 2020 Turkish, offensive language (real tweets) 3,528 88.4 88.3 88.3

The real customer messages are two held-out sets of 500 anonymized messages licensed from a commercial partner (customer messages, and long customer complaints); they are not published. Pusula 2.0 scores below Pusula 1.0 on the benchmark, 92.0 (Pusula 1.0: 92.6), mainly in urgency, human handoff and domain. The full comparison, including the results per question, is given in the Pusula repository.

Usage

Pusula is loaded with the pusula package. Generic PEFT loading of the adapter is not sufficient, since the code readout and the non-causal attention hook of the d3 prompt contract are applied by this package.

pip install "pusula[d3] @ git+https://github.com/erenextlabs/pusula"
hf download vllm-sr/d3 --local-dir d3 --exclude "assets/*"
hf download erenextlabs/pusula --local-dir pusula
from pusula.inference import D3Engine

engine = D3Engine.load("d3", adapter="pusula")
answers = engine.decide(
    "Kartımdan bilgim dışında üç çekim yapıldı, hemen engelleyin!",
    {
        "temsilci": {"type": "noul", "instructions": "Bir insan temsilciye aktarılmalı mı?"},
        "aciliyet": {"type": "score", "instructions": "Ne kadar acil?", "criteria": ["Rutin", "Yakın", "Yüksek", "Kritik"]},
    },
)

Custom questions (questions that are not among the built-in templates) and the missing-information template (eksik_bilgi) are answered by the base Decision 3.0 model with the adapter disabled; the other built-in templates are answered with the adapter. On the missing-information set, the base model scores 98.0 (Pusula 1.0: 96.0), while on realistic messages the adapter answers this question more accurately (gold test set 91.3 vs 70.9). This default is turned off with PUSULA_OWN_BASE=0 or D3Engine.load(..., own_base=False).

An HTTP server (pusula-serve), a built-in Turkish taxonomy (20 domains, 103 subdomains, 333 intents), 20 ready-made decision templates and the benchmark are provided in the Pusula repository. A smaller model with the same interface is available as Pusula Nano (149M, CPU-capable), which can be tried on Google Colab without installation: Open In Colab

Hardware requirements: approximately 64 GB of GPU memory in BF16, or approximately 24 GB when loaded in 4-bit.

Training

  • Data: 19,399 new synthetic Turkish messages written by Gemma-4-31B-it across NACE Rev. 2.1 sectors and ESCO occupations, and 16,236 earlier synthetic messages of the project; all were labeled by Qwen3.8-27B under the written labeling policy (about 642,000 labeled questions on the 20 templates and on custom questions). Messages of the evaluation sets are excluded from training.
  • Method: training started from the v1.0 adapter, which had also been trained on customer messages licensed from a commercial partner. The LoRA adapter (rank 32) and the code readout were trained on top of vllm-sr/d3 in BF16, in two rounds of 60,000 sampled questions each, with rare label values sampled with priority (at most threefold), and a third round of 12,000 questions on the domain, subdomain, urgency, human handoff and emotion templates.

Limitations

  • Pusula 2.0 scores below Pusula 1.0 on the benchmark and, per question on the gold test set, on domain, human handoff and missing information. Improvements in these areas are planned for v2.1.
  • Custom questions are answered by the base Decision 3.0 model; on these questions, Pusula 2.0 therefore performs at the level of Decision 3.0.
  • Most of the training data is synthetic; evaluation on application-specific data is recommended before deployment.

Contributors and citation

Pusula is developed by Erenext's AI Lab. The contributors are listed below:

Name Role GitHub Hugging Face
Hasan Şahin Project lead hsnsahinhsn hsnsahinhsn
Ahmet Sayman Contributor asayman asaymantr

Source code: github.com/erenextlabs/pusula.

@software{pusula2026,
  title   = {Pusula: The First Full-Featured Turkish Decision Model},
  author  = {Şahin, Hasan and Sayman, Ahmet},
  year    = {2026},
  version = {2.0},
  url     = {https://github.com/erenextlabs/pusula},
  license = {Apache-2.0}
}

License and attribution

Released under Apache-2.0. Pusula is built on vllm-sr/d3 (vLLM Semantic Router Team, Apache-2.0), which is itself built on Qwen3.8-27B (Apache-2.0). In version 2.0, Gemma-4-31B-it (Google, Apache-2.0) was used to write synthetic training messages and Qwen3.8-27B to label them; boun-tabilab/TabiBERT (Apache-2.0) was used for data curation. The sectors and occupations of the synthetic messages were sampled from NACE Rev. 2.1 (Source: Eurostat) and the ESCO classification of the European Commission (© European Union). External evaluations: Amazon MASSIVE (CC BY 4.0) and OffensEval 2020 Turkish (Çöltekin, 2020; CC BY). See NOTICE.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for erenextlabs/pusula

Base model

Qwen/Qwen3.8-27B
Finetuned
vllm-sr/d3
Adapter
(1)
this model