tasksource 0.0.45__tar.gz → 0.0.47__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. {tasksource-0.0.45 → tasksource-0.0.47}/PKG-INFO +1 -1
  2. tasksource-0.0.47/src/tasksource/.ipynb_checkpoints/access-checkpoint.py +112 -0
  3. tasksource-0.0.47/src/tasksource/.ipynb_checkpoints/preprocess-checkpoint.py +295 -0
  4. tasksource-0.0.47/src/tasksource/.ipynb_checkpoints/recast-checkpoint.py +115 -0
  5. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource/.ipynb_checkpoints/tasks-checkpoint.py +64 -17
  6. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource/access.py +4 -0
  7. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource/preprocess.py +33 -5
  8. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource/recast.py +4 -2
  9. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource/tasks.py +64 -17
  10. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource.egg-info/PKG-INFO +1 -1
  11. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource.egg-info/SOURCES.txt +3 -0
  12. tasksource-0.0.47/tasks.md +669 -0
  13. tasksource-0.0.45/tasks.md +0 -660
  14. {tasksource-0.0.45 → tasksource-0.0.47}/.github/scripts/release.py +0 -0
  15. {tasksource-0.0.45 → tasksource-0.0.47}/.github/workflows/python-publish.yml +0 -0
  16. {tasksource-0.0.45 → tasksource-0.0.47}/.github/workflows/release.yml +0 -0
  17. {tasksource-0.0.45 → tasksource-0.0.47}/.gitignore +0 -0
  18. {tasksource-0.0.45 → tasksource-0.0.47}/CITATION.cff +0 -0
  19. {tasksource-0.0.45 → tasksource-0.0.47}/LICENSE +0 -0
  20. {tasksource-0.0.45 → tasksource-0.0.47}/README.md +0 -0
  21. {tasksource-0.0.45 → tasksource-0.0.47}/mtasks.md +0 -0
  22. {tasksource-0.0.45 → tasksource-0.0.47}/pyproject.toml +0 -0
  23. {tasksource-0.0.45 → tasksource-0.0.47}/setup.cfg +0 -0
  24. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource/__init__.py +0 -0
  25. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource/metadata/__init__.py +0 -0
  26. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource/metadata/bigbench_groups.py +0 -0
  27. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource/metadata/blimp_groups.py +0 -0
  28. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource/metadata/original.txt +0 -0
  29. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource/metadata/popularity.py +0 -0
  30. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource/mtasks.py +0 -0
  31. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource.egg-info/dependency_links.txt +0 -0
  32. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource.egg-info/requires.txt +0 -0
  33. {tasksource-0.0.45 → tasksource-0.0.47}/src/tasksource.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tasksource
3
- Version: 0.0.45
3
+ Version: 0.0.47
4
4
  Summary: Preprocessings to prepare datasets for a task
5
5
  Home-page: https://github.com/sileod/tasksource/
6
6
  Classifier: Programming Language :: Python :: 3
