xiao-fei commited on
Commit
f7d6d00
·
1 Parent(s): a6fc3cc

register model & update readme

Browse files
Files changed (5) hide show
  1. .gitattributes +1 -0
  2. README.md +101 -190
  3. config.json +4 -0
  4. model.png +3 -0
  5. modeling_prot2text2.py +288 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.png filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -3,205 +3,116 @@ license: mit
3
  language:
4
  - en
5
  base_model:
6
- - meta-llama/Llama-3.1-8B-Instruct
7
  - facebook/esm2_t36_3B_UR50D
8
  pipeline_tag: text-generation
9
  tags:
10
  - biology
11
- - medical
12
  ---
13
 
14
- # Model Card for Model ID
15
 
16
- <!-- Provide a quick summary of what the model is/does. -->
17
 
18
- This modelcard aims to be a base template for new models. It has been generated using [this raw template](https://github.com/huggingface/huggingface_hub/blob/main/src/huggingface_hub/templates/modelcard_template.md?plain=1).
19
 
20
- ## Model Details
21
-
22
- ### Model Description
23
-
24
- <!-- Provide a longer summary of what this model is. -->
25
-
26
-
27
-
28
- - **Developed by:** [More Information Needed]
29
- - **Funded by [optional]:** [More Information Needed]
30
- - **Shared by [optional]:** [More Information Needed]
31
- - **Model type:** [More Information Needed]
32
- - **Language(s) (NLP):** [More Information Needed]
33
- - **License:** [More Information Needed]
34
- - **Finetuned from model [optional]:** [More Information Needed]
35
-
36
- ### Model Sources [optional]
37
-
38
- <!-- Provide the basic links for the model. -->
39
-
40
- - **Repository:** [More Information Needed]
41
- - **Paper [optional]:** [More Information Needed]
42
- - **Demo [optional]:** [More Information Needed]
43
-
44
- ## Uses
45
-
46
- <!-- Address questions around how the model is intended to be used, including the foreseeable users of the model and those affected by the model. -->
47
-
48
- ### Direct Use
49
-
50
- <!-- This section is for the model use without fine-tuning or plugging into a larger ecosystem/app. -->
51
-
52
- [More Information Needed]
53
-
54
- ### Downstream Use [optional]
55
-
56
- <!-- This section is for the model use when fine-tuned for a task, or when plugged into a larger ecosystem/app -->
57
-
58
- [More Information Needed]
59
-
60
- ### Out-of-Scope Use
61
-
62
- <!-- This section addresses misuse, malicious use, and uses that the model will not work well for. -->
63
-
64
- [More Information Needed]
65
-
66
- ## Bias, Risks, and Limitations
67
-
68
- <!-- This section is meant to convey both technical and sociotechnical limitations. -->
69
-
70
- [More Information Needed]
71
-
72
- ### Recommendations
73
-
74
- <!-- This section is meant to convey recommendations with respect to the bias, risk, and technical limitations. -->
75
-
76
- Users (both direct and downstream) should be made aware of the risks, biases and limitations of the model. More information needed for further recommendations.
77
-
78
- ## How to Get Started with the Model
79
-
80
- Use the code below to get started with the model.
81
-
82
- [More Information Needed]
83
-
84
- ## Training Details
85
-
86
- ### Training Data
87
-
88
- <!-- This should link to a Dataset Card, perhaps with a short stub of information on what the training data is all about as well as documentation related to data pre-processing or additional filtering. -->
89
-
90
- [More Information Needed]
91
-
92
- ### Training Procedure
93
-
94
- <!-- This relates heavily to the Technical Specifications. Content here should link to that section when it is relevant to the training procedure. -->
95
-
96
- #### Preprocessing [optional]
97
-
98
- [More Information Needed]
99
-
100
-
101
- #### Training Hyperparameters
102
-
103
- - **Training regime:** [More Information Needed] <!--fp32, fp16 mixed precision, bf16 mixed precision, bf16 non-mixed precision, fp16 non-mixed precision, fp8 mixed precision -->
104
-
105
- #### Speeds, Sizes, Times [optional]
106
-
107
- <!-- This section provides information about throughput, start/end time, checkpoint size if relevant, etc. -->
108
-
109
- [More Information Needed]
110
-
111
- ## Evaluation
112
-
113
- <!-- This section describes the evaluation protocols and provides the results. -->
114
 
115
- ### Testing Data, Factors & Metrics
 
 
 
116
 
117
- #### Testing Data
118
-
119
- <!-- This should link to a Dataset Card if possible. -->
120
-
121
- [More Information Needed]
122
-
123
- #### Factors
124
-
125
- <!-- These are the things the evaluation is disaggregating by, e.g., subpopulations or domains. -->
126
-
127
- [More Information Needed]
128
-
129
- #### Metrics
130
-
131
- <!-- These are the evaluation metrics being used, ideally with a description of why. -->
132
-
133
- [More Information Needed]
134
-
135
- ### Results
136
-
137
- [More Information Needed]
138
-
139
- #### Summary
140
-
141
-
142
-
143
- ## Model Examination [optional]
144
-
145
- <!-- Relevant interpretability work for the model goes here -->
146
-
147
- [More Information Needed]
148
-
149
- ## Environmental Impact
150
-
151
- <!-- Total emissions (in grams of CO2eq) and additional considerations, such as electricity usage, go here. Edit the suggested text below accordingly -->
152
-
153
- Carbon emissions can be estimated using the [Machine Learning Impact calculator](https://mlco2.github.io/impact#compute) presented in [Lacoste et al. (2019)](https://arxiv.org/abs/1910.09700).
154
-
155
- - **Hardware Type:** [More Information Needed]
156
- - **Hours used:** [More Information Needed]
157
- - **Cloud Provider:** [More Information Needed]
158
- - **Compute Region:** [More Information Needed]
159
- - **Carbon Emitted:** [More Information Needed]
160
-
161
- ## Technical Specifications [optional]
162
-
163
- ### Model Architecture and Objective
164
-
165
- [More Information Needed]
166
-
167
- ### Compute Infrastructure
168
-
169
- [More Information Needed]
170
-
171
- #### Hardware
172
-
173
- [More Information Needed]
174
-
175
- #### Software
176
-
177
- [More Information Needed]
178
-
179
- ## Citation [optional]
180
-
181
- <!-- If there is a paper or blog post introducing the model, the APA and Bibtex information for that should go in this section. -->
182
-
183
- **BibTeX:**
184
-
185
- [More Information Needed]
186
-
187
- **APA:**
188
-
189
- [More Information Needed]
190
-
191
- ## Glossary [optional]
192
-
193
- <!-- If relevant, include terms and calculations in this section that can help readers understand the model or model card. -->
194
-
195
- [More Information Needed]
196
-
197
- ## More Information [optional]
198
-
199
- [More Information Needed]
200
-
201
- ## Model Card Authors [optional]
202
-
203
- [More Information Needed]
204
-
205
- ## Model Card Contact
206
 
207
- [More Information Needed]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  language:
4
  - en
5
  base_model:
6
+ - meta-llama/Llama-3.1-8B-Instruct-Instruct
7
  - facebook/esm2_t36_3B_UR50D
8
  pipeline_tag: text-generation
9
  tags:
10
  - biology
 
11
  ---
12
 
13
+ # Pro2Text-V2: Protein Function Prediction with Multimodal Contrastive Alignment
14
 
15
+ This is the official repository for the paper "Prot2Text-V2: Protein Function Prediction with Multimodal Contrastive Alignment" by Xiao Fei, Michail Chatzianastasis, Sarah Almeida Carneiro, Hadi Abdine, Lawrence P. Petalidis, and Michalis Vazirgiannis.
16
 
17
+ We're excited to share that our paper has been accepted to **NeurIPS 2025**! The pretrained model weights and the dataset are now publicly available here.
18
 
19
+ Resources and Documentation:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
+ * [📃 ArXiV Preprint 2505.11194](https://arxiv.org/abs/2505.11194)
22
+ * [📜 NeurIPS 2025 Poster](ttps://neurips.cc/virtual/2025/poster/115368)
23
+ * [💻 GitHub Repository](https://github.com/ColinFX/Prot2Text-V2)
24
+ * [🤗 Experimental Dataset](https://huggingface.co/datasets/habdine/Prot2Text-Data)
25
 
26
+ ## Model Details
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ **Prot2Text-V2** treats a protein sequence as if it were another language, and then translate it into English. The model takes the raw amino acid sequence as input and generates a clear, human-readable paragraph describing what the protein does.
29
+
30
+ The model is an innovative fusion of three key components:
31
+
32
+ * Protein language model as sequence encoder: `facebook/esm2_t36_3B_UR50D`
33
+ * Modality adapter as a unique and lightweight component that bridges the gap between protein embeddings and the language model.
34
+ * Natural language decoder for generating articulate textual descriptions utilizing the sequence embeddings: `meta-llama/Llama-3.1-8B-Instruct`
35
+
36
+ <img src="./model.png" alt="Model Architecture" width="100%"/>
37
+
38
+ ## Usage: inference
39
+
40
+ ```python
41
+ import torch
42
+ from transformers import AutoConfig, AutoModelForCausalLM, AutoTokenizer
43
+
44
+ model = AutoModelForCausalLM.from_pretrained(
45
+ pretrained_model_name_or_path="xiao-fei/Prot2Text-V2-11B-Instruct-hf",
46
+ trust_remote_code=True,
47
+ torch_dtype=torch.bfloat16,
48
+ device_map="cpu"
49
+ )
50
+
51
+ esm_tokenizer = AutoTokenizer.from_pretrained("facebook/esm2_t36_3B_UR50D")
52
+ llama_tokenizer = AutoTokenizer.from_pretrained(
53
+ pretrained_model_name_or_path="meta-llama/Llama-3.1-8B-Instruct",
54
+ pad_token='<|reserved_special_token_0|>'
55
+ )
56
+
57
+ example_sequence = (
58
+ "MCYSANGNTFLIVDNTQKRIPEEKKPDFVRENVGDLDGVIFVELVDGKYFMDYYNRDGSMAAFCGNGARAFSQ"
59
+ "YLIDRGWIKEKEFTFLSRAGEIKVIVDDSIWVRMPGVSEKKEMKVDGYEGYFVVVGVPHFVMEVKGIDELDVE"
60
+ "KLGRDLRYKTGANVDFYEVLPDRLKVRTYERGVERETKACGTGVTSVFVVYRDKTGAKEVKIQVPGGTLFLKE"
61
+ "ENGEIFLRGDVKRCSEE"
62
+ )
63
+ system_message = (
64
+ "You are a scientific assistant specialized in protein function "
65
+ "predictions. Given the sequence embeddings and other information "
66
+ "of a protein, describe its function clearly and concisely in "
67
+ "professional language. "
68
+ )
69
+ placeholder = '<|reserved_special_token_1|>'
70
+ user_message = "Sequence embeddings: " + placeholder * (len(example_sequence)+2)
71
+ tokenized_prompt = llama_tokenizer.apply_chat_template(
72
+ [
73
+ {"role": "system", "content": system_message},
74
+ {"role": "user", "content": user_message}
75
+ ],
76
+ add_generation_prompt=True,
77
+ tokenize=True,
78
+ return_tensors="pt",
79
+ return_dict=True
80
+ )
81
+ tokenized_sequence = esm_tokenizer(
82
+ ex_seq,
83
+ return_tensors="pt"
84
+ )
85
+
86
+ model.eval()
87
+ generated = model.generate(
88
+ inputs=tokenized_prompt["input_ids"].to("cuda"),
89
+ attention_mask=tokenized_prompt["attention_mask"].to("cuda"),
90
+ protein_input_ids=tokenized_sequence["input_ids"].to("cuda"),
91
+ protein_attention_mask=tokenized_sequence["attention_mask"].to("cuda"),
92
+ max_new_tokens=1024,
93
+ eos_token_id=128009,
94
+ pad_token_id=128002,
95
+ return_dict_in_generate=False,
96
+ num_beams=4,
97
+ do_sample=False,
98
+ )
99
+ print(llama_tokenizer.decode(generated[0], skip_special_tokens=True))
100
+ ```
101
+
102
+ For detailed instructions on fine-tuning the model and reproducing the experiments, please refer to our [GitHub page](https://github.com/ColinFX/Prot2Text-V2).
103
+
104
+ ## Ⓒ Citation
105
+
106
+ If you find our research helpful, feel free to 🖋️ cite our work or ❤️ like the page:
107
+
108
+ ```bibtex
109
+ @misc{prot2textv2,
110
+ title={Prot2Text-V2: Protein Function Prediction with Multimodal Contrastive Alignment},
111
+ author={Xiao Fei and Michail Chatzianastasis and Sarah Almeida Carneiro and Hadi Abdine and Lawrence P. Petalidis and Michalis Vazirgiannis},
112
+ year={2025},
113
+ eprint={2505.11194},
114
+ archivePrefix={arXiv},
115
+ primaryClass={cs.CE},
116
+ url={https://arxiv.org/abs/2505.11194},
117
+ }
118
+ ```
config.json CHANGED
@@ -70,6 +70,10 @@
70
  "architectures": [
71
  "Esm2LlamaInstructForCausalLM"
72
  ],
 
 
 
 
73
  "esm_config": {
74
  "_attn_implementation_autoset": true,
75
  "_name_or_path": "/ssd1/huggingface-models/esm2_t36_3B_UR50D",
 
70
  "architectures": [
71
  "Esm2LlamaInstructForCausalLM"
72
  ],
73
+ "auto_map": {
74
+ "AutoConfig": "modeling_prot2text2.Esm2LlamaInstructConfig",
75
+ "AutoModelForCausalLM": "modeling_prot2text2.Esm2LlamaInstructForCausalLM"
76
+ },
77
  "esm_config": {
78
  "_attn_implementation_autoset": true,
79
  "_name_or_path": "/ssd1/huggingface-models/esm2_t36_3B_UR50D",
model.png ADDED

Git LFS Details

  • SHA256: faff935131de00279a4a6232ff4ae1fdaa73fd8ed15f35bfd64b84298f45bcdd
  • Pointer size: 131 Bytes
  • Size of remote file: 451 kB
modeling_prot2text2.py ADDED
@@ -0,0 +1,288 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, Optional, Tuple, Union
2
+ import torch
3
+ from transformers import AutoConfig, AutoModelForCausalLM
4
+ from transformers import EsmConfig, LlamaConfig, PretrainedConfig
5
+ from transformers import EsmModel, LlamaForCausalLM, PreTrainedModel
6
+ from transformers.modeling_outputs import CausalLMOutputWithPast
7
+ from transformers.generation.utils import Cache, GenerateOutput
8
+
9
+
10
+ class ModalityAdapterConfig(PretrainedConfig):
11
+ model_type = "modality_adapter"
12
+
13
+ def __init__(
14
+ self,
15
+ input_dim: int,
16
+ intermediate_dim: int,
17
+ output_dim: int,
18
+ dropout_rate: float = 0.3,
19
+ **kwargs
20
+ ):
21
+ super().__init__(**kwargs)
22
+ self.input_dim = input_dim
23
+ self.intermediate_dim = intermediate_dim
24
+ self.output_dim = output_dim
25
+ self.dropout_rate = dropout_rate
26
+
27
+
28
+ class Esm2LlamaInstructConfig(PretrainedConfig):
29
+ model_type = "esm2llama_instruct"
30
+
31
+ def __init__(
32
+ self,
33
+ # model components
34
+ esm_config: Optional[Union[EsmConfig, Dict]] = None,
35
+ adapter_config: Optional[Union[ModalityAdapterConfig, Dict]] = None,
36
+ llama_config: Optional[Union[LlamaConfig, Dict]] = None,
37
+ # standalone attributes
38
+ placeholder_id: int = 128003,
39
+ **kwargs
40
+ ):
41
+ super().__init__(**kwargs)
42
+
43
+ if isinstance(esm_config, dict):
44
+ self.esm_config = EsmConfig(**esm_config)
45
+ else:
46
+ self.esm_config = esm_config
47
+
48
+ if isinstance(llama_config, dict):
49
+ self.llama_config = LlamaConfig(**llama_config)
50
+ else:
51
+ self.llama_config = llama_config
52
+
53
+ if isinstance(adapter_config, dict):
54
+ self.adapter_config = ModalityAdapterConfig(**adapter_config)
55
+ else:
56
+ self.adapter_config = adapter_config
57
+
58
+ self.placeholder_id = placeholder_id
59
+
60
+
61
+ class ModalityAdapter(PreTrainedModel):
62
+ config_class = ModalityAdapterConfig
63
+
64
+ def __init__(self, config: ModalityAdapterConfig):
65
+ super().__init__(config)
66
+ self.config = config
67
+ self.fc1 = torch.nn.Linear(config.input_dim, config.intermediate_dim)
68
+ self.fc2 = torch.nn.Linear(config.intermediate_dim, config.output_dim)
69
+ self.activation = torch.nn.GELU()
70
+ self.ln1 = torch.nn.LayerNorm(normalized_shape=config.intermediate_dim) # DEPRECATED
71
+ self.ln2 = torch.nn.LayerNorm(normalized_shape=config.output_dim) # DEPRECATED
72
+ self.dropout = torch.nn.Dropout(p=config.dropout_rate)
73
+
74
+ self.post_init() # initialize weights and apply final processing
75
+
76
+ def forward(self, hidden_states: torch.FloatTensor) -> torch.FloatTensor:
77
+ # input: (bsz, seq_len, input_dim)
78
+ hidden_states = self.activation(self.fc1(hidden_states))
79
+ hidden_states = self.dropout(hidden_states)
80
+ # interm: (bsz, seq_len, interm_dim)
81
+ hidden_states = self.activation(self.fc2(hidden_states))
82
+ hidden_states = self.dropout(hidden_states)
83
+ hidden_states = torch.nn.functional.normalize(hidden_states, p=2, dim=-1)
84
+ return hidden_states # (bsz, seq_len, output_dim)
85
+
86
+
87
+ class Esm2LlamaInstructForCausalLM(PreTrainedModel):
88
+ """
89
+ Esm2LlamaInstructForCausalLM model for protein function prediction.
90
+ Similar to `EncoderDecoderModel` but with more complicated architecture.
91
+ Initialize with either a configuration OR all three components.
92
+ `kwargs` can override standalone attributes in `Esm2LlamaInstructConfig`.
93
+ """
94
+ config_class = Esm2LlamaInstructConfig
95
+
96
+ def __init__(
97
+ self,
98
+ config: Optional[Esm2LlamaInstructConfig] = None,
99
+ esm_encoder: Optional[EsmModel] = None,
100
+ adapter: Optional[ModalityAdapter] = None,
101
+ llama_decoder: Optional[LlamaForCausalLM] = None,
102
+ **kwargs
103
+ ):
104
+ if config is not None: # components ignored if config is provided
105
+ super().__init__(config)
106
+ self.esm_encoder = EsmModel(
107
+ config.esm_config,
108
+ add_pooling_layer=False
109
+ )
110
+ self.adapter = ModalityAdapter(config.adapter_config)
111
+ self.llama_decoder = LlamaForCausalLM(config.llama_config)
112
+ else:
113
+ config = Esm2LlamaInstructConfig(
114
+ esm_config=esm_encoder.config,
115
+ adapter_config=adapter.config,
116
+ llama_config=llama_decoder.config,
117
+ **kwargs # override standalone attributes
118
+ )
119
+ super().__init__(config)
120
+ self.esm_encoder = esm_encoder
121
+ self.adapter = adapter
122
+ self.llama_decoder = llama_decoder
123
+
124
+ def prepare_decoder_inputs(
125
+ self,
126
+ input_ids: torch.LongTensor,
127
+ encoder_hidden_states: torch.FloatTensor,
128
+ attention_mask: Optional[torch.LongTensor] = None,
129
+ encoder_attention_mask: Optional[torch.LongTensor] = None,
130
+ ):
131
+ """
132
+ Embed and replace placeholder in `input_ids` by encoder hidden states.
133
+ `input_ids` must be passed to locate placeholder for replacement.
134
+ """
135
+ # preparation
136
+ batch_size, seq_len = input_ids.size()
137
+ _, encoder_seq_len, _ = encoder_hidden_states.size()
138
+ if attention_mask is None:
139
+ attention_mask = torch.ones(
140
+ (batch_size, seq_len),
141
+ dtype=torch.long,
142
+ device=input_ids.device
143
+ )
144
+ if encoder_attention_mask is None:
145
+ encoder_attention_mask = torch.ones(
146
+ (batch_size, encoder_seq_len),
147
+ dtype=torch.long,
148
+ device=encoder_hidden_states.device
149
+ )
150
+ inputs_embeds = self.llama_decoder.get_input_embeddings()(input_ids)
151
+ # replacement
152
+ placeholder_mask = input_ids == self.config.placeholder_id
153
+ encoder_mask = encoder_attention_mask.bool()
154
+ inputs_embeds[placeholder_mask] = encoder_hidden_states[encoder_mask]
155
+ return inputs_embeds, attention_mask
156
+
157
+ def forward(
158
+ self,
159
+ # chat template text inputs
160
+ input_ids: Optional[torch.LongTensor] = None,
161
+ attention_mask: Optional[torch.LongTensor] = None,
162
+ position_ids: Optional[torch.LongTensor] = None,
163
+ past_key_values: Optional[Cache] = None,
164
+ labels: Optional[torch.LongTensor] = None,
165
+ # protein amino-acid sequence inputs
166
+ protein_input_ids: Optional[torch.LongTensor] = None,
167
+ protein_attention_mask: Optional[torch.LongTensor] = None,
168
+ protein_position_ids: Optional[torch.LongTensor] = None,
169
+ protein_head_mask: Optional[torch.LongTensor] = None,
170
+ protein_inputs_embeds: Optional[torch.FloatTensor] = None,
171
+ # behavior control arguments
172
+ use_cache: Optional[bool] = None,
173
+ output_attentions: Optional[bool] = None,
174
+ output_hidden_states: Optional[bool] = None,
175
+ return_dict: Optional[bool] = None,
176
+ return_encoder_outputs: bool = False,
177
+ return_adapter_outputs: bool = False,
178
+ return_decoder_inputs: bool = False,
179
+ cache_position: Optional[torch.LongTensor] = None
180
+ ) -> Union[Tuple, CausalLMOutputWithPast]:
181
+ """
182
+ Compute encoder and adapter outputs, then pass to decoder.
183
+ `input_ids` is expected to be [prompt + description] in teacher-forcing
184
+ scenario and [prompt] only in first iteration of inference (with
185
+ return_decoder_inputs=True).
186
+ Attention: possible concatenation of the mask and labels should be
187
+ handled before calling this method.
188
+ `inputs_embeds` not allowed due to placeholder replacement scheme.
189
+ """
190
+ # esm_encoder forward
191
+ encoder_output = self.esm_encoder(
192
+ input_ids=protein_input_ids,
193
+ attention_mask=protein_attention_mask,
194
+ position_ids=protein_position_ids,
195
+ head_mask=protein_head_mask,
196
+ inputs_embeds=protein_inputs_embeds,
197
+ use_cache=False, # because config.esm_config.is_decoder=False
198
+ output_attentions=output_attentions,
199
+ output_hidden_states=output_hidden_states,
200
+ return_dict=return_dict
201
+ )
202
+ encoder_hidden_states = encoder_output[0]
203
+ encoder_attention_mask = protein_attention_mask
204
+ if return_encoder_outputs:
205
+ return encoder_output
206
+ # adapter forward
207
+ adapter_output = self.adapter(encoder_hidden_states)
208
+ if return_adapter_outputs:
209
+ return adapter_output, encoder_attention_mask
210
+ # decoder input preparation
211
+ inputs_embeds, attention_mask = self.prepare_decoder_inputs(
212
+ input_ids=input_ids,
213
+ encoder_hidden_states=adapter_output,
214
+ attention_mask=attention_mask,
215
+ encoder_attention_mask=encoder_attention_mask,
216
+ )
217
+ if return_decoder_inputs:
218
+ return inputs_embeds, attention_mask
219
+ # llama_decoder forward
220
+ return self.llama_decoder.forward(
221
+ input_ids=None,
222
+ attention_mask=attention_mask,
223
+ position_ids=position_ids,
224
+ past_key_values=past_key_values,
225
+ inputs_embeds=inputs_embeds,
226
+ labels=labels,
227
+ use_cache=use_cache,
228
+ output_attentions=output_attentions,
229
+ return_dict=return_dict,
230
+ cache_position=cache_position
231
+ )
232
+
233
+ def generate(
234
+ self,
235
+ inputs: torch.LongTensor, # alias of `input_ids`
236
+ attention_mask: Optional[torch.LongTensor] = None,
237
+ protein_input_ids: Optional[torch.LongTensor] = None,
238
+ protein_attention_mask: Optional[torch.LongTensor] = None,
239
+ protein_inputs_embeds: Optional[torch.FloatTensor] = None,
240
+ **kwargs
241
+ ) -> Union[GenerateOutput, torch.LongTensor]:
242
+ """
243
+ Do inference based on given input prompt.
244
+ `inputs` is expected to be [prompt] only.
245
+ Output will not keep the input prompt due to input in form of embeds.
246
+ Generation behavior can be controlled by `args` and `kwargs`, read
247
+ `GenerationMixin.generate` for more info.
248
+ """
249
+ # get decoder inputs
250
+ prompt_inputs_embeds, prompt_attention_mask = self(
251
+ input_ids=inputs,
252
+ attention_mask=attention_mask,
253
+ protein_input_ids=protein_input_ids,
254
+ protein_attention_mask=protein_attention_mask,
255
+ protein_inputs_embeds=protein_inputs_embeds,
256
+ use_cache=False,
257
+ output_attentions=False,
258
+ output_hidden_states=False,
259
+ return_dict=False,
260
+ return_decoder_inputs=True
261
+ )
262
+ # do generate on llama_decoder
263
+ return self.llama_decoder.generate(
264
+ inputs_embeds=prompt_inputs_embeds,
265
+ attention_mask=prompt_attention_mask,
266
+ **kwargs
267
+ )
268
+
269
+ def gradient_checkpointing_enable(self):
270
+ """
271
+ Enable gradient checkpointing for all submodules that support it.
272
+ Attention! Model need to be in train mode before calling this method.
273
+ """
274
+ if hasattr(self.esm_encoder, "gradient_checkpointing_enable"):
275
+ self.esm_encoder.gradient_checkpointing_enable()
276
+ if hasattr(self.llama_decoder, "gradient_checkpointing_enable"):
277
+ self.llama_decoder.gradient_checkpointing_enable()
278
+ # simple adapter no need to implement gradient checkpointing
279
+
280
+ def gradient_checkpointing_disable(self):
281
+ if hasattr(self.esm_encoder, "gradient_checkpointing_disable"):
282
+ self.esm_encoder.gradient_checkpointing_disable()
283
+ if hasattr(self.llama_decoder, "gradient_checkpointing_disable"):
284
+ self.llama_decoder.gradient_checkpointing_disable()
285
+
286
+
287
+ AutoConfig.register("esm2llama_instruct", Esm2LlamaInstructConfig)
288
+ AutoModelForCausalLM.register(Esm2LlamaInstructConfig, Esm2LlamaInstructForCausalLM)