qa-completeness-regressor / modeling_completeness_regressor.py
egcortes's picture
Publish QA completeness regressor v1.0.0
294449c
Raw
History Blame Contribute Delete
2.34 kB
"""
A BERT model that predicts how complete an answer is.
The head is a single linear layer on the CLS token, with no pooler in between.
That is not one of the standard transformers heads, so the class lives here and
you load it with trust_remote_code=True.
"""
import torch
from torch import nn
from transformers import BertModel, BertPreTrainedModel
from transformers.modeling_outputs import SequenceClassifierOutput
class BertCompletenessRegressor(BertPreTrainedModel):
"""Predicts a completeness score. Higher means more complete."""
def __init__(self, config):
super().__init__(config)
self.num_labels = 1
self.bert = BertModel(config, add_pooling_layer=False)
self.regressor = nn.Linear(config.hidden_size, 1)
self.post_init()
def forward(self, input_ids=None, attention_mask=None, token_type_ids=None,
position_ids=None, head_mask=None, inputs_embeds=None,
labels=None, output_attentions=None, output_hidden_states=None,
return_dict=None):
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
outputs = self.bert(
input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids,
position_ids=position_ids, head_mask=head_mask, inputs_embeds=inputs_embeds,
output_attentions=output_attentions, output_hidden_states=output_hidden_states,
return_dict=True,
)
cls = outputs.last_hidden_state[:, 0] # CLS token, no pooler
logits = self.regressor(cls)
loss = None
if labels is not None:
loss = nn.functional.mse_loss(logits.squeeze(-1), labels.float())
if not return_dict:
return (loss, logits) if loss is not None else (logits,)
return SequenceClassifierOutput(
loss=loss, logits=logits,
hidden_states=outputs.hidden_states, attentions=outputs.attentions,
)
def build_input(question, answer):
"""Format a question and answer the way the model was trained.
The stray "f" before "Answer:" is a typo in the original training code.
It has to stay, otherwise the input does not match what the model saw.
"""
return f'Question: {question}\n\nfAnswer: {answer}\n\nHow complete is this answer?'