From 93a03c5bf7dd4ecde8f6dacf35b36df16192750f Mon Sep 17 00:00:00 2001 From: Delaram Rajaei <48606206+DelaramRajaei@users.noreply.github.com> Date: Fri, 27 Oct 2023 16:27:35 -0400 Subject: [PATCH 1/5] Debugging Update some files and solve issues. --- environment.yml | 2 +- src/dal/ds.py | 7 ++++--- src/dal/msmarco.py | 2 +- src/main.py | 45 ++++++++++++++++++++++++--------------------- src/stats/stats.py | 2 +- 5 files changed, 31 insertions(+), 27 deletions(-) diff --git a/environment.yml b/environment.yml index f59e4d4..6c33716 100644 --- a/environment.yml +++ b/environment.yml @@ -1,4 +1,4 @@ -name: repair +name: Repair channels: - conda-forge - pytorch diff --git a/src/dal/ds.py b/src/dal/ds.py index ad7b6f2..56737b2 100644 --- a/src/dal/ds.py +++ b/src/dal/ds.py @@ -1,6 +1,7 @@ import json, pandas as pd from tqdm import tqdm from os.path import isfile,join +import os from pyserini.search.lucene import LuceneSearcher from pyserini.search.faiss import FaissSearcher, TctColBertQueryEncoder @@ -50,7 +51,7 @@ def search(cls, in_query, out_docids, qids, ranker='bm25', topk=100, batch=None, cls.search_df(queries, out_docids, qids, ranker=ranker, topk=topk, batch=batch, ncores=ncores, index=index) @classmethod - def search_df(cls, queries, out_docids, qids, ranker='bm25', topk=100, batch=None, ncores=1, index=None,encoder=None): + def search_df(cls, queries, out_docids, qids, ranker='bm25', topk=100, batch=None, ncores=1, index=None, encoder=None): if not cls.searcher: if ranker == 'tct_colbert': @@ -88,7 +89,7 @@ def _docids(row): hits = cls.searcher.search(row.query, k=topk, remove_dups=True) for i, h in enumerate(hits): o.write(f'{qids[row.name]}\tQ0\t{h.docid:7}\t{i + 1:2}\t{h.score:.5f}\tPyserini\n') - queries.progress_apply(_docids, axis=1) + queries.apply(_docids, axis=1) @classmethod def aggregate(cls, original, changes, output, is_large_ds=False): @@ -101,7 +102,7 @@ def aggregate(cls, original, changes, output, is_large_ds=False): if is_large_ds: pred_metric_values = pd.read_csv(join(output, metric_value), sep='\t', usecols=[1, 2], names=['qid', f'{change}.{ranker}.{metric}'], index_col=False, dtype={'qid': str}) else: - pred_metric_values = pd.read_csv(join(output, metric_value), sep='\t', usecols=[1, 2], names=['qid', f'{change}.{ranker}.{metric}'], index_col=False,skipfooter=1, dtype={'qid': str}) + pred_metric_values = pd.read_csv(join(output, metric_value), sep='\t', usecols=[1, 2], names=['qid', f'{change}.{ranker}.{metric}'], index_col=False,skipfooter=1, dtype={'qid': str}, engine='python') original[change] = pred # to know the actual change original = original.merge(pred_metric_values, how='left', on='qid') # to know the metric value of the change original[f'{change}.{ranker}.{metric}'].fillna(0, inplace=True) diff --git a/src/dal/msmarco.py b/src/dal/msmarco.py index c6ac671..8266703 100644 --- a/src/dal/msmarco.py +++ b/src/dal/msmarco.py @@ -18,7 +18,7 @@ def pair(cls, input, output, cat=True): qrels.to_csv(f'{input}/qrels.train.tsv_', index=False, sep='\t', header=False) # trec_eval.9.0.4 does not accept duplicate rows!! queries_qrels = pd.merge(queries, qrels, on='qid', how='inner', copy=False) doccol = 'docs' if cat else 'doc' - queries_qrels[doccol] = queries_qrels['pid'].progress_apply(cls._txt) # 100%|██████████| 532761/532761 [00:32<00:00, 16448.77it/s] + queries_qrels[doccol] = queries_qrels['pid'].apply(cls._txt) # 100%|██████████| 532761/532761 [00:32<00:00, 16448.77it/s] queries_qrels['ctx'] = '' if cat: queries_qrels = queries_qrels.groupby(['qid', 'query'], as_index=False, observed=True).agg({'did': list, 'pid': list, doccol: ' '.join}) queries_qrels.to_csv(output, sep='\t', encoding='utf-8', index=False) diff --git a/src/main.py b/src/main.py index 0f94593..5f3852b 100644 --- a/src/main.py +++ b/src/main.py @@ -43,6 +43,7 @@ def run(data_list, domain_list, output, settings): t5_model = settings['t5model'] # {"small", "base", "large", "3B", "11B"} cross {"local", "gc"} t5_output = f'../output/{os.path.split(datapath)[-1]}/{ds.user_pairing}t5.{t5_model}.{in_type}.{out_type}.{index_item_str}' if not os.path.isdir(t5_output): os.makedirs(t5_output) + copyfile('./param.py', f'{t5_output}/param.py') if {'finetune', 'predict'} & set(settings['cmd']): from mdl import mt5w @@ -69,33 +70,37 @@ def run(data_list, domain_list, output, settings): print(f"Searching documents for query changes using {settings['ranker']} ...") # seems for some queries there is no qrels, so they are missed for t5 prediction. # query_originals = pd.read_csv(f'{datapath}/queries.train.tsv', sep='\t', names=['qid', 'query'], dtype={'qid': str}) - # we use the file after panda.merge that create the training set so we make sure the mapping of qids + # we use the file after panda.merge that create the training set, so we make sure the mapping of qids query_originals = pd.read_csv(f'{prep_output}/{ds.user_pairing}queries.qrels.doc{"s" if "docs" in {in_type, out_type} else ""}.ctx.{index_item_str}.train.tsv', sep='\t', usecols=['qid', 'query'], dtype={'qid': str}) - if settings['large_ds']: # we can run this logic if shape of query_originals is greater than split_size + + original_dir = f'{t5_output}/original' + if not os.path.isdir(original_dir): os.makedirs(original_dir) + + # we can run this logic if shape of query_originals is greater than split_size + if settings['large_ds']: import numpy as np import glob split_size = 1000000 # need to make this dynamic based on shape of query_originals. for _, chunk in query_originals.groupby(np.arange(query_originals.shape[0]) // split_size): - file_changes = [(file, f'{file}.{settings["ranker"]}') for file in - glob.glob(f'{t5_output}/**/pred.{_}*') if f'{file}.{settings["ranker"]}' not in glob.glob(f'{t5_output}/**')] + # Generate original queries' files + original_file_i = f'{original_dir}/original.{_}.tsv' + chunk[['query']].to_csv(original_file_i, sep='\t', index=False, header=False) + + file_changes = [(file, f'{file}.{settings["ranker"]}') for file in glob.glob(f'{t5_output}/**/pred.{_}*') if f'{file}.{settings["ranker"]}' not in glob.glob(f'{t5_output}/**')] chunk.drop_duplicates(subset=['qid'], inplace=True) # in the event there are duplicates in query qrels. with mp.Pool(settings['ncore']) as p: - p.starmap(partial(ds.search, qids=chunk['qid'].values.tolist(), ranker=settings['ranker'], - topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore'], - index=ds.searcher.index_dir), file_changes) + p.starmap(partial(ds.search, qids=chunk['qid'].values.tolist(), ranker=settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore'], index=ds.searcher.index_dir), file_changes) - print('for original queries') + print('For original queries') file_changes = list() for _, chunk in query_originals.groupby(np.arange(query_originals.shape[0]) // split_size): chunk.drop_duplicates(subset=['qid'], inplace=True) - file_changes.append((f'{t5_output}/original/original.{_}.tsv', - f'{t5_output}/original/original.{_}.tsv.bm25', chunk['qid'].values.tolist())) + file_changes.append((f'{t5_output}/original/original.{_}.tsv', f'{t5_output}/original/original.{_}.tsv.bm25', chunk['qid'].values.tolist())) with mp.Pool(settings['ncore']) as p: p.starmap(partial(ds.search, ranker=settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore'], index=ds.searcher.index_dir), file_changes) + else: - query_changes = [(f'{t5_output}/{f}', f'{t5_output}/{f}.{settings["ranker"]}') for f in - listdir(t5_output) if - isfile(join(t5_output, f)) and f.startswith('pred.') and len(f.split('.')) == 2 and f'{f}.{settings["ranker"]}' not in listdir(t5_output)] + query_changes = [(f'{t5_output}/{f}', f'{t5_output}/{f}.{settings["ranker"]}') for f in listdir(t5_output) if isfile(join(t5_output, f)) and f.startswith('pred.') and len(f.split('.')) == 2 and f'{f}.{settings["ranker"]}' not in listdir(t5_output)] # for (i, o) in query_changes: ds.search(i, o, query_originals['qid'].values.tolist(), settings['ranker'], topk=settings['topk'], batch=settings['batch']) # batch search: @@ -103,14 +108,13 @@ def run(data_list, domain_list, output, settings): # seems the LuceneSearcher cannot be shared in multiple processes! See dal.ds.py # parallel on each file ==> Problem: starmap does not understand inherited Dataset.searcher attribute! with mp.Pool(settings['ncore']) as p: - p.starmap(partial(ds.search, qids=query_originals['qid'].values.tolist(), ranker=settings['ranker'], - topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore'], - index=None), query_changes) + p.starmap(partial(ds.search, qids=query_originals['qid'].values.tolist(), ranker=settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore'], index=ds.searcher.index_dir), query_changes) # we need to add the original queries as well - if not isfile(join(t5_output, f'original.{settings["ranker"]}')): - query_originals.to_csv(f'{t5_output}/original', columns=['query'], index=False, header=False) - ds.search_df(pd.DataFrame(query_originals['query']), f'{t5_output}/original.{settings["ranker"]}', query_originals['qid'].values.tolist(), settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore']) + original_path = f'{t5_output}/original.{settings["ranker"]}' + if not isfile(original_path): + query_originals[['query']].to_csv(original_path, sep='\t', index=False, header=False) + ds.search_df(pd.DataFrame(query_originals['query']), original_path, query_originals['qid'].values.tolist(), settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore']) if 'eval' in settings['cmd']: from evl import trecw @@ -251,8 +255,7 @@ def run(data_list, domain_list, output, settings): agg_df['pred_sparse'] = original[f'{ranker}.{metric}_'] agg_df.to_csv(f'{t5_output}/colbert.comparison.{condition}.{metric}.tsv', sep="\t", index=None) - if 'stats' in settings['cmd']: - from stats import stats + if 'stats' in settings['cmd']: from stats import stats def addargs(parser): diff --git a/src/stats/stats.py b/src/stats/stats.py index 4dcff55..9e3bb26 100644 --- a/src/stats/stats.py +++ b/src/stats/stats.py @@ -10,7 +10,7 @@ def plot_stats(box_path): for ds in datasets: map_ds = pd.read_csv(f'{box_path}/{ds}.tsv', sep='\t', encoding='utf-8', names=['qid', 'i', 'i_map', 't', 't_map']) map_ds.sort_values(by='i_map', inplace=True) - stats = map_ds.groupby(np.arange(len(map_ds)) // (len(map_ds) / 10)).mean() + stats = map_ds.groupby(np.arange(len(map_ds)) // (len(map_ds) / 10)).mean(numeric_only=True) X = [x for x in range(1, 11)] original_mean = stats['i_map'] changes_mean = stats['t_map'] From c24a58462cd85303df55320511ffc583d7bdd4f5 Mon Sep 17 00:00:00 2001 From: Delaram Rajaei <48606206+DelaramRajaei@users.noreply.github.com> Date: Wed, 1 Nov 2023 18:30:05 -0400 Subject: [PATCH 2/5] Add refinement add query class add files related to refinement update param.py file --- src/Query.py | 10 + src/param.py | 115 +++- src/refinement/param.py | 46 ++ src/refinement/refiner_factory.py | 55 ++ src/refinement/refiners/__init__.py | 0 src/refinement/refiners/abstractqrefiner.py | 217 +++++++ src/refinement/refiners/adaponfields.py | 163 ++++++ src/refinement/refiners/anchor.py | 69 +++ src/refinement/refiners/backtranslation.py | 51 ++ src/refinement/refiners/bertqe.py | 107 ++++ src/refinement/refiners/conceptluster.py | 50 ++ src/refinement/refiners/conceptnet.py | 62 ++ src/refinement/refiners/docluster.py | 127 ++++ src/refinement/refiners/expanders.csv | 59 ++ src/refinement/refiners/glove.py | 70 +++ src/refinement/refiners/onfields.py | 271 +++++++++ src/refinement/refiners/relevancefeedback.py | 86 +++ src/refinement/refiners/rm3.py | 53 ++ .../refiners/sensedisambiguation.py | 36 ++ src/refinement/refiners/stem.py | 49 ++ src/refinement/refiners/tagmee.py | 43 ++ src/refinement/refiners/termluster.py | 111 ++++ src/refinement/refiners/thesaurus.py | 79 +++ src/refinement/refiners/wiki.py | 82 +++ src/refinement/refiners/word2vec.py | 51 ++ src/refinement/refiners/wordnet.py | 48 ++ src/refinement/stemmers/__init__.py | 0 src/refinement/stemmers/abstractstemmer.py | 63 ++ src/refinement/stemmers/krovetz.py | 27 + src/refinement/stemmers/kstem-3.4.jar | Bin 0 -> 327037 bytes src/refinement/stemmers/lovins.py | 19 + src/refinement/stemmers/lovinsstemmer.py | 542 ++++++++++++++++++ src/refinement/stemmers/nostemmer.py | 18 + src/refinement/stemmers/paicehusk.py | 19 + src/refinement/stemmers/paicehuskstemmer.py | 254 ++++++++ src/refinement/stemmers/porter.py | 19 + src/refinement/stemmers/porter2.py | 19 + src/refinement/stemmers/porter2stemmer.py | 288 ++++++++++ src/refinement/stemmers/porterstemmer.py | 188 ++++++ src/refinement/stemmers/sstemmer.py | 28 + src/refinement/stemmers/trunc4.py | 24 + src/refinement/stemmers/trunc5.py | 24 + src/refinement/utils.py | 139 +++++ 43 files changed, 3775 insertions(+), 6 deletions(-) create mode 100644 src/Query.py create mode 100644 src/refinement/param.py create mode 100644 src/refinement/refiner_factory.py create mode 100644 src/refinement/refiners/__init__.py create mode 100644 src/refinement/refiners/abstractqrefiner.py create mode 100644 src/refinement/refiners/adaponfields.py create mode 100644 src/refinement/refiners/anchor.py create mode 100644 src/refinement/refiners/backtranslation.py create mode 100644 src/refinement/refiners/bertqe.py create mode 100644 src/refinement/refiners/conceptluster.py create mode 100644 src/refinement/refiners/conceptnet.py create mode 100644 src/refinement/refiners/docluster.py create mode 100644 src/refinement/refiners/expanders.csv create mode 100644 src/refinement/refiners/glove.py create mode 100644 src/refinement/refiners/onfields.py create mode 100644 src/refinement/refiners/relevancefeedback.py create mode 100644 src/refinement/refiners/rm3.py create mode 100644 src/refinement/refiners/sensedisambiguation.py create mode 100644 src/refinement/refiners/stem.py create mode 100644 src/refinement/refiners/tagmee.py create mode 100644 src/refinement/refiners/termluster.py create mode 100644 src/refinement/refiners/thesaurus.py create mode 100644 src/refinement/refiners/wiki.py create mode 100644 src/refinement/refiners/word2vec.py create mode 100644 src/refinement/refiners/wordnet.py create mode 100644 src/refinement/stemmers/__init__.py create mode 100644 src/refinement/stemmers/abstractstemmer.py create mode 100644 src/refinement/stemmers/krovetz.py create mode 100644 src/refinement/stemmers/kstem-3.4.jar create mode 100644 src/refinement/stemmers/lovins.py create mode 100644 src/refinement/stemmers/lovinsstemmer.py create mode 100644 src/refinement/stemmers/nostemmer.py create mode 100644 src/refinement/stemmers/paicehusk.py create mode 100644 src/refinement/stemmers/paicehuskstemmer.py create mode 100644 src/refinement/stemmers/porter.py create mode 100644 src/refinement/stemmers/porter2.py create mode 100644 src/refinement/stemmers/porter2stemmer.py create mode 100644 src/refinement/stemmers/porterstemmer.py create mode 100644 src/refinement/stemmers/sstemmer.py create mode 100644 src/refinement/stemmers/trunc4.py create mode 100644 src/refinement/stemmers/trunc5.py create mode 100644 src/refinement/utils.py diff --git a/src/Query.py b/src/Query.py new file mode 100644 index 0000000..319ce1d --- /dev/null +++ b/src/Query.py @@ -0,0 +1,10 @@ +class Query: + + def __init__(self, dataset_name, q, qid, time=None, user_id=None): + self.dataset_name = dataset_name + self.qid = qid + self.q = q + + # Features + self.user_id = user_id + self.time = time diff --git a/src/param.py b/src/param.py index 12b033b..7a46d86 100644 --- a/src/param.py +++ b/src/param.py @@ -9,20 +9,24 @@ os.environ['CUDA_VISIBLE_DEVICES'] = '-1' settings = { - 'cmd': ['stats'], # steps of pipeline, ['pair', 'finetune', 'predict', 'search', 'eval','agg', 'box','dense_retrieve'] + 'query_refinement': True, + 'cmd': ['pair', 'finetune', 'predict', 'search', 'eval','agg', 'box'], # steps of pipeline, ['pair', 'finetune', 'predict', 'search', 'eval','agg', 'box','dense_retrieve', 'stats] 'ncore': 2, - 't5model': 'base.gc', # 'base.gc' on google cloud tpu, 'small.local' on local machine + 't5model': 'small.local', # 'base.gc' on google cloud tpu, 'small.local' on local machine 'iter': 5, # number of finetuning iteration for t5 'nchanges': 5, # number of changes to a query 'ranker': 'bm25', # 'qld', 'bm25', 'tct_colbert' 'batch': None, # search per batch of queries for IR search using pyserini, if None, search per query 'topk': 100, # number of retrieved documents for a query - 'metric': 'recip_rank.10', # any valid trec_eval.9.0.4 metric like map, ndcg, recip_rank, ... - 'large_ds': True, + 'metric': 'map', # any valid trec_eval.9.0.4 metric like map, ndcg, recip_rank, ... + 'large_ds': False, 'treclib': f'"./trec_eval.9.0.4/trec_eval{extension}"', # in non-windows, remove .exe, also for pytrec_eval, 'pytrec' 'box': {'gold': 'refined_q_metric >= original_q_metric and refined_q_metric > 0', 'platinum': 'refined_q_metric > original_q_metric', - 'diamond': 'refined_q_metric > original_q_metric and refined_q_metric == 1'}, + 'diamond': 'refined_q_metric > original_q_metric and refined_q_metric == 1'} +} + +corpora = { 'msmarco.passage': { 'index_item': ['passage'], 'index': '../data/raw/msmarco.passage/lucene-index.msmarco-v1-passage.20220131.9ea315/', @@ -39,5 +43,104 @@ 'pairing': [None, 'docs', 'query'], # [context={2 scenarios, one with userID and one without userID). input={'userid','query','doc(s)'} output={'query','doc(s)'} 'lseq': {"inputs": 32, "targets": 256}, # query length and doc length for t5 model, 'filter': {'minql': 1, 'mindocl': 10} # [min query length, min doc length], after merge queries with relevant 'index_item', if |query| <= minql drop the row, if |'index_item'| < mindocl, drop row - } + }, + 'robust04': { + 'index': '../ds/robust04/lucene-index.robust04.pos+docvectors+rawdocs', + 'dense_index': '../ds/robust04/faiss_index_robust04', + 'encoded': '../ds/robust04/encoded_robust04', + 'size': 528155, + 'topics': '../ds/robust04/topics.robust04.txt', + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 2.25, # OnFields + 'w_a': 1, # OnFields + 'tokens': 148000000, + 'qrels': '../ds/robust04/qrels.robust04.txt', + 'extcorpus': 'gov2', # AdaptOnFields + }, + 'gov2': { + 'index': '../ds/gov2/lucene-index.gov2.pos+docvectors+rawdocs', + 'size': 25000000, + 'topics': '../ds/gov2/topics.terabyte0{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 4, # OnFields + 'w_a': 0.25, # OnFields + 'tokens': 17000000000, + 'qrels': '../ds/gov2/qrels.terabyte0{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'extcorpus': 'robust04', # AdaptOnFields + }, + 'clueweb09b': { + 'index': '../ds/clueweb09b/lucene-index.cw09b.pos+docvectors+rawdocs', + 'size': 50000000, + 'topics': '../ds/clueweb09b/topics.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 1, # OnFields + 'w_a': 0, # OnFields + 'tokens': 31000000000, + 'qrels': '../ds/clueweb09b/qrels.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'extcorpus': 'gov2', # AdaptOnFields + }, + 'clueweb12b13': { + 'index': '../ds/clueweb12b13/lucene-index.cw12b13.pos+docvectors+rawdocs', + 'size': 50000000, + 'topics': '../ds/clueweb12b13/topics.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 4, # OnFields + 'w_a': 0, # OnFields + 'tokens': 31000000000, + 'qrels': '../ds/clueweb12b13/qrels.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'extcorpus': 'gov2', # AdaptOnFields + }, + 'antique': { + 'index': '../ds/antique/lucene-index-antique', + 'size': 403000, + 'topics': '../ds/antique/topics.antique.txt', + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 2.25, # OnFields # to be tuned + 'w_a': 1, # OnFields # to be tuned + 'tokens': 16000000, + 'qrels': '../ds/antique/qrels.antique.txt', + 'extcorpus': 'gov2', # AdaptOnFields + }, + 'trec09mq': { + 'index': 'D:\clueweb09b\lucene-index.cw09b.pos+docvectors+rawdocs', + 'size': 50000000, + # 'topics': '../ds/trec2009mq/prep/09.mq.topics.20001-60000.prep.tsv', + 'topics': '../ds/trec09mq/09.mq.topics.20001-60000.prep', + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 2.25, # OnFields # to be tuned + 'w_a': 1, # OnFields # to be tuned + 'tokens': 16000000, + 'qrels': '../ds/trec09mq/prels.20001-60000.prep', + 'extcorpus': 'gov2', # AdaptOnFields + }, + 'dbpedia': { + 'index': '../ds/dbpedia/lucene-index-dbpedia-collection', + 'size': 4632359, + 'topics': '../ds/dbpedia/topics.dbpedia.txt', + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 1, # OnFields # to be tuned + 'w_a': 1, # OnFields # to be tuned + 'tokens': 200000000, + 'qrels': '../ds/dbpedia/qrels.dbpedia.txt', + 'extcorpus': 'gov2', # AdaptOnFields + }, + 'orcas': { + 'index': '../ds/orcas/lucene-index.msmarco-v1-doc.20220131.9ea315', + 'size': 50000000, + # 'topics': '../ds/trec2009mq/prep/09.mq.topics.20001-60000.prep.tsv', + 'topics': '../ds/orcas/preprocess/orcas-I-2M_topics.prep', + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 2.25, # OnFields # to be tuned + 'w_a': 1, # OnFields # to be tuned + 'tokens': 16000000, + 'qrels': '../ds/orcas/preprocess/orcas-doctrain-qrels.prep', + 'extcorpus': 'gov2', # AdaptOnFields + }, } + +# Only for sparse indexing +anserini = { + 'path': '../anserini/', + 'trec_eval': '../anserini/eval/trec_eval.9.0.4/trec_eval' +} + diff --git a/src/refinement/param.py b/src/refinement/param.py new file mode 100644 index 0000000..f34ac20 --- /dev/null +++ b/src/refinement/param.py @@ -0,0 +1,46 @@ +import sys, platform + +extension = '.exe' if platform.system() == 'Windows' else "" + +refiners = { + 'SenseDisambiguation': 0, + 'Thesaurus': 0, + 'Wordnet': 0, + 'Conceptnet': 0, + 'Tagmee': 0, + + 'Word2Vec': 0, + 'Glove': 0, + 'Anchor': 0, + 'Wiki': 0, + + 'KrovetzStemmer': 0, + 'LovinsStemmer': 0, + 'PaiceHuskStemmer': 0, + 'PorterStemmer': 0, + 'Porter2Stemmer': 0, + 'SRemovalStemmer': 0, + 'Trunc4Stemmer': 0, + 'Trunc5Stemmer': 0, + + 'RelevanceFeedback': 0, + 'Docluster': 0, + 'Termluster': 0, + 'Conceptluster': 0, + 'OnFields': 0, # make sure that the index for 'extcorpus' is available + 'AdapOnFields': 0, # make sure that the index for 'extcorpus' is available + 'BertQE': 0, + 'RM3': 0, + + 'BackTranslation': 1, + } + +# Backtranslation settings +backtranslation = { + 'src_lng': 'eng_Latn', + 'tgt_lng': ['fra_Latn'], # ['yue_Hant', 'kor_Hang', 'arb_Arab', 'pes_Arab', 'fra_Latn', 'deu_Latn', 'rus_Cyrl', 'zsm_Latn', 'tam_Taml', 'swh_Latn'] + 'max_length': 512, + 'device': 'cpu', + 'model_card': 'facebook/nllb-200-distilled-600M', + 'transformer_model': 'johngiorgi/declutr-small', +} diff --git a/src/refinement/refiner_factory.py b/src/refinement/refiner_factory.py new file mode 100644 index 0000000..da06347 --- /dev/null +++ b/src/refinement/refiner_factory.py @@ -0,0 +1,55 @@ +from refiners.abstractqrefiner import AbstractQRefiner +from refiners.stem import Stem # Stem refiner is the wrapper for all stemmers as an refiner :) +import param +import utils + +#global analysis +def get_nrf_refiner(): + refiners_list = [AbstractQRefiner()] + if param.refiners['Thesaurus']: from refiners.thesaurus import Thesaurus; refiners_list.append(Thesaurus()) + if param.refiners['Thesaurus']: from refiners.thesaurus import Thesaurus; refiners_list.append(Thesaurus(replace=True)) + if param.refiners['Wordnet']: from refiners.wordnet import Wordnet; refiners_list.append(Wordnet()) + if param.refiners['Wordnet']: from refiners.wordnet import Wordnet; refiners_list.append(Wordnet(replace=True)) + if param.refiners['Word2Vec']: from refiners.word2vec import Word2Vec; refiners_list.append(Word2Vec('../pre/wiki-news-300d-1M.vec')) + if param.refiners['Word2Vec']: from refiners.word2vec import Word2Vec; refiners_list.append(Word2Vec('../pre/wiki-news-300d-1M.vec', replace=True)) + if param.refiners['Glove']: from refiners.glove import Glove; refiners_list.append(Glove('../pre/glove.6B.300d')) + if param.refiners['Glove']: from refiners.glove import Glove; refiners_list.append(Glove('../pre/glove.6B.300d', replace=True)) + if param.refiners['Anchor']: from refiners.anchor import Anchor; refiners_list.append(Anchor(anchorfile='../pre/anchor_text_en.ttl', vectorfile='../pre/wiki-anchor-text-en-ttl-300d.vec')) + if param.refiners['Anchor']: from refiners.anchor import Anchor; refiners_list.append(Anchor(anchorfile='../pre/anchor_text_en.ttl', vectorfile='../pre/wiki-anchor-text-en-ttl-300d.vec', replace=True)) + if param.refiners['Wiki']: from refiners.wiki import Wiki; refiners_list.append(Wiki('../pre/temp_model_Wiki')) + if param.refiners['Wiki']: from refiners.wiki import Wiki; refiners_list.append(Wiki('../pre/temp_model_Wiki', replace=True)) + if param.refiners['Tagmee']: from refiners.tagmee import Tagmee; refiners_list.append(Tagmee()) + if param.refiners['Tagmee']: from refiners.tagmee import Tagmee; refiners_list.append(Tagmee(replace=True)) + if param.refiners['SenseDisambiguation']: from refiners.sensedisambiguation import SenseDisambiguation; refiners_list.append(SenseDisambiguation()) + if param.refiners['SenseDisambiguation']: from refiners.sensedisambiguation import SenseDisambiguation; refiners_list.append(SenseDisambiguation(replace=True)) + if param.refiners['Conceptnet']: from refiners.conceptnet import Conceptnet; refiners_list.append(Conceptnet()) + if param.refiners['Conceptnet']: from refiners.conceptnet import Conceptnet; refiners_list.append(Conceptnet(replace=True)) + if param.refiners['KrovetzStemmer']: from stemmers.krovetz import KrovetzStemmer; refiners_list.append(Stem(KrovetzStemmer(jarfile='stemmers/kstem-3.4.jar'))) + if param.refiners['LovinsStemmer']: from stemmers.lovins import LovinsStemmer; refiners_list.append(Stem(LovinsStemmer())) + if param.refiners['PaiceHuskStemmer']: from stemmers.paicehusk import PaiceHuskStemmer; refiners_list.append(Stem(PaiceHuskStemmer())) + if param.refiners['PorterStemmer']: from stemmers.porter import PorterStemmer; refiners_list.append(Stem(PorterStemmer())) + if param.refiners['Porter2Stemmer']: from stemmers.porter2 import Porter2Stemmer; refiners_list.append(Stem(Porter2Stemmer())) + if param.refiners['SRemovalStemmer']: from stemmers.sstemmer import SRemovalStemmer; refiners_list.append(Stem(SRemovalStemmer())) + if param.refiners['Trunc4Stemmer']: from stemmers.trunc4 import Trunc4Stemmer; refiners_list.append(Stem(Trunc4Stemmer())) + if param.refiners['Trunc5Stemmer']: from stemmers.trunc5 import Trunc5Stemmer; refiners_list.append(Stem(Trunc5Stemmer())) + if param.refiners['BackTranslation']: from refiners.backtranslation import BackTranslation; refiners_list.extend([BackTranslation(each_lng) for index, each_lng in enumerate(param.backtranslation['tgt_lng'])]) + # since RF needs index and search output which depends on ir method and topics corpora, we cannot add this here. Instead, we run it individually + # RF assumes that there exist abstractqueryexpansion files + + return refiners_list + +#local analysis +def get_rf_refiner(rankers, corpus, output, ext_corpus=None): + refiners_list = [] + for ranker in rankers: + ranker_name = utils.get_ranker_name(ranker) + if param.refiners['RM3']: from refiners.rm3 import RM3; refiners_list.append(RM3(ranker=ranker_name, index=corpus['index'])) + if param.refiners['RelevanceFeedback']: from refiners.relevancefeedback import RelevanceFeedback; refiners_list.append(RelevanceFeedback(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=param.anserini['path'], index=corpus['index'])) + if param.refiners['Docluster']: from refiners.docluster import Docluster; refiners_list.append(Docluster(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=param.anserini['path'], index=corpus['index'])), + if param.refiners['Termluster']: from refiners.termluster import Termluster; refiners_list.append(Termluster(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=param.anserini['path'], index=corpus['index'])) + if param.refiners['Conceptluster']: from refiners.conceptluster import Conceptluster; refiners_list.append(Conceptluster(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=param.anserini['path'], index=corpus['index'])) + if param.refiners['BertQE']: from refiners.bertqe import BertQE; refiners_list.append(BertQE(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), index=corpus['index'], anserini=param.anserini['path'])) + if param.refiners['OnFields']: from refiners.onfields import OnFields; refiners_list.append(OnFields(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=param.anserini['path'], index=param.corpora[corpus]['index'], w_t=corpus['w_t'], w_a=corpus['w_a'], corpus_size=corpus['size'])) + if param.refiners['AdapOnFields']: from refiners.adaponfields import AdapOnFields; refiners_list.append(AdapOnFields(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=param.anserini['path'], index=corpus['index'], w_t=corpus['w_t'], w_a=corpus['w_a'], corpus_size=corpus['size'], collection_tokens=corpus['tokens'], ext_corpus=ext_corpus, ext_index=ext_corpus['index'], ext_collection_tokens=ext_corpus['tokens'], ext_w_t=ext_corpus['w_t'], ext_w_a=ext_corpus['w_a'], ext_corpus_size=ext_corpus['size'], adap=True)) + + return refiners_list diff --git a/src/refinement/refiners/__init__.py b/src/refinement/refiners/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/refinement/refiners/abstractqrefiner.py b/src/refinement/refiners/abstractqrefiner.py new file mode 100644 index 0000000..b191fcd --- /dev/null +++ b/src/refinement/refiners/abstractqrefiner.py @@ -0,0 +1,217 @@ +import traceback +import pandas as pd +import sys + +sys.path.extend(['../refinement']) +from refinement import utils + + +class AbstractQRefiner: + def __init__(self, replace=False, topn=None): + self.replace = replace + self.topn = topn + self.query_set = pd.DataFrame(columns=['qid'], dtype=int) + + # all children expanders must call this in the returning line + def get_refined_query(self, q, args=None): + return q, args + + def get_model_name(self): + # this is for backward compatibility for renaming this class + if self.__class__.__name__ == 'AbstractQExpander': return 'AbstractQueryExpansion'.lower() + return f"{self.__class__.__name__.lower()}{f'.topn{self.topn}' if self.topn else ''}{'.replace' if self.replace else ''}" + + def get_query_set(self): + return self.query_set + + def generate_queue(self, Qfilename, Q_filename): + query_df = self.read_queries(Qfilename) + query_df.apply(lambda row: self.preprocess_expanded_query(q=row[self.get_model_name().lower()], qid=row['qid'], clean=True), axis=1) + self.write_queries(Q_filename) + + def preprocess_expanded_query(self, q, qid, clean): + try: + q_, args = self.get_expanded_query(q, args=[qid]) + q_ = utils.clean(q_) if clean else q_ + except: + print(f'WARNING: MAIN: {self.get_model_name()}: Expanding query [{qid}:{q}] failed!') + print(traceback.format_exc()) + q_.args = q, [0] + + new_line = {'qid': qid, self.get_model_name(): q_} + if self.get_model_name().__contains__('backtranslation'): new_line['semsim'] = args[0] + self.query_set = pd.concat([self.query_set, pd.DataFrame([new_line])], ignore_index=True) + print(f'INFO: MAIN: {self.get_model_name()}: {qid}: {q} -> {q_}') + + def write_queries(self, Q_filename): + self.query_set.to_csv(Q_filename, sep='\t', index=False, header=False) + + def read_queries(self, Qfilename): + model_name = self.get_model_name().lower() + is_tag_file = False + q, qid = '', '' + query_df = pd.DataFrame(columns=['qid']) + with open(Qfilename, 'r', encoding='UTF-8') as Qfile: + for line in Qfile: + if '' in line and not is_tag_file: is_tag_file = True + if '' in line: qid = int(line[line.index(':') + 1:]) + elif line[:7] == '': + q = line[8:].strip() + if not q: q = next(Qfile).strip() + elif '<topic' in line: + s = line.index('\"') + 1 + e = line.index('\"', s + 1) + qid = int(line[s:e]) + elif line[2:9] == '<query>': q = line[9:-9] + elif len(line.split('\t')) >= 2 and not is_tag_file: + qid = line.split('\t')[0].rstrip() + q = line.split('\t')[1].rstrip() + if q != '' and qid != '': + new_line = {'qid': qid, model_name: q} + query_df = pd.concat([query_df, pd.DataFrame([new_line])], ignore_index=True) + q, qid = '', '' + return query_df.astype({'qid': 'str'}) + + def write_expanded_queries(self, Qfilename, Q_filename, clean=True): + # prevent to clean the original query + if self.__class__.__name__ == 'AbstractQExpander': clean = False + model_name = self.get_model_name().lower() + Q_ = pd.DataFrame() + is_tag_file = False + with open(Qfilename, 'r', encoding='UTF-8') as Qfile: + with open(Q_filename, 'w', encoding='UTF-8') as Q_file: + print(f'INFO: MAIN: {self.get_model_name()}: Expanding queries in {Qfilename} ...') + for line in Qfile: + # For txt files + if '<top>' in line and not is_tag_file: is_tag_file = True + if '<num>' in line: + qid = int(line[line.index(':') + 1:]) + Q_file.write(line) + # For robust & gov2 + elif line[:7] == '<title>': + q = line[8:].strip() + if not q: q = next(Qfile).strip() + q_, args, Q_ = self.preprocess_expanded_query(q, qid, clean, Q_) + if model_name.__contains__('backtranslation'): Q_file.write( + f'<semsim> {args[0]:.4f} </semsim>\n') + Q_file.write('<title> ' + str(q_) + '\n') + elif '<topic' in line: + s = line.index('\"') + 1 + e = line.index('\"', s + 1) + qid = int(line[s:e]) + Q_file.write(line) + # For clueweb09b & clueweb12b13 + elif line[2:9] == '<query>': + q = line[9:-9] + q_, args, Q_ = self.preprocess_expanded_query(q, qid, clean, Q_) + if model_name.__contains__('backtranslation'): Q_file.write( + f'<semsim> {args[0]:.4f} </semsim>\n') + Q_file.write(' <query>' + str(q_) + '</query>' + '\n') + # For tsv files + elif len(line.split('\t')) >= 2 and not is_tag_file: + qid = line.split('\t')[0].rstrip() + q = line.split('\t')[1].rstrip() + q_, args, Q_ = self.preprocess_expanded_query(q, qid, clean, Q_) + Q_file.write(qid + '\t' + str(q_)) + Q_file.write('\t' + str(args[0]) + '\n') if model_name.__contains__('backtranslation') else Q_file.write('\n') + else: + Q_file.write(line) + return Q_ + + def read_expanded_queries(self, Q_filename): + model_name = self.get_model_name().lower() + Q_ = pd.DataFrame(columns=['qid'], dtype=int) + is_tag_file = False + with open(Q_filename, 'r', encoding='UTF-8') as Q_file: + print(f'INFO: MAIN: {self.get_model_name()}: Reading expanded queries in {Q_filename} ...') + for line in Q_file: + q_ = None + # for files with tag + if '<top>' in line and not is_tag_file: is_tag_file = True + if '<num>' in line: + qid = line[line.index(':') + 1:].strip() + elif '<semsim>' in line: + score = line[8:-10] + ' ' + # for robust & gov2 + elif line[:7] == '<title>': + q_ = line[8:].strip() + ' ' + elif '<topic' in line: + s = line.index('\"') + 1 + e = line.index('\"', s + 1) + qid = line[s:e].strip() + # for clueweb09b & clueweb12b13 + elif line[2:9] == '<query>': + q_ = line[9:-9] + ' ' + elif len(line.split('\t')) >= 2 and not is_tag_file: + qid = line.split('\t')[0].rstrip() + q_ = line.split('\t')[1].rstrip() + if model_name.__contains__('backtranslation'): score = line.split('\t')[2].rstrip() + else: + continue + if q_: + new_line = {'qid': qid, model_name: q_} + # For backtranslation expander add a new column as semsim + if model_name.__contains__('backtranslation'): new_line['semsim'] = score + Q_ = pd.concat([Q_, pd.DataFrame([new_line])], ignore_index=True) + return Q_.astype({'qid': 'str'}) + + +if __name__ == "__main__": + qe = AbstractQRefiner() + print(qe.get_model_name()) + print(qe.get_expanded_query('International Crime Organization')) + + # from expanders.abstractqexpander import AbstractQExpander + # from expanders.sensedisambiguation import SenseDisambiguation + # from expanders.thesaurus import Thesaurus + # from expanders.wordnet import Wordnet + # from expanders.word2vec import Word2Vec + from expanders.anchor import Anchor + # from expanders.glove import Glove + # from expanders.conceptnet import Conceptnet + # from expanders.relevancefeedback import RelevanceFeedback + # from expanders.stem import Stem # Stem expander is the wrapper for all stemmers as an expnader :) + # from stemmers.krovetz import KrovetzStemmer + # from stemmers.lovins import LovinsStemmer + # from stemmers.paicehusk import PaiceHuskStemmer + # from stemmers.porter import PorterStemmer + # from stemmers.porter2 import Porter2Stemmer + # from stemmers.sstemmer import SRemovalStemmer + # from stemmers.trunc4 import Trunc4Stemmer + # from stemmers.trunc5 import Trunc5Stemmer + from expanders.docluster import Docluster + from expanders.termluster import Termluster + from expanders.conceptluster import Conceptluster + + expanders = [AbstractQRefiner(), + # Thesaurus(), + # Wordnet(), + # Word2Vec('../pre/wiki-news-300d-1M.vec', topn=3), + # Glove('../pre/glove.6B.300d', topn=3), + # SenseDisambiguation(), + # Conceptnet(), + # Thesaurus(replace=True), + # Wordnet(replace=True), + # Word2Vec('../pre/wiki-news-300d-1M.vec', topn=3, replace=True), + # Glove('../pre/glove.6B.300d', topn=3, replace=True), + # SenseDisambiguation(replace=True), + # Conceptnet(replace=True), + # Stem(KrovetzStemmer(jarfile='stemmers/kstem-3.4.jar')), + # Stem(LovinsStemmer()), + # Stem(PaiceHuskStemmer()), + # Stem(PorterStemmer()), + # Stem(Porter2Stemmer()), + # Stem(SRemovalStemmer()), + # Stem(Trunc4Stemmer()), + # Stem(Trunc5Stemmer()), + # RelevanceFeedback(ranker='bm25', prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt',anserini='../anserini/',index='../ds/robust04/index-robust04-20191213'), + # Docluster(ranker='bm25', prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt',anserini='../anserini/', index='../ds/robust04/index-robust04-20191213'), + # Termluster(ranker='bm25', prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt',anserini='../anserini/', index='../ds/robust04/index-robust04-20191213'), + # Conceptluster(ranker='bm25', prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt', anserini='../anserini/', index='../ds/robust04/index-robust04-20191213'), + # Anchor(anchorfile='../pre/anchor_text_en_sample.ttl', vectorfile='../pre/wiki-anchor-text-en-ttl-300d-sample.vec', topn=3), + # Anchor(anchorfile='../pre/anchor_text_en_sample.ttl', vectorfile='../pre/wiki-anchor-text-en-ttl-300d-sample.vec', topn=3, replace=True) + ] + for expander in expanders: expander.write_expanded_queries('../ds/robust04/topics.robust04.txt', 'dummy.txt') + # expanders.write_expanded_queries('../ds/gov2/topics.terabyte05.751-800.txt', 'dummy') + # expanders.write_expanded_queries('../ds/clueweb09b/topics.web.101-150.txt', 'dummy') + # expanders.write_expanded_queries('../ds/clueweb12b13/topics.web.201-250.txt', 'dummy') diff --git a/src/refinement/refiners/adaponfields.py b/src/refinement/refiners/adaponfields.py new file mode 100644 index 0000000..2abaf23 --- /dev/null +++ b/src/refinement/refiners/adaponfields.py @@ -0,0 +1,163 @@ +import sys +sys.path.extend(['../refinement']) + +import traceback, os, subprocess, nltk, string, math +from bs4 import BeautifulSoup +from nltk.tokenize import word_tokenize +from nltk.stem import PorterStemmer +from collections import Counter +from nltk.corpus import stopwords +from pyserini import analysis, index +import pyserini +from pyserini.search import SimpleSearcher +from pyserini import analysis, index + +from refiners.onfields import OnFields +import utils + +# @article{DBLP:journals/ipm/HeO07, +# author = {Ben He and +# Iadh Ounis}, +# title = {Combining fields for query expansion and adaptive query expansion}, +# journal = {Inf. Process. Manag.}, +# volume = {43}, +# number = {5}, +# pages = {1294--1307}, +# year = {2007}, +# url = {https://doi.org/10.1016/j.ipm.2006.11.002}, +# doi = {10.1016/j.ipm.2006.11.002}, +# timestamp = {Fri, 21 Feb 2020 13:11:30 +0100}, +# biburl = {https://dblp.org/rec/journals/ipm/HeO07.bib}, +# bibsource = {dblp computer science bibliography, https://dblp.org} +# } + +class AdapOnFields(OnFields): + + def __init__(self, ranker, prels, anserini, index, w_t, w_a,corpus_size, collection_tokens, + ext_index, ext_corpus, ext_collection_tokens, ext_w_t, ext_w_a, ext_corpus_size, + replace=False, topn=3, topw=10, adap=False): + OnFields.__init__(self, ranker, prels, anserini, index, w_t, w_a,corpus_size, topn=topn, replace=replace, topw=topw, adap=adap) + + self.collection_tokens = collection_tokens # number of tokens in the collection + + self.ext_index=ext_index + self.ext_corpus=ext_corpus + self.ext_collection_tokens=ext_collection_tokens # number of tokens in the external collection + self.ext_w_t=ext_w_t + self.ext_w_a=ext_w_a + self.ext_corpus_size=ext_corpus_size + + + def get_refined_query(self, q, args): + qid=args[0] + Preferred_expansion=self.avICTF(q) + if Preferred_expansion =="NoExpansionPreferred": + output_weighted_q_dic={} + for terms in q.split(): + output_weighted_q_dic[ps.stem(terms)]=2 + return super().get_refined_query(output_weighted_q_dic) + + elif Preferred_expansion =="InternalExpansionPreferred": + return super().get_refined_query(q, [qid]) + + elif Preferred_expansion =="ExternalExpansionPreferred": + self.adap = True + self.prels = None#when adap is True, no need for prels since it does the retrieval again! + self.index = self.ext_index + self.corpus = self.ext_corpus + self.w_t = self.ext_w_t + self.w_a = self.ext_w_a + self.corpus_size = self.ext_corpus_size + + return super().get_refined_query(q, [qid]) + + def get_model_name(self): + return super().get_model_name().replace('topn{}'.format(self.topn), + 'topn{}.ex{}.{}.{}'.format(self.topn,self.ext_corpus, self.ext_w_t, self.ext_w_a)) + + def write_expanded_queries(self, Qfilename, Q_filename,clean=False): + return super().write_expanded_queries(Qfilename, Q_filename, clean=False) + + def avICTF(self,query): + index_reader = index.IndexReader(self.ext_index) + ql=len(query.split()) + sub_result=1 + for term in query.split(): + try: + df, collection_freq = index_reader.get_term_counts(ps.stem(term.lower())) + except: + collection_freq=1 + df=1 + + if isinstance(collection_freq,int)==False: + collection_freq=1 + df=1 + + try: + sub_result= sub_result * (self.ext_collection_tokens / collection_freq) + except: + sub_result= sub_result * self.ext_collection_tokens + sub_result=math.log2(sub_result) + externalavICTF= (sub_result/ql) + index_reader = index.IndexReader(self.index) + sub_result=1 + for term in query.split(): + try: + df, collection_freq = index_reader.get_term_counts(ps.stem(term.lower())) + except: + collection_freq=1 + df=1 + if isinstance(collection_freq,int)==False: + df=1 + collection_freq=1 + try: + sub_result= sub_result * (self.ext_collection_tokens / collection_freq) + except: + sub_result= sub_result * self.ext_collection_tokens + sub_result=math.log2(sub_result) + internalavICTF = (sub_result/ql) + if internalavICTF < 10 and externalavICTF < 10: + return "NoExpansionPreferred" + elif internalavICTF >= externalavICTF: + return "InternalExpansionPreferred" + elif externalavICTF > internalavICTF: + return "ExternalExpansionPreferred" + + +if __name__ == "__main__": + number_of_tokens_in_collections={'robust04':148000000, + 'gov2' : 17000000000, + 'cw09' : 31000000000, + 'cw12' : 31000000000} + + tuned_weights={'robust04': {'w_t':2.25 , 'w_a':1 }, + 'gov2': {'w_t':4 , 'w_a':0.25 }, + 'cw09': {'w_t': 1, 'w_a': 0}, + 'cw12': {'w_t': 4, 'w_a': 0}} + + total_documents_number = { 'robust04':520000 , + 'gov2' : 25000000, + 'cw09' : 50000000 , + 'cw12': 50000000} + + qe = AdapOnFields(ranker='bm25', + corpus='robust04', + index='../anserini/lucene-index.robust04.pos+docvectors+rawdocs', + prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt', + anserini='../anserini/', + w_t=tuned_weights['robust04']['w_t'], + w_a=tuned_weights['robust04']['w_a'], + corpus_size=total_documents_number['robust04'], + collection_tokens=number_of_tokens_in_collections['robust04'], + ext_corpus='gov2', + ext_index='../anserini/lucene-index.gov2.pos+docvectors+rawdocs', + ext_prels='./output/gov2/topics.terabyte04.701-750.abstractqueryexpansion.bm25.txt', + ext_collection_tokens = number_of_tokens_in_collections['gov2'], + ext_corpus_size=total_documents_number['gov2'], + ext_w_t= tuned_weights['gov2']['w_t'], + ext_w_a= tuned_weights['gov2']['w_a'], + ) + + print(qe.get_model_name()) + + print(qe.get_refined_query('most dangerous vehicle', [305])) diff --git a/src/refinement/refiners/anchor.py b/src/refinement/refiners/anchor.py new file mode 100644 index 0000000..548ab47 --- /dev/null +++ b/src/refinement/refiners/anchor.py @@ -0,0 +1,69 @@ +import gensim +from gensim.models.callbacks import CallbackAny2Vec +from gensim.models import KeyedVectors +# from rdflib import Graph + +from nltk.stem import PorterStemmer +ps = PorterStemmer() + +import sys, os +sys.path.extend(['../refinement']) + +from refiners.word2vec import Word2Vec +# The anchor texts dataset: +# https://wiki.dbpedia.org/downloads-2016-10 +# http://downloads.dbpedia.org/2016-10/core-i18n/en/anchor_text_en.ttl.bz2 + +class Anchor(Word2Vec): + def __init__(self, anchorfile, vectorfile, topn=3, replace=False): + Word2Vec.__init__(self, vectorfile, topn=topn, replace=replace) + Anchor.anchorfile = anchorfile + + def train(self): + + class AnchorIter: + def __init__(self, anchorfile): + self.anchorfile = anchorfile + def __iter__(self): + for i, line in enumerate(open(self.anchorfile, encoding='utf-8')): + if (i % 10000 == 0 and i > 0): + print('INFO: ANCHOR: {} anchors have been read ...'.format(i)) + s = line.find('> "') + e = line.find('"@en', s) + if s < 1: + continue + anchor_text = line[s + 3:e] + yield [ps.stem(w) for w in anchor_text.lower().split(' ')] + + class EpochLogger(CallbackAny2Vec): + def __init__(self, epoch_count): + self.epoch = 1 + self.epoch_count = epoch_count + def on_epoch_begin(self, model): + print("Epoch {}/{} ...".format(self.epoch, self.epoch_count)) + self.epoch += 1 + anchors = AnchorIter(Anchor.anchorfile) + anchors = [anchor for anchor in AnchorIter(Anchor.anchorfile)]#all in memory at once + model = gensim.models.Word2Vec(anchors, size=300, sg=1, window=2, iter=100, workers=40, min_count=0, callbacks=[EpochLogger(100)]) + model.wv.save(Anchor.vectorfile) + + def get_refined_query(self, q, args=None): + if not Word2Vec.word2vec: + if not os.path.exists(Anchor.vectorfile): + print('INFO: ANCHOR: Pretrained anchor vector file {} does not exist! Training has been started ...'.format(Anchor.vectorfile)) + self.train() + print('INFO: ANCHOR: Loading anchor vectors in {} ...'.format(Anchor.vectorfile)) + Word2Vec.word2vec = gensim.models.KeyedVectors.load(Anchor.vectorfile, mmap='r') + + return super().get_refined_query(q) + +if __name__ == "__main__": + qe = Anchor(anchorfile='../pre/anchor_text_en.ttl', vectorfile='../pre/wiki-anchor-text-en-ttl-300d-100iter.vec') + for i in range(5): + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani actor International Crime Organization')) + + qe.replace = True + for i in range(5): + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani actor International Crime Organization')) diff --git a/src/refinement/refiners/backtranslation.py b/src/refinement/refiners/backtranslation.py new file mode 100644 index 0000000..98b4f9e --- /dev/null +++ b/src/refinement/refiners/backtranslation.py @@ -0,0 +1,51 @@ +from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM +from sentence_transformers import SentenceTransformer +from scipy.spatial.distance import cosine +import sys + +sys.path.extend(['../refinement']) + +from refiners.abstractqrefiner import AbstractQRefiner +import param + + +class BackTranslation(AbstractQRefiner): + def __init__(self, tgt): + AbstractQRefiner.__init__(self) + + # Initialization + self.tgt = tgt + model = AutoModelForSeq2SeqLM.from_pretrained(param.backtranslation['model_card']) + tokenizer = AutoTokenizer.from_pretrained(param.backtranslation['model_card']) + # translator = pipeline("translation", model=model, tokenizer=tokenizer, src_lang='eng_Latn', tgt_lang='pes_Arab', max_length=512, device='cpu') + + # Translation models + self.translator = pipeline("translation", model=model, tokenizer=tokenizer, src_lang=param.backtranslation['src_lng'], tgt_lang=self.tgt, max_length=param.backtranslation['max_length'], device=param.backtranslation['device']) + self.back_translator = pipeline("translation", model=model, tokenizer=tokenizer, src_lang=self.tgt, tgt_lang=param.backtranslation['src_lng'], max_length=param.backtranslation['max_length'], device=param.backtranslation['device']) + # Model use for calculating semsim + self.transformer_model = SentenceTransformer(param.backtranslation['transformer_model']) + + # Generate the backtranslated of the original query then calculates the difference of the two queries + def get_refined_query(self, q, args=None): + translated_query = self.translator(q) + back_translated_query = self.back_translator(translated_query[0]['translation_text']) + + score = self.semsim(q, back_translated_query[0]['translation_text']) + return super().get_expanded_query(back_translated_query[0]['translation_text'], [score]) + # return super().get_expanded_query(q, [0]) + + # Returns the name of the model ('backtranslation) with name of the target language + # Example: 'backtranslation_fra_latn' + def get_model_name(self): + return super().get_model_name() + '_' + self.tgt.lower() + + # Calculate the difference between the original and back-translated query + def semsim(self, q1, q2): + me, you = self.transformer_model.encode([q1, q2]) + return 1 - cosine(me, you) + + +if __name__ == "__main__": + qe = BackTranslation() + print(qe.get_model_name()) + print(qe.get_refined_query('This is my pc')) diff --git a/src/refinement/refiners/bertqe.py b/src/refinement/refiners/bertqe.py new file mode 100644 index 0000000..3931542 --- /dev/null +++ b/src/refinement/refiners/bertqe.py @@ -0,0 +1,107 @@ +import sys +sys.path.extend(['../refinement']) +sys.path.extend(['../pygaggle']) + +import pyserini +from pyserini import index +#from pyserini.search import SimpleSearcher +import subprocess, string +import nltk +from bs4 import BeautifulSoup +from nltk.tokenize import word_tokenize +from collections import Counter +from nltk.corpus import stopwords +from pygaggle.rerank.base import Query, Text +from pygaggle.rerank.transformer import MonoT5 +from nltk.tokenize import word_tokenize + +from pygaggle.rerank.transformer import MonoBERT +from pygaggle.rerank.base import hits_to_texts + +from refiners.relevancefeedback import RelevanceFeedback +import utils + +reranker = MonoBERT() + +#@inproceedings{zheng-etal-2020-bert, +# title = "{BERT-QE}: {C}ontextualized {Q}uery {E}xpansion for {D}ocument {R}e-ranking", +# author = "Zheng, Zhi and Hui, Kai and He, Ben and Han, Xianpei and Sun, Le and Yates, Andrew", +# booktitle = "Findings of the Association for Computational Linguistics: EMNLP 2020", +# month = nov, +# year = "2020", +# address = "Online", +# publisher = "Association for Computational Linguistics", +# url = "https://www.aclweb.org/anthology/2020.findings-emnlp.424", +# pages = "4718--4728", +#} + +class BertQE(RelevanceFeedback): + def __init__(self, ranker, prels, anserini, index): + RelevanceFeedback.__init__(self, ranker, prels, anserini, index, topn=10) + self.index_reader = pyserini.index.IndexReader(self.index) + + + def get_refined_query(self, q, args): + q=q.translate(str.maketrans('', '', string.punctuation)) + qid=args[0] + topn_docs = self.get_topn_relevant_docids(qid) + print() + topn_text="" + for docid in topn_docs: + raw_doc=self.index_reader.doc_raw(docid).lower() + raw_doc= ''.join([i if ord(i) < 128 else ' ' for i in raw_doc]) + topn_text= topn_text+ ' ' + raw_doc + + chunk_dic_for_bert=[] + chunks=self.make_chunks(topn_text) + for i in range(len(chunks)): + chunk_dic_for_bert.append([i,chunks[i]]) + + chunk_scores=self.Bert_Score(q,chunk_dic_for_bert) + scores=list(chunk_scores.values()) + norm = [(float(i)-min(scores))/(max(scores)-min(scores)) for i in scores] + normalized_chunks={} + normalized_chunks[q]=1.5 + for i in range(5): + normalized_chunks[list(chunk_scores.keys())[i]]=norm[i] + return super().get_expanded_query(str(normalized_chunks)) + + def write_expanded_queries(self, Qfilename, Q_filename,clean=False): + return super().write_expanded_queries(Qfilename, Q_filename, clean=False) + + def make_chunks(self,raw_doc): + chunks=[] + terms=raw_doc.split() + for i in range(0, len(terms),5 ): + chunk='' + for j in range(i,i+5): + if j < (len(terms)-1): + chunk=chunk+' '+terms[j] + chunks.append(chunk) + return chunks + + def Bert_Score(self,q,doc_dic_for_bert): + chunk_scores={} + query = Query(q) + texts = [ Text(p[1], {'docid': p[0]}, 0) for p in doc_dic_for_bert] + reranked = reranker.rerank(query, texts) + reranked.sort(key=lambda x: x.score, reverse=True) + for i in range(0,10): + chunk_text=reranked[i].text + word_tokens = word_tokenize(chunk_text) + filtered_sentence = [w for w in word_tokens if not w in stop_words] + filtered_sentence = (" ").join(filtered_sentence).translate(str.maketrans('', '', string.punctuation)) + chunk_scores[filtered_sentence]=round(reranked[i].score,3) + #print(f'{i+1:2} {reranked[i].score:.5f} {reranked[i].text}') + return chunk_scores + +if __name__ == "__main__": + + qe = BertQE(ranker='bm25', + prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt', + anserini='../anserini/', + index='../anserini/lucene-index.robust04.pos+docvectors+rawdocs') + print(qe.get_model_name()) + print(qe.get_expanded_query('International Organized Crime ', [305])) + + diff --git a/src/refinement/refiners/conceptluster.py b/src/refinement/refiners/conceptluster.py new file mode 100644 index 0000000..78f71f2 --- /dev/null +++ b/src/refinement/refiners/conceptluster.py @@ -0,0 +1,50 @@ +import tagme +tagme.GCUBE_TOKEN = "10df41c6-f741-45fc-88dd-9b24b2568a7b" + +import os,sys +sys.path.extend(['../refinement']) + +from refiners.termluster import Termluster +import utils +class Conceptluster(Termluster): + def __init__(self, ranker, prels, anserini, index, topn=5, topw=3): + Termluster.__init__(self, ranker, prels, anserini, index, topn=topn, topw=topw) + + def get_refined_query(self, q, args): + qid = args[0] + list_of_concept_lists = [] + docids = self.get_topn_relevant_docids(qid) + for docid in docids: + doc_text = self.get_document(docid) + concept_list = self.get_concepts(doc_text, score=0.1) + list_of_concept_lists.append(concept_list) + + G, cluster_dict = self.make_graph_document(list_of_concept_lists, min_edge=10) + expanded_query = self.expand_query_concept_cluster(q, G, cluster_dict, k_relevant_words=self.topw) + return super().get_expanded_query(expanded_query) + + def expand_query_concept_cluster(self, q, G, cluster_dict, k_relevant_words): + q += ' ' + ' '.join(self.get_concepts(q, 0.1)) + return super().refined_query_term_cluster(q, G, cluster_dict, k_relevant_words) + + def get_document(self, docid): + command = '\"{}target/appassembler/bin/IndexUtils\" -index \"{}\" -dumpRawDoc \"{}\"'.format(self.anserini, self.index, docid) + stream = os.popen(command) + return stream.read() + + def get_concepts(self, text, score): + concepts = tagme.annotate(text).get_annotations(score) + return list(set([c.entity_title for c in concepts if c.entity_title not in text])) + + +if __name__ == "__main__": + qe = Conceptluster(ranker='bm25', + prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt', + anserini='../anserini/', + index='../ds/robust04/index-robust04-20191213') + + for i in range(5): + print(qe.get_model_name()) + print(qe.get_expanded_query('HosseinFani International Crime Organization', [301])) + print(qe.get_expanded_query('Agoraphobia', [698])) + print(qe.get_expanded_query('Unsolicited Faxes', [317])) diff --git a/src/refinement/refiners/conceptnet.py b/src/refinement/refiners/conceptnet.py new file mode 100644 index 0000000..f5a16b1 --- /dev/null +++ b/src/refinement/refiners/conceptnet.py @@ -0,0 +1,62 @@ +import requests + +import sys +sys.path.extend(['../refinement']) +from nltk.stem import PorterStemmer + +from refiners.abstractqrefiner import AbstractQRefiner +import utils + +class Conceptnet(AbstractQRefiner): + def __init__(self, replace=False, topn=3): + AbstractQRefiner.__init__(self, replace, topn) + + def get_refined_query(self, q, args=None): + upd_query = utils.get_tokenized_query(q) + res = [] + if not self.replace: + res = [w for w in upd_query] + ps = PorterStemmer() + for q in upd_query: + q_stem = ps.stem(q) + found_flag = False + try: + obj = requests.get('http://api.conceptnet.io/c/en/' + q).json() + except: + if self.replace: + res.append(q) + continue + if len(obj['edges']) < self.topn: + x = len(obj['edges']) + else: + x = self.topn + for i in range(x): + + try: + start_lan = obj['edges'][i]['start']['language'] + end_lan = obj['edges'][i]['end']['language'] + except: + continue + if obj['edges'][i]['start']['language'] != 'en' or obj['edges'][i]['end']['language'] != 'en': + continue + if obj['edges'][i]['start']['label'].lower() == q: + if obj['edges'][i]['end']['label'] not in res and q_stem != ps.stem(obj['edges'][i]['end']['label']): + found_flag = True + res.append(obj['edges'][i]['end']['label']) + elif obj['edges'][i]['end']['label'].lower() == q: + if obj['edges'][i]['start']['label'] not in res and q_stem != ps.stem(obj['edges'][i]['start']['label']): + found_flag = True + res.append(obj['edges'][i]['start']['label']) + if not found_flag and self.replace: + res.append(q) + return super().get_expanded_query(' '.join(res)) + + +if __name__ == "__main__": + qe = Conceptnet() + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani International Crime Organization')) + + qe = Conceptnet(replace=True) + print(qe.get_model_name()) + print(qe.get_refined_query('compost pile')) diff --git a/src/refinement/refiners/docluster.py b/src/refinement/refiners/docluster.py new file mode 100644 index 0000000..7cbfd12 --- /dev/null +++ b/src/refinement/refiners/docluster.py @@ -0,0 +1,127 @@ +import networkx as nx +from networkx.algorithms import community +import math + +import sys +sys.path.extend(['../refinement']) + +from refiners.relevancefeedback import RelevanceFeedback +class Docluster(RelevanceFeedback): + def __init__(self, ranker, prels, anserini, index, topn=10, topw=3): + RelevanceFeedback.__init__(self, ranker, prels, anserini, index, topn=topn) + self.topw = topw + + def get_model_name(self): + return super().get_model_name().replace('topn{}'.format(self.topn),'topn{}.{}'.format(self.topn, self.topw)) + + def getsim(self, tfidf1, tfidf2): + words_doc_id_1 = [] + values_doc_id_1 = [] + + words_doc_id_2 = [] + values_doc_id_2 = [] + + for x in tfidf1.split('\n'): + if not x: + continue + x_splited = x.split() + words_doc_id_1.append(x_splited[0]) + values_doc_id_1.append(int(x_splited[1])) + + for x in tfidf2.split('\n'): + if not x: + continue + x_splited = x.split() + words_doc_id_2.append(x_splited[0]) + values_doc_id_2.append(int(x_splited[1])) + + sum_docs_1_2 = 0 + i = 0 + for word in words_doc_id_1: + try: + index = words_doc_id_2.index(word) + except ValueError: + index = -1 + if index != -1: + sum_docs_1_2 = sum_docs_1_2 + values_doc_id_1[i] * values_doc_id_2[index] + i = i + 1 + + sum_doc_1 = 0 + for j in range(len(values_doc_id_1)): + sum_doc_1 = sum_doc_1 + (values_doc_id_1[j] * values_doc_id_1[j]) + + sum_doc_2 = 0 + for j in range(len(values_doc_id_2)): + sum_doc_2 = sum_doc_2 + (values_doc_id_2[j] * values_doc_id_2[j]) + + if sum_doc_1 == 0 or sum_doc_2 == 0: + return 0 + + result = sum_docs_1_2 / (math.sqrt(sum_doc_1) * math.sqrt(sum_doc_2)) + + return result + + def get_refined_query(self, q, args): + qid = args[0] + selected_words = [] + docids = self.get_topn_relevant_docids(qid) + tfidfs = [] + for docid in docids: + tfidfs.append(self.get_tfidf(docid)) + + G = nx.Graph() + for i in range(len(docids)): + G.add_node(docids[i]) + for j in range(i + 1, len(docids) - 1): + sim = self.getsim(tfidfs[i], tfidfs[j]) + if sim > 0.5: + G.add_weighted_edges_from([(docids[i], docids[j], sim)]) + comp = community.girvan_newman(G) + partitions = tuple(sorted(c) for c in next(comp)) + for partition in partitions: + if len(partition) > 1: + pairlist = [] + for p in partition: + pairlist.append(self.get_top_word(tfidf=tfidfs[docids.index(p)])) + + top_k = self.get_top_k(pairlist, self.topw) + for (word, value) in top_k: + selected_words.append(word) + + query_splited = q.lower().split() + for word in selected_words: + if word.lower() not in query_splited: + query_splited.append(word) + + return super().get_refined_query(' '.join(query_splited)) + + def get_top_k(self, pairlist, k): + output = [] + from_index = 0 + for j in range(min(len(pairlist), k)): + max_value = 0 + max_index = 0 + max_word = "" + for i in range(from_index, len(pairlist)): + (word, value) = pairlist[i] + if value > max_value: + max_value = value + max_word = word + max_index = i + output.append((max_word, max_value)) + temp = pairlist[from_index] + pairlist[from_index] = pairlist[max_index] + pairlist[max_index] = temp + from_index = from_index + 1 + return output + +if __name__ == "__main__": + qe = Docluster(ranker='bm25', + prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt', + anserini='../anserini/', + index='../ds/robust04/index-robust04-20191213') + for i in range(5): + print(qe.get_model_name()) + # print(qe.get_expanded_query('HosseinFani International Crime Organization', [301])) + # print(qe.get_expanded_query('Agoraphobia', [698])) + print(qe.get_refined_query('Unsolicited Faxes', [317])) diff --git a/src/refinement/refiners/expanders.csv b/src/refinement/refiners/expanders.csv new file mode 100644 index 0000000..875f8bb --- /dev/null +++ b/src/refinement/refiners/expanders.csv @@ -0,0 +1,59 @@ +name, category +stem.krovetz,Stemming_Analysis +stem.lovins,Stemming_Analysis +stem.paicehusk,Stemming_Analysis +stem.porter,Stemming_Analysis +stem.porter2,Stemming_Analysis +stem.sstemmer,Stemming_Analysis +stem.trunc4,Stemming_Analysis +stem.trunc5,Stemming_Analysis +conceptnet.topn3,Semantic_Analysis +conceptnet.topn3.replace,Semantic_Analysis +glove.topn3,Semantic_Analysis +glove.topn3.replace,Semantic_Analysis +sensedisambiguation,Semantic_Analysis +sensedisambiguation.replace,Semantic_Analysis +thesaurus.topn3,Semantic_Analysis +thesaurus.topn3.replace,Semantic_Analysis +word2vec.topn3,Semantic_Analysis +word2vec.topn3.replace,Semantic_Analysis +wordnet.topn3,Semantic_Analysis +wordnet.topn3.replace,Semantic_Analysis +termluster.topn5.3.bm25,Term_Clustering +termluster.topn5.3.qld,Term_Clustering +conceptluster.topn5.3.bm25,Concept_Clustering +conceptluster.topn5.3.qld,Concept_Clustering +anchor.topn3,Anchor_Text +anchor.topn3.replace,Anchor_Text +wiki.topn3,Wikipedia +wiki.topn3.replace,Wikipedia +tagmee.topn3,Wikipedia +tagmee.topn3.replace,Wikipedia +relevancefeedback.topn10.bm25,Top_Documents +relevancefeedback.topn10.qld,Top_Documents +rm3.topn10.10.0.5.bm25,Top_Documents +rm3.topn10.10.0.5.qld,Top_Documents +adaponfields.topn3.exgov2.4.0.25.10.2.25.1.bm25,Top_Documents +adaponfields.topn3.exgov2.4.0.25.10.1.1.bm25,Top_Documents +adaponfields.topn3.exgov2.4.0.25.10.1.1.qld,Top_Documents +onfields.topn3.10.2.25.1.bm25,Top_Documents +onfields.topn3.10.1.1.bm25,Top_Documents +onfields.topn3.10.2.25.1.qld,Top_Documents +onfields.topn3.10.1.1.qld,Top_Documents +onfields.topn3.10.4.0.25.bm25,Top_Documents +onfields.topn3.10.1.0.bm25,Top_Documents +adaponfields.topn3.exgov2.4.0.25.10.2.25.1.qld,Top_Documents +adaponfields.topn3.exgov2.4.0.25.10.1.0.qld,Top_Documents +adaponfields.topn3.exrobust04.2.25.1.10.4.0.25.bm25,Top_Documents +adaponfields.topn3.exrobust04.2.25.1.10.4.0.25.qld,Top_Documents +adaponfields.topn3.exgov2.4.0.25.10.4.0.qld,Top_Documents +onfields.topn3.10.4.0.25.qld,Top_Documents +onfields.topn3.10.4.0.bm25,Top_Documents +adaponfields.topn3.exgov2.4.0.25.10.4.0.bm25,Top_Documents +onfields.topn3.10.4.0.qld,Top_Documents +adaponfields.topn3.exgov2.4.0.25.10.1.0.bm25,Top_Documents +onfields.topn3.10.1.0.qld,Top_Documents +bertqe.topn10.bm25,Top_Documents +bertqe.topn10.qld,Top_Documents +docluster.topn10.3.bm25,Document_Summaries +docluster.topn10.3.qld,Document_Summaries diff --git a/src/refinement/refiners/glove.py b/src/refinement/refiners/glove.py new file mode 100644 index 0000000..db0cc2c --- /dev/null +++ b/src/refinement/refiners/glove.py @@ -0,0 +1,70 @@ +import scipy +from nltk.stem import PorterStemmer +import numpy as np + +import sys +sys.path.extend(['../refinement']) + +from refiners.abstractqrefiner import AbstractQRefiner +import utils + +class Glove(AbstractQRefiner): + def __init__(self, vectorfile, replace=False, topn=3): + AbstractQRefiner.__init__(self, replace, topn) + Glove.vectorfile = vectorfile + Glove.glove = None + + + def get_refined_query(self, q, args=None): + if not Glove.glove: + print('INFO: Glove: Loading word vectors in {} ...'.format(Glove.vectorfile)) + Glove.glove = load_glove_model(Glove.vectorfile) + + upd_query = utils.get_tokenized_query(q) + synonyms = [] + res = [] + if not self.replace: + res = [w for w in upd_query] + ps = PorterStemmer() + for qw in upd_query: + found_flag = False + qw_stem = ps.stem(qw) + if qw.lower() in Glove.glove.keys(): + w = sorted(Glove.glove.keys(), key=lambda word: scipy.spatial.distance.euclidean(Glove.glove[word], Glove.glove[qw])) + w = w[:self.topn] + for u in w: + u_stem = ps.stem(u) + if u_stem != qw_stem: + found_flag = True + res.append(u) + if not found_flag and self.replace: + res.append(qw) + return super().get_refined_query(' '.join(res)) + + +def load_glove_model(glove_file): + with open(glove_file + ".txt", 'r', encoding='utf-8') as f: + model = {} + counter=0 + for line in f: + if counter>0: + split_line = line.split() + word = split_line[0] + embedding = np.array([float(val) for val in split_line[1:]]) + model[word] = embedding + counter+=1 + else: + counter+=1 + return model + +if __name__ == "__main__": + qe = Glove('../pre/glove.6B.300d') + for i in range(5): + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani International Crime Organization')) + qe.replace = True + for i in range(5): + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani International Crime Organization')) + + diff --git a/src/refinement/refiners/onfields.py b/src/refinement/refiners/onfields.py new file mode 100644 index 0000000..71a9578 --- /dev/null +++ b/src/refinement/refiners/onfields.py @@ -0,0 +1,271 @@ +import sys +sys.path.extend(['../refinement']) + +from pyserini.search import SimpleSearcher +import traceback, os, subprocess, nltk, string, math +from bs4 import BeautifulSoup +from nltk.tokenize import word_tokenize +from nltk.stem import PorterStemmer +from collections import Counter +from nltk.corpus import stopwords +from pyserini import analysis, index +import pyserini + +from refiners.relevancefeedback import RelevanceFeedback +import utils + +# @article{DBLP:journals/ipm/HeO07, +# author = {Ben He and +# Iadh Ounis}, +# title = {Combining fields for query expansion and adaptive query expansion}, +# journal = {Inf. Process. Manag.}, +# volume = {43}, +# number = {5}, +# pages = {1294--1307}, +# year = {2007}, +# url = {https://doi.org/10.1016/j.ipm.2006.11.002}, +# doi = {10.1016/j.ipm.2006.11.002}, +# timestamp = {Fri, 21 Feb 2020 13:11:30 +0100}, +# biburl = {https://dblp.org/rec/journals/ipm/HeO07.bib}, +# bibsource = {dblp computer science bibliography, https://dblp.org} +# } + +class OnFields(RelevanceFeedback): + def __init__(self, ranker, prels, anserini, index, w_t, w_a, corpus_size, replace=False, topn=3, topw=10,adap=False): + RelevanceFeedback.__init__(self, ranker, prels, anserini, index, topn=topn) + self.index_reader = pyserini.index.IndexReader(self.index) + self.topw=10 + self.adap=adap + self.w_t = w_t # weight for title field + self.w_a = w_a # weight for anchor field + self.corpus_size=corpus_size #total number of documents in the collection + + def get_refined_query(self, q, args): + q=q.translate(str.maketrans('', '', string.punctuation)) + qid=args[0] + if self.adap == False: + topn_docs = self.get_topn_relevant_docids(qid) + elif self.adap == True: + topn_docs=self.retrieve_and_get_topn_relevant_docids(ps.stem(q.lower())) + topn_title='' + topn_body='' + topn_anchor='' + for docid in topn_docs: + raw_doc=self.extract_raw_documents(docid) + raw_doc=raw_doc.lower() + raw_doc= ''.join([i if ord(i) < 128 else ' ' for i in raw_doc]) + + title='' + body=raw_doc + anchor='' + try: + title=self.extract_specific_field(raw_doc,'title') + except: + # 'title' field do not exist + pass + try: + body=self.extract_specific_field(raw_doc,'body') + if body =='': + body=raw_doc + except: + # 'body' field do not exist + pass + try: + anchor=self.extract_specific_field(raw_doc,'anchor') + except: + #'anchor' field do not exist + pass + + topn_title='{} {}'.format(topn_title ,title) + topn_anchor = '{} {}'.format(topn_anchor,anchor) + topn_body='{} {}'.format(topn_body,body) + topn_title=topn_title.translate(str.maketrans('', '', string.punctuation)) + topn_anchor=topn_anchor.translate(str.maketrans('', '', string.punctuation)) + topn_body=topn_body.translate(str.maketrans('', '', string.punctuation)) + all_topn_docs= '{} {} {}'.format(topn_body, topn_anchor ,topn_title) + tfx = self.term_weighting(topn_title,topn_anchor,topn_body) + tfx=dict(sorted(tfx.items(), key=lambda x: x[1])[::-1]) + w_t_dic={} + c=0 + + + for term in tfx.keys(): + if term.isalnum(): + + c=c+1 + collection_freq =1 + try: + df, collection_freq = self.index_reader.get_term_counts(term) + except: + # term do not exist in the collection + pass + if collection_freq==0 or collection_freq==None: + collection_freq=1 + + P_n = collection_freq / self.corpus_size + try: + term_weight= tfx[term] * math.log2( (1 + P_n ) / P_n) + math.log2( 1 + P_n) + w_t_dic[term]=term_weight + except: + + pass + + + sorted_term_weights=dict(sorted(w_t_dic.items(), key=lambda x: x[1])[::-1]) + counter=0 + top_n_informative_words={} + for keys,values in sorted_term_weights.items(): + counter=counter+1 + top_n_informative_words[keys]=values + if counter>self.topw: + break + + expanded_term_freq= {} + for keys,values in top_n_informative_words.items(): + expanded_term_freq[keys]=all_topn_docs.count(keys) + + for keys,values in top_n_informative_words.items(): + part_A = expanded_term_freq[keys] /max(expanded_term_freq.values()) + part_B = top_n_informative_words[keys] / max(top_n_informative_words.values()) + top_n_informative_words[keys]= round(part_A+part_B,3) + + for original_q_term in q.lower().split(): + top_n_informative_words[ps.stem(original_q_term)]=2 + + top_n_informative_words=dict(sorted(top_n_informative_words.items(), key=lambda x: x[1])[::-1]) + return super().get_refined_query(str(top_n_informative_words)) + + def get_model_name(self): + return super().get_model_name().replace('topn{}'.format(self.topn), + 'topn{}.{}.{}.{}'.format(self.topn, self.topw, self.w_t, self.w_a)) + + def write_expanded_queries(self, Qfilename, Q_filename,clean=False): + return super().write_expanded_queries(Qfilename, Q_filename, clean=False) + + def extract_raw_documents(self,docid): + index_address=self.index + anserini_address=self.anserini + cmd = '\"{}/target/appassembler/bin/IndexUtils\" -index \"{}\" -dumpRawDoc \"{}\"'.format(anserini_address,index_address,docid) + output = subprocess.check_output(cmd, shell=True) + return (output.decode('utf-8')) + + def extract_specific_field(self,raw_document,field): + soup = BeautifulSoup(raw_document) # txt is simply the a string with your XML file + title_out='' + body_out='' + anchor_out='' + if field=='title': + try: + title= soup.find('headline') + title_out=title.text + except: + if title_out=='': + try: + title = soup.find('title') + title_out=title.text + except: + # document had not 'title' + pass + + return title_out + + if field == 'body': + if '<html>' not in raw_document: + pageText = soup.findAll(text=True) + body_out= (' '.join(pageText)) + else: + bodies= soup.find_all('body') + for b in bodies: + try: + body_out='{} {}'.format(body_out,b.text.strip()) + except: + # no 'body' field in the document + pass + return body_out + + if field=='anchor': + for link in soup.findAll('a'): + if link.string != None: + anchor_out='{} {}'.format(anchor_out,link.string) + return anchor_out + + + def term_weighting(self,topn_title,topn_anchor,topn_body): + # w_t and w_a is tuned for all the copora ( should be tuned for future corpora as well) + + w_b = 1 + topn_title=topn_title.translate(str.maketrans('', '', string.punctuation)) + topn_body=topn_body.translate(str.maketrans('', '', string.punctuation)) + topn_anchor=topn_anchor.translate(str.maketrans('', '', string.punctuation)) + + title_tokens = word_tokenize(topn_title) + body_tokens= word_tokenize(topn_body) + anchor_tokens= word_tokenize(topn_anchor) + + filtered_words_title = [ps.stem(word) for word in title_tokens if word not in stop_words] + filtered_words_body = [ps.stem(word) for word in body_tokens if word not in stop_words] + filtered_words_anchor = [ps.stem(word) for word in anchor_tokens if word not in stop_words] + + term_freq_title = dict(Counter(filtered_words_title)) + term_freq_body = dict(Counter(filtered_words_body)) + term_freq_anchor = dict(Counter(filtered_words_anchor)) + + term_weights={} + for term in list(set(filtered_words_title)): + if term not in term_weights.keys(): + term_weights[term]=0 + term_weights[term]=term_weights[term] + term_freq_title[term] * self.w_t + + for term in list(set(filtered_words_body)): + if term_freq_body[term] : + if term not in term_weights.keys(): + term_weights[term]=0 + term_weights[term]=term_weights[term] + term_freq_body[term] * w_b + + for term in list(set(filtered_words_anchor)): + if term not in term_weights.keys(): + term_weights[term]=0 + term_weights[term]=term_weights[term] + term_freq_anchor[term] * self.w_a + + return term_weights + + def retrieve_and_get_topn_relevant_docids(self, q): + relevant_documents = [] + searcher = SimpleSearcher(self.index) + + if self.ranker =='bm25': + searcher.set_bm25() + elif self.ranker=='qld': + searcher.set_qld() + hits = searcher.search(q) + for i in range(0, self.topn): + relevant_documents.append(hits[i].docid) + return relevant_documents + + +if __name__ == "__main__": + tuned_weights={'robust04': {'w_t':2.25 , 'w_a':1 }, + 'gov2': {'w_t':4 , 'w_a':0.25 }, + 'cw09': {'w_t': 1, 'w_a': 0}, + 'cw12': {'w_t': 4, 'w_a': 0}} + + total_documents_number = { 'robust04':520000 , + 'gov2' : 25000000, + 'cw09' : 50000000 , + 'cw12': 50000000} + + + + qe = OnFields(ranker='bm25', + prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt', + anserini='../anserini/', + index='./ds/robust04/lucene-index.robust04.pos+docvectors+rawdocs', + corpus='robust04', + w_t=tuned_weights['robust04']['w_t'], + w_a=tuned_weights['robust04']['w_a'], + corpus_size= total_documents_number['robust04']) + + print(qe.get_model_name()) + print(qe.get_refined_query('Most Dangerous Vehicles', [305])) + + diff --git a/src/refinement/refiners/relevancefeedback.py b/src/refinement/refiners/relevancefeedback.py new file mode 100644 index 0000000..a971ec0 --- /dev/null +++ b/src/refinement/refiners/relevancefeedback.py @@ -0,0 +1,86 @@ +import os +import sys +sys.path.extend(['../refinement']) + +from refiners.abstractqrefiner import AbstractQRefiner +class RelevanceFeedback(AbstractQRefiner): + def __init__(self, ranker, prels, anserini, index, topn=10): + AbstractQRefiner.__init__(self, replace=False, topn=topn) + self.prels = prels + self.f = None + self.anserini = anserini + self.index = index + self.ranker = ranker + + def get_model_name(self): + return super().get_model_name() + '.' + self.ranker + + def get_refined_query(self, q, args): + qid = args[0] + selected_words = [] + docids = self.get_topn_relevant_docids(qid) + for docid in docids: + tfidf = self.get_tfidf(docid) + top_word, _ = self.get_top_word(tfidf) + selected_words.append(top_word) + + query_splited = q.lower().split() + for word in selected_words: + if word.lower() not in query_splited: + query_splited.append(word) + + return super().get_refined_query(' '.join(query_splited)) + + def get_topn_relevant_docids(self, qid): + relevant_documents = [] + if not self.f: + self.f = open(self.prels, "r", encoding='utf-8') + self.f.seek(0) + i = 0 + for x in self.f: + x_splited = x.split() + try : + if (int(x_splited[0]) == qid or x_splited[0] == qid): + relevant_documents.append(x_splited[2]) + i = i+1 + if i >= self.topn: + break + except: + if ('dbpedia' in self.prels and x_splited[0] == qid): + relevant_documents.append(x_splited[2]) + i = i+1 + if i >= self.topn: + break + return super().get_refined_query(relevant_documents) + + def get_tfidf(self, docid): + #command = "target/appassembler/bin/IndexUtils -index lucene-index.robust04.pos+docvectors+rawdocs -dumpDocVector FBIS4-40260 -docVectorWeight TF_IDF " + cli_cmd = '\"{}target/appassembler/bin/IndexUtils\" -index \"{}\" -dumpDocVector \"{}\" -docVectorWeight TF_IDF'.format(self.anserini, self.index, docid) + stream = os.popen(cli_cmd) + return stream.read() + + def get_top_word(self, tfidf): + i = 0 + max = 0 + top_word = "" + for x in tfidf.split('\n'): + if not x: + continue + x_splited = x.split() + word = x_splited[0] + value = int(x_splited[1]) + if value > max: + top_word = word + max = value + + return top_word, max + + +if __name__ == "__main__": + qe = RelevanceFeedback(ranker='bm25', + prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt', + anserini='../anserini/', + index='../ds/robust04/index-robust04-20191213') + for i in range(5): + print(qe.get_model_name()) + print(qe.get_refined_query('Agoraphobia', [698])) diff --git a/src/refinement/refiners/rm3.py b/src/refinement/refiners/rm3.py new file mode 100644 index 0000000..5626ab7 --- /dev/null +++ b/src/refinement/refiners/rm3.py @@ -0,0 +1,53 @@ +import os, sys, re, io +sys.path.extend(['../refinement']) + +from pyserini.search import SimpleSearcher +import utils #although it's not used here, this is required! +from refiners.relevancefeedback import RelevanceFeedback + +class RM3(RelevanceFeedback): + def __init__(self, ranker, index, topn=10, topw=10, original_q_w=0.5): + RelevanceFeedback.__init__(self, ranker=ranker, prels=None, anserini=None, index=index, topn=topn) + self.topw=topw + self.searcher = SimpleSearcher(index) + self.ranker=ranker + self.original_q_w=original_q_w + + + def get_refined_query(self, q, args=None): + + if self.ranker=='bm25': + self.searcher.set_bm25() + elif self.ranker=='qld': + self.searcher.set_qld() + + self.searcher.set_rm3(fb_terms=self.topw, fb_docs=self.topn, original_query_weight=self.original_q_w, rm3_output_query=True) + + f = io.BytesIO() + with utils.stdout_redirector_2_stream(f): + self.searcher.search(q) + print('RM3 Log: {0}"'.format(f.getvalue().decode('utf-8'))) + q_= self.parse_rm3_log(f.getvalue().decode('utf-8')) + + # with stdout_redirected(to='rm3.log'): + # self.searcher.search(q) + # rm3_log = open('rm3.log', 'r').read() + # q_ = self.parse_rm3_log(rm3_log) + # os.remove("rm3.log") + + return super().get_refined_query(q_) + + def get_model_name(self): + return super().get_model_name().replace('topn{}'.format(self.topn), 'topn{}.{}.{}'.format(self.topn, self.topw, self.original_q_w)) + + def parse_rm3_log(self,rm3_log): + new_q=rm3_log.split('Running new query:')[1] + new_q_clean=re.findall('\(([^)]+)', new_q) + new_q_clean=" ".join(new_q_clean) + return new_q_clean + + +if __name__ == "__main__": + qe = RM3(index='../ds/robust04/index-robust04-20191213/' ) + print(qe.get_model_name()) + print(qe.get_refined_query('International Crime Organization')) diff --git a/src/refinement/refiners/sensedisambiguation.py b/src/refinement/refiners/sensedisambiguation.py new file mode 100644 index 0000000..d2a5301 --- /dev/null +++ b/src/refinement/refiners/sensedisambiguation.py @@ -0,0 +1,36 @@ +from pywsd import disambiguate + +import sys +sys.path.extend(['../refinement']) + +from refiners.abstractqrefiner import AbstractQRefiner + +class SenseDisambiguation(AbstractQRefiner): + def __init__(self, replace=False): + AbstractQRefiner.__init__(self, replace) + + def get_refined_query(self, q, args=None): + res=[] + disamb = disambiguate(q) + for i,t in enumerate(disamb): + if t[1] is not None: + if not self.replace: + res.append(t[0]) + x=t[1].name().split('.')[0].split('_') + if t[0].lower() != (' '.join(x)).lower() or self.replace: + res.append(' '.join(x)) + else: + res.append(t[0]) + return super().get_refined_query(' '.join(res)) + + +if __name__ == "__main__": + qe = SenseDisambiguation() + print(qe.get_model_name()) + print(qe.get_refined_query('obama family tree')) + print(qe.get_refined_query('HosseinFani International Crime Organization')) + + qe = SenseDisambiguation(replace=True) + print(qe.get_model_name()) + print(qe.get_refined_query('maryland department of natural resources')) + print(qe.get_refined_query('HosseinFani International Crime Organization')) diff --git a/src/refinement/refiners/stem.py b/src/refinement/refiners/stem.py new file mode 100644 index 0000000..05ebc8e --- /dev/null +++ b/src/refinement/refiners/stem.py @@ -0,0 +1,49 @@ +import sys +sys.path.extend(['../refinement']) + +from refiners.abstractqrefiner import AbstractQRefiner +from stemmers.abstractstemmer import AbstractStemmer +class Stem(AbstractQRefiner): + def __init__(self, stemmer:AbstractStemmer): + AbstractQRefiner.__init__(self, replace=False) + self.stemmer = stemmer + + def get_model_name(self): + return super().get_model_name() + '.' + self.stemmer.basename + + def get_refined_query(self, q, args=None): + return super().get_refined_query(self.stemmer.stem_query(q)) + +if __name__ == "__main__": + from refinement.stemmers.krovetz import KrovetzStemmer + qe = Stem(KrovetzStemmer(jarfile='stemmers/kstem-3.4.jar')) + print(qe.get_model_name()) + print(qe.get_refined_query('International Crime Organization')) + from refinement.stemmers.lovins import LovinsStemmer + qe = Stem(LovinsStemmer()) + print(qe.get_model_name()) + print(qe.get_refined_query('International Crime Organization')) + from refinement.stemmers.paicehusk import PaiceHuskStemmer + qe = Stem(PaiceHuskStemmer()) + print(qe.get_model_name()) + print(qe.get_refined_query('International Crime Organization')) + from refinement.stemmers.porter import PorterStemmer + qe = Stem(PorterStemmer()) + print(qe.get_model_name()) + print(qe.get_refined_query('International Crime Organization')) + from refinement.stemmers.porter2 import Porter2Stemmer + qe = Stem(Porter2Stemmer()) + print(qe.get_model_name()) + print(qe.get_refined_query('International Crime Organization')) + from refinement.stemmers.sstemmer import SRemovalStemmer + qe = Stem(SRemovalStemmer()) + print(qe.get_model_name()) + print(qe.get_refined_query('International Crime Organization')) + from refinement.stemmers.trunc4 import Trunc4Stemmer + qe = Stem(Trunc4Stemmer()) + print(qe.get_model_name()) + print(qe.get_refined_query('International Crime Organization')) + from refinement.stemmers.trunc5 import Trunc5Stemmer + qe = Stem(Trunc5Stemmer()) + print(qe.get_model_name()) + print(qe.get_refined_query('International Crime Organization')) diff --git a/src/refinement/refiners/tagmee.py b/src/refinement/refiners/tagmee.py new file mode 100644 index 0000000..3b577a3 --- /dev/null +++ b/src/refinement/refiners/tagmee.py @@ -0,0 +1,43 @@ +import tagme +tagme.GCUBE_TOKEN = "10df41c6-f741-45fc-88dd-9b24b2568a7b" + +import sys, os +sys.path.extend(['../refinement']) + +from refiners.abstractqrefiner import AbstractQRefiner +import utils + +class Tagmee(AbstractQRefiner): + def __init__(self, topn=3, replace=False): + AbstractQRefiner.__init__(self, replace, topn) + + def get_concepts(self, text, score): + concepts = tagme.annotate(text).get_annotations(score) + res = [] + for ann in concepts: + res.append(ann.entity_title) + return res + + def get_refined_query(self, q, args=None): + + query_concepts = self.get_concepts(q, 0.1) + upd_query = utils.get_tokenized_query(q) + res = [] + if not self.replace: + res = [w for w in upd_query] + for c in query_concepts: + res.append(c) + return super().get_refined_query(' '.join(res)) + + +if __name__ == "__main__": + qe = Tagmee() + + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani actor International Crime Organization')) + + + qe = Tagmee(replace=True) + print(qe.get_model_name()) + print(qe.get_refined_query('Magnetic Levitation-Maglev')) + diff --git a/src/refinement/refiners/termluster.py b/src/refinement/refiners/termluster.py new file mode 100644 index 0000000..31806bd --- /dev/null +++ b/src/refinement/refiners/termluster.py @@ -0,0 +1,111 @@ +import networkx as nx +from collections import defaultdict +from community import community_louvain +from nltk.stem import PorterStemmer + +import sys +sys.path.extend(['../refinement']) + +from refiners.relevancefeedback import RelevanceFeedback +import utils +class Termluster(RelevanceFeedback): + def __init__(self, ranker, prels, anserini, index, topn=5, topw=3): + RelevanceFeedback.__init__(self, ranker, prels, anserini, index, topn=topn) + self.topw = topw + + def get_model_name(self): + return super().get_model_name().replace('topn{}'.format(self.topn),'topn{}.{}'.format(self.topn, self.topw)) + + def get_refined_query(self, q, args): + qid = args[0] + list_of_word_lists = [] + docids = self.get_topn_relevant_docids(qid) + for docid in docids: + tfidf = self.get_tfidf(docid) + list_of_word_lists.append(self.get_list_of_words(tfidf, threshold=2)) + + G, cluster_dict = self.make_graph_document(list_of_word_lists, min_edge=4) + + # add three relevant words from each cluster for each query word + refined_query = self.refined_query_term_cluster(q, G, cluster_dict, k_relevant_words=self.topw) + + return super().get_refined_query(refined_query) + + def make_graph_document(self, list_s, min_edge): + G = nx.Graph() + counter = 1 + for s in list_s: + for i in range(len(s) - 1): + j = i + 1 + while j < len(s): + if (s[i], s[j]) in G.edges(): + G[s[i]][s[j]]['weight'] += 1 + elif (s[j], s[i]) in G.edges(): + G[s[j]][s[i]]['weight'] += 1 + else: + G.add_weighted_edges_from([(s[i], s[j], 1)]) + j += 1 + counter += 1 + G_TH = self.remove_nodes_from_graph(G, min_edge=min_edge) + clusters_dict = self.get_the_clusters(G_TH) + return G, clusters_dict + + def remove_nodes_from_graph(self, G, min_edge): + G = G.copy() + for n in G.copy().edges(data=True): + if n[2]['weight'] < min_edge: + G.remove_edge(n[0], n[1]) + G.remove_nodes_from(list(nx.isolates(G))) + return G + + def get_the_clusters(self, G): + clusters = community_louvain.best_partition(G) + clusters_dic = defaultdict(list) + for key, value in clusters.items(): + clusters_dic[value].append(key) + return clusters_dic + + def refined_query_term_cluster(self, q, G, cluster_dict, k_relevant_words): + upd_query = utils.get_tokenized_query(q) + porter = PorterStemmer() + res = [w for w in upd_query] + for qw in upd_query: + counter = 0 + for cluster in cluster_dict.values(): + if qw in cluster or porter.stem(qw) in cluster: + list_neighbors = [i for i in cluster if (i != qw and i != porter.stem(qw))] + counter += 1 + break + if counter == 0: + continue + weight_list = [] + for i in list_neighbors: + weight_list.append((i, G.edges[(qw, i)]['weight'] if (qw, i) in G.edges else (porter.stem(qw), i))) + final_res = sorted(weight_list, key=lambda x: x[1], reverse=True)[:k_relevant_words] + for u, v in final_res: + res.append(u) + return ' '.join(res) + + def get_list_of_words(self, tfidf, threshold): + list = [] + for x in tfidf.split('\n'): + if not x: + continue + x_splited = x.split() + w = x_splited[0] + value = int(x_splited[1]) + if not (w.isdigit()) and w not in stop_words and len(w) > 2 and value > threshold: + list.append(x_splited[0]) + + return list + +if __name__ == "__main__": + qe = Termluster(ranker='bm25', + prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt', + anserini='../anserini/', + index='../ds/robust04/index-robust04-20191213') + for i in range(5): + print(qe.get_model_name()) + # print(qe.get_expanded_query('HosseinFani International Crime Organization', [301])) + # print(qe.get_expanded_query('Agoraphobia', [698])) + print(qe.get_refined_query('Unsolicited Faxes', [317])) diff --git a/src/refinement/refiners/thesaurus.py b/src/refinement/refiners/thesaurus.py new file mode 100644 index 0000000..5734322 --- /dev/null +++ b/src/refinement/refiners/thesaurus.py @@ -0,0 +1,79 @@ +from nltk.corpus import wordnet +import urllib, traceback +from urllib.request import urlopen +from bs4 import BeautifulSoup + +import sys +sys.path.extend(['../refinement']) + +from refiners.abstractqrefiner import AbstractQRefiner +import utils + +class Thesaurus(AbstractQRefiner): + def __init__(self, replace=False, topn=3): + AbstractQRefiner.__init__(self, replace, topn) + + def get_refined_query(self, q, args=None): + pos_dict = {'n': 'noun', 'v': 'verb', 'a': 'adjective', 's': 'satellite adj', 'r': 'adverb'} + upd_query = utils.get_tokenized_query(q) + q_ = [] + if not self.replace: + q_ = [w for w in upd_query] + for w in upd_query: + found_flag = False + if utils.valid(w): + pos = wordnet.synsets(w)[0].pos() if wordnet.synsets(w) else 'n' + syn = self.get_synonym(w, pos_dict[pos]) + if not syn and self.replace: + q_.append(w) + else: + q_.append(' '.join(syn)) + + return super().get_refined_query(' '.join(q_)) + + + def get_synonym(self, word, pos="noun"): + try: + if pos == "noun": + response = urlopen('http://www.thesaurus.com/browse/{}/noun'.format(word)) + # print(response) + elif pos == "verb": + response = urlopen('http://www.thesaurus.com/browse/{}/verb'.format(word)) + elif pos == "adjective": + response = urlopen('http://www.thesaurus.com/browse/{}/adjective'.format(word)) + else: + # raise PosTagError('invalid pos tag: {}, valid POS tags: {{noun,verb,adj}}'.format(pos)) + print('WARNING: Thesaurus: Invalid pos tag: {}'.format(pos)) + return [] + html = response.read().decode('utf-8') + soup = BeautifulSoup(html, 'lxml') + counter=0 + result = [] + if len(soup.findAll('ul', {'class': "css-1lc0dpe et6tpn80"})) > 0: + for s in str(soup.findAll('ul',{'class':"css-1lc0dpe et6tpn80"})[0]).split('href'): + if counter < self.topn: + counter+=1 + start_index=s.index('>') + end_index=s.index('<', start_index + 1) + result.append(s[start_index+1:end_index]) + return result + except urllib.error.HTTPError as err: + if err.code == 404: + return [] + except urllib.error.URLError: + print("No Internet Connection") + return [] + except: + print('WARNING: Thesaurus: Exception has been raised!') + print(traceback.format_exc()) + return [] + + +if __name__ == "__main__": + qe = Thesaurus() + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani International Crime Organization quickly')) + + qe = Thesaurus(replace=True) + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani International Crime Organization')) diff --git a/src/refinement/refiners/wiki.py b/src/refinement/refiners/wiki.py new file mode 100644 index 0000000..5108159 --- /dev/null +++ b/src/refinement/refiners/wiki.py @@ -0,0 +1,82 @@ +import gensim +import tagme +tagme.GCUBE_TOKEN = "10df41c6-f741-45fc-88dd-9b24b2568a7b" + +import sys, os +sys.path.extend(['../refinement']) + +# @inproceedings{DBLP:conf/coling/LiZTHIS16, +# author = {Yuezhang Li and +# Ronghuo Zheng and +# Tian Tian and +# Zhiting Hu and +# Rahul Iyer and +# Katia P. Sycara}, +# editor = {Nicoletta Calzolari and +# Yuji Matsumoto and +# Rashmi Prasad}, +# title = {Joint Embedding of Hierarchical Categories and Entities for Concept +# Categorization and Dataless Classification}, +# booktitle = {{COLING} 2016, 26th International Conference on Computational Linguistics, +# Proceedings of the Conference: Technical Papers, December 11-16, 2016, +# Osaka, Japan}, +# pages = {2678--2688}, +# publisher = {{ACL}}, +# year = {2016}, +# url = {https://www.aclweb.org/anthology/C16-1252/}, +# timestamp = {Mon, 16 Sep 2019 17:08:53 +0200}, +# biburl = {https://dblp.org/rec/conf/coling/LiZTHIS16.bib}, +# bibsource = {dblp computer science bibliography, https://dblp.org} +# } + +import utils +from refiners.word2vec import Word2Vec + +class Wiki(Word2Vec): + def __init__(self, vectorfile, topn=3, replace=False): + Word2Vec.__init__(self, vectorfile, topn=topn, replace=replace) + + def get_concepts(self, text, score): + concepts = tagme.annotate(text).get_annotations(score) + res = [] + for ann in concepts: + res.append(ann.entity_title) + return res + + def get_refined_query(self, q, args=None): + + if not Word2Vec.word2vec: + print('INFO: Word2Vec: Loading word vectors in {} ...'.format(Word2Vec.vectorfile)) + Word2Vec.word2vec = gensim.models.KeyedVectors.load(Word2Vec.vectorfile) + + query_concepts = self.get_concepts(q, 0.1) + upd_query = utils.get_tokenized_query(q) + res = [] + if not self.replace: + res = [w for w in upd_query] + for c in query_concepts: + c_lower_e = "e_" + c.replace(" ", "_").lower() + if c_lower_e in Word2Vec.word2vec.vocab: + w = Word2Vec.word2vec.most_similar(positive=[c_lower_e], topn=self.topn) + for u, v in w: + if u.startswith("e_"): + u = u.replace("e_", "") + elif u.startswith("c_"): + u = u.replace("c_", "") + res.append(u.replace("_", " ")) + + res.append(c) + return super().get_refined_query(' '.join(res)) + + +if __name__ == "__main__": + + qe = Wiki(vectorfile='../pre/temp_model_Wiki') + for i in range(5): + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani actor International Crime Organization')) + + qe.replace = True + for i in range(5): + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani actor International Crime Organization')) diff --git a/src/refinement/refiners/word2vec.py b/src/refinement/refiners/word2vec.py new file mode 100644 index 0000000..dffa864 --- /dev/null +++ b/src/refinement/refiners/word2vec.py @@ -0,0 +1,51 @@ +import gensim +from nltk.stem import PorterStemmer + +import sys +sys.path.extend(['../refinement']) + +from refiners.abstractqrefiner import AbstractQRefiner +import utils + +class Word2Vec(AbstractQRefiner): + def __init__(self, vectorfile, replace=False, topn=3): + AbstractQRefiner.__init__(self, replace, topn) + Word2Vec.vectorfile = vectorfile + Word2Vec.word2vec = None + + def get_refined_query(self, q, args=None): + if not Word2Vec.word2vec: + print('INFO: Word2Vec: Loading word vectors in {} ...'.format(Word2Vec.vectorfile)) + Word2Vec.word2vec = gensim.models.KeyedVectors.load_word2vec_format(Word2Vec.vectorfile) + + upd_query = utils.get_tokenized_query(q) + synonyms = [] + res = [] + if not self.replace: + res = [w for w in upd_query] + ps = PorterStemmer() + for qw in upd_query: + found_flag = False + qw_stem = ps.stem(qw) + if qw in Word2Vec.word2vec.key_to_index: #in gensim 4.0 vocab change to key_to_index + w = Word2Vec.word2vec.most_similar(positive=[qw], topn=self.topn) + for u,v in w: + u_stem=ps.stem(u) + if u_stem!=qw_stem: + found_flag = True + res.append(u) + if not found_flag and self.replace: + res.append(qw) + return super().get_refined_query(' '.join(res)) + + +if __name__ == "__main__": + qe = Word2Vec('../pre/wiki-news-300d-1M.vec') + for i in range(5): + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani International Crime Organization')) + + qe.replace = True + for i in range(5): + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani International Crime Organization')) diff --git a/src/refinement/refiners/wordnet.py b/src/refinement/refiners/wordnet.py new file mode 100644 index 0000000..73087e8 --- /dev/null +++ b/src/refinement/refiners/wordnet.py @@ -0,0 +1,48 @@ +from nltk.corpus import wordnet +from nltk.stem import PorterStemmer + +import sys +sys.path.extend(['../refinement']) + +from refiners.abstractqrefiner import AbstractQRefiner +import utils + +class Wordnet(AbstractQRefiner): + def __init__(self, replace=False, topn=3): + AbstractQRefiner.__init__(self, replace, topn) + + def get_refined_query(self, q, args=None): + upd_query = utils.get_tokenized_query(q) + ps = PorterStemmer() + synonyms =[] + res = [] + if not self.replace: + res=[w for w in upd_query] + for w in upd_query: + found_flag = False + w_stem=ps.stem(w) + for syn in wordnet.synsets(w): + for l in syn.lemmas(): + synonyms.append(l.name()) + synonyms=list(set(synonyms)) + synonyms=synonyms[:self.topn] + for s in synonyms: + s_stem=ps.stem(s) + if s_stem!=w_stem: + found_flag = True + res.append(s) + synonyms=[] + + if not found_flag and self.replace: + res.append(w) + return super().get_refined_query(' '.join(res)) + + +if __name__ == "__main__": + qe = Wordnet() + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani International Crime Organization')) + + qe = Wordnet(replace=True) + print(qe.get_model_name()) + print(qe.get_refined_query('HosseinFani International Crime Organization')) diff --git a/src/refinement/stemmers/__init__.py b/src/refinement/stemmers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/refinement/stemmers/abstractstemmer.py b/src/refinement/stemmers/abstractstemmer.py new file mode 100644 index 0000000..91d21c5 --- /dev/null +++ b/src/refinement/stemmers/abstractstemmer.py @@ -0,0 +1,63 @@ +#!/usr/bin/python +import gzip +import codecs +from collections import defaultdict +from nltk.tokenize import WordPunctTokenizer +import re +import sys + +from cmn import utils +class AbstractStemmer(object): + def __init__(self): + super(AbstractStemmer, self).__init__() + self.tokenizer = WordPunctTokenizer() + self.vocab = set() + self.basename = 'nostemmer' + + def stem_query(self, q): + # isword = re.compile('[a-z0-9]+') + q = utils.clean(q) + curr_words = self.tokenizer.tokenize(q) + clean_words = [word.lower() for word in curr_words] + processed_words = self.process(clean_words) + self.vocab.update(processed_words) + return ' '.join(processed_words) + + def stem(self, files): + # We write files to a -[stemmer].txt file + filename_mod = files[0].split('.')[0] + wf = codecs.open('{1}-{0}.txt'.format(self.basename, filename_mod), 'w', encoding='utf-8') + isword = re.compile('[a-z0-9]+') + + # We can work with both gzip and non-gzip + for fname in files: + if fname.endswith('gz'): + f = gzip.open(fname, 'r') + else: + f = open(fname) + for no, line in enumerate(f): + if isinstance(line, bytes): + line = line.decode('utf-8') + # We drop empty lines + if len(line.strip()) == 0: + continue + + # Clean and process words + curr_words = self.tokenizer.tokenize(line) + clean_words = [word.lower() for word in curr_words] + processed_words = self.process(clean_words) + + # Keep track of vocab size + self.vocab.update(processed_words) + + # We output according to the one-doc-per-line format for Mallet + current_line = u' '.join(processed_words) + line_fmt = '{0}\n'.format(current_line) + wf.write(line_fmt) + f.close() + + print ('Resulting vocab size: {0}'.format(len(self.vocab))) + wf.close() + + def process(self, words): + raise NotImplementedError("No stemmer here!") diff --git a/src/refinement/stemmers/krovetz.py b/src/refinement/stemmers/krovetz.py new file mode 100644 index 0000000..168e885 --- /dev/null +++ b/src/refinement/stemmers/krovetz.py @@ -0,0 +1,27 @@ +#!/bin/python +from stemmers.abstractstemmer import AbstractStemmer +import subprocess +import sys + + +class KrovetzStemmer(AbstractStemmer): + + def __init__(self, jarfile): + super(KrovetzStemmer, self).__init__() + self.jarfile = jarfile + self.basename = 'krovetz' + + def process(self, words): + new_words = [] + while len(words) > 1000: + # new_words += subprocess.check_output(['java', '-jar', 'kstem-3.4.jar', '-w', ' '.join(words[:1000])]).split() + new_words += subprocess.check_output(['java', '-jar', self.jarfile, '-w', ' '.join(words[:1000])]).split() + words = words[1000:] + # new_words += subprocess.check_output('java -jar kstem-3.4.jar -w ' + ' '.join(words),shell=True,).split() + new_words += subprocess.check_output('java -jar ' + self.jarfile + ' -w ' + ' '.join(words), shell=True, ).split() + return [s.decode() for s in new_words] + + +if __name__ == '__main__': + stemmer = KrovetzStemmer() + stemmer.stem(sys.argv[1:]) diff --git a/src/refinement/stemmers/kstem-3.4.jar b/src/refinement/stemmers/kstem-3.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..d811f3592a80418fa4a99dc092d3433768461c75 GIT binary patch literal 327037 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­#%6ROs5m@i1{H zYp_vh@%!sWi*Y_+<1r40aseVjQU+uihzrJT2BHBZ0f#aHVgzL34<Ic_FvSyyFA^Ne z4oE4IVjzP+8Zl)X5L+ZTizSdIQ|P|I0)CZ<DxnC(hw#X1z)e4af($n?eG7_CjKMeU zf*3MxU%~A+kcWdi!P9(v8c%Zs9!dy;t_p@*!b1sAxc&y)mv9>%nofa&4w*^#?hM#Y z#%Wrxz|J0cOBuceKkNS$kD&;{X>MYHTMwb=#SVVgz1V4l!VNpuvA|9p6fErEht0wc z6ACJJ%CW#sJrs&p{jBL4XDD9xv&uY;;ExxiEBMf?|1KRVah508(iN_-q{A}bSw3w= zS2V%029{x0TBvT>&^z$2xVO!mu1G#}c4i_5cFEB2GE&HjK@DC8RS)XyXHb@)TtSV! z>1PFP0+I?u2MDVc$TlFhtAVTql8s~wkjp>{kURi#90{g40(paEGmtDGen{>E*$1Qs zQ|y6MBH0S05J)GIM?m6`V2TTnZ$Nr+mUJKvNbUjI1%!+#c0h`d;4D{w)FXKa<RlVI zaRSnf1ZT+u5|5+~NC1!#OmP6hM1r%F0+~R9=aPg3Q`~?|198JyQh;axq2jr01wzD> z-(c|^7IZxN?ZEuunGAdeha<tFAC8{5iVlD7A}k2_oHZ<#!NLR*E&c|&AE+rb@`3tZ zf>#tnDn94?J1kORaRO*LrtSvn2@79%A2kbh_5dq`tCq(?Kp0%L+a4eXfV3gW0}_M8 z0!Shd9U!cqfNTR|izE|>7my%KISs@Q$<ILc0jWWf3nT&wrkn%ffCOjR1%$O6y4g^W z(c<@a2y8FL;rADh7KaJ|GJ=E-BmoJ=B?Hj_LdBuB0wDrXTm<3)#0^tU0r5qGL+t@l zh9n0_7!pi53&a))4&?<T2nimLE&MW4;8$1!+lmS({NN!L=0<>H*+8L>1>R8{#E>xt z=RJg7Gw60h(TjO_n(_EFzS0T11<*}_?g-qYq7(`Z*ruAo_B3o$@nk|Evkc$;7i<%8 z8vL67*Vzki2}1{;lKg)KPNRbzoW>6e{8}8afG<)Wj|Kb&06(}=Is!juP$Bol0)7vW z+hTz^WGpa;hy~^ZVSzbr3!tbxuaHw0NQt38KUKV2*+*Rib=4fXO8I#O+p>>3AC}kV z$TM!7SFC{LN?2CF^6HXNx3|~MD~{}+H=|Lvs*n0dz-+~H1K2$X4TxG(4(jn@P<KHY zL33<1C|^)BpqBphR8jjUkPASps(@$#$p+%@4MYg!3X&T@ZX&@HT_A6e_yGA1WIqy| z?sp(nn6d;&C6Zl0z5?k$atp{qB$#3d<Qo#4WeUg!B!2<P1rmuV1RzB~x^R{OAdisT z1acP%rsxCdMuM|QfSf^c9Y_g~AxzN$!bF0zh=53t;JGv+!4x8pX(Tv{9LORd(ReOt zKnx&7pa~=c$g-QTSObgeaP&F5;e_|YGXi)f51v_rV^Cn%11M=HER=8oH%8hHi;Iw$ ziF6-OPiP#2-97jUxMl%9w+B*-|AdhWfqnt%vlk}042yi+fvXnm1y&AMO~R|z1;Rmc z1xOu|>p%_z8AK8UWF8P3B$t3>138Q-KLaTM!Z-|M36N?ezXPd6f+_e3bs`A_q7Ebq zNj?x;_&}w2;YDD3Fb==JdbBu{Ay^UG0w7Ez7#9d+0tpT^7l;v%(O-dN0CC2Y-9YF- zC^!@WNGX!vfRrP_lmkH8kl;{iKmw8A0Tlpgz!Wd&HsPIFVo?FbK6t1G9+Kjz*1&B@ z)1e^49Z_&zeQ<n?!9ygYdjv&2=HV*?;OP<U=0SG?x`}W>0w#vzwQYrMB5pUqHW5$8 zA2KaqJNY(jdtianV8<0Me)KB1GI+Q2e+5o+0Xjk0!SfHoPA(L^*eSsRJ84k3VFxe3 z4LjLTu&`5v1$Hu^pkfCPo{Am1u{=YuT1b_a8OvL)E*86O$dVFsjpZJd7Zu!9Lh27# zroq<ji;A_dd<)BLSXNwAoC@7GL$6yYq!#bfQuIf{Mwnl-f|LQf`?VC;A&PSclntmD zOHdx58bA&10mT9}4~Pxqo>~D!4ai}4AlHEC0AVnIm?6QGRY1IuYzJ~5NCA=tAWMK$ zV~QCNOC;NXQ~>cq@&t%I5=^lM5`hF~c><&pNfQutAW@iN0z@B356*H6hy#+xK&+8q ziY1UkNN|=%K<be+0x<+4!W0W2PDpT;Y9R4Qm_S^RV2Uk}1SB|16OaiccrJ5+7(t47 zIS>^f&N$0oKs?|EoV{W33+#jd%iGtipx{B7-~s|jfv|fCDE((xY=#9F7rS9`4PJT; zXvh+=n-A_DfZfFq)Pkw_++J8%;Dz1-iU&skT6zN}IR-oBu;YwZeF74F;i@U=K<tp* z1QH2k5Q!g<vq0LAqySL^5{M~BffN8~*bC%15L+Y{fLJ2IlyD%ONZ=Fdj{{PJ1V2E1 zAbd<wgDwk?2fx31v^dmB=#tUm_veHb<D!5}Ai<%MfQ$f<o(G}=#1-R?0HFg(#Gyif z5RuS;SRlca6F}OK;7~C@%8;Z2(E-wgDaV1-0GYWAU0b-bnJg%3;1^aRP8R_WvEWq2 z->~=#iXte2Fa{6N0b}q@hj9BY6el5X1Ye1RCt&wFbd#V<#J5z#LnCl)Ge5z$2X5EE zwh9z(`yn$Ewu$iWnM+vUG}!Tlw<O~b<>07T3}S)P6kve^bYg+8s>h-niU}wbe?mdW z0{>duuz;^gT!RJXj9`H|WmsTNFBaEn3NdRZ6y-F<33Ia<-&}3E1vFo;7En*`l$JGU z%gg_yDOSO9CoJ#7@)}KX2bP5gR2A>7pclIDnPPnrY<&EE)UEX|*oB5EM8%-;0@VX* zU^l25P?Nubs)4u72BHS!;0_?qfGh>_;5LvKK&-2Qr~>gqvJ=QZK&~LE0`e~sOqmD7 z5{V~}zk%#WQURnL$X!fP2NHn<XZZxA14%WIaU_^B7l=NPPdLj<ARCa}0n!TOB&MhV zIfMjf=>YNw$z34BNH9eOh!YZ=g#+Xal1d;vAj6oV0VDwl&cX*GL4xNZLjoyZW&u$F zvJq!t16c$l7SCljF807V9)z7`z(U}}4I%c+d|32DK&~Iq8$hqaV%JZwcmRtK+*t{i zaT};V(0tt84?)`?=oF;p!E@{P!9o=lw^jkgRCk~ju-J%Ky$W`G;AUeBA@M!DxCE~H zi#L!kB!_@F0^uMj1u_OC06v{BTY%^QdEyVm42TVqt3ci$!IYgq{E*;Zm_3kcBqcz; z0pVfFb|4Nwrc$A63&-;Whq4A6g%-cRZnPNZ12!Jxa3~ibA|z!%rh&L%+-4veK+fS% zCP0jU{P+V%3ldE61mcSXhq41wili9GAdp5(*#^WG3C>~(r0E89-(Ug1O1@M=5r_}r zk=1~kdIAL*Zer>d6rC7@Z`uVhWZb@j+m?`rgFC^~e0&;Da|9kb7X)1u46lTT5}<J1 z3)`1)8y=cUfr1X1N%-yz*iOc2TCl**9(YR`z6C$){}qp+2*PP@Vu4!^q3Fd9e%HO& zX@tTJJJ+$mP8}31?BIvZ!VVJ(Dt5}Tz)n3Bik1D;shV|Atm>zhdg>}-uIDH|Li5qz z(z23u^01m5g(EEUV41&8K3J8bcnr&GScdI?sc_DQ-hto6Zf&=66lc#IpJ|JM-6&{y z=_<yGK@I*4svgwY-#}G@as@SJ*-s6Ge}{A|6^IUyhFT!ofY??5Sqmf^$rd1&ffOKl z0OU9lOmPJA2FYe1SwQ@d+y}A`NDZdg1F1x^6-XhFP9%?j#38{H7a-q&@Nt%OAPz|G z0oetFj45_Nijd$eSAf(bc?jer5=?Od(v1XX!IO$dQU@de$Oxu50AV7*SxSLSAi;A< zLV_u7K&FAX;w&jZG=L=HxoibO#FXD)@f;R(Jo@dx{Nb4ld<KUj!J;3Io_HrmF}V^J z1bpr;ESAB-1QIP)1KkhQ6dL(JeRsnviXj!B^W6uFR9Kt<T8^o^fqKHi7v7hc1v`6y zmBCd{#zH_CT(#>SAP0c7A;|+0gQOftA`l%QO+NwI2E-OgCJ-+mL6~wHh#!)lf$RfP zgCrM71QJX+2gCsh&aw*#>rd!rLqSH1-`^pyy%>kzUp!hIDgej`5;~9sBp8<rL<2}N z4z(2s5y;F%ARa*6Fy#~wUnDrx9w22%a)5*(!IZN=Y?0tlUO<A7-~rjfFC#gAg*C7( zuYkf29%5l`1UObT6#7`;9mPQm8DntXL)g6u-EJs)F%M5O9-qcnI$_rjx+%~dfqRsf zLZJcM)Elrp4ck;anGnb<!*~A$+eDlOzvlmS_QG4j(7~rP`M(0E(ZLQ*<A())Ee=?~ z7daV^1^fmusR4!JHWa>C!0!Q*wpd^e84JuIVu3k9SYVFZYA7mG6_eD}(xA|v*@}N| z_fgkEU9~{2Q=Y1LQQ1dTh2^yc@`4+w3Nu))f@K9PukIUVy}g#IIKF?$jBVYWKI+wg zd5Sj%uzL_15Vfux)Z@LN?t(Ic=2!(NUr;lkmj1+6-2W5E1t3;cK(v5l13BOgL<r;x zk{dv7BEb}0Aa9WP0QnANKN6hocOX@mvIIyal3hT)0_i|<3&=wxm|_Uz8xovl3djZ| ze*wt_5{W4UAVokv;w%F|9wE62<Sr6S(Ff9v1ZR-|IfLXnkP;w6n4$xOi3Dd60g)iV zb7@3^DMTRCNN^T8kVQaF<GG{(F@ThRHGyOR(Y*<aHL$o2N1wABPIx~&BY<b};F)ze z1_gFKfI9Akg%U2{#vHf9;vytwBHahn6B@^0cMrY-uK8blZV#ju{|O@%0{sHiXD>{0 z85a4t16Td;USQ>L)sA@8x<EKct^lb+avjKFAcIJPfXoA8gX9vBY#@g*<!2xTKpr0k zvIIyqlHY+;BEb~=ggTJ~0#OGNg(M${EqtJpc;Q80doT{azk0Mdlp$CV+5#X<Bp4S6 zWC95eH5Z5xkng_&$pGSvDZ7Etft<ym2tZ1a{05{P38owX(uM?wQUel*1P`bHNCT#L zLAMF-%o2+VDE7faHSo|Ro@x!;#$-AaWVoZVIIli9KE~i7lF>baq8{_`l>zYd2zK+J zI|1E9xS)TT7>?Jr6}E}E-2~f2JQ;t;w1Dm8+pz6{1x|w<SGf4^SHYFRyC?rw;4~MY z6NDW+{~+w-LeYzz5-hNj28A1T@B-YhlMMw6J4IMvCj$y9cJSb-*rBhM7bq%()X6gV z<Fv2t6|*)}NP}`$%l#^|6zz9})Nxp*!Pf08g*_}=VVMofiY!H3=)Reny4yl($-X6u zZ;`MO=J!IeF#~q@FHuxN6z2{o8&ENopgce|fEwHbiUn#O5F5yiTLDB3NPs(#Yd~~> zJYfJaLxL%*fOsL<4&*+N0wfJUmH?^76f+=}NVWl~0OE(_2@rcEm|_hi0twFY1V|^6 zCLroSqA<k-h&~V=&T<Qg1Cqx;tdU@fC6Gf%aF$0v>X9@8F$5yQ6bm3uNN|>FAn{0; zKwOYuiY<@?BsfbGkO?GsE^~nxLCW}YASysyaF)M-c)$&~c*Eis*a-oax9^4G93GSj zE+AlIAnaZOO8*%an_<Dl#co(!gO^?d8nRE!^1<B$u)7$7S}+x#+Y1W|ywF=f@!$wR zOK-p=$6%)%c3kkPPe7tCT=lthAa+P@0*M4Nh{O-bSs-mlQh=xd3B;76Knj2~?gerj zh%J%}KrE49N;r^CB=8A+ivv=F1V2E1Abd<wgDwk?2fx31v^dmB=#tUm_veHb<D!5} zAi<%MfQ$f{IuAqzh%3e&0YV3oghPb@AtIpxu|R?;CxEme!J%S+lp#q4q64G}Q;q|v z0V2B$U0b*_Sr!yE@Cz#mr;C7xSa7Q2->~=#iXte2Fa{6N0b}q@hj9BY6el5X1YhYl zE^{%eA+BjY_g>?k(bS4|_)%xB!x;gJA;qkpyyhw`m^EwG{8_vRC68+@&kAJ)vt}JO zn?1_{y5!SgwvoqA#+{BnO%6XE5^Ea~6MOumt=As-Z}%gyN7mYeL>`HWIb1w1)}X#q z@;*KJl<)|DogMrqhWW@r(xE0wC6o`d-v0l8dXlew{4C>$@0C_^=hxVH*7?d41{<$$ z&plZ2)5zDRzoz+O-UK(vji>QWww$NIm962?-^o_;=v*0z=lf1(%Jb#Q*7Mrl$*g#7 zT$wY^_MOa_XUmnX<JG*At>)EmWgB_qcQSJxnJe4C8+j+Q;f-)*t~}y9*$N(!D_hGe zdna4PE91%>c|q@FX1pM-%%0c#PG-&P<;q-mZtr9!JU6b)j>mc@v*fY3GAADOoy>wq z<;om*igz+wp5jREvqIH~&?>HfNbSp`xzF|J^E#BOY^pN-^J|~nv$E2E!#;h_*@|fS zbiqC2s%4h!o%hyN&FQf6uRGeBZtv7#;2(3e^@6=ahqM3K(bf!mw~jgfYDcYU57%@U z`)41uPJc-1(DwH_YJK71`i^z}Z;o1LJaq0@;BR^KF74sEj@AB^NAIRT+}NS#A93{V zg@+qDHu`@%dN<>tYlpJG{?U`Phif~`{fmyCOn>OuvDE+2(UTV*+IMX5?>>4m<DpB( zB7di&!?cHX9X9^Vqr>SBojQ#Cw^bQc1y;FMX?Gl}O0Jq+wXUPoKh1wh)$0A~m3j8G zhdTS`R%W(83lC8b*~Ko*vQM>Fk04hi)k<DW5j&For$Y?S$1U&J?5`4Hm>RdT<A{Go zh+#^cX~%AVj}XJOIIE6R{w*OT=i`h!JpC;~N>bxicbxDq4=G8BGw(Ry9~M%Q7H89O z)_*W0;C$SQj&1%rApxmzt2&PR7lZ_)#F=&M^Y;r0NQ<-Xi1Y6Z;hm2&>DcA(5W-81 zv+OwOUmwCtiL>Yk@Q)ASrN!BHB>7K-xSStf-m%qRBg7?jd}T+7KRv`HW!$u5kH2q- zOWL?qM~r`4NaOi&;|?!>+mOc8@zos>{xu<uDdXlHhy2MQjcMaH9SQy;AxY=QS9Eyz z6GM_x$5(ZP`Im(xrHq?(`1uEgB&Cg8cf|YmhRDv3n{@d4yM@S7$1OX^{;UvL%D6>G zkUup<mNstNLG8L;8}_VJH(|YG+0ebN{@Rw1G?&>-wFF~{=}=UpTKCH{wE>YD-7Sl1 zw+_vBdg)WUXJ{ewyo;Kos;lluTb_%Gq_`{QNL#LphNPiu>_{8Eah4>tOYMklPUC#Z zwXW<Vwt0<8lFMCQM{IK&7fSATy*Xk_Z=55^>asjilhe3BQqfg;q$aOXSyI>)aik`< zagpRn*S8}z^v2ne^e+7)<eWxT$*r!UBjmisd6Fw#hmMeQ8`UL`y1I{$>5X$Gd0kFN zMsga}B-LHaBO`f@DrdBqDoh=w29xHZ%OobuV&*hjNS2?O$IJ?NULB%wWaI+xY1GmB z+U~CBU3+TFkJ5vEpY!z-h(k&D6d8>~iM&fCn0PTsQ^M}b2qtDFEt3ekJc5atNsA@i zu9je8c9MZa++`75b}>m?^17=$xGXD4Px7TJEVwK)X{qF6*I;m2c9M}~vP&m8=wgzV z<V9COa8Oo~uH@e?zu=(Eq$QH}uFl|~>?A|Uc$Y(P@5Lm7q_wL)xHl_FUozYkAKaUn zq$A;VO$7I5ClMvGE{$Nfi!x2g^DcU@Tb68@q`%8I*ez4GSn|HBE!ZtvW*`~svJGZk zlxa)ebkzj2vSfOaZ(ZbIR;FyJq`PY*n3XLvl1z6IgQ*u~T9THovS4bKOjk146%<U( zlr52TcJ&5Rvt@>oi7vNb#YGuG($>WaR%FTaB_mzbU`3`(N7CD+2v%gvh@6$hSEEB; z>gL)hhgoq*#bQ#Q_tP)Wu3ofLE!S^(cJGvdflkYF@u@k*nikJ8PiYq~ws^j(?`^7` zB`1<p*Z(%f&VqB86x07U&CZsSNE++6I$yV(vxTJAZ<SiNl5>=l-EWmrXUh4R<kfGL zR%gXIO?uN`b-vD+vy)`mUzJ+7niEc{?5|3xGv^#6Mf6vt)!A^)k-qgup08WM*-p~$ zk4&vw#R(-9^+%@EnQ``$4)sT-)md}Skh=Sa&exf6d`M3HL#cI^oG22re<)>7^B4A) z7hj&Q5_rG-(xUrxRsT??-NilZJHijqUrAd@34-;}g(U0Z4V*Qc#l?3>CZzY#l9wM< z!h(twf}xB$H_mL5iqL=-vxc(*{&Y!$^cWIHi{v3RxDd0RvzF8%G{}f?=BSb^gvGR& zb(~eCa$#|L%tnqbDNI;=A!Y-|ku)eQ&WLg4%p>Ut57T1Sa?D5t!o%q?j+`YVKjGmE zG4>pLQm626MvMyw{^cHF4=u)yV@;|T_N2!+aSTcE!k!B;4jdQKgs>+g#*H(Vq#<;s zjjiFBkmy3^^f3~LK=KtjUl?1@u_Lt!oioOqIcg+ZVFPV!9mkSXBWy??+sM%;k%bKx z#x`)ANF&0Aj4@Y^3W+F8q>ZiRSdhwuiRojG934`SF!92eJ;#C6D@@E7bKz)^+=Mf< zF*}Yei6xv#A9LamNmSv?g)s+?8%ZIY$#7Z_Z{BnDlt+Ia+c4W{QM|JagAmP(wh;O} z8-DpP`s87i&KKj+Nj<Y1nscK=dXyYqv_`8j>iRfYPWqxDMob?k(@96v!x-!1WIGW> zGYqvpn~O|M(KAMNpG_8XnMla+>a)pYE*Aa6c++Q-%`^~wXIS=CUu0^F{$^D6RcA5v zL|+*Zebt%FrJ_%aZ++F-Oe4`0L%%QTB2!EBl2OzbmBrK*4KNP%MP)LVh&mYEeNov= zLy?5x)F-;gB#1Z+W}hgFsV@>S68e^&N{CK4H6886$UilGN+tRYBSE-GxIem*Vc)Y+ zq$vtysP~vhsnzE?<v7iYUoDz1THn)nYJ$zvnV>SJ1tNOFEKv$WMPQVZFkkc+BST=6 zm!KrN#PARp<t8i?-D9)}jOYn-M41c=L1|9H0?{2txu7&JL0NQ_5hf_jO;{v)%or4u z(i3KjE--WifjJ4PqMM8YL113OJkjqAKS5w_f;#;8_D(?{Jz=gWm*F7b=On0!?lS5H z{JaDeQ3)enz|T$45H&I;1bq7REKwRmL*SY-JzsR4K^M5@O)H7=8NLG7-06j)I!2qo zl|DU3l+CaeH04Y$5LGg21WkF<%Az6$S<sX_y-37lj0l?O)3Zex45A=8XIfQM&L|Tk z=S|NO6)=JX$+^?&qIyQJAelZrS43yH3FJA`YN8qjOCZmiRuPpkr~-NJw1$YqPzZ9L z6{(U#8@QB^(U-#9=lXONzEXotLnbAE^oiKYS-*`PBX)Ks+CEhi8#gSoWqXO&HO%2# zQR;-P=?+eO14@jr^@4)~-<dKdY|U_R<Ika}39V`MYxu^LY@u~}J&CVP@e*2Js9z6% z7~~tFbw<52e*wi(c$Zecj=!2xDZHCrzmcy;i4fksP``n{k@8J=H>2K_uT0Swo}|^U z<(pHAgeTMM9r;TshlD3D)Z6nnP`ZUDGwNOVizrUQVOqT%--f~z4yV^U@r@|k8jKnO z8(bT-`NtZP8)i4G<Cjv>C`%ev2ddZPIne5L0_WCbc0P;fSMT4&F3NI9bx<dh8<IvP zFQ$q7WXg2E;raOG{LK`Ve#6xGmHZ==jDEwEcvJpvibua;TD%qi6s4uV<b1p_-;-j| zUy>TXnty^)-d~auZ_YnJ3F|LOi?`vQr4055oR43@-$v2t4@iw)#Xn9d=nqJVH{<W4 z`1J>*#ar{^D4qSh^YJG9T@;6YUTVB0|0JcppO+GE!4IIs_w&-?ZTU%*iGG*!6U+Hq zDH{DQsS_*tAryMQOUi^Pe-FjC-z9CriXTI1>u)?iVa)fU*!DN3PORofP-^-cQzp#$ zhbZL!#<U3=egb8rKk59$3cd%0*q@X-v5Fr?DeF&4nK0w~QG)uD(k86=@s!?v+4%_* zzAweCUzR#y$tP1-{j!t^3w{uV+Am9+u;o*w*GI#imFZH~%a_gEllG6c^ryMaW~ot) z<)$-HiE6zs<3|G$HF{e#Mz_w)cYEnOx@Tq~>%5zqyh>UpXv=d`krzv21Z}x)8uA9| zn4pc$nk7$_stIg!So7uAq}c-7JeHFDveZjpo6A}#zb}0wu%)x+$g`xDf|?xG0(phB zQc#n}QkEA=BLp?MtVQxC(r<zqI%~E(U8*l2=de`ex1>b^avp1*{EGCDfSk)xmp_tr z3&?cVTzQ_<NidSbQj=FpnSzl#mP)b~ONFJw(qPftbXi2|ELIN7LcTnC9xE&8c}>5D zVB|vYQ?jsrv|IXIx@WXpNbmD~-m6a~&LoKy87!h)E>-CxUZiTu+0u+YVit9oTp;!6 zBW6+;%em5)K4Lc2KrWVA^p#ztYRg|s%lpc*sCx1*(y+d=OzKkkN9kZ+SvJ*3J}K4d z3%W?vlE07^^aW*6b>;s`{rZA3sY~ST($2o1Y^tGrT<Xx*dyz_zw@T~#db6nd@?mLw zUvDN=N6wQ@^z~*_iE^1#qtET4LR0=+O7C;aQY@4AOMUy?G8K#E@1<>hZrKV0`IywU zk9AR@Eq^1e>0@On^yJ^9<UUrWVyV1aI?~6=Rv5{rrNln!MTM5UMOxNJ%~I&f2c<!M z)J(+^d8f3ukD9G8lut<A`V<!x1bLg3)u+f(=*vf>)ILR~LPy>!RrD#c6-4&R)T{GD z&6n+3lOAlvCZ&p%G`*MqXZ**GHJN`FJvFXXHJDTI)MQk3PU^4AjW4Qdr~bCwWTocY zEo&^<kxF%hx0}~kun#N65Z-QGW6Mrd8Y5V3s$I_BqNGN!+ETlceN-u%V70l{l>M`k z7r|<4trh#U(i=k6rdnh6P9;l1)t1`T>~N(@Le=J4bM`@{2tw7?S{wE`rEi4DO|>i7 z+m-YQky~n4u|t)L2$7p>&Di^u4iO@^)>^aAD0LHtHr1N2eUzLCLtAPs*-=VN!qDcQ zO#fT)pV@yVE494M|Fc-Od?jJXbIp#QR@~P9F#oI4R;2{3_45mrtW!6z*RU6--cd49 zdOu%c4*zHyl&a7g@~CxV&sI{=HgJz#!(O43p>41|n#9&p^3XQe20tiqtx}7&fk(76 zTUE(IyVyN?9eb5hxpwjP=#6Y$r7-Q{ZP6Rpj!J{t#U9bF?0HH$+K1hv*Rsu&3bYSz zk9K4)QS#G1ye-<EZLid+eb^(~g{`jSpxxshZO67&s@Lw>9__?7REpQ`*%s}<c2Szp z?(v9rW6xF6&~|noUBfm}qH8;EA0@E~O1|38+eX*3?UdTIojpdK*=kC*+70fb>)4h` zHQEi^M>n$dmB`u++eSCAos>qj8$3o`*(ypz?L_y{wQLKeGVR3eqmFDHr6BFZZKL*V z2c=%^M2}GywuX|M_Kf?e9otrkr9HEK)QL@0qH51<8+Bm2DJisPJV;s5=FhIGdJytf z7<iHLqMcXJ2=kfqEwp`%hs+<$Ke;92o!O81Nzcx&G0mAD@{G2|?CpFtTAe2R)2hB; zh!&&C@g(U8dT3*s94``4Fhf(*wAsPX6g;D4YufB&EE5Q6UYa(ZjKzX~Xm2!aych<8 z?=(xz>KzPi!QZq>&FY;DJ;7I6gl4rTW2xX1?VDz`7sE&}Mbp=e+QHBgyrdOrM(t$i z3I=G0G^0EjO9UOXZp|n!hM_=0bJ7&;U=Rcx8vOIpPKLffL`%?Is+urAL3Mh*7cF0P zT2*EK8(M<)BJKV2D{1!6HVQNafi(4J=0~z?cagkF7ot}S<_p$8YgC<B(Ni!=rA=#z zd?~X8DKr%=BX7!l!C$ltEh8U_lHd}}L(6CvWuf36twqbomoi6?Nwd%@^`<Nk+@Y0g zmHJSW1y^ZdTBW-viv*8pgIcA&l-Ys{G##x#Z;GnmCapj#(1$Wl@H@><D{vP@UGR|B zsTJr;nJdVpIcV{{DQW`v`?D6`hoT}Vp~Y*#-=j1HjkF0ZzOQtaAdRM><?1b+FSt&l zYq|PJl?3@TUoF>N(uIOLTAP-uuXK(en`W!k<SktwsHD|sHTg)D1w}NnR?{x&A_0>& zqSfRpoh`_q5w()NrK*B*TA5a|k93}(fEJ{cyi2MssHgR6CHqR}3g|R9Ex9-R9ioQD z(vtf~RRm=;_+4_BR71d`DYSBp3p0NSy~cG9x%g5$*F?`(iK}$Y=31tE{>3MmR>noI zR-DdsHZEJad_ku1wLey_*qOQR+8nNxd!2Uc_VrF&1NRv1)@|z@xX$il+N~bz-MDky z)wHeMAFSaTyJu@#Z+}4IYP)-BTW@=?p1aQdjkdMN18436cT4TN?hn>+SG!kg-`)OT zBUjHoLi_Hv2OGE>-M?wy^?2aQRd(0cKI#5oE!W(=Nc-gW2aepO?uWEbZhK(Q-QeD> zebNJd!sH@%C+%VP2X<T=cc%96_6JT}Blm6BjIIS<bG@d`J$5bm+U#rVxTWrC?n|z% z-kp2fXTAFao!x1-JwF(S6VwU2Rut}Bzh!;yFXU@U7bRv>L~gSCG{JCF>~ijAcNK!+ zme`ftBkmal!_Bd#+}-XT1jDVdR@_tWErgOyvBq3acMC$vme|$Y6Yk}NlFhN^+ym}m zgp#eXHr%uBgM@%hu`9US+;s>6TVhvnkGmHT0yf8*are3V5dyZxT65#vI|;l^u_oMI z?hXXrmRL*fN%wjJZ*!~#H^4ofz}p&Y%T02hAh>M$v7EcrU4!7V<;O~Hh&!F&viXN8 zcaOU-!DZ_YD{hQ?8=-O24`Z&EyDgz{%a7IE2=^L7<K`dc+(YhULgUsSHrxdF5kk_Y zA1k;X?nFY;mLIFQVeVywq|HCfxPI<Igru!Mthw>-y#(2&A0}L1cQ=A;%MVK~*_}m@ zZT?}w4RWUvWLtmOa;eSNFNPVHUZt!TFB9Ht?!VYV*y^0Z$fg*JO@&cMv%AdCTnso$ z@3L5QajWnm$=v7S9$^k+le3z*s<}?9&Bs|qT-+R^)wau7L)_3jrq$-#FiV`;tfpn_ z-7sH#tvOrE)~5k}Om(xDmhG;Fh2s0oZ?tTE8|H|!nk}_zyc-sXE1D~{YJ3`$#f8lg zS~a^G7KxuUf77b*ZI~@iZ`Ri$dpD?xZ#5Tbk$oEGiLW#t(jxC_P!~UH?$#pvHp~_0 zH9KjIcsHnttDBixBR&l(r!Fxv7zGSE!`=BRql|K%;oV>%UViEVW9MO$YJ!H=$hMy4 zQQGwvyPKak@3~m6P1p1_;TKVe!lX=vM*~qTZ&uMH?nu-Wvzs$Ci8~XQi3QCbnncgU z#bR!Aizd-4(LgM2w$Lowk*F<x-CV9&wlh&r{G~Zev&=JbsrX~_pk|p@qLFyASw}Ny zN1~SaMRS2>(9T3%@xRS}nn9k4OT_KXoti;jiH73wW(UpQ9f<^SYjeG3@6JSh@o;mz zX0K<Wj+oaxq1o$|NEFMOH8kCJ%xH?AH`6uUcFrsl_c!}$x_Qnl7Qb(9({%HiF%XY6 z+iJ3Q%xH_>G}madcFyRDzcrIJS)MaX#of&#nk=swBk^=IQIoo3MoZk%T&79gIio8c zY!1?-dd@5ncQ*HGQoUvj#S_hLnu;AW1aVt4OH;9PMqfPAOx09)&gh7Hn-!W0uNmU& zm6xyX2sPK;wJ!ab)oapavFWeg%fA?3-LWq7Mp3izJx>Gef@Tx3=bX#Gni^+%YG3}% z)MVAKZ?~+od>v_8m;ZM2I*ZqbO=I%kZe3^lI?;42-)htS<*&Dxs^wd4xxe!DQPb>v ztIhXKU;k|Cm2b86zSZl~rf>4AHr+RVz0=e(ziP|<)vv=%EAy*1-#34K&@>{yYU_QQ z*XK;X<wtJ1zvA_FQ~mtNE%#Tw4mB;xkKBCU?Dc-rL-~<g?_0k<W7?fRwCTRdYadgm z{Gl!PEni2OGV_Nv|7`kY#TT<LCaW%an}4y;{Xde<GpGsY`}!&hiWH@&fPi#D??^|1 z&|BzTARwViXc9n01*Ag~TIdi$LhnddQ6LF5)X>zgQWA<kLlXr2GtcvOXJ=pSoV`2e zp3i*%Kx`W;7=Z+E@EIeju%2*CwvrJ_SQ@T^m&0?wal%5v(?*A)<Rq{M{9pFAVT%s_ zvM>YuzCKhAFCd%*zYl~y#NQS+gx@!SD&ggYhvD}Pp_=#`!ea0ueW(H+AY2W<;L@w( zxrCp>iwvMDcs1b-c#$Dg8-GpsF5FcgDvuWt&V#!Gp=x+eVF$RY0aO{UEIbc)HH2#6 znT1v1%lc47ytHs9d>IJU!1D@6!Iur7s(3BoBlxl*R0mHd%nH}kr^(@kgfroqK-xn* zyRao((}1RgR}`LrYZ}rt@i&EK;l27a1-ztiBfJ+#Q^)fNhroLcXexLO;a~7xLz*_8 zL6{#Nt51{1iwT#)V}Ud^{9R!Wc&q_U8Luk*6&`Cy)55a~>%dR-X^MDR;Q{z5kfwp> z7k&vpHK3{Db%g)HPYu;m!bM31#)gOt0bWz}jBrf=n%$_!NDOWvxFgzb6a-3|5jil5 zBfU}*PB-!<y;Tw!GrEax%^EjR=b>z)!?MPW)$dZ4(R*3rrt18ZQ}oR&8Kdr7luzi? zEE$vTdzAmsrdcw^-5eAWnwTYH+I^owLrZ2g7<IEz2<Y0Z29s`X3KboY)nMFxhq8#? z%4#s}=A)dTd9s3yx^Gj4(1lsSCf!_=b+k)XuyHphWe&ZR6>QqgOF2YqWbGPtvs1>= zJz2XZ-8__CbWGMA;~1kD<G)6xXoT@!V+JGQ#q<;wxV=#=TA8FyxkYhDGm}Iiscq)! zX6gyy5|rx{B~qX9k-$pc{!8@V>|IOPB}zP+A)C((cAZj=PRi!9fL*0zqYbn9%wbHF zX7q42pC#-HB^fQ2U1A1fq~Ori*(DY*dP)KMX?BS@jD^yL-pDSogk7d2pzmh8o55~S zs?d4a?iR3XlpM4}w!1lunbMA)&vv(j(NWUTs@bb%u$z>6bZ7Re1&o1GjE>4)HHWcM z`p`$&tClC1C~wfL+1h3&*D00g%xrColdBX2+A>?){Dg_pik`^Uwmi8)Nkz+M_nVzC zQfkqS+5HwL7xWo)NOr&Z2@9nM{VTiQ^5ill3C*AV!tCS*r5atD{lenp8YK_yk^RE_ zgqhNb{+j*5@`R3(iPp(JH#@mWX+#fXpIe+TP)gA+v(L>>STBIl|FY8s3zGwVTc*I? zBSY|XAs$P5^3@iZmSiwuq#G}#P&g_OhSyXmm3nX!FW8bVC18qIXt_d`0=L4)fGQf~ z``|G6n1PBaSrfbmA2U?ZAzuOCgiGsp$dLuXsc>mv$3rq3*c2{p(4j<D02ATTh8>z@ zMzAEjUcW<uECH^C*8@A$$=u)oc)dY~3RxYz1+O>k&?eJ^dEi0%9r9#Ra3MSh*r7(g z19pK28FVO<RlrN|Aj1wVG7DG(zN6ovNR|Qjz;}Qh8e~4OK?`4tdy94p8yVd4qUCan z0=WeI2F%$a;gnuyp`zb$*Xd22@tj})f*D~hP-vp^SS39$q$O_TP~<N^`33kdf>$^4 z0r?S_0m1t?Qk?7wPD1cLiWDYWgAEb9dXZA(Q1CFKST|CTYz!7d6hDrXAVa{_h~h_) zqGTuVQ$(>|qzpM4yn%4jjT9gofbSyQ9!CPmKHxlr+oMPkvK`m~;ieZUO^yK1BUW@H zg~;Y$Rm95UNJ(-KxD&DRC{m2<2983k=tats<G@D<E#1QhWIZq|LhJFNIN2MViO_m< zC``5iTOzdd4yDLp;0Z*Z?x7&r6fBGAdweKC4gfbI`W{_~rVBU((WiGPLyiIeLd5AF z3Xl!K{D`>6hXC?Za4910(V+<00qlW@(>s(VM}fa0&U6oj$d+Io#M$FRNpc8y0CD!{ zP>k#Weu+5KJCr5A<N#XdCx05{0NUKs^OQ;m<ruPg_30|38;2+;U%$NYwZTWsH>+oW z=Nz$&mlLuc>kDAAtc(C)4n_{&ayiKaviPWlCkta3C_nYnGRJzkoNU6e_^74lWyYHz z$9JDTaoj0y5>NOdE@k0)gV7Y^nDU9lkz3v*m9Qo*W$Ag1Q4-{s{E5I}U*05<Fe_eX z;mOPx0CG(Iw8$}6-XxQ7AYNzbNyo?oT6p(qh(o2k36L-*9%$itlhFmVkn(Acqoce@ zI$=jV(9)BEQ3JG){Arvcvb;$$VMTn~!jqNJfKiJB2H3Y2x6U^!Fa2~WK_Nj4z+|!6 zf6=Mvfz6Pe@#R*=G%iStD-pg%BeYTnzkHGW;{5MFmrm|A=YIsnbnZ@*F8knmm1*qM zO{w?A;ysaljY`wvF$idVn^VuCjenrcHtya15Cklwxy7y7I=2mff0|od^(nXVk>~;N z-+wuv_LY17Ge=Sf9e4NxJ4|N3sIEGndKk9#qy3WYV3L^nhWf1?U<jnIrS5ZyyT3g7 zqw$Jr)K`UR@r{4Kw#_Ps?!=_@y{VW`2ue*HzG<~pn<{T1hn=ZTRW=pnorIW9j<ngy zs@gJZRr%UzZ2{6Z+g91M*ddiluJ*EK)LTB}p-nH##+s_e<=T?e^}p0vkooNV{4VFO zOu*rY%)7@`z)Hu99&c=IR;J6zZ=>e9S`9U;5bWi5ZPxI{cfHWkhJod3piD`w<eGgK znnC*aJAXTi4*H!$J}(0$Wmiyij#rP*hc>u>uNR>$B1-gU6RtD^yE|uchUuyBt6#<5 zk@Wvxgq=g*!ep4Ms#~1{0h%i&j{eG?GgG^U3J!TK@H5SPG_=~Wa#?mWMFw+S3viHF zB9>j#!XD-rZ1M8RkW<LKS>7V-kV<=$XJY>H%T~HqNVBCVwHVlJIbl$_Fgh&py@}7Z z(iXX6WV^dHujPPsR!Efqn2#({4f?3*umNuDXaFmP8`YOG%TYrtF|h^J>R1S9J-A`g zEy7G3^WTVf<vw=qn&X}<V58ht+VZ-6@Jd-}3;Qm%LRlc-e&cn;h%s2D;aK0*8Zmmw z4x3-fiQyu&KKtgt8g`cs*Sr`j_I3($`)9VAkNAf6&vl(<{clD3?x03C+^lvm6ib(e z+|4(RBro^WPcR?5uHOoFk|OyX^-mjDNT~uP=}Mf#897)$z>f4`ZfXni$)%|sck(ql zqJgr40giWe$%SeY2GFgVk%K-EW0G74_j$TcX_o6Q)eSsIq%D`{t}?25&h<Me0`us7 zT3wXNJF7n(480qAES?XTTCi;_yWf1zFr><{fhuF4GRvjz3NZCYLCQgV_H6odwvE{O z2RCPHXJMt(mq+0yp`X&)>PRO#;fk_ywskoN>So)MW4XaL)<WIHD-MLdDz58*$D-yJ z6^-LGKDIKM3D57wy%}9pc4Kxdnb(!8;2iC)_=_qnt=ltg5Wl||j&%-MH8yA;U0AG7 zTs$?`3P=ZekeTYN{UcC*ZDVDNvyoMUnkcIT-v>$NwJ2n-uw-y*u{<fh9>h{8qWHha zRv~R>`M~%1K$dGKqcLOleW<&fR_mEE+@cc6L93wGRh=^gvON>VA-#5n8;A7wM;x$h zrZ5mhrXdM6K$ioSnXMW}ryHu-NU_YH*s7<k%hl_8LBR&%-v#`+>t?HMO-zOs6|K61 z17I2Bx6*AR^8C9^4+uuY2c9nCD*|(_c+O_uu~<27YWq^HG}_TrIw292S;U23*Nryn zd+%_u$z99uO?!T}Z6)HXR8$A5e6-?vO^(A1sK<7{uRKNyX*RGMT3I(=Yu#``A*OOi zc-CW8IpIGxsoyXF5D%`#p8Ej9S9qyrbF-r3ChXwQ;Ihd1@Y?H6(>KfFw?01`r|Uja zpV)M{=0X5b?Rq5^?`l-wq>@&1b6X$(0hl-F$~+OCqndsKG8A+y4k2$Zm7&F&v}PKT zuP|#V2lZj&{A-5rZFTwejo9!4qqN{nNfz8O93m6UIX;^wY?6K-FP|oJi0h)-w0;%) z>F3c?L#0XrrdGwwwA^r4f#LymPmR9CsxTuJpU{#bCjLtJcl|xt4>y;?qKAdHfg+#v ze;hzdqg_0GN)7?if~|*y>bj7!naM_@CrYn}r0K#Cz(>>RP+WbtHD8UXngFn`TB7A? z^St=EHpHBJXlJR_eXg~mx@nf#zcy&G%4(SYj=s5~OR36Z&Pi7xT}h7;e`~x^wtv;U zL(YAi{bxcl(6DbbOTKP@YM&`c=4N+!UUctJjzzEm@xrm4l1jF4B4c3MZd?A3b93CJ zJI&(lB|9H;l>0QrJAb+E<xjl#HO>xF%Ce~d;#;dLzg{)`rET7h=YUTu=fFh928?mq zKCueE5Ab_lzd9oAf5Rm@WD8ck4`{9~nXNfaVJx|&VLhQ+sp%wZQ|WFmST}*i-r!z4 zXqSZT3o6r3Ue!Y)Gf0lC?(g4qzq>czR1@}I(UTDnV>#$QUYbJEc=RE6k&IAx1kg_r zzsEAMi361I-*P)N$ApxR+<2EKnf)usMe!*2=8kAiai0F$?;&pypQ<bxvMt#*&Tcmt z+9+0i>>Bg-6A4?B^l9x(;FvY7Rwyhs8`J-x9Q@O$@CtXjpLo%)Rm!B<A0-inYTT^s zL0*oy3?x$Zrr0AVp1~_vUsFXaf)pN6!FPQeE0H7m+o&EJxMr+qWxm%Ws!60YGT)GO z+mVh>2=Ig!>V0vaPOyj6Pz(9YaRAM`WA@yr@q2Z5aKcTC>x{^KL1T?t&@cY%2y>Yl z3QAM0)FHm@sZMkYEm_Qe@;8{XYKQe&x<`F;$0#(gt^toAb|nCwc!W9zK;tESevEN1 zLmm&Q0>i}!={0~U?42;T2UuM9QclZZsuI=K3c_O=MFaa#Ds*uW8uypmD+xfuQ%2YM zk`LhT<L}0g06KBdE?aAh-#=S&@rVSSC%S!D^w>|B8>^9u74puAaDofnLFB(z!Oi6~ z5pjr^N1LXj)EtV}6|p5eS81K6spd4lOk%UgXsrQF2LSI@D^v=EWeO5VmM4-20JR3B zSRPbry<so1zTpcbgR|PGqF_UXA!YF(Pv7+Y|4drM1^JOLRH_yxPud5tvqffw(#49l zB;2a+;_jv_Ao2FKgstio!Z{qu$+0O}<B)c5^KRt@XLUgu(Ck7h8%}H6t`*q?HqXsx z3l^tAs$A2EX`X{ndL9>jtEzK~rFwRui~(2roIs-KvBnr?uHuTRse5S3hm?pDh7?~> zf^*+to(qs!9Gq|G>69vty<-WURbPKPpg=m=f{mk{ZDUM?+HZ1>irIaG6knOf+|BpB z^74!zb;p|{CB(06Rp{)POPn*0oqgKsyjOfxoN}I`G+#iU`SW2O*^3^Q092H49eq^q zZui(pm(!7L&`;9ho>i)*l|;>GJjhNYqH2~%XqJ$abv1L*D=b<|3HE8D5w5w-jw(9i zB_64UW1&U*i|=ohd2L$?3$#V!KLA6U=!ojKB%bu(_Fz2zN9LoRc1bG2cBqPgJKEn~ z$tMz-1-6s+3q?F5Q7P#QSrcM~2AtT{P37Y4kit#|>f)zdqd>(zAwoLT=kuk$rZr## z&sBx>Mty1T<h(WCkTr3Boc{5T?)zAMJLR4q95oau@b`#Bl71H)=Vx?{b@)0M1ALdz zdwXXAfW}y9@hR{%zZKb0zq#O#9J|_10P^J~e7iRlZ9}c$VdvoZ&qu!#tBHoTR_Ggb z&1yVoJ(7|bQ*vxL#0JSb+K1SKUpbq9c8re*ks#fed0}6*fTh*}?Z`UbS8Wv?Z#%p6 z#QwM{ljFjT3?Q`C?YD8Z;@i+XY%IMEUcEy?+_MaA9dkyto^RS~#jn@Dmq--wsTtB* zY%;47zFM2n;ed=6rWQ;6o6*Cmz#^(oQd5{E&O|t0bEc=PxCAqczcdw}!dS!*)TMDE zxe)7N6=kIsLpGm!4oO(hPmMEJli-*Tdk(EE+G+jX-v+Ouz+=bOOtb2N3f?k8*{hoR zM>ZBrPEMd4lh6-n!UWb<-7Bg{@FM27Z>KJjCM|D$I|4V5Q(KL*0F=kMM9dl+&zL8h zxD3l)3*0CAa5sK`2N@}H7?H^Vnti-Ih|4ii%T#5=iqu{@bB?rxzn{GkG_LDkS_zV0 z_sxq3{<`jk#pb)K)a+a@i1eMph83(|ar6w^6lkKjg<*@18dmb&Btn{3HlH)U9_e$w zoJ2g{zp-Hddf_UU#A~fo6MjE*l${+knaw<>Ci$ajSzm1Y=wXcnPd8{jt}Y+|18U@Q zE=*Ghs-fd9a44<g#<J$vW;yw`=iqH`gA5c;tZ*u2MXfRkh0-F^`uOt8eRYC%8;=oC zY?t1g^&F{HFz}nUR)3=J^WUhnGtOBYs0yd*REyn~DPYMl^{q*lw}*_~`q&`uUDt{t zl_}W2{pb^9$Yl~E%o(IlQT?3Z&sFe1Q=vV)f*&5e=5p}D`y+8Uy+e&KX=T~&+IB<X zwn~`G&BDlbds{sY-GFw&Go1U>r&hr~P6>SyLSvXa&+Gtpw&6BHgIF(e0_Td9WO79% z^N-oVNIjigqb`a>PlHdSU2!(P2r?AMZscNVCx9s=HRjH_B+0$V(G<!N%ErlwprD+! zw9{aJ)0iS7P!eP)V1cwoJPWeZowE)uczq1_!?HSF<-0?&`&CzyJbz=jXI1KMgwyx_ zLM@r5`(!_#?Nm}#NkvVCEnvR=kvhh4_LH43EP&vpEOHNw8eSBcvvDA~kLkywmq{JV zOtuj~lfux~YV^RiPq^H@Tb0iqjCD1?>h6P<+K!kPS8<f54Q|>dVQLd6^yB^Ao?h>< z+TlqUML8@*zc)Z)b7n^U(4BGZ4ZdEzS3qx5PN@EO?YDfpwwUAI3BF2}y{@E`CF`~F z{EXgWdb&Q74J;kRX;mkIC|4IgM9tB$siZ1%GT>NlusWpG`IazUk8qfg!Zi8&!v#O@ z0%}4hbg7qeA8av;Kx*_jZL;Mm2#a2z=fV@Se?jYWOTNsBi_$;TOdLtXuXA%?I}TDM zWb0mnS(t{?2q_-e=i31_r(ga%lQx&~>3x0%EW&ebT(!N}z3}5ysZufN)Ebf41OK*u z|GjAX)xkyjBf{zp*I%jy2QR{MtD2ky6P85Wa4a0+N)>tL<<M3HnV{&h_!7&Rlv1VH zIi*pS$)Xf!|MUZ9=}PA2CoiSh3O>|plt#C(Q=`9=_QzYtMCmnfnV_d=1@4L7mU24h z#vF`+wgLUF>;Q0`+Y<lX#1{}k_A^aKb^AFvN~j-Vl}ptvW*ZN4c$@`h-fB$hfE3d_ zBo7W}T`-c2lEICXgk5-9@Zs8XgPHy3|0XInYF$y;q`SBMNkUvMbvK?mD+`dI7nJhL z?N%Jva+|R(!JI3=2+POpK*jg!ya8%5&Dw)^ureK4+CPam6j=;#R@<LhtnF2=`kzGv zRWnX<ta@4>8A#srytEl{A=E@x?wk{|V1uM;f1e=rNMe{ZyTy#UNOcZ2M_**3e!t_O z!~U&WOWylg{MfbP562@3=7ok5*McRJou?(Nh+DrUW=mcKSq+bZYcw8oJhFKMw-2~t zW~apl8GfJh)_v32X|%lg-qoq(k`$ksSr_2#0KYVqM{PM7DCD4Kx2I9xLi@=(JP+Q^ zxqfc$wbP{^+&7RL*n-@M6m>%JgUGRE3mkr=s-enVW$ebVd8u~Bykm5*a(!d~&B$EY z>si0R)u$sLG8>E^{^xIW0EE<J$3_J0zN;PsEUtodw|b@w;(WzjZ$$tXs{~hoxfWv1 zinoB>H}o1ht7h%Y4MhwpI0yA_tOX^Yw2dZkb7`5*V@2F@xhXZ}6Zg$c9qs4B$27AO z>w=xSU3^!s<>nShXUjcVBArM^c2A4XU%ZP4-3n_zSCA}|8s#GQfW$|h2L9ir{%TI% zvhjMGEsUZ1zQx?;>)U*(7gHr#UDt5!-eZZ&aZ++x-r&UfoWtBkjen|!7O?89rq1@0 z%@X;i`t!~ueD>LHS={RLoUgG*5cj|}H;$I4SjA?PoV%Tcgo_O#2mbr=K_TtMknPIN zN7orVO`I4K{iWF>^PZp`G=ysCoF!`K6H46_yc+FxWedJYrFJzIs#h&i9r<4K)d9rx zwb=LUl^WhtUF;spd>RVMCwu{QLdWGBS|vnzKb&^F5->DNC#~adLagznvwu?*zk#&N z`W8jOsshzaF34HP(^9S}_Z?96J9&d^!AkUm_73tRuZ~2FtbXgN%kF4B$aswMd0(cJ zYI8t#thd9HZA)>fJHBm`O&OF~Os?tT15P9P(aj2NTw}VQ#jW-<rp+v;ATSm*L;o^J zc!0;A=eCP(A*y{@?XE8WdWJM(AqbZ*u=ih<QksdnA-^U*ybR6!G<mPqPc4|raD083 zb1Wsz{&LXgf52cqBk}h`y1aky3zexC-QxL>Kf!oVqs_F*!$>+*0+|lxb{r*so});n z&d==Lleo(xswwpS9X)ll(e$<EvP4*Vo;rFTJA$35)vC$w4N+G>*E8tl=djy)>mQH1 z@zyP`34D*t4G%Vem0?2E%G30vRa3h8L>`+cewz!gJDRpKv^T~-Snn9{e`kW5zfNah z#ye#d*t#CRps<o{)jlIYqZZbuP+m3BnKN1ZmpJnfTD|tR8IXj=P?QPwx1%$!*6}n( z`Hh&3SXtk6yEbZ<RbJF?+wqLCT?Xk`=*`HrO0r677PcM_iZ2%klc;{>8JNt|jlC58 zxmGVf(&US;*Z^6c?yAW43|FY6tR0Tysh@pM4P$<#cfuE_c;RB!<8K`V*cVQ<+1{DS zsC#yiwaW_AWm40<8`5Fh5B@p>I+TByqJI?W4eh`wB@!RdO*dL20Lz68eM;pyEkj+u zMFBw>H<T*E+R_!K9%v~de9QLl@DpUe5Q2?cCzM=5B0n+c>7{#hIVlkV%>~3nCYypK z`9%K$wVAh5j=azXrb=sWD@7f^@EDhg1oXWP&el!@httsKi@eLV7JDb+xeeya>SY_m z+v7M*<HK-4`$Q18txbhQ*r&O2^;Qy=HDJl$k+lC+6ly?Y_MY6zG;aLaA~WP~{;PCs zM`uH<SG<I}@|IZoHJ_)fl)p+RyF*rd%$4Hdj#c$>w=UOu?fD%@UJrwo6O;(*MIv@3 zcf=VX#?rQ>{Z2Bad1;lBZDog&L+|3Mb`{>CXKekUMW3B7P-h=fo0{qU*R<W-d8<bX zU#bU-SXW{j!~E(xi$4yz$s@IQ5lNsL=WK3)vL~j)zpu_UXC>|$gjg^A$L9Cd<iT`I z*Z<gkKvJ_|nQkB$9|wsg<L#o`HvGLI_GWbKtX8pHZbjK&6NQHYcU$%R8nVGo`8n!* z4{#mY{I}#nUKR;*V}#aAQuXVz%i$2KrquuC5q&GJO6w!lf7^-}ya*w-H9YI_9MXBx zkarW!^eVI~LRPml`Iqv^e!W+AM}+Lj;?U}(v$I*3gacI>Vm<-6Naznl#_QKS#7=!3 zAB<(@<h6Ek?g-zQ4BVF|-Jec|o29ozMsptvm=0cN!>uN)OH+GV)T#`N*?qOpo;bVE zqwtEli7f6n)B#_f@3$n|rQ-j`i44E>Q0G#X!)01Q-67U0aTF<4(FJk~&N(of8~3cN zVFie7?kR?iPGV8_94c!X<q5WhooqSn{~@1!eieCc)wZh2yDr<g_gc?~lN`LM_ZDau z&5#bW`y%19Nb0byY><u#>#ckBeWV;T(7h^NwlJ!7@(EN~jvRe{V}>j5vGSSSYhd)~ zTx^(v{cDWzK?$4dv|M{m_;$sVIBVfYl{93?$i&^z1L<@ZUMy?=)gmtwiz$Zh+^REf zZ1VoR{<n<Hi5|(LO@${y+-IIiS<Q%9Ub|}tZ5rHjg(Ni+X7piBmDu~Lxro<ouX&t1 zO<i{{j-di`9I674Moxun9bq;Vdg7`rdb2Yh_t6%KQ-ZIHR=?1|VR^(4i8xpHZh1kg zhoBs|wimM8D{iGZJ4uamBxYXewfo1@oRlu}CBFjwYogpioFPGnBM-|_x1-&xuHELC zJen2zsb9NSru2i(+uL|qDc80&3WkwS88TfaF{F*H0-Zdpk=Q-vch6eQn3SX53!@h2 zzFw#3<*e&YZGXXJjdeH2yT>V3s#y_iwDRM-SEt9~bN`!_zk(~CR{E-|OjHg#U9{~f zQ_JTURAKPBXFXFs2E1WXC13|~TMahZ>hK7uSkLMTMC-aRbX~QVT(Lc$d>0+)6<#4i zacB#Vzx=)3p6Px;O=S{2wOC+6KEk)la>ZsgfymsN%rTRTN<3CzDoDk#A!k{p#Oy!O zT_7IqvN7E!a*y8h_GA7?N=}dHvd`T`c7If}uee=o15%DKw%x&r*K+BNUNQ{#VMHx; zk72T<uK3B?UiS9!uN#w$Kj?G61}(3@9;AGIL17|E<H*Ed;P2w`jA@_@gmF1!NK|*2 z$=Y`Jh_S+XT&HCuIo7^Vv<Rd7B7NePukO$_n=%~#e9T^99DNkMbK}}~BQ-unmCO58 zyw~<*IZ&`c)xw~#D6<j=YQo(oez4-5p?&pqUmIQADkiyWq;1)DSdndx*4y2mKhMEv zr|4a~9AZ2AnPsYuT0_7{glR>CSoT6NSIKk1IX{;_UT*z!qV$+<%(x!t^pbDZ_A7Xu zP5&V_$IJ3u_joCN{7rX%^@C9Jxa^0xH#wFKUvYSzu;QoFndVGta2>Xo28c|uic8QS ztzu98Wbr<3^PN?gKHq(nwpad~Nn;7Qx##viZDh%M(3he@{74E*yW|WB3nB@+2=K<r zHQ{cW0jL_X(va6RihpvuE2r%O?Y16kBlqKmizXSKOarPa6P6maZ$c;wICTY31mQ;o zC}Tg`yEd2w&mlMUKYKTq>H2QA7%w=CIAmkxI9$KKj5Bd2e5aBgbn*(z`@QNfMeCN@ zM=)-5YB)>B^-lTc)ab4IR3bP=jtT{w)yADXetfqmI3?1@7ZU#2l~umutco%q<`V^H zj}Dx>dX(`WTC{ib<BNP535DS>QFRZI4$RA>1%bq|rN?LOE?qn!Mt%9*JOfJAi5hEA zt{MOK_DnI&q@uzlTJEb*x+Seoy}^)7?25N`i(gcCrL}PgI?|)L6~nlt%=tr+&9w|} zoqDCl<(`6aQn*B`4`Hpw^%HCm$$_ntW;Pce@-Gy67#C*WJ5`z_tVF%v+4gtI|1UoL z^D9jE(E=Z`h&%_MDynE7d(?9)A|h_EZDkU(bTwhWz#{K6!t}WPEK;v{I2lu@@M6I; zBeIp<$+oE|?=IABUb?EP!39s6d)HvVsLHiD)7~~3y8HYZL(XUao7Pr}Npor{R8g_9 z?7{~JT=iE>Zbt^V21g>_m77kNwwvw8s2A^Lmm6Yq3J?FyR#wI{ZhcGHPEacf*|>wr zr`fx0%*3S7DMP$X9UG2_g{>&bo~NS<bQ5tJOu+?SUTV(8KkOgXM(x)bGYt1;mD>4Z zcLd)shXhpEr1vIHM?W|L$-hCsbv91yH@q5N>5bjCdE8LB&m(Qn_V;f>og7coioe4c zl~8K{qqE3)I)Lg+N_P^Oj;*|zXT*n<9Ot@2tki=st`#Y}22v!A2T_gJ#An+ucgyPa ze>crZ46bv(izQ8JyKgWp=*A5w=-l9wDI5vja9|jcbaYUCl6b(7OJmQ{<_x;G>x$<Q zYmN*|+B!+o#YA7X{|5Ak!8YiyaWz;@g_up9xLt~qfA-!@u_q)j)TDWtL@DErzep_u zp6vQq$`8=XRbegVG2(Zhm{}*N0`FF1ql-ZPHNQ+mjb{9@M9~Ut=(JBw2(u-Z+}-hN zCMwL}TFpxv^|4uV4{D8U1#euVXN`ZXe^<jj6O6&&KbwPh)zp+~#sGBHg+pb%0_V1# zHJ7wEp?>go?ph4S5sRmhk5sy=#lM7EHXFW#VB%d<`FwWMa*PeCL1&pZ5ObZ7Eq$44 zv$t`R)wTDmfsRp@%?{f-fNSl_6@F`~_k<5HZ|P2aM;((Rf?hw8l%N-T(p4d2mNqqz zE)Yh4z|ccm`N&t!NpBXJnc@h+nk5=DrW`UHOuZ5|2*9j-beDHJ?&+gC0w2XauPg7? z)3*2or;L}Ke?yyodJ$nDDQ4EI$H{H=yRhMY?m6q!Btl-VT4J%)wyESP)upheT2JI` z4gGmB#FjipU~=TIgVYVEZ7Dc@Wmo-dBsNf<Z{9aa61b;4d6)&Liw=LxQdk@qA*8Rz z3$}BVdO2;@_37kJkFepsD0Rx(w4h2*u)8Vcoga_0))cp%oNuY~p7vM*b#OFPVs`5R z6MtN+c-hH%xnbNR+~+!R)o7?eWBKX1kwq)E$s-4zU1DM|KX;M2zH}DtbA}N*(_1Tt z`}Uk;U~#&)sTuudNSw%{Xd3vyx2yap0WKkEtr`#87h_hyZBBHG1Y*_cBmQUiYF!rx z7HtP@*I)k_@T|&_PpT$z^qLV9Nu!=rYf)<;$vO6fb^`MlH|0Dly!=DBCM{per-FEQ zKcfyg!!eTfsCe_YorJ;k+w+5~=`(Bc$*|e)-P;wK>y4aa8dbS?C2Cjgo5FR2-|o{h z_Np3&0&zJ2v6(4<%NM_$uY^I-)X6-#A(I6q%DZT#ih-HClSnKobUp_n6^6pJnn$$S zU-AJQKoYSM0M$otAe_<y0aOE#iXpr$OH>-mWJX@H7jL@1bGNarBx;l|TB6blw=iet z=VJFJaWzZ%c;#7tp+Bvb%=L^c7dN&okt3~jrv0XxBf`qnYwVWtboKZNxBX=2IEP$e z8Ahe(in%oN-bAiXL=5$~4l?D!{<^*4nnBRyNVBtH#w`6o$fxi%t2pgBp+>uciW5*` zT_=WI*5Tk1H!GO6e6{<zsmz!#GX^=@3DBaRr_&2zhCi)uS<A9g2A{sE;hiB&DfJ<p zTX7TKK3=0XOuNM;D^g>xYNvm<QH~db5$|V~=CtO&K7?4|9}OZ&d4EME78G>i1Zvq( zRxbmPKT_`8XO_Oi1DjVhasC&v)`Xt#7Z@C^(zXG<q+tmoo9)&b>7Xj%ZQyh}Jo_5+ z8RVN|vf0t>&J`zXr=Dd6%a?JJl^F`c#iosk@K+Z;W+^%=$NqpJhp}L>7A3^viwQ8; zVKf$ROtd#YG-?Ru?wYNCw)@>U&>y??>hL+U3#LqW2$t3Pd@ML<v$QblNn>m_N0w9i za)lKZw{^Q|#bNa3PsQnxr;XXNft9w3vdDwWPaGHu`;`faJ3J==@^0@7!kX3mH?zeq ziS|}D(VKG?@K)-S>WMn5SXx>A+e8rNtRt8Y7<{#gO&PpJW=uvm->$!cGtlBak1*kI z30Nid0|JJvXU?vPsijw87@I~Jo3EghQB=Bi8D`9p{jC~vB^8>*rwdQrUY%;%$jAOD zXHEYmP)ez=s}G{mdMk!`Y>ts)DyAksmgd3cysA2;g3wt)7ctr;ocAdn&<R(hours! zMEcg8VGXn`Gq%}-`$V2_ttu8J7*=^wNw#fK%RiNvNoV%VOk0+fx^ePW-#$MiBbUpS zI5V03i`HpN7|PEUK;QSv@GsC4N=_>mitqJQ6-W|UVUHg(%uG}`lIm8fiVGkkavPfJ zCqUP*o9;I=TdG7z96?{q<t2b8GF~hP=iE~op>_JsM03eI5l^dc<X9sO)+UJQI{@6b zW&IqJT9+*~;{rO>glcT6$`9D6^-+EaT*b)b%W}<aqa)jwYQl>9=Kj}g1&-&+UMOMv zQ1I?#SvX3@k%wf6Wn*lZ0%rL;Yb)Pn0<$wu!zwLJuf*>=BU6|w|0(&e7dRIXyz!6v zJVq@WaJFs)PHfed!p*?oenRIAzA(IkX|&JBJoBd!kuy0Q*;M<+T*tY+h0Df8C+L^c zU3(v!DC`QUvD4**njn$I@3F<;(;BU;!oCvBC0FOunq@=?5WnFBnjONuqRu!d)w|uy z_In|7AQ8fKEiE)yw7pSWHS4NYkk75$6C}bHI6d$5SKAIZDnYrK#&%(7mElFs;!6A~ z8eQwxFI;C!>UFD-ya>ya#1t6lZz8f)geP!>bzu+1?Q>kK)@@W-(us@e*I&P7DHt&> z_7%dS%+X4i`;w>{yCgOsZlgDQ-wsqdo)Ui1UxiwBnc2;MRkhs6<~S#Z{VGRvSD2T& zs?Z6(N{abhm#AIE2?<N#xIv5eZG&guVLR1n*j4xt>Jr5Bzm%$k*T4QBsX=jiau-ur zV1_6t9?$(<^#9k6iWK%deW|rB@anVv<MNHrp-{HrLlI&ND5U*&R*^sR>Ct}pREx$O zfK*>55BVuAJX8)_u?${g|Azd@zVbdFza8sD`mQNzby{ab0%4GOnbl6wd%o~m0RZn< zm@>_R>xb^~AG58zViF<3SrqqIv^CN{)JFwbx<p_w#q4Mnv2O4LBhQ|jaQ}NJA9Bg2 z2Zb<I&}uBmN1v~<Q`=_#(Krg@#WL28D@>!l&Yb)$S)4CLage-^r9@x2bO9cSL`VFd zvTxNC5%u|1iV6YlX4tK=*~s=e=4}(S;82xi8P@dx`cWEV;33+?rjG4@8RxNo0xe_$ zI?0<vR;Bk}(k=1(3LmUWMoM*j*1m8%<-I?97WOUdKk}2>qQ%e2yY^0z4Ff|Xg;ZkH z-HB5e$TBM#PzoP{a+^zbl#EJ>|EiS{D{lEP)si-~Jom$<gvB5hC|N3l0dMCo1)4WH zT)#UK<>vkbdmoO{^9~3XkFug>csQzE-QTcY`wv){Ifrw@S2=Erd$<LUf4|>%oWO7b z%JIC?suVe=`!%zg79Ct*Qu!&=3p$_qPq`~ieSKO#IH!I(zMNka)ED__L7zOqKzo7W zE9HB{b1&uviqP}FOO|Lt`LhRKO-m3nOpSY+`LS^<sfC>j@m!i$a#v(5(tN5a$aiZ= zRUMz(0{^!|S{@D!A^>w*Y_H)VFV9wnZE|e`-Wk7$h$Q%_lKw(A2HksNM<SnYXV1Ll z`r)Tdi=us;!ASl3S{&>A;bG)5w}!nU1zFd4Ur_z5{iOIDsNry(Tvy2NzgFH1Ldo9w zVoBmMJ7{VNilCnkRrkSpnnxXRUN9G0C4cDvh;+ki$*!qeM299D&|$*375A**SZ<?n zZTQUySE`l&$9JC2+9phEHf*a|Me_`j4F${PCqnF{r`bu+X@!3UGO)iz;W^bE)4wH= zQf@Zl(d2L_Z+NT);ov}X3h*yv?Z@<_kw<ozA3D_UJh%F2ty@2C<-rRSC7L-6ncLo< z4INriCHduINck9vZWBGO;b`EV^zKTWBCVbsb1}5G;a64Y9owkNLe|`Xq_i~?E0aBn zPxrllm6UL>31ZD%UAvL#hhH>p)xz#C5-EUuIGYzNY|_~`V{?FiT6AB^QYJ`*LZ7#9 zhv{MVBD?U%^Hc>_?oEy)3hdlYhsFQaIev)bzW+l<bPp3BKF7V~x1->1A0>oa%_rsj z`Z5YR19+h#G0(+~zy-Uc-||CqR_B(r_oWNg##-fl(Af_{?k}69pF?Jn|2(f-P$8M> z=R#$hcV|3BzW(IeYdNCs{ufeNaIzNmY9k(S+@QK%zx?6r$n39Jeoj5LiS|+A;=9ir zYToL~%D}2NYiCxIMZ9T)WjQxF|F@arH1Plp<O2x|m0w{DIeCiku{?ni^$$y<=$Xye z*ll<BIEf9k?+Q%m-4Gp-N)gG~y8QH?J?v`x&peXrPaB&>vxjtR`_(mbqiCAVHKPZd zoh|lUI~Vbx&Q1G}I%;?hGbHxtUr+SEKk9yerj)J5hYNLKgea@8*GOZg)IOi*iNP#} zD~M9Z(sA0g=+2c7tP}U{Z?W7X=m&2GGvzYl!s#<J+rp|kt@~%650yl<MTWFac~l?E zjQ`POxkJj?2wAJ%AS$QzLC{Ue!|D#)Z-DHP$l6Qfxu4nu56soST8!C=+oK=RJsK_A z^`^AG$1RCJqHEoTVAq<TvxD0=__aPiX;P@anwqGfpB6nmB6gb2T@H+6EQQB6OU*Ju zRY>y=xys1S@^a15u|G&<n)Ij)b3v9R9rv`$Af+F@3yj@uYcZdA!p`~iv0`VoiW*z& zqB!(U=8a=TWz!x(Z%q(->l7lW`u*oiByZPgWwy%`P)XEOGNj_^`|!yKh{8aCZ>Yya zkC+&B5!%{+HJ4xeecO<H$YHwHvQ+(h0DsKQ=q9vg7&oWZfW=e)%CkZJmv2htESb!u z&5;M+Y)-!&|L4?N8?yZ{C#jz@?u}322%}qii<}n{An%5AYRSfyRS(o|lg4cON|9ca z7juA2OQNi{ob=0{vCsGU@qLkhoR^15f8IuvgpAi$1NZi*vr~X!%JUDrE*r<ewl?&i zI{_VAXv79!@TDA)xdwnYJn;=Kx}j!VSmmi*f2vq&s`M8+=+wH6O*=-$JM|-1ihF8k zrDw-;ox8pbpgj+|wP?Bn2W#$dt}ugCCtRH>(Mt07lJS{m4>8L~TWpPP=!fBpu=Mkf z_lc><!4_F3_e%M(3^Z4D&M;<eu}C($+9Gvy4Cn-nZmp7zip5h87LDlUGbfCD+<DW> zxuQcAeUU@L88!<?dbv8DwHiq?wz&)pdw})dr(x<MA;R)Id=0YPp%TBGeuTLv)~B#f zo7^8MRduUo1*~_B8v`;mLPEGe56ms4-9)GL&tHq?#$tn?{|DydEF0fDNJ8d)+$ZXv zh_e&)HQEPraNk|E2sbk$<|Fw?!sZ#dQOl(cHoJNh(>dHUOb-$PN-y3D5tsE8Fa50S zqIVEUGNH4Q2aMU^d_PdKW5F5tpRr8oPX1!wQq#<&&3DaQ#%OM7N<D<RIc_d-OXH-< zeM|SpGO4>rRt1nYc_i(Wad2hriZvpgv#YALpwaTPRfCh_R;@=#bi;!xCEiZj;DNOo zroP+hp~XJ>yPS=>8tW<%X}A=d!67CXehhsyx;H<H=(1PS-1D?oJI<x`E0u#ow}^)C zzC$l@^NC9rj(zX-VD0QNl_E~e3!r>j4@6AcYwTP4b6^`B_O2<>7QWGS=jzgh&yA+n z=1!4OR0cy(s!U#PCaS)BDU?8{nz9d02%1d~mhL#(XkIVKyK|f$0VLhw{R;6%2S!9~ zB(CJAtuw%AHNn5DAJeR>W>+9IHeYAQBdgtPyO!84ft`Dy1<`^Y?}883d!qAy1}N5d zQ(9*WQHY3sfQB50o7Ub5%0x0`S2}}?x>MReGKY+%pG7H%IE=X92I#yi%{FRL()RK_ zw5^})t@f1#tdaHMO_Fwppu3r#P~7tzrI)DK<gQt>BTAV1tcuJ1#wyK_Iz!!B*UAmH z{{(zsLUtx5B}?Ro@~Dj+<PV?P0*8l5y99GP9Dk;__<S;SZe%H_1Z(M{mct`G)S&kn z+*C}jWf~oO(Az5CNH&fR{_&*qn2QqIt2|j8^%WYtD8WnjrxYrnB8qF54f%#UFxtp4 zDH^4Hb}U7$eP8<1Hj{RdlA39NYLmG~inAYvXy^Gco24fW(pu7$X57s%IfyV8CpqL( z{*k4Rx=E@Q|BI)^&1F`@-cZL^0M7MocZVkd@)NUEX^&?C{#xF&l)JGs^9Hlw@uVRP zLCv~|N|E@><st$zwP)EFRktBdW4=&7vu5U%h{|vMlF(`el~`WQ&$Y;flzfb3zxMS{ zn?*tSAdq;H98pzDv8p-1B<=OvR-YZy9d2-`odz{<BDWB@|3>q~4N-FoqKgv0BCxjY zUHv9{_Yt&l8qPe;2b_RBG{^Ce4y=D}i+wE+>B3dVKdKQL06bRrMF!O=3-LSIh;`ig z#bRl?o-eFLDUYNa&6o%wKIi$j<`EoGyP!5e(0pb)F>$2Lsk>_}87g0q!}E;P*P3o& zytj+LD-lpt%v!wDa=cNP!8Lt7Hg*gerzvva@O5_|8P~K@u!xx0^ioGotUB*-)z3sO zm<*(H>dBW+6N+y+`$$K&4A+l8)9x6)P@yJ;jpK?Ki=-h^OJox1!@b|+=>6$k(tjSn zk%BBlx8$=D!kJ#s4s^tr_B3{!fncX#Z+SwjtUo{b??r&$`!wXt3iqzL&TmfsG>K}| zKQnosrx}#{*Hd}5#LhP3!&QTh7M#cG^NQjXqoTfa2cFjz$$b6zOdEL3H*VUL-HdBx zBx3#z*D-Qdg1NdQZrbfA9xOFBZT6RbsHNp+JgC}iLfUJXs^_7$;khclb2dtZQ+FTN ze~(mOh7Lv6Jya$EoQv-gNzx1|U;5!cB|LByU$T~13&#DJEd$V97*)dd^io1UWtuo8 z*DlZwgps$Tqcp|Y6={+gKkt;>+hh0MMl#Tb`HbljH#pTn7Lv|FKI^_@Ekjh5hu5gd zRt!PmyU<wg9FQg*C{LN0AkKzNNZC^q0)>QP=Oqpvr%q_M&D><EpWi7zXo%P}QkS=) zR9F=8?IagIflXH)v}<XjdX9(0*4_Jm?_^>`=VJvLiVe9fn(w1cQL9ROXst}$<A|lI z@-ndA8u@s#^v*-%KXRe^{muM?wGUtQyz)u2M4s0)_Gq<cO;3LcID7c{hETe%_VspR z!42<;8DOjGz{HSl-+(;-Xl)*(x}<C0fuOjN(ZoJXgIXZPrp?~~_@#}jd&9d6REJ_i z1a*v}i=mOrG7h$TWfU9Y1y|Fmr`BB(f~9Z}S^3eu*^8Tj1jD^gL_&Va%e*&E(frdc zYdV7m4yq)n=HBw`_?9%<ZQq%%(`mp}enRRRkZ!tIHpbHEchasdq{dFdyJ!=_x}okI zQ<uu!ir+c4c?_vo-7VM%2v8%wL9gSop~VmTp1nrNXP&~RvzLuVdOM5C+D#p@PB(ux zSe(J9X}2HB3iCb?#URgO6T{Am5!<}Qt061LYJISmPOQZz>`{r(FTsyX#Fev>qic3y zZtJ77Y5S+mnFLeW%Hk7%PmSBE{<&u_e73Y|-=4d4?<7{soGD_~u12X~U@UfQbOYUp z&@l?m@XKu9Xxln0+JDQnM)w7+Wd1YBaIY@Ze9g4_VzBDLaQ@LoKjom^1al1Y)=*vl zZ1u7!yMMWVCirLAhuAkArp@P;7xTdbFFr;+A7zf?y6BX|P;QkzRZ1{Sdi~Prw4UqZ zUD3gZBBhG!$rdYN&8H9k`%^SyE&=(^&{Xnoa4x2}0hh!PW0I-0eo&JNsUDplw<LZA zdYeFAn>kTrMq<l)*OA>Zp#}FOlxDq!H_&wlz~F`;Ra(|U^z;OKbbw4W4%0rJb;eYc zWI2vHhMW~IUqiAYsH>-JbZdLQsf!fhD6f>W?T>}@ACnRFu}RjW3Jc{I7mY%(IO0&; z*uF#F<{{GPzl5rwicjr{NxXzYiMzuZpjIDTr~ixK26ytV!p{tVjw=^v+qh@rb93*i z$HRhOS3@C!QQP2Lo)S@X?|^mbP-seVP7;-@exULt7Cp-s^F;w2HX38H=Qav+hAc;5 zY?6q#l~}h3orM~T?L@K)e}TO(ATOxkXXc7TUgP5LG+B>zAC)Xs>>W>{LvdIMJ+cW> zku(44gH`Rc@-klof2p-Q)~>OeDXu3tF`&A&hhxv3UFh#&9>W%=qeo(Jrro=+TuGMG z<=@XxF<$Ma5lUJQmCw%gPg}w!>hE=%YJ~M@M-DHD2f)B(Hb>UMt@KFur|*-VN=2tN zJ<O4v4mH~CjZECjymcW&h0nU~&G7M!<OO?ySe(rW^o0zMGUUHjeS8Q)S%<BT^Xxy1 zbHi$BB4xX((BWbe$CI0^$7wBp%4zgTjDH4?U(^+$kCS2^Vyv`dnKlY#6Nel69oOT$ z@m9t(z8rWYo@Dg7#A!F!gX9_nM!oEgr&!g7UwfxE{FsZ7I^z8vx2qKBC>2wk%Z~WI z+D*~%tyEjryDP-%0cl;+Ukn3*8p?7H4N4||Dvsx`)feHdjy<}(g`ZYUJ$uM&{DW-a zU-M+n4VFQ($L|MK3lnomr>lf??LnI%ZbDKul2b**f%M-J3N?DqLRml0%L!b$?26zA zS3MYCF>6QNBdi_fuZ_<QjxCb~B5(&x5j>V=dyFH}-tznFe+NLhzf{B_=T-*^|3jj` z%R|-Y{5Y#cpYn=ktX27<M2S1l(WUzEOKFg}R$Umw+Gl0oI<|Bz*9L>nb-VxLo_;>U zPbd}QZ{s4~`24KZ%{eBiP$*g$y+6qNTkmI0$cQoZ7A3zrapAqpiP%Qh32}W@C%>9u zPe5KYy7>Y-IEMlj8__u{Oz;37H?P)CQ!dJ;=q);%Zj-xHo+`q5ef9kS-{%kh6-Ag~ z)+i)`lB<UhqZtu{I4{+>!@~OWFZ1(5)WmM0OY|4??-zR-L{tB~p%`LYZ(xtAhoZT0 zu+p<4@f_(@6Sbm#sOZ7}Y`txcH5$ce>F&SN9?A-NxQ#dkUrQ#>&_-sUuly__kvUPS zRb;z?9zYjBR<!=SnSS5%+}<LjpmP5?SFmaiNN-W@B~x|y7+3Iy>6Nv>BC#K9U+AfB z*y0c^6Q{0v(WgF_>7sl5HdgA2J6}g?@B^S4w-FW&PS2`cv1v})k<Xq?(Wq6!XV27P ze=1K=#zW+f$Qc4(=lu(EfB1_v-^oui+aYW+S0DOmms<}x)=ZxcO0iS%=gUa#qF)yV z-1eBxsnEa#H0({i>{b;z@O?22<nz!z=LOdylqty-z#}u?eUIp%WJ~}2hwEC$>i2S5 z9kf|UL`(CPIYCXbeoX>W61*NH6>(&u6)t)qVwM5hoJl4x^YUktl93UFfE*!41Z~jd zKtI6wtT)~w+P!C0o7G24=*9S{TShLcoHq~#>`L=5SZkdMZw!+vbc4j)tJh$v7M2ce zJD-2jwf6SM0w&~zQq(G+x$5lN;HV!(KphnjYGyJU91e6#wb$Bq_4Fz@nUcd~q>Xlm z?di0J=YDvL99|$^#xEW>t7CrSKxXFq2bT%~>-@L=r{xxb=rO%e(hod-L<FqcS<Pas zaV+%A1RhM>q!4Cb|7qi6p)Yk7gLOj(X8u56(=9P!1Lwa*h(!ngGxXSFFzyfQr?p;i z?R{>YH})dH1M6Auq7%=<g}DA@!!nP;4?^pxt_kVv#WRezzs~*ahlV{neLr;``-y$J zysdiw=b?Y%>1SM*f#&$s$d0Exo}r{9)-brJdJ4Z13F~GVznctoi1~_mS?=!-Tk-7! z4lDl3+~A<-+KSRrm19V}x7b1UnTtq%{>|D}C2dPf?)4Yj8i5(<Q}!Fj8@<CA5(~(( zD&s@6;K2dqdt48$5y<*dw5qdKD;J{&vCyErY1X)C!&968`DXyw-*%B_Sm-f2USRP1 z*>T@jQ_F}|BsdPQzBcg2C+N%1B!l18tRTzgWF3^mucyu|WBch!g>KQ`yS5(Y<!6|> znzUL+S(qyRR0k61w~jmp5XoA{{r}Nw5HB>H>>XQI{lX>&kW6`<Go??HdsR$x3n!tu zyFK5d<d=1_42jU_ir!WVS6<2T83D6^pD1yE@n&(Yym+r+;l7sAj`JDC`!MRa?~i@h zZ`^TBr8hiebQeDmFgR&OOp|B5M6oG(F)yGsTFsK<<Pz-}w{udu(-3<U#~KsAzRD<{ z{xoT<H~y$IQEbDL^e5%b@z*!e`(Lt1@ux9tYK_D12{wbLY{#$zdXkRgkp2^A);Awm zmGgn=1y(Jjr39Pw7Ud(>^_w^d#OLLf?0|1I?Hx?(cs!ugt6vT=&2=12R}hc<8RGZq z=-*lrj36Muhe1JF|Bs_{0f#z$|9{TpGzdvZPFu<$IiC`RRCc#5r$SUJn?r5o5L3t@ zp|t5h>`JxC(rn*qoSHDhZ?nrTTj?OCsf2AbwIrIE|NH*$b=|z?{k-q@bAO)aW9z#1 z+S<Ot=|uR&Kg#vaY<cqJWh5`y<>wuPdvaFyJTLDw`aQ5!G~yv;$5bx$|KItkv(As6 z)s5_%I(sk3G<fn>^Zw7h(f0zrzWShGa@xbOl&NuA=hs7FN18NqZsaKmRt~*=wX5m= zSv@bem4Dp+<>S}?JF+*SW%PINa(;Se!pAq#tGc;;twvrv;o29+6#LGOik9##s*iY> z{GV0yo=0o@5?5b(WBMKQ{Fqeqo%q++Lzn+A@Lq<~$WHmJmG<Ag`1Zx1V)*NKk9)sA z8-Ga9_2EO~Sd`$8(UWe=LvCEqC|h&r!GZ^CHPpWOSm0V<RrlG3z0yF_D*N-<{Vzg# zyBwYG@YN2gA3VEkG9$Qqnfvdn3|bwQn+dlbREUoLW%I6Oigrsr`PUSDP~R}I)OLmE z<83ic7lkqJwx4ysccIPZ&=uo#W>1Sv%KtDF44?PQjum|W`pEA8c|7mQh!8xT|HpXh z&F_n{M@J5J?y6&cpBJ>RW^M6>bxuz6{+VVe&18D~Efo~}Y~q>NDV4T-ID4g_XFw1e z&MVk*E0cZSE&2P!(z)+StlU3;{PA6GYg+&7#pgbLFz!-Zwe(hv>OV(xF0JiN^17;7 zW~zJP%2>dI+@Ry%-#lsmpw8>w!)sSeuk^=nco1B9&i~{5h(EgTd7dw^5|#fsl+hf& zKQq$(*6@Yb{K)kN{#N1xX$zu%+VT0--k1wxe%cFm-ubR!XIY}-|2<h1nfFfk=%2q| zYz=z9XNBXZfg_K7!#BO2%6swU+db8huPYW9_AUEy^xL2fpHJSK3453C=URVf)3!x_ zY6m~=_Ue06@bA}rv*3SjT-)YW^lDk6$-7Xw_$wxg1%^pu5!_WDK9r7Ie|_ZJM2T+R zj~kY(|IIrr<klbV=OfhF3F+NRqeWj`>F@ob+I!^jr11-(b*|m-g9_(^H+ug){;k{A zd;goccJ{)d4_hv5)bBf!w=P)kjag&5pQch{kLsQuZb^EAAEY148+SfEb;#?=y|msR zzMuSb&L?hqH~ysfeVYGRS-xYHY-Q#xnTU59yS?I6-q#wg8;sm7|4B_q<mc-STD*BW z&;M)ds8tnLZe%907nW{%^hf-DJ5EvCjHBZ02mWt8&o1xGO|wwnAARh%u#qDVG(Vmz zpFMv~Ykj{%_s{i4!Aq|Gc(|&Mb?K**eW!l=)_V8dh@I#5-hHsWVH;;(=3lZ=CmS2S zUf2KCjO&IF&CmaR(P{Zo^ZMA&tj$%4Psf(XdA--|3pl(ps$f-(tJTBQ(W%~E&;L5q zjde25FN@#%%M0b)@X1fE-`VWGa%9KeDDjeY?{0gxO1|`uFFpKa>!|ff%|j1{r<TM{ zetT{_!gJ636I<%f{xGvZ?zO$s@!*OdKGmdi*~cT^EwS!&>q$z#Iq1f2h}+HE!)pJV z^YTt}=l)v(uOGxbU#8S`x&OqU^~aW23kUv8?OeWcv?uUzk)gAVO-W(Fg@smDgYKjE zl4JVB$$KA8n`m7Qdvh!~%i%$wCU^gliha-7x}BrR)*I98cIkXvf5!OYe@Q1Z`^+X~ zuV$Ex6fpbml^^W;wWR1w`i*t(n(o&BSD#+~;NPaZzy4dF-uwVc!<YK>-k2MVppc@H zD-D+172oN^y574uuUqBedR9f~p9{MKA1-56T)*g8<`A-ZS=@C-ci4?5F=3l;b!k6b z$g24DqC?rOkORE^#e0RJJz;<9bT`(f#=0JMj9NBw{Y}a1mWQ&eiiU8zvX3FEy#2@a z@<VMxmuq()uU!+{m~=aInf`UXlGoJ_wOL#1!dH|Ph6M5U7wjDkwFz6U(|x6OXKdpS zx3?}kcfG9S^=}X7vbNTT+n05RSo8KD-}^eWKJ-`Z?z6R<V;lG14qp~>eM`yf+J_5R zTYn9AD7z67&)Z+L_g!dx*snU>w`&i^HXgbix$N=vM<uVD9xAf7HaxW}8xJw$?a$sT z2u%pxr`=styCJqQ`F7Yc=j%=-udhDTV?D2Xx}vN+B!aiUaPN3%LfAf??q6&7#Wo(i zy=~du>vu|C-+8FPdS3t3zU*0uJ8ys9-jPsY=sWH1OSRi#8xP!$Sa$gOp_1424~<#R ze|_pu)*O<~+h4MGB2*amPN%!IHY2w2@a?E&pRP}pyuSBPhV{I`&8}=VM2Yv|Xsvab z(w0G%$1h_AJ3}5Cb_;85%RC>x3Z2@rDdtJYhN9Q6YPGtTJZxiCgl{O^d3kT=hv8c9 zvi{m*p-wlpEStU27OL@G9{0D+w_{yH55}YhIL_-n<hZbVqoZe;@56v)c{hAxU0W9v zy$*0RE6dxG$J_ru{5J=OTC<qc(1SacX*Lv}c&+vDZ<fbzZkA>Ko4bTfpXvm~^~JF+ zSKTW417q^Jf?6Ge;)cxjq}7v~a&>N;nV<RXr9a;HkIl<HQ@hDvWBtZhmn&|U`2UQl z<@VP)7;J37pRRn_t(^bI*uvafwFeA(>U&~cuDMn5pO4AreymkB=xMNtVgJ;0p5H#E zom*HNWMETo6U(k?s^IsH&CTtuwKlM6sE=V+H(lgE7+a8gqc+~4zP>(|eYL5Q|8z_- zcf8inpuQm?hW&HX1%Bt4UT%49gh4`mLM;1A(<T0+F^$}3weAK94Z;}q<)(6e&zNy; zb8WhTuwEF;zSdO5e=#PLJ6o${AZ##>N%<-5Jil#BD>tv!-@v%uI5wpwt%Cpem`ZL} zt(AdsLuE`#b=pP#?_&nJ*J|SoD(fp_Q?8~}@}G<;<c`$p8&oz##-#k5c7e|u)6G3s z8)6Vy9~ql+CG8Ub;h1{v<638f$c7g&DVNjA`G1bZsU>dqj!S7y%j3sAY*zDbz#nUR zEv<?_I3}0-saDhAMT1w&^iMPA`5j|Axh1v1243}EvC}m(75x4&)!g1%TLZ6#dok11 zGZ*>YV}`j6wTTAz>hHx)U!76txcku7;NFc)-uuF_$7-Cq%#Qar#_p<d>NC6Emydl? z<NPYQ|Gs&wM2*uR;l9rs>s4dcN!s6E8*5Nw)=N6ypBtM{WBw{>dw+MVN{!hd;k_>z z8&Z?jNjly)jB(VY^^&glRb%P7($yzpznJ7ie=%O&`BkUSS8HW{Hn7Oq{vD(28(){T za(sj3e$hWL1O}d5`OZ1^r;|On=A9}G2m6gV=Px8{bC;cT@cH9`i-RA}MOA)&-0|~8 ztgQ2wv>5nPtrhL91phMd$5PAKI}0ip_;aNd>}>_l8Tf;t<?Ou$Eeut=9wpWy!54<A zz0Dk!ogj-*XlEnO`byBwD73ecWw{8d89{b7iY#-%OGc2rjSOq0pp?;VXQRMcCg@{y z+uO*oJOsZntnF-+Sc?T87}oanb66_`Cm1*E>g8EW1rHcE?CWJ&Zh~4yyj{H_%Th4L zh_|noVL1sdGRE!d6<9Wcr;Ks?dO4Ptpow8<SFgk}70fUU?Gxs(>;<`ua=Qe1))GM{ zquf40mgOqA%80N_P-IyM-Y_EU6J%J9f-=T4y95Q+a=|0UGy4QNmZ#tj!`&`HiDf33 zVz}E2=dc_E#f)Y<p*+i4(8Fl97s|5S1@(+{JE0=WN+4vU+Y4n_&VowDtesGSWh;2W zn6($mvAhNM7)o|RrQ}5d2}8-=c+TIvltq5d0w0Fw$!(0*lY@+mlb(z-2I;0(?WTOz z@2pV!JGw$P*-r3X{+^TS`Idq<hWKRvBE|XTjOCq~`97U8`M&cb82dVX@-+me4BwOc z^0#+taDV7D&DZMOp6_dL&G+Pr;#Ge{d(3-j*ZEC;he6z`g>5PGxu;L&`7Y$8$aDWb z>A!kmN6I{T6+M67zoL`X<hAs=R)4)cd7-?4UYGA*+mmJGP4%o+e;p&zQT}#W=3Jjb zULb=TTA}7s#9P966<RUZr-ZkMAs<$u;d7d2z%UQ1Q1Lm#3uE|&RjB)%<+(C;gjJ~e zoa3c3a>6P!eJ=167&T#Am3_*2YZ%<Ht!h4(covLTVO!_=RPlB)<iodW`25V%WtfL= zRq?sZ+syC_->U9&h3ClF5x!N`=Nj)IBPV>Trq6YrI-@51xw6j<-UbFY{JEOXue{}q zSK-g+`ZVzNG2|njYxuBuMhx?a=PEw8c-t6$5zp0qZu2}DJ0hN|`rPGZFmfWEYx*?u z<QO#(9?Cw=JYNPk!b8ocm1o9y72z@0hr^3y$Zz$~@M+`eFwD1lsQ7g7HZlCRdZ_#G zcn*vmTRl{Lx_Ac|Ia@t6eSYVuGHSNADEoBtf*9PbEowf0@~j!Jwzkam>E*>U<hQkG z`25W?WSDPjQSs^LMKJufwW#|%<n=E4zouzd`EB|Ws~CqwHu5|5CwxvF5_!q*(>Gbg zI4m-iKd5iwbLz0jUOq#=Y84|zv_$^6ewELu6p^cZk$%)FMykj{{;YnK?Aqx>cP zp;e4D(Q^4K`a?da(nPAt;kKD7KL7F>7X8vX?I_=<&pGzfr<Zpb@=;$jvR)Pr`JOr= zQc}KXD^d3Ok5{$mmwVF=@=x@c$9|f9*}%w&`l6oop^)QyDpRDX{M1&W;`4>aS@a8M z+FAayzVz5n(wCf5|3!V#ER_^an2vH5Dg{cf9IcUlySk5gebFfAA1p2in6X`ME<UGG zDhbjIl<vgxeh+-s!Fq*qp!Bsl3~^adcM%)|YynuKWU%@@B6>6c3kg&JTM5(w9t5g@ zBLv8PEeo)r%+&;HfW-uJ0Wk!WqfJ0L-x5&H3IfX6Pe3_y0rix#j(~EO5>U=w0?JuH zKsn(Al;cJ~IcWrxqX<Z#oV5g$V@W_cy9g*pkAQNv5KxX20p%Pbpd1Z=ka9K>P>u}& z<s=YLjxhn{L=sSr7XjsD5>So|z?gD;0Ec|~m`~u_sfpWYg)jxd)u2?;y#yaN9<P!9 zMi<aVAF}ZQ**m>qm4k2xm$xvdM*4w)YkCIZ5D9dN^U*&Fp?FmvGxaOjFXKZGF8zZY zteSZMWk3lve?^cBm`{KWKe!N(M;;JN9xJp<<{|V9cJQF-HWBCo`U#8x4g@-YTLgxH z0|fejj|3(FRX_^^P)I;i1`$wlH^D-HHGwwZ2EhVAJb@lyoWK}hNT3BMC!l#E2xy*X z1T>F30nO7)K=Y&%&^)sQG>;PC2+fm6K=b$$&^%oPG>;Vl&2x=_=7}Sqc}56m9(@9u z=Ntje6GA}qJSL!doC#>2y96{(6|Va80i5v=e%?N8Bfu4Z$N+fLUHKB=IzPk`kY^JC zd8ms+o*)A9#1oJwf`B~wbZInr6zxOnOgX$tiTGE<7bCnA9J*pnGSTGTWQv1HDhpE- znG9iKlF5WjG&++^iDaTA=Fe|AUrgqS&kgzh&2-c_A+eTOBR!i_EnVmHH}eV>SA6|n zRM=ND4GZUqLyS*IZp>LDeVBsJmaE{`f)EJ9pYl-uAdm&r0XCy#u=?bux15Vc09OJX zKqG-6AeBHL@R`5_pa2MG0FD#P2dp8O2jCGb1XvJg1FjG(0PG~t1H2}n8FdM0wzC8V zfXxKDfQJM$k0SxibDMzXIY>bBOcKyM>VT&-PZ0slvw?u-`ICU=Sx!Ln{7OLc>?5Fg z-Vx9|Mg%m^B?6jf8v)HTNI>&=63{%Y1T;?u0nH;Opn2o~ZZuCeU@WUzT1!4-+(sI1 zYAm~2x_1SxX%kj2&RrwjEJs$XTvWsd%FcvU5vzM~xsJ-XDpOq3ZR(}lq)W6ze?No; z$Eu}cU&FqZ`teRY+zzXe20)8I1@H}lI>4Sl6_8Az2~YuCq78zv+sqP#T4BqBG~G39 zb#N&GDQ<u`QY;BbaRQ8xVnaZR7eJpBQvy=#0q01e<a4CB0zyc!ARxsN@R*e41f+NZ zoJlbwAjJW2mlSIPQrrQDNwFdz#ToF46k7sPyaAd}CKnMvnWR%IA>}IqQd|JRq?i+s zvJ%is$}$2{JOH+&EG8g@&ZmJCI-dqo=zJ1Mq4P;3h0eztS3Nd@Gj5f`88;Is0cHUi z^aGklK-bwtKtGe$2=E#_q^=CQ&vOI{fX4)sbC-Z}Z0XYIAUSx)#%Nuvh_`2GHMV!h zJCR9OY(geFNhX<k$)o@ihfK~eN$6eiCKDZ{luScpQi4gkx}Q1ey?dtNUfxw{+QOCM z$FdhC@hTgnx3jKF!+rai`+geb-1+OjD0g@~u`F{@GA_dB;G^&_hHwUkN)@OVeg-H2 z!T|M96|s8Dr=RKR4mhw1U`0TRGvFgBwgjYj15}~3E+T-^Y6mDJ<tqYGTmV6&m=ln) z63|V`G6GUO0M?|?Y}TZ#0NfyDDFG>NfOt|Y2}p4QjFVzRK#CW@kQ7q_QtSccq%0vI z#T5`iiUk2Fj(}®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%0A3uP*# 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 QIZyrtlaJ=eI208B2NvrYn*aa+ literal 0 HcmV?d00001 diff --git a/src/refinement/stemmers/lovins.py b/src/refinement/stemmers/lovins.py new file mode 100644 index 0000000..84a9e03 --- /dev/null +++ b/src/refinement/stemmers/lovins.py @@ -0,0 +1,19 @@ +#!/bin/python +from stemmers.abstractstemmer import AbstractStemmer +import stemmers.lovinsstemmer as lovinsstemmer +import sys + + +class LovinsStemmer(AbstractStemmer): + + def __init__(self, ): + super(LovinsStemmer, self).__init__() + self.basename = 'lovins' + + def process(self, words): + return [lovinsstemmer.stem(word) for word in words] + + +if __name__ == '__main__': + stemmer = LovinsStemmer() + stemmer.stem(sys.argv[1:]) diff --git a/src/refinement/stemmers/lovinsstemmer.py b/src/refinement/stemmers/lovinsstemmer.py new file mode 100644 index 0000000..6c59bb3 --- /dev/null +++ b/src/refinement/stemmers/lovinsstemmer.py @@ -0,0 +1,542 @@ +"""This module implements the Lovins stemming algorithm. Use the ``stem()`` +function:: + + stemmed_word = stem(word) +""" + +from collections import defaultdict + + +# Conditions + +def A(base): + # A No restrictions on stem + return True + +def B(base): + # B Minimum stem length = 3 + return len(base) > 2 + +def C(base): + # C Minimum stem length = 4 + return len(base) > 3 + +def D(base): + # D Minimum stem length = 5 + return len(base) > 4 + +def E(base): + # E Do not remove ending after e + return base[-1] != "e" + +def F(base): + # F Minimum stem length = 3 and do not remove ending after e + return len(base) > 2 and base[-1] != "e" + +def G(base): + # G Minimum stem length = 3 and remove ending only after f + return len(base) > 2 and base[-1] == "f" + +def H(base): + # H Remove ending only after t or ll + c1, c2 = base[-2:] + return c2 == "t" or (c2 == "l" and c1 == "l") + +def I(base): + # I Do not remove ending after o or e + c = base[-1] + return c != "o" and c != "e" + +def J(base): + # J Do not remove ending after a or e + c = base[-1] + return c != "a" and c != "e" + +def K(base): + # K Minimum stem length = 3 and remove ending only after l, i or u*e + c = base[-1] + cc = "" if len(base) < 3 else base[-3] + return len(base) > 2 and (c == "l" or c == "i" or (c == "e" and cc == "u")) + +def L(base): + # L Do not remove ending after u, x or s, unless s follows o + c1, c2 = base[-2:] + return c2 != "u" and c2 != "x" and (c2 != "s" or c1 == "o") + +def M(base): + # M Do not remove ending after a, c, e or m + c = base[-1] + return c != "a" and c!= "c" and c != "e" and c != "m" + +def N(base): + # N Minimum stem length = 4 after s**, elsewhere = 3 + return len(base) > 3 or (len(base) == 3 and base[-1] != "s") + +def O(base): + # O Remove ending only after l or i + c = base[-1] + return c == "l" or c == "i" + +def P(base): + # P Do not remove ending after c + return base[-1] != "c" + +def Q(base): + # Q Minimum stem length = 3 and do not remove ending after l or n + c = base[-1] + return len(base) > 2 and (c != "l" and c != "n") + +def R(base): + # R Remove ending only after n or r + c = base[-1] + return c == "n" or c == "r" + +def S(base): + # S Remove ending only after dr or t, unless t follows t + l2 = base[-2] + return l2 == "rd" or (base[-1] == "t" and l2 != "tt") + +def T(base): + # T Remove ending only after s or t, unless t follows o + c1, c2 = base[-2:] + return c2 == "s" or (c2 == "t" and c1 != "o") + +def U(base): + # U Remove ending only after l, m, n or r + c = base[-1] + return c == "l" or c == "m" or c == "n" or c == "r" + +def V(base): + # V Remove ending only after c + return base[-1] == "c" + +def W(base): + # W Do not remove ending after s or u + c = base[-1] + return c != "s" and c != "u" + +def X(base): + # X Remove ending only after l, i or u*e + c = base[-1] + cc = "" if len(base) < 3 else base[-3] + return c == "l" or c == "i" or (c == "e" and cc == "u") + +def Y(base): + # Y Remove ending only after in + return base[-2:] == "in" + +def Z(base): + # Z Do not remove ending after f + return base[-1] != "f" + +def a(base): + # a Remove ending only after d, f, ph, th, l, er, or, es or t + c = base[-1] + l2 = base[-2:] + return (c == "d" or c == "f" or l2 == "ph" or l2 == "th" or c == "l" + or l2 == "er" or l2 == "or" or l2 == "es" or c == "t") + +def b(base): + # b Minimum stem length = 3 and do not remove ending after met or ryst + return len(base) > 2 and not (base.endswith("met") + or base.endswith("ryst")) + +def c(base): + # c Remove ending only after l + return base[-1] == "l" + +# Endings + +m = [None] * 12 + +m[11] = dict(( + ("alistically", B), + ("arizability", A), + ("izationally", B))) +m[10] = dict(( + ("antialness", A), + ("arisations", A), + ("arizations", A), + ("entialness", A))) +m[9] = dict(( + ("allically", C), + ("antaneous", A), + ("antiality", A), + ("arisation", A), + ("arization", A), + ("ationally", B), + ("ativeness", A), + ("eableness", E), + ("entations", A), + ("entiality", A), + ("entialize", A), + ("entiation", A), + ("ionalness", A), + ("istically", A), + ("itousness", A), + ("izability", A), + ("izational", A))) +m[8] = dict(( + ("ableness", A), + ("arizable", A), + ("entation", A), + ("entially", A), + ("eousness", A), + ("ibleness", A), + ("icalness", A), + ("ionalism", A), + ("ionality", A), + ("ionalize", A), + ("iousness", A), + ("izations", A), + ("lessness", A))) +m[7] = dict(( + ("ability", A), + ("aically", A), + ("alistic", B), + ("alities", A), + ("ariness", E), + ("aristic", A), + ("arizing", A), + ("ateness", A), + ("atingly", A), + ("ational", B), + ("atively", A), + ("ativism", A), + ("elihood", E), + ("encible", A), + ("entally", A), + ("entials", A), + ("entiate", A), + ("entness", A), + ("fulness", A), + ("ibility", A), + ("icalism", A), + ("icalist", A), + ("icality", A), + ("icalize", A), + ("ication", G), + ("icianry", A), + ("ination", A), + ("ingness", A), + ("ionally", A), + ("isation", A), + ("ishness", A), + ("istical", A), + ("iteness", A), + ("iveness", A), + ("ivistic", A), + ("ivities", A), + ("ization", F), + ("izement", A), + ("oidally", A), + ("ousness", A))) +m[6] = dict(( + ("aceous", A), + ("acious", B), + ("action", G), + ("alness", A), + ("ancial", A), + ("ancies", A), + ("ancing", B), + ("ariser", A), + ("arized", A), + ("arizer", A), + ("atable", A), + ("ations", B), + ("atives", A), + ("eature", Z), + ("efully", A), + ("encies", A), + ("encing", A), + ("ential", A), + ("enting", C), + ("entist", A), + ("eously", A), + ("ialist", A), + ("iality", A), + ("ialize", A), + ("ically", A), + ("icance", A), + ("icians", A), + ("icists", A), + ("ifully", A), + ("ionals", A), + ("ionate", D), + ("ioning", A), + ("ionist", A), + ("iously", A), + ("istics", A), + ("izable", E), + ("lessly", A), + ("nesses", A), + ("oidism", A))) +m[5] = dict(( + ("acies", A), + ("acity", A), + ("aging", B), + ("aical", A), + ("alist", A), + ("alism", B), + ("ality", A), + ("alize", A), + ("allic", b), + ("anced", B), + ("ances", B), + ("antic", C), + ("arial", A), + ("aries", A), + ("arily", A), + ("arity", B), + ("arize", A), + ("aroid", A), + ("ately", A), + ("ating", I), + ("ation", B), + ("ative", A), + ("ators", A), + ("atory", A), + ("ature", E), + ("early", Y), + ("ehood", A), + ("eless", A), + ("elily", A), + ("ement", A), + ("enced", A), + ("ences", A), + ("eness", E), + ("ening", E), + ("ental", A), + ("ented", C), + ("ently", A), + ("fully", A), + ("ially", A), + ("icant", A), + ("ician", A), + ("icide", A), + ("icism", A), + ("icist", A), + ("icity", A), + ("idine", I), + ("iedly", A), + ("ihood", A), + ("inate", A), + ("iness", A), + ("ingly", B), + ("inism", J), + ("inity", c), + ("ional", A), + ("ioned", A), + ("ished", A), + ("istic", A), + ("ities", A), + ("itous", A), + ("ively", A), + ("ivity", A), + ("izers", F), + ("izing", F), + ("oidal", A), + ("oides", A), + ("otide", A), + ("ously", A))) +m[4] = dict(( + ("able", A), + ("ably", A), + ("ages", B), + ("ally", B), + ("ance", B), + ("ancy", B), + ("ants", B), + ("aric", A), + ("arly", K), + ("ated", I), + ("ates", A), + ("atic", B), + ("ator", A), + ("ealy", Y), + ("edly", E), + ("eful", A), + ("eity", A), + ("ence", A), + ("ency", A), + ("ened", E), + ("enly", E), + ("eous", A), + ("hood", A), + ("ials", A), + ("ians", A), + ("ible", A), + ("ibly", A), + ("ical", A), + ("ides", L), + ("iers", A), + ("iful", A), + ("ines", M), + ("ings", N), + ("ions", B), + ("ious", A), + ("isms", B), + ("ists", A), + ("itic", H), + ("ized", F), + ("izer", F), + ("less", A), + ("lily", A), + ("ness", A), + ("ogen", A), + ("ward", A), + ("wise", A), + ("ying", B), + ("yish", A))) +m[3] = dict(( + ("acy", A), + ("age", B), + ("aic", A), + ("als", b), + ("ant", B), + ("ars", O), + ("ary", F), + ("ata", A), + ("ate", A), + ("eal", Y), + ("ear", Y), + ("ely", E), + ("ene", E), + ("ent", C), + ("ery", E), + ("ese", A), + ("ful", A), + ("ial", A), + ("ian", A), + ("ics", A), + ("ide", L), + ("ied", A), + ("ier", A), + ("ies", P), + ("ily", A), + ("ine", M), + ("ing", N), + ("ion", Q), + ("ish", C), + ("ism", B), + ("ist", A), + ("ite", a), + ("ity", A), + ("ium", A), + ("ive", A), + ("ize", F), + ("oid", A), + ("one", R), + ("ous", A))) +m[2] = dict(( + ("ae", A), + ("al", b), + ("ar", X), + ("as", B), + ("ed", E), + ("en", F), + ("es", E), + ("ia", A), + ("ic", A), + ("is", A), + ("ly", B), + ("on", S), + ("or", T), + ("um", U), + ("us", V), + ("yl", R), + ("s'", A), + ("'s", A))) +m[1] = dict(( + ("a", A), + ("e", A), + ("i", A), + ("o", A), + ("s", W), + ("y", B))) + + +def remove_ending(word): + length = len(word) + el = 11 + while el > 0: + if length - el > 1: + ending = word[length-el:] + cond = m[el].get(ending) + if cond: + base = word[:length-el] + if cond(base): + return base + el -= 1 + return word + + +_endings = (("iev", "ief"), + ("uct", "uc"), + ("iev", "ief"), + ("uct", "uc"), + ("umpt", "um"), + ("rpt", "rb"), + ("urs", "ur"), + ("istr", "ister"), + ("metr", "meter"), + ("olv", "olut"), + ("ul", "l", "aoi"), + ("bex", "bic"), + ("dex", "dic"), + ("pex", "pic"), + ("tex", "tic"), + ("ax", "ac"), + ("ex", "ec"), + ("ix", "ic"), + ("lux", "luc"), + ("uad", "uas"), + ("vad", "vas"), + ("cid", "cis"), + ("lid", "lis"), + ("erid", "eris"), + ("pand", "pans"), + ("end", "ens", "s"), + ("ond", "ons"), + ("lud", "lus"), + ("rud", "rus"), + ("her", "hes", "pt"), + ("mit", "mis"), + ("ent", "ens", "m"), + ("ert", "ers"), + ("et", "es", "n"), + ("yt", "ys"), + ("yz", "ys")) + +# Hash the ending rules by the last letter of the target ending +_endingrules = defaultdict(list) +for rule in _endings: + _endingrules[rule[0][-1]].append(rule) + +_doubles = frozenset(("dd", "gg", "ll", "mm", "nn", "pp", "rr", "ss", "tt")) + + +def fix_ending(word): + if word[-2:] in _doubles: + word = word[:-1] + + for endingrule in _endingrules[word[-1]]: + target, newend = endingrule[:2] + if word.endswith(target): + if len(endingrule) > 2 and len(word) > len(target): + exceptafter = endingrule[2] + c = word[0-(len(target)+1)] + if c in exceptafter: return word + + return word[:0-len(target)] + newend + + return word + + +def stem(word): + """Returns the stemmed version of the argument string. + """ + return fix_ending(remove_ending(word)) + + + diff --git a/src/refinement/stemmers/nostemmer.py b/src/refinement/stemmers/nostemmer.py new file mode 100644 index 0000000..bba960a --- /dev/null +++ b/src/refinement/stemmers/nostemmer.py @@ -0,0 +1,18 @@ +#!/bin/python +from abstractstemmer import AbstractStemmer +import sys + + +class NoStemmer(AbstractStemmer): + + def __init__(self, ): + super(NoStemmer, self).__init__() + self.basename = 'nostemmer' + + def process(self, words): + return words + + +if __name__ == '__main__': + stemmer = NoStemmer() + stemmer.stem(sys.argv[1:]) diff --git a/src/refinement/stemmers/paicehusk.py b/src/refinement/stemmers/paicehusk.py new file mode 100644 index 0000000..6046093 --- /dev/null +++ b/src/refinement/stemmers/paicehusk.py @@ -0,0 +1,19 @@ +#!/bin/python +from stemmers.abstractstemmer import AbstractStemmer +import stemmers.paicehuskstemmer as paicehuskstemmer +import sys + + +class PaiceHuskStemmer(AbstractStemmer): + + def __init__(self, ): + super(PaiceHuskStemmer, self).__init__() + self.basename = 'paicehusk' + + def process(self, words): + return [paicehuskstemmer.stem(word) for word in words] + + +if __name__ == '__main__': + stemmer = PaiceHuskStemmer() + stemmer.stem(sys.argv[1:]) diff --git a/src/refinement/stemmers/paicehuskstemmer.py b/src/refinement/stemmers/paicehuskstemmer.py new file mode 100644 index 0000000..6a1b866 --- /dev/null +++ b/src/refinement/stemmers/paicehuskstemmer.py @@ -0,0 +1,254 @@ +"""This module contains an object that implements the Paice-Husk stemming +algorithm. + +If you just want to use the standard Paice-Husk stemming rules, use the +module's ``stem()`` function:: + + stemmed_word = stem(word) + +If you want to use a custom rule set, read the rules into a string where the +rules are separated by newlines, and instantiate the object with the string, +then use the object's stem method to stem words:: + + stemmer = PaiceHuskStemmer(my_rules_string) + stemmed_word = stemmer.stem(word) +""" + +import re +from collections import defaultdict + + +class PaiceHuskStemmer(object): + """Implements the Paice-Husk stemming algorithm. + """ + + rule_expr = re.compile(r""" + ^(?P<ending>\w+) + (?P<intact>[*]?) + (?P<num>\d+) + (?P<append>\w*) + (?P<cont>[.>]) + """, re.UNICODE | re.VERBOSE) + + stem_expr = re.compile("^\w+", re.UNICODE) + + def __init__(self, ruletable): + """ + :param ruletable: a string containing the rule data, separated + by newlines. + """ + self.rules = defaultdict(list) + self.read_rules(ruletable) + + def read_rules(self, ruletable): + rule_expr = self.rule_expr + rules = self.rules + + for line in ruletable.split("\n"): + line = line.strip() + if not line: + continue + + match = rule_expr.match(line) + if match: + ending = match.group("ending")[::-1] + lastchar = ending[-1] + intact = match.group("intact") == "*" + num = int(match.group("num")) + append = match.group("append") + cont = match.group("cont") == ">" + + rules[lastchar].append((ending, intact, num, append, cont)) + else: + raise Exception("Bad rule: %r" % line) + + def first_vowel(self, word): + # Find the first position of each regular vowel (if any) + has_vowel_list = [p for p in [word.find(v) for v in "aeiou"] if p > -1] + # We add some logic to make sure y can be the only vowel + if len(has_vowel_list) > 0: + vp = min(has_vowel_list) + else: + vp = -1 + yp = word.find("y") + if yp > 0 and (yp < vp | vp == -1): + return yp + return vp + + def strip_prefix(self, word): + for prefix in ("kilo", "micro", "milli", "intra", "ultra", "mega", + "nano", "pico", "pseudo"): + if word.startswith(prefix) and len(word) > len(prefix): + return word[len(prefix):] + return word + + def stem(self, word): + """Returns a stemmed version of the argument string. + """ + if len(word) == 0: + return word + + rules = self.rules + match = self.stem_expr.match(word) + if not match: return word + stem = self.strip_prefix(match.group(0)) + + is_intact = True + continuing = True + while continuing: + rulelist = rules.get(stem[-1]) + if not rulelist: break + pfv = self.first_vowel(stem) + continuing = False + for ending, intact, num, append, cont in rulelist: + if stem.endswith(ending): + if intact and not is_intact: continue + newlen = len(stem) - num + len(append) + if ((pfv == 0 and newlen < 2) + or (pfv > 0 and newlen < 3) + or (pfv >= newlen) + or (pfv < 0)): + # If word starts with vowel, minimum stem length is 2. + # If word starts with consonant, minimum stem length is + # 3 and there must be a vowel in the stem somewhere + continue + + is_intact = False + if num > 0: + stem = stem[:0-num] + append + + continuing = cont + break + + return stem + +# The default rules for the Paice-Husk stemming algorithm + +defaultrules = """ +ai*2. { -ia > - if intact } +a*1. { -a > - if intact } +bb1. { -bb > -b } +city3s. { -ytic > -ys } +ci2> { -ic > - } +cn1t> { -nc > -nt } +dd1. { -dd > -d } +dei3y> { -ied > -y } +deec2ss. { -ceed > -cess } +dee1. { -eed > -ee } +de2> { -ed > - } +dooh4> { -hood > - } +e1> { -e > - } +feil1v. { -lief > -liev } +fi2> { -if > - } +gni3> { -ing > - } +gai3y. { -iag > -y } +ga2> { -ag > - } +gg1. { -gg > -g } +ht*2. { -th > - if intact } +hsiug5ct. { -guish > -ct } +hsi3> { -ish > - } +i*1. { -i > - if intact } +i1y> { -i > -y } +ji1d. { -ij > -id -- see nois4j> & vis3j> } +juf1s. { -fuj > -fus } +ju1d. { -uj > -ud } +jo1d. { -oj > -od } +jeh1r. { -hej > -her } +jrev1t. { -verj > -vert } +jsim2t. { -misj > -mit } +jn1d. { -nj > -nd } +j1s. { -j > -s } +lbaifi6. { -ifiabl > - } +lbai4y. { -iabl > -y } +lba3> { -abl > - } +lbi3. { -ibl > - } +lib2l> { -bil > -bl } +lc1. { -cl > c } +lufi4y. { -iful > -y } +luf3> { -ful > - } +lu2. { -ul > - } +lai3> { -ial > - } +lau3> { -ual > - } +la2> { -al > - } +ll1. { -ll > -l } +mui3. { -ium > - } +mu*2. { -um > - if intact } +msi3> { -ism > - } +mm1. { -mm > -m } +nois4j> { -sion > -j } +noix4ct. { -xion > -ct } +noi3> { -ion > - } +nai3> { -ian > - } +na2> { -an > - } +nee0. { protect -een } +ne2> { -en > - } +nn1. { -nn > -n } +pihs4> { -ship > - } +pp1. { -pp > -p } +re2> { -er > - } +rae0. { protect -ear } +ra2. { -ar > - } +ro2> { -or > - } +ru2> { -ur > - } +rr1. { -rr > -r } +rt1> { -tr > -t } +rei3y> { -ier > -y } +sei3y> { -ies > -y } +sis2. { -sis > -s } +si2> { -is > - } +ssen4> { -ness > - } +ss0. { protect -ss } +suo3> { -ous > - } +su*2. { -us > - if intact } +s*1> { -s > - if intact } +s0. { -s > -s } +tacilp4y. { -plicat > -ply } +ta2> { -at > - } +tnem4> { -ment > - } +tne3> { -ent > - } +tna3> { -ant > - } +tpir2b. { -ript > -rib } +tpro2b. { -orpt > -orb } +tcud1. { -duct > -duc } +tpmus2. { -sumpt > -sum } +tpec2iv. { -cept > -ceiv } +tulo2v. { -olut > -olv } +tsis0. { protect -sist } +tsi3> { -ist > - } +tt1. { -tt > -t } +uqi3. { -iqu > - } +ugo1. { -ogu > -og } +vis3j> { -siv > -j } +vie0. { protect -eiv } +vi2> { -iv > - } +ylb1> { -bly > -bl } +yli3y> { -ily > -y } +ylp0. { protect -ply } +yl2> { -ly > - } +ygo1. { -ogy > -og } +yhp1. { -phy > -ph } +ymo1. { -omy > -om } +ypo1. { -opy > -op } +yti3> { -ity > - } +yte3> { -ety > - } +ytl2. { -lty > -l } +yrtsi5. { -istry > - } +yra3> { -ary > - } +yro3> { -ory > - } +yfi3. { -ify > - } +ycn2t> { -ncy > -nt } +yca3> { -acy > - } +zi2> { -iz > - } +zy1s. { -yz > -ys } +""" + +# Make the standard rules available as a module-level function + +stem = PaiceHuskStemmer(defaultrules).stem + + + + + + + diff --git a/src/refinement/stemmers/porter.py b/src/refinement/stemmers/porter.py new file mode 100644 index 0000000..19506ea --- /dev/null +++ b/src/refinement/stemmers/porter.py @@ -0,0 +1,19 @@ +#!/bin/python +from stemmers.abstractstemmer import AbstractStemmer +from stemmers import porterstemmer +import sys + + +class PorterStemmer(AbstractStemmer): + + def __init__(self, ): + super(PorterStemmer, self).__init__() + self.basename = 'porter' + + def process(self, words): + return [porterstemmer.stem(word) for word in words] + + +if __name__ == '__main__': + stemmer = PorterStemmer() + # stemmer.stem(sys.argv[1:]) diff --git a/src/refinement/stemmers/porter2.py b/src/refinement/stemmers/porter2.py new file mode 100644 index 0000000..83a32cb --- /dev/null +++ b/src/refinement/stemmers/porter2.py @@ -0,0 +1,19 @@ +#!/bin/python +from stemmers.abstractstemmer import AbstractStemmer +import stemmers.porter2stemmer as porter2stemmer +import sys + + +class Porter2Stemmer(AbstractStemmer): + + def __init__(self, ): + super(Porter2Stemmer, self).__init__() + self.basename = 'porter2' + + def process(self, words): + return [porter2stemmer.stem(word) for word in words] + + +if __name__ == '__main__': + stemmer = Porter2Stemmer() + stemmer.stem(sys.argv[1:]) diff --git a/src/refinement/stemmers/porter2stemmer.py b/src/refinement/stemmers/porter2stemmer.py new file mode 100644 index 0000000..ebb2380 --- /dev/null +++ b/src/refinement/stemmers/porter2stemmer.py @@ -0,0 +1,288 @@ +"""An implementation of the Porter2 stemming algorithm. +See http://snowball.tartarus.org/algorithms/english/stemmer.html + +Adapted from pyporter2 by Michael Dirolf. + +This algorithm is more correct but (at least in this implementation) +several times slower than the original porter algorithm as implemented +in stemming.porter. +""" + +import re + +r_exp = re.compile(r"[^aeiouy]*[aeiouy]+[^aeiouy](\w*)") +ewss_exp1 = re.compile(r"^[aeiouy][^aeiouy]$") +ewss_exp2 = re.compile(r".*[^aeiouy][aeiouy][^aeiouywxY]$") +ccy_exp = re.compile(r"([aeiouy])y") +s1a_exp = re.compile(r"[aeiouy].") +s1b_exp = re.compile(r"[aeiouy]") + +def get_r1(word): + # exceptional forms + if word.startswith('gener') or word.startswith('arsen'): + return 5 + if word.startswith('commun'): + return 6 + + # normal form + match = r_exp.match(word) + if match: + return match.start(1) + return len(word) + +def get_r2(word): + match = r_exp.match(word, get_r1(word)) + if match: + return match.start(1) + return len(word) + +def ends_with_short_syllable(word): + if len(word) == 2: + if ewss_exp1.match(word): + return True + if ewss_exp2.match(word): + return True + return False + +def is_short_word(word): + if ends_with_short_syllable(word): + if get_r1(word) == len(word): + return True + return False + +def remove_initial_apostrophe(word): + if word.startswith("'"): + return word[1:] + return word + +def capitalize_consonant_ys(word): + if word.startswith('y'): + word = 'Y' + word[1:] + return ccy_exp.sub('\g<1>Y', word) + +def step_0(word): + if word.endswith("'s'"): + return word[:-3] + if word.endswith("'s"): + return word[:-2] + if word.endswith("'"): + return word[:-1] + return word + +def step_1a(word): + if word.endswith('sses'): + return word[:-4] + 'ss' + if word.endswith('ied') or word.endswith('ies'): + if len(word) > 4: + return word[:-3] + 'i' + else: + return word[:-3] + 'ie' + if word.endswith('us') or word.endswith('ss'): + return word + if word.endswith('s'): + preceding = word[:-1] + if s1a_exp.search(preceding): + return preceding + return word + return word + +doubles = ('bb', 'dd', 'ff', 'gg', 'mm', 'nn', 'pp', 'rr', 'tt') +def ends_with_double(word): + for double in doubles: + if word.endswith(double): + return True + return False +def step_1b_helper(word): + if word.endswith('at') or word.endswith('bl') or word.endswith('iz'): + return word + 'e' + if ends_with_double(word): + return word[:-1] + if is_short_word(word): + return word + 'e' + return word +s1b_suffixes = ('ed', 'edly', 'ing', 'ingly') + +def step_1b(word, r1): + if word.endswith('eedly'): + if len(word) - 5 >= r1: + return word[:-3] + return word + if word.endswith('eed'): + if len(word) - 3 >= r1: + return word[:-1] + return word + + for suffix in s1b_suffixes: + if word.endswith(suffix): + preceding = word[:-len(suffix)] + if s1b_exp.search(preceding): + return step_1b_helper(preceding) + return word + + return word + +def step_1c(word): + if word.endswith('y') or word.endswith('Y') and len(word) > 1: + if word[-2] not in 'aeiouy': + if len(word) > 2: + return word[:-1] + 'i' + return word + +def step_2_helper(word, r1, end, repl, prev): + if word.endswith(end): + if len(word) - len(end) >= r1: + if prev == []: + return word[:-len(end)] + repl + for p in prev: + if word[:-len(end)].endswith(p): + return word[:-len(end)] + repl + return word + return None +s2_triples = (('ization', 'ize', []), + ('ational', 'ate', []), + ('fulness', 'ful', []), + ('ousness', 'ous', []), + ('iveness', 'ive', []), + ('tional', 'tion', []), + ('biliti', 'ble', []), + ('lessli', 'less', []), + ('entli', 'ent', []), + ('ation', 'ate', []), + ('alism', 'al', []), + ('aliti', 'al', []), + ('ousli', 'ous', []), + ('iviti', 'ive', []), + ('fulli', 'ful', []), + ('enci', 'ence', []), + ('anci', 'ance', []), + ('abli', 'able', []), + ('izer', 'ize', []), + ('ator', 'ate', []), + ('alli', 'al', []), + ('bli', 'ble', []), + ('ogi', 'og', ['l']), + ('li', '', ['c', 'd', 'e', 'g', 'h', 'k', 'm', 'n', 'r', 't'])) + +def step_2(word, r1): + for trip in s2_triples: + attempt = step_2_helper(word, r1, trip[0], trip[1], trip[2]) + if attempt: + return attempt + return word + +def step_3_helper(word, r1, r2, end, repl, r2_necessary): + if word.endswith(end): + if len(word) - len(end) >= r1: + if not r2_necessary: + return word[:-len(end)] + repl + else: + if len(word) - len(end) >= r2: + return word[:-len(end)] + repl + return word + return None +s3_triples = (('ational', 'ate', False), + ('tional', 'tion', False), + ('alize', 'al', False), + ('icate', 'ic', False), + ('iciti', 'ic', False), + ('ative', '', True), + ('ical', 'ic', False), + ('ness', '', False), + ('ful', '', False)) +def step_3(word, r1, r2): + for trip in s3_triples: + attempt = step_3_helper(word, r1, r2, trip[0], trip[1], trip[2]) + if attempt: + return attempt + return word + +s4_delete_list = ('al', 'ance', 'ence', 'er', 'ic', 'able', 'ible', 'ant', 'ement', + 'ment', 'ent', 'ism', 'ate', 'iti', 'ous', 'ive', 'ize') + +def step_4(word, r2): + for end in s4_delete_list: + if word.endswith(end): + if len(word) - len(end) >= r2: + return word[:-len(end)] + return word + + if word.endswith('sion') or word.endswith('tion'): + if len(word) - 3 >= r2: + return word[:-3] + + return word + +def step_5(word, r1, r2): + if word.endswith('l'): + if len(word) - 1 >= r2 and word[-2] == 'l': + return word[:-1] + return word + + if word.endswith('e'): + if len(word) - 1 >= r2: + return word[:-1] + if len(word) - 1 >= r1 and not ends_with_short_syllable(word[:-1]): + return word[:-1] + + return word + +def normalize_ys(word): + return word.replace('Y', 'y') + +exceptional_forms = {'skis': 'ski', + 'skies': 'sky', + 'dying': 'die', + 'lying': 'lie', + 'tying': 'tie', + 'idly': 'idl', + 'gently': 'gentl', + 'ugly': 'ugli', + 'early': 'earli', + 'only': 'onli', + 'singly': 'singl', + 'sky': 'sky', + 'news': 'news', + 'howe': 'howe', + 'atlas': 'atlas', + 'cosmos': 'cosmos', + 'bias': 'bias', + 'andes': 'andes'} + +exceptional_early_exit_post_1a = frozenset(['inning', 'outing', 'canning', 'herring', + 'earring', 'proceed', 'exceed', 'succeed']) + + +def stem(word): + if len(word) <= 2: + return word + word = remove_initial_apostrophe(word) + + # handle some exceptional forms + if word in exceptional_forms: + return exceptional_forms[word] + + word = capitalize_consonant_ys(word) + r1 = get_r1(word) + r2 = get_r2(word) + word = step_0(word) + word = step_1a(word) + + # handle some more exceptional forms + if word in exceptional_early_exit_post_1a: + return word + + word = step_1b(word, r1) + word = step_1c(word) + word = step_2(word, r1) + word = step_3(word, r1, r2) + word = step_4(word, r2) + word = step_5(word, r1, r2) + word = normalize_ys(word) + + return word + +if __name__ == "__main__": + assert stem("bill's") == "bill" + assert stem("y's") == "y" + + diff --git a/src/refinement/stemmers/porterstemmer.py b/src/refinement/stemmers/porterstemmer.py new file mode 100644 index 0000000..29ff5a6 --- /dev/null +++ b/src/refinement/stemmers/porterstemmer.py @@ -0,0 +1,188 @@ +""" +Reimplementation of the +`Porter stemming algorithm <http://tartarus.org/~martin/PorterStemmer/>`_ +in Python. + +In my quick tests, this implementation about 3.5 times faster than the +seriously weird Python linked from the official page. +""" + +import re + +# Suffix replacement lists + +_step2list = { + "ational": "ate", + "tional": "tion", + "enci": "ence", + "anci": "ance", + "izer": "ize", + "bli": "ble", + "alli": "al", + "entli": "ent", + "eli": "e", + "ousli": "ous", + "ization": "ize", + "ation": "ate", + "ator": "ate", + "alism": "al", + "iveness": "ive", + "fulness": "ful", + "ousness": "ous", + "aliti": "al", + "iviti": "ive", + "biliti": "ble", + "logi": "log", + } + +_step3list = { + "icate": "ic", + "ative": "", + "alize": "al", + "iciti": "ic", + "ical": "ic", + "ful": "", + "ness": "", + } + + +_cons = "[^aeiou]" +_vowel = "[aeiouy]" +_cons_seq = "[^aeiouy]+" +_vowel_seq = "[aeiou]+" + +# m > 0 +_mgr0 = re.compile("^(" + _cons_seq + ")?" + _vowel_seq + _cons_seq) +# m == 0 +_meq1 = re.compile("^(" + _cons_seq + ")?" + _vowel_seq + _cons_seq + "(" + _vowel_seq + ")?$") +# m > 1 +_mgr1 = re.compile("^(" + _cons_seq + ")?" + _vowel_seq + _cons_seq + _vowel_seq + _cons_seq) +# vowel in stem +_s_v = re.compile("^(" + _cons_seq + ")?" + _vowel) +# ??? +_c_v = re.compile("^" + _cons_seq + _vowel + "[^aeiouwxy]$") + +# Patterns used in the rules + +_ed_ing = re.compile("^(.*)(ed|ing)$") +_at_bl_iz = re.compile("(at|bl|iz)$") +_step1b = re.compile("([^aeiouylsz])\\1$") +_step2 = re.compile("^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$") +_step3 = re.compile("^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$") +_step4_1 = re.compile("^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$") +_step4_2 = re.compile("^(.+?)(s|t)(ion)$") +_step5 = re.compile("^(.+?)e$") + +# Stemming function + +def stem(w): + """Uses the Porter stemming algorithm to remove suffixes from English + words. + + >>> stem("fundamentally") + "fundament" + """ + + if len(w) < 3: return w + + first_is_y = w[0] == "y" + if first_is_y: + w = "Y" + w[1:] + + # Step 1a + if w.endswith("s"): + if w.endswith("sses"): + w = w[:-2] + elif w.endswith("ies"): + w = w[:-2] + elif w[-2] != "s": + w = w[:-1] + + # Step 1b + + if w.endswith("eed"): + s = w[:-3] + if _mgr0.match(s): + w = w[:-1] + else: + m = _ed_ing.match(w) + if m: + stem = m.group(1) + if _s_v.match(stem): + w = stem + if _at_bl_iz.match(w): + w += "e" + elif _step1b.match(w): + w = w[:-1] + elif _c_v.match(w): + w += "e" + + # Step 1c + + if w.endswith("y"): + stem = w[:-1] + if _s_v.match(stem): + w = stem + "i" + + # Step 2 + + m = _step2.match(w) + if m: + stem = m.group(1) + suffix = m.group(2) + if _mgr0.match(stem): + w = stem + _step2list[suffix] + + # Step 3 + + m = _step3.match(w) + if m: + stem = m.group(1) + suffix = m.group(2) + if _mgr0.match(stem): + w = stem + _step3list[suffix] + + # Step 4 + + m = _step4_1.match(w) + if m: + stem = m.group(1) + if _mgr1.match(stem): + w = stem + else: + m = _step4_2.match(w) + if m: + stem = m.group(1) + m.group(2) + if _mgr1.match(stem): + w = stem + + # Step 5 + + m = _step5.match(w) + if m: + stem = m.group(1) + if _mgr1.match(stem) or (_meq1.match(stem) and not _c_v.match(stem)): + w = stem + + if w.endswith("ll") and _mgr1.match(w): + w = w[:-1] + + if first_is_y: + w = "y" + w[1:] + + return w + +if __name__ == '__main__': + print (stem("fundamentally")) + + + + + + + + + + + + diff --git a/src/refinement/stemmers/sstemmer.py b/src/refinement/stemmers/sstemmer.py new file mode 100644 index 0000000..ed2a4e7 --- /dev/null +++ b/src/refinement/stemmers/sstemmer.py @@ -0,0 +1,28 @@ +#!/bin/python +from stemmers.abstractstemmer import AbstractStemmer +import sys + + +class SRemovalStemmer(AbstractStemmer): + + def __init__(self, ): + super(SRemovalStemmer, self).__init__() + self.basename = 'sstemmer' + + def process(self, words): + return [self.stem_word(word) for word in words] + + def stem_word(self, word): + if len(word) > 5 and word[-3:] == 'ies' and word[-4] not in 'ae': + return word[:-3] + 'y' + elif len(word) > 4 and word[-2:] == 'es' and word[-3] not in 'aeo': + return word[:-1] + elif len(word) > 3 and word[-1] == 's' and word[-2] not in 'us': + return word[:-1] + else: + return word + + +if __name__ == '__main__': + stemmer = SRemovalStemmer() + stemmer.stem(sys.argv[1:]) diff --git a/src/refinement/stemmers/trunc4.py b/src/refinement/stemmers/trunc4.py new file mode 100644 index 0000000..969a171 --- /dev/null +++ b/src/refinement/stemmers/trunc4.py @@ -0,0 +1,24 @@ +#!/bin/python +from stemmers.abstractstemmer import AbstractStemmer +import sys + + +class Trunc4Stemmer(AbstractStemmer): + + def __init__(self, ): + super(Trunc4Stemmer, self).__init__() + self.basename = 'trunc4' + + def process(self, words): + return [self.stem_word(word) for word in words] + + def stem_word(self, word): + if len(word) > 4: + return word[:4] + else: + return word + + +if __name__ == '__main__': + stemmer = Trunc4Stemmer() + stemmer.stem(sys.argv[1:]) diff --git a/src/refinement/stemmers/trunc5.py b/src/refinement/stemmers/trunc5.py new file mode 100644 index 0000000..e1c0bd9 --- /dev/null +++ b/src/refinement/stemmers/trunc5.py @@ -0,0 +1,24 @@ +#!/bin/python +from stemmers.abstractstemmer import AbstractStemmer +import sys + + +class Trunc5Stemmer(AbstractStemmer): + + def __init__(self, ): + super(Trunc5Stemmer, self).__init__() + self.basename = 'trunc5' + + def process(self, words): + return [self.stem_word(word) for word in words] + + def stem_word(self, word): + if len(word) > 5: + return word[:5] + else: + return word + + +if __name__ == '__main__': + stemmer = Trunc5Stemmer() + stemmer.stem(sys.argv[1:]) diff --git a/src/refinement/utils.py b/src/refinement/utils.py new file mode 100644 index 0000000..9391ad9 --- /dev/null +++ b/src/refinement/utils.py @@ -0,0 +1,139 @@ +from nltk.corpus import stopwords +from nltk.tokenize import word_tokenize +from nltk.stem import PorterStemmer +import re +from contextlib import contextmanager +import os, sys, threading, io, tempfile + +stop_words = set(stopwords.words('english')) +l = ['.', ',', '!', '?', ';', 'a', 'an', '(', ')', "'", '_', '-', '<', '>', 'if', '/', '[', ']', ' '] +stop_words.update(l) + +ps = PorterStemmer() + +def get_tokenized_query(q): + word_tokens = word_tokenize(q) + q_ = [w.lower() for w in word_tokens if w.lower() not in stop_words] + return q_ + +def valid(word): + """ + Check if input is null or contains only spaces or numbers or special characters + """ + temp = re.sub(r'[^A-Za-z ]', ' ', word) + temp = re.sub(r"\s+", " ", temp) + temp = temp.strip() + if temp != "": + return True + return False + +def clean(str): + result = [0] * len(str) + for i in range(len(str)): + ch = str[i] + if ch.isalpha(): + result[i] = ch + else: + result[i] = ' ' + return ''.join(result) + +def insert_row(df, idx, row): + import pandas as pd + df1 = df[0:idx] + df2 = df[idx:] + df1.loc[idx] = row + df = pd.concat([df1, df2]) + df.index = [*range(df.shape[0])] + return df + +def get_raw_query(topicreader,Q_filename): + q_file=open(Q_filename,'r').readlines() + raw_queries={} + if topicreader=='Trec': + for line in q_file: + if '<title>' in line : + raw_queries[qid]=line.split('<title>')[1].rstrip().lower() + elif '<num>' in line: + qid=line.split(':')[1].rstrip() + + elif topicreader=='Webxml': + for line in q_file: + if '<query>' in line: + raw_queries[qid]=line.split('<query>')[1].rstrip().lower().split('</query>')[0] + elif '<topic number' in line: + qid=line.split('<topic number="')[1].split('"')[0] + elif topicreader=='TsvInt' or topicreader=='TsvString': + for line in q_file: + qid=line.split('\t')[0] + raw_queries[qid]=line.split('\t')[1].rstrip().lower() + return raw_queries + +def get_ranker_name(ranker): + return ranker.replace('-', '').replace(' ', '.') + +# Thanks to the following links, we can capture outputs from external c/java libs +# - https://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/ +# - https://stackoverflow.com/questions/5081657/how-do-i-prevent-a-c-shared-library-to-print-on-stdout-in-python/17954769#17954769 + +# libc = ctypes.CDLL(None) +# c_stdout = ctypes.c_void_p.in_dll(libc, 'stdout') +@contextmanager +def stdout_redirector_2_stream(stream): + # The original fd stdout points to. Usually 1 on POSIX systems. + original_stdout_fd = sys.stdout.fileno() + + def _redirect_stdout(to_fd): + """Redirect stdout to the given file descriptor.""" + # Flush the C-level buffer stdout + # libc.fflush(c_stdout) + # Flush and close sys.stdout - also closes the file descriptor (fd) + sys.stdout.close() + # Make original_stdout_fd point to the same file as to_fd + os.dup2(to_fd, original_stdout_fd) + # Create a new sys.stdout that points to the redirected fd + sys.stdout = io.TextIOWrapper(os.fdopen(original_stdout_fd, 'wb')) + + # Save a copy of the original stdout fd in saved_stdout_fd + saved_stdout_fd = os.dup(original_stdout_fd) + try: + # Create a temporary file and redirect stdout to it + tfile = tempfile.TemporaryFile(mode='w+b') + _redirect_stdout(tfile.fileno()) + # Yield to caller, then redirect stdout back to the saved fd + yield + _redirect_stdout(saved_stdout_fd) + # Copy contents of temporary file to the given stream + tfile.flush() + tfile.seek(0, io.SEEK_SET) + stream.write(tfile.read()) + finally: + tfile.close() + os.close(saved_stdout_fd) + +@contextmanager +def stdout_redirected_2_file(to=os.devnull): + ''' + import os + with stdout_redirected(to=filename): + print("from Python") + os.system("echo non-Python applications are also supported") + ''' + fd = sys.stdout.fileno() + + ##### assert that Python and C stdio write using the same file descriptor + ####assert libc.fileno(ctypes.c_void_p.in_dll(libc, "stdout")) == fd == 1 + + def _redirect_stdout(to): + sys.stdout.close() # + implicit flush() + os.dup2(to.fileno(), fd) # fd writes to 'to' file + sys.stdout = os.fdopen(fd, 'w') # Python writes to fd + + with os.fdopen(os.dup(fd), 'w') as old_stdout: + with open(to, 'w') as file: + _redirect_stdout(to=file) + try: + yield # allow code to be run with the redirected stdout + finally: + _redirect_stdout(to=old_stdout) # restore stdout. + # buffering and flags such as + # CLOEXEC may be different \ No newline at end of file From 04f52a5ba3e0aa1ab16a83d3950383ea47adc01a Mon Sep 17 00:00:00 2001 From: Delaram Rajaei <48606206+DelaramRajaei@users.noreply.github.com> Date: Thu, 2 Nov 2023 19:10:56 -0400 Subject: [PATCH 3/5] Query class - Add a class for query - Write functions for reading query and create an object of the query --- src/Query.py | 10 ---------- src/dal/ds.py | 23 +++++++++++++++++++++-- src/dal/query.py | 13 +++++++++++++ 3 files changed, 34 insertions(+), 12 deletions(-) delete mode 100644 src/Query.py create mode 100644 src/dal/query.py diff --git a/src/Query.py b/src/Query.py deleted file mode 100644 index 319ce1d..0000000 --- a/src/Query.py +++ /dev/null @@ -1,10 +0,0 @@ -class Query: - - def __init__(self, dataset_name, q, qid, time=None, user_id=None): - self.dataset_name = dataset_name - self.qid = qid - self.q = q - - # Features - self.user_id = user_id - self.time = time diff --git a/src/dal/ds.py b/src/dal/ds.py index 56737b2..c9ec187 100644 --- a/src/dal/ds.py +++ b/src/dal/ds.py @@ -1,13 +1,14 @@ import json, pandas as pd from tqdm import tqdm from os.path import isfile,join -import os +from query import Query from pyserini.search.lucene import LuceneSearcher from pyserini.search.faiss import FaissSearcher, TctColBertQueryEncoder class Dataset(object): + queries = [] searcher = None settings = None @@ -23,11 +24,29 @@ def __init__(self, settings): if not Dataset.searcher: raise ValueError(f'Lucene searcher cannot find/build index at {Dataset.settings["index"]}!') + @classmethod + def read_queries(cls, input): + queries = pd.read_csv(f'{input}/queries.train.tsv', sep='\t', index_col=False, names=['qid', 'query'], converters={'query': str.lower}, header=None) + qrels = pd.read_csv(f'{input}/qrels.train.tsv', sep='\t', index_col=False, names=['qid', 'did', 'rel'], header=None) + queries_qrels = pd.merge(queries, qrels, on='qid', how='inner', copy=False) + queries_qrels = queries_qrels.sort_values(by='qid') + cls.create_query_objects(queries_qrels) + + @classmethod + def create_query_objects(cls, queries_qrels): + qid = "" + for i, row in queries_qrels.iterrows(): + if qid != str(row['qid']): + if len(Dataset.queries) != 0: Dataset.queries.append(query) + query = Query(qid=row['qid'], q=row['query']) + qid = row['qid'] + query.add_document(row['did'], row['rel']) + @classmethod def _txt(cls, pid): # The``docid`` is overloaded: if it is of type ``str``, it is treated as an external collection ``docid``; # if it is of type ``int``, it is treated as an internal Lucene``docid``. # stupid!! - try:return json.loads(cls.searcher.doc(str(pid)).raw())['contents'].lower() + try: return json.loads(cls.searcher.doc(str(pid)).raw())['contents'].lower() except AttributeError: return '' # if Dataset.searcher.doc(str(pid)) is None except Exception as e: raise e diff --git a/src/dal/query.py b/src/dal/query.py new file mode 100644 index 0000000..030fcaa --- /dev/null +++ b/src/dal/query.py @@ -0,0 +1,13 @@ +class Query: + + def __init__(self, qid, q, args=None): + self.qid = qid + self.q = q + self.docs_rel = [] + + # Features + if args['id']: self.user_id = args['id'] + if args['time']: self.time = args['time'] + if args['location']: self.time = args['location'] + + def add_document(self, docid, rel): self.docs.append((docid, rel)) \ No newline at end of file From 1f13624b28caea3bccaa39bfa6195ff08922c415 Mon Sep 17 00:00:00 2001 From: Delaram Rajaei <48606206+DelaramRajaei@users.noreply.github.com> Date: Thu, 2 Nov 2023 19:14:05 -0400 Subject: [PATCH 4/5] update param and main - Separate the code settings from corpus names and files. - Add expanders --- src/main.py | 100 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 40 deletions(-) diff --git a/src/main.py b/src/main.py index 5f3852b..36b916d 100644 --- a/src/main.py +++ b/src/main.py @@ -6,9 +6,11 @@ from shutil import copyfile import param +from refinement import refiner_factory as rf +from refinement.refiners.abstractqrefiner import AbstractQRefiner -def run(data_list, domain_list, output, settings): +def run(data_list, domain_list, output, corpora, settings): # 'qrels.train.tsv' => ,["qid","did","pid","relevancy"] # 'queries.train.tsv' => ["qid","query"] @@ -19,53 +21,70 @@ def run(data_list, domain_list, output, settings): if domain == 'msmarco.passage': from dal.msmarco import MsMarcoPsg - ds = MsMarcoPsg(param.settings[domain]) - if domain == 'aol-ia': + ds = MsMarcoPsg(corpora[domain]) + elif domain == 'aol-ia': from dal.aol import Aol - ds = Aol(param.settings[domain], datapath, param.settings['ncore']) - if domain == 'yandex' in domain_list: raise ValueError('Yandex is yet to be added ...') + ds = Aol(corpora[domain], datapath, param.settings['ncore']) + elif domain == 'yandex' in domain_list: raise ValueError('Yandex is yet to be added ...') + # TODO: two or three different classes for datasets tsv, ... - index_item_str = '.'.join(settings[domain]['index_item']) - in_type, out_type = settings[domain]['pairing'][1], settings[domain]['pairing'][2] - tsv_path = {'train': f'{prep_output}/{ds.user_pairing}{in_type}.{out_type}.{index_item_str}.train.tsv', 'test': f'{prep_output}/{ds.user_pairing}{in_type}.{out_type}.{index_item_str}.test.tsv'} + ds.read_queries(datapath) - query_qrel_doc = None - if 'pair' in settings['cmd']: - print('Pairing queries and relevant passages for training set ...') - cat = True if 'docs' in {in_type, out_type} else False - query_qrel_doc = ds.pair(datapath, f'{prep_output}/{ds.user_pairing}queries.qrels.doc{"s" if cat else ""}.ctx.{index_item_str}.train.no_dups.tsv', cat=cat) - # print(f'Pairing queries and relevant passages for test set ...') - # TODO: query_qrel_doc = pair(datapath, f'{prep_output}/queries.qrels.doc.ctx.{index_item_str}.test.tsv') - # query_qrel_doc = ds.pair(datapath, f'{prep_output}/queries.qrels.doc{"s" if cat else ""}.ctx.{index_item_str}.test.tsv', cat=cat) - query_qrel_doc.to_csv(tsv_path['train'], sep='\t', encoding='utf-8', index=False, columns=[in_type, out_type], header=False) - query_qrel_doc.to_csv(tsv_path['test'], sep='\t', encoding='utf-8', index=False, columns=[in_type, out_type], header=False) + index_item_str = '.'.join(corpora[domain]['index_item']) + in_type, out_type = corpora[domain]['pairing'][1], corpora[domain]['pairing'][2] + tsv_path = {'train': f'{prep_output}/{ds.user_pairing}{in_type}.{out_type}.{index_item_str}.train.tsv', 'test': f'{prep_output}/{ds.user_pairing}{in_type}.{out_type}.{index_item_str}.test.tsv'} t5_model = settings['t5model'] # {"small", "base", "large", "3B", "11B"} cross {"local", "gc"} t5_output = f'../output/{os.path.split(datapath)[-1]}/{ds.user_pairing}t5.{t5_model}.{in_type}.{out_type}.{index_item_str}' if not os.path.isdir(t5_output): os.makedirs(t5_output) - copyfile('./param.py', f'{t5_output}/param.py') - if {'finetune', 'predict'} & set(settings['cmd']): - from mdl import mt5w - if 'finetune' in settings['cmd']: - print(f"Finetuning {t5_model} for {settings['iter']} iterations and storing the checkpoints at {t5_output} ...") - mt5w.finetune( - tsv_path=tsv_path, - pretrained_dir=f'./../output/t5-data/pretrained_models/{t5_model.split(".")[0]}', # "gs://t5-data/pretrained_models/{"small", "base", "large", "3B", "11B"} - steps=settings['iter'], - output=t5_output, task_name=f"{domain.replace('-', '')}_cf", # :DD Task name must match regex: ^[\w\d\.\:_]+$ - lseq=settings[domain]['lseq'], - nexamples=None, in_type=in_type, out_type=out_type, gcloud=False) - - if 'predict' in settings['cmd']: - print(f"Predicting {settings['nchanges']} query changes using {t5_model} and storing the results at {t5_output} ...") - mt5w.predict( - iter=settings['nchanges'], - split='test', - tsv_path=tsv_path, - output=t5_output, - lseq=settings[domain]['lseq'], - gcloud=False) + + query_qrel_doc = None + + # TODO: Adding t5 as a refiner with other refiners + # Query refinement - refining queries using the selected refiners + if settings['query_refinement']: + refiners = rf.get_nrf_refiner() + if rf: refiners += rf.get_rf_refiner(rankers=settings['ranker'], corpus=corpora[domain], output=t5_output, ext_corpus=corpora[corpora[domain]['extcorpus']]) + # TODO: each core for one expander to generate q* and set the output in a way to use in other parts of the pipeline + with mp.Pool(settings['ncore']) as p: + for refiner in refiners: + p.starmap(partial(refiner.generate_queue, dataset=ds, batch=settings['batch'])) + + # Consider t5 as a refiner + else: + if 'pair' in settings['cmd']: + print('Pairing queries and relevant passages for training set ...') + cat = True if 'docs' in {in_type, out_type} else False + query_qrel_doc = ds.pair(datapath, f'{prep_output}/{ds.user_pairing}queries.qrels.doc{"s" if cat else ""}.ctx.{index_item_str}.train.no_dups.tsv', cat=cat) + # print(f'Pairing queries and relevant passages for test set ...') + # TODO: query_qrel_doc = pair(datapath, f'{prep_output}/queries.qrels.doc.ctx.{index_item_str}.test.tsv') + # query_qrel_doc = ds.pair(datapath, f'{prep_output}/queries.qrels.doc{"s" if cat else ""}.ctx.{index_item_str}.test.tsv', cat=cat) + query_qrel_doc.to_csv(tsv_path['train'], sep='\t', encoding='utf-8', index=False, columns=[in_type, out_type], header=False) + query_qrel_doc.to_csv(tsv_path['test'], sep='\t', encoding='utf-8', index=False, columns=[in_type, out_type], header=False) + + if {'finetune', 'predict'} & set(settings['cmd']): + from mdl import mt5w + if 'finetune' in settings['cmd']: + print(f"Finetuning {t5_model} for {settings['iter']} iterations and storing the checkpoints at {t5_output} ...") + mt5w.finetune( + tsv_path=tsv_path, + pretrained_dir=f'./../output/t5-data/pretrained_models/{t5_model.split(".")[0]}', # "gs://t5-data/pretrained_models/{"small", "base", "large", "3B", "11B"} + steps=settings['iter'], + output=t5_output, task_name=f"{domain.replace('-', '')}_cf", # :DD Task name must match regex: ^[\w\d\.\:_]+$ + lseq=corpora[domain]['lseq'], + nexamples=None, in_type=in_type, out_type=out_type, gcloud=False) + + if 'predict' in settings['cmd']: + print(f"Predicting {settings['nchanges']} query changes using {t5_model} and storing the results at {t5_output} ...") + mt5w.predict( + iter=settings['nchanges'], + split='test', + tsv_path=tsv_path, + output=t5_output, + lseq=corpora[domain]['lseq'], + gcloud=False) + if 'search' in settings['cmd']: # 'bm25 ranker' print(f"Searching documents for query changes using {settings['ranker']} ...") # seems for some queries there is no qrels, so they are missed for t5 prediction. @@ -281,6 +300,7 @@ def addargs(parser): run(data_list=args.data_list, domain_list=args.domain_list, output=args.output, + corpora=param.corpora, settings=param.settings) # after finetuning and predict, we can benchmark on rankers and metrics From 56fb08418587d71c856f32341446cedcea84c9f0 Mon Sep 17 00:00:00 2001 From: Delaram Rajaei <48606206+DelaramRajaei@users.noreply.github.com> Date: Fri, 17 Nov 2023 16:43:20 -0500 Subject: [PATCH 5/5] Updating RePair - Add refiners - Add Query Class --- .../refiner_param.py | 167 ++++++++++++ src/dal/aol.py | 27 +- src/dal/ds.py | 107 +++++--- src/dal/msmarco.py | 19 +- src/dal/query.py | 45 +++- src/main.py | 195 ++++++++------ src/mdl/mt5w.py | 4 +- src/param.py | 44 ++-- src/refinement/refiner_factory.py | 78 +++--- src/refinement/{param.py => refiner_param.py} | 4 + src/refinement/refiners/abstractqrefiner.py | 247 ++++-------------- src/refinement/refiners/backtranslation.py | 52 ++-- src/refinement/refiners/stem.py | 6 +- src/refinement/stemmers/abstractstemmer.py | 2 +- src/refinement/utils.py | 18 +- 15 files changed, 584 insertions(+), 431 deletions(-) create mode 100644 output/toy.msmarco.passage/t5.small.local.docs.query.passage/refiner_param.py rename src/refinement/{param.py => refiner_param.py} (95%) diff --git a/output/toy.msmarco.passage/t5.small.local.docs.query.passage/refiner_param.py b/output/toy.msmarco.passage/t5.small.local.docs.query.passage/refiner_param.py new file mode 100644 index 0000000..0458df5 --- /dev/null +++ b/output/toy.msmarco.passage/t5.small.local.docs.query.passage/refiner_param.py @@ -0,0 +1,167 @@ +import random, os, numpy as np, platform +import torch + +random.seed(0) +torch.manual_seed(0) +torch.cuda.manual_seed_all(0) +np.random.seed(0) +extension = '.exe' if platform.system() == 'Windows' else "" +os.environ['CUDA_VISIBLE_DEVICES'] = '-1' + +settings = { + 'query_refinement': True, + 'cmd': ['search', 'eval','agg', 'box'], # steps of pipeline, ['pair', 'finetune', 'predict', 'search', 'eval','agg', 'box','dense_retrieve', 'stats] + 'ncore': 1, + 't5model': 'small.local', # 'base.gc' on google cloud tpu, 'small.local' on local machine + 'iter': 5, # number of finetuning iteration for t5 + 'nchanges': 5, # number of changes to a query + 'ranker': 'bm25', # 'qld', 'bm25', 'tct_colbert' + 'batch': None, # search per batch of queries for IR search using pyserini, if None, search per query + 'topk': 100, # number of retrieved documents for a query + 'metric': 'map', # any valid trec_eval.9.0.4 metric like map, ndcg, recip_rank, ... + 'large_ds': False, + 'treclib': f'"./trec_eval.9.0.4/trec_eval{extension}"', # in non-windows, remove .exe, also for pytrec_eval, 'pytrec' + 'box': {'gold': 'refined_q_metric >= original_q_metric and refined_q_metric > 0', + 'platinum': 'refined_q_metric > original_q_metric', + 'diamond': 'refined_q_metric > original_q_metric and refined_q_metric == 1'} +} + +corpora = { + 'msmarco.passage': { + 'index_item': ['passage'], + 'index': '../data/raw/msmarco.passage/lucene-index.msmarco-v1-passage.20220131.9ea315/', + 'dense_encoder': 'castorini/tct_colbert-msmarco', + 'dense_index': 'msmarco-passage-tct_colbert-hnsw', + 'extcorpus': 'orcas', + 'pairing': [None, 'docs', 'query'], # [context={msmarco does not have userinfo}, input={query, doc, doc(s)}, output={query, doc, doc(s)}], s means concat of docs + 'lseq': {"inputs": 32, "targets": 256}, # query length and doc length for t5 model, + }, + 'aol-ia': { + 'index_item': ['title'], # ['url'], ['title', 'url'], ['title', 'url', 'text'] + 'index': '../data/raw/aol-ia/lucene-index/title/', # change based on index_item + 'dense_index': '../data/raw/aol-ia/dense-index/tct_colbert.title/', # change based on index_item + 'dense_encoder':'../data/raw/aol-ia/dense-encoder/tct_colbert.title/', # change based on index_item + 'pairing': [None, 'docs', 'query'], # [context={2 scenarios, one with userID and one without userID). input={'userid','query','doc(s)'} output={'query','doc(s)'} + 'extcorpus': 'msmarco.passage', + 'lseq': {"inputs": 32, "targets": 256}, # query length and doc length for t5 model, + 'filter': {'minql': 1, 'mindocl': 10} # [min query length, min doc length], after merge queries with relevant 'index_item', if |query| <= minql drop the row, if |'index_item'| < mindocl, drop row + }, + 'robust04': { + 'index': '../data/raw/robust04/lucene-index.robust04.pos+docvectors+rawdocs', + 'dense_index': '../data/raw/robust04/faiss_index_robust04', + 'encoded': '../data/raw/robust04/encoded_robust04', + 'size': 528155, + 'topics': '../data/raw/robust04/topics.robust04.txt', + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 2.25, # OnFields + 'w_a': 1, # OnFields + 'tokens': 148000000, + 'qrels': '../data/raw/robust04/qrels.robust04.txt', + 'extcorpus': 'gov2', # AdaptOnFields + 'pairing': [None, None, None], + 'index_item': [], + }, + 'gov2': { + 'index': '../data/raw/gov2/lucene-index.gov2.pos+docvectors+rawdocs', + 'size': 25000000, + 'topics': '../data/raw/gov2/topics.terabyte0{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'trec': ['4.701-750', '5.751-800', '6.801-850'], + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 4, # OnFields + 'w_a': 0.25, # OnFields + 'tokens': 17000000000, + 'qrels': '../data/raw/gov2/qrels.terabyte0{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'extcorpus': 'robust04', # AdaptOnFields + 'pairing': [None, None, None], + 'index_item': [], + }, + 'clueweb09b': { + 'index': '../data/raw/clueweb09b/lucene-index.cw09b.pos+docvectors+rawdocs', + 'size': 50000000, + 'topics': '../data/raw/clueweb09b/topics.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'trec': ['1-50', '51-100', '101-150', '151-200'], + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 1, # OnFields + 'w_a': 0, # OnFields + 'tokens': 31000000000, + 'qrels': '../data/raw/clueweb09b/qrels.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'extcorpus': 'gov2', # AdaptOnFields + 'pairing': [None, None, None], + 'index_item': [], + }, + 'clueweb12b13': { + 'index': '../data/raw/clueweb12b13/lucene-index.cw12b13.pos+docvectors+rawdocs', + 'size': 50000000, + 'topics': '../data/raw/clueweb12b13/topics.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'trec': ['201-250', '251-300'], + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 4, # OnFields + 'w_a': 0, # OnFields + 'tokens': 31000000000, + 'qrels': '../data/raw/clueweb12b13/qrels.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'extcorpus': 'gov2', # AdaptOnFields + 'pairing': [None, None, None], + 'index_item': [], + }, + 'antique': { + 'index': '../data/raw/antique/lucene-index-antique', + 'size': 403000, + 'topics': '../data/raw/antique/topics.antique.txt', + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 2.25, # OnFields # to be tuned + 'w_a': 1, # OnFields # to be tuned + 'tokens': 16000000, + 'qrels': '../data/raw/antique/qrels.antique.txt', + 'extcorpus': 'gov2', # AdaptOnFields + 'pairing': [None, None, None], + 'index_item': [], + }, + 'trec09mq': { + 'index': '/data/raw/clueweb09b/lucene-index.cw09b.pos+docvectors+rawdocs', + 'size': 50000000, + # 'topics': '../ds/trec2009mq/prep/09.mq.topics.20001-60000.prep.tsv', + 'topics': '../data/raw/trec09mq/09.mq.topics.20001-60000.prep', + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 2.25, # OnFields # to be tuned + 'w_a': 1, # OnFields # to be tuned + 'tokens': 16000000, + 'qrels': '../data/raw/trec09mq/prels.20001-60000.prep', + 'extcorpus': 'gov2', # AdaptOnFields + 'pairing': [None, None, None], + 'index_item': [], + }, + 'dbpedia': { + 'index': '../data/raw/dbpedia/lucene-index-dbpedia-collection', + 'size': 4632359, + 'topics': '../data/raw/dbpedia/topics.dbpedia.txt', + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 1, # OnFields # to be tuned + 'w_a': 1, # OnFields # to be tuned + 'tokens': 200000000, + 'qrels': '../data/raw/dbpedia/qrels.dbpedia.txt', + 'extcorpus': 'gov2', # AdaptOnFields + 'pairing': [None, None, None], + 'index_item': [], + }, + 'orcas': { + 'index': '../data/raw/orcas/lucene-index.msmarco-v1-doc.20220131.9ea315', + 'size': 50000000, + # 'topics': '../data/raw/trec2009mq/prep/09.mq.topics.20001-60000.prep.tsv', + 'topics': '../data/raw/orcas/preprocess/orcas-I-2M_topics.prep', + 'prels': '', # this will be generated after a retrieval {bm25, qld} + 'w_t': 2.25, # OnFields # to be tuned + 'w_a': 1, # OnFields # to be tuned + 'tokens': 16000000, + 'qrels': '../data/raw/orcas/preprocess/orcas-doctrain-qrels.prep', + 'extcorpus': 'gov2', # AdaptOnFields + 'pairing': [None, None, None], + 'index_item': [], + }, +} + +# Only for sparse indexing +anserini = { + 'path': '../anserini/', + 'trec_eval': '../anserini/eval/trec_eval.9.0.4/trec_eval' +} + diff --git a/src/dal/aol.py b/src/dal/aol.py index 0d9f1e7..9c5d9aa 100644 --- a/src/dal/aol.py +++ b/src/dal/aol.py @@ -3,14 +3,15 @@ from shutil import copyfile from ftfy import fix_text from pyserini.search.lucene import LuceneSearcher -from dal.ds import Dataset +from ds import Dataset +from query import Query tqdm.pandas() class Aol(Dataset): - def __init__(self, settings, homedir, ncore): - try: super(Aol, self).__init__(settings=settings) + def __init__(self, settings, domain, homedir, ncore): + try: super(Aol, self).__init__(settings=settings, domain=domain) except: self._build_index(homedir, Dataset.settings['index_item'], Dataset.settings['index'], ncore) @classmethod @@ -22,7 +23,7 @@ def _build_index(cls, homedir, index_item, indexdir, ncore): index_item_str = '.'.join(index_item) if not os.path.isdir(f'{indexdir}/{cls.user_pairing}{index_item_str}'): os.makedirs(f'{indexdir}/{cls.user_pairing}{index_item_str}') import ir_datasets - from cmn.lucenex import lucenex + from src.cmn.lucenex import lucenex print(f"Setting up aol corpus using ir-datasets at {homedir}...") aolia = ir_datasets.load("aol-ia") @@ -48,6 +49,17 @@ def _build_index(cls, homedir, index_item, indexdir, ncore): # for d in os.listdir(homedir): # if not (d.find('aol-ia') > -1) and os.path.isdir(f'./../data/raw/{d}'): shutil.rmtree(f'./../data/raw/{d}') + def read_queries(cls, input, domain): + queries = pd.read_csv(f'{input}/queries.train.tsv', encoding='UTF-8', sep='\t', index_col=False, names=['qid', 'query'], converters={'query': str.lower}, header=None) + # the column order in the file is [qid, uid, did, uid]!!!! STUPID!! + qrels = pd.read_csv(f'{input}/qrels.train.tsv', encoding='UTF-8', sep='\t', index_col=False, names=['qid', 'uid', 'did', 'rel'], header=None) + qrels.to_csv(f'{input}/qrels.train.tsv_', index=False, sep='\t', header=False) + # docid is a hash of the URL. qid is the a hash of the *noramlised query* ==> two uid may have same qid then, same docid. + qrels.drop_duplicates(subset=['qid', 'did', 'uid'], inplace=True) + queries_qrels = pd.merge(queries, qrels, on='qid', how='inner', copy=False) + queries_qrels = queries_qrels.sort_values(by='qid') + cls.create_query_objects(queries_qrels, ['qid', 'uid', 'did', 'rel'], domain) + @classmethod def create_jsonl(cls, aolia, index_item, output): """ @@ -69,19 +81,21 @@ def create_jsonl(cls, aolia, index_item, output): output_jsonl_file.close() @classmethod - def pair(cls, input, output, cat=True): + def pair(cls, queries, output, cat=True): + # TODO: change the code in a way to use read_queries queries = pd.read_csv(f'{input}/queries.train.tsv', encoding='UTF-8', sep='\t', index_col=False, names=['qid', 'query'], converters={'query': str.lower}, header=None) # the column order in the file is [qid, uid, did, uid]!!!! STUPID!! qrels = pd.read_csv(f'{input}/qrels.train.tsv', encoding='UTF-8', sep='\t', index_col=False, names=['qid', 'uid', 'did', 'rel'], header=None) # docid is a hash of the URL. qid is the a hash of the *noramlised query* ==> two uid may have same qid then, same docid. qrels.drop_duplicates(subset=['qid', 'did', 'uid'], inplace=True) queries_qrels = pd.merge(queries, qrels, on='qid', how='inner', copy=False) + doccol = 'docs' if cat else 'doc' del queries # in the event of user oriented pairing, we simply concat qid and uid if cls.user_pairing: queries_qrels['qid'] = queries_qrels['qid'].astype(str) + "_" + queries_qrels['uid'].astype(str) queries_qrels = queries_qrels.astype('category') - queries_qrels[doccol] = queries_qrels['did'].progress_apply(cls._txt) + queries_qrels[doccol] = queries_qrels['did'].apply(cls._txt) # queries_qrels.drop_duplicates(subset=['qid', 'did','pid'], inplace=True) # two users with same click for same query if not cls.user_pairing: queries_qrels['uid'] = -1 @@ -111,3 +125,4 @@ def pair(cls, input, output, cat=True): qrels_splits.to_csv(f'../output/aol-ia/{cls.user_pairing}t5.base.gc.docs.query.{index_item_str}/qrels/qrels.splits.{_}.tsv_', sep='\t', encoding='utf-8', index=False, header=False, columns=['qid', 'uid', 'did', 'rel']) return queries_qrels + pass diff --git a/src/dal/ds.py b/src/dal/ds.py index c9ec187..6839cea 100644 --- a/src/dal/ds.py +++ b/src/dal/ds.py @@ -1,8 +1,7 @@ import json, pandas as pd from tqdm import tqdm from os.path import isfile,join -from query import Query - +from src.dal.query import Query from pyserini.search.lucene import LuceneSearcher from pyserini.search.faiss import FaissSearcher, TctColBertQueryEncoder @@ -12,7 +11,7 @@ class Dataset(object): searcher = None settings = None - def __init__(self, settings): + def __init__(self, settings, domain): Dataset.settings = settings # https://github.com/castorini/pyserini/blob/master/docs/prebuilt-indexes.md # searcher = LuceneSearcher.from_prebuilt_index('msmarco-v1-passage') @@ -21,26 +20,47 @@ def __init__(self, settings): Dataset.user_pairing = "user/" if "user" in settings["pairing"] else "" index_item_str = '.'.join(settings["index_item"]) if self.__class__.__name__ != 'MsMarcoPsg' else "" Dataset.searcher = LuceneSearcher(f'{Dataset.settings["index"]}{self.user_pairing}{index_item_str}') + Dataset.domain = domain if not Dataset.searcher: raise ValueError(f'Lucene searcher cannot find/build index at {Dataset.settings["index"]}!') @classmethod - def read_queries(cls, input): - queries = pd.read_csv(f'{input}/queries.train.tsv', sep='\t', index_col=False, names=['qid', 'query'], converters={'query': str.lower}, header=None) - qrels = pd.read_csv(f'{input}/qrels.train.tsv', sep='\t', index_col=False, names=['qid', 'did', 'rel'], header=None) - queries_qrels = pd.merge(queries, qrels, on='qid', how='inner', copy=False) + def read_queries(cls, input, domain): + is_tag_file = False + q, qid = '', '' + queries = pd.DataFrame(columns=['qid']) + with open(f'{input}/topics.{cls.domain}.txt', 'r', encoding='UTF-8') as Qfile: + for line in Qfile: + if '<top>' in line and not is_tag_file: is_tag_file = True + if '<num>' in line: + qid = int(line[line.index(':') + 1:]) + elif line[:7] == '<title>': + q = line[8:].strip() + if not q: q = next(Qfile).strip() + elif '<topic' in line: + s = line.index('\"') + 1 + e = line.index('\"', s + 1) + qid = int(line[s:e]) + elif line[2:9] == '<query>': + q = line[9:-9] + elif len(line.split('\t')) >= 2 and not is_tag_file: + qid = line.split('\t')[0].rstrip() + q = line.split('\t')[1].rstrip() + if q != '' and qid != '': + new_line = {'qid': qid, 'query': q} + queries = pd.concat([queries, pd.DataFrame([new_line])], ignore_index=True) + q, qid = '', '' + infile = f'{input}/qrels.{cls.domain}.txt' + with open(infile, 'r') as file: separator = '\t' if '\t' in file.readline() else '\s' + qrels = pd.read_csv(infile, sep=separator, index_col=False, names=['qid', '0', 'did', 'relevancy'], header=None, engine='python') + qrels.drop_duplicates(subset=['qid', 'did'], inplace=True) # qrels have duplicates!! + qrels.to_csv(f'{input}/qrels.train.tsv_', index=False, sep='\t', header=False) + queries_qrels = pd.merge(queries, qrels, on='qid', how='left', copy=False) queries_qrels = queries_qrels.sort_values(by='qid') - cls.create_query_objects(queries_qrels) + cls.create_query_objects(queries_qrels, ['qid', 'did', 'relevancy'], domain) @classmethod - def create_query_objects(cls, queries_qrels): - qid = "" - for i, row in queries_qrels.iterrows(): - if qid != str(row['qid']): - if len(Dataset.queries) != 0: Dataset.queries.append(query) - query = Query(qid=row['qid'], q=row['query']) - qid = row['qid'] - query.add_document(row['did'], row['rel']) + def pair(cls, input, output, index_item, cat=True): pass @classmethod def _txt(cls, pid): @@ -51,7 +71,16 @@ def _txt(cls, pid): except Exception as e: raise e @classmethod - def pair(cls, input, output, index_item, cat=True): pass + def create_query_objects(cls, queries_qrels, qrel_col, domain): + qid = "" + query = None + for i, row in queries_qrels.iterrows(): + if qid != row['qid']: + if query: cls.queries.append(query) + qid = row['qid'] + query = Query(domain=domain, qid=qid, q=row['query']) + query.docs.update({col: str(row[col]) for col in qrel_col}) + if query: cls.queries.append(query) # gpu-based t5 generate the predictions in b'' format!!! @classmethod @@ -61,26 +90,24 @@ def clean(cls, tf_txt): return tf_txt.replace('b\'', '').replace('\'', '').replace('b\"', '').replace('\"', '') @classmethod - def search(cls, in_query, out_docids, qids, ranker='bm25', topk=100, batch=None, ncores=1, index=None): - print(f'Searching docs for {in_query} ...') + def search(cls, in_query:str, out_docids:str, qids:list, ranker='bm25', topk=100, batch=None, ncores=1, index=None): + ansi_reset = "\033[0m" + print(f'Searching docs for {hex_to_ansi("#3498DB")}{in_query} {ansi_reset}and writing results in {hex_to_ansi("#F1C40F")}{out_docids}{ansi_reset} ...') # https://github.com/google-research/text-to-text-transfer-transformer/issues/322 # with open(in_query, 'r', encoding='utf-8') as f: [to_docids(l) for l in f] - queries = pd.read_csv(in_query, names=['query'], sep='\r\r', skip_blank_lines=False, engine='python') # a query might be empty str (output of t5)!! + if (in_query.split('/')[-1]).split('.')[0] == 'refiner': queries = pd.read_csv(in_query, names=['query'], sep='\t', usecols=[1], skip_blank_lines=False, engine='python') + else: queries = pd.read_csv(in_query, names=['query'], sep='\r\r', skip_blank_lines=False, engine='python') # a query might be empty str (output of t5)!! assert len(queries) == len(qids) cls.search_df(queries, out_docids, qids, ranker=ranker, topk=topk, batch=batch, ncores=ncores, index=index) @classmethod def search_df(cls, queries, out_docids, qids, ranker='bm25', topk=100, batch=None, ncores=1, index=None, encoder=None): - if not cls.searcher: if ranker == 'tct_colbert': cls.encoder = TctColBertQueryEncoder(encoder) - if 'msmarco.passage' in out_docids.split('/'): - cls.searcher = FaissSearcher.from_prebuilt_index(index, cls.encoder) - else: - cls.searcher = FaissSearcher(index, cls.encoder) - else: - cls.searcher = LuceneSearcher(index) + if 'msmarco.passage' in out_docids.split('/'): cls.searcher = FaissSearcher.from_prebuilt_index(index, cls.encoder) + else: cls.searcher = FaissSearcher(index, cls.encoder) + else: cls.searcher = LuceneSearcher(index) if ranker == 'bm25': cls.searcher.set_bm25(0.82, 0.68) if ranker == 'qld': cls.searcher.set_qld() @@ -106,7 +133,8 @@ def _docids(row): print(f'unique docids fetched less than {topk}') else: hits = cls.searcher.search(row.query, k=topk, remove_dups=True) - for i, h in enumerate(hits): o.write(f'{qids[row.name]}\tQ0\t{h.docid:7}\t{i + 1:2}\t{h.score:.5f}\tPyserini\n') + for i, h in enumerate(hits): o.write( + f'{qids[row.name]}\tQ0\t{h.docid:7}\t{i + 1:2}\t{h.score:.5f}\tPyserini\n') queries.apply(_docids, axis=1) @@ -116,7 +144,8 @@ def aggregate(cls, original, changes, output, is_large_ds=False): metric = '.'.join(changes[0][1].split('.')[3:]) # e.g., pred.0-1004000.bm25.success.10 => success.10 for change, metric_value in changes: - pred = pd.read_csv(join(output, change), sep='\r\r', skip_blank_lines=False, names=[change], converters={change: cls.clean}, engine='python', index_col=False, header=None) + if 'refiner.' in change: pred = pd.read_csv(join(output, change), sep='\t', usecols=[1], skip_blank_lines=False, names=[change], converters={change: cls.clean}, engine='python', index_col=False, header=None) + else: pred = pd.read_csv(join(output, change), sep='\r\r', skip_blank_lines=False, names=[change], converters={change: cls.clean}, engine='python', index_col=False, header=None) assert len(original['qid']) == len(pred[change]) if is_large_ds: pred_metric_values = pd.read_csv(join(output, metric_value), sep='\t', usecols=[1, 2], names=['qid', f'{change}.{ranker}.{metric}'], index_col=False, dtype={'qid': str}) @@ -135,14 +164,14 @@ def aggregate(cls, original, changes, output, is_large_ds=False): agg_gold.write(f'qid\torder\tquery\t{ranker}.{metric}\n') agg_all.write(f'qid\torder\tquery\t{ranker}.{metric}\n') for index, row in tqdm(original.iterrows(), total=original.shape[0]): - agg_gold.write(f'{row.qid}\t-1\t{row.query}\t{row[f"original.{ranker}.{metric}"]}\n') - agg_all.write(f'{row.qid}\t-1\t{row.query}\t{row[f"original.{ranker}.{metric}"]}\n') + agg_gold.write(f'{row.qid}\t-1\t{row.query}\t{row[f"original.queries.{ranker}.{metric}"]}\n') + agg_all.write(f'{row.qid}\t-1\t{row.query}\t{row[f"original.queries.{ranker}.{metric}"]}\n') all = list() for change, metric_value in changes: all.append((row[change], row[f'{change}.{ranker}.{metric}'], change)) all = sorted(all, key=lambda x: x[1], reverse=True) for i, (query, metric_value, change) in enumerate(all): agg_all.write(f'{row.qid}\t{change}\t{query}\t{metric_value}\n') - if metric_value > 0 and metric_value >= row[f'original.{ranker}.{metric}']: agg_gold.write(f'{row.qid}\t{change}\t{query}\t{metric_value}\n') + if metric_value > 0 and metric_value >= row[f'original.queries.{ranker}.{metric}']: agg_gold.write(f'{row.qid}\t{change}\t{query}\t{metric_value}\n') @classmethod def box(cls, input, qrels, output, checks): @@ -169,6 +198,14 @@ def box(cls, input, qrels, output, checks): # df.drop_duplicates(subset=['qid'], inplace=True) del ds df.to_csv(f'{output}/{c}.tsv', sep='\t', encoding='utf-8', index=False, header=False) - print(f'{c} has {df.shape[0]} queries') - qrels = df.merge(qrels, on='qid', how='inner') - qrels.to_csv(f'{output}/{c}.qrels.tsv', sep='\t', encoding='utf-8', index=False, header=False, columns=['qid', 'did', 'pid', 'rel']) + print(f'{c} has {df.shape[0]} queries\n') + df = df.merge(qrels, on='qid', how='inner') + df.to_csv(f'{output}/{c}.qrels.tsv', sep='\t', encoding='utf-8', index=False, header=False, columns=list(qrels.columns)) + + +def hex_to_ansi(hex_color_code): + hex_color_code = hex_color_code.lstrip('#') + red = int(hex_color_code[0:2], 16) + green = int(hex_color_code[2:4], 16) + blue = int(hex_color_code[4:6], 16) + return f'\033[38;2;{red};{green};{blue}m' diff --git a/src/dal/msmarco.py b/src/dal/msmarco.py index 8266703..d33610a 100644 --- a/src/dal/msmarco.py +++ b/src/dal/msmarco.py @@ -1,22 +1,31 @@ -import os -from os.path import isfile,join import pandas as pd from tqdm import tqdm -from dal.ds import Dataset +from src.dal.ds import Dataset tqdm.pandas() class MsMarcoPsg(Dataset): - def __init__(self, settings): super(MsMarcoPsg, self).__init__(settings=settings) + def __init__(self, settings, domain): super(MsMarcoPsg, self).__init__(settings=settings, domain=domain) @classmethod - def pair(cls, input, output, cat=True): + def read_queries(cls, input, domain): queries = pd.read_csv(f'{input}/queries.train.tsv', sep='\t', index_col=False, names=['qid', 'query'], converters={'query': str.lower}, header=None) qrels = pd.read_csv(f'{input}/qrels.train.tsv', sep='\t', index_col=False, names=['qid', 'did', 'pid', 'relevancy'], header=None) qrels.drop_duplicates(subset=['qid', 'pid'], inplace=True) # qrels have duplicates!! qrels.to_csv(f'{input}/qrels.train.tsv_', index=False, sep='\t', header=False) # trec_eval.9.0.4 does not accept duplicate rows!! queries_qrels = pd.merge(queries, qrels, on='qid', how='inner', copy=False) + queries_qrels = queries_qrels.sort_values(by='qid') + cls.create_query_objects(queries_qrels, ['qid', 'did', 'pid', 'relevancy'], domain) + + @classmethod + def pair(cls, output, cat=True): + # TODO: change the code in a way to use read_queries + queries = pd.read_csv(f'{input}/queries.train.tsv', sep='\t', index_col=False, names=['qid', 'query'],converters={'query': str.lower}, header=None) + qrels = pd.read_csv(f'{input}/qrels.train.tsv', sep='\t', index_col=False, names=['qid', 'did', 'pid', 'relevancy'], header=None) + qrels.drop_duplicates(subset=['qid', 'pid'], inplace=True) # qrels have duplicates!! + qrels.to_csv(f'{input}/qrels.train.tsv_', index=False, sep='\t', header=False) # trec_eval.9.0.4 does not accept duplicate rows!! + queries_qrels = pd.merge(queries, qrels, on='qid', how='inner', copy=False) doccol = 'docs' if cat else 'doc' queries_qrels[doccol] = queries_qrels['pid'].apply(cls._txt) # 100%|██████████| 532761/532761 [00:32<00:00, 16448.77it/s] queries_qrels['ctx'] = '' diff --git a/src/dal/query.py b/src/dal/query.py index 030fcaa..b5f8533 100644 --- a/src/dal/query.py +++ b/src/dal/query.py @@ -1,13 +1,44 @@ +from tqdm import tqdm +import pandas as pd + class Query: + """ + Query Class + + Represents a query with associated attributes and features. + + Attributes: + qid (int): The query identifier. + q (str): The query text. + docs (list): A list of tuples containing document information. + Each tuple includes docid and relevancy, and additional information + related to documents can be added in between. + q_ (list): A list of tuples containing semantic similarity refined query, score and refiner's name. + user_id (str, optional): The user identifier associated with the query. + time (str, optional): The time of the query. + location (str, optional): The location associated with the query. - def __init__(self, qid, q, args=None): + Args: + qid (str): The query identifier. + q (str): The query text. + args (dict, optional): Additional features and attributes associated with the query, + including 'id' for user identifier, 'time' for time information, and 'location' + for location information. + + Example Usage: + # Creating a Query object + query = Query(qid='Q123', q='Sample query text', args={'id': 'U456', 'time': '2023-10-31'}) + + """ + def __init__(self, domain, qid, q, args=None): + self.domain = domain self.qid = qid self.q = q - self.docs_rel = [] + self.docs = dict() + self.q_ = dict() # Features - if args['id']: self.user_id = args['id'] - if args['time']: self.time = args['time'] - if args['location']: self.time = args['location'] - - def add_document(self, docid, rel): self.docs.append((docid, rel)) \ No newline at end of file + if args: + if args['id']: self.user_id = args['id'] + if args['time']: self.time = args['time'] + if args['location']: self.time = args['location'] diff --git a/src/main.py b/src/main.py index 36b916d..62205e1 100644 --- a/src/main.py +++ b/src/main.py @@ -2,11 +2,11 @@ from functools import partial from multiprocessing import freeze_support from os import listdir -from os.path import isfile, join +from os.path import isfile, join, exists from shutil import copyfile import param -from refinement import refiner_factory as rf +from src.refinement import refiner_factory as rf from refinement.refiners.abstractqrefiner import AbstractQRefiner @@ -21,119 +21,136 @@ def run(data_list, domain_list, output, corpora, settings): if domain == 'msmarco.passage': from dal.msmarco import MsMarcoPsg - ds = MsMarcoPsg(corpora[domain]) + ds = MsMarcoPsg(corpora[domain], domain) elif domain == 'aol-ia': from dal.aol import Aol - ds = Aol(corpora[domain], datapath, param.settings['ncore']) + ds = Aol(corpora[domain], domain, datapath, param.settings['ncore']) elif domain == 'yandex' in domain_list: raise ValueError('Yandex is yet to be added ...') - # TODO: two or three different classes for datasets tsv, ... + else: + from dal.ds import Dataset + ds = Dataset(corpora[domain], domain) - ds.read_queries(datapath) + ds.read_queries(datapath, domain) index_item_str = '.'.join(corpora[domain]['index_item']) in_type, out_type = corpora[domain]['pairing'][1], corpora[domain]['pairing'][2] tsv_path = {'train': f'{prep_output}/{ds.user_pairing}{in_type}.{out_type}.{index_item_str}.train.tsv', 'test': f'{prep_output}/{ds.user_pairing}{in_type}.{out_type}.{index_item_str}.test.tsv'} + #TODO: change files naming t5_model = settings['t5model'] # {"small", "base", "large", "3B", "11B"} cross {"local", "gc"} t5_output = f'../output/{os.path.split(datapath)[-1]}/{ds.user_pairing}t5.{t5_model}.{in_type}.{out_type}.{index_item_str}' if not os.path.isdir(t5_output): os.makedirs(t5_output) - copyfile('./param.py', f'{t5_output}/param.py') + copyfile('./param.py', f'{t5_output}/refiner_param.py') query_qrel_doc = None - # TODO: Adding t5 as a refiner with other refiners # Query refinement - refining queries using the selected refiners if settings['query_refinement']: refiners = rf.get_nrf_refiner() if rf: refiners += rf.get_rf_refiner(rankers=settings['ranker'], corpus=corpora[domain], output=t5_output, ext_corpus=corpora[corpora[domain]['extcorpus']]) - # TODO: each core for one expander to generate q* and set the output in a way to use in other parts of the pipeline with mp.Pool(settings['ncore']) as p: for refiner in refiners: - p.starmap(partial(refiner.generate_queue, dataset=ds, batch=settings['batch'])) + if refiner.get_model_name() == 'original.queries': refiner_outfile = f'{t5_output}/{refiner.get_model_name()}' + else: refiner_outfile = f'{t5_output}/refiner.{refiner.get_model_name()}' + if not exists(refiner_outfile): + print(f'Writing results from {refiner.get_model_name()} queries in {refiner_outfile}') + ds.queries = p.map(partial(refiner.preprocess_query), ds.queries) + refiner.write_queries(queries=ds.queries, outfile=refiner_outfile) + else: print(f'Results from {refiner.get_model_name()} queries in {refiner_outfile}') # Consider t5 as a refiner - else: - if 'pair' in settings['cmd']: - print('Pairing queries and relevant passages for training set ...') - cat = True if 'docs' in {in_type, out_type} else False - query_qrel_doc = ds.pair(datapath, f'{prep_output}/{ds.user_pairing}queries.qrels.doc{"s" if cat else ""}.ctx.{index_item_str}.train.no_dups.tsv', cat=cat) - # print(f'Pairing queries and relevant passages for test set ...') - # TODO: query_qrel_doc = pair(datapath, f'{prep_output}/queries.qrels.doc.ctx.{index_item_str}.test.tsv') - # query_qrel_doc = ds.pair(datapath, f'{prep_output}/queries.qrels.doc{"s" if cat else ""}.ctx.{index_item_str}.test.tsv', cat=cat) - query_qrel_doc.to_csv(tsv_path['train'], sep='\t', encoding='utf-8', index=False, columns=[in_type, out_type], header=False) - query_qrel_doc.to_csv(tsv_path['test'], sep='\t', encoding='utf-8', index=False, columns=[in_type, out_type], header=False) - - if {'finetune', 'predict'} & set(settings['cmd']): - from mdl import mt5w - if 'finetune' in settings['cmd']: - print(f"Finetuning {t5_model} for {settings['iter']} iterations and storing the checkpoints at {t5_output} ...") - mt5w.finetune( - tsv_path=tsv_path, - pretrained_dir=f'./../output/t5-data/pretrained_models/{t5_model.split(".")[0]}', # "gs://t5-data/pretrained_models/{"small", "base", "large", "3B", "11B"} - steps=settings['iter'], - output=t5_output, task_name=f"{domain.replace('-', '')}_cf", # :DD Task name must match regex: ^[\w\d\.\:_]+$ - lseq=corpora[domain]['lseq'], - nexamples=None, in_type=in_type, out_type=out_type, gcloud=False) - - if 'predict' in settings['cmd']: - print(f"Predicting {settings['nchanges']} query changes using {t5_model} and storing the results at {t5_output} ...") - mt5w.predict( - iter=settings['nchanges'], - split='test', - tsv_path=tsv_path, - output=t5_output, - lseq=corpora[domain]['lseq'], - gcloud=False) + # TODO: add paring with other expanders + if 'pair' in settings['cmd']: + print('Pairing queries and relevant passages for training set ...') + cat = True if 'docs' in {in_type, out_type} else False + query_qrel_doc = ds.pair(datapath, f'{prep_output}/{ds.user_pairing}queries.qrels.doc{"s" if cat else ""}.ctx.{index_item_str}.train.no_dups.tsv', cat=cat) + # print(f'Pairing queries and relevant passages for test set ...') + # TODO: query_qrel_doc = pair(datapath, f'{prep_output}/queries.qrels.doc.ctx.{index_item_str}.test.tsv') + # query_qrel_doc = ds.pair(datapath, f'{prep_output}/queries.qrels.doc{"s" if cat else ""}.ctx.{index_item_str}.test.tsv', cat=cat) + query_qrel_doc.to_csv(tsv_path['train'], sep='\t', encoding='utf-8', index=False, columns=[in_type, out_type], header=False) + query_qrel_doc.to_csv(tsv_path['test'], sep='\t', encoding='utf-8', index=False, columns=[in_type, out_type], header=False) + + if {'finetune', 'predict'} & set(settings['cmd']): + from mdl import mt5w + if 'finetune' in settings['cmd']: + print(f"Finetuning {t5_model} for {settings['iter']} iterations and storing the checkpoints at {t5_output} ...") + mt5w.finetune( + tsv_path=tsv_path, + pretrained_dir=f'./../output/t5-data/pretrained_models/{t5_model.split(".")[0]}', # "gs://t5-data/pretrained_models/{"small", "base", "large", "3B", "11B"} + steps=settings['iter'], + output=t5_output, task_name=f"{domain.replace('-', '')}_cf", # :DD Task name must match regex: ^[\w\d\.\:_]+$ + lseq=corpora[domain]['lseq'], + nexamples=None, in_type=in_type, out_type=out_type, gcloud=False) + + if 'predict' in settings['cmd']: + print(f"Predicting {settings['nchanges']} query changes using {t5_model} and storing the results at {t5_output} ...") + mt5w.predict( + iter=settings['nchanges'], + split='test', + tsv_path=tsv_path, + output=t5_output, + lseq=corpora[domain]['lseq'], + gcloud=False) if 'search' in settings['cmd']: # 'bm25 ranker' print(f"Searching documents for query changes using {settings['ranker']} ...") # seems for some queries there is no qrels, so they are missed for t5 prediction. # query_originals = pd.read_csv(f'{datapath}/queries.train.tsv', sep='\t', names=['qid', 'query'], dtype={'qid': str}) # we use the file after panda.merge that create the training set, so we make sure the mapping of qids - query_originals = pd.read_csv(f'{prep_output}/{ds.user_pairing}queries.qrels.doc{"s" if "docs" in {in_type, out_type} else ""}.ctx.{index_item_str}.train.tsv', sep='\t', usecols=['qid', 'query'], dtype={'qid': str}) + # query_originals = pd.read_csv(f'{prep_output}/{ds.user_pairing}queries.qrels.doc{"s" if "docs" in {in_type, out_type} else ""}.ctx.{index_item_str}.train.tsv', sep='\t', usecols=['qid', 'query'], dtype={'qid': str}) - original_dir = f'{t5_output}/original' - if not os.path.isdir(original_dir): os.makedirs(original_dir) - # we can run this logic if shape of query_originals is greater than split_size + + # we can run this logic if shape of queries is greater than split_size if settings['large_ds']: - import numpy as np import glob - split_size = 1000000 # need to make this dynamic based on shape of query_originals. - for _, chunk in query_originals.groupby(np.arange(query_originals.shape[0]) // split_size): - # Generate original queries' files + original_dir = f'{t5_output}/original' + if not os.path.isdir(original_dir): os.makedirs(original_dir) + split_size = 1000000 # need to make this dynamic based on shape of queries. + for _, chunk in [ds.queries[i:i + split_size] for i in range(0, len(ds.queries), split_size)]: + # Generate original queries' files - keep records original_file_i = f'{original_dir}/original.{_}.tsv' - chunk[['query']].to_csv(original_file_i, sep='\t', index=False, header=False) + pd.DataFrame({'query': [query.q for query in chunk]}).to_csv(original_file_i, sep='\t', index=False, header=False) file_changes = [(file, f'{file}.{settings["ranker"]}') for file in glob.glob(f'{t5_output}/**/pred.{_}*') if f'{file}.{settings["ranker"]}' not in glob.glob(f'{t5_output}/**')] - chunk.drop_duplicates(subset=['qid'], inplace=True) # in the event there are duplicates in query qrels. - with mp.Pool(settings['ncore']) as p: - p.starmap(partial(ds.search, qids=chunk['qid'].values.tolist(), ranker=settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore'], index=ds.searcher.index_dir), file_changes) + file_changes.extend([(f'{t5_output}/{f}', f'{t5_output}/{f}.{settings["ranker"]}') for f in os.listdir(t5_output) if os.path.isfile(os.path.join(t5_output, f)) and f.startswith('refiner.')]) + + with mp.Pool(settings['ncore']) as p: p.starmap(partial(ds.search, qids=[query.qid for query in chunk], ranker=settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore'], index=ds.searcher.index_dir), file_changes) print('For original queries') file_changes = list() - for _, chunk in query_originals.groupby(np.arange(query_originals.shape[0]) // split_size): - chunk.drop_duplicates(subset=['qid'], inplace=True) - file_changes.append((f'{t5_output}/original/original.{_}.tsv', f'{t5_output}/original/original.{_}.tsv.bm25', chunk['qid'].values.tolist())) - with mp.Pool(settings['ncore']) as p: - p.starmap(partial(ds.search, ranker=settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore'], index=ds.searcher.index_dir), file_changes) + for _, chunk in [ds.queries[i:i + split_size] for i in range(0, len(ds.queries), split_size)]: file_changes.append((f'{t5_output}/original/original.{_}.tsv', f'{t5_output}/original/original.{_}.tsv.bm25', [query.qid for query in chunk])) + with mp.Pool(settings['ncore']) as p: p.starmap(partial(ds.search, ranker=settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore'], index=ds.searcher.index_dir), file_changes) else: - query_changes = [(f'{t5_output}/{f}', f'{t5_output}/{f}.{settings["ranker"]}') for f in listdir(t5_output) if isfile(join(t5_output, f)) and f.startswith('pred.') and len(f.split('.')) == 2 and f'{f}.{settings["ranker"]}' not in listdir(t5_output)] - - # for (i, o) in query_changes: ds.search(i, o, query_originals['qid'].values.tolist(), settings['ranker'], topk=settings['topk'], batch=settings['batch']) + # Here it considers generated queries from t5 or refiners and the original queries + query_changes = [ + (f'{t5_output}/{f}', f'{t5_output}/{f}.{settings["ranker"]}') + for f in listdir(t5_output) + if isfile(join(t5_output, f)) and ( + f.startswith('pred.') or f.startswith('refiner.') or f.startswith('original.') + ) and len(f.split('.')) == 2 and f'{f}.{settings["ranker"]}' not in listdir(t5_output) + ] + # query_changes = [] + # for f in listdir(t5_output): + # if isfile(join(t5_output, f)) and (f.startswith('pred.') or f.startswith('refiner.')) and len( + # f.split('.')) == 2 and f'{f}.{settings["ranker"]}' not in listdir(t5_output): + # query_changes.append((f'{t5_output}/{f}', f'{t5_output}/{f}.{settings["ranker"]}')) + # for (i, o) in query_changes: ds.search(i, o, query_originals['qid'].values.tolist(), settings['ranker'], topk=settings['topk'], batch=settings['batch']) # batch search: # for (i, o) in query_changes: ds.search(i, o, query_originals['qid'].values.tolist(), settings['ranker'], topk=settings['topk'], batch=settings['batch']) # seems the LuceneSearcher cannot be shared in multiple processes! See dal.ds.py - # parallel on each file ==> Problem: starmap does not understand inherited Dataset.searcher attribute! - with mp.Pool(settings['ncore']) as p: - p.starmap(partial(ds.search, qids=query_originals['qid'].values.tolist(), ranker=settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore'], index=ds.searcher.index_dir), query_changes) + #TODO: parallel on each file ==> Problem: starmap does not understand inherited Dataset.searcher attribute! + user_pairing = "user/" if "user" in ds.settings["pairing"] else "" + index_item_str = '.'.join(settings["index_item"]) if ds.__class__.__name__ != 'MsMarcoPsg' else "" + with mp.Pool(settings['ncore']) as p: p.starmap(partial(ds.search, qids=[query.qid for query in ds.queries], ranker=settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore'], index=f'{ds.settings["index"]}{user_pairing}{index_item_str}'), query_changes) + # we need to add the original queries as well - original_path = f'{t5_output}/original.{settings["ranker"]}' - if not isfile(original_path): - query_originals[['query']].to_csv(original_path, sep='\t', index=False, header=False) - ds.search_df(pd.DataFrame(query_originals['query']), original_path, query_originals['qid'].values.tolist(), settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore']) + # original_path = f'{t5_output}/original.{settings["ranker"]}' + # if not isfile(original_path): + # pd.DataFrame({'query': [query.q for query in ds.queries]}).to_csv(original_path, sep='\t', index=False, header=False) + # ds.search_df(queries=pd.DataFrame([query.q for query in ds.queries]), out_docids=original_path, qids=[query.qid for query in ds.queries], ranker=settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore']) if 'eval' in settings['cmd']: from evl import trecw @@ -181,19 +198,22 @@ def run(data_list, domain_list, output, corpora, settings): print('all files are merged and ready for aggregation') else: search_results = [(f'{t5_output}/{f}', f'{t5_output}/{f}.{settings["metric"]}') for f in listdir(t5_output) if f.endswith(settings["ranker"]) and f'{f}.{settings["ranker"]}.{settings["metric"]}' not in listdir(t5_output)] - if not isfile(f'{datapath}/{ds.user_pairing}qrels.train.tsv_'): - qrels = pd.read_csv(f'{datapath}/{ds.user_pairing}qrels.train.tsv', sep='\t', index_col=False, names=['qid', 'did', 'pid', 'relevancy'], header=None) - qrels.drop_duplicates(subset=['qid', 'pid'], inplace=True) # qrels have duplicates!! - qrels.to_csv(f'{datapath}/qrels.train.tsv_', index=False, sep='\t', header=False) # trec_eval.9.0.4 does not accept duplicate rows!! + # This snipet code is added in the read_quereis function! + # if not isfile(f'{datapath}/{ds.user_pairing}qrels.train.tsv_'): + # qrels = pd.read_csv(f'{datapath}/{ds.user_pairing}qrels.train.tsv', sep='\t', index_col=False, names=['qid', 'did', 'pid', 'relevancy'], header=None) + # qrels.drop_duplicates(subset=['qid', 'pid'], inplace=True) # qrels have duplicates!! + # qrels.to_csv(f'{datapath}/qrels.train.tsv_', index=False, sep='\t', header=False) # trec_eval.9.0.4 does not accept duplicate rows!! # for (i, o) in search_results: trecw.evaluate(i, o, qrels=f'{datapath}/qrels.train.tsv_', metric=settings['metric'], lib=settings['treclib']) - with mp.Pool(settings['ncore']) as p: - p.starmap(partial(trecw.evaluate, qrels=f'{datapath}/{ds.user_pairing}qrels.train.tsv_', metric=settings['metric'], lib=settings['treclib'], mean=not settings['large_ds']), search_results) + with mp.Pool(settings['ncore']) as p: p.starmap(partial(trecw.evaluate, qrels=f'{datapath}/{ds.user_pairing}qrels.train.tsv_', metric=settings['metric'], lib=settings['treclib'], mean=not settings['large_ds']), search_results) + if 'agg' in settings['cmd']: - originals = pd.read_csv(f'{prep_output}/queries.qrels.doc{"s" if "docs" in {in_type, out_type} else ""}.ctx.{index_item_str}.train.tsv', sep='\t', usecols=['qid', 'query'], dtype={'qid': str}) - original_metric_values = pd.read_csv(join(t5_output, f'original.{settings["ranker"]}.{settings["metric"]}'), sep='\t', usecols=[1, 2], names=['qid', f'original.{settings["ranker"]}.{settings["metric"]}'], index_col=False, dtype={'qid': str}) + # originals = pd.read_csv(f'{prep_output}/queries.qrels.doc{"s" if "docs" in {in_type, out_type} else ""}.ctx.{index_item_str}.train.tsv', sep='\t', usecols=['qid', 'query'], dtype={'qid': str}) + originals = pd.DataFrame({'qid': [str(query.qid) for query in ds.queries], 'query': [query.q for query in ds.queries]}) + original_metric_values = pd.read_csv(join(t5_output, f'original.queries.{settings["ranker"]}.{settings["metric"]}'), sep='\t', usecols=[1, 2], names=['qid', f'original.queries.{settings["ranker"]}.{settings["metric"]}'], index_col=False, dtype={'qid': str}) + originals = originals.merge(original_metric_values, how='left', on='qid') - originals[f'original.{settings["ranker"]}.{settings["metric"]}'].fillna(0, inplace=True) + originals[f'original.queries.{settings["ranker"]}.{settings["metric"]}'].fillna(0, inplace=True) changes = [('.'.join(f.split('.')[0:2]), f) for f in os.listdir(t5_output) if f.endswith(f'{settings["ranker"]}.{settings["metric"]}') and 'original' not in f] ds.aggregate(originals, changes, t5_output, settings["large_ds"]) @@ -202,21 +222,22 @@ def run(data_list, domain_list, output, corpora, settings): box_path = join(t5_output, f'{settings["ranker"]}.{settings["metric"]}.boxes') if not os.path.isdir(box_path): os.makedirs(box_path) gold_df = pd.read_csv(f'{t5_output}/{settings["ranker"]}.{settings["metric"]}.agg.all.tsv', sep='\t', header=0, dtype={'qid': str}) - qrels = pd.read_csv(f'{datapath}/qrels.train.tsv_', names=['qid', 'did', 'pid', 'rel'], sep='\t', dtype={'qid': str}) + qrels = pd.DataFrame([query.docs for query in ds.queries]) box_condition = settings['box'] ds.box(gold_df, qrels, box_path, box_condition) for c in box_condition.keys(): - print(f'Stamping boxes for {settings["ranker"]}.{settings["metric"]} before and after refinements ...') - + print(f'{c}: Stamping boxes for {settings["ranker"]}.{settings["metric"]} before and after refinements ...') if not os.path.isdir(join(box_path, 'stamps')): os.makedirs(join(box_path, 'stamps')) - df = pd.read_csv(f'{box_path}/{c}.tsv', sep='\t', encoding='utf-8', index_col=False, header=None, names=['qid', 'query', 'metric', 'query_', 'metric_'], dtype={'qid': str}) df.drop_duplicates(subset=['qid'], inplace=True) # See ds.boxing(): in case we store more than two changes with the same metric value - ds.search_df(df['query'].to_frame(), f'{box_path}/stamps/{c}.original.{settings["ranker"]}', df['qid'].values.tolist(), settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore']) - trecw.evaluate(f'{box_path}/stamps/{c}.original.{settings["ranker"]}', f'{box_path}/stamps/{c}.original.{settings["ranker"]}.{settings["metric"]}', qrels=f'{datapath}/qrels.train.tsv_', metric=settings['metric'], lib=settings['treclib'], mean=True) - ds.search_df(df['query_'].to_frame().rename(columns={'query_': 'query'}), f'{box_path}/stamps/{c}.change.{settings["ranker"]}', df['qid'].values.tolist(), settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore']) - trecw.evaluate(f'{box_path}/stamps/{c}.change.{settings["ranker"]}', f'{box_path}/stamps/{c}.change.{settings["ranker"]}.{settings["metric"]}', qrels=f'{datapath}/qrels.train.tsv_', metric=settings['metric'], lib=settings['treclib'], mean=True) + if df['query'].to_frame().empty: print(f'No queries for {c}') + else: + ds.search_df(df['query'].to_frame(), f'{box_path}/stamps/{c}.original.{settings["ranker"]}', df['qid'].values.tolist(), settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore']) + trecw.evaluate(f'{box_path}/stamps/{c}.original.{settings["ranker"]}', f'{box_path}/stamps/{c}.original.{settings["ranker"]}.{settings["metric"]}', qrels=f'{datapath}/qrels.train.tsv_', metric=settings['metric'], lib=settings['treclib'], mean=True) + ds.search_df(df['query_'].to_frame().rename(columns={'query_': 'query'}), f'{box_path}/stamps/{c}.change.{settings["ranker"]}', df['qid'].values.tolist(), settings['ranker'], topk=settings['topk'], batch=settings['batch'], ncores=settings['ncore']) + trecw.evaluate(f'{box_path}/stamps/{c}.change.{settings["ranker"]}', f'{box_path}/stamps/{c}.change.{settings["ranker"]}.{settings["metric"]}', qrels=f'{datapath}/qrels.train.tsv_', metric=settings['metric'], lib=settings['treclib'], mean=True) + if 'dense_retrieve' in settings['cmd']: from evl import trecw from tqdm import tqdm @@ -249,7 +270,7 @@ def run(data_list, domain_list, output, corpora, settings): search_results = [(f'{t5_output}/original.{condition}.tct_colbert', f'{t5_output}/original.{condition}.tct_colbert.{metric}'), (f'{t5_output}/pred.{condition}.tct_colbert', f'{t5_output}/pred.{condition}.tct_colbert.{metric}')] with mp.Pool(settings['ncore']) as p: - p.starmap(partial(ds.search_df, qids=original['qid'].values.tolist(), ranker='tct_colbert', topk=100, batch=None, + p.starmap(partial(ds.search_list, qids=original['qid'].values.tolist(), ranker='tct_colbert', topk=100, batch=None, ncores=settings['ncore'], index=settings[f'{domain}']["dense_index"], encoder=settings[f'{domain}']['dense_encoder']), search_list) p.starmap(partial(trecw.evaluate, qrels=f'{datapath}/qrels.train.tsv_', metric=settings['metric'], lib=settings['treclib']), search_results) diff --git a/src/mdl/mt5w.py b/src/mdl/mt5w.py index ff2575d..07e1198 100644 --- a/src/mdl/mt5w.py +++ b/src/mdl/mt5w.py @@ -1,6 +1,6 @@ import functools, os, sys, time import tensorflow.compat.v1 as tf -import tensorflow_datasets as tfds +# import tensorflow_datasets as tfds import t5 import t5.models @@ -95,7 +95,7 @@ def predict(iter, split, tsv_path, output, lseq, vocab_model_path='./../output/t # def predict(iter, split, tsv_path, pretrained_dir, steps, output, lseq, task_name, nexamples=None, in_type='query', out_type='doc', vocab_model_path='./../output/t5-data/vocabs/cc_en.32000/sentencepiece.model', gcloud=False): if gcloud: import gcloud - model_parallelism, train_batch_size, keep_checkpoint_max = {"small": (1, 256, 16), "base": (2, 128, 8), "large": (8, 64, 4), "3B": (8, 16, 1), "11B": (8, 16, 1)}[output.split('.')[-4]] + model_parallelism, train_batch_size, keep_checkpoint_max = {"small": (1, 256, 16), "base": (2, 128, 8), "large": (8, 64, 4), "3B": (8, 16, 1), "11B": (8, 16, 1)}[output.split('.')[-5]] model = t5.models.MtfModel( model_dir=output.replace('/', os.path.sep), tpu=gcloud.TPU_ADDRESS if gcloud else None, diff --git a/src/param.py b/src/param.py index 7a46d86..c3108ff 100644 --- a/src/param.py +++ b/src/param.py @@ -32,6 +32,7 @@ 'index': '../data/raw/msmarco.passage/lucene-index.msmarco-v1-passage.20220131.9ea315/', 'dense_encoder': 'castorini/tct_colbert-msmarco', 'dense_index': 'msmarco-passage-tct_colbert-hnsw', + 'extcorpus': 'orcas', 'pairing': [None, 'docs', 'query'], # [context={msmarco does not have userinfo}, input={query, doc, doc(s)}, output={query, doc, doc(s)}], s means concat of docs 'lseq': {"inputs": 32, "targets": 256}, # query length and doc length for t5 model, }, @@ -45,55 +46,66 @@ 'filter': {'minql': 1, 'mindocl': 10} # [min query length, min doc length], after merge queries with relevant 'index_item', if |query| <= minql drop the row, if |'index_item'| < mindocl, drop row }, 'robust04': { - 'index': '../ds/robust04/lucene-index.robust04.pos+docvectors+rawdocs', - 'dense_index': '../ds/robust04/faiss_index_robust04', - 'encoded': '../ds/robust04/encoded_robust04', + 'index': '../data/raw/robust04/lucene-index.robust04.pos+docvectors+rawdocs', + 'dense_index': '../data/raw/robust04/faiss_index_robust04', + 'encoded': '../data/raw/robust04/encoded_robust04', 'size': 528155, - 'topics': '../ds/robust04/topics.robust04.txt', + 'topics': '../data/raw/robust04/topics.robust04.txt', 'prels': '', # this will be generated after a retrieval {bm25, qld} 'w_t': 2.25, # OnFields 'w_a': 1, # OnFields 'tokens': 148000000, - 'qrels': '../ds/robust04/qrels.robust04.txt', + 'qrels': '../data/raw/robust04/qrels.robust04.txt', 'extcorpus': 'gov2', # AdaptOnFields + 'pairing': [None, None, None], + 'index_item': [], }, 'gov2': { - 'index': '../ds/gov2/lucene-index.gov2.pos+docvectors+rawdocs', + 'index': '../data/raw/gov2/lucene-index.gov2.pos+docvectors+rawdocs', 'size': 25000000, - 'topics': '../ds/gov2/topics.terabyte0{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'topics': '../data/raw/gov2/topics.terabyte0{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'trec': ['4.701-750', '5.751-800', '6.801-850'], 'prels': '', # this will be generated after a retrieval {bm25, qld} 'w_t': 4, # OnFields 'w_a': 0.25, # OnFields 'tokens': 17000000000, - 'qrels': '../ds/gov2/qrels.terabyte0{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'qrels': '../data/raw/gov2/qrels.terabyte0{}.txt', # {} is a placeholder for subtopics in main.py -> run() 'extcorpus': 'robust04', # AdaptOnFields + 'pairing': [None, None, None], + 'index_item': [], }, 'clueweb09b': { - 'index': '../ds/clueweb09b/lucene-index.cw09b.pos+docvectors+rawdocs', + 'index': '../data/raw/clueweb09b/lucene-index.cw09b.pos+docvectors+rawdocs', 'size': 50000000, - 'topics': '../ds/clueweb09b/topics.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'topics': '../data/raw/clueweb09b/topics.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'trec': ['1-50', '51-100', '101-150', '151-200'], 'prels': '', # this will be generated after a retrieval {bm25, qld} 'w_t': 1, # OnFields 'w_a': 0, # OnFields 'tokens': 31000000000, - 'qrels': '../ds/clueweb09b/qrels.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'qrels': '../data/raw/clueweb09b/qrels.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() 'extcorpus': 'gov2', # AdaptOnFields + 'pairing': [None, None, None], + 'index_item': [], }, 'clueweb12b13': { - 'index': '../ds/clueweb12b13/lucene-index.cw12b13.pos+docvectors+rawdocs', + 'index': '../data/raw/clueweb12b13/lucene-index.cw12b13.pos+docvectors+rawdocs', 'size': 50000000, - 'topics': '../ds/clueweb12b13/topics.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'topics': '../data/raw/clueweb12b13/topics.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'trec': ['201-250', '251-300'], 'prels': '', # this will be generated after a retrieval {bm25, qld} 'w_t': 4, # OnFields 'w_a': 0, # OnFields 'tokens': 31000000000, - 'qrels': '../ds/clueweb12b13/qrels.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() + 'qrels': '../data/raw/clueweb12b13/qrels.web.{}.txt', # {} is a placeholder for subtopics in main.py -> run() 'extcorpus': 'gov2', # AdaptOnFields + 'pairing': [None, None, None], + 'index_item': [], }, 'antique': { - 'index': '../ds/antique/lucene-index-antique', + 'index': '../data/raw/antique/lucene-index-antique', 'size': 403000, - 'topics': '../ds/antique/topics.antique.txt', + 'topics': '../data/raw/antique/topics.antique.txt', 'prels': '', # this will be generated after a retrieval {bm25, qld} 'w_t': 2.25, # OnFields # to be tuned 'w_a': 1, # OnFields # to be tuned diff --git a/src/refinement/refiner_factory.py b/src/refinement/refiner_factory.py index da06347..7db2951 100644 --- a/src/refinement/refiner_factory.py +++ b/src/refinement/refiner_factory.py @@ -1,38 +1,38 @@ -from refiners.abstractqrefiner import AbstractQRefiner -from refiners.stem import Stem # Stem refiner is the wrapper for all stemmers as an refiner :) -import param -import utils +from src.refinement.refiners.abstractqrefiner import AbstractQRefiner +from src.refinement.refiners.stem import Stem # Stem refiner is the wrapper for all stemmers as an refiner :) +from src.refinement import refiner_param +from src.refinement import utils #global analysis def get_nrf_refiner(): refiners_list = [AbstractQRefiner()] - if param.refiners['Thesaurus']: from refiners.thesaurus import Thesaurus; refiners_list.append(Thesaurus()) - if param.refiners['Thesaurus']: from refiners.thesaurus import Thesaurus; refiners_list.append(Thesaurus(replace=True)) - if param.refiners['Wordnet']: from refiners.wordnet import Wordnet; refiners_list.append(Wordnet()) - if param.refiners['Wordnet']: from refiners.wordnet import Wordnet; refiners_list.append(Wordnet(replace=True)) - if param.refiners['Word2Vec']: from refiners.word2vec import Word2Vec; refiners_list.append(Word2Vec('../pre/wiki-news-300d-1M.vec')) - if param.refiners['Word2Vec']: from refiners.word2vec import Word2Vec; refiners_list.append(Word2Vec('../pre/wiki-news-300d-1M.vec', replace=True)) - if param.refiners['Glove']: from refiners.glove import Glove; refiners_list.append(Glove('../pre/glove.6B.300d')) - if param.refiners['Glove']: from refiners.glove import Glove; refiners_list.append(Glove('../pre/glove.6B.300d', replace=True)) - if param.refiners['Anchor']: from refiners.anchor import Anchor; refiners_list.append(Anchor(anchorfile='../pre/anchor_text_en.ttl', vectorfile='../pre/wiki-anchor-text-en-ttl-300d.vec')) - if param.refiners['Anchor']: from refiners.anchor import Anchor; refiners_list.append(Anchor(anchorfile='../pre/anchor_text_en.ttl', vectorfile='../pre/wiki-anchor-text-en-ttl-300d.vec', replace=True)) - if param.refiners['Wiki']: from refiners.wiki import Wiki; refiners_list.append(Wiki('../pre/temp_model_Wiki')) - if param.refiners['Wiki']: from refiners.wiki import Wiki; refiners_list.append(Wiki('../pre/temp_model_Wiki', replace=True)) - if param.refiners['Tagmee']: from refiners.tagmee import Tagmee; refiners_list.append(Tagmee()) - if param.refiners['Tagmee']: from refiners.tagmee import Tagmee; refiners_list.append(Tagmee(replace=True)) - if param.refiners['SenseDisambiguation']: from refiners.sensedisambiguation import SenseDisambiguation; refiners_list.append(SenseDisambiguation()) - if param.refiners['SenseDisambiguation']: from refiners.sensedisambiguation import SenseDisambiguation; refiners_list.append(SenseDisambiguation(replace=True)) - if param.refiners['Conceptnet']: from refiners.conceptnet import Conceptnet; refiners_list.append(Conceptnet()) - if param.refiners['Conceptnet']: from refiners.conceptnet import Conceptnet; refiners_list.append(Conceptnet(replace=True)) - if param.refiners['KrovetzStemmer']: from stemmers.krovetz import KrovetzStemmer; refiners_list.append(Stem(KrovetzStemmer(jarfile='stemmers/kstem-3.4.jar'))) - if param.refiners['LovinsStemmer']: from stemmers.lovins import LovinsStemmer; refiners_list.append(Stem(LovinsStemmer())) - if param.refiners['PaiceHuskStemmer']: from stemmers.paicehusk import PaiceHuskStemmer; refiners_list.append(Stem(PaiceHuskStemmer())) - if param.refiners['PorterStemmer']: from stemmers.porter import PorterStemmer; refiners_list.append(Stem(PorterStemmer())) - if param.refiners['Porter2Stemmer']: from stemmers.porter2 import Porter2Stemmer; refiners_list.append(Stem(Porter2Stemmer())) - if param.refiners['SRemovalStemmer']: from stemmers.sstemmer import SRemovalStemmer; refiners_list.append(Stem(SRemovalStemmer())) - if param.refiners['Trunc4Stemmer']: from stemmers.trunc4 import Trunc4Stemmer; refiners_list.append(Stem(Trunc4Stemmer())) - if param.refiners['Trunc5Stemmer']: from stemmers.trunc5 import Trunc5Stemmer; refiners_list.append(Stem(Trunc5Stemmer())) - if param.refiners['BackTranslation']: from refiners.backtranslation import BackTranslation; refiners_list.extend([BackTranslation(each_lng) for index, each_lng in enumerate(param.backtranslation['tgt_lng'])]) + if refiner_param.refiners['Thesaurus']: from src.refinement.refiners.thesaurus import Thesaurus; refiners_list.append(Thesaurus()) + if refiner_param.refiners['Thesaurus']: from src.refinement.refiners.thesaurus import Thesaurus; refiners_list.append(Thesaurus(replace=True)) + if refiner_param.refiners['Wordnet']: from src.refinement.refiners.wordnet import Wordnet; refiners_list.append(Wordnet()) + if refiner_param.refiners['Wordnet']: from src.refinement.refiners.wordnet import Wordnet; refiners_list.append(Wordnet(replace=True)) + if refiner_param.refiners['Word2Vec']: from src.refinement.refiners.word2vec import Word2Vec; refiners_list.append(Word2Vec('../pre/wiki-news-300d-1M.vec')) + if refiner_param.refiners['Word2Vec']: from src.refinement.refiners.word2vec import Word2Vec; refiners_list.append(Word2Vec('../pre/wiki-news-300d-1M.vec', replace=True)) + if refiner_param.refiners['Glove']: from src.refinement.refiners.glove import Glove; refiners_list.append(Glove('../pre/glove.6B.300d')) + if refiner_param.refiners['Glove']: from src.refinement.refiners.glove import Glove; refiners_list.append(Glove('../pre/glove.6B.300d', replace=True)) + if refiner_param.refiners['Anchor']: from src.refinement.refiners.anchor import Anchor; refiners_list.append(Anchor(anchorfile='../pre/anchor_text_en.ttl', vectorfile='../pre/wiki-anchor-text-en-ttl-300d.vec')) + if refiner_param.refiners['Anchor']: from src.refinement.refiners.anchor import Anchor; refiners_list.append(Anchor(anchorfile='../pre/anchor_text_en.ttl', vectorfile='../pre/wiki-anchor-text-en-ttl-300d.vec', replace=True)) + if refiner_param.refiners['Wiki']: from src.refinement.refiners.wiki import Wiki; refiners_list.append(Wiki('../pre/temp_model_Wiki')) + if refiner_param.refiners['Wiki']: from src.refinement.refiners.wiki import Wiki; refiners_list.append(Wiki('../pre/temp_model_Wiki', replace=True)) + if refiner_param.refiners['Tagmee']: from src.refinement.refiners.tagmee import Tagmee; refiners_list.append(Tagmee()) + if refiner_param.refiners['Tagmee']: from src.refinement.refiners.tagmee import Tagmee; refiners_list.append(Tagmee(replace=True)) + if refiner_param.refiners['SenseDisambiguation']: from src.refinement.refiners.sensedisambiguation import SenseDisambiguation; refiners_list.append(SenseDisambiguation()) + if refiner_param.refiners['SenseDisambiguation']: from src.refinement.refiners.sensedisambiguation import SenseDisambiguation; refiners_list.append(SenseDisambiguation(replace=True)) + if refiner_param.refiners['Conceptnet']: from src.refinement.refiners.conceptnet import Conceptnet; refiners_list.append(Conceptnet()) + if refiner_param.refiners['Conceptnet']: from src.refinement.refiners.conceptnet import Conceptnet; refiners_list.append(Conceptnet(replace=True)) + if refiner_param.refiners['KrovetzStemmer']: from stemmers.krovetz import KrovetzStemmer; refiners_list.append(Stem(KrovetzStemmer(jarfile='stemmers/kstem-3.4.jar'))) + if refiner_param.refiners['LovinsStemmer']: from stemmers.lovins import LovinsStemmer; refiners_list.append(Stem(LovinsStemmer())) + if refiner_param.refiners['PaiceHuskStemmer']: from stemmers.paicehusk import PaiceHuskStemmer; refiners_list.append(Stem(PaiceHuskStemmer())) + if refiner_param.refiners['PorterStemmer']: from stemmers.porter import PorterStemmer; refiners_list.append(Stem(PorterStemmer())) + if refiner_param.refiners['Porter2Stemmer']: from stemmers.porter2 import Porter2Stemmer; refiners_list.append(Stem(Porter2Stemmer())) + if refiner_param.refiners['SRemovalStemmer']: from stemmers.sstemmer import SRemovalStemmer; refiners_list.append(Stem(SRemovalStemmer())) + if refiner_param.refiners['Trunc4Stemmer']: from stemmers.trunc4 import Trunc4Stemmer; refiners_list.append(Stem(Trunc4Stemmer())) + if refiner_param.refiners['Trunc5Stemmer']: from stemmers.trunc5 import Trunc5Stemmer; refiners_list.append(Stem(Trunc5Stemmer())) + if refiner_param.refiners['BackTranslation']: from src.refinement.refiners.backtranslation import BackTranslation; refiners_list.extend([BackTranslation(each_lng) for index, each_lng in enumerate(refiner_param.backtranslation['tgt_lng'])]) # since RF needs index and search output which depends on ir method and topics corpora, we cannot add this here. Instead, we run it individually # RF assumes that there exist abstractqueryexpansion files @@ -43,13 +43,13 @@ def get_rf_refiner(rankers, corpus, output, ext_corpus=None): refiners_list = [] for ranker in rankers: ranker_name = utils.get_ranker_name(ranker) - if param.refiners['RM3']: from refiners.rm3 import RM3; refiners_list.append(RM3(ranker=ranker_name, index=corpus['index'])) - if param.refiners['RelevanceFeedback']: from refiners.relevancefeedback import RelevanceFeedback; refiners_list.append(RelevanceFeedback(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=param.anserini['path'], index=corpus['index'])) - if param.refiners['Docluster']: from refiners.docluster import Docluster; refiners_list.append(Docluster(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=param.anserini['path'], index=corpus['index'])), - if param.refiners['Termluster']: from refiners.termluster import Termluster; refiners_list.append(Termluster(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=param.anserini['path'], index=corpus['index'])) - if param.refiners['Conceptluster']: from refiners.conceptluster import Conceptluster; refiners_list.append(Conceptluster(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=param.anserini['path'], index=corpus['index'])) - if param.refiners['BertQE']: from refiners.bertqe import BertQE; refiners_list.append(BertQE(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), index=corpus['index'], anserini=param.anserini['path'])) - if param.refiners['OnFields']: from refiners.onfields import OnFields; refiners_list.append(OnFields(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=param.anserini['path'], index=param.corpora[corpus]['index'], w_t=corpus['w_t'], w_a=corpus['w_a'], corpus_size=corpus['size'])) - if param.refiners['AdapOnFields']: from refiners.adaponfields import AdapOnFields; refiners_list.append(AdapOnFields(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=param.anserini['path'], index=corpus['index'], w_t=corpus['w_t'], w_a=corpus['w_a'], corpus_size=corpus['size'], collection_tokens=corpus['tokens'], ext_corpus=ext_corpus, ext_index=ext_corpus['index'], ext_collection_tokens=ext_corpus['tokens'], ext_w_t=ext_corpus['w_t'], ext_w_a=ext_corpus['w_a'], ext_corpus_size=ext_corpus['size'], adap=True)) + if refiner_param.refiners['RM3']: from src.refinement.refiners.rm3 import RM3; refiners_list.append(RM3(ranker=ranker_name, index=corpus['index'])) + if refiner_param.refiners['RelevanceFeedback']: from src.refinement.refiners.relevancefeedback import RelevanceFeedback; refiners_list.append(RelevanceFeedback(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=refiner_param.anserini['path'], index=corpus['index'])) + if refiner_param.refiners['Docluster']: from src.refinement.refiners.docluster import Docluster; refiners_list.append(Docluster(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=refiner_param.anserini['path'], index=corpus['index'])), + if refiner_param.refiners['Termluster']: from src.refinement.refiners.termluster import Termluster; refiners_list.append(Termluster(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=refiner_param.anserini['path'], index=corpus['index'])) + if refiner_param.refiners['Conceptluster']: from src.refinement.refiners.conceptluster import Conceptluster; refiners_list.append(Conceptluster(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=refiner_param.anserini['path'], index=corpus['index'])) + if refiner_param.refiners['BertQE']: from src.refinement.refiners.bertqe import BertQE; refiners_list.append(BertQE(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), index=corpus['index'], anserini=refiner_param.anserini['path'])) + if refiner_param.refiners['OnFields']: from src.refinement.refiners.onfields import OnFields; refiners_list.append(OnFields(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=refiner_param.anserini['path'], index=refiner_param.corpora[corpus]['index'], w_t=corpus['w_t'], w_a=corpus['w_a'], corpus_size=corpus['size'])) + if refiner_param.refiners['AdapOnFields']: from src.refinement.refiners.adaponfields import AdapOnFields; refiners_list.append(AdapOnFields(ranker=ranker_name, prels='{}.abstractqueryexpansion.{}.txt'.format(output, ranker_name), anserini=refiner_param.anserini['path'], index=corpus['index'], w_t=corpus['w_t'], w_a=corpus['w_a'], corpus_size=corpus['size'], collection_tokens=corpus['tokens'], ext_corpus=ext_corpus, ext_index=ext_corpus['index'], ext_collection_tokens=ext_corpus['tokens'], ext_w_t=ext_corpus['w_t'], ext_w_a=ext_corpus['w_a'], ext_corpus_size=ext_corpus['size'], adap=True)) return refiners_list diff --git a/src/refinement/param.py b/src/refinement/refiner_param.py similarity index 95% rename from src/refinement/param.py rename to src/refinement/refiner_param.py index f34ac20..63b6296 100644 --- a/src/refinement/param.py +++ b/src/refinement/refiner_param.py @@ -2,6 +2,10 @@ extension = '.exe' if platform.system() == 'Windows' else "" +settings = { + 'transformer_model': 'johngiorgi/declutr-small', +} + refiners = { 'SenseDisambiguation': 0, 'Thesaurus': 0, diff --git a/src/refinement/refiners/abstractqrefiner.py b/src/refinement/refiners/abstractqrefiner.py index b191fcd..6d95db5 100644 --- a/src/refinement/refiners/abstractqrefiner.py +++ b/src/refinement/refiners/abstractqrefiner.py @@ -1,217 +1,74 @@ import traceback -import pandas as pd +from src.dal.query import Query +from sentence_transformers import SentenceTransformer +from scipy.spatial.distance import cosine import sys - -sys.path.extend(['../refinement']) -from refinement import utils +sys.path.extend(['../src']) +from src.refinement import utils +from src.refinement.refiner_param import settings class AbstractQRefiner: def __init__(self, replace=False, topn=None): + self.transformer_model = SentenceTransformer(settings['transformer_model']) self.replace = replace self.topn = topn - self.query_set = pd.DataFrame(columns=['qid'], dtype=int) - # all children expanders must call this in the returning line - def get_refined_query(self, q, args=None): - return q, args + # All children expanders must call this in the returning line + def get_refined_query(self, q: Query, args=None): return q.q + + def get_refined_query_batch(self, queries, args=None): return queries, [1] * len(queries) def get_model_name(self): # this is for backward compatibility for renaming this class - if self.__class__.__name__ == 'AbstractQExpander': return 'AbstractQueryExpansion'.lower() + if self.__class__.__name__ == 'AbstractQRefiner': return 'original.queries'.lower() return f"{self.__class__.__name__.lower()}{f'.topn{self.topn}' if self.topn else ''}{'.replace' if self.replace else ''}" - def get_query_set(self): - return self.query_set - - def generate_queue(self, Qfilename, Q_filename): - query_df = self.read_queries(Qfilename) - query_df.apply(lambda row: self.preprocess_expanded_query(q=row[self.get_model_name().lower()], qid=row['qid'], clean=True), axis=1) - self.write_queries(Q_filename) - - def preprocess_expanded_query(self, q, qid, clean): + def preprocess_query(self, query, clean=True): + ansi_reset = "\033[0m" try: - q_, args = self.get_expanded_query(q, args=[qid]) + q_ = self.get_refined_query(query) q_ = utils.clean(q_) if clean else q_ - except: - print(f'WARNING: MAIN: {self.get_model_name()}: Expanding query [{qid}:{q}] failed!') + semsim = self.get_semsim(query, q_) + print(f'{utils.hex_to_ansi("#F1C40F")}Info: {utils.hex_to_ansi("#3498DB")}({self.get_model_name()}){ansi_reset} {query.qid}: {query.q} -> {utils.hex_to_ansi("#52BE80")}{q_}{ansi_reset}') + except Exception as e: + print(f'{utils.hex_to_ansi("#E74C3C")}WARNING: {utils.hex_to_ansi("#3498DB")}({self.get_model_name()}){ansi_reset} Refining query [{query.qid}:{query.q}] failed!') print(traceback.format_exc()) - q_.args = q, [0] - - new_line = {'qid': qid, self.get_model_name(): q_} - if self.get_model_name().__contains__('backtranslation'): new_line['semsim'] = args[0] - self.query_set = pd.concat([self.query_set, pd.DataFrame([new_line])], ignore_index=True) - print(f'INFO: MAIN: {self.get_model_name()}: {qid}: {q} -> {q_}') - - def write_queries(self, Q_filename): - self.query_set.to_csv(Q_filename, sep='\t', index=False, header=False) - - def read_queries(self, Qfilename): - model_name = self.get_model_name().lower() - is_tag_file = False - q, qid = '', '' - query_df = pd.DataFrame(columns=['qid']) - with open(Qfilename, 'r', encoding='UTF-8') as Qfile: - for line in Qfile: - if '<top>' in line and not is_tag_file: is_tag_file = True - if '<num>' in line: qid = int(line[line.index(':') + 1:]) - elif line[:7] == '<title>': - q = line[8:].strip() - if not q: q = next(Qfile).strip() - elif '<topic' in line: - s = line.index('\"') + 1 - e = line.index('\"', s + 1) - qid = int(line[s:e]) - elif line[2:9] == '<query>': q = line[9:-9] - elif len(line.split('\t')) >= 2 and not is_tag_file: - qid = line.split('\t')[0].rstrip() - q = line.split('\t')[1].rstrip() - if q != '' and qid != '': - new_line = {'qid': qid, model_name: q} - query_df = pd.concat([query_df, pd.DataFrame([new_line])], ignore_index=True) - q, qid = '', '' - return query_df.astype({'qid': 'str'}) - - def write_expanded_queries(self, Qfilename, Q_filename, clean=True): - # prevent to clean the original query - if self.__class__.__name__ == 'AbstractQExpander': clean = False - model_name = self.get_model_name().lower() - Q_ = pd.DataFrame() - is_tag_file = False - with open(Qfilename, 'r', encoding='UTF-8') as Qfile: - with open(Q_filename, 'w', encoding='UTF-8') as Q_file: - print(f'INFO: MAIN: {self.get_model_name()}: Expanding queries in {Qfilename} ...') - for line in Qfile: - # For txt files - if '<top>' in line and not is_tag_file: is_tag_file = True - if '<num>' in line: - qid = int(line[line.index(':') + 1:]) - Q_file.write(line) - # For robust & gov2 - elif line[:7] == '<title>': - q = line[8:].strip() - if not q: q = next(Qfile).strip() - q_, args, Q_ = self.preprocess_expanded_query(q, qid, clean, Q_) - if model_name.__contains__('backtranslation'): Q_file.write( - f'<semsim> {args[0]:.4f} </semsim>\n') - Q_file.write('<title> ' + str(q_) + '\n') - elif '<topic' in line: - s = line.index('\"') + 1 - e = line.index('\"', s + 1) - qid = int(line[s:e]) - Q_file.write(line) - # For clueweb09b & clueweb12b13 - elif line[2:9] == '<query>': - q = line[9:-9] - q_, args, Q_ = self.preprocess_expanded_query(q, qid, clean, Q_) - if model_name.__contains__('backtranslation'): Q_file.write( - f'<semsim> {args[0]:.4f} </semsim>\n') - Q_file.write(' <query>' + str(q_) + '</query>' + '\n') - # For tsv files - elif len(line.split('\t')) >= 2 and not is_tag_file: - qid = line.split('\t')[0].rstrip() - q = line.split('\t')[1].rstrip() - q_, args, Q_ = self.preprocess_expanded_query(q, qid, clean, Q_) - Q_file.write(qid + '\t' + str(q_)) - Q_file.write('\t' + str(args[0]) + '\n') if model_name.__contains__('backtranslation') else Q_file.write('\n') - else: - Q_file.write(line) - return Q_ - - def read_expanded_queries(self, Q_filename): - model_name = self.get_model_name().lower() - Q_ = pd.DataFrame(columns=['qid'], dtype=int) - is_tag_file = False - with open(Q_filename, 'r', encoding='UTF-8') as Q_file: - print(f'INFO: MAIN: {self.get_model_name()}: Reading expanded queries in {Q_filename} ...') - for line in Q_file: - q_ = None - # for files with tag - if '<top>' in line and not is_tag_file: is_tag_file = True - if '<num>' in line: - qid = line[line.index(':') + 1:].strip() - elif '<semsim>' in line: - score = line[8:-10] + ' ' - # for robust & gov2 - elif line[:7] == '<title>': - q_ = line[8:].strip() + ' ' - elif '<topic' in line: - s = line.index('\"') + 1 - e = line.index('\"', s + 1) - qid = line[s:e].strip() - # for clueweb09b & clueweb12b13 - elif line[2:9] == '<query>': - q_ = line[9:-9] + ' ' - elif len(line.split('\t')) >= 2 and not is_tag_file: - qid = line.split('\t')[0].rstrip() - q_ = line.split('\t')[1].rstrip() - if model_name.__contains__('backtranslation'): score = line.split('\t')[2].rstrip() - else: - continue - if q_: - new_line = {'qid': qid, model_name: q_} - # For backtranslation expander add a new column as semsim - if model_name.__contains__('backtranslation'): new_line['semsim'] = score - Q_ = pd.concat([Q_, pd.DataFrame([new_line])], ignore_index=True) - return Q_.astype({'qid': 'str'}) + q_, semsim = query.q, 1 + + query.q_[self.get_model_name()] = (q_, semsim) + return query + + def preprocess_query_batch(self, queries, clean=True): + q_s, semsims = self.get_refined_query_batch(queries) + for q_, semsim, query in zip(q_s, semsims, queries): + if q_: + q_ = [utils.clean(q_) if clean else q_] + semsim = self.get_semsim(query, q_) + print(f'INFO: MAIN: {self.get_model_name()}: {query.qid}: {query.q} -> {q_}') + else: + print(f'WARNING: MAIN: {self.get_model_name()}: Refining query [{query.qid}:{query.q}] failed!') + print(traceback.format_exc()) + q_, semsim = query.q, 1 + + query.q_[self.get_model_name()] = (q_, semsim) + return queries + + ''' + Calculates the difference between the original and back-translated query + ''' + def get_semsim(self, q1, q2): + me, you = self.transformer_model.encode([q1, q2]) + return 1 - cosine(me, you) + + def write_queries(self, queries, outfile): + with open(outfile, 'w', encoding='utf-8') as file: + # file.write(f"qid\tq\tq_\tsemsim\n") + for query in queries: + file.write(f"{query.qid}\t{query.q}\t{query.q_[self.get_model_name()][0]}\t{query.q_[self.get_model_name()][1]}\n") if __name__ == "__main__": qe = AbstractQRefiner() print(qe.get_model_name()) - print(qe.get_expanded_query('International Crime Organization')) - - # from expanders.abstractqexpander import AbstractQExpander - # from expanders.sensedisambiguation import SenseDisambiguation - # from expanders.thesaurus import Thesaurus - # from expanders.wordnet import Wordnet - # from expanders.word2vec import Word2Vec - from expanders.anchor import Anchor - # from expanders.glove import Glove - # from expanders.conceptnet import Conceptnet - # from expanders.relevancefeedback import RelevanceFeedback - # from expanders.stem import Stem # Stem expander is the wrapper for all stemmers as an expnader :) - # from stemmers.krovetz import KrovetzStemmer - # from stemmers.lovins import LovinsStemmer - # from stemmers.paicehusk import PaiceHuskStemmer - # from stemmers.porter import PorterStemmer - # from stemmers.porter2 import Porter2Stemmer - # from stemmers.sstemmer import SRemovalStemmer - # from stemmers.trunc4 import Trunc4Stemmer - # from stemmers.trunc5 import Trunc5Stemmer - from expanders.docluster import Docluster - from expanders.termluster import Termluster - from expanders.conceptluster import Conceptluster - - expanders = [AbstractQRefiner(), - # Thesaurus(), - # Wordnet(), - # Word2Vec('../pre/wiki-news-300d-1M.vec', topn=3), - # Glove('../pre/glove.6B.300d', topn=3), - # SenseDisambiguation(), - # Conceptnet(), - # Thesaurus(replace=True), - # Wordnet(replace=True), - # Word2Vec('../pre/wiki-news-300d-1M.vec', topn=3, replace=True), - # Glove('../pre/glove.6B.300d', topn=3, replace=True), - # SenseDisambiguation(replace=True), - # Conceptnet(replace=True), - # Stem(KrovetzStemmer(jarfile='stemmers/kstem-3.4.jar')), - # Stem(LovinsStemmer()), - # Stem(PaiceHuskStemmer()), - # Stem(PorterStemmer()), - # Stem(Porter2Stemmer()), - # Stem(SRemovalStemmer()), - # Stem(Trunc4Stemmer()), - # Stem(Trunc5Stemmer()), - # RelevanceFeedback(ranker='bm25', prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt',anserini='../anserini/',index='../ds/robust04/index-robust04-20191213'), - # Docluster(ranker='bm25', prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt',anserini='../anserini/', index='../ds/robust04/index-robust04-20191213'), - # Termluster(ranker='bm25', prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt',anserini='../anserini/', index='../ds/robust04/index-robust04-20191213'), - # Conceptluster(ranker='bm25', prels='./output/robust04/topics.robust04.abstractqueryexpansion.bm25.txt', anserini='../anserini/', index='../ds/robust04/index-robust04-20191213'), - # Anchor(anchorfile='../pre/anchor_text_en_sample.ttl', vectorfile='../pre/wiki-anchor-text-en-ttl-300d-sample.vec', topn=3), - # Anchor(anchorfile='../pre/anchor_text_en_sample.ttl', vectorfile='../pre/wiki-anchor-text-en-ttl-300d-sample.vec', topn=3, replace=True) - ] - for expander in expanders: expander.write_expanded_queries('../ds/robust04/topics.robust04.txt', 'dummy.txt') - # expanders.write_expanded_queries('../ds/gov2/topics.terabyte05.751-800.txt', 'dummy') - # expanders.write_expanded_queries('../ds/clueweb09b/topics.web.101-150.txt', 'dummy') - # expanders.write_expanded_queries('../ds/clueweb12b13/topics.web.201-250.txt', 'dummy') + print(qe.get_refined_query('International Crime Organization')) diff --git a/src/refinement/refiners/backtranslation.py b/src/refinement/refiners/backtranslation.py index 98b4f9e..f905760 100644 --- a/src/refinement/refiners/backtranslation.py +++ b/src/refinement/refiners/backtranslation.py @@ -1,12 +1,6 @@ from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM -from sentence_transformers import SentenceTransformer -from scipy.spatial.distance import cosine -import sys - -sys.path.extend(['../refinement']) - -from refiners.abstractqrefiner import AbstractQRefiner -import param +from src.refinement.refiners.abstractqrefiner import AbstractQRefiner +from src.refinement.refiner_param import backtranslation class BackTranslation(AbstractQRefiner): @@ -15,35 +9,39 @@ def __init__(self, tgt): # Initialization self.tgt = tgt - model = AutoModelForSeq2SeqLM.from_pretrained(param.backtranslation['model_card']) - tokenizer = AutoTokenizer.from_pretrained(param.backtranslation['model_card']) - # translator = pipeline("translation", model=model, tokenizer=tokenizer, src_lang='eng_Latn', tgt_lang='pes_Arab', max_length=512, device='cpu') + model = AutoModelForSeq2SeqLM.from_pretrained(backtranslation['model_card']) + tokenizer = AutoTokenizer.from_pretrained(backtranslation['model_card']) # Translation models - self.translator = pipeline("translation", model=model, tokenizer=tokenizer, src_lang=param.backtranslation['src_lng'], tgt_lang=self.tgt, max_length=param.backtranslation['max_length'], device=param.backtranslation['device']) - self.back_translator = pipeline("translation", model=model, tokenizer=tokenizer, src_lang=self.tgt, tgt_lang=param.backtranslation['src_lng'], max_length=param.backtranslation['max_length'], device=param.backtranslation['device']) + self.translator = pipeline("translation", model=model, tokenizer=tokenizer, src_lang=backtranslation['src_lng'], tgt_lang=self.tgt, max_length=backtranslation['max_length'], device=backtranslation['device']) + self.back_translator = pipeline("translation", model=model, tokenizer=tokenizer, src_lang=self.tgt, tgt_lang=backtranslation['src_lng'], max_length=backtranslation['max_length'], device=backtranslation['device']) # Model use for calculating semsim - self.transformer_model = SentenceTransformer(param.backtranslation['transformer_model']) - # Generate the backtranslated of the original query then calculates the difference of the two queries - def get_refined_query(self, q, args=None): - translated_query = self.translator(q) + ''' + Generates the backtranslated query then calculates the semantic similarity of the two queries + ''' + def get_refined_query(self, query, args=None): + translated_query = self.translator(query.q) back_translated_query = self.back_translator(translated_query[0]['translation_text']) - - score = self.semsim(q, back_translated_query[0]['translation_text']) - return super().get_expanded_query(back_translated_query[0]['translation_text'], [score]) + return back_translated_query[0]['translation_text'] # return super().get_expanded_query(q, [0]) - # Returns the name of the model ('backtranslation) with name of the target language - # Example: 'backtranslation_fra_latn' + def get_refined_query_batch(self, queries, args=None): + try: + translated_queries = self.translator([query.q for query in queries]) + back_translated_queries = self.back_translator([tq_['translation_text'] for tq_ in translated_queries]) + q_s = [q_['translation_text'] for q_ in back_translated_queries] + except: + q_s = [None] * len(queries) + return q_s + + ''' + Returns the name of the model ('backtranslation) with name of the target language + Example: 'backtranslation_fra_latn' + ''' def get_model_name(self): return super().get_model_name() + '_' + self.tgt.lower() - # Calculate the difference between the original and back-translated query - def semsim(self, q1, q2): - me, you = self.transformer_model.encode([q1, q2]) - return 1 - cosine(me, you) - if __name__ == "__main__": qe = BackTranslation() diff --git a/src/refinement/refiners/stem.py b/src/refinement/refiners/stem.py index 05ebc8e..6f3ddbf 100644 --- a/src/refinement/refiners/stem.py +++ b/src/refinement/refiners/stem.py @@ -1,8 +1,8 @@ import sys sys.path.extend(['../refinement']) -from refiners.abstractqrefiner import AbstractQRefiner -from stemmers.abstractstemmer import AbstractStemmer +from src.refinement.refiners.abstractqrefiner import AbstractQRefiner +from src.refinement.stemmers.abstractstemmer import AbstractStemmer class Stem(AbstractQRefiner): def __init__(self, stemmer:AbstractStemmer): AbstractQRefiner.__init__(self, replace=False) @@ -15,7 +15,7 @@ def get_refined_query(self, q, args=None): return super().get_refined_query(self.stemmer.stem_query(q)) if __name__ == "__main__": - from refinement.stemmers.krovetz import KrovetzStemmer + from src.refinement.stemmers.krovetz import KrovetzStemmer qe = Stem(KrovetzStemmer(jarfile='stemmers/kstem-3.4.jar')) print(qe.get_model_name()) print(qe.get_refined_query('International Crime Organization')) diff --git a/src/refinement/stemmers/abstractstemmer.py b/src/refinement/stemmers/abstractstemmer.py index 91d21c5..db71a76 100644 --- a/src/refinement/stemmers/abstractstemmer.py +++ b/src/refinement/stemmers/abstractstemmer.py @@ -6,7 +6,7 @@ import re import sys -from cmn import utils +from src.refinement import utils class AbstractStemmer(object): def __init__(self): super(AbstractStemmer, self).__init__() diff --git a/src/refinement/utils.py b/src/refinement/utils.py index 9391ad9..534f043 100644 --- a/src/refinement/utils.py +++ b/src/refinement/utils.py @@ -28,13 +28,7 @@ def valid(word): return False def clean(str): - result = [0] * len(str) - for i in range(len(str)): - ch = str[i] - if ch.isalpha(): - result[i] = ch - else: - result[i] = ' ' + result = [ch if ch.isalpha() else ' ' for ch in str] return ''.join(result) def insert_row(df, idx, row): @@ -136,4 +130,12 @@ def _redirect_stdout(to): finally: _redirect_stdout(to=old_stdout) # restore stdout. # buffering and flags such as - # CLOEXEC may be different \ No newline at end of file + # CLOEXEC may be different + + +def hex_to_ansi(hex_color_code): + hex_color_code = hex_color_code.lstrip('#') + red = int(hex_color_code[0:2], 16) + green = int(hex_color_code[2:4], 16) + blue = int(hex_color_code[4:6], 16) + return f'\033[38;2;{red};{green};{blue}m'