ereniko commited on
Commit
320c763
·
verified ·
1 Parent(s): a2c16e1

Upload folder using huggingface_hub

Browse files
README.md ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ pipeline_tag: text-generation
4
+ library_name: transformers
5
+ language:
6
+ - en
7
+ tags:
8
+ - from-scratch
9
+ - experimental
10
+ - causal-lm
11
+ - small-language-model
12
+ - instruct-pretrained
13
+ datasets:
14
+ - HuggingFaceH4/ultrachat_200k
15
+ - allenai/soda
16
+ - openbmb/UltraInteract_sft
17
+ - microsoft/orca-math-word-problems-200k
18
+ - databricks/databricks-dolly-15k
19
+ - b-mc2/sql-create-context
20
+ ---
21
+
22
+ # Ivme-Conversate-S-v2-Instruct
23
+
24
+ 9,021,600 parameters. Standard decoder-only Transformer (tied
25
+ embeddings, multi-head attention, RoPE, SwiGLU, RMSNorm) -- matching
26
+ Ivme-Conversate-v2-Base's proven recipe exactly, deliberately with zero
27
+ architectural novelty.
28
+
29
+ Trained single-epoch on ~900M tokens, instruct-heavy from the start rather
30
+ than base-pretrain-then-finetune: UltraChat-200k (real multi-turn dialogue)
31
+ as the dominant 45% share, plus SODA, UltraInteract reasoning traces,
32
+ orca-math, dolly-15k instructions, and sql-create-context. All sources
33
+ permissively licensed (MIT/CC-BY/CC-BY-SA).
34
+
35
+ ## Usage
36
+
37
+ ```python
38
+ from transformers import AutoModelForCausalLM, AutoTokenizer
39
+
40
+ model = AutoModelForCausalLM.from_pretrained(
41
+ "ivmelabs/Ivme-Conversate-S-v2-Instruct", trust_remote_code=True
42
+ )
43
+ tok = AutoTokenizer.from_pretrained("ivmelabs/Ivme-Conversate-S-v2-Instruct")
44
+
45
+ ids = tok("Hello!", return_tensors="pt").input_ids
46
+ out = model.generate(ids, max_new_tokens=80, do_sample=True, temperature=0.8, top_k=40)
47
+ print(tok.decode(out[0]))
48
+ ```
49
+
50
+ Note: no KV-cache in this architecture -- `.generate()` works but is O(n^2)
51
+ rather than O(n), fine for short samples, not tuned for long-form serving.
config.json ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "IvmeConversateSV2InstructModel"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "configuration_ivme_s_v2_instruct.IvmeConversateSV2InstructConfig",
7
+ "AutoModelForCausalLM": "modeling_ivme_s_v2_instruct.IvmeConversateSV2InstructModel"
8
+ },
9
+ "d_ff": 896,
10
+ "d_model": 224,
11
+ "dtype": "float32",
12
+ "max_seq_len": 1024,
13
+ "model_type": "ivme_conversate_s_v2_instruct",
14
+ "n_heads": 7,
15
+ "n_layers": 9,
16
+ "norm_eps": 1e-05,
17
+ "rope_theta": 10000.0,
18
+ "tie_word_embeddings": true,
19
+ "transformers_version": "5.14.1",
20
+ "vocab_size": 8000
21
+ }
configuration_ivme_s_v2_instruct.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Configuration class for Ivme-Conversate-S-v2-Instruct.
3
+
4
+ Mirrors train_conversate_s_v2_instruct.ModelConfig exactly (same field
5
+ names, same defaults), so config.json produced from a real training run's
6
+ ModelConfig round-trips into this class with no field remapping needed.
7
+ """
8
+
9
+ from transformers import PretrainedConfig
10
+
11
+
12
+ class IvmeConversateSV2InstructConfig(PretrainedConfig):
13
+ model_type = "ivme_conversate_s_v2_instruct"
14
+
15
+ def __init__(
16
+ self,
17
+ vocab_size: int = 8000,
18
+ d_model: int = 224,
19
+ n_layers: int = 9,
20
+ n_heads: int = 7,
21
+ d_ff: int = 896,
22
+ max_seq_len: int = 1024,
23
+ norm_eps: float = 1e-5,
24
+ rope_theta: float = 10000.0,
25
+ **kwargs,
26
+ ):
27
+ self.vocab_size = vocab_size
28
+ self.d_model = d_model
29
+ self.n_layers = n_layers
30
+ self.n_heads = n_heads
31
+ self.d_ff = d_ff
32
+ self.max_seq_len = max_seq_len
33
+ self.norm_eps = norm_eps
34
+ self.rope_theta = rope_theta
35
+ kwargs.setdefault("tie_word_embeddings", True)
36
+ super().__init__(**kwargs)
generation_config.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "output_attentions": false,
4
+ "output_hidden_states": false,
5
+ "transformers_version": "5.14.1"
6
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5e553ab3502dfdf950779e2730088f23259cdf12f3ac87affddfc2fe81a35c59
3
+ size 36354824
modeling_ivme_s_v2_instruct.py ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Modeling file for Ivme-Conversate-S-v2-Instruct.
3
+
4
+ Standard decoder-only Transformer architecture, deliberately matching
5
+ Ivme-Conversate-v2-Base's proven recipe (pulled directly from its real
6
+ config.json): tied embeddings, standard multi-head attention (no GQA, no
7
+ DIFF), RoPE, SwiGLU, RMSNorm, pre-norm. No architectural novelty by design --
8
+ this model tests a DATA strategy (instruct-heavy, single-epoch pretraining)
9
+ in isolation, on infrastructure already proven stable.
10
+
11
+ Trained on ~900M tokens, single epoch, instruct-heavy mix (UltraChat-200k as
12
+ the dominant 45% share, plus SODA, UltraInteract, orca-math, dolly-15k,
13
+ sql-create-context) -- all permissively licensed (MIT/CC-BY/CC-BY-SA), no
14
+ CC-BY-NC sources, matching v2-Base's Apache-2.0 license.
15
+
16
+ Uses standard HF tied-embedding conventions (get_output_embeddings /
17
+ set_output_embeddings + config.tie_word_embeddings), so PreTrainedModel's
18
+ own tie_weights() machinery handles the tie correctly through from_pretrained
19
+ -- more robust than manual weight assignment, since it's re-applied
20
+ automatically by HF's own loading path rather than needing to survive it.
21
+ """
22
+
23
+ import math
24
+
25
+ import torch
26
+ import torch.nn as nn
27
+ import torch.nn.functional as F
28
+ from transformers import PreTrainedModel
29
+ from transformers.modeling_outputs import CausalLMOutput
30
+
31
+ try:
32
+ from .configuration_ivme_s_v2_instruct import IvmeConversateSV2InstructConfig
33
+ except ImportError:
34
+ from configuration_ivme_s_v2_instruct import IvmeConversateSV2InstructConfig
35
+
36
+
37
+ def build_rope_cache(dim, max_seq_len, base=10000.0):
38
+ assert dim % 2 == 0
39
+ inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))
40
+ t = torch.arange(max_seq_len).float()
41
+ freqs = torch.outer(t, inv_freq)
42
+ emb = torch.cat([freqs, freqs], dim=-1)
43
+ return emb.cos(), emb.sin()
44
+
45
+
46
+ def rotate_half(x):
47
+ x1, x2 = x.chunk(2, dim=-1)
48
+ return torch.cat([-x2, x1], dim=-1)
49
+
50
+
51
+ def apply_rope(x, cos, sin):
52
+ T = x.shape[-2]
53
+ cos = cos[:T].unsqueeze(0).unsqueeze(0).to(x.dtype)
54
+ sin = sin[:T].unsqueeze(0).unsqueeze(0).to(x.dtype)
55
+ return x * cos + rotate_half(x) * sin
56
+
57
+
58
+ class RMSNorm(nn.Module):
59
+ def __init__(self, dim, eps=1e-5):
60
+ super().__init__()
61
+ self.weight = nn.Parameter(torch.ones(dim))
62
+ self.eps = eps
63
+
64
+ def forward(self, x):
65
+ norm = x.pow(2).mean(-1, keepdim=True).add(self.eps).rsqrt()
66
+ return x * norm * self.weight
67
+
68
+
69
+ class StandardAttention(nn.Module):
70
+ def __init__(self, d_model, n_heads):
71
+ super().__init__()
72
+ assert d_model % n_heads == 0
73
+ self.n_heads = n_heads
74
+ self.head_dim = d_model // n_heads
75
+ self.wqkv = nn.Linear(d_model, 3 * d_model, bias=False)
76
+ self.wo = nn.Linear(d_model, d_model, bias=False)
77
+
78
+ def forward(self, x, rope_cos, rope_sin):
79
+ B, T, D = x.shape
80
+ qkv = self.wqkv(x)
81
+ q, k, v = qkv.split(D, dim=-1)
82
+ q = q.view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
83
+ k = k.view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
84
+ v = v.view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
85
+ q = apply_rope(q, rope_cos, rope_sin)
86
+ k = apply_rope(k, rope_cos, rope_sin)
87
+ out = F.scaled_dot_product_attention(q, k, v, is_causal=True)
88
+ out = out.transpose(1, 2).contiguous().view(B, T, D)
89
+ return self.wo(out)
90
+
91
+
92
+ class SwiGLU(nn.Module):
93
+ def __init__(self, d_model, d_ff):
94
+ super().__init__()
95
+ self.w_gate = nn.Linear(d_model, d_ff, bias=False)
96
+ self.w_up = nn.Linear(d_model, d_ff, bias=False)
97
+ self.w_down = nn.Linear(d_ff, d_model, bias=False)
98
+
99
+ def forward(self, x):
100
+ return self.w_down(F.silu(self.w_gate(x)) * self.w_up(x))
101
+
102
+
103
+ class Block(nn.Module):
104
+ def __init__(self, d_model, n_heads, d_ff, eps=1e-5):
105
+ super().__init__()
106
+ self.norm1 = RMSNorm(d_model, eps)
107
+ self.attn = StandardAttention(d_model, n_heads)
108
+ self.norm2 = RMSNorm(d_model, eps)
109
+ self.ffn = SwiGLU(d_model, d_ff)
110
+
111
+ def forward(self, x, rope_cos, rope_sin):
112
+ x = x + self.attn(self.norm1(x), rope_cos, rope_sin)
113
+ x = x + self.ffn(self.norm2(x))
114
+ return x
115
+
116
+
117
+ class IvmeConversateSV2InstructModel(PreTrainedModel):
118
+ """HF-compatible wrapper. Load with:
119
+ AutoModelForCausalLM.from_pretrained(repo_id, trust_remote_code=True)
120
+ """
121
+
122
+ config_class = IvmeConversateSV2InstructConfig
123
+ # Explicit declarative tied-weights mapping -- confirmed via direct
124
+ # inspection of transformers' PreTrainedModel.get_expanded_tied_weights_keys
125
+ # that get_input_embeddings()/get_output_embeddings() ALONE do not trigger
126
+ # automatic tying in this version; the class needs _tied_weights_keys set
127
+ # explicitly (same convention used by e.g. GPT2LMHeadModel:
128
+ # {'lm_head.weight': 'transformer.wte.weight'}). Verified this actually
129
+ # ties the weights via post_init() -> init_weights() -> tie_weights():
130
+ # an earlier version of this file relied on get_output_embeddings() alone
131
+ # and the weights were NOT tied (model.tok_embed.weight is model.lm_head.
132
+ # weight was False) despite tie_word_embeddings=True in config.
133
+ _tied_weights_keys = {"lm_head.weight": "tok_embed.weight"}
134
+
135
+ def __init__(self, config: IvmeConversateSV2InstructConfig):
136
+ super().__init__(config)
137
+ self.tok_embed = nn.Embedding(config.vocab_size, config.d_model)
138
+ nn.init.normal_(self.tok_embed.weight, mean=0.0, std=0.02)
139
+
140
+ self.blocks = nn.ModuleList([
141
+ Block(config.d_model, config.n_heads, config.d_ff, config.norm_eps)
142
+ for _ in range(config.n_layers)
143
+ ])
144
+ self.norm_f = RMSNorm(config.d_model, config.norm_eps)
145
+ self.lm_head = nn.Linear(config.d_model, config.vocab_size, bias=False)
146
+
147
+ head_dim = config.d_model // config.n_heads
148
+ cos, sin = build_rope_cache(head_dim, config.max_seq_len, config.rope_theta)
149
+ self.register_buffer("rope_cos", cos, persistent=True)
150
+ self.register_buffer("rope_sin", sin, persistent=True)
151
+
152
+ self.post_init()
153
+
154
+ def get_input_embeddings(self):
155
+ return self.tok_embed
156
+
157
+ def set_input_embeddings(self, value):
158
+ self.tok_embed = value
159
+
160
+ def get_output_embeddings(self):
161
+ return self.lm_head
162
+
163
+ def set_output_embeddings(self, new_embeddings):
164
+ self.lm_head = new_embeddings
165
+
166
+ def can_generate(self):
167
+ return True
168
+
169
+ def forward(self, input_ids, labels=None, **kwargs):
170
+ x = self.tok_embed(input_ids)
171
+ for block in self.blocks:
172
+ x = block(x, self.rope_cos, self.rope_sin)
173
+ x = self.norm_f(x)
174
+ logits = self.lm_head(x)
175
+
176
+ loss = None
177
+ if labels is not None:
178
+ loss = F.cross_entropy(
179
+ logits[:, :-1, :].reshape(-1, self.config.vocab_size),
180
+ labels[:, 1:].reshape(-1),
181
+ )
182
+
183
+ return CausalLMOutput(loss=loss, logits=logits)
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff