|
|
| |
| |
| |
| |
|
|
| import os |
| import itertools |
|
|
| from colbert.evaluation.loaders import load_collection |
| from colbert.infra.run import Run |
|
|
|
|
| class Collection: |
| def __init__(self, path=None, data=None): |
| self.path = path |
| self.data = data or self._load_file(path) |
|
|
| def __iter__(self): |
| |
| return self.data.__iter__() |
|
|
| def __getitem__(self, item): |
| |
| return self.data[item] |
|
|
| def __len__(self): |
| |
| return len(self.data) |
|
|
| def _load_file(self, path): |
| self.path = path |
| return self._load_tsv(path) if path.endswith('.tsv') else self._load_jsonl(path) |
|
|
| def _load_tsv(self, path): |
| return load_collection(path) |
|
|
| def _load_jsonl(self, path): |
| raise NotImplementedError() |
|
|
| def provenance(self): |
| return self.path |
| |
| def toDict(self): |
| return {'provenance': self.provenance()} |
|
|
| def save(self, new_path): |
| assert new_path.endswith('.tsv'), "TODO: Support .json[l] too." |
| assert not os.path.exists(new_path), new_path |
|
|
| with Run().open(new_path, 'w') as f: |
| |
| for pid, content in enumerate(self.data): |
| content = f'{pid}\t{content}\n' |
| f.write(content) |
| |
| return f.name |
|
|
| def enumerate(self, rank): |
| for _, offset, passages in self.enumerate_batches(rank=rank): |
| for idx, passage in enumerate(passages): |
| yield (offset + idx, passage) |
|
|
| def enumerate_batches(self, rank, chunksize=None): |
| assert rank is not None, "TODO: Add support for the rank=None case." |
|
|
| chunksize = chunksize or self.get_chunksize() |
|
|
| offset = 0 |
| iterator = iter(self) |
|
|
| for chunk_idx, owner in enumerate(itertools.cycle(range(Run().nranks))): |
| L = [line for _, line in zip(range(chunksize), iterator)] |
|
|
| if len(L) > 0 and owner == rank: |
| yield (chunk_idx, offset, L) |
|
|
| offset += len(L) |
|
|
| if len(L) < chunksize: |
| return |
| |
| def get_chunksize(self): |
| return min(25_000, 1 + len(self) // Run().nranks) |
|
|
| @classmethod |
| |
| def cast(cls, obj): |
| if type(obj) is str: |
| return cls(path=obj) |
|
|
| if type(obj) is list: |
| return cls(data=obj) |
|
|
| if type(obj) is cls: |
| return obj |
|
|
| assert False, f"obj has type {type(obj)} which is not compatible with cast()" |
|
|
|
|
| |
|
|