Dev.to AI 🤖 Ai 👁 0 📖 10 min read

Antes de enviar una molécula: cómo comprobar los límites del Open Discovery Challenge con RDKit

TL;DR El Open Discovery Challenge (ODC) de FINAL-Bench, organizado por VIDRAFT, pide una sola cosa: una molécula escrita como SMILES. Un verificador automático que no puedes ver la puntúa y la coloca en un ranking públ

Antes de enviar una molécula: cómo comprobar los límites del Open Discovery Challenge con RDKit

TL;DR

El Open Discovery Challenge (ODC) de FINAL-Bench, organizado por VIDRAFT, pide una sola cosa: una molécula escrita como SMILES. Un verificador automático que no puedes ver la puntúa y la coloca en un ranking público. Antes de que tu envío llegue a ese verificador hay una puerta barata y totalmente pública: los límites de entrada (peso molecular máximo y átomos pesados máximos), que cambian por temporada. Un envío fuera de límites se rechaza con el motivo a la vista. En este artículo leo los límites desde la API en vivo de hoy (22 de octubre de 2026), escribo un validador de 30 líneas con RDKit y lo pruebo con cinco fármacos reales. Resultado concreto: la bedaquilina pesa 555,5 Da, solo 5,5 por encima del límite de 550 de la temporada 2, y la rifampicina se rechaza en todas las temporadas abiertas. La temporada 2 (tuberculosis, premio de USD 2.000) cierra el 31 de octubre de 2026.

Una aclaración de entrada: VIDRAFT organiza el reto, y esta cuenta es de VIDRAFT. Todo lo que sigue sale de la documentación pública del reto y de mediciones mías que puedes repetir. Las puntuaciones del ODC son predicciones computacionales, no mediciones de laboratorio.

¿Qué pide exactamente el Open Discovery Challenge?

Cada temporada es una enfermedad distinta con una proteína diana distinta. Además de la diana, el verificador puntúa una contradiana: una proteína humana parecida. Una molécula que se une igual de fuerte a la proteína humana que a la del patógeno no gana solo por potencia.

Estos son los valores que devuelve hoy el endpoint /api/seasons del Space (los leí en vivo, no copiados de un README):

Temporada Enfermedad Diana Contradiana Cierre Premio Acepta envíos
1 Malaria PfDHODH DHODH humana 2026-09-30 USD 1.000 no (cerrada)
2 Tuberculosis InhA FASN humana (dominio ER) 2026-10-31 USD 2.000 sí
3 Enfermedad de Chagas CYP51 de T. cruzi CYP51A1 humana 2026-11-30 USD 1.000 sí
4 Analgesia no opioide Nav1.7 (VSD4) hERG (tetrámero del poro) 2027-01-31 USD 1.000 sí

La contradiana de la temporada 4 tiene una razón clínica clara: un fármaco contra un canal de sodio que además bloquea hERG es un riesgo cardíaco.

¿Cómo se reparte la puntuación entre los seis ejes?

El verificador usa seis ejes que suman 100 puntos: actividad, unión (binding), selectividad, ADMET, novedad y síntesis. Los pesos cambian por temporada porque la biología cambia.

Pesos de puntuación por temporada

Lo que enseña el gráfico: de la temporada 1 a la 4, la actividad cae de 30 a 10 puntos, mientras la unión y la selectividad suben a 30 puntos cada una. Es decir, a partir de la temporada 3, 60 de los 100 puntos dependen de cómo se une tu molécula a la diana frente a la contradiana. ADMET (15), novedad (10) y síntesis (5) son idénticos en las cuatro.

La unión y la selectividad salen de predicción de estructura contra la diana y la contradiana. Cada molécula se acopla varias veces y la dispersión se publica junto a la nota, para que una sola pose afortunada no decida un puesto. Si algún eje no se puede calcular, no se escribe ningún resultado: un eje ausente es un estado, no un cero.

¿Qué límites de entrada son públicos?

Aquí está el punto de este artículo. Los límites de entrada son el único filtro duro que el organizador publica con números exactos:

Temporada Peso molecular máximo Átomos pesados máximos
1 550 45
2 550 45
3 750 55
4 600 45

Un envío fuera de estos límites se rechaza al momento de enviarlo, con el motivo visible. Lo que no es público, y con razón: el código de puntuación, los umbrales de las puertas más allá de estos límites y los conjuntos de referencia de novedad. Publicarlos permitiría moldear una entrada contra el evaluador en lugar de contra la biología.

Si vas a automatizar envíos, por ejemplo con un agente que genera candidatos en bucle, conviene filtrar localmente antes de gastar un envío.

¿Cómo escribo un validador de límites con RDKit?

Treinta líneas bastan. La idea: leer los límites de la API (así no se quedan viejos si el organizador los cambia), parsear el SMILES, y devolver un veredicto por temporada.

import json, urllib.request
from rdkit import Chem
from rdkit.Chem import Descriptors

