Fix: Resolve runtime errors and Add: MCP support

#2
Files changed (2) hide show
  1. README.md +1 -1
  2. app.py +152 -58
README.md CHANGED
@@ -4,7 +4,7 @@ emoji: 🧬
4
  colorFrom: gray
5
  colorTo: green
6
  sdk: gradio
7
- sdk_version: 4.37.1
8
  app_file: app.py
9
  pinned: true
10
  short_description: A frontier generative model for biology by EvolutionaryScale
 
4
  colorFrom: gray
5
  colorTo: green
6
  sdk: gradio
7
+ sdk_version: 5.38.2
8
  app_file: app.py
9
  pinned: true
10
  short_description: A frontier generative model for biology by EvolutionaryScale
app.py CHANGED
@@ -1,11 +1,11 @@
1
-
2
  import gradio as gr
3
  import numpy as np
4
  import os, tempfile
5
  import torch
6
  import py3Dmol
7
  from huggingface_hub import login
8
- # import spaces
9
 
10
  from esm.utils.structure.protein_chain import ProteinChain
11
  from esm.models.esm3 import ESM3
@@ -16,60 +16,107 @@ from esm.sdk.api import (
16
 
17
  from gradio_molecule3d import Molecule3D
18
 
 
 
 
19
 
20
  theme = gr.themes.Monochrome(
21
  primary_hue="gray",
22
  )
23
 
24
- ## Function to get model from Hugging Face using token
25
- # @spaces.GPU()
26
  def get_model(model_name, token):
27
- login(token=token)
 
28
 
29
- if torch.cuda.is_available():
30
- model = ESM3.from_pretrained(model_name, device=torch.device("cuda"))
31
- else:
32
- model = ESM3.from_pretrained(model_name, device=torch.device("cpu"))
 
 
 
 
 
 
 
 
 
 
33
 
34
  # model = ESM3.from_pretrained(model_name, device=torch.device("cpu"))
35
  return model
36
 
37
- ## Function to get PDB data
38
  def get_pdb(pdb_id, chain_id):
 
 
 
 
 
 
 
 
 
 
39
  pdb = ProteinChain.from_rcsb(pdb_id, chain_id)
40
  # return [pdb.sequence, render_pdb(pdb.to_pdb_string())]
41
  return pdb
42
 
43
- ## Function to generate rep for 3D structure
44
  def make_reps(res_start=None, res_end=None, main_color="whiteCarbon", highlight_color="redCarbon", main_style="cartoon", highlight_style="cartoon"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  residue_range = f"{res_start}-{res_end}" if res_start != res_end else ""
46
 
47
  return [
48
- {
49
- "model": 0,
50
- "chain": "",
51
- "resname": "",
52
- "style": main_style,
53
- "color": main_color,
54
- "residue_range": "",
55
- "around": 0,
56
- "byres": False,
57
- "visible": True
58
- },
59
- {
60
- "model": 0,
61
- "chain": "",
62
- "resname": "",
63
- "style": highlight_style,
64
- "color": highlight_color,
65
- "residue_range": residue_range,
66
- "around": 0,
67
- "byres": False,
68
- "visible": True
69
- }]
70
-
71
- ## Function to render 3D structure
72
  def render_pdb(pdb_id, chain_id, res_start, res_end, pdb_string=None):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  if pdb_string is None:
74
  pdb_string = get_pdb(pdb_id, chain_id).to_pdb_string()
75
  ## Write to temporary file and read back in to get the 3D structure
@@ -78,8 +125,25 @@ def render_pdb(pdb_id, chain_id, res_start, res_end, pdb_string=None):
78
 
79
  return Molecule3D(tmp_pdb.name, reps=make_reps(res_start=res_start, res_end=res_end))
80
 
81
- ## Function for Scaffolding
82
- def scaffold(model_name, token, pdb_id, chain_id, motif_start, motif_end, prompt_length, insert_size):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  pdb = get_pdb(pdb_id, chain_id)
84
 
85
  ## Get motif sequence and atom37 positions
@@ -102,7 +166,7 @@ def scaffold(model_name, token, pdb_id, chain_id, motif_start, motif_end, prompt
102
  num_steps=sequence_prompt.count("_") // 2,
103
  temperature=0.5)
104
  ## Generate sequence
105
- model = get_model(model_name, token)
106
  sequence_generation = model.generate(protein_prompt, sequence_generation_config)
107
  generated_sequence = sequence_generation.sequence
108
 
@@ -110,7 +174,7 @@ def scaffold(model_name, token, pdb_id, chain_id, motif_start, motif_end, prompt
110
  structure_prediction_config = GenerationConfig(
111
  track="structure", # We want ESM3 to generate tokens for the structure track
112
  num_steps=len(sequence_generation) // 8,
113
- temperature=0.7,
114
  )
115
  structure_prediction_prompt = ESMProtein(sequence=sequence_generation.sequence)
116
  structure_prediction = model.generate(structure_prediction_prompt, structure_prediction_config)
@@ -121,14 +185,14 @@ def scaffold(model_name, token, pdb_id, chain_id, motif_start, motif_end, prompt
121
  # crmsd = structure_prediction_chain.rmsd(renal_dipep_chain, mobile_inds=motif_inds_in_generation, target_inds=motif_inds)
122
 
123
  structure_orig_highlight = render_pdb(pdb_id, chain_id, res_start=motif_start, res_end=motif_end)
124
- structure_new_highlight = render_pdb(pdb_id, chain_id, res_start=insert_size, res_end=insert_size+len(motif_sequence),
125
  pdb_string=structure_prediction_chain.to_pdb_string())
126
 
127
  return [
128
  pdb.sequence,
129
  motif_sequence,
130
  structure_orig_highlight,
131
- # motif_atom37_positions,
132
  sequence_prompt,
133
  # structure_prompt,
134
  # protein_prompt
@@ -138,8 +202,23 @@ def scaffold(model_name, token, pdb_id, chain_id, motif_start, motif_end, prompt
138
  structure_new_highlight
139
  ]
140
 
141
- ## Function for Secondary Structure Editing
142
- def ss_edit(model_name, token, pdb_id, chain_id, region_start, region_end, shortened_region_length, shortening_ss8):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  pdb = get_pdb(pdb_id, chain_id)
144
  edit_region = np.arange(region_start, region_end)
145
 
@@ -148,21 +227,21 @@ def ss_edit(model_name, token, pdb_id, chain_id, region_start, region_end, short
148
 
149
  ## Construct a secondary structure prompt that retains the secondary structure of the flanking regions, and shortens the lengths of helices in the helix-coil-helix region
150
  ss8_prompt = shortening_ss8[:edit_region[0]] + (((shortened_region_length - 3) // 2) * "H" + "C"*3 + ((shortened_region_length - 3) // 2) * "H") + shortening_ss8[edit_region[-1] + 1:]
151
-
152
  ## Save original sequence and secondary structure
153
  original_sequence = pdb.sequence
154
  original_ss8 = shortening_ss8
155
  original_ss8_region = " "*edit_region[0] + shortening_ss8[edit_region[0]:edit_region[-1]+1]
156
-
157
  proposed_ss8_region = " "*edit_region[0] + ss8_prompt[edit_region[0]:edit_region[0]+shortened_region_length]
158
 
159
  ## Create protein prompt
160
  protein_prompt = ESMProtein(sequence=sequence_prompt, secondary_structure=ss8_prompt)
161
 
162
  ## Generatre sequence
163
- model = get_model(model_name, token)
164
  sequence_generation = model.generate(protein_prompt, GenerationConfig(track="sequence", num_steps=protein_prompt.sequence.count("_") // 2, temperature=0.5))
165
-
166
  ## Generate structure
167
  structure_prediction = model.generate(ESMProtein(sequence=sequence_generation.sequence), GenerationConfig(track="structure", num_steps=len(protein_prompt) // 4, temperature=0))
168
  structure_prediction_chain = structure_prediction.to_protein_chain()
@@ -184,19 +263,34 @@ def ss_edit(model_name, token, pdb_id, chain_id, region_start, region_end, short
184
  structure_new_highlight
185
  ]
186
 
187
- ## Function for SASA Editing
188
- def sasa_edit(model_name, token, pdb_id, chain_id, span_start, span_end, n_samples):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  pdb = get_pdb(pdb_id, chain_id)
190
 
191
  structure_prompt = torch.full((len(pdb), 37, 3), torch.nan)
192
- structure_prompt[span_start:span_end] = torch.tensor(pdb[span_start:span_end].atom37_positions, dtype=torch.float32)
193
 
194
  sasa_prompt = [None]*len(pdb)
195
  sasa_prompt[span_start:span_end] = [40.0]*(span_end - span_start)
196
 
197
  protein_prompt = ESMProtein(sequence="_"*len(pdb), coordinates=structure_prompt, sasa=sasa_prompt)
198
 
199
- model = get_model(model_name, token)
200
 
201
  generated_proteins = []
202
  for i in range(n_samples):
@@ -227,7 +321,7 @@ scaffold_app = gr.Interface(
227
  fn=scaffold,
228
  inputs=[
229
  gr.Dropdown(label="Model Name", choices=["esm3_sm_open_v1"], value="esm3_sm_open_v1", allow_custom_value=True),
230
- gr.Textbox(value = "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", label="Hugging Face Token", type="password"),
231
  gr.Textbox(value="1ITU", label = "PDB Code"),
232
  gr.Textbox(value="A", label = "Chain"),
233
  gr.Number(value=123, label="Motif Start"),
@@ -253,7 +347,7 @@ ss_app = gr.Interface(
253
  fn=ss_edit,
254
  inputs=[
255
  gr.Dropdown(label="Model Name", choices=["esm3_sm_open_v1"], value="esm3_sm_open_v1", allow_custom_value=True),
256
- gr.Textbox(value = "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", label="Hugging Face Token", type="password"),
257
  gr.Textbox(value = "7XBQ", label="PDB ID"),
258
  gr.Textbox(value = "A", label="Chain ID"),
259
  gr.Number(value=38, label="Edit Region Start"),
@@ -280,12 +374,12 @@ sasa_app = gr.Interface(
280
  fn=sasa_edit,
281
  inputs=[
282
  gr.Dropdown(label="Model Name", choices=["esm3_sm_open_v1"], value="esm3_sm_open_v1", allow_custom_value=True),
283
- gr.Textbox(value = "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", label="Hugging Face Token", type="password"),
284
  gr.Textbox(value = "1LBS", label="PDB ID"),
285
  gr.Textbox(value = "A", label="Chain ID"),
286
  gr.Number(value=105, label="Span Start"),
287
  gr.Number(value=116, label="Span End"),
288
- # gr.Textbox(value="CCSSCCCCSSCHHHHHHTEEETTBBTTBCSSEEEEECCTTCCHHHHHTTTHHHHHHHTTCEEEEECCTTTTCSCHHHHHHHHHHHHHHHHHHTTSCCEEEEEETHHHHHHHHHHHHCGGGGGTEEEEEEESCCTTCBGGGHHHHHTTCBCHHHHHTBTTCHHHHHHHHTTTTBCSSCEEEEECTTCSSSCCCCSSSTTSTTCCBTSEEEEHHHHHCTTCCCCSHHHHHBHHHHHHHHHHHHCTTSSCCGGGCCSTTCCCSBCTTSCHHHHHHHHSTHHHHHHHHHHSCCBSSCCCCCGGGGGGSTTCEETTEECCC", label="SS8 String")
289
  gr.Number(value=1, label="Number of Samples")
290
  ],
291
  outputs = [
@@ -323,9 +417,9 @@ with gr.Blocks(theme=theme) as esm_app:
323
  - GitHub: https://github.com/evolutionaryscale/esm
324
  - HuggingFace Model: https://huggingface.co/EvolutionaryScale/esm3-sm-open-v1
325
 
326
- Spaces App By: [[Colby T. Ford](https://colbyford.com)] from [Tuple, The Cloud Genomics Company](https://tuple.xyz)
327
 
328
- NOTE: You will need to agree to EvolutionaryScale's [license agreement](https://huggingface.co/EvolutionaryScale/esm3-sm-open-v1) to use the model. Then, create and paste your HuggingFace token in the appropriate field.
329
  """
330
  )
331
  with gr.Row():
@@ -343,4 +437,4 @@ with gr.Blocks(theme=theme) as esm_app:
343
  ])
344
 
345
  if __name__ == "__main__":
346
- esm_app.launch()
 
1
+ import spaces
2
  import gradio as gr
3
  import numpy as np
4
  import os, tempfile
5
  import torch
6
  import py3Dmol
7
  from huggingface_hub import login
8
+
9
 
10
  from esm.utils.structure.protein_chain import ProteinChain
11
  from esm.models.esm3 import ESM3
 
16
 
17
  from gradio_molecule3d import Molecule3D
18
 
19
+ # --- Retrieve the HF token from the Space's secrets ---
20
+ HF_TOKEN = os.getenv("HF_TOKEN")
21
+
22
 
23
  theme = gr.themes.Monochrome(
24
  primary_hue="gray",
25
  )
26
 
 
 
27
  def get_model(model_name, token):
28
+ """
29
+ Logs into Hugging Face and loads a specified ESM3 model.
30
 
31
+ Args:
32
+ model_name (str): The name of the model to load from Hugging Face.
33
+ token (str): The Hugging Face authentication token.
34
+
35
+ Returns:
36
+ ESM3: The loaded ESM3 model moved to the CUDA device.
37
+ """
38
+ if token:
39
+ login(token=token)
40
+
41
+ # if torch.cuda.is_available():
42
+ model = ESM3.from_pretrained(model_name, device=torch.device("cuda"))
43
+ # else:
44
+ # model = ESM3.from_pretrained(model_name, device=torch.device("cpu"))
45
 
46
  # model = ESM3.from_pretrained(model_name, device=torch.device("cpu"))
47
  return model
48
 
 
49
  def get_pdb(pdb_id, chain_id):
50
+ """
51
+ Fetches a protein structure from the RCSB PDB database.
52
+
53
+ Args:
54
+ pdb_id (str): The 4-character PDB identifier.
55
+ chain_id (str): The specific chain identifier within the PDB file.
56
+
57
+ Returns:
58
+ ProteinChain: An object representing the specified protein chain.
59
+ """
60
  pdb = ProteinChain.from_rcsb(pdb_id, chain_id)
61
  # return [pdb.sequence, render_pdb(pdb.to_pdb_string())]
62
  return pdb
63
 
 
64
  def make_reps(res_start=None, res_end=None, main_color="whiteCarbon", highlight_color="redCarbon", main_style="cartoon", highlight_style="cartoon"):
65
+ """
66
+ Creates representation styles for 3D protein visualization with py3Dmol.
67
+
68
+ Args:
69
+ res_start (int, optional): The starting residue for highlighting. Defaults to None.
70
+ res_end (int, optional): The ending residue for highlighting. Defaults to None.
71
+ main_color (str, optional): The color for the main protein structure. Defaults to "whiteCarbon".
72
+ highlight_color (str, optional): The color for the highlighted region. Defaults to "redCarbon".
73
+ main_style (str, optional): The style for the main structure (e.g., 'cartoon'). Defaults to "cartoon".
74
+ highlight_style (str, optional): The style for the highlighted region. Defaults to "cartoon".
75
+
76
+ Returns:
77
+ list: A list of dictionary objects defining the py3Dmol styles.
78
+ """
79
  residue_range = f"{res_start}-{res_end}" if res_start != res_end else ""
80
 
81
  return [
82
+ {
83
+ "model": 0,
84
+ "chain": "",
85
+ "resname": "",
86
+ "style": main_style,
87
+ "color": main_color,
88
+ "residue_range": "",
89
+ "around": 0,
90
+ "byres": False,
91
+ "visible": True
92
+ },
93
+ {
94
+ "model": 0,
95
+ "chain": "",
96
+ "resname": "",
97
+ "style": highlight_style,
98
+ "color": highlight_color,
99
+ "residue_range": residue_range,
100
+ "around": 0,
101
+ "byres": False,
102
+ "visible": True
103
+ }]
104
+
 
105
  def render_pdb(pdb_id, chain_id, res_start, res_end, pdb_string=None):
106
+ """
107
+ Renders a PDB structure for display in a Gradio Molecule3D component.
108
+
109
+ Args:
110
+ pdb_id (str): The PDB ID, used for file naming.
111
+ chain_id (str): The chain ID, used for file naming.
112
+ res_start (int): The starting residue for highlighting.
113
+ res_end (int): The ending residue for highlighting.
114
+ pdb_string (str, optional): A string containing PDB data. If None,
115
+ it will be fetched from RCSB. Defaults to None.
116
+
117
+ Returns:
118
+ Molecule3D: A Gradio component object for 3D visualization.
119
+ """
120
  if pdb_string is None:
121
  pdb_string = get_pdb(pdb_id, chain_id).to_pdb_string()
122
  ## Write to temporary file and read back in to get the 3D structure
 
125
 
126
  return Molecule3D(tmp_pdb.name, reps=make_reps(res_start=res_start, res_end=res_end))
127
 
128
+ @spaces.GPU()
129
+ def scaffold(model_name, pdb_id, chain_id, motif_start, motif_end, prompt_length, insert_size):
130
+ """
131
+ Performs protein scaffolding by generating a new protein structure around a
132
+ functional motif from an existing protein.
133
+
134
+ Args:
135
+ model_name (str): The ESM3 model to use.
136
+ pdb_id (str): PDB ID of the source protein.
137
+ chain_id (str): Chain of the source protein.
138
+ motif_start (int): Starting residue of the motif.
139
+ motif_end (int): Ending residue of the motif.
140
+ prompt_length (int): Total length of the new protein sequence.
141
+ insert_size (int): Position where the motif will be inserted.
142
+
143
+ Returns:
144
+ list: A list of outputs for the Gradio interface, including sequences
145
+ and 3D structures.
146
+ """
147
  pdb = get_pdb(pdb_id, chain_id)
148
 
149
  ## Get motif sequence and atom37 positions
 
166
  num_steps=sequence_prompt.count("_") // 2,
167
  temperature=0.5)
168
  ## Generate sequence
169
+ model = get_model(model_name, HF_TOKEN)
170
  sequence_generation = model.generate(protein_prompt, sequence_generation_config)
171
  generated_sequence = sequence_generation.sequence
172
 
 
174
  structure_prediction_config = GenerationConfig(
175
  track="structure", # We want ESM3 to generate tokens for the structure track
176
  num_steps=len(sequence_generation) // 8,
177
+ temperature=0.7,
178
  )
179
  structure_prediction_prompt = ESMProtein(sequence=sequence_generation.sequence)
180
  structure_prediction = model.generate(structure_prediction_prompt, structure_prediction_config)
 
185
  # crmsd = structure_prediction_chain.rmsd(renal_dipep_chain, mobile_inds=motif_inds_in_generation, target_inds=motif_inds)
186
 
187
  structure_orig_highlight = render_pdb(pdb_id, chain_id, res_start=motif_start, res_end=motif_end)
188
+ structure_new_highlight = render_pdb(pdb_id, chain_id, res_start=insert_size, res_end=insert_size+len(motif_sequence),
189
  pdb_string=structure_prediction_chain.to_pdb_string())
190
 
191
  return [
192
  pdb.sequence,
193
  motif_sequence,
194
  structure_orig_highlight,
195
+ # gr.Textbox(label="Motif Positions")
196
  sequence_prompt,
197
  # structure_prompt,
198
  # protein_prompt
 
202
  structure_new_highlight
203
  ]
204
 
205
+ @spaces.GPU()
206
+ def ss_edit(model_name, pdb_id, chain_id, region_start, region_end, shortened_region_length, shortening_ss8):
207
+ """
208
+ Edits the secondary structure of a protein, for example, by shortening a helix.
209
+
210
+ Args:
211
+ model_name (str): The ESM3 model to use.
212
+ pdb_id (str): PDB ID of the source protein.
213
+ chain_id (str): Chain of the source protein.
214
+ region_start (int): Starting residue of the region to edit.
215
+ region_end (int): Ending residue of the region to edit.
216
+ shortened_region_length (int): The new length of the edited region.
217
+ shortening_ss8 (str): The 8-state secondary structure string for the original protein.
218
+
219
+ Returns:
220
+ list: A list of outputs for the Gradio interface.
221
+ """
222
  pdb = get_pdb(pdb_id, chain_id)
223
  edit_region = np.arange(region_start, region_end)
224
 
 
227
 
228
  ## Construct a secondary structure prompt that retains the secondary structure of the flanking regions, and shortens the lengths of helices in the helix-coil-helix region
229
  ss8_prompt = shortening_ss8[:edit_region[0]] + (((shortened_region_length - 3) // 2) * "H" + "C"*3 + ((shortened_region_length - 3) // 2) * "H") + shortening_ss8[edit_region[-1] + 1:]
230
+
231
  ## Save original sequence and secondary structure
232
  original_sequence = pdb.sequence
233
  original_ss8 = shortening_ss8
234
  original_ss8_region = " "*edit_region[0] + shortening_ss8[edit_region[0]:edit_region[-1]+1]
235
+
236
  proposed_ss8_region = " "*edit_region[0] + ss8_prompt[edit_region[0]:edit_region[0]+shortened_region_length]
237
 
238
  ## Create protein prompt
239
  protein_prompt = ESMProtein(sequence=sequence_prompt, secondary_structure=ss8_prompt)
240
 
241
  ## Generatre sequence
242
+ model = get_model(model_name, HF_TOKEN)
243
  sequence_generation = model.generate(protein_prompt, GenerationConfig(track="sequence", num_steps=protein_prompt.sequence.count("_") // 2, temperature=0.5))
244
+
245
  ## Generate structure
246
  structure_prediction = model.generate(ESMProtein(sequence=sequence_generation.sequence), GenerationConfig(track="structure", num_steps=len(protein_prompt) // 4, temperature=0))
247
  structure_prediction_chain = structure_prediction.to_protein_chain()
 
263
  structure_new_highlight
264
  ]
265
 
266
+ @spaces.GPU()
267
+ def sasa_edit(model_name, pdb_id, chain_id, span_start, span_end, n_samples):
268
+ """
269
+ Edits a protein region to increase its solvent-accessible surface area (SASA).
270
+
271
+ Args:
272
+ model_name (str): The ESM3 model to use.
273
+ pdb_id (str): PDB ID of the source protein.
274
+ chain_id (str): Chain of the source protein.
275
+ span_start (int): Starting residue of the region to edit.
276
+ span_end (int): Ending residue of the region to edit.
277
+ n_samples (int): The number of new designs to generate.
278
+
279
+ Returns:
280
+ list: A list of outputs for the Gradio interface, including the best
281
+ generated structure.
282
+ """
283
  pdb = get_pdb(pdb_id, chain_id)
284
 
285
  structure_prompt = torch.full((len(pdb), 37, 3), torch.nan)
286
+ structure_prompt[span_start:span_end] = torch.tensor(pdb[span_start:span_end].atom37_positions, dtype=torch.float32)
287
 
288
  sasa_prompt = [None]*len(pdb)
289
  sasa_prompt[span_start:span_end] = [40.0]*(span_end - span_start)
290
 
291
  protein_prompt = ESMProtein(sequence="_"*len(pdb), coordinates=structure_prompt, sasa=sasa_prompt)
292
 
293
+ model = get_model(model_name, HF_TOKEN)
294
 
295
  generated_proteins = []
296
  for i in range(n_samples):
 
321
  fn=scaffold,
322
  inputs=[
323
  gr.Dropdown(label="Model Name", choices=["esm3_sm_open_v1"], value="esm3_sm_open_v1", allow_custom_value=True),
324
+ # gr.Textbox(value = "hf_...", label="Hugging Face Token", type="password"),
325
  gr.Textbox(value="1ITU", label = "PDB Code"),
326
  gr.Textbox(value="A", label = "Chain"),
327
  gr.Number(value=123, label="Motif Start"),
 
347
  fn=ss_edit,
348
  inputs=[
349
  gr.Dropdown(label="Model Name", choices=["esm3_sm_open_v1"], value="esm3_sm_open_v1", allow_custom_value=True),
350
+ # gr.Textbox(value = "hf_...", label="Hugging Face Token", type="password"),
351
  gr.Textbox(value = "7XBQ", label="PDB ID"),
352
  gr.Textbox(value = "A", label="Chain ID"),
353
  gr.Number(value=38, label="Edit Region Start"),
 
374
  fn=sasa_edit,
375
  inputs=[
376
  gr.Dropdown(label="Model Name", choices=["esm3_sm_open_v1"], value="esm3_sm_open_v1", allow_custom_value=True),
377
+ # gr.Textbox(value = "hf_...", label="Hugging Face Token", type="password"),
378
  gr.Textbox(value = "1LBS", label="PDB ID"),
379
  gr.Textbox(value = "A", label="Chain ID"),
380
  gr.Number(value=105, label="Span Start"),
381
  gr.Number(value=116, label="Span End"),
382
+ # gr.Textbox(value="...", label="SS8 String")
383
  gr.Number(value=1, label="Number of Samples")
384
  ],
385
  outputs = [
 
417
  - GitHub: https://github.com/evolutionaryscale/esm
418
  - HuggingFace Model: https://huggingface.co/EvolutionaryScale/esm3-sm-open-v1
419
 
420
+ Spaces App By: [[Colby T. Ford](https://colbyford.com)] from [Tuple, The Cloud Genomics Company](https://tuple.xyz)
421
 
422
+ NOTE: You will need to agree to EvolutionaryScale's [license agreement](https://huggingface.co/EvolutionaryScale/esm3-sm-open-v1) to use the model. This space uses a stored token for API access.
423
  """
424
  )
425
  with gr.Row():
 
437
  ])
438
 
439
  if __name__ == "__main__":
440
+ esm_app.launch(mcp_server=True)