ThingsAI commited on
Commit
92a7d9d
·
verified ·
1 Parent(s): 3c3cbe3

Export Quark Instruct checkpoint

Browse files
README.md ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - en
4
+ - it
5
+ license: mit
6
+ tags:
7
+ - quark
8
+ - causal-lm
9
+ - bash
10
+ - code
11
+ pipeline_tag: text-generation
12
+ ---
13
+
14
+ # Quark-72M-Instruct
15
+
16
+ Quark-72M Instruct — compact autoregressive language model trained by [ThingAI](https://things-ai.org).
17
+
18
+ ## Model Details
19
+
20
+ | Parameter | Value |
21
+ |-----------|-------|
22
+ | Parameters | 71.6M |
23
+ | Architecture | Decoder-only Transformer |
24
+ | Layers | 14 |
25
+ | Hidden size | 512 |
26
+ | Attention heads | 8 (GQA, 2 KV) |
27
+ | FFN | SwiGLU (1344) |
28
+ | Norm | RMSNorm |
29
+ | Position | RoPE |
30
+ | Vocab size | 65,538 |
31
+ | Context length | 2,048 |
32
+
33
+ ## Usage
34
+
35
+ ```python
36
+ from transformers import AutoTokenizer, AutoModelForCausalLM
37
+ import torch
38
+
39
+ tokenizer = AutoTokenizer.from_pretrained("ThingAI/Quark-72M-Instruct")
40
+ model = AutoModelForCausalLM.from_pretrained("ThingAI/Quark-72M-Instruct", trust_remote_code=True)
41
+
42
+ prompt = "<|user|>\nHow do I find files larger than 100MB?\n<|end|>\n<|assistant|>\n"
43
+ ids = tokenizer(prompt, return_tensors="pt").input_ids
44
+ out = model.generate_text(ids, max_new_tokens=200, temperature=0.2)
45
+ print(tokenizer.decode(out[0], skip_special_tokens=False))
46
+ ```
47
+
48
+ ## Training
49
+
50
+ - **Pre-training**: 5B tokens on math, code, EN/IT text
51
+ - **SFT**: bash commands, code, conversations (ChatML template)
52
+ - **Tokenizer**: BPE byte-level, 65536 vocab
53
+
54
+ ## License
55
+
56
+ MIT
config.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "quark",
3
+ "architectures": [
4
+ "QuarkForCausalLM"
5
+ ],
6
+ "auto_map": {
7
+ "AutoConfig": "configuration_quark.QuarkConfig",
8
+ "AutoModelForCausalLM": "modeling_quark.QuarkForCausalLM"
9
+ },
10
+ "vocab_size": 65538,
11
+ "d_model": 512,
12
+ "n_heads": 8,
13
+ "n_kv_heads": 2,
14
+ "n_layers": 14,
15
+ "d_ff": 1344,
16
+ "head_dim": 64,
17
+ "max_seq_len": 2048,
18
+ "max_position_embeddings": 2048,
19
+ "rope_theta": 10000.0,
20
+ "rms_eps": 1e-05,
21
+ "qkv_bias": true,
22
+ "dropout": 0.0,
23
+ "tie_word_embeddings": true,
24
+ "torch_dtype": "float32",
25
+ "transformers_version": "4.40.0"
26
+ }
configuration_quark.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Quark model configuration — compatibile con AutoConfig / AutoModel HuggingFace.
3
+ """
4
+ from transformers import PretrainedConfig
5
+
6
+
7
+ class QuarkConfig(PretrainedConfig):
8
+ model_type = "quark"
9
+
10
+ def __init__(
11
+ self,
12
+ vocab_size = 65_536,
13
+ d_model = 512,
14
+ n_heads = 8,
15
+ n_kv_heads = 2,
16
+ n_layers = 14,
17
+ d_ff = 1344,
18
+ head_dim = 64,
19
+ max_seq_len = 2048,
20
+ rope_theta = 10_000.0,
21
+ rms_eps = 1e-5,
22
+ qkv_bias = True,
23
+ dropout = 0.0,
24
+ tie_word_embeddings = True,
25
+ **kwargs,
26
+ ):
27
+ self.vocab_size = vocab_size
28
+ self.d_model = d_model
29
+ self.n_heads = n_heads
30
+ self.n_kv_heads = n_kv_heads
31
+ self.n_layers = n_layers
32
+ self.d_ff = d_ff
33
+ self.head_dim = head_dim
34
+ self.max_seq_len = max_seq_len
35
+ self.rope_theta = rope_theta
36
+ self.rms_eps = rms_eps
37
+ self.qkv_bias = qkv_bias
38
+ self.dropout = dropout
39
+ super().__init__(tie_word_embeddings=tie_word_embeddings, **kwargs)
generation_config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "eos_token_id": 3,
3
+ "pad_token_id": 0,
4
+ "bos_token_id": 2,
5
+ "max_new_tokens": 512,
6
+ "temperature": 0.7,
7
+ "top_p": 0.9,
8
+ "do_sample": true
9
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9cbff9d64001da4c03728705430220b2178d1934523b8d9131c4b6e198c3ade5
3
+ size 286646720
modeling_quark.py ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Quark language model — compatibile con AutoModelForCausalLM HuggingFace.
3
+ """
4
+ import math
5
+ import torch
6
+ import torch.nn as nn
7
+ import torch.nn.functional as F
8
+ from transformers import PreTrainedModel
9
+ from transformers.modeling_outputs import CausalLMOutputWithPast
10
+
11
+ from .configuration_quark import QuarkConfig
12
+
13
+
14
+ class RMSNorm(nn.Module):
15
+ def __init__(self, dim, eps=1e-5):
16
+ super().__init__()
17
+ self.eps = eps
18
+ self.scale = nn.Parameter(torch.ones(dim))
19
+
20
+ def forward(self, x):
21
+ rms = x.float().pow(2).mean(-1, keepdim=True).add(self.eps).rsqrt()
22
+ return (x.float() * rms).to(x.dtype) * self.scale
23
+
24
+
25
+ class RotaryEmbedding(nn.Module):
26
+ def __init__(self, head_dim, max_seq_len, theta=10_000.0):
27
+ super().__init__()
28
+ inv_freq = 1.0 / (theta ** (torch.arange(0, head_dim, 2).float() / head_dim))
29
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
30
+ self._build_cache(max_seq_len)
31
+
32
+ def _build_cache(self, seq_len):
33
+ t = torch.arange(seq_len, device=self.inv_freq.device).float()
34
+ freqs = torch.outer(t, self.inv_freq)
35
+ emb = torch.cat([freqs, freqs], dim=-1)
36
+ self.register_buffer("cos_cache", emb.cos()[None, None], persistent=False)
37
+ self.register_buffer("sin_cache", emb.sin()[None, None], persistent=False)
38
+ self._max = seq_len
39
+
40
+ @staticmethod
41
+ def _rotate_half(x):
42
+ x1, x2 = x.chunk(2, dim=-1)
43
+ return torch.cat([-x2, x1], dim=-1)
44
+
45
+ def forward(self, q, k):
46
+ T = q.size(2)
47
+ if T > self._max:
48
+ self._build_cache(T)
49
+ cos = self.cos_cache[:, :, :T, :]
50
+ sin = self.sin_cache[:, :, :T, :]
51
+ return q * cos + self._rotate_half(q) * sin, k * cos + self._rotate_half(k) * sin
52
+
53
+
54
+ class GroupedQueryAttention(nn.Module):
55
+ def __init__(self, cfg):
56
+ super().__init__()
57
+ self.n_heads = cfg.n_heads
58
+ self.n_kv_heads = cfg.n_kv_heads
59
+ self.n_groups = cfg.n_heads // cfg.n_kv_heads
60
+ self.head_dim = cfg.head_dim
61
+
62
+ self.q_proj = nn.Linear(cfg.d_model, cfg.n_heads * cfg.head_dim, bias=cfg.qkv_bias)
63
+ self.k_proj = nn.Linear(cfg.d_model, cfg.n_kv_heads * cfg.head_dim, bias=cfg.qkv_bias)
64
+ self.v_proj = nn.Linear(cfg.d_model, cfg.n_kv_heads * cfg.head_dim, bias=cfg.qkv_bias)
65
+ self.o_proj = nn.Linear(cfg.n_heads * cfg.head_dim, cfg.d_model, bias=False)
66
+ self.rope = RotaryEmbedding(cfg.head_dim, cfg.max_seq_len, cfg.rope_theta)
67
+ self.drop = cfg.dropout
68
+
69
+ def forward(self, x, attention_mask=None, **kwargs):
70
+ B, T, _ = x.shape
71
+ q = self.q_proj(x).view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
72
+ k = self.k_proj(x).view(B, T, self.n_kv_heads, self.head_dim).transpose(1, 2)
73
+ v = self.v_proj(x).view(B, T, self.n_kv_heads, self.head_dim).transpose(1, 2)
74
+ q, k = self.rope(q, k)
75
+ if self.n_groups > 1:
76
+ k = k.repeat_interleave(self.n_groups, dim=1)
77
+ v = v.repeat_interleave(self.n_groups, dim=1)
78
+ out = F.scaled_dot_product_attention(
79
+ q, k, v, attn_mask=None,
80
+ dropout_p=self.drop if self.training else 0.0,
81
+ is_causal=True,
82
+ )
83
+ out = out.transpose(1, 2).contiguous().view(B, T, self.n_heads * self.head_dim)
84
+ return self.o_proj(out)
85
+
86
+
87
+ class SwiGLUFFN(nn.Module):
88
+ def __init__(self, cfg):
89
+ super().__init__()
90
+ self.gate_proj = nn.Linear(cfg.d_model, cfg.d_ff, bias=False)
91
+ self.up_proj = nn.Linear(cfg.d_model, cfg.d_ff, bias=False)
92
+ self.down_proj = nn.Linear(cfg.d_ff, cfg.d_model, bias=False)
93
+
94
+ def forward(self, x):
95
+ return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x))
96
+
97
+
98
+ class TransformerBlock(nn.Module):
99
+ def __init__(self, cfg):
100
+ super().__init__()
101
+ self.norm_attn = RMSNorm(cfg.d_model, cfg.rms_eps)
102
+ self.attn = GroupedQueryAttention(cfg)
103
+ self.norm_ffn = RMSNorm(cfg.d_model, cfg.rms_eps)
104
+ self.ffn = SwiGLUFFN(cfg)
105
+
106
+ def forward(self, x, **kwargs):
107
+ x = x + self.attn(self.norm_attn(x), **kwargs)
108
+ x = x + self.ffn(self.norm_ffn(x))
109
+ return x
110
+
111
+
112
+ class QuarkPreTrainedModel(PreTrainedModel):
113
+ config_class = QuarkConfig
114
+ base_model_prefix = "model"
115
+ supports_gradient_checkpointing = False
116
+
117
+ def _init_weights(self, module):
118
+ std = 0.02
119
+ if isinstance(module, nn.Linear):
120
+ nn.init.normal_(module.weight, 0.0, std)
121
+ if module.bias is not None:
122
+ nn.init.zeros_(module.bias)
123
+ elif isinstance(module, nn.Embedding):
124
+ nn.init.normal_(module.weight, 0.0, std)
125
+
126
+
127
+ class QuarkForCausalLM(QuarkPreTrainedModel):
128
+ """
129
+ Quark autoregressive language model.
130
+ Compatibile con AutoModelForCausalLM.from_pretrained(..., trust_remote_code=True)
131
+ """
132
+ def __init__(self, config: QuarkConfig):
133
+ super().__init__(config)
134
+ self.embed_tokens = nn.Embedding(config.vocab_size, config.d_model)
135
+ self.layers = nn.ModuleList([TransformerBlock(config) for _ in range(config.n_layers)])
136
+ self.norm = RMSNorm(config.d_model, config.rms_eps)
137
+ self.lm_head = nn.Linear(config.d_model, config.vocab_size, bias=False)
138
+
139
+ if config.tie_word_embeddings:
140
+ self.lm_head.weight = self.embed_tokens.weight
141
+
142
+ self.post_init()
143
+
144
+ def get_input_embeddings(self):
145
+ return self.embed_tokens
146
+
147
+ def set_input_embeddings(self, value):
148
+ self.embed_tokens = value
149
+
150
+ def get_output_embeddings(self):
151
+ return self.lm_head
152
+
153
+ def set_output_embeddings(self, value):
154
+ self.lm_head = value
155
+
156
+ def forward(
157
+ self,
158
+ input_ids = None,
159
+ attention_mask = None,
160
+ labels = None,
161
+ **kwargs,
162
+ ):
163
+ x = self.embed_tokens(input_ids)
164
+ for layer in self.layers:
165
+ x = layer(x, attention_mask=attention_mask)
166
+ x = self.norm(x)
167
+ logits = self.lm_head(x)
168
+
169
+ loss = None
170
+ if labels is not None:
171
+ loss = F.cross_entropy(
172
+ logits[:, :-1, :].contiguous().view(-1, self.config.vocab_size),
173
+ labels[:, 1:].contiguous().view(-1),
174
+ ignore_index=-100,
175
+ )
176
+
177
+ return CausalLMOutputWithPast(loss=loss, logits=logits)
178
+
179
+ @torch.no_grad()
180
+ def generate_text(self, input_ids, max_new_tokens=200, temperature=0.7,
181
+ top_p=0.9, eos_token_id=None):
182
+ """Generazione semplice senza dipendere da .generate() HF."""
183
+ ctx = input_ids.clone()
184
+ for _ in range(max_new_tokens):
185
+ out = self(ctx[:, -self.config.max_seq_len:])
186
+ logits = out.logits[0, -1, :].float()
187
+ if temperature > 0:
188
+ logits /= temperature
189
+ probs = F.softmax(logits, dim=-1)
190
+ # top-p
191
+ sorted_p, sorted_i = torch.sort(probs, descending=True)
192
+ cum_p = torch.cumsum(sorted_p, dim=-1)
193
+ remove = cum_p - sorted_p > top_p
194
+ sorted_p[remove] = 0.0
195
+ sorted_p /= sorted_p.sum()
196
+ token = sorted_i[torch.multinomial(sorted_p, 1)].unsqueeze(0).unsqueeze(0)
197
+ else:
198
+ token = logits.argmax().view(1, 1)
199
+ ctx = torch.cat([ctx, token], dim=1)
200
+ if eos_token_id is not None and token.item() == eos_token_id:
201
+ break
202
+ return ctx
tokenizer_config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "tokenizer_class": "AutoTokenizer",
3
+ "model_max_length": 2048,
4
+ "padding_side": "right",
5
+ "bos_token": "<s>",
6
+ "eos_token": "</s>",
7
+ "unk_token": "<unk>",
8
+ "pad_token": "<pad>"
9
+ }