yungisimon commited on
Commit
dbd7316
·
verified ·
1 Parent(s): b7cb6bd

Upload modeling_phase2_tc.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. modeling_phase2_tc.py +144 -0
modeling_phase2_tc.py ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Token-classification head on the PHASE-2 bidirectional LFM2.5 MLM encoder
2
+ (LiquidAI/mlm_phase2_bidir2_step140800, "theirs" bidir variant: full gated shortconv
3
+ made symmetric + non-causal attention). Self-contained for trust_remote_code.
4
+
5
+ The encoder section is inlined VERBATIM from the backbone's shipped
6
+ `modeling_lfm2_bidir_theirs.py` (so the trained conv in_proj/out_proj/conv weights are
7
+ used exactly as trained — unlike our v13 vendored patch which dropped in_proj/out_proj).
8
+ On top sits our BIOES classifier head + class-weighted label-smoothed CE.
9
+ """
10
+ from __future__ import annotations
11
+ from typing import Optional
12
+ import torch
13
+ import torch.nn as nn
14
+ import torch.nn.functional as F
15
+ from transformers.modeling_outputs import TokenClassifierOutput
16
+ from transformers.models.lfm2 import modeling_lfm2 as _lfm2_mod
17
+ from transformers.models.lfm2.configuration_lfm2 import Lfm2Config
18
+ from transformers.models.lfm2.modeling_lfm2 import (
19
+ Lfm2Attention, Lfm2Model, Lfm2PreTrainedModel, Lfm2ShortConv, apply_mask_to_padding_states,
20
+ )
21
+
22
+
23
+ # ---- bidirectional patches (verbatim from the backbone's modeling_lfm2_bidir_theirs) ----
24
+ def _bidirectional_mask(config, input_embeds=None, attention_mask=None, cache_position=None,
25
+ past_key_values=None, position_ids=None, **kwargs):
26
+ if input_embeds is None:
27
+ input_embeds = kwargs.get("inputs_embeds")
28
+ if config._attn_implementation == "flash_attention_2":
29
+ if attention_mask is not None and not attention_mask.all():
30
+ return attention_mask
31
+ return None
32
+ device = input_embeds.device; dtype = input_embeds.dtype
33
+ bsz, q_len = input_embeds.shape[:2]
34
+ past = past_key_values.get_seq_length() if past_key_values is not None else 0
35
+ kv_len = past + q_len
36
+ mask = torch.zeros((bsz, 1, q_len, kv_len), device=device, dtype=dtype)
37
+ if attention_mask is not None:
38
+ cur_len = attention_mask.size(-1)
39
+ key_pad_flags = (attention_mask == 0).to(device=device, dtype=torch.float32)
40
+ pad_vec = torch.zeros((bsz, kv_len), device=device, dtype=torch.float32)
41
+ if cur_len > 0:
42
+ pad_vec[:, past:past + cur_len] = key_pad_flags * -1e9
43
+ mask = mask + pad_vec.to(dtype)[:, None, None, :]
44
+ return mask
45
+
46
+
47
+ def _noncausal_shortconv_forward(self, hidden_states, past_key_values=None, cache_position=None,
48
+ attention_mask=None, **kwargs):
49
+ x = apply_mask_to_padding_states(hidden_states, attention_mask)
50
+ BCx = self.in_proj(x).transpose(-1, -2)
51
+ B, C, x = BCx.chunk(3, dim=-2)
52
+ Bx = B * x
53
+ k = self.conv.weight.shape[-1]; pad = k // 2
54
+ conv_out = F.conv1d(Bx, weight=self.conv.weight, bias=self.conv.bias,
55
+ stride=1, padding=pad, dilation=1, groups=Bx.shape[1])
56
+ if conv_out.shape[-1] > Bx.shape[-1]:
57
+ conv_out = conv_out[..., :Bx.shape[-1]]
58
+ elif conv_out.shape[-1] < Bx.shape[-1]:
59
+ conv_out = F.pad(conv_out, (0, Bx.shape[-1] - conv_out.shape[-1]))
60
+ y = C * conv_out
61
+ y = y.transpose(-1, -2).contiguous()
62
+ return self.out_proj(y)
63
+
64
+
65
+ def _shortconv_forward(self, *args, **kwargs):
66
+ return self.slow_forward(*args, **kwargs)
67
+
68
+
69
+ _PATCHED = False
70
+ def _install_patches():
71
+ global _PATCHED
72
+ if _PATCHED:
73
+ return
74
+ _lfm2_mod.create_causal_mask = _bidirectional_mask
75
+ Lfm2ShortConv.slow_forward = _noncausal_shortconv_forward
76
+ Lfm2ShortConv.forward = _shortconv_forward
77
+ _PATCHED = True
78
+ _install_patches()
79
+
80
+
81
+ def _set_attention_noncausal(model):
82
+ for m in model.modules():
83
+ if isinstance(m, Lfm2Attention):
84
+ m.is_causal = False
85
+
86
+
87
+ class Lfm2BidirectionalModel_theirs(Lfm2Model):
88
+ def __init__(self, config):
89
+ _install_patches()
90
+ super().__init__(config)
91
+ _set_attention_noncausal(self)
92
+
93
+
94
+ # ---- token-classification head (BIOES) ----
95
+ class Lfm2BidirP2ForTokenClassification(Lfm2PreTrainedModel):
96
+ config_class = Lfm2Config
97
+ base_model_prefix = "lfm2"
98
+
99
+ def __init__(self, config: Lfm2Config):
100
+ _install_patches()
101
+ config = type(config).from_dict({**config.to_dict(), "use_cache": False})
102
+ super().__init__(config)
103
+ self.num_labels = config.num_labels
104
+ self.lfm2 = Lfm2BidirectionalModel_theirs(config)
105
+ cd = getattr(config, "classifier_dropout", None)
106
+ self.dropout = nn.Dropout(cd if cd is not None else 0.1)
107
+ self.classifier = nn.Linear(config.hidden_size, config.num_labels)
108
+ self.register_buffer("class_weights", torch.ones(config.num_labels), persistent=True)
109
+ self.label_smoothing = float(getattr(config, "label_smoothing", 0.0))
110
+ self.post_init()
111
+
112
+ def set_class_weights(self, weights: torch.Tensor) -> None:
113
+ if weights.shape != (self.num_labels,):
114
+ raise ValueError(f"class_weights must be ({self.num_labels},), got {tuple(weights.shape)}")
115
+ self.class_weights = weights.to(device=self.class_weights.device, dtype=torch.float32)
116
+
117
+ def get_input_embeddings(self):
118
+ return self.lfm2.embed_tokens
119
+
120
+ def set_input_embeddings(self, value):
121
+ self.lfm2.embed_tokens = value
122
+
123
+ def forward(self, input_ids=None, attention_mask=None, position_ids=None,
124
+ inputs_embeds=None, labels=None, output_hidden_states=None,
125
+ output_attentions=None, return_dict=None, **kwargs) -> TokenClassifierOutput:
126
+ return_dict = True if return_dict is None else return_dict
127
+ outputs = self.lfm2(input_ids=input_ids, attention_mask=attention_mask,
128
+ position_ids=position_ids, inputs_embeds=inputs_embeds,
129
+ use_cache=False, output_attentions=output_attentions,
130
+ output_hidden_states=output_hidden_states, return_dict=True)
131
+ hidden = self.dropout(outputs.last_hidden_state)
132
+ logits = self.classifier(hidden)
133
+ loss = None
134
+ if labels is not None:
135
+ cw = self.class_weights.float()
136
+ if not torch.isfinite(cw).all():
137
+ cw = torch.ones_like(cw)
138
+ loss = F.cross_entropy(logits.view(-1, self.num_labels).float(), labels.view(-1),
139
+ weight=cw, ignore_index=-100, label_smoothing=self.label_smoothing)
140
+ if not return_dict:
141
+ out = (logits,) + outputs[1:]
142
+ return ((loss,) + out) if loss is not None else out
143
+ return TokenClassifierOutput(loss=loss, logits=logits,
144
+ hidden_states=outputs.hidden_states, attentions=outputs.attentions)