-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathreranker.py
More file actions
107 lines (88 loc) · 4.25 KB
/
Copy pathreranker.py
File metadata and controls
107 lines (88 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import json
import torch
from transformers import T5Tokenizer, T5ForConditionalGeneration
from typing import List
import argparse
from tqdm import tqdm
class Reranker:
def __init__(self, model_name_or_path: str, device: str = "cuda"):
"""
Initializes the Reranker with a specified model.
Args:
model_name_or_path (str): Path to the pretrained reranker model.
device (str): Device to load the model on ("cuda" or "cpu").
"""
self.device = device
print(f"Loading reranker model from: {model_name_or_path}")
self.tokenizer = T5Tokenizer.from_pretrained(model_name_or_path)
self.model = T5ForConditionalGeneration.from_pretrained(model_name_or_path)
self.model = self.model.to(self.device)
self.model.eval()
print("Reranker model loaded successfully.")
def rerank(self, query: str, docs: List[dict]) -> List[str]:
"""
Rerank a list of documents based on their relevance to the query.
Args:
query (str): The input query.
docs (List[dict]): A list of documents, each represented as a dictionary with keys "id" and "text".
Returns:
List[str]: A list of relevance labels ("true" or "false") for the documents.
"""
labels = []
inputs = []
# Prepare inputs for the model
for doc in docs:
combined_input = f"Query: {query} Document: {doc['text']} Relevant:"
inputs.append(combined_input)
# Tokenize inputs in batches
batch_size = 128 # Adjust based on available memory
for start in range(0, len(inputs), batch_size):
batch = inputs[start:start + batch_size]
encoded_batch = self.tokenizer.batch_encode_plus(
batch,
return_tensors="pt",
padding=True,
truncation=True,
max_length=512
)
encoded_batch = {k: v.to(self.device) for k, v in encoded_batch.items()}
# Generate labels
with torch.no_grad():
outputs = self.model.generate(
input_ids=encoded_batch["input_ids"],
attention_mask=encoded_batch["attention_mask"],
max_length=2 # Only need a short output like "true" or "false"
)
# Decode generated sequences to labels
decoded_outputs = self.tokenizer.batch_decode(outputs, skip_special_tokens=True)
labels.extend([output.strip().lower() for output in decoded_outputs])
return labels
if __name__ == "__main__":
# Define command-line arguments
parser = argparse.ArgumentParser(description="Reranker Demo")
parser.add_argument("--model_name_or_path", type=str, default="",
help="Path to the pretrained reranker model.")
parser.add_argument("--device", type=str, default="cuda" if torch.cuda.is_available() else "cpu",
help="Device to run the reranker on ('cuda' or 'cpu').")
parser.add_argument("--input_file", type=str, required=True, help="Path to the input JSONL file.")
parser.add_argument("--output_file", type=str, required=True, help="Path to save the output JSONL file.")
args = parser.parse_args()
# Load the reranker model
reranker = Reranker(model_name_or_path=args.model_name_or_path, device=args.device)
# Process JSONL file
with open(args.input_file, "r", encoding='utf-8') as input_file, open(args.output_file, "a", encoding='utf-8') as output_file:
for line in tqdm(input_file):
if not line.strip():
continue
# Parse the JSON object
example = json.loads(line.strip())
query = example["question"]
docs = example["docs"]
# Get rerank labels
rerank_labels = reranker.rerank(query=query, docs=docs)
# Add rerank labels to each document
for doc, label in zip(docs, rerank_labels):
doc["rerank_label"] = label
# Save the updated example to the output file as a JSONL entry
output_file.write(json.dumps(example, ensure_ascii=False) + "\n")
print(f"Reranking completed and saved to {args.output_file}.")