drug-discovery-pipeline

Par nvidia · skills

REMARQUE : les entrées molecule et target ainsi que votre NGC_API_KEY sont transmises à des endpoints API externes hébergés par NVIDIA à chaque appel. Utilisez des conteneurs NIM locaux pour les données confidentielles ou propriétaires. Exécutez un pipeline complet de découverte de médicaments par calcul en utilisant les NIMs NVIDIA BioNeMo : générez des molécules drug-like avec GenMol, ancrez-les sur une cible protéique avec DiffDock, puis prédisez l'affinité de liaison avec Boltz2. Utilisez cette skill chaque fois que l'utilisateur souhaite générer et cribler des candidats médicaments de petites molécules, effectuer de la découverte de hits, optimiser des leads contre une cible protéique, ou réaliser un criblage virtuel combinant génération de molécules, docking et prédiction d'affinité. Se déclenche sur : pipeline de découverte de médicaments, hit discovery, lead optimization, criblage virtuel, génération de molécules, docking moléculaire, affinité de liaison, GenMol, DiffDock, Boltz2, SMILES, notation SAFE, microservice NIM. Il s'agit d'un pipeline multi-étapes composant trois NIMs BioNeMo.

npx skills add https://github.com/nvidia/skills --skill drug-discovery-pipeline

Pipeline de découverte de médicaments

Cribler les candidats médicamenteux de bout en bout en utilisant trois NIMs BioNeMo en séquence :

Étape 1: GenMol    →  Étape 2: DiffDock  →  Étape 3: Boltz2
(Générer mols)       (Docking sur cible)     (Prédire affinité)

Aperçu

Ce pipeline est utilisé pour :

  • Découverte de hits de novo : générer des molécules de type médicament et les cribler contre une cible
  • Optimisation de leads : partir d'un scaffold connu et générer des analogs améliorés, puis docking et notation
  • Virtual screening : docking d'une librairie de candidats et filtrage par confiance de docking + affinité

Avant de commencer

Confirmez avec l'utilisateur :

  1. Protéine cible : fichier PDB ou séquence de la cible de liaison
  2. Point de départ : de novo (pas de scaffold) ou décoration de scaffold (noyau connu) ?
  3. Notation : drug-likeness (QED) ou lipophilicité (LogP) ?
  4. Mode API : hébergé ou Docker local ?

Pour Docker local, ne supposez pas que tous les NIMs s'exécutent sur localhost:8000 en même temps. Exécutez soit un conteneur à la fois et transmettez les fichiers/résultats entre les étapes, soit lancez chaque NIM sur un port hôte distinct et définissez les URLs par étape.


Étape 1 : Générer des molécules avec GenMol

GenMol nécessite une entrée en notation SAFE (pas du SMILES brut). Utilisez le package safe-mol.

import requests, json, os
import safe as sf                          # pip install safe-mol
from pathlib import Path

NGC_API_KEY = os.getenv("NGC_API_KEY")
HOSTED = True

if HOSTED:
    genmol_url = "https://health.api.nvidia.com/v1/biology/nvidia/genmol/generate"
    headers = {"Content-Type": "application/json",
               "Authorization": f"Bearer {NGC_API_KEY}"}
else:
    genmol_url = "http://localhost:8000/generate"
    headers = {"Content-Type": "application/json"}

# Génération de novo (sans scaffold) :
safe_input = "[*{20-30}]"

# Décoration de scaffold (scaffold connu) :
# scaffold_smiles = "c1ccccc1"
# safe_input = sf.encode(scaffold_smiles) + ".[*{5-10}]"

payload = {
    "smiles": safe_input,              # le champ s'appelle 'smiles' mais prend la notation SAFE
    "num_molecules": 30,               # demandez plus pour compenser le filtrage post-génération
    "scoring": "QED",                  # QED ou LogP
    "unique": True,
    "temperature": "1.0",             # NOTE : doit être une chaîne, pas un flottant
    "noise": "1.0",                   # NOTE : doit être une chaîne, pas un flottant
}

r = requests.post(genmol_url, headers=headers, json=payload)
r.raise_for_status()
molecules = r.json()["molecules"]
molecules_sorted = sorted(molecules, key=lambda x: x["score"], reverse=True)
top_20 = molecules_sorted[:20]

print(f"Generated {len(molecules)} valid molecules (requested 30)")
print("Top 5 by QED score:")
for m in top_20[:5]:
    print(f"  {m['smiles'][:50]}  score={m['score']:.4f}")

Étape 2 : Docker des molécules avec DiffDock

Préparez la protéine et effectuez le docking de chaque candidat :

# Charger la protéine (enregistrements ATOM uniquement)
receptor_pdb_raw = Path("target.pdb").read_text()
receptor_pdb = "\n".join(line for line in receptor_pdb_raw.splitlines()
                          if line.startswith("ATOM"))

if HOSTED:
    diffdock_url = "https://health.api.nvidia.com/v1/biology/mit/diffdock"
else:
    diffdock_url = "http://localhost:8000/molecular-docking/diffdock/generate"

docking_results = []

for i, mol in enumerate(top_20):
    payload = {
        "protein": receptor_pdb,
        "ligand": mol["smiles"],
        "ligand_file_type": "txt",     # "txt" pour entrée SMILES
        "num_poses": 5,
        "time_divisions": 20,
        "steps": 18,
        "save_trajectory": False,
    }

    r = requests.post(diffdock_url, headers=headers, json=payload)
    r.raise_for_status()
    result = r.json()

    best_conf = result["position_confidence"][0]  # pose rang 1
    best_pose = result["ligand_positions"][0]

    docking_results.append({
        "smiles": mol["smiles"],
        "qed_score": mol["score"],
        "docking_confidence": best_conf,
        "best_pose_sdf": best_pose,
    })
    print(f"  Mol {i+1:2d}: QED={mol['score']:.3f}  docking_conf={best_conf:.4f}")

# Classez par confiance de docking
docking_results.sort(key=lambda x: x["docking_confidence"], reverse=True)
print(f"\nTop 3 by docking confidence:")
for d in docking_results[:3]:
    print(f"  {d['smiles'][:50]}  conf={d['docking_confidence']:.4f}")

Étape 3 : Prédire l'affinité de liaison avec Boltz2

Pour les meilleurs candidats de docking, prédisez l'affinité de liaison basée sur la structure :

if HOSTED:
    boltz_url = "https://health.api.nvidia.com/v1/biology/mit/boltz2/predict"
else:
    boltz_url = "http://localhost:8000/biology/mit/boltz2/predict"

# Utilisez la séquence de protéine cible (pas PDB)
target_sequence = "<YOUR_TARGET_PROTEIN_SEQUENCE>"

affinity_results = []
for d in docking_results[:5]:  # notez les 5 meilleurs résultats de docking
    payload = {
        "polymers": [
            {"id": "A", "molecule_type": "protein", "sequence": target_sequence}
        ],
        "ligands": [
            {"id": "L1", "smiles": d["smiles"], "predict_affinity": True}
        ],
        "recycling_steps": 3,
        "sampling_steps": 50,
        "diffusion_samples": 1,
        "output_format": "mmcif",
    }

    r = requests.post(boltz_url, headers=headers, json=payload)
    r.raise_for_status()
    result = r.json()

    aff = result["affinities"]["L1"]
    pic50 = aff["affinity_pic50"][0]
    prob_binding = aff["affinity_probability_binary"][0]

    affinity_results.append({
        **d,
        "pic50": pic50,
        "probability_binding": prob_binding,
    })
    print(f"  {d['smiles'][:40]}  pIC50={pic50:.2f}  P(bind)={prob_binding:.3f}")

# Classement final par pIC50
affinity_results.sort(key=lambda x: x["pic50"], reverse=True)

Interprétation des résultats

  • Score QED GenMol : 0–1 ; >0,5 est de type médicament
  • Confiance DiffDock : supérieur = prédiction de pose de liaison plus fiable
  • Boltz2 pIC50 : -log10(IC50) prédit ; >6 = submicromolaire, >8 = très puissant
  • P(bind) : probabilité de liaison binaire ; >0,7 = liant probable

Référence rapide — dépendances de skill

Étape Skill Endpoint clé
Génération de molécules genmol-nim /biology/nvidia/genmol/generate
Docking diffdock-nim /molecular-docking/diffdock/generate
Prédiction d'affinité boltz2-nim /biology/mit/boltz2/predict

Skills similaires