pepe-cli 1.0.3__tar.gz → 1.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/MANIFEST.in +6 -0
- {pepe_cli-1.0.3/src/pepe_cli.egg-info → pepe_cli-1.0.4}/PKG-INFO +1 -1
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe/__init__.py +1 -1
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe/embedders/custom_embedder.py +6 -106
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe/embedders/huggingface_embedder.py +171 -4
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe/utils.py +155 -26
- {pepe_cli-1.0.3 → pepe_cli-1.0.4/src/pepe_cli.egg-info}/PKG-INFO +1 -1
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/tests/test_run.py +1 -1
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/LICENSE +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/README.md +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/custom_model/create_example_custom_model.py +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/custom_model/example_protein_model/config.json +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/custom_model/example_protein_model/pytorch_model.pt +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/custom_model/example_protein_model/special_tokens_map.json +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/custom_model/example_protein_model/tokenizer_config.json +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/custom_model/example_protein_model/vocab.json +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/custom_model/example_protein_model/vocab.txt +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/custom_model/example_sequences.fasta +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/custom_model/example_substring.csv +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/embedding_options.md +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/model_selection.md +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/pyproject.toml +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/requirements.txt +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/setup.cfg +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/setup.py +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe/__main__.py +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe/embedders/__init__.py +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe/embedders/base_embedder.py +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe/embedders/esm_embedder.py +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe/model_selecter.py +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe/parse_arguments.py +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe_cli.egg-info/SOURCES.txt +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe_cli.egg-info/dependency_links.txt +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe_cli.egg-info/entry_points.txt +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe_cli.egg-info/requires.txt +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/pepe_cli.egg-info/top_level.txt +0 -0
- {pepe_cli-1.0.3 → pepe_cli-1.0.4}/src/tests/__init__.py +0 -0
|
@@ -8,3 +8,9 @@ recursive-exclude * __pycache__
|
|
|
8
8
|
recursive-exclude * *.py[co]
|
|
9
9
|
recursive-exclude * *.so
|
|
10
10
|
recursive-exclude * .DS_Store
|
|
11
|
+
recursive-exclude .github *
|
|
12
|
+
recursive-exclude .git *
|
|
13
|
+
recursive-exclude .venv *
|
|
14
|
+
recursive-exclude * .pytest_cache
|
|
15
|
+
recursive-exclude * .coverage
|
|
16
|
+
exclude .gitignore
|
|
@@ -53,8 +53,9 @@ class CustomEmbedder(BaseEmbedder):
|
|
|
53
53
|
|
|
54
54
|
# Set up tokenizer and validate tokens
|
|
55
55
|
self.valid_tokens = self._get_valid_tokens()
|
|
56
|
+
self.bracket_type = pepe.utils.get_bracket_type(self.tokenizer)
|
|
56
57
|
pepe.utils.check_input_tokens(
|
|
57
|
-
self.valid_tokens, self.sequences, self.model_name
|
|
58
|
+
self.valid_tokens, self.sequences, self.model_name,
|
|
58
59
|
)
|
|
59
60
|
|
|
60
61
|
# Set up special tokens
|
|
@@ -65,7 +66,7 @@ class CustomEmbedder(BaseEmbedder):
|
|
|
65
66
|
|
|
66
67
|
# Load and tokenize data
|
|
67
68
|
self.data_loader, self.max_length = self._load_data(
|
|
68
|
-
self.sequences, self.substring_dict
|
|
69
|
+
self.sequences, self.substring_dict, self.bracket_type
|
|
69
70
|
)
|
|
70
71
|
|
|
71
72
|
# Initialize output objects
|
|
@@ -297,13 +298,14 @@ class CustomEmbedder(BaseEmbedder):
|
|
|
297
298
|
layers = [(i + self.num_layers + 1) % (self.num_layers + 1) for i in layers]
|
|
298
299
|
return layers
|
|
299
300
|
|
|
300
|
-
def _load_data(self, sequences, substring_dict=None):
|
|
301
|
+
def _load_data(self, sequences, substring_dict=None, bracket_type=None):
|
|
301
302
|
"""Load and tokenize sequences."""
|
|
302
303
|
# Create dataset
|
|
303
|
-
dataset = CustomDataset(
|
|
304
|
+
dataset = pepe.utils.CustomDataset(
|
|
304
305
|
sequences,
|
|
305
306
|
substring_dict,
|
|
306
307
|
self.context,
|
|
308
|
+
bracket_type,
|
|
307
309
|
self.tokenizer,
|
|
308
310
|
self.max_length,
|
|
309
311
|
add_special_tokens=not self.disable_special_tokens,
|
|
@@ -543,105 +545,3 @@ class DefaultProteinTokenizer:
|
|
|
543
545
|
}
|
|
544
546
|
|
|
545
547
|
return tokenized[0] if len(tokenized) == 1 else tokenized
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
class CustomDataset(pepe.utils.SequenceDictDataset):
|
|
549
|
-
"""
|
|
550
|
-
Dataset class for custom embedder.
|
|
551
|
-
"""
|
|
552
|
-
|
|
553
|
-
def __init__(
|
|
554
|
-
self,
|
|
555
|
-
sequences,
|
|
556
|
-
substring_dict,
|
|
557
|
-
context,
|
|
558
|
-
tokenizer,
|
|
559
|
-
max_length,
|
|
560
|
-
add_special_tokens=True,
|
|
561
|
-
):
|
|
562
|
-
super().__init__(sequences, substring_dict, context)
|
|
563
|
-
self.tokenizer = tokenizer
|
|
564
|
-
self.max_length = max_length
|
|
565
|
-
self.add_special_tokens = add_special_tokens
|
|
566
|
-
self.pad_token_id = getattr(tokenizer, "pad_token_id", 0)
|
|
567
|
-
|
|
568
|
-
# Encode sequences
|
|
569
|
-
self.encoded_data = self._encode_sequences(
|
|
570
|
-
self.data, tokenizer, max_length, add_special_tokens
|
|
571
|
-
)
|
|
572
|
-
|
|
573
|
-
# Handle substring sequences if provided
|
|
574
|
-
if self.substring_dict:
|
|
575
|
-
logger.info("Tokenizing substrings...")
|
|
576
|
-
self.encoded_substring_data = self._encode_sequences(
|
|
577
|
-
self.filtered_substring_data,
|
|
578
|
-
tokenizer,
|
|
579
|
-
"max_length",
|
|
580
|
-
add_special_tokens=False,
|
|
581
|
-
)
|
|
582
|
-
self.substring_masks = self._get_substring_masks()
|
|
583
|
-
|
|
584
|
-
def _encode_sequences(self, data, tokenizer, max_length, add_special_tokens):
|
|
585
|
-
"""Encode sequences using the tokenizer."""
|
|
586
|
-
labels, strs = zip(*data)
|
|
587
|
-
|
|
588
|
-
# Convert max_length to int if needed
|
|
589
|
-
if max_length == "max_length":
|
|
590
|
-
max_length = max(len(s) for s in strs) + (2 if add_special_tokens else 0)
|
|
591
|
-
|
|
592
|
-
encoded_sequences = []
|
|
593
|
-
for label, seq in zip(labels, strs):
|
|
594
|
-
# Tokenize the sequence
|
|
595
|
-
tokens = tokenizer(
|
|
596
|
-
seq,
|
|
597
|
-
truncation=True,
|
|
598
|
-
padding="max_length",
|
|
599
|
-
max_length=max_length,
|
|
600
|
-
add_special_tokens=add_special_tokens,
|
|
601
|
-
return_tensors="pt",
|
|
602
|
-
)
|
|
603
|
-
|
|
604
|
-
encoded_sequences.append(
|
|
605
|
-
(
|
|
606
|
-
label,
|
|
607
|
-
seq,
|
|
608
|
-
tokens["input_ids"].squeeze(0),
|
|
609
|
-
tokens["attention_mask"].squeeze(0),
|
|
610
|
-
)
|
|
611
|
-
)
|
|
612
|
-
|
|
613
|
-
return encoded_sequences
|
|
614
|
-
|
|
615
|
-
def get_max_encoded_length(self):
|
|
616
|
-
"""Get maximum encoded sequence length."""
|
|
617
|
-
return max(len(toks) for _, _, toks, _ in self.encoded_data)
|
|
618
|
-
|
|
619
|
-
def safe_collate(self, batch):
|
|
620
|
-
"""Collate function for data loader."""
|
|
621
|
-
if self.substring_dict:
|
|
622
|
-
labels, seqs, toks, attn_masks, substring_masks = zip(*batch)
|
|
623
|
-
return (
|
|
624
|
-
list(labels),
|
|
625
|
-
list(seqs),
|
|
626
|
-
torch.stack(toks),
|
|
627
|
-
torch.stack(attn_masks),
|
|
628
|
-
torch.stack(substring_masks),
|
|
629
|
-
)
|
|
630
|
-
else:
|
|
631
|
-
labels, seqs, toks, attn_masks = zip(*batch)
|
|
632
|
-
return (
|
|
633
|
-
list(labels),
|
|
634
|
-
list(seqs),
|
|
635
|
-
torch.stack(toks),
|
|
636
|
-
torch.stack(attn_masks),
|
|
637
|
-
None,
|
|
638
|
-
)
|
|
639
|
-
|
|
640
|
-
def __getitem__(self, idx):
|
|
641
|
-
"""Get item from dataset."""
|
|
642
|
-
labels, seqs, toks, attn_mask = self.encoded_data[idx]
|
|
643
|
-
if self.substring_dict:
|
|
644
|
-
substring_masks = self.substring_masks[idx]
|
|
645
|
-
return labels, seqs, toks, attn_mask, substring_masks
|
|
646
|
-
else:
|
|
647
|
-
return labels, seqs, toks, attn_mask
|
|
@@ -14,6 +14,7 @@ def _import_transformers():
|
|
|
14
14
|
from transformers.models.roformer.modeling_roformer import (
|
|
15
15
|
RoFormerSinusoidalPositionalEmbedding,
|
|
16
16
|
)
|
|
17
|
+
from transformers import AutoModel, AutoTokenizer, AutoModelForCausalLM
|
|
17
18
|
|
|
18
19
|
return (
|
|
19
20
|
T5EncoderModel,
|
|
@@ -21,6 +22,9 @@ def _import_transformers():
|
|
|
21
22
|
RoFormerTokenizer,
|
|
22
23
|
RoFormerModel,
|
|
23
24
|
RoFormerSinusoidalPositionalEmbedding,
|
|
25
|
+
AutoModel,
|
|
26
|
+
AutoTokenizer,
|
|
27
|
+
AutoModelForCausalLM,
|
|
24
28
|
)
|
|
25
29
|
except ImportError as e:
|
|
26
30
|
logger.error(f"Failed to import transformers: {e}")
|
|
@@ -63,13 +67,14 @@ class HuggingfaceEmbedder(BaseEmbedder):
|
|
|
63
67
|
]
|
|
64
68
|
return layers
|
|
65
69
|
|
|
66
|
-
def _load_data(self, sequences, substring_dict):
|
|
70
|
+
def _load_data(self, sequences, substring_dict, bracket_type):
|
|
67
71
|
"""Tokenize sequences and create a DataLoader."""
|
|
68
72
|
# Tokenize sequences
|
|
69
73
|
dataset = pepe.utils.HuggingFaceDataset(
|
|
70
74
|
sequences,
|
|
71
75
|
substring_dict,
|
|
72
76
|
self.context,
|
|
77
|
+
bracket_type,
|
|
73
78
|
self.tokenizer, # type: ignore
|
|
74
79
|
self.max_length,
|
|
75
80
|
add_special_tokens=not self.disable_special_tokens,
|
|
@@ -139,6 +144,7 @@ class Antiberta2Embedder(HuggingfaceEmbedder):
|
|
|
139
144
|
self.embedding_size,
|
|
140
145
|
) = self._initialize_model(self.model_link)
|
|
141
146
|
self.valid_tokens = set(self.tokenizer.get_vocab().keys())
|
|
147
|
+
self.bracket_type = pepe.utils.get_bracket_type(self.tokenizer)
|
|
142
148
|
pepe.utils.check_input_tokens(
|
|
143
149
|
self.valid_tokens, self.sequences, self.model_name
|
|
144
150
|
)
|
|
@@ -147,7 +153,7 @@ class Antiberta2Embedder(HuggingfaceEmbedder):
|
|
|
147
153
|
)
|
|
148
154
|
self.layers = self._load_layers(self.layers)
|
|
149
155
|
self.data_loader, self.max_length = self._load_data(
|
|
150
|
-
self.sequences, self.substring_dict
|
|
156
|
+
self.sequences, self.substring_dict, self.bracket_type
|
|
151
157
|
)
|
|
152
158
|
self._set_output_objects()
|
|
153
159
|
assert self.max_length <= 256, "AntiBERTa2 only supports max_length <= 256"
|
|
@@ -168,6 +174,9 @@ class Antiberta2Embedder(HuggingfaceEmbedder):
|
|
|
168
174
|
RoFormerTokenizer,
|
|
169
175
|
RoFormerModel,
|
|
170
176
|
RoFormerSinusoidalPositionalEmbedding,
|
|
177
|
+
AutoModel,
|
|
178
|
+
AutoTokenizer,
|
|
179
|
+
AutoModelForCausalLM,
|
|
171
180
|
) = _import_transformers()
|
|
172
181
|
|
|
173
182
|
tokenizer = RoFormerTokenizer.from_pretrained(model_link, use_fast=True)
|
|
@@ -192,15 +201,16 @@ class T5Embedder(HuggingfaceEmbedder):
|
|
|
192
201
|
self.embedding_size,
|
|
193
202
|
) = self._initialize_model(self.model_link)
|
|
194
203
|
self.valid_tokens = self.get_valid_tokens()
|
|
204
|
+
self.bracket_type = pepe.utils.get_bracket_type(self.tokenizer)
|
|
195
205
|
pepe.utils.check_input_tokens(
|
|
196
|
-
self.valid_tokens, self.sequences, self.model_name
|
|
206
|
+
self.valid_tokens, self.sequences, self.model_name, self.bracket_type
|
|
197
207
|
)
|
|
198
208
|
self.special_tokens = torch.tensor(
|
|
199
209
|
self.tokenizer.all_special_ids, device=self.device, dtype=torch.int8
|
|
200
210
|
)
|
|
201
211
|
self.layers = self._load_layers(self.layers)
|
|
202
212
|
self.data_loader, self.max_length = self._load_data(
|
|
203
|
-
self.sequences, self.substring_dict
|
|
213
|
+
self.sequences, self.substring_dict, self.bracket_type
|
|
204
214
|
)
|
|
205
215
|
self._set_output_objects()
|
|
206
216
|
|
|
@@ -228,6 +238,9 @@ class T5Embedder(HuggingfaceEmbedder):
|
|
|
228
238
|
RoFormerTokenizer,
|
|
229
239
|
RoFormerModel,
|
|
230
240
|
RoFormerSinusoidalPositionalEmbedding,
|
|
241
|
+
AutoModel,
|
|
242
|
+
AutoTokenizer,
|
|
243
|
+
AutoModelForCausalLM,
|
|
231
244
|
) = _import_transformers()
|
|
232
245
|
|
|
233
246
|
tokenizer = T5Tokenizer.from_pretrained(model_link, use_fast=True)
|
|
@@ -237,3 +250,157 @@ class T5Embedder(HuggingfaceEmbedder):
|
|
|
237
250
|
num_layers = model.config.num_layers
|
|
238
251
|
embedding_size = model.config.hidden_size
|
|
239
252
|
return model, tokenizer, num_heads, num_layers, embedding_size
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class GenericHuggingFaceEmbedder(HuggingfaceEmbedder):
|
|
256
|
+
"""Generic HuggingFace embedder that can handle models with unknown architectures using AutoModel and AutoTokenizer."""
|
|
257
|
+
|
|
258
|
+
def __init__(self, args):
|
|
259
|
+
super().__init__(args)
|
|
260
|
+
self.sequences = pepe.utils.fasta_to_dict(args.fasta_path)
|
|
261
|
+
self.num_sequences = len(self.sequences)
|
|
262
|
+
(
|
|
263
|
+
self.model,
|
|
264
|
+
self.tokenizer,
|
|
265
|
+
self.num_heads,
|
|
266
|
+
self.num_layers,
|
|
267
|
+
self.embedding_size,
|
|
268
|
+
) = self._initialize_model(self.model_link)
|
|
269
|
+
self.valid_tokens = self._get_valid_tokens()
|
|
270
|
+
self.bracket_type = pepe.utils.get_bracket_type(self.tokenizer)
|
|
271
|
+
pepe.utils.check_input_tokens(
|
|
272
|
+
self.valid_tokens, self.sequences, self.model_name
|
|
273
|
+
)
|
|
274
|
+
self.special_tokens = torch.tensor(
|
|
275
|
+
self.tokenizer.all_special_ids, device=self.device, dtype=torch.int8
|
|
276
|
+
)
|
|
277
|
+
self.layers = self._load_layers(self.layers)
|
|
278
|
+
self.data_loader, self.max_length = self._load_data(
|
|
279
|
+
self.sequences, self.substring_dict, self.bracket_type
|
|
280
|
+
)
|
|
281
|
+
self._set_output_objects()
|
|
282
|
+
|
|
283
|
+
def _get_valid_tokens(self):
|
|
284
|
+
"""Get valid tokens from the tokenizer."""
|
|
285
|
+
if hasattr(self.tokenizer, "get_vocab"):
|
|
286
|
+
vocab = self.tokenizer.get_vocab()
|
|
287
|
+
# Handle different tokenizer types
|
|
288
|
+
if hasattr(self.tokenizer, "decoder") and self.tokenizer.decoder:
|
|
289
|
+
# T5-style tokenizer
|
|
290
|
+
valid_tokens = set(
|
|
291
|
+
k[1:] if k.startswith("▁") else k for k in vocab.keys()
|
|
292
|
+
)
|
|
293
|
+
else:
|
|
294
|
+
# Standard tokenizer
|
|
295
|
+
valid_tokens = set(vocab.keys())
|
|
296
|
+
return valid_tokens
|
|
297
|
+
return set()
|
|
298
|
+
|
|
299
|
+
def _initialize_model(self, model_link):
|
|
300
|
+
"""Initialize the model, tokenizer, and device using AutoModel and AutoTokenizer."""
|
|
301
|
+
if torch.cuda.is_available() and self.device == "cuda":
|
|
302
|
+
device = torch.device("cuda")
|
|
303
|
+
logger.info("Transferred model to GPU")
|
|
304
|
+
else:
|
|
305
|
+
device = torch.device("cpu")
|
|
306
|
+
logger.info("No GPU available, using CPU")
|
|
307
|
+
|
|
308
|
+
# Lazy import transformers components
|
|
309
|
+
(
|
|
310
|
+
T5EncoderModel,
|
|
311
|
+
T5Tokenizer,
|
|
312
|
+
RoFormerTokenizer,
|
|
313
|
+
RoFormerModel,
|
|
314
|
+
RoFormerSinusoidalPositionalEmbedding,
|
|
315
|
+
AutoModel,
|
|
316
|
+
AutoTokenizer,
|
|
317
|
+
AutoModelForCausalLM,
|
|
318
|
+
) = _import_transformers()
|
|
319
|
+
|
|
320
|
+
# For models that commonly require custom code, use trust_remote_code=True immediately
|
|
321
|
+
requires_custom_code = any(
|
|
322
|
+
pattern in model_link.lower()
|
|
323
|
+
for pattern in ["progen", "protgpt", "esm-fold", "esmfold", "alphafold"]
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
if requires_custom_code:
|
|
327
|
+
tokenizer = AutoTokenizer.from_pretrained(
|
|
328
|
+
model_link, use_fast=True, trust_remote_code=True
|
|
329
|
+
)
|
|
330
|
+
try:
|
|
331
|
+
model = AutoModel.from_pretrained(
|
|
332
|
+
model_link, trust_remote_code=True
|
|
333
|
+
).to(device)
|
|
334
|
+
except ValueError as model_error:
|
|
335
|
+
# If AutoModel fails, try AutoModelForCausalLM
|
|
336
|
+
model = AutoModelForCausalLM.from_pretrained(
|
|
337
|
+
model_link, trust_remote_code=True
|
|
338
|
+
).to(device)
|
|
339
|
+
else:
|
|
340
|
+
# Try without trust_remote_code first, then with it if needed
|
|
341
|
+
try:
|
|
342
|
+
tokenizer = AutoTokenizer.from_pretrained(model_link, use_fast=True)
|
|
343
|
+
try:
|
|
344
|
+
model = AutoModel.from_pretrained(model_link).to(device)
|
|
345
|
+
except ValueError as model_error:
|
|
346
|
+
# If AutoModel fails, try AutoModelForCausalLM
|
|
347
|
+
model = AutoModelForCausalLM.from_pretrained(model_link).to(device)
|
|
348
|
+
except (OSError, ValueError) as e:
|
|
349
|
+
# If the model requires custom code, try with trust_remote_code=True
|
|
350
|
+
if (
|
|
351
|
+
"trust_remote_code" in str(e).lower()
|
|
352
|
+
or "custom code" in str(e).lower()
|
|
353
|
+
):
|
|
354
|
+
tokenizer = AutoTokenizer.from_pretrained(
|
|
355
|
+
model_link, use_fast=True, trust_remote_code=True
|
|
356
|
+
)
|
|
357
|
+
try:
|
|
358
|
+
model = AutoModel.from_pretrained(
|
|
359
|
+
model_link, trust_remote_code=True
|
|
360
|
+
).to(device)
|
|
361
|
+
except ValueError as model_error:
|
|
362
|
+
# If AutoModel fails, try AutoModelForCausalLM
|
|
363
|
+
model = AutoModelForCausalLM.from_pretrained(
|
|
364
|
+
model_link, trust_remote_code=True
|
|
365
|
+
).to(device)
|
|
366
|
+
else:
|
|
367
|
+
raise
|
|
368
|
+
|
|
369
|
+
# Handle tokenizer padding token
|
|
370
|
+
if tokenizer.pad_token is None:
|
|
371
|
+
if tokenizer.eos_token is not None:
|
|
372
|
+
tokenizer.pad_token = tokenizer.eos_token
|
|
373
|
+
elif tokenizer.unk_token is not None:
|
|
374
|
+
tokenizer.pad_token = tokenizer.unk_token
|
|
375
|
+
else:
|
|
376
|
+
# Add a special padding token
|
|
377
|
+
tokenizer.add_special_tokens({"pad_token": "[PAD]"})
|
|
378
|
+
model.resize_token_embeddings(len(tokenizer))
|
|
379
|
+
|
|
380
|
+
model.eval()
|
|
381
|
+
|
|
382
|
+
# Get model configuration
|
|
383
|
+
config = model.config
|
|
384
|
+
num_heads = getattr(
|
|
385
|
+
config,
|
|
386
|
+
"num_attention_heads",
|
|
387
|
+
getattr(config, "num_heads", getattr(config, "n_head", 12)),
|
|
388
|
+
)
|
|
389
|
+
num_layers = getattr(
|
|
390
|
+
config,
|
|
391
|
+
"num_hidden_layers",
|
|
392
|
+
getattr(config, "num_layers", getattr(config, "n_layer", 12)),
|
|
393
|
+
)
|
|
394
|
+
embedding_size = getattr(
|
|
395
|
+
config,
|
|
396
|
+
"hidden_size",
|
|
397
|
+
getattr(config, "d_model", getattr(config, "embed_dim", 768)),
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
logger.info(f"Loaded generic HuggingFace model: {model_link}")
|
|
401
|
+
logger.info(f"Model type: {config.model_type}")
|
|
402
|
+
logger.info(
|
|
403
|
+
f"Number of heads: {num_heads}, layers: {num_layers}, embedding size: {embedding_size}"
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
return model, tokenizer, num_heads, num_layers, embedding_size
|
|
@@ -7,7 +7,7 @@ import time
|
|
|
7
7
|
import gc
|
|
8
8
|
import os
|
|
9
9
|
import json
|
|
10
|
-
from transformers import RoFormerTokenizer
|
|
10
|
+
from transformers import RoFormerTokenizer, T5Tokenizer
|
|
11
11
|
import threading, queue
|
|
12
12
|
from alive_progress import alive_bar
|
|
13
13
|
import shutil
|
|
@@ -43,7 +43,7 @@ class TokenBudgetBatchSampler:
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
class SequenceDictDataset(Dataset):
|
|
46
|
-
def __init__(self, sequences, substring_dict, context):
|
|
46
|
+
def __init__(self, sequences, substring_dict, context, bracket_type = "square"):
|
|
47
47
|
self.data = list(sequences.items()) # (label, seq)
|
|
48
48
|
if substring_dict:
|
|
49
49
|
self.substring_dict = substring_dict
|
|
@@ -53,7 +53,7 @@ class SequenceDictDataset(Dataset):
|
|
|
53
53
|
self.substring_dict = None
|
|
54
54
|
self.context = None
|
|
55
55
|
self.filtered_substring_data = None
|
|
56
|
-
|
|
56
|
+
self.bracket_type = bracket_type
|
|
57
57
|
|
|
58
58
|
def __getitem__(self, idx):
|
|
59
59
|
return self.data[idx]
|
|
@@ -128,13 +128,15 @@ class HuggingFaceDataset(SequenceDictDataset):
|
|
|
128
128
|
sequences,
|
|
129
129
|
substring_dict,
|
|
130
130
|
context,
|
|
131
|
+
bracket_type,
|
|
131
132
|
tokenizer,
|
|
132
133
|
max_length,
|
|
133
134
|
add_special_tokens=True,
|
|
134
135
|
):
|
|
135
|
-
super().__init__(sequences, substring_dict, context)
|
|
136
|
+
super().__init__(sequences, substring_dict, context, bracket_type)
|
|
137
|
+
|
|
136
138
|
self.encoded_data = self._encode_sequences(
|
|
137
|
-
self.data, tokenizer, max_length, add_special_tokens
|
|
139
|
+
self.data, tokenizer, max_length, add_special_tokens, gapped_sequences = True
|
|
138
140
|
) # (label, seq, toks, attention_mask)
|
|
139
141
|
self.pad_token_id = tokenizer.pad_token_type_id
|
|
140
142
|
if self.substring_dict:
|
|
@@ -144,16 +146,14 @@ class HuggingFaceDataset(SequenceDictDataset):
|
|
|
144
146
|
tokenizer,
|
|
145
147
|
"max_length",
|
|
146
148
|
add_special_tokens=False,
|
|
149
|
+
gapped_sequences=True
|
|
147
150
|
) # (label, seq, toks, attention_mask)
|
|
148
151
|
self.substring_masks = self._get_substring_masks()
|
|
149
152
|
|
|
150
|
-
def _encode_sequences(self, data, tokenizer, max_length, add_special_tokens):
|
|
153
|
+
def _encode_sequences(self, data, tokenizer, max_length, add_special_tokens, gapped_sequences = True):
|
|
151
154
|
labels, strs = zip(*data)
|
|
152
|
-
if
|
|
153
|
-
|
|
154
|
-
# for the input sequences
|
|
155
|
-
logger.info("Using RoFormerTokenizer, applying gap_sequence.")
|
|
156
|
-
strs = self._gap_sequence(strs)
|
|
155
|
+
if gapped_sequences:
|
|
156
|
+
strs = gap_sequence(strs, self.bracket_type)
|
|
157
157
|
max_token_length = max(len(seq.split(" ")) for seq in strs)
|
|
158
158
|
else:
|
|
159
159
|
# For other tokenizers, use the default tokenization
|
|
@@ -187,11 +187,6 @@ class HuggingFaceDataset(SequenceDictDataset):
|
|
|
187
187
|
attention_masks = torch.cat(loop_attention_mask, dim=0)
|
|
188
188
|
return list(zip(labels, strs, list(toks), list(attention_masks)))
|
|
189
189
|
|
|
190
|
-
def _gap_sequence(self, sequences: Sequence[str]) -> Sequence[str]:
|
|
191
|
-
"""Space-separated tokenization for RoFormer input."""
|
|
192
|
-
seqs = [" ".join(re.findall(r"\[.*?\]|.", sequence)) for sequence in sequences]
|
|
193
|
-
return seqs
|
|
194
|
-
|
|
195
190
|
def get_max_encoded_length(self):
|
|
196
191
|
return max(len(toks) for _, _, toks, _ in self.encoded_data)
|
|
197
192
|
|
|
@@ -319,21 +314,137 @@ class ESMDataset(SequenceDictDataset):
|
|
|
319
314
|
else:
|
|
320
315
|
return labels, seqs, toks, None, None
|
|
321
316
|
|
|
317
|
+
class CustomDataset(SequenceDictDataset):
|
|
318
|
+
"""
|
|
319
|
+
Dataset class for custom embedder.
|
|
320
|
+
"""
|
|
321
|
+
|
|
322
|
+
def __init__(
|
|
323
|
+
self,
|
|
324
|
+
sequences,
|
|
325
|
+
substring_dict,
|
|
326
|
+
context,
|
|
327
|
+
bracket_type,
|
|
328
|
+
tokenizer,
|
|
329
|
+
max_length,
|
|
330
|
+
add_special_tokens=True,
|
|
331
|
+
gapped_sequences = True,
|
|
332
|
+
):
|
|
333
|
+
super().__init__(sequences, substring_dict, context, bracket_type)
|
|
334
|
+
self.tokenizer = tokenizer
|
|
335
|
+
self.max_length = max_length
|
|
336
|
+
self.add_special_tokens = add_special_tokens
|
|
337
|
+
self.pad_token_id = getattr(tokenizer, "pad_token_id", 0)
|
|
338
|
+
self.gapped_sequences = gapped_sequences
|
|
339
|
+
self.bracket_type = bracket_type
|
|
340
|
+
|
|
341
|
+
# Encode sequences
|
|
342
|
+
self.encoded_data = self._encode_sequences(
|
|
343
|
+
self.data, tokenizer, max_length, add_special_tokens, self.gapped_sequences
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# Handle substring sequences if provided
|
|
347
|
+
if self.substring_dict:
|
|
348
|
+
logger.info("Tokenizing substrings...")
|
|
349
|
+
self.encoded_substring_data = self._encode_sequences(
|
|
350
|
+
self.filtered_substring_data,
|
|
351
|
+
tokenizer,
|
|
352
|
+
"max_length",
|
|
353
|
+
add_special_tokens=False,
|
|
354
|
+
)
|
|
355
|
+
self.substring_masks = self._get_substring_masks()
|
|
356
|
+
|
|
357
|
+
def _encode_sequences(self, data, tokenizer, max_length, add_special_tokens, gapped_sequences = True):
|
|
358
|
+
"""Encode sequences using the tokenizer."""
|
|
359
|
+
labels, strs = zip(*data)
|
|
360
|
+
|
|
361
|
+
if gapped_sequences:
|
|
362
|
+
strs = gap_sequence(strs, self.bracket_type)
|
|
363
|
+
max_token_length = max(len(seq.split(" ")) for seq in strs)
|
|
364
|
+
else:
|
|
365
|
+
# For other tokenizers, use the default tokenization
|
|
366
|
+
max_token_length = max(len(seq) for seq in strs)
|
|
367
|
+
|
|
368
|
+
# Convert max_length to int if needed
|
|
369
|
+
if max_length == "max_length":
|
|
370
|
+
max_token_length = max(len(s) for s in strs) + (2 if add_special_tokens else 0)
|
|
371
|
+
|
|
372
|
+
encoded_sequences = []
|
|
373
|
+
for label, seq in zip(labels, strs):
|
|
374
|
+
# Tokenize the sequence
|
|
375
|
+
tokens = tokenizer(
|
|
376
|
+
seq,
|
|
377
|
+
truncation=True,
|
|
378
|
+
padding="max_length",
|
|
379
|
+
max_length=max_token_length,
|
|
380
|
+
add_special_tokens=add_special_tokens,
|
|
381
|
+
return_tensors="pt",
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
encoded_sequences.append(
|
|
385
|
+
(
|
|
386
|
+
label,
|
|
387
|
+
seq,
|
|
388
|
+
tokens["input_ids"].squeeze(0),
|
|
389
|
+
tokens["attention_mask"].squeeze(0),
|
|
390
|
+
)
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
return encoded_sequences
|
|
394
|
+
|
|
395
|
+
def get_max_encoded_length(self):
|
|
396
|
+
"""Get maximum encoded sequence length."""
|
|
397
|
+
return max(len(toks) for _, _, toks, _ in self.encoded_data)
|
|
398
|
+
|
|
399
|
+
def safe_collate(self, batch):
|
|
400
|
+
"""Collate function for data loader."""
|
|
401
|
+
if self.substring_dict:
|
|
402
|
+
labels, seqs, toks, attn_masks, substring_masks = zip(*batch)
|
|
403
|
+
return (
|
|
404
|
+
list(labels),
|
|
405
|
+
list(seqs),
|
|
406
|
+
torch.stack(toks),
|
|
407
|
+
torch.stack(attn_masks),
|
|
408
|
+
torch.stack(substring_masks),
|
|
409
|
+
)
|
|
410
|
+
else:
|
|
411
|
+
labels, seqs, toks, attn_masks = zip(*batch)
|
|
412
|
+
return (
|
|
413
|
+
list(labels),
|
|
414
|
+
list(seqs),
|
|
415
|
+
torch.stack(toks),
|
|
416
|
+
torch.stack(attn_masks),
|
|
417
|
+
None,
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
def __getitem__(self, idx):
|
|
421
|
+
"""Get item from dataset."""
|
|
422
|
+
labels, seqs, toks, attn_mask = self.encoded_data[idx]
|
|
423
|
+
if self.substring_dict:
|
|
424
|
+
substring_masks = self.substring_masks[idx]
|
|
425
|
+
return labels, seqs, toks, attn_mask, substring_masks
|
|
426
|
+
else:
|
|
427
|
+
return labels, seqs, toks, attn_mask
|
|
428
|
+
|
|
429
|
+
def check_input_tokens(valid_tokens, sequences, model_name, bracket_type = "square"):
|
|
430
|
+
def __str_to_list(sequence, bracket_type = "square"):
|
|
431
|
+
if bracket_type == "square":
|
|
432
|
+
return re.findall(r"\[.*?\]|.", sequence)
|
|
433
|
+
elif bracket_type == "angle":
|
|
434
|
+
return re.findall(r"<.*?>|.", sequence)
|
|
435
|
+
else:
|
|
436
|
+
raise ValueError(f"Invalid bracket type: {bracket_type}")
|
|
322
437
|
|
|
323
|
-
def check_input_tokens(valid_tokens, sequences, model_name):
|
|
324
438
|
with alive_bar(
|
|
325
439
|
len(sequences), title="Checking input sequences for invalid tokens..."
|
|
326
440
|
) as bar:
|
|
327
441
|
for label, sequence in sequences.items():
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
), f"Antiberta2 does not support sequences longer than 256 tokens. Found {len(sequence)} tokens in sequence {label}."
|
|
442
|
+
sequence = __str_to_list(sequence, bracket_type)
|
|
443
|
+
if "antiberta" in model_name: # check for longest sequence
|
|
444
|
+
assert (
|
|
445
|
+
len(sequence) <= 256
|
|
446
|
+
), f"Antiberta2 does not support sequences longer than 256 tokens. Found {len(sequence)} tokens in sequence {label}."
|
|
334
447
|
|
|
335
|
-
else:
|
|
336
|
-
sequence = re.findall(r"<.*?>|.", sequence)
|
|
337
448
|
if not set(sequence).issubset(valid_tokens):
|
|
338
449
|
raise ValueError(
|
|
339
450
|
f"Invalid tokens found in sequence {label}: {set(sequence) - set(valid_tokens)}"
|
|
@@ -365,7 +476,25 @@ def fasta_to_dict(fasta_path):
|
|
|
365
476
|
flush()
|
|
366
477
|
|
|
367
478
|
return seq_dict
|
|
368
|
-
|
|
479
|
+
def get_bracket_type(tokenizer):
|
|
480
|
+
try:
|
|
481
|
+
special_token_bracket = tokenizer.special_tokens_map["additional_special_tokens"][0][0]
|
|
482
|
+
except KeyError:
|
|
483
|
+
special_token_bracket = tokenizer.all_special_tokens[0][0]
|
|
484
|
+
if special_token_bracket == "<":
|
|
485
|
+
return "angle"
|
|
486
|
+
elif special_token_bracket == "[":
|
|
487
|
+
return "square"
|
|
488
|
+
else:
|
|
489
|
+
raise ValueError(f"Invalid special token bracket: {special_token_bracket}")
|
|
490
|
+
def gap_sequence(sequences: Sequence[str], bracket_type = "square") -> Sequence[str]:
|
|
491
|
+
if bracket_type == "square":
|
|
492
|
+
seqs = [" ".join(re.findall(r"\[.*?\]|.", sequence)) for sequence in sequences]
|
|
493
|
+
elif bracket_type == "angle":
|
|
494
|
+
seqs = [" ".join(re.findall(r"<.*?>|.", sequence)) for sequence in sequences]
|
|
495
|
+
else:
|
|
496
|
+
raise ValueError(f"Invalid bracket type: {bracket_type}")
|
|
497
|
+
return seqs
|
|
369
498
|
|
|
370
499
|
def flush_memmaps(obj):
|
|
371
500
|
"""Recursively flush memory maps."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/custom_model/example_protein_model/pytorch_model.pt
RENAMED
|
File without changes
|
|
File without changes
|
{pepe_cli-1.0.3 → pepe_cli-1.0.4}/examples/custom_model/example_protein_model/tokenizer_config.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|