anonymous5378 commited on
Commit
bbd6ee6
·
verified ·
1 Parent(s): 30ba075

Create file

Browse files
Files changed (1) hide show
  1. language_model.py +179 -0
language_model.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import logging
4
+
5
+ import pandas as pd
6
+ import torch
7
+ import transformers
8
+ from transformers import AutoTokenizer, AutoConfig, T5ForConditionalGeneration, BartForConditionalGeneration
9
+
10
+
11
+ TASK_PREFIX = {
12
+ "ve": "extract values",
13
+ "ag": "generate attributes",
14
+ "avg": "generate attributes and values",
15
+ "av": "attribute value extraction"
16
+ }
17
+
18
+ ADDITIONAL_SP_TOKENS = {'hl': '<hl>'}
19
+
20
+ def load_language_model(model_id,
21
+ use_auth_token: bool = True,
22
+ ):
23
+ """ Load language model from hugging face hub. """
24
+ tokenizer = AutoTokenizer.from_pretrained(model_id, use_auth_token=use_auth_token)
25
+ config = AutoConfig.from_pretrained(model_id, use_auth_token=use_auth_token)
26
+
27
+ # model class
28
+ if config.model_type == 't5':
29
+ model_class = T5ForConditionalGeneration.from_pretrained
30
+ elif config.model_type == 'bart':
31
+ model_class = BartForConditionalGeneration.from_pretrained
32
+ else:
33
+ raise ValueError(f"Unsupported model type: {config.model_type}")
34
+
35
+ param = {'config': config, "use_auth_token": use_auth_token}
36
+ model = model_class(model_id, **param)
37
+ return tokenizer, model, config
38
+
39
+ class TransformersAVG:
40
+ """ Transformers Language Model for Attribute Value Generation. """
41
+
42
+ def __init__(self,
43
+ model: str = None,
44
+ max_input_length: int = 512,
45
+ max_target_length: int = 256,
46
+ model_ve: str = None,
47
+ max_target_length_ve: int = 34,
48
+ use_auth_token: bool = True,
49
+ is_ag: bool = None,
50
+ is_avg: bool = None,
51
+ is_ve: bool = None,
52
+ is_av: bool = None
53
+ ) -> None:
54
+
55
+ self.is_ag = 'ag' in model.split('-') if is_ag is None else is_ag
56
+ self.is_ve = 'ae' in model.split('-') if is_ve is None else is_ve
57
+ self.is_av = 'av' in model.split('-') if is_av is None else is_av
58
+ self.is_avg = 'avg' in model.split('-') if is_avg is None else is_avg
59
+
60
+ self.model_name = model
61
+ self.max_input_length = max_input_length
62
+ self.max_target_length = max_target_length
63
+ self.model_name_ve = model_ve
64
+ self.max_target_length_ve = max_target_length_ve
65
+ self.__use_auth_token = use_auth_token
66
+
67
+ # load model
68
+ self.tokenizer, self.model, config = load_language_model(
69
+ self.model_name,
70
+ use_auth_token=self.__use_auth_token,
71
+ )
72
+
73
+ # Setup GPU device
74
+ self.device = 'cuda' if torch.cuda.device_count() > 0 else 'cpu'
75
+ self.model.to(self.device)
76
+
77
+ def generate_av_end2end(self,
78
+ context: str,
79
+ num_beams: int = 4,
80
+ splitting_symbol: str = '|'
81
+ ):
82
+ """ Generate attribute value pairs in an end2end fashion. """
83
+ logging.info(f"running model for 'attribute value pair generation'.")
84
+ model_input = self.tokenizer(context, max_length=self.max_input_length, truncation=True,
85
+ padding="max_length")
86
+ model_input = {k:torch.unsqueeze(torch.tensor(v),dim=0) for k,v in model_input.items()}
87
+ outputs = self.model.generate(**model_input, num_beams=num_beams, do_sample=True, max_length=self.max_target_length)
88
+ outputs = self.tokenizer.batch_decode(outputs, skip_special_tokens=True)[0]
89
+ predictions = self.__format_av(outputs)
90
+ return predictions
91
+
92
+ def generate_av_pipeline(self,
93
+ context: str,
94
+ num_beams: int = 4
95
+ ):
96
+ """ Generate attribute value pairs using the pipeline: first extract values then generate attributes """
97
+ logging.info(f"running model for value candidate extraction.")
98
+ # load ve model
99
+ self.ve_tokenizer, self.ve_model, ve_config = load_language_model(
100
+ self.model_name_ve,
101
+ use_auth_token=self.__use_auth_token,
102
+ )
103
+
104
+ # generate values
105
+ model_input = self.ve_tokenizer(context, max_length=self.max_input_length, truncation=True,
106
+ padding="max_length")
107
+ model_input = {k:torch.unsqueeze(torch.tensor(v),dim=0) for k,v in model_input.items()}
108
+ outputs = self.ve_model.generate(**model_input, num_beams=num_beams, do_sample=True, max_length=self.max_target_length_ve)
109
+ outputs = self.ve_tokenizer.batch_decode(outputs, skip_special_tokens=True)[0]
110
+ list_of_values = self.__format_v(outputs)
111
+
112
+ # generate attributes
113
+ list_of_attributes = []
114
+ logging.info(f"running model for attribute generation.")
115
+ list_of_contexts = self.__highlight_value(context, list_of_values)
116
+ model_input = self.tokenizer(list_of_contexts, max_length=self.max_input_length, truncation=True,
117
+ padding="max_length")
118
+ model_input = {k:torch.tensor(v) for k,v in model_input.items()}
119
+ outputs = self.model.generate(**model_input, num_beams=num_beams, do_sample=True, max_length=self.max_target_length)
120
+ outputs = self.tokenizer.batch_decode(outputs, skip_special_tokens=True)
121
+ list_of_attributes.append(outputs)
122
+ list_of_attributes = [pred for preds in list_of_attributes for pred in preds]
123
+ return [(att, val) for att, val in zip(list_of_attributes, list_of_values)]
124
+
125
+ def generate_av_mul(self,
126
+ context: str,
127
+ num_beams: int = 4):
128
+ """ Generate attribute-value pairs using a multi-task approach: same model for attribute genration and value extraction """
129
+ logging.info(f"running model for value extraction.")
130
+ model_input = self.tokenizer(f"extract value {context}", max_length=self.max_input_length, truncation=True,
131
+ padding="max_length")
132
+ model_input = {k:torch.unsqueeze(torch.tensor(v),dim=0) for k,v in model_input.items()}
133
+ outputs = self.model.generate(**model_input, num_beams=num_beams, do_sample=True, max_length=self.max_target_length)
134
+ outputs = self.tokenizer.batch_decode(outputs, skip_special_tokens=True)[0]
135
+ list_of_values = self.__format_v(outputs)
136
+
137
+ # generate attributes
138
+ list_of_attributes = []
139
+ logging.info(f"running model for attribute generation.")
140
+ list_of_contexts = self.__highlight_value(context, list_of_values, prefix=True)
141
+ model_input = self.tokenizer(list_of_contexts, max_length=self.max_input_length, truncation=True,
142
+ padding="max_length")
143
+ model_input = {k:torch.tensor(v) for k,v in model_input.items()}
144
+ outputs = self.model.generate(**model_input, num_beams=num_beams, do_sample=True, max_length=self.max_target_length)
145
+ outputs = self.tokenizer.batch_decode(outputs, skip_special_tokens=True)
146
+ list_of_attributes.append(outputs)
147
+ list_of_attributes = [pred for preds in list_of_attributes for pred in preds]
148
+ return [(att, val) for att, val in zip(list_of_attributes, list_of_values)]
149
+
150
+ def __highlight_value(self,
151
+ context: str,
152
+ list_of_values: list,
153
+ prefix: bool = False
154
+ ):
155
+ list_of_contexts = []
156
+ for value in list_of_values:
157
+ my_context = context.replace(value, f'<hl> {value} <hl>')
158
+ if prefix:
159
+ my_context = f"generate attribute {my_context}"
160
+ list_of_contexts.append(my_context)
161
+ return list_of_contexts
162
+
163
+ def __format_v(self, predictions: str, splitting_symbol: str = '|') -> list:
164
+ my_list = []
165
+ for raw_string in predictions.split(splitting_symbol):
166
+ v = raw_string.strip()
167
+ my_list.append(v)
168
+ return my_list
169
+
170
+ def __format_av(self, predictions: str, splitting_symbol: str = '|') -> list:
171
+ my_list = []
172
+ for raw_string in predictions.split(splitting_symbol):
173
+ a = raw_string.replace('attribute: ', '')
174
+ a = a.split(',')[0].strip()
175
+ v = raw_string.replace('value: ', '')
176
+ v = v.split(',')[1].strip()
177
+ my_list.append((a,v))
178
+
179
+ return my_list