API = "https://final-bench-open-discovery-challenge.hf.space/api/seasons"
seasons = json.load(urllib.request.urlopen(API, timeout=30))["seasons"]
limits = {s["number"]: (s["limits"]["mw_max"], s["limits"]["heavy_max"], s["accepting"])
          for s in seasons}

def preflight(smiles):
    m = Chem.MolFromSmiles(smiles)
    if m is None:
        return None                      # SMILES invalido: ni llega al verificador
    mw = Descriptors.MolWt(m)
    ha = m.GetNumHeavyAtoms()
    out = {"mw": round(mw, 1), "heavy": ha}
    for n, (mw_max, ha_max, accepting) in sorted(limits.items()):
        if not accepting:
            out[f"T{n}"] = "cerrada"
        else:
            out[f"T{n}"] = "ok" if (mw <= mw_max and ha <= ha_max) else "RECHAZO"
    return out

Dos decisiones de diseño que importan. Primera, el campo accepting es distinto de open: la temporada 1 devuelve open: true pero accepting: false, porque la temporada existe y sus resultados son visibles, pero ya no admite envíos. Si filtras por open enviarás a una temporada cerrada. Segunda, los límites vienen de la API y no de constantes en tu código, de modo que si el organizador ajusta un tope, tu validador lo sigue sin cambios.

¿Qué pasa con cinco fármacos reales?

Ejecuté preflight con cinco moléculas conocidas más una cadena que no es un SMILES. Aclaro el propósito: son pruebas de tamaño. No son candidatos propuestos, no son nuevas (el eje de novedad existe justamente para eso) y varias ni siquiera actúan sobre InhA. La isoniazida es un profármaco que, activado por KatG, forma un aducto con NAD que inhibe InhA. El triclosán es un inhibidor conocido de InhA. El etambutol actúa sobre otra enzima de la pared celular, la bedaquilina sobre la ATP sintasa y la rifampicina sobre la ARN polimerasa.

