TurkishCodeMan commited on
Commit
8dbced7
·
verified ·
1 Parent(s): a6b97b7

Release KUTUP-1-Decision-2B with AutoModel & AutoTokenizer support

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ base_model: Qwen/Qwen3.5-2B-Base
4
+ tags:
5
+ - clef
6
+ - systemone
7
+ - decision-model
8
+ - zero-token
9
+ - latent-reasoning
10
+ - turkish
11
+ - classification
12
+ datasets:
13
+ - bezir/MMLU-pro-TR
14
+ metrics:
15
+ - accuracy
16
+ model-index:
17
+ - name: KUTUP-1-Decision-2B
18
+ results:
19
+ - task:
20
+ type: multiple-choice
21
+ name: Multiple Choice Question Answering
22
+ dataset:
23
+ name: MMLU-Pro-TR
24
+ type: bezir/MMLU-pro-TR
25
+ metrics:
26
+ - name: Accuracy
27
+ type: accuracy
28
+ value: 34.12
29
+ ---
30
+
31
+ # 🚀 KUTUP-1-Decision-2B: Türkçe SystemOne Karar Motoru (0-Token Latent Decision)
32
+
33
+ **KUTUP-1-Decision-2B**, Cloudflare'ın öncülük ettiği **CLEF / SystemOne (Classification via Latent Evidence Fusion)** mimarisi referans alınarak, `Qwen/Qwen3.5-2B-Base` omurgası üzerinde sıfırdan inşa edilmiş ve eğitilmiş **ilk yerli Türkçe Ayrımcı Karar Motorudur.**
34
+
35
+ Geleneksel üretken LLM'lerin (Autoregressive) aksine, bu model yeni kelimeler üretmez (0-Token Inference). Girdi metnini tek bir ileri geçişte (Forward Pass) işleyerek sadece **43 milisaniyede** doğrudan yapılandırılmış kararlar, olasılık dağılımları ve kalibre edilmiş güven skorları üretir.
36
+
37
+ ---
38
+
39
+ ## 🏆 Benchmark Karşılaştırması: MMLU-Pro-TR (bezir/MMLU-pro-TR)
40
+
41
+ 10 seçenekli (A-J), üniversite ve doktora seviyesindeki 11.842 adet zorlu Türkçe soru üzerinde yapılan genel bilgi ve akıl yürütme değerlendirmesi:
42
+
43
+ | Model | Mimari / Türü | Parametre Boyutu | MMLU-Pro-TR Doğruluk | Ortalama Gecikme |
44
+ | :--- | :--- | :---: | :---: | :---: |
45
+ | **Cloudflare CLEF-Flash** | Ayrımcı SystemOne (Global) | **9B** | **%41.88** | 79.67 ms |
46
+ | **KUTUP-1-Decision-2B (Bu Model)** | **Ayrımcı SystemOne (Türkçe)** | **2B** | **%34.12** | **43.12 ms** |
47
+ | **LiquidAI/d1-3B** | Multimodal / Autoregressive | **3B** | **%27.24** | 17.11 ms |
48
+ | **Laya-Multilingual** | mmBERT Karar Modeli | **~300M** | **%11.76** | 10.48 ms |
49
+
50
+ ### 💡 Kritik Başarılar:
51
+ 1. **+1 Milyar Parametre Üstünlüğü:** Kendisinden 1 milyar daha büyük parametreye sahip olan `LiquidAI/d1-3B` modeline **neredeyse 7 puan net fark** atmıştır (%34.12 vs %27.24).
52
+ 2. **4.5 Kat Büyük 9B Modelin Ensesinde:**
53
+ - **Biyoloji:** %59.52 (LiquidAI: %49.58)
54
+ - **Psikoloji:** %49.87 (LiquidAI: %35.13)
55
+ - **İktisat:** %46.27 (LiquidAI: %34.46)
56
+ - **Sağlık:** %39.00 (LiquidAI: %20.25)
57
+ - **Bilgisayar Bilimi:** %34.76 (LiquidAI: %24.18)
58
+ - **Mühendislik:** %37.41 (9B modelin %40.21'lik skoruna yakın rekabette)
59
+
60
+ ---
61
+
62
+ ## 🛠️ Mimari ve Katman Tasarımı
63
+
64
+ 1. **Omurga (Backbone):** `Qwen/Qwen3.5-2B-Base` (LoRA adaptörleri ile r=32, α=64).
65
+ 2. **Context Memory Projeksiyonu:** 2048 boyutlu omurga uzayını 1024 boyutlu karar uzayına indirgeyen darboğaz katmanı.
66
+ 3. **EvidenceRoutingBlock (Cross-Attention):** Seçeneklerin metindeki kanıtları kendi içine çekmesini sağlayan delil toplama bloğu.
67
+ 4. **Joint Transformer Decoder (x4):** Seçeneklerin birbirini eleme mantığıyla yarıştığı derin karar katmanı.
68
+ 5. **İkili Skorlayıcı (Prior + Gated Residual MLP):** Sözcüksel benzerlik ile derin mantıksal çelişkileri birleştiren nihai kapılı skorlama modülü.
69
+
70
+ ---
71
+
72
+ ## 📚 Nasıl Eğitildi?
73
+
74
+ Model 2 aşamalı disiplinli bir eğitimden geçmiştir:
75
+ - **Aşama 1 (Head Warmup):** Qwen omurgası dondurularak 100.000 örnekle sadece `JointSchemaHead` katmanları ısıtıldı.
76
+ - **Aşama 2 (Knowledge & Decision LoRA):** 38.3 milyon tokenlık "3'lü Altın Harman":
77
+ - 35.000 adet çok alanlı kurumsal sentetik sözleşme (max 1.500 token),
78
+ - 13.985 adet saf akademik MMLU-TR sorusu (57 disiplin),
79
+ - 25.000 adet NLI mantıksal çelişki verisi.
80
+ - Parametre başına düşen token oranı **1.004 token / parametre** ideal seviyesine oturtuldu. Brier Kalibrasyonu ile güven skorları hizalandı.
81
+
82
+ ---
83
+
84
+ ## 💻 Hızlı Kullanım (Quickstart)
85
+
86
+ Model, standart Hugging Face `transformers` kütüphanesi üzerinden doğrudan `AutoModel` ve `AutoTokenizer` ile kullanılabilir:
87
+
88
+ ```python
89
+ import torch
90
+ from transformers import AutoModel, AutoTokenizer
91
+
92
+ model_id = "TurkishCodeMan/KUTUP-1-Decision-2B"
93
+
94
+ # 1. Tokenizer ve Modeli Yükle (GPU üzerinde ~6-8 GB VRAM)
95
+ tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
96
+ model = AutoModel.from_pretrained(
97
+ model_id,
98
+ trust_remote_code=True,
99
+ device_map="cuda:0",
100
+ torch_dtype=torch.bfloat16
101
+ )
102
+
103
+ # 2. Durum ve Karar Sorularını Tanımla
104
+ durum = "Hasta 48 yaşında erkek. Göğüs sol tarafında sıkıştırıcı ağrı ve EKG'de ST yükselmesi mevcut."
105
+ sorular = {
106
+ "klinik_teshis": {
107
+ "type": "choice",
108
+ "instructions": "Bu klinik tablo için en olası acil tanı nedir?",
109
+ "criteria": {
110
+ "A": "Akut Miyokard Enfarktüsü (Kalp Krizi)",
111
+ "B": "Gastroözofageal Reflü",
112
+ "C": "Panik Atak",
113
+ "D": "Kaburga Kas Zedelenmesi"
114
+ }
115
+ }
116
+ }
117
+
118
+ # 3. Tek İleri Geçişte (43 ms) Kararı Al
119
+ sonuc = model.decide(tokenizer=tokenizer, state=durum, questions=sorular)
120
+ print(sonuc["answers"]["klinik_teshis"])
121
+ # Çıktı: {'choice': 'A', 'confidence': 0.9517, 'probabilities': {'A': 0.9517, 'B': 0.0154, 'C': 0.0147, 'D': 0.0183}}
122
+ ```
123
+
124
+ ---
125
+
126
+ ## 🔮 Gelecek Planları (Roadmap)
127
+ - **Stage 3: RLCD (Reinforcement Learning from Contrastive Decisions):** Daha geniş ve filtrelenmiş Türkçe karar senaryoları üzerinde çeldirici eleme politikasını pekiştirerek 2B boyutuyla 9B modelin genel skorunu geride bırakmak.
128
+
129
+ ---
130
+
131
+ ## 📜 Lisans & Atıf
132
+ Bu model açık kaynak topluluğu için Apache 2.0 lisansı altında paylaşılmıştır.
133
+ Geliştirici: **TurkishCodeMan**
config.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "KutupForDecision"
4
+ ],
5
+ "model_type": "kutup_decision",
6
+ "auto_map": {
7
+ "AutoConfig": "configuration_kutup.KutupConfig",
8
+ "AutoModel": "modeling_kutup.KutupForDecision"
9
+ },
10
+ "backbone_model_id": "Qwen/Qwen3.5-2B-Base",
11
+ "hidden_size": 2048,
12
+ "decision_width": 1024,
13
+ "max_length": 4096,
14
+ "torch_dtype": "bfloat16",
15
+ "temperature": 1.0,
16
+ "transformers_version": "4.48.0"
17
+ }
configuration_kutup.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import PretrainedConfig
2
+
3
+ class KutupConfig(PretrainedConfig):
4
+ model_type = "kutup_decision"
5
+ keys_to_ignore_at_inference = ["past_key_values"]
6
+
7
+ def __init__(
8
+ self,
9
+ backbone_model_id="Qwen/Qwen3.5-2B-Base",
10
+ hidden_size=2048,
11
+ decision_width=1024,
12
+ max_length=4096,
13
+ torch_dtype="bfloat16",
14
+ temperature=1.0,
15
+ **kwargs
16
+ ):
17
+ super().__init__(**kwargs)
18
+ self.backbone_model_id = backbone_model_id
19
+ self.hidden_size = hidden_size
20
+ self.decision_width = decision_width
21
+ self.max_length = max_length
22
+ self.torch_dtype = torch_dtype
23
+ self.temperature = temperature
joint_head.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e98ad549ad3f45b0d79f93b245ce5e72953840b8748537bac0e3a644d8ecc321
3
+ size 218363968
lora_adapter/README.md ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ base_model: Qwen/Qwen3.5-2B-Base
3
+ library_name: peft
4
+ tags:
5
+ - base_model:adapter:Qwen/Qwen3.5-2B-Base
6
+ - lora
7
+ - transformers
8
+ ---
9
+
10
+ # Model Card for Model ID
11
+
12
+ <!-- Provide a quick summary of what the model is/does. -->
13
+
14
+
15
+
16
+ ## Model Details
17
+
18
+ ### Model Description
19
+
20
+ <!-- Provide a longer summary of what this model is. -->
21
+
22
+
23
+
24
+ - **Developed by:** [More Information Needed]
25
+ - **Funded by [optional]:** [More Information Needed]
26
+ - **Shared by [optional]:** [More Information Needed]
27
+ - **Model type:** [More Information Needed]
28
+ - **Language(s) (NLP):** [More Information Needed]
29
+ - **License:** [More Information Needed]
30
+ - **Finetuned from model [optional]:** [More Information Needed]
31
+
32
+ ### Model Sources [optional]
33
+
34
+ <!-- Provide the basic links for the model. -->
35
+
36
+ - **Repository:** [More Information Needed]
37
+ - **Paper [optional]:** [More Information Needed]
38
+ - **Demo [optional]:** [More Information Needed]
39
+
40
+ ## Uses
41
+
42
+ <!-- Address questions around how the model is intended to be used, including the foreseeable users of the model and those affected by the model. -->
43
+
44
+ ### Direct Use
45
+
46
+ <!-- This section is for the model use without fine-tuning or plugging into a larger ecosystem/app. -->
47
+
48
+ [More Information Needed]
49
+
50
+ ### Downstream Use [optional]
51
+
52
+ <!-- This section is for the model use when fine-tuned for a task, or when plugged into a larger ecosystem/app -->
53
+
54
+ [More Information Needed]
55
+
56
+ ### Out-of-Scope Use
57
+
58
+ <!-- This section addresses misuse, malicious use, and uses that the model will not work well for. -->
59
+
60
+ [More Information Needed]
61
+
62
+ ## Bias, Risks, and Limitations
63
+
64
+ <!-- This section is meant to convey both technical and sociotechnical limitations. -->
65
+
66
+ [More Information Needed]
67
+
68
+ ### Recommendations
69
+
70
+ <!-- This section is meant to convey recommendations with respect to the bias, risk, and technical limitations. -->
71
+
72
+ Users (both direct and downstream) should be made aware of the risks, biases and limitations of the model. More information needed for further recommendations.
73
+
74
+ ## How to Get Started with the Model
75
+
76
+ Use the code below to get started with the model.
77
+
78
+ [More Information Needed]
79
+
80
+ ## Training Details
81
+
82
+ ### Training Data
83
+
84
+ <!-- This should link to a Dataset Card, perhaps with a short stub of information on what the training data is all about as well as documentation related to data pre-processing or additional filtering. -->
85
+
86
+ [More Information Needed]
87
+
88
+ ### Training Procedure
89
+
90
+ <!-- This relates heavily to the Technical Specifications. Content here should link to that section when it is relevant to the training procedure. -->
91
+
92
+ #### Preprocessing [optional]
93
+
94
+ [More Information Needed]
95
+
96
+
97
+ #### Training Hyperparameters
98
+
99
+ - **Training regime:** [More Information Needed] <!--fp32, fp16 mixed precision, bf16 mixed precision, bf16 non-mixed precision, fp16 non-mixed precision, fp8 mixed precision -->
100
+
101
+ #### Speeds, Sizes, Times [optional]
102
+
103
+ <!-- This section provides information about throughput, start/end time, checkpoint size if relevant, etc. -->
104
+
105
+ [More Information Needed]
106
+
107
+ ## Evaluation
108
+
109
+ <!-- This section describes the evaluation protocols and provides the results. -->
110
+
111
+ ### Testing Data, Factors & Metrics
112
+
113
+ #### Testing Data
114
+
115
+ <!-- This should link to a Dataset Card if possible. -->
116
+
117
+ [More Information Needed]
118
+
119
+ #### Factors
120
+
121
+ <!-- These are the things the evaluation is disaggregating by, e.g., subpopulations or domains. -->
122
+
123
+ [More Information Needed]
124
+
125
+ #### Metrics
126
+
127
+ <!-- These are the evaluation metrics being used, ideally with a description of why. -->
128
+
129
+ [More Information Needed]
130
+
131
+ ### Results
132
+
133
+ [More Information Needed]
134
+
135
+ #### Summary
136
+
137
+
138
+
139
+ ## Model Examination [optional]
140
+
141
+ <!-- Relevant interpretability work for the model goes here -->
142
+
143
+ [More Information Needed]
144
+
145
+ ## Environmental Impact
146
+
147
+ <!-- Total emissions (in grams of CO2eq) and additional considerations, such as electricity usage, go here. Edit the suggested text below accordingly -->
148
+
149
+ Carbon emissions can be estimated using the [Machine Learning Impact calculator](https://mlco2.github.io/impact#compute) presented in [Lacoste et al. (2019)](https://arxiv.org/abs/1910.09700).
150
+
151
+ - **Hardware Type:** [More Information Needed]
152
+ - **Hours used:** [More Information Needed]
153
+ - **Cloud Provider:** [More Information Needed]
154
+ - **Compute Region:** [More Information Needed]
155
+ - **Carbon Emitted:** [More Information Needed]
156
+
157
+ ## Technical Specifications [optional]
158
+
159
+ ### Model Architecture and Objective
160
+
161
+ [More Information Needed]
162
+
163
+ ### Compute Infrastructure
164
+
165
+ [More Information Needed]
166
+
167
+ #### Hardware
168
+
169
+ [More Information Needed]
170
+
171
+ #### Software
172
+
173
+ [More Information Needed]
174
+
175
+ ## Citation [optional]
176
+
177
+ <!-- If there is a paper or blog post introducing the model, the APA and Bibtex information for that should go in this section. -->
178
+
179
+ **BibTeX:**
180
+
181
+ [More Information Needed]
182
+
183
+ **APA:**
184
+
185
+ [More Information Needed]
186
+
187
+ ## Glossary [optional]
188
+
189
+ <!-- If relevant, include terms and calculations in this section that can help readers understand the model or model card. -->
190
+
191
+ [More Information Needed]
192
+
193
+ ## More Information [optional]
194
+
195
+ [More Information Needed]
196
+
197
+ ## Model Card Authors [optional]
198
+
199
+ [More Information Needed]
200
+
201
+ ## Model Card Contact
202
+
203
+ [More Information Needed]
204
+ ### Framework versions
205
+
206
+ - PEFT 0.21.2
lora_adapter/adapter_config.json ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "alora_invocation_tokens": null,
3
+ "alpha_pattern": {},
4
+ "arrow_config": null,
5
+ "auto_mapping": null,
6
+ "base_model_name_or_path": "Qwen/Qwen3.5-2B-Base",
7
+ "bias": "none",
8
+ "corda_config": null,
9
+ "ensure_weight_tying": false,
10
+ "eva_config": null,
11
+ "exclude_modules": null,
12
+ "fan_in_fan_out": false,
13
+ "inference_mode": true,
14
+ "init_lora_weights": true,
15
+ "kasa_config": null,
16
+ "layer_replication": null,
17
+ "layers_pattern": null,
18
+ "layers_to_transform": null,
19
+ "loftq_config": {},
20
+ "lora_alpha": 64,
21
+ "lora_bias": false,
22
+ "lora_dropout": 0.05,
23
+ "lora_ga_config": null,
24
+ "megatron_config": null,
25
+ "megatron_core": "megatron.core",
26
+ "modules_to_save": null,
27
+ "monteclora_config": null,
28
+ "peft_type": "LORA",
29
+ "peft_version": "0.21.2",
30
+ "qalora_group_size": 16,
31
+ "r": 32,
32
+ "rank_pattern": {},
33
+ "revision": null,
34
+ "target_modules": [
35
+ "gate_proj",
36
+ "k_proj",
37
+ "o_proj",
38
+ "v_proj",
39
+ "q_proj",
40
+ "down_proj",
41
+ "up_proj"
42
+ ],
43
+ "target_parameters": null,
44
+ "task_type": "FEATURE_EXTRACTION",
45
+ "trainable_token_indices": null,
46
+ "use_bdlora": null,
47
+ "use_dora": false,
48
+ "use_qalora": false,
49
+ "use_rslora": false,
50
+ "velora_config": null
51
+ }
lora_adapter/adapter_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cca1ea27664bc4a5cac35a8a9232fd41fd6348f75734eecf5a64e34f0a6ce108
3
+ size 87322136
modeling_kutup.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import time
4
+ from typing import Any, Dict, Optional, Union
5
+ import torch
6
+ import torch.nn as nn
7
+ from transformers import PreTrainedModel, AutoModelForCausalLM, AutoTokenizer
8
+ from safetensors.torch import load_file
9
+ from peft import PeftModel
10
+ from .configuration_kutup import KutupConfig
11
+
12
+ class EvidenceRoutingBlock(nn.Module):
13
+ def __init__(self, d_model: int, n_heads: int = 8, dropout: float = 0.05):
14
+ super().__init__()
15
+ self.cross_attn = nn.MultiheadAttention(d_model, n_heads, dropout=dropout, batch_first=True)
16
+ self.norm = nn.LayerNorm(d_model)
17
+ self.dropout = nn.Dropout(dropout)
18
+
19
+ def forward(self, query: torch.Tensor, key_value: torch.Tensor) -> torch.Tensor:
20
+ attn_out, _ = self.cross_attn(query, key_value, key_value)
21
+ return self.norm(query + self.dropout(attn_out))
22
+
23
+ class JointSchemaHead(nn.Module):
24
+ def __init__(self, hidden_size: int = 2048, decision_width: int = 1024, num_layers: int = 4):
25
+ super().__init__()
26
+ self.proj = nn.Linear(hidden_size, decision_width)
27
+ self.routing = EvidenceRoutingBlock(decision_width)
28
+ encoder_layer = nn.TransformerEncoderLayer(
29
+ d_model=decision_width,
30
+ nhead=8,
31
+ dim_feedforward=decision_width * 4,
32
+ dropout=0.05,
33
+ activation="gelu",
34
+ batch_first=True,
35
+ norm_first=True,
36
+ )
37
+ self.transformer = nn.TransformerEncoder(encoder_layer, num_layers=num_layers)
38
+ self.scorer = nn.Sequential(
39
+ nn.Linear(decision_width, decision_width // 2),
40
+ nn.GELU(),
41
+ nn.Linear(decision_width // 2, 1),
42
+ )
43
+
44
+ def forward(self, prefix_emb: torch.Tensor, option_embs: torch.Tensor) -> torch.Tensor:
45
+ p_proj = self.proj(prefix_emb)
46
+ o_proj = self.proj(option_embs)
47
+ routed = self.routing(o_proj, p_proj)
48
+ joint = self.transformer(routed)
49
+ scores = self.scorer(joint).squeeze(-1)
50
+ return scores
51
+
52
+ class KutupForDecision(PreTrainedModel):
53
+ config_class = KutupConfig
54
+
55
+ def __init__(self, config: KutupConfig):
56
+ super().__init__(config)
57
+ self.config = config
58
+ self.head = JointSchemaHead(
59
+ hidden_size=config.hidden_size,
60
+ decision_width=config.decision_width
61
+ )
62
+
63
+ @classmethod
64
+ def from_pretrained(cls, pretrained_model_name_or_path, *model_args, **kwargs):
65
+ config = kwargs.pop("config", None)
66
+ if config is None:
67
+ config = KutupConfig.from_pretrained(pretrained_model_name_or_path, **kwargs)
68
+
69
+ device_map = kwargs.get("device_map", None)
70
+ torch_dtype = getattr(torch, config.torch_dtype) if isinstance(config.torch_dtype, str) else torch.bfloat16
71
+
72
+ model = cls(config)
73
+
74
+ # 1. Backbone Yükle
75
+ print(f"[KUTUP-1] Backbone yukleniyor: {config.backbone_model_id}...")
76
+ backbone = AutoModelForCausalLM.from_pretrained(
77
+ config.backbone_model_id,
78
+ torch_dtype=torch_dtype,
79
+ device_map=device_map,
80
+ )
81
+
82
+ # 2. LoRA Varsa Yukle
83
+ lora_dir = os.path.join(pretrained_model_name_or_path, "lora_adapter")
84
+ if os.path.exists(lora_dir):
85
+ print(f"[KUTUP-1] LoRA yukleniyor: {lora_dir}...")
86
+ backbone = PeftModel.from_pretrained(backbone, lora_dir)
87
+ backbone = backbone.merge_and_unload()
88
+ model.backbone = backbone
89
+
90
+ # 3. Head safetensors yukle
91
+ head_path = os.path.join(pretrained_model_name_or_path, "joint_head.safetensors")
92
+ if os.path.exists(head_path):
93
+ print(f"[KUTUP-1] Joint Head yukleniyor: {head_path}...")
94
+ weights = load_file(head_path)
95
+ model.head.load_state_dict(weights, strict=False)
96
+
97
+ model.to(torch_dtype)
98
+ model.eval()
99
+ return model
100
+
101
+ @torch.inference_mode()
102
+ def decide(self, tokenizer: AutoTokenizer, state: str, questions: Dict[str, Any]) -> Dict[str, Any]:
103
+ device = next(self.parameters()).device
104
+ answers = {}
105
+ for qid, qdef in questions.items():
106
+ qtype = qdef.get("type", "choice")
107
+ inst = qdef.get("instructions", "")
108
+ crit = qdef.get("criteria", {})
109
+
110
+ prefix_text = f"[DURUM]
111
+ {state}
112
+
113
+ [SORU]
114
+ {inst}"
115
+ p_inputs = tokenizer(prefix_text, return_tensors="pt", truncation=True, max_length=self.config.max_length).to(device)
116
+ p_out = self.backbone.model(**p_inputs)
117
+ p_emb = p_out.last_hidden_state
118
+
119
+ opts = []
120
+ if qtype == "noul":
121
+ opts = ["Evet", "Hayır"]
122
+ opt_keys = ["true", "false"]
123
+ elif isinstance(crit, dict):
124
+ opt_keys = list(crit.keys())
125
+ opts = [f"{k}: {v}" for k, v in crit.items()]
126
+ elif isinstance(crit, list):
127
+ opt_keys = [str(i) for i in range(len(crit))]
128
+ opts = [f"Seviye {i}: {v}" for i, v in enumerate(crit)]
129
+
130
+ opt_embs = []
131
+ for opt in opts:
132
+ o_inp = tokenizer(f"[SECENEK] {opt}", return_tensors="pt").to(device)
133
+ o_out = self.backbone.model(**o_inp)
134
+ opt_embs.append(o_out.last_hidden_state.mean(dim=1))
135
+
136
+ all_opt_emb = torch.stack(opt_embs, dim=1) # [1, num_opts, hidden]
137
+ logits = self.head(p_emb, all_opt_emb).squeeze(0) / self.config.temperature
138
+ probs = torch.softmax(logits, dim=-1).tolist()
139
+
140
+ prob_dict = {k: round(p, 4) for k, p in zip(opt_keys, probs)}
141
+ best_idx = int(torch.argmax(logits).item())
142
+ best_key = opt_keys[best_idx]
143
+ conf = round(probs[best_idx], 4)
144
+
145
+ if qtype == "noul":
146
+ answers[qid] = {"type": "noul", "noul": prob_dict.get("true", 0.5), "confidence": conf}
147
+ else:
148
+ answers[qid] = {"choice": best_key, "confidence": conf, "probabilities": prob_dict}
149
+
150
+ return {"model": "TurkishCodeMan/KUTUP-1-Decision-2B", "answers": answers}
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:06b9509352d2af50381ab2247e083b80d32d5c0aba91c272ca9ff729b6a0e523
3
+ size 19989325
tokenizer_config.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "audio_bos_token": "<|audio_start|>",
4
+ "audio_eos_token": "<|audio_end|>",
5
+ "audio_token": "<|audio_pad|>",
6
+ "backend": "tokenizers",
7
+ "bos_token": null,
8
+ "clean_up_tokenization_spaces": false,
9
+ "eos_token": "<|endoftext|>",
10
+ "errors": "replace",
11
+ "image_token": "<|image_pad|>",
12
+ "is_local": false,
13
+ "local_files_only": false,
14
+ "model_max_length": 262144,
15
+ "model_specific_special_tokens": {
16
+ "audio_bos_token": "<|audio_start|>",
17
+ "audio_eos_token": "<|audio_end|>",
18
+ "audio_token": "<|audio_pad|>",
19
+ "image_token": "<|image_pad|>",
20
+ "video_token": "<|video_pad|>",
21
+ "vision_bos_token": "<|vision_start|>",
22
+ "vision_eos_token": "<|vision_end|>"
23
+ },
24
+ "pad_token": "<|endoftext|>",
25
+ "pretokenize_regex": "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?[\\p{L}\\p{M}]+|\\p{N}| ?[^\\s\\p{L}\\p{M}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+",
26
+ "split_special_tokens": false,
27
+ "tokenizer_class": "Qwen2Tokenizer",
28
+ "unk_token": null,
29
+ "video_token": "<|video_pad|>",
30
+ "vision_bos_token": "<|vision_start|>",
31
+ "vision_eos_token": "<|vision_end|>"
32
+ }