| --- |
| language: vi |
| tags: |
| - cross-encoder |
| - reranker |
| - phobert |
| - vietnamese |
| - question-answering |
| license: mit |
| --- |
| |
| # HUMG Cross-Encoder (Reranker) |
|
|
| Mô hình Cross-Encoder được fine-tune từ `vinai/phobert-base` |
| để xếp hạng lại (rerank) các cặp câu hỏi - đoạn văn bản. |
|
|
| ## Kiến trúc |
| - **Base model**: `vinai/phobert-base` |
| - **Classifier**: Mean pooling → Dropout → Linear(768 → 1) |
| - **Loss**: BCEWithLogitsLoss |
| - **Max length**: 512 |
|
|
| ## Cách sử dụng |
| ```python |
| import torch |
| from transformers import AutoModel, AutoTokenizer |
| import torch.nn as nn |
| |
| class CrossEncoderModel(nn.Module): |
| def __init__(self, backbone_name, hidden_dropout=0.1): |
| super().__init__() |
| self.backbone = AutoModel.from_pretrained(backbone_name) |
| hidden_size = self.backbone.config.hidden_size |
| self.dropout = nn.Dropout(hidden_dropout) |
| self.classifier = nn.Linear(hidden_size, 1) |
| |
| def forward(self, input_ids, attention_mask): |
| out = self.backbone(input_ids=input_ids, attention_mask=attention_mask) |
| mask = attention_mask.unsqueeze(-1).float() |
| pooled = (out.last_hidden_state * mask).sum(dim=1) / mask.sum(dim=1).clamp(min=1e-9) |
| x = self.dropout(pooled) |
| logit = self.classifier(x).squeeze(-1) |
| return logit |
| |
| tokenizer = AutoTokenizer.from_pretrained("mudotet/humg-cross-encoder", use_fast=False) |
| model = CrossEncoderModel("vinai/phobert-base") |
| state = torch.load("model.pt", map_location="cpu") # download from this repo |
| model.load_state_dict(state) |
| model.eval() |
| |
| # Score a question-passage pair |
| inputs = tokenizer("câu hỏi", "đoạn văn bản", return_tensors="pt", truncation=True, max_length=512) |
| with torch.no_grad(): |
| logit = model(inputs["input_ids"], inputs["attention_mask"]) |
| score = torch.sigmoid(logit).item() |
| print(f"Relevance score: {score:.4f}") |
| ``` |
|
|