Text Classification
Transformers
Safetensors
lfm2
feature-extraction
betterwright
accessibility
browser-agent
reranking
long-context
custom_code
Instructions to use ProCreations/betterwright-encoder-350m with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use ProCreations/betterwright-encoder-350m with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="ProCreations/betterwright-encoder-350m", trust_remote_code=True)# Load model directly from transformers import AutoTokenizer, AutoModel tokenizer = AutoTokenizer.from_pretrained("ProCreations/betterwright-encoder-350m", trust_remote_code=True) model = AutoModel.from_pretrained("ProCreations/betterwright-encoder-350m", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Add hard-negative token ranking objective
Browse files- modeling_betterwright.py +34 -1
modeling_betterwright.py
CHANGED
|
@@ -21,6 +21,8 @@ class BetterWrightEncoderOutput(ModelOutput):
|
|
| 21 |
logits: Optional[torch.Tensor] = None
|
| 22 |
token_logits: Optional[torch.Tensor] = None
|
| 23 |
uncertainty_logits: Optional[torch.Tensor] = None
|
|
|
|
|
|
|
| 24 |
last_hidden_state: Optional[torch.Tensor] = None
|
| 25 |
|
| 26 |
|
|
@@ -84,6 +86,8 @@ class BetterWrightEncoder(Lfm2PreTrainedModel):
|
|
| 84 |
logits = self.relevance_head(pooled).squeeze(-1)
|
| 85 |
uncertainty_logits = self.uncertainty_head(pooled).squeeze(-1)
|
| 86 |
loss = None
|
|
|
|
|
|
|
| 87 |
if labels is not None:
|
| 88 |
labels = labels.to(logits.dtype)
|
| 89 |
positive_weight = float(getattr(self.config, "betterwright_positive_weight", 3.0))
|
|
@@ -122,12 +126,41 @@ class BetterWrightEncoder(Lfm2PreTrainedModel):
|
|
| 122 |
dtype=token_logits.dtype,
|
| 123 |
),
|
| 124 |
)
|
| 125 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
result = BetterWrightEncoderOutput(
|
| 127 |
loss=loss,
|
| 128 |
logits=logits,
|
| 129 |
token_logits=token_logits,
|
| 130 |
uncertainty_logits=uncertainty_logits,
|
|
|
|
|
|
|
| 131 |
last_hidden_state=hidden,
|
| 132 |
)
|
| 133 |
return result if return_dict else tuple(result.values())
|
|
|
|
| 21 |
logits: Optional[torch.Tensor] = None
|
| 22 |
token_logits: Optional[torch.Tensor] = None
|
| 23 |
uncertainty_logits: Optional[torch.Tensor] = None
|
| 24 |
+
token_loss: Optional[torch.Tensor] = None
|
| 25 |
+
token_rank_loss: Optional[torch.Tensor] = None
|
| 26 |
last_hidden_state: Optional[torch.Tensor] = None
|
| 27 |
|
| 28 |
|
|
|
|
| 86 |
logits = self.relevance_head(pooled).squeeze(-1)
|
| 87 |
uncertainty_logits = self.uncertainty_head(pooled).squeeze(-1)
|
| 88 |
loss = None
|
| 89 |
+
token_loss = None
|
| 90 |
+
token_rank_loss = None
|
| 91 |
if labels is not None:
|
| 92 |
labels = labels.to(logits.dtype)
|
| 93 |
positive_weight = float(getattr(self.config, "betterwright_positive_weight", 3.0))
|
|
|
|
| 126 |
dtype=token_logits.dtype,
|
| 127 |
),
|
| 128 |
)
|
| 129 |
+
# Runtime pruning ranks lines by their highest-scoring token.
|
| 130 |
+
# BCE alone can achieve a reasonable average while leaving a
|
| 131 |
+
# few distractor tokens above the evidence. Explicitly compare
|
| 132 |
+
# each positive row against its hardest negative tokens so the
|
| 133 |
+
# training objective matches that production ranking behavior.
|
| 134 |
+
token_rank_losses = []
|
| 135 |
+
for row_index in range(token_logits.shape[0]):
|
| 136 |
+
row_valid = valid[row_index]
|
| 137 |
+
row_labels = token_labels[row_index]
|
| 138 |
+
positives = token_logits[row_index][row_valid & (row_labels == 1)]
|
| 139 |
+
negatives = token_logits[row_index][row_valid & (row_labels == 0)]
|
| 140 |
+
if positives.numel() == 0 or negatives.numel() == 0:
|
| 141 |
+
continue
|
| 142 |
+
hard_count = min(64, negatives.numel())
|
| 143 |
+
hard_negatives = torch.topk(
|
| 144 |
+
negatives.float(), hard_count, sorted=False
|
| 145 |
+
).values
|
| 146 |
+
token_rank_losses.append(
|
| 147 |
+
F.softplus(
|
| 148 |
+
1.0 + hard_negatives.mean() - positives.float().mean()
|
| 149 |
+
)
|
| 150 |
+
)
|
| 151 |
+
if token_rank_losses:
|
| 152 |
+
token_rank_loss = torch.stack(token_rank_losses).mean()
|
| 153 |
+
else:
|
| 154 |
+
token_rank_loss = token_loss.new_zeros(())
|
| 155 |
+
token_objective = 0.75 * token_loss + token_rank_loss
|
| 156 |
+
loss = token_objective if loss is None else loss + token_objective
|
| 157 |
result = BetterWrightEncoderOutput(
|
| 158 |
loss=loss,
|
| 159 |
logits=logits,
|
| 160 |
token_logits=token_logits,
|
| 161 |
uncertainty_logits=uncertainty_logits,
|
| 162 |
+
token_loss=token_loss,
|
| 163 |
+
token_rank_loss=token_rank_loss,
|
| 164 |
last_hidden_state=hidden,
|
| 165 |
)
|
| 166 |
return result if return_dict else tuple(result.values())
|