Molécula Peso molecular (Da) Átomos pesados T2 T3 T4
Isoniazida 137,1 10 ok ok ok
Etambutol 204,3 14 ok ok ok
Triclosán 289,5 17 ok ok ok
Bedaquilina 555,5 37 RECHAZO ok ok
Rifampicina 823,0 59 RECHAZO RECHAZO RECHAZO
C1CC( (no parsea) None None None

La temporada 1 aparece como cerrada para todas. Medido con RDKit 2026.03.1 el 22 de octubre de 2026.

Peso molecular de cinco fármacos frente a los límites

La bedaquilina es el caso instructivo. Pasa el límite de átomos pesados con holgura (37 de 45), pero su peso molecular de 555,5 Da supera por 5,5 el tope de 550 de la temporada 2. Dos topes distintos, y el que muerde no es el que uno miraría primero. La misma molécula entra sin problema en la temporada 3 (tope 750) y en la 4 (tope 600).

Átomos pesados frente a los límites publicados

La rifampicina, con 59 átomos pesados, sobrepasa incluso el límite de 55 de la temporada 3, el más generoso. Es un recordatorio útil para quien piense en macrociclos grandes: el reto está pensado para moléculas del tamaño de un candidato oral, no de un antibiótico macrocíclico.

¿Cuánto confío en mi validador local?

Con límites. Mi validador usa Descriptors.MolWt y GetNumHeavyAtoms de RDKit sobre el SMILES tal como lo escribo. El servidor del organizador aplica sus propias reglas de normalización, por ejemplo con sales o fragmentos múltiples, que no están publicadas. Trata mi filtro como una criba previa que descarta lo obvio, no como una garantía de aceptación. El criterio final lo da el servidor, y lo da con un motivo de rechazo visible.

Un caso borde que vale la pena probar antes de automatizar: una molécula con contraión (por ejemplo una sal clorhidrato). MolWt suma todos los fragmentos. Si el servidor cuenta solo el fragmento mayor, tu filtro será más estricto que el suyo; si cuenta todo, coincidirá. No lo sé, y no voy a inventarlo: pruébalo con un envío de bajo valor en una temporada abierta si te importa.

¿Y los otros retos abiertos del mismo organizador?

FINAL-Bench mantiene otros cuatro retos con la misma filosofía: un verificador que guarda la respuesta en privado. Todos los Spaces estaban en estado RUNNING cuando los consulté hoy.

Reto Qué envías Cierre
Open Materials Challenge Una estructura cristalina con litio (electrolito sólido) 2026-11-30
Open Superconductor Challenge Una estimación de emparejamiento d-wave por material 2D 2026-12-31
Open Quantum Challenge Energías de Fermi-Hubbard o un decodificador de código de superficie 2027-02-28 y 2027-03-31
LEADBOARD Predicciones de propiedades para moléculas retenidas tableros abiertos

El Open Materials Challenge admite un validador análogo con pymatgen. Sus límites públicos (leídos de /api/season) son: máximo 60 átomos, energía sobre el casco convexo de hasta 0,10 eV/átomo, banda prohibida mínima de 1,0 eV y presencia obligatoria de litio. Dos de esas comprobaciones, la energía sobre el casco y la banda prohibida, necesitan un cálculo previo que no cabe en un validador de 30 líneas. Las otras dos sí:

from pymatgen.core import Structure, Lattice

s = Structure.from_spacegroup("Fm-3m", Lattice.cubic(5.14), ["Li", "Cl"],
                              [[0, 0, 0], [0.5, 0.5, 0.5]])
s2 = s.copy(); s2.make_supercell([2, 2, 2])
for name, st in [("LiCl celda convencional", s), ("LiCl supercelda 2x2x2", s2)]:
    els = {e.symbol for e in st.composition.elements}
    print(name, "atomos", len(st), "tiene_Li", "Li" in els, "atomos<=60", len(st) <= 60)

Salida medida: la celda convencional de LiCl tiene 8 átomos y pasa; la supercelda 2x2x2 tiene 64 átomos y deja de cumplir el tope de 60. Es un ejemplo ilustrativo de un error muy común, enviar una supercelda en lugar de la celda primitiva.

¿Por qué un verificador privado y no un benchmark público?

Si el evaluador es público, una entrada se puede moldear contra el evaluador. Es la razón por la que estos retos publican reglas, pesos y límites, pero no la implementación de la puntuación ni la clave de respuestas.

El tablero LEADBOARD del mismo organizador da una cifra que ilustra el problema de preguntar lo equivocado. Según su documentación, con los mismos datos y el mismo modelo, el AUROC en el tablero de cardiotoxicidad hERG fue de 0,818 con una partición aleatoria y de 0,606 con una partición temporal. Mismas moléculas, mismo código: solo cambió la pregunta. Un modelo se usa para ordenar compuestos que nadie ha medido todavía, así que la prueba honesta es entrenar con lo conocido hasta un año de corte y predecir lo que vino después. Es una cifra del organizador, medida por él; yo la cito, no la he reproducido.

¿Pueden participar agentes de IA?

El reto de superconductores lo dice de forma explícita: investigadores, estudiantes y agentes de código pueden participar. El ODC exige iniciar sesión en Hugging Face para enviar. Un agente con herramienta de código puede leer las reglas, consultar /api/seasons, filtrar candidatos con un validador como el de arriba y preparar el envío. Lo que no debería hacer, ni un agente ni una persona, es tratar la nota como evidencia biológica: una nota alta es una hipótesis que merece probarse en un laboratorio, nada más.

Preguntas frecuentes

¿Cómo envío una molécula al Open Discovery Challenge?
Abre el Space FINAL-Bench/open-discovery-challenge en Hugging Face, inicia sesión, elige una temporada que acepte envíos y pega tu SMILES. Se rechaza al momento si excede los límites de peso molecular o átomos pesados, con el motivo visible.

¿Qué temporadas aceptan envíos hoy?
Según /api/seasons el 22 de octubre de 2026: la 2 (tuberculosis, cierra el 31 de octubre), la 3 (Chagas, cierra el 30 de noviembre) y la 4 (analgesia no opioide, cierra el 31 de enero de 2027). La 1 (malaria) ya no admite envíos.

¿Por qué mi molécula pasa en la temporada 3 pero no en la 2?
Porque los límites difieren. La temporada 3 permite hasta 750 Da y 55 átomos pesados, la 2 solo 550 Da y 45 átomos pesados. La bedaquilina (555,5 Da) es un ejemplo medido de ese caso.

¿La nota del ODC demuestra que una molécula funciona?
No. Son predicciones computacionales de unión, selectividad, ADMET, novedad y síntesis. Una nota alta es una hipótesis para validar en laboratorio, no evidencia de actividad en células ni en animales.

¿Qué hace el verificador si no puede calcular un eje?
No escribe ningún resultado. Un eje ausente es un estado, no una puntuación de cero. Una entrada sin nota todavía no se ha evaluado, y una que falla repetidamente por causas del entorno, como una GPU llena, se mantiene en cola en lugar de descartarse.

¿Puedo ver el código de puntuación?
No. El código de puntuación, los umbrales de las puertas más allá de los límites publicados y los conjuntos de referencia de novedad son privados, a propósito, para que nadie moldee una entrada contra el evaluador.

Reproducibilidad

Los scripts de este artículo (es_preflight.py, es_omc.py) usan solo RDKit, pymatgen y la API pública del Space. Los límites se leen en vivo, así que si el organizador los modifica después del 22 de octubre de 2026, tus resultados serán los vigentes y los números de las tablas de arriba serán los de ese día. Los repositorios públicos del reto están en github.com/final-bench/open-discovery-challenge y github.com/final-bench/open-materials-challenge.

Further reading

📰 Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.