@@ -0,0 +1,112 @@
1
+ from .preprocess import Preprocessing
2
+ import re
3
+ import pandas as pd
4
+ from . import tasks, recast
5
+ from .metadata import dataset_rank
6
+ from datasets import load_dataset
7
+ import funcy as fc
8
+ import os
9
+ import copy
10
+ from sorcery import dict_of
11
+ from functools import cache
12
+ import random
13
+
14
+
15
+ class lazy_mtasks:
16
+ def __getattr__(self, name):
17
+ from . import mtasks
18
+ return getattr(mtasks, name)
19
+
20
+ def __dir__(self):
21
+ from . import mtasks
22
+ return dir(mtasks)
23
+ lmtasks=lazy_mtasks()
24
+
25
+ def parse_var_name(s):
26
+ config_name,task_name = None,None
27
+ if '__' in s and '___' not in s: # dataset__task
28
+ dataset_name, task_name = s.split('__')
29
+ elif '__' not in s.replace('___','') and '___' in s: #dataset___config
30
+ dataset_name, config_name = s.split('___')
31
+ elif '___' in s and '__' in s.split('___')[1]: #dataset___config__task
32
+ dataset_name, config_task=s.split('___')
33
+ config_name,task_name = config_task.split('__')
34
+ else: # dataset
35
+ dataset_name = s
36
+ return dataset_name,config_name,task_name
37
+
38
+ def pretty_name(x):
39
+ dn = x.dataset_name.split("/")[-1]
40
+ cn = x.config_name if x.config_name else ""
41
+ tn = x.task_name if x.task_name else ""
42
+ return f"{dn}/{cn}/{tn}".replace('//','/').rstrip('/')
43
+
44
+ @cache
45
+ def list_tasks(tasks_path=f'{os.path.dirname(__file__)}/tasks.py',multilingual=False,instruct=False, excluded=[]):
46
+ if multilingual:
47
+ tasks_path=tasks_path.replace('/tasks.py','/mtasks.py')
48
+ task_order = open(tasks_path).readlines()
49
+ task_order = [x.split('=')[0].rstrip() for x in task_order if '=' in x]
50
+ task_order = [x for x in task_order if x.isidentifier()]
51
+ task_order = fc.flip(dict(enumerate(task_order)))
52
+
53
+ l = []
54
+ _tasks = (lmtasks if multilingual else tasks)
55
+
56
+ for key in dir(_tasks):
57
+ if key not in task_order:
58
+ continue
59
+ value=getattr(_tasks, key)
60
+ if isinstance(value,Preprocessing):
61
+ dataset_name, config_name, task_name = parse_var_name(key)
62
+ dataset_name = (value.dataset_name if value.dataset_name else dataset_name)
63
+ config_name = (value.config_name if value.config_name else config_name)
64
+ hasattr(value,key)
65
+ l+=[{'dataset_name': dataset_name,
66
+ 'config_name' : config_name,
67
+ 'task_name': task_name,
68
+ 'preprocessing_name': key,
69
+ 'task_type': value.__class__.__name__,'mapping': value,
70
+ 'rank':task_order.get(key,None)}]
71
+ df=pd.DataFrame(l).explode('config_name')
72
+ df = df.sort_values('rank').reset_index(drop=True)
73
+ df['id'] = df.apply(lambda x: pretty_name(x), axis=1)
74
+ df.insert(0, 'id', df.pop('id'))
75
+ del df['rank']
76
+ if instruct:
77
+ df=df[df.id.map(lambda x: not any(a in x for a in recast.improper_labels))]
78
+ df=df[df.id.map(lambda x: not any(x in a for a in excluded))]
79
+ return df
80
+
81
+ #task_df =list_tasks()
82
+ #mtask_df =list_tasks(multilingual=True)
83
+
84
+ def dict_to_query(d=dict(), **kwargs):
85
+ d={**d,**kwargs}
86
+ return '&'.join([f'`{k}`=="{v}"' for k,v in d.items()])
87
+
88
+ def load_preprocessing(tasks=tasks, **kwargs):
89
+ _tasks_df = list_tasks(multilingual=tasks==lmtasks)
90
+ y = _tasks_df.copy().query(dict_to_query(**kwargs)).iloc[0]
91
+ preprocessing= copy.copy(getattr(tasks, y.preprocessing_name))
92
+ for c in 'dataset_name','config_name':
93
+ if not isinstance(getattr(preprocessing,c), str):
94
+ setattr(preprocessing,c,getattr(y,c))
95
+ return preprocessing
96
+
97
+ def load_task(id=None, dataset_name=None,config_name=None,task_name=None,preprocessing_name=None,
98
+ max_rows=None, max_rows_eval=None, multilingual=False, instruct=False, seed=0, **load_dataset_kwargs):
99
+ query = dict_of(id, dataset_name, config_name, task_name,preprocessing_name)
100
+ query = {k:v for k,v in query.items() if v}
101
+ _tasks = (lmtasks if multilingual else tasks)
102
+ preprocessing = load_preprocessing(_tasks, **query)
103
+
104
+ if "trust_remote_code" not in load_dataset_kwargs:
105
+ load_dataset_kwargs["trust_remote_code"] = True
106
+
107
+ dataset = load_dataset(preprocessing.dataset_name, preprocessing.config_name, **load_dataset_kwargs)
108
+ dataset= preprocessing(dataset,max_rows, max_rows_eval)
109
+ dataset.task_type = preprocessing.__class__.__name__
110
+ if instruct:
111
+ dataset=recast.recast_instruct(dataset)
112
+ return dataset
@@ -0,0 +1,295 @@
1
+ from collections.abc import Iterable
2
+ from dotwiz import DotWiz
3
+ from dataclasses import dataclass
4
+ from typing import Union
5
+ import itertools
6
+ import funcy as fc
7
+ import exrex
8
+ import magicattr
9
+ import numpy as np
10
+ import copy
11
+ import datasets
12
+ import time
13
+
14
+ MAX_MC_OPTIONS = 4
15
+
16
+ def get_column_names(dataset):
17
+ cn = dataset.column_names
18
+ if type(cn)==dict:
19
+ return set(fc.flatten(cn.values()))
20
+ else:
21
+ return set(cn)
22
+
23
+
24
+ def sample_dataset(dataset,n=10000, n_eval=1000,seed=0):
25
+ for k in dataset:
26
+ n_k=(n if k=='train' else n_eval)
27
+ if n_k and len(dataset[k])>n_k:
28
+ dataset[k]=dataset[k].train_test_split(train_size=n_k,seed=seed)['train']
29
+ return dataset
30
+
31
+ class Preprocessing(DotWiz):
32
+ default_splits = ('train','validation','test')
33
+ _instances = []
34
+
35
+ def __post_init__(self):
36
+ Preprocessing._instances+=[self]
37
+
38
+ @staticmethod
39
+ def __map_to_target(x,fn=lambda x:None, target=None):
40
+ x[target]=fn(x)
41
+ return x
42
+
43
+ def load(self):
44
+ return self(datasets.load_dataset(self.dataset_name,self.config_name))
45
+
46
+ def __call__(self,dataset, max_rows=None, max_rows_eval=None,seed=0):
47
+ dataset = self.pre_process(dataset)
48
+
49
+ # manage splits
50
+ for k,v in zip(self.default_splits, self.splits):
51
+ if v and k!=v:
52
+ dataset[k]=dataset[v]
53
+ del dataset[v]
54
+ if k in dataset and not v: # obfuscated label
55
+ del dataset[k]
56
+ dataset = fix_splits(dataset)
57
+
58
+ for k in list(dataset.keys()):
59
+ if k not in self.default_splits:
60
+ del dataset[k]
61
+ dataset = sample_dataset(dataset, max_rows, max_rows_eval,seed=seed)
62
+
63
+ # field annotated with a string
64
+ substitutions = {v:k for k,v in self.to_dict().items()
65
+ if (k and k not in {'splits','dataset_name','config_name'}
66
+ and type(v)==str and k!=v)}
67
+
68
+ dataset=dataset.remove_columns([c for c in substitutions.values() if c in dataset['train'].features and c not in substitutions])
69
+ dataset=dataset.rename_columns(substitutions)
70
+
71
+ # field annotated with a function
72
+ for k in self.to_dict().keys():
73
+ v=getattr(self, k)
74
+ if callable(v) and k not in {"post_process","pre_process","load"}:
75
+ dataset=dataset.map(self.__map_to_target,
76
+ fn_kwargs={'fn':v,'target':k})
77
+
78
+ dataset=dataset.remove_columns(
79
+ get_column_names(dataset)-set(self.to_dict().keys()))
80
+ dataset = fix_labels(dataset)
81
+ dataset = fix_splits(dataset) # again: label mapping changed
82
+ dataset = self.post_process(dataset)
83
+ return dataset
84
+
85
+
86
+ @dataclass
87
+ class cat(Preprocessing):
88
+ fields:Union[str,list]=None
89
+ separator:str=' '
90
+
91
+ def __call__(self, example=None):
92
+ y=[np.char.array(example[f]) + sep
93
+ for f,sep in zip(self.fields[::-1],itertools.repeat(self.separator))]
94
+ y=list(sum(*y))
95
+ if len(y)==1:
96
+ y=y[0]
97
+ return y
98
+
99
+
100
+ def pretty(f):
101
+ class pretty_f(DotWiz):
102
+ def __init__(self,*args):
103
+ self.__f_arg = f(*args)
104
+ for a in args:
105
+ setattr(self,'value',a)
106
+
107
+ def __call__(self, *args,**kwargs):
108
+ return self.__f_arg(*args,**kwargs)
109
+
110
+ def __repr__(self):
111
+ return f"{self.__f_arg.__qualname__ .split('.')[0]}({self.value})"
112
+ return pretty_f
113
+
114
+ class dotgetter:
115
+ def __init__(self, path=''):
116
+ self.path=path
117
+
118
+ def __bool__(self):
119
+ return bool(self.path)
120
+
121
+ def __getattr__(self, k):
122
+ return self.__class__(f'{self.path}.{k}'.lstrip('.'))
123
+
124
+ def __getitem__(self, i):
125
+ return self.__class__(f'{self.path}[{i}]')
126
+
127
+ def __call__(self, example=None):
128
+ return magicattr.get(DotWiz(example), self.path)
129
+
130
+ def __hash__(self):
131
+ return hash(self.path)
132
+
133
+
134
+ @dataclass
135
+ class ClassificationFields(Preprocessing):
136
+ sentence1:str='sentence1'
137
+ sentence2:str='sentence2'
138
+ labels:str='labels'
139
+
140
+ @dataclass
141
+ class Seq2SeqLMFields(Preprocessing):
142
+ prompt:str='prompt'
143
+ output:str='output'
144
+
145
+ @dataclass
146
+ class TokenClassificationFields(Preprocessing):
147
+ tokens:str='tokens'
148
+ labels:str='labels'
149
+
150
+ @dataclass
151
+ class MultipleChoiceFields(Preprocessing):
152
+ inputs:str='input'
153
+ choices:Iterable=tuple()
154
+ labels:str='labels'
155
+ choices_list:str=None
156
+ def __post_init__(self):
157
+ for i, c in enumerate(self.choices):
158
+ setattr(self,f'choice{i}',c)
159
+ delattr(self,'choices')
160
+ if not self.choices_list:
161
+ delattr(self,'choices_list')
162
+
163
+ def __call__(self,dataset, *args, **kwargs):
164
+ dataset = super().__call__(dataset, *args, **kwargs)
165
+ if self.choices_list:
166
+ dataset = dataset.filter(lambda x: 1<len(x['choices_list']))
167
+ n_options = min([len(x) for k in dataset for x in dataset[k]['choices_list']])
168
+ n_options = min(MAX_MC_OPTIONS,n_options)
169
+ dataset = dataset.map(self.flatten_choice_list, fn_kwargs={'n_options':n_options})
170
+
171
+ else:
172
+ dataset = dataset.map(self.sample_choices, fn_kwargs={'n_options':MAX_MC_OPTIONS})
173
+ return dataset
174
+
175
+ @staticmethod
176
+ def flatten_choice_list(x, n_options=None):
177
+ n_neg = n_options-1 if n_options else None
178
+ choices = x['choices_list']
179
+ label=x['labels']
180
+ neg = choices[:label] + choices[label+1:]
181
+ pos = choices[label]
182
+ x['labels']=0
183
+ x['choices_list']=[pos]+neg[:n_neg]
184
+ for i,o in enumerate(x['choices_list']):
185
+ x[f'choice{i}']=o
186
+ del x['choices_list']
187
+ return x
188
+
189
+ @staticmethod
190
+ def sample_choices(x, n_options=None):
191
+ choices = [x[c] for c in x if 'choice' in c]
192
+ if not MAX_MC_OPTIONS or len(choices)<=n_options:
193
+ return x
194
+ n_neg = n_options-1 if n_options else None
195
+ label=x['labels']
196
+ neg = choices[:label] + choices[label+1:]
197
+ pos = choices[label]
198
+ x['labels']=0
199
+ choices_list=[pos]+neg[:n_neg]
200
+ for c in list(x):
201
+ if 'choice' in c:
202
+ del x[c]
203
+ for i,o in enumerate(choices_list):
204
+ x[f'choice{i}']=o
205
+ return x
206
+
207
+ @dataclass
208
+ class SharedFields:
209
+ splits:list=Preprocessing.default_splits
210
+ dataset_name:str = None
211
+ config_name:str = None
212
+ pre_process: callable = fc.identity
213
+ post_process: callable = fc.identity
214
+ #language:str="en"
215
+
216
+
217
+ @dataclass
218
+ class Classification(SharedFields, ClassificationFields): pass
219
+
220
+ @dataclass
221
+ class MultipleChoice(SharedFields, MultipleChoiceFields): pass
222
+
223
+ @dataclass
224
+ class TokenClassification(SharedFields, TokenClassificationFields): pass
225
+
226
+ @dataclass
227
+ class Seq2SeqLM(SharedFields, Seq2SeqLMFields): pass
228
+
229
+ get=dotgetter()
230
+ constant = pretty(fc.constantly)
231
+ regen = lambda x: list(exrex.generate(x))
232
+
233
+ def name(label_name, classes):
234
+ return lambda x:classes[x[label_name]]
235
+
236
+ def fix_splits(dataset):
237
+
238
+ if len(dataset)==1 and "train" not in dataset:
239
+ k = list(dataset)[0]
240
+ dataset['train'] = copy.deepcopy(dataset[k])
241
+ del dataset[k]
242
+
243
+ if 'auxiliary_train' in dataset:
244
+ del dataset['auxiliary_train']
245
+
246
+ if 'test' in dataset: # manage obfuscated labels
247
+ if 'labels' in dataset['test'].features:
248
+ if len(set(fc.flatten(dataset['test'].to_dict()['labels'])))==1:
249
+ del dataset['test']
250
+
251
+ if 'validation' in dataset and 'train' not in dataset:
252
+ train_validation = dataset['validation'].train_test_split(0.5, seed=0)
253
+ dataset['train'] = train_validation['train']
254
+ dataset['validation']=train_validation['test']
255
+
256
+ if 'validation' in dataset and 'test' not in dataset:
257
+ validation_test = dataset['validation'].train_test_split(0.5, seed=0)
258
+ dataset['validation'] = validation_test['train']
259
+ dataset['test']=validation_test['test']
260
+
261
+ if 'train' in dataset and 'validation' not in dataset:
262
+ train_val = dataset['train'].train_test_split(train_size=0.90, seed=0)
263
+ dataset['train'] = train_val['train']
264
+ dataset['validation']=train_val['test']
265
+
266
+ if 'test' in dataset and 'validation' not in dataset:
267
+ validation_test = dataset['test'].train_test_split(0.5, seed=0)
268
+ dataset['validation'] = validation_test['train']
269
+ dataset['test']=validation_test['test']
270
+
271
+ if 'validation' not in dataset and 'test' not in dataset:
272
+ train_val_test = dataset["train"].train_test_split(train_size=0.90, seed=0)
273
+ val_test = train_val_test["test"].train_test_split(0.5, seed=0)
274
+ dataset["train"] = train_val_test["train"]
275
+ dataset["validation"] = val_test["train"]
276
+ dataset["test"] = val_test["test"]
277
+
278
+ return dataset
279
+
280
+ def fix_labels(dataset, label_key='labels'):
281
+ if type(dataset['train'][label_key][0]) in [int,list,float]:
282
+ return dataset
283
+ labels=set(fc.flatten(dataset[k][label_key] for k in {"train"}))
284
+ if set(labels)=={'entailment','neutral','contradiction'}:
285
+ order=lambda x:dict(fc.flip(enumerate(['entailment','neutral','contradiction']))).get(x,x)
286
+ else:
287
+ order=str
288
+ labels=sorted(labels, key=order)
289
+ dataset=dataset.cast_column(label_key, datasets.ClassLabel(names=labels))
290
+ return dataset
291
+
292
+ def concatenate_dataset_dict(l):
293
+ """Concatenate a list of DatastDict objects sharing same splits and columns."""
294
+ keys=l[0].keys()
295
+ return datasets.DatasetDict({k: datasets.concatenate_datasets([x[k] for x in l]) for k in keys})
@@ -0,0 +1,115 @@
1
+ import random
2
+ from datasets import DatasetDict, Dataset
3
+ from sorcery import dict_of
4
+ import string
5
+
6
+ improper_labels =['recast/recast_kg_relations','linguisticprobing',"lex_glue/scotus",'lexical_relation_classification/ROOT09',"pragmeval/squinky","pragmeval/emobank",'pragmeval/persuasiveness']
7
+ improper_labels += ['glue/stsb', 'sick/relatedness', 'joci', 'utilitarianism', 'amazon_counterfactual/en', 'toxic_conversations', 'ethos/multilabel', 'lex_glue/eurlex', 'lex_glue/unfair_tos', 'app_reviews', 'humicroedit/subtask-1', 'stackoverflow-questions', 'go_emotions/simplified', 'google_wellformed_query', 'has_part', 'blog_authorship_corpus/age', 'promptCoherence', 'Sarcasm_News_Headline', 'auditor_review/demo-org--auditor_review', 'Dynasent_Disagreement', 'Politeness_Disagreement', 'SBIC_Disagreement', 'SChem_Disagreement', 'Dilemmas_Disagreement', 'sts-companion', 'acceptability-prediction', 'chaos-mnli-ambiguity', 'headline_cause/en_simple', 'oasst1_dense_flat', 'civil_comments']
8
+
9
+ improper_labels += ['stsb_multi_mt','MLMA_hate_speech','icl-symbol-tuning-instruct','zero-shot-label-nli']
10
+
11
+ improper_labels += ['essay-scoring','english-grading','HelpSteer','oasst2']
12
+
13
+ def render_options(options):
14
+ options = [f'"{x}"' for x in options]
15
+ return f"{', '.join(options[:-1])} or {options[-1]}"
16
+
17
+ def render_classification(text,options,answer):
18
+ example = 'text_A→text_B' if text.startswith('text_A:') else 'the following'
19
+ inputs = f'With no explanation, label {example} with either {render_options(options)}.\n{text}'
20
+ targets = f"{answer}."
21
+ return dict_of(inputs,targets)
22
+
23
+ def render_token_classification(tokens,options,labels):
24
+ prefix = f'With no explanation, label each line with {render_options(options)} preceded by ":".\n'
25
+ inputs = prefix+"\n".join(tokens)
26
+ targets = "\n".join([':'.join(x) for x in zip(tokens,labels)])
27
+ return dict_of(inputs,targets)
28
+
29
+ def render_multiple_choice(prompt, options, labels):
30
+ inputs=(prompt+'\n' if prompt else '')
31
+ letters = string.ascii_uppercase[:len(options)]
32
+ inputs=f'With no explanation, chose the best option from {render_options(letters)}. {inputs}'
33
+ for letter, option in zip(letters, options):
34
+ inputs+=f'\n{letter}: {option}'
35
+ targets = f'{letters[labels]}.'
36
+ return dict_of(inputs, targets)
37
+
38
+ def negative_sample_options(y, labels,N=4):
39
+ if len(labels)<N:
40
+ return labels
41
+ else:
42
+ return [y]+random.sample([x for x in labels if x!=y], N-1)
43
+
44
+ def shuffle_choices(x):
45
+ choices = sorted([k for k in x if 'choice' in k])
46
+ choices_texts = [x[c] for c in choices]
47
+ correct_choice =choices_texts[x['labels']]
48
+ random.shuffle(choices_texts)
49
+ for c, ct in zip(choices, choices_texts):
50
+ x[c]=ct
51
+ x["labels"]=choices_texts.index(correct_choice)
52
+ return x
53
+
54
+ def recast_dataset_classification_to_mc(dataset,sep="[SEP]",N=4):
55
+
56
+ def recast_split(d,N=N):
57
+ labels = d.features['labels']
58
+ df=d.to_pandas()
59
+ df['inputs'] = df.sentence1
60
+ if "sentence2" in df:
61
+ df['inputs'] +=sep + df.sentence2
62
+
63
+ N=min(N, len(labels.names))
64
+ df['choices']=df.apply(lambda x:negative_sample_options(labels.int2str(x['labels']), labels.names,N),axis=1)
65
+ df['labels']=df.apply(lambda x:x['choices'].index(labels.int2str(x['labels'])),axis=1)
66
+
67
+ for i in range(N):
68
+ df[f'choice{i}']= "This example is " + df.choices.map(lambda x:x[i])
69
+
70
+ choices = [f'choice{i}' for i in range(N)]
71
+ return Dataset.from_pandas(df[['inputs',*choices,'labels']],preserve_index=False)
72
+
73
+ return DatasetDict({k: recast_split(v) for k,v in dataset.items()})
74
+
75
+
76
+ def recast_instruct(dataset):
77
+ features = dataset['train'].features
78
+ labels = features['labels']
79
+
80
+ if "sentence1" in features:
81
+ task_type='Classification'
82
+ if "choice0" in features:
83
+ task_type = "MultipleChoice"
84
+ if "tokens" in features:
85
+ task_type = "TokenClassification"
86
+
87
+ def recast_MultipleChoice(x):
88
+ x=shuffle_choices(x)
89
+ choices = sorted([k for k in x if 'choice' in k])
90
+ if all([x[c] in x['inputs'] for c in choices]):
91
+ return {"inputs":x['inputs'], 'targets': x[f"choice{x['labels']}"].strip()+"."}
92
+ else:
93
+ return render_multiple_choice(x['inputs'],[x[c] for c in choices],x['labels'])
94
+
95
+ def recast_TokenClassification(x):
96
+ distractors = list(labels.feature.names)
97
+ x_labels = [labels.feature.int2str(y) for y in x['labels']]
98
+ labels_set= list({labels.feature.int2str(y) for y in x['labels']})
99
+ options=list(dict.fromkeys(labels_set+distractors))[:max(len(labels_set),10)]
100
+ return render_token_classification(x['tokens'],options,x_labels)
101
+
102
+ def recast_Classification(x):
103
+ if 'sentence2' in x:
104
+ text=f"text_A: {x['sentence1']}\ntext_B: {x['sentence2']}"
105
+ else:
106
+ text=x['sentence1']
107
+
108
+ answer=labels.int2str(x['labels']).strip()
109
+ options= negative_sample_options(answer, labels._int2str)
110
+ return render_classification(text, options, answer)
111
+
112
+ dataset = dataset.map(eval(f"recast_{task_type}"))
113
+ dataset = dataset.remove_columns([k for k in features if k not in ['inputs','targets']])
114
+ return dataset
115
+