Volver a la lista

Diseño autónomo de proteínas basado en modelos fundacionales multimodales: Generación automática de 100 nuevas secuencias que preservan el sitio activo de las serina proteasas.

ESM3 (EvolutionaryScale 2024) es un modelo de lenguaje de enmascaramiento que integra secuencia, estructura y función. Este modelo fija el sitio activo del trípode catalítico (Ser-His-Asp) y diseña de forma autónoma el resto de la secuencia. Se generaron 100 nuevas serina proteasas, se validó su estructura con AF2/Boltz, se cuantificó la autoconsistencia y la novedad, y se realizó una comparación y un ensamblaje con RFdiffusion+ProteinMPNN, completando así un flujo de trabajo integral.

Avanzado
|
50min
|
Verificado (2026-07)
Progreso0/15 (0%)

Diseño autónomo de proteínas basado en modelos fundacionales multimodales — Generación autónoma de 100 nuevas secuencias manteniendo el sitio activo de las serina proteasas

En los episodios 02 (incrustaciones de proteínas) y 11 (predicción de estructura y afinidad), vimos qué tan bien comprenden los modelos fundacionales las proteínas naturales. Sin embargo, la pregunta realmente interesante es: ¿puede este modelo diseñar desde cero nuevas proteínas que no existen en la naturaleza? ESM3 de EvolutionaryScale (2024) es el primer modelo fundacional de proteínas a gran escala capaz de generar condicionalmente cualquier modalidad, al haber aprendido las tres modalidades de secuencia, estructura y función dentro de un único transformador. En este episodio, construimos una herramienta práctica que fija el triplete catalítico (Ser195-His57-Asp102, numeración de la quimotripsina) del sitio activo de las serina proteasas y diseña de forma autónoma el resto de la secuencia. Generamos 100 candidatos reales de serina proteasa verdaderamente novedosos con una similitud inferior al 30% con respecto a las secuencias naturales, completando la validación de la estructura 3D mediante AF2/Boltz.

📚 Recomendación de episodios previos (muy recomendable)

Este episodio representa la cúspide de los contenidos avanzados y técnicos de IA y biología en DryBench. Antes de comenzar, se recomienda encarecidamente revisar primero los siguientes episodios de DryBench:

Si se accede a este episodio sin los conocimientos previos, se iniciará directamente con el código práctico sin reexplicar los principios de los transformadores multimodales, el aprendizaje de modelos de lenguaje enmascarado y la gestión de modelos grandes en PyTorch, lo que dificultará su comprensión.


Lo que ya aprendimos en DryBench

En DryBench ai-native #3 aprendimos que las incrustaciones de los transformadores son escalables e independientes del dominio y la modalidad; en #12, adquirimos los fundamentos para optimizar tensores grandes, la memoria de GPU y la precisión mixta mediante PyTorch; y en #13, comprendimos que HuggingFace proporciona una API estándar para cargar e inferir modelos preentrenados.

ESM3 es un ejemplo paradigmático de cómo estos tres principios convergen en los dominios de las proteínas. Los tokens de secuencia, los tokens discretos de estructura (similares al alfabeto 3Di) y los tokens de dominio funcional se integran en un vocabulario unificado, y el transformador se entrena para predecir tokens en posiciones y modalidades arbitrarias mediante un enfoque de modelo de lenguaje enmascarado. Los resultados son notables: se puede fijar la estructura de un sitio activo específico y generar el resto de la secuencia, o codificar de forma autónoma nuevas secuencias condicionadas por una función deseada (por ejemplo, fluorescencia, catálisis, unión). Este artículo transforma esa capacidad en una herramienta práctica para el diseño de enzimas.

Definición del problema

Escenario práctico: Diseño autónomo de una nueva serina proteasa

Las serina proteasas son enzimas que degradan proteínas; la quimotripsina, la tripsina y la elastasa son ejemplos representativos. El mecanismo catalítico común implica que el hidroxilo de Ser195 actúa como nucleófilo, la His57 funciona como base general para el movimiento de protones y la Asp102 estabiliza a la His57. Este tríada debe mantener una disposición 3D óptima para la actividad.

Nuestro objetivo:

  • Similitud de secuencia inferior al 30% con las serina proteasas naturales (verdaderamente novedosas).
  • Mantener las coordenadas 3D del tríada catalítico Ser-His-Asp (RMSD ≤ 2 Å predicho por AF2).
  • Generación autónoma de 100 candidatos (aproximadamente 30-60 minutos).
  • Tasa de éxito ≥ 40% en la autoconsistencia (generación ESM3 → predicción AF2 → replicación del sitio activo).
  • Revalidación selectiva de las 5 mejores mediante predicción de actividad experimental (Rosetta · MD).

El espectro del diseño de proteínas de novo

  • Rosetta (desde 2003): Diseño de proteínas basado en la física; el estándar clásico.
  • RFdiffusion (Baker Lab, 2023): Generación de la estructura principal mediante modelos de difusión. El diseño posterior de la secuencia se realiza con ProteinMPNN [1].
  • ProteinMPNN (Baker Lab, 2022): Estándar para el rediseño de secuencias a partir de la estructura principal [2].
  • RFdiffusion + ProteinMPNN + AF2: Pipeline estándar moderno (estructura principal → secuencia → validación).
  • Chroma (2024, Baker Lab): Modelo atómico completo basado en la difusión [3].
  • ESM3 (2024): Primer modelo fundacional multimodal a gran escala. Integración de la generación condicional [4].
  • Boltz-2 (episodio 11): Especializado en la predicción; el diseño es limitado.
  • Diseño condicionado por ligandos: RFdiffusion-Motif · Chroma-Ligand.

Este episodio combina la generación condicional de ESM3 (episodio principal) con una comparación de conjuntos mediante validación AF2/Boltz y RFdiffusion+ProteinMPNN (expansión).

Indicadores objetivo de este episodio

  • Extracción de las coordenadas 3D del triplete catalítico a partir de la PDB de quimotripsina (1AB9, 4CHA, etc.).
  • Generación de 100 secuencias con ESM3 condicional (longitud objetivo: 200~250 residuos).
  • Filtro de diversidad (identidad por pares ≤ 70%).
  • Prueba de similitud con la secuencia natural (BLAST de UniProt Swiss-Prot o incrustaciones de ESM) → mantener solo aquellas con ≤ 30%.
  • Predicción de estructura con AF2/Boltz → proporción de reproducción del sitio activo con RMSD ≤ 2 Å ≥ 40%.
  • pLDDT medio ≥ 70 (confiabilidad estructural).

Stack de herramientas e infraestructura requerida

HerramientaFunciónLicencia
ESM3 (esm3-sm-open-v1 1.4B)Generación condicional de 3 víasAbierto académico, comercial bajo negociación separada
ESM3 large (pesos abiertos, no comercial)Modelo grande alternativoLicencia EvolutionaryScale
RFdiffusion + ProteinMPNNComparación de conjuntosAbierto académico
Boltz-2 (episodio 11)Validación de predicción estructural de secuencias generadasMIT
AlphaFold2 (o ColabFold)Validación estructural alternativaApache 2.0
Biopython · PyMOLManipulación y visualización de secuencias/estructurasLicencia Biopython · LGPL
BLAST · FoldseekBúsqueda de secuencias y estructuras naturales similaresAbierto académico
PyTorchBackendBSD

Requisitos de infraestructura:

  • Pesos abiertos pequeños de ESM3 1.4B: GPU con al menos 16-24GB de VRAM. Aproximadamente 4GB de VRAM en fp16.
  • ESM3 grande (98B, privado): Solo acceso a API académico.
  • RFdiffusion: GPU de centro de datos de 24-48GB de VRAM.
  • Validación AF2/Boltz: Ver episodio 11 (GPU de gama alta para consumidores o GPU de centro de datos de 24-48GB de VRAM).
  • Generación y validación por lotes grandes: Estación de trabajo de centro de datos con 80GB+ de VRAM (acceso general no disponible, se recomienda nube bajo demanda).
  • RAM ≥ 32GB.

Costo estimado para la reproducción por parte del estudiante: Costo API 0 al usar GPU local. Generación de 100 secuencias + validación AF2/Boltz aprox. 4~8 horas (basado en GPU de 24-48GB de VRAM).

Implementación práctica del pipeline

Flujo general:

mermaid

Paso 1. Definición del sitio activo · Preparación de las condiciones de ESM3

Se extraen las coordenadas 3D de los residuos del tríada catalítica de la quimotripsina (PDB 4CHA, 5CHA, 1AB9, etc.).

python
from dataclasses import dataclass
from pathlib import Path
import torch
import numpy as np
from Bio.PDB import PDBParser
@dataclass
class ActiveSiteConstraint:
\"\"\"Definir condiciones del sitio activo.\"\"\"
site_name: str # e.g. "serine_protease_triad"
residue_positions: list[int] # Posición (0-based) del residuo en el sitio activo en la secuencia generada
residue_types: list[str] # Aminoácidos en cada posición (ej. [\"S\", \"H\", \"D\"])
coordinates_backbone: np.ndarray # (N_residuos, 4, 3): Coordenadas N, CA, C, O
ideal_distances: dict[tuple[int, int], float] # Distancia ideal entre residuos del sitio activo (Å)
AA_3TO1 = {
"ALA": "A", "ARG": "R", "ASN": "N", "ASP": "D", "CYS": "C",
"GLN": "Q", "GLU": "E", "GLY": "G", "HIS": "H", "ILE": "I",
"LEU": "L", "LYS": "K", "MET": "M", "PHE": "F", "PRO": "P",
"SER": "S", "THR": "T", "TRP": "W", "TYR": "Y", "VAL": "V",
}
def load_catalytic_triad_from_pdb(
pdb_path: Path,
triad_selection: list[tuple[str, int, str]], # [(chain, resid, expected_aa)]
site_name: str = "serine_protease_triad",
) -> ActiveSiteConstraint:
\"\"\"Extraer coordenadas del triplete catalítico desde PDB.
Ejemplo de Quimotripsina (4CHA): [(\"A\", 195, \"S\"), (\"A\", 57, \"H\"), (\"A\", 102, \"D\")]
"""
parser = PDBParser(QUIET=True)
structure = parser.get_structure("target", str(pdb_path))
residue_types = []
coordinates = []
positions = []
for i, (chain_id, resid, expected_aa) in enumerate(triad_selection):
try:
chain = structure[0][chain_id]
residue = chain[resid]
except KeyError:
raise ValueError(f\"PDB faltante: {chain_id}:{resid}\")
aa = AA_3TO1.get(residue.get_resname().upper(), "X")
if aa != expected_aa:
raise ValueError(f\"Discrepancia de aminoácido en sitio activo {chain_id}:{resid}: esperado {expected_aa}, obtenido {aa}\")
residue_types.append(aa)
coords = np.array([
residue["N"].get_coord(),
residue["CA"].get_coord(),
residue["C"].get_coord(),
residue["O"].get_coord(),
])
coordinates.append(coords)
positions.append(i)
coordinates_arr = np.stack(coordinates, axis=0)
# Distancia ideal CA-CA entre residuos del sitio activo (basado en datos experimentales de quimotripsina)
ca_positions = coordinates_arr[:, 1, :] # Solo CA
ideal_dist = {}
for i in range(len(triad_selection)):
for j in range(i + 1, len(triad_selection)):
d = float(np.linalg.norm(ca_positions[i] - ca_positions[j]))
ideal_dist[(i, j)] = d
return ActiveSiteConstraint(
site_name=site_name,
residue_positions=positions,
residue_types=residue_types,
coordinates_backbone=coordinates_arr,
ideal_distances=ideal_dist,
)
# Ejemplo: tríada catalítica de quimotripsina
CHYMOTRYPSIN_TRIAD_4CHA = [
("A", 57, "H"), # His57 (histidine base)
("A", 102, "D"), # Asp102 (aspartate stabilizer)
("A", 195, "S"), # Ser195 (serine nucleophile)
]

Paso 2. Generación condicional de ESM3

El SDK de ESM3 permite especificar máscaras para las pistas de secuencia, estructura y función, y luego realizar una eliminación iterativa de las máscaras.

python
from esm.models.esm3 import ESM3
from esm.sdk.api import ESMProtein, GenerationConfig
class ESM3Designer:
"""Diseño de proteínas condicional de ESM3."""
def __init__(self, device: str = "cuda", model_name: str = "esm3-sm-open-v1"):
self.device = device
self.model = ESM3.from_pretrained(model_name).to(device).eval()
self.model_name = model_name
@torch.no_grad()
def design_with_active_site(
self,
constraint: ActiveSiteConstraint,
target_length: int = 245, # longitud similar a la quimotripsina
num_samples: int = 100,
temperature: float = 0.7,
seed: int | None = None,
) -> list[dict]:
"""Genera nuevas secuencias manteniendo las condiciones del sitio activo.
Returns: [{sequence, seed, active_site_preserved: bool}]
"""
if seed is not None:
torch.manual_seed(seed)
np.random.seed(seed)
generated = []
for i in range(num_samples):
# Proteína inicial: secuencia enmascarada, posiciones de residuos del sitio activo fijas
seq_list = ["_"] * target_length
# Posiciones del sitio activo (distribución aleatoria dentro de target_length, ej.: mitad)
triad_positions = self._distribute_triad_positions(
target_length, len(constraint.residue_positions),
)
for pos, aa in zip(triad_positions, constraint.residue_types):
seq_list[pos] = aa
initial_sequence = "".join(seq_list)
protein = ESMProtein(sequence=initial_sequence)
# ESM3 iterative decoding
config = GenerationConfig(
track="sequence",
num_steps=max(target_length // 4, 20),
temperature=temperature,
)
try:
result = self.model.generate(protein, config)
# Verificar post-hoc si el residuo del sitio activo se mantuvo realmente
preserved = all(
result.sequence[pos] == aa
for pos, aa in zip(triad_positions, constraint.residue_types)
)
generated.append({
"sequence": result.sequence,
"seed": (seed or 0) + i,
"triad_positions": triad_positions,
"active_site_preserved": preserved,
"length": len(result.sequence),
})
except Exception as e:
print(f"[{i}] Fallo en la generación: {e}")
return generated
def _distribute_triad_positions(
self, target_length: int, n_triad: int, spread_ratio: float = 0.4,
) -> list[int]:
"""Distribución uniforme de residuos del sitio activo a lo largo de target_length.
La quimotripsina real está en las posiciones 57, 102 y 195. En una cadena de 245 residuos, esto corresponde al 21%, 42% y 80%.
"""
"""
chymo_ref = [57, 102, 195]
chymo_length = 245
positions = [
int(target_length * (p / chymo_length))
for p in chymo_ref[:n_triad]
]
return positions

Paso 3. Filtro de diversidad

Asegurar la diversidad aplicando un filtro de identidad por pares a las secuencias generadas.

python
def compute_pairwise_identity(seq_a: str, seq_b: str) -> float:
"""Si las longitudes son iguales, posición por posición; si no, alineamiento."""
if len(seq_a) == len(seq_b):
matches = sum(1 for a, b in zip(seq_a, seq_b) if a == b)
return matches / len(seq_a)
# Si las longitudes difieren, alineamiento global
from Bio import pairwise2
aln = pairwise2.align.globalxx(seq_a, seq_b, one_alignment_only=True)[0]
return aln.score / max(len(seq_a), len(seq_b))
def diversity_filter(
sequences: list[str],
max_pairwise_identity: float = 0.7,
) -> list[str]:
"""Filtro voraz: mantiene solo aquellos con baja identidad respecto a las secuencias ya aceptadas."""
kept = []
for seq in sequences:
keep = True
for existing in kept:
if compute_pairwise_identity(seq, existing) > max_pairwise_identity:
keep = False
break
if keep:
kept.append(seq)
return kept

Paso 4. Verificación de la similitud con secuencias naturales

Utilice BLAST o los modelos de incrustación ESM del módulo 02, junto con FAISS, para verificar la similitud con secuencias naturales.

python
def blast_against_swissprot(
query_seq: str,
swissprot_fasta_path: Path,
e_threshold: float = 1e-5,
) -> list[dict]:
"""Verificación de similitud de secuencias naturales mediante BLAST.
En la práctica, se utiliza una base de datos local de BLAST (makeblastdb + blastp).
"""
import subprocess
import tempfile
with tempfile.NamedTemporaryFile(mode="w", suffix=".fasta", delete=False) as query_f:
query_f.write(f">query\n{query_seq}\n")
query_path = query_f.name
try:
result = subprocess.run(
["blastp",
"-query", query_path,
"-db", str(swissprot_fasta_path),
"-outfmt", "6 qseqid sseqid pident evalue bitscore",
"-evalue", str(e_threshold),
"-max_target_seqs", "5"],
capture_output=True, text=True, check=True,
)
hits = []
for line in result.stdout.strip().split("\n"):
if not line:
continue
fields = line.split("\t")
hits.append({
"subject": fields[1],
"identity": float(fields[2]),
"e_value": float(fields[3]),
"bit_score": float(fields[4]),
})
return hits
except (subprocess.CalledProcessError, FileNotFoundError):
return []
def natural_similarity_check(
seq: str,
max_identity: float = 30.0, # %
) -> tuple[bool, float]:
"""Comprueba si seq es lo suficientemente novedosa, con identidad máxima respecto a secuencias naturales.
Returns: (is_novel, max_identity_found)
"""
hits = blast_against_swissprot(seq, Path("/path/to/swissprot.fasta"))
if not hits:
return True, 0.0
max_id = max(h["identity"] for h in hits)
return max_id < max_identity, max_id

Paso 5. Validación de la estructura con AF2/Boltz

Predicción de la estructura 3D de la secuencia generada mediante AF2 o Boltz-2 (volumen 11) y comparación con las coordenadas del sitio activo original utilizando RMSD.

python
import subprocess
import yaml
def predict_structure_boltz(sequence: str, output_dir: Path, seq_id: str) -> Path:
"""Predicción de estructura mediante el pipeline Boltz-2 del capítulo 11."""
yaml_content = {
"version": 1,
"sequences": [{"protein": {"id": "A", "sequence": sequence}}],
}
output_dir.mkdir(parents=True, exist_ok=True)
yaml_path = output_dir / f"{seq_id}.yaml"
with open(yaml_path, "w") as f:
yaml.safe_dump(yaml_content, f)
try:
subprocess.run([
"boltz", "predict", str(yaml_path),
"--out_dir", str(output_dir),
"--use_msa_server",
], check=True, capture_output=True)
except subprocess.CalledProcessError as e:
raise RuntimeError(f"Fallo de Boltz-2 {seq_id}: {e.stderr.decode()[:500]}")
return output_dir / seq_id / f"{seq_id}_model_0.pdb"
def kabsch_rmsd(coords_a: np.ndarray, coords_b: np.ndarray) -> float:
"""Cálculo de RMSD tras el alineamiento de Kabsch."""
a = coords_a - coords_a.mean(axis=0)
b = coords_b - coords_b.mean(axis=0)
h = a.T @ b
u, _, vt = np.linalg.svd(h)
d = np.sign(np.linalg.det(vt.T @ u.T))
correction = np.eye(3)
correction[2, 2] = d
r = vt.T @ correction @ u.T
a_aligned = a @ r.T
return float(np.sqrt(np.mean(np.sum((a_aligned - b) ** 2, axis=1))))
def check_active_site_recovery(
predicted_pdb: Path,
triad_positions: list[int],
original_constraint: ActiveSiteConstraint,
rmsd_threshold: float = 2.0,
) -> tuple[bool, float, float]:
"""¿Reproduce la estructura predicha el sitio activo?
Returns: (recovered, rmsd, mean_plddt)
"""
parser = PDBParser(QUIET=True)
structure = parser.get_structure("predicted", str(predicted_pdb))
residues_list = list(structure.get_residues())
predicted_coords = []
plddt_values = []
for pos in triad_positions:
if pos >= len(residues_list):
return False, float("inf"), 0.0
residue = residues_list[pos]
try:
coords = np.array([
residue["N"].get_coord(),
residue["CA"].get_coord(),
residue["C"].get_coord(),
residue["O"].get_coord(),
])
except KeyError:
return False, float("inf"), 0.0
predicted_coords.append(coords)
# pLDDT se almacena en el factor B del átomo CA (convención AF2/Boltz)
plddt_values.append(float(residue["CA"].get_bfactor()))
predicted_arr = np.stack(predicted_coords, axis=0).reshape(-1, 3)
reference_arr = original_constraint.coordinates_backbone.reshape(-1, 3)
rmsd = kabsch_rmsd(predicted_arr, reference_arr)
mean_plddt = float(np.mean(plddt_values))
return rmsd < rmsd_threshold, rmsd, mean_plddt

Paso 6. Integración y clasificación de los candidatos

python
from dataclasses import asdict
import pandas as pd
@dataclass
class DesignCandidate:
sequence: str
length: int
seed: int
active_site_preserved_in_seq: bool
triad_positions: list[int]
pdb_path: str | None
active_site_rmsd: float
plddt_active_site: float
natural_identity_max: float
novelty_score: float
composite_score: float
def full_design_pipeline(
catalytic_pdb: Path,
triad_selection: list[tuple[str, int, str]],
target_length: int,
output_dir: Path,
num_samples: int = 100,
device: str = "cuda",
) -> pd.DataFrame:
"""Sitio activo → generación de nueva secuencia → diversidad, novedad y validación → clasificación."""
output_dir.mkdir(parents=True, exist_ok=True)
print("[1/6] Carga de restricciones del sitio activo")
constraint = load_catalytic_triad_from_pdb(catalytic_pdb, triad_selection)
print(f" triad: {constraint.residue_types}, distances: {constraint.ideal_distances}")
print("[2/6] Generación condicional de ESM3")
designer = ESM3Designer(device=device)
generated = designer.design_with_active_site(
constraint, target_length, num_samples, temperature=0.7, seed=42,
)
preserved = [g for g in generated if g["active_site_preserved"]]
print(f" Generados {len(generated)}, sitio activo conservado {len(preserved)}")
print("[3/6] Filtro de diversidad")
preserved_seqs = [g["sequence"] for g in preserved]
diverse_seqs = diversity_filter(preserved_seqs, max_pairwise_identity=0.7)
diverse = [g for g in preserved if g["sequence"] in diverse_seqs]
print(f" Tras diversidad {len(diverse)}")
print("[4/6] Prueba de novedad de secuencia natural")
novel_candidates = []
for g in diverse:
is_novel, max_id = natural_similarity_check(g["sequence"])
g["natural_identity_max"] = max_id
g["novelty_score"] = 1.0 - (max_id / 100.0)
if is_novel:
novel_candidates.append(g)
print(f" novel (identity ≤ 30%) {len(novel_candidates)}")
print(f"[5/6] Verificación estructural con Boltz-2 ({len(novel_candidates)} casos)")
candidates_verified = []
for i, g in enumerate(novel_candidates):
seq_id = f"design_{g['seed']}"
try:
pdb = predict_structure_boltz(g["sequence"], output_dir / "structures", seq_id)
recovered, rmsd, plddt = check_active_site_recovery(
pdb, g["triad_positions"], constraint,
)
candidates_verified.append(DesignCandidate(
sequence=g["sequence"],
length=g["length"],
seed=g["seed"],
active_site_preserved_in_seq=g["active_site_preserved"],
triad_positions=g["triad_positions"],
pdb_path=str(pdb),
active_site_rmsd=rmsd,
plddt_active_site=plddt,
natural_identity_max=g["natural_identity_max"],
novelty_score=g["novelty_score"],
composite_score=0.0, # calculado más abajo
))
except Exception as e:
print(f" [{i}] {seq_id} fallido: {e}")
print(f"[6/6] Clasificación compuesta · Guardar CSV")
if not candidates_verified:
return pd.DataFrame()
df = pd.DataFrame([asdict(c) for c in candidates_verified])
# compuesto: plddt (40%) + RMSD del sitio activo (40%) + novedad (20%)
df["composite_score"] = (
df["plddt_active_site"] / 100 * 0.4 +
(1 - df["active_site_rmsd"].clip(0, 5) / 5.0) * 0.4 +
df["novelty_score"] * 0.2
)
df = df.sort_values("composite_score", ascending=False)
df.to_csv(output_dir / "design_candidates.csv", index=False)
print(f" Top 5 compuestos: {df.head(5)['composite_score'].tolist()}")
return df
# Ejemplo de ejecución (tríada catalítica de la quimotripsina → 100 nuevas serina proteasas)
# result = full_design_pipeline(
# catalytic_pdb=Path("./4CHA.pdb"),
# triad_selection=CHYMOTRYPSIN_TRIAD_4CHA,
# target_length=245,
# output_dir=Path("./serine_protease_design"),
# num_samples=100,
# )

Paso 7. Comparación de los resultados de RFdiffusion + ProteinMPNN (extensión opcional)

Ejecutar el flujo de trabajo estándar del laboratorio Baker con las mismas condiciones del sitio activo y comparar los resultados.

python
def run_rfdiffusion_motif(
active_site_pdb: Path,
triad_residues: list[int],
output_dir: Path,
num_designs: int = 100,
) -> list[Path]:
"""RFdiffusion motif scaffolding.
Para casos prácticos, consulte el ejemplo de GitHub de RosettaCommons RFdiffusion.
"""
"""
# Concepto stub: llamada a la CLI de RFdiffusion
# subprocess.run(["python", "run_inference.py", ...])
return [] # Implementación completa en producción
def run_proteinmpnn(
backbone_pdb: Path,
output_dir: Path,
num_sequences: int = 10,
) -> list[str]:
"""Coloca la secuencia en el backbone con ProteinMPNN."""
# subprocess.run(["python", "protein_mpnn_run.py", ...])
return []

Rendimiento, costo y casos de fallo conocidos

Referencias de rendimiento (citas de evaluaciones comparativas públicas)

EnfoqueEvaluación comparativa (autoconsistencia RMSD ≤ 2 Å de AF2)NovedadFuente
Diseño de enzimas con Rosetta20–30 %BajaBaker Lab, 2003+
ProteinMPNN solo (rediseño del esqueleto principal existente)40–50 %Baja–MediaDauparas et al., Science 2022 [2]
RFdiffusion + ProteinMPNN + AF260–70 %Media–AltaWatson et al., Nature 2023 [1]
Generación condicional de ESM340–55 % (estimado)Media–AltaHayes et al., bioRxiv 2024 [4]
Chroma (todo-átomo de Baker Lab)65–75 %Media–AltaIngraham et al., Nature 2023 [3]
RFdiffusion + ProteinMPNN + validación con Boltz-2~65–72 % (conjunto de 11 miembros)Media–AltaEvaluación comparativa de la comunidad

Observaciones prácticas: RFdiffusion + ProteinMPNN + AF2 es el estándar de oro para el diseño basado en el esqueleto principal. ESM3 destaca por su flexibilidad condicional (condiciones arbitrarias de función, secuencia y estructura). El enfoque de conjunto ofrece los mejores resultados.

Costo estimado de reproducción para estudiantes

  • Costo de la API: 0 (completamente local).
  • Generación de 100 secuencias: con ESM3 1.4B en una GPU de 16–24 GB de VRAM, entre 30 minutos y 1 hora.
  • Validación de 100 secuencias con Boltz-2: entre 2 y 4 horas según el flujo de trabajo de un solo miembro.
  • Descarga e indexación local de BLAST swissprot: aproximadamente 500 MB, entre 1 y 2 horas.

5 casos de fallo conocidos (recopilación de la comunidad y bibliográfica)

  1. Alto pLDDT en la secuencia generada, pero fallo en la reproducción del sitio activo Síntoma: El pLDDT predicho por AF2/Boltz es superior a 80, pero la disposición de los residuos del sitio activo está desalineada. Causa: El pLDDT mide la confianza global y no refleja directamente la disposición 3D de residuos específicos. En particular, las regiones de lazo pueden tener un alto pLDDT a pesar de su flexibilidad. Prevención: (a) Verificar individualmente el pLDDT de los residuos del sitio activo (Paso 5 de este capítulo), (b) realizar obligatoriamente la comprobación del RMSD del sitio activo en la estructura predicha, (c) revalidar la estabilidad mediante simulaciones de dinámica molecular (OpenMM · GROMACS), (d) generar repetidamente con múltiples semillas y aplicar consenso. Fuente: Discusión sobre la autoconsistencia de RFdiffusion frente a AF2 [1].

  2. Excesiva similitud con la secuencia natural (no es realmente novedosa) Síntoma: Al realizar una búsqueda BLAST en UniProt con la secuencia generada, se obtienen múltiples resultados con una identidad superior al 40%. Causa: El modelo base no logra desviarse de la distribución de secuencias naturales aprendida durante el entrenamiento. Solución: (a) aplicar filtros de diversidad estrictos (sección 3 de este artículo), (b) aplicar filtros de similitud con UniProt posteriormente (sección 4 de este artículo), (c) aumentar la temperatura para incrementar la diversidad del muestreo (0.9+), (d) forzar la generación condicional bajo condiciones de baja similitud (pérdida auxiliar). Referencia: Discusión en varios artículos sobre diseño de novo [3][4].

  3. Ausencia de actividad funcional medida (catalítica o fluorescente) Síntoma: La estructura 3D reproduce perfectamente los requisitos solicitados, pero tras la expresión y purificación experimental, la actividad real es nula. Causa: La actividad no depende únicamente de la disposición de los residuos del sitio activo, sino también de la estabilidad global del plegamiento, la dinámica y el posicionamiento sutil de las cadenas laterales. El plegamiento de proteínas y el rendimiento de expresión son problemas independientes. Solución: (a) mejorar la predicción de actividad mediante simulaciones de dinámica molecular (MD) y diseño de enzimas con Rosetta, (b) someter a los mejores candidatos a múltiples experimentos en paralelo, (c) automatizar el cribado de alto rendimiento (display de levaduras o display de fagos), (d) utilizar etiquetas de estabilidad e indicadores fluorescentes junto con los ensayos experimentales. Referencia: Discusión sobre la validación experimental en el artículo de RFdiffusion de Watson et al. [1].

  4. Solo se conservan los residuos del sitio activo, pero la orientación es incorrecta Síntoma: La secuencia contiene Ser195, His57 y Asp102, pero en el espacio 3D no se establece la disposición catalítica correcta (por ejemplo, el grupo hidroxilo de la serina no forma un enlace de hidrógeno con la histidina). Causa: ESM3 conserva solo la identidad del residuo, sin optimizar por separado los rotámeros de las cadenas laterales ni su posición relativa en 3D. Solución: (a) inyectar simultáneamente restricciones de cadena principal y cadenas laterales en el rastro estructural de ESM3, (b) optimizar las cadenas laterales posteriormente con diseño de enzimas mediante Rosetta, (c) verificar posteriormente las distancias CA-CA del sitio activo y los ángulos diedros (verificar ideal_distances en la sección 1 de este artículo), (d) validar la dinámica mediante MDFF y MDshaping. Referencia: Discusión en el artículo de ESM3 [4]; tutorial de diseño de enzimas con Rosetta.

  5. Limitaciones de la licencia comercial de ESM3 Síntomas: El modelo grande ESM3 de EvolutionaryScale (98B) requiere un acuerdo por separado para su uso comercial. La versión pequeña (1.4B) es de código abierto, pero sigue dando prioridad al uso académico. Causa: Políticas de EvolutionaryScale y licencia diferente a la del ESM2 existente de Meta. Solución: (a) Para proyectos académicos, utilizar los pesos abiertos de 1.4B; (b) para proyectos comerciales, consultar la licencia o utilizar alternativas (combinación RFdiffusion + ProteinMPNN); (c) al realizar un ajuste fino personalizado, volver a verificar las cláusulas de la licencia. Fuente: Licencia ESM de EvolutionaryScale [10].

Ideas para ampliar

  • Diseño de complejos: Diseñar interfaces proteína-proteína en lugar de proteínas individuales (véase la sección 11 con Boltz-2).
  • Diseño de anticuerpos: Generar bucles CDR condicionalmente para el diseño de anticuerpos (véase RFantibody e IgLM).
  • Enzima de novo con sustrato: Utilizar el sitio de unión a un sustrato específico como condición para el acoplamiento (véase la sección 08).
  • Péptido cíclico: Diseñar de forma autónoma péptidos cíclicos estables mediante condiciones de conexión N-C.
  • Optimización multiobjetivo: Optimizar simultáneamente la actividad, la estabilidad (estabilidad térmica, resistencia a la agregación) y la solubilidad.
  • Diseño de proteínas fluorescentes: Mantener el trípode Ser65-Tyr66-Gly67 del cromóforo de GFP para crear nuevas proteínas fluorescentes.

Próxima sección

  • Sección 11 structure-affinity-boltz: Predicción de la unión a ligandos de las proteínas generadas.
  • Sección 12 single-cell-perturbation: Reacción in silico al expresar la proteína generada en células.
  • Sección 07 drug-target-gnn: Puntuación GNN del potencial inhibidor de una nueva proteasa.
  • Sección 14 bio-mcp-agent: Exponer el diseño de proteínas como herramienta MCP → diseño autónomo de experimentos por agentes.

Referencias

  1. Watson JL, Juergens D, Bennett NR, et al. "De novo design of protein structure and function with RFdiffusion." Nature 2023. https://www.nature.com/articles/s41586-023-06415-8
  2. Dauparas J, Anishchenko I, Bennett N, et al. "Diseño robusto de secuencias de proteínas basado en aprendizaje profundo utilizando ProteinMPNN." Science 2022. https://www.science.org/doi/10.1126/science.add2187
  3. Ingraham J, Baranov M, Costello Z, et al. "Iluminando el espacio de proteínas con un modelo generativo programable (Chroma)." Nature 2023.
  4. Hayes T, Rao R, Akin H, et al. "Simulando 500 millones de años de evolución con un modelo de lenguaje (ESM3)." bioRxiv 2024. https://www.biorxiv.org/content/10.1101/2024.07.01.600583v1
  5. EvolutionaryScale ESM en GitHub: https://github.com/evolutionaryscale/esm
  6. RFdiffusion en GitHub: https://github.com/RosettaCommons/RFdiffusion
  7. ProteinMPNN en GitHub: https://github.com/dauparas/ProteinMPNN
  8. AlphaFold2 (DeepMind): https://github.com/google-deepmind/alphafold
  9. ColabFold: https://github.com/sokrypton/ColabFold
  10. Licencia de EvolutionaryScale ESM: https://www.evolutionaryscale.ai/ · GitHub LICENSE
  11. Chroma (Baker Lab): https://github.com/RosettaCommons/chroma
  12. Baker Lab (información general): https://www.bakerlab.org/
  13. pyrosetta: https://www.pyrosetta.org/
  14. PyMOL (código abierto): https://github.com/schrodinger/pymol-open-source
  15. Boltz en GitHub (véase la nota 11): https://github.com/jwohlwend/boltz
  16. Biopython: https://biopython.org/
  17. Foldseek (búsqueda de similitud estructural): https://github.com/steineggerlab/foldseek
  18. UniProt (búsqueda de secuencias naturales): https://www.uniprot.org/
  19. RCSB PDB (quimotripsina 4CHA, etc.): https://www.rcsb.org/
  20. Tutorial de diseño de enzimas de RosettaCommons: https://www.rosettacommons.org/docs/latest/application_documentation/design/enzyme-design

💬 Preguntas y comentarios

0 comentarios

Puedes publicar sin iniciar sesión. Los comentarios de invitados no pueden editarse ni eliminarse después.

0/2000

Cargando...