TL;DR
- BIRD Mini-Dev es un benchmark pequeño de texto a SQL (NL2SQL): 500 preguntas sobre bases de datos reales. La métrica es la precisión de ejecución (EX): una consulta es correcta si, al ejecutarla, devuelve el mismo conjunto de filas que la consulta de referencia.
- El 29 de octubre de 2026 medimos Darwin-180B-NL2SQL, un sistema de VIDRAFT, sobre la edición revisada del 28 de octubre: 83,80 % (419 de 500) en SQLite. Es una cifra autorreportada, no una puntuación recalculada por BIRD.
- Lo primero, aunque incomode: en la misma edición, la tabla oficial de líneas base (un solo prompt fijo por modelo) da Claude Opus 5.5 90,00, GPT-6.1 Sol 88,00 y Claude Sonnet 5.5 86,60. Nuestro 83,80 queda por debajo de los tres. Este artículo no trata de un primer puesto.
- Lo que sí podemos medir: con el mismo modelo base y el prompt fijo oficial obtuvimos 68,20 % (341/500). El sistema aportó +78 preguntas netas (89 pasaron a correctas y 11 pasaron a incorrectas).
- Abajo hay un evaluador EX de 25 líneas con
sqlite3, ejecutado de verdad, que muestra cuatro trampas: el orden y los duplicados se ignoran, un>puede dar el mismo resultado que un>=, el tiempo límite entra en el puntaje y los modelos de razonamiento pierden puntos si se les corta la salida.
Una aclaración de entrada: esta cuenta pertenece a VIDRAFT, que desarrolla el sistema que se mide aquí. Por eso separo lo que se puede comprobar con archivos públicos de lo que es opinión nuestra.
¿Qué mide exactamente la precisión de ejecución?
BIRD (creado por investigadores de HKU y Alibaba) parte de una pregunta en lenguaje natural, un esquema de base de datos y, a veces, una nota de contexto (evidence). El modelo produce una consulta SQL. El evaluador ejecuta la consulta del modelo y la de referencia sobre la misma base y compara los resultados.
Dos consecuencias prácticas que mucha gente pasa por alto:
- No se compara el texto del SQL. Dos consultas muy distintas son iguales si devuelven las mismas filas.
- No se compara la intención. Dos consultas con intenciones distintas también son iguales si, en esa base concreta, devuelven las mismas filas por casualidad.
La segunda frase es la que conviene recordar al leer cualquier porcentaje de "exactitud" en NL2SQL.
¿Cómo se escribe un evaluador EX en Python?
La versión siguiente está inspirada en el evaluador oficial que usamos al reproducir el puntaje (comparte la misma idea: tiempo límite dentro de la consulta y comparación de conjuntos; el oficial además abre la base en modo lectura). La ejecuté con la base de juguete que aparece después.
import sqlite3, time
def rows(con, sql, limit=None):
if limit:
end = time.time() + limit
con.set_progress_handler(lambda: time.time() > end, 10000)
try:
return set(con.execute(sql).fetchall())
finally:
con.set_progress_handler(None, 0)
def judge(con, pred, gold, limit=1):
if not pred:
return "sin_sql"
try:
return "ok" if rows(con, pred, limit) == rows(con, gold) else "mal"
except sqlite3.OperationalError as e:
return "tiempo" if "interrupted" in str(e) else "error_exec"
Tres decisiones de diseño merecen explicación:
-
set(...)convierte el resultado en un conjunto. Por eso el orden de las filas y las filas repetidas no cuentan. -
set_progress_handlercorta la consulta desde dentro de SQLite. Un tiempo límite externo no detiene una consulta que se queda en bucle y deja procesos ocupados. - Cada desenlace tiene nombre propio (
sin_sql,mal,tiempo,error_exec). Contarlos por separado es lo que permite diagnosticar después.
¿Qué pasa cuando le doy nueve consultas distintas?
Preparé una tabla mínima (datos de ejemplo, ilustrativos) y una consulta de referencia: clientes con algún pedido de 30 o más.
con = sqlite3.connect(":memory:")
con.executescript("""
CREATE TABLE pedidos(id INTEGER, cliente TEXT, total REAL);
INSERT INTO pedidos VALUES (1,'ana',30),(2,'ana',50),(3,'luis',20),(4,'luis',20),(5,'eva',90);
""")
gold = "SELECT cliente FROM pedidos WHERE total >= 30 ORDER BY cliente"
Salida real de ejecutar el script completo con nueve candidatos en esta máquina:
| Candidato | Veredicto | Qué enseña |
|---|---|---|
| mismo SQL | ok | caso base |
ORDER BY cliente DESC |
ok | el orden se ignora |
sin DISTINCT (devuelve ana, ana, eva) |
ok | los duplicados se ignoran |
con DISTINCT
|
ok | equivale al conjunto |
total > 30 en lugar de >= 30
|
ok | falso positivo por coincidencia |
total > 50 |
mal | el conjunto cambia |
| tabla inexistente | error_exec | fallo de ejecución |
| respuesta vacía | sin_sql | el modelo no devolvió SQL |
| consulta recursiva infinita | tiempo (1,00 s) | cortada por el límite |
La fila del > es la más instructiva. Esa consulta tiene un error de lógica real (excluye los pedidos de exactamente 30), pero en esta base el único pedido de 30 es de ana, que también tiene uno de 50, así que el conjunto final no cambia y el evaluador la da por buena. En un benchmark de 500 preguntas sucede lo mismo a escala: un puntaje EX alto no prueba que la lógica sea correcta, solo que el resultado coincidió. No es un defecto de BIRD, es una propiedad de la métrica que hay que conocer.
¿Dónde queda un 83,80 frente a la tabla oficial?
La ficha del dataset birdsql/bird_mini_dev publica una tabla de líneas base de prompt fijo (una sola llamada por modelo). Esta es su columna SQLite, junto con nuestras dos mediciones:
El gráfico de portada muestra lo mismo, con el eje empezando en 50, así que lee los números y no el largo de las barras:
| Modelo | SQLite EX (%) |
|---|---|
| Claude Opus 5.5 | 90,00 |
| GPT-6.1 Sol | 88,00 |
| Claude Sonnet 5.5 | 86,60 |
| Darwin-180B-NL2SQL (sistema, medición propia) | 83,80 |
| Qwen3.8-Flash-Next | 70,20 |
| Darwin-180B-RSI (mismo modelo, prompt fijo, medición propia) | 68,20 |
| DeepSeek-V4.1-Flash | 61,00 |
Tres matices que cambian la lectura:
- Las líneas base son una sola llamada. Nuestro 83,80 es un sistema de varios pasos: la consulta se ejecuta en la base (solo lectura) y el resultado se usa para decidir si se corrige. La ficha del modelo lo declara con sus condiciones: sin SQL de referencia, sin conocimiento oráculo fuera de la nota de contexto, sin ajuste fino sobre BIRD, un candidato final por pregunta. Aun así, no es la misma categoría que una llamada única.
- Los pesos son los publicados de Darwin-180B-RSI, sin entrenamiento nuevo para este resultado. La diferencia está en el sistema que rodea al modelo.
- Es una cifra autorreportada. No pasó por la reevaluación de BIRD. La última vez que lo comprobamos (31 de octubre de 2026, 08:00 hora de Corea) el tablero oficial no incluía nuestra entrada; la solicitud de registro está abierta. Si más tarde aparece, el valor que cuente es el de ese tablero.
Sobre el "81,00" que figura en la tabla pública de BIRD: su fecha es del 19 de octubre, nueve días antes de la revisión del dataset, y no pudimos confirmar con qué edición se midió. Por eso no lo tratamos como comparación válida, aunque 83,80 sea un número mayor.
¿Por qué el mismo modelo pasó de 68,20 a 83,80?
Lo medimos con el prompt fijo oficial (baseline_inference) y temperatura 0: 341 de 500, 68,20 %. Así se reparten los 500 resultados:
| Resultado | Preguntas |
|---|---|
| Correcta | 341 |
| Resultado distinto | 123 |
| Respuesta vacía (sin SQL) | 23 |
| Tiempo agotado (60 s) | 12 |
| Error de ejecución | 1 |
Hay una anécdota que vale por sí sola. Con un límite de salida de 12.000 tokens, la primera pasada dejó 98 respuestas vacías y un puntaje de 58,60 %. Al regenerar solo las vacías con un límite de 32.000 se recuperaron 75 y el puntaje subió a 68,20 %. Con un modelo de razonamiento, el límite de salida es parte del experimento: si es corto, lo que baja el número es la salida cortada, no la capacidad del modelo.
Ahora, la comparación pregunta por pregunta entre ese resultado y las 419 respuestas correctas del sistema:
| Grupo | Preguntas |
|---|---|
| Correctas en ambos | 330 |
| Solo el sistema acierta | 89 |
| Solo el prompt fijo acierta | 11 |
| Incorrectas en ambos | 70 |
De las 89 que ganó el sistema, 62 eran errores de resultado, 17 respuestas vacías y 10 tiempos agotados. Es decir, 27 de 89 (30 %) no eran errores de significado, sino fallos de proceso. Ejecutar la consulta y mirar el resultado hace evidente enseguida que está vacío o que tarda demasiado. Las otras 62 son correcciones de verdad.
Y la otra cara, igual de importante: 11 preguntas pasaron de correctas a incorrectas. Un sistema que revisa y reescribe también puede estropear lo que estaba bien. El +78 es un neto, no una mejora en una sola dirección.
¿El puntaje cambia según la máquina que lo calcula?
Sí, y lo vivimos. La ficha del modelo indica 419/500 "calculado dos veces en una máquina inactiva con resultado idéntico". Nosotros puntuamos el archivo de predicciones público con el score_ex.py publicado, dos veces en un PC interno con 8 procesos en paralelo, y ambas dieron 418/500 (83,60 %), con tres tiempos agotados.
Al medir cada consulta sola, sin paralelismo:
| Pregunta | Tiempo en solitario | Resultado |
|---|---|---|
| Q93 | 29,4 s | coincide |
| Q144 | 28,4 s | no coincide (era incorrecta de todos modos) |
| Q204 | 73,3 s | supera 60 s, tiempo agotado igualmente |
La Q93 acierta en 29 segundos aislada, pero con 8 procesos compitiendo pasó de 60 s. Esa sola pregunta explica la diferencia entre 418 y 419. La lección general: en un benchmark con tiempo límite por consulta, el hardware y la carga del evaluador entran en la nota. Una diferencia de 0,2 puntos entre dos sistemas cae dentro de ese ruido.
¿Cómo lo reproduzco yo?
El repositorio del modelo contiene el archivo de predicciones y el evaluador. El dataset es birdsql/bird_mini_dev, archivo data/mini_dev_sqlite.jsonl (la ficha incluye su sha256, para que verifiques la edición), y las bases salen del paquete minidev.zip de BIRD.
# con mini_dev_sqlite.jsonl junto a score_ex.py
python score_ex.py predictions.jsonl ruta/a/MINIDEV/dev_databases
Si quieres acercarte al valor de la ficha, baja la carga de la máquina antes de lanzar el cálculo. Con 8 procesos en paralelo nosotros obtuvimos 418.
¿Hasta dónde conviene creer estos números?
- Son medición propia. Los hizo quien fabrica el sistema. Publicar predicciones y evaluador sirve para que cualquiera pueda comprobarlo.
- No hacemos ninguna afirmación de ranking. En la misma edición, tres modelos comerciales con prompt fijo puntúan más alto.
- El benchmark es pequeño. Con 500 preguntas, cada una vale 0,2 puntos y la carga del evaluador mueve una.
- El motor de verificación no es público. Aquí solo analizamos lo que se reproduce con los archivos y datos abiertos.
- No hay registro oficial todavía. Si aparece en el tablero de BIRD, ese valor manda.
Preguntas frecuentes
¿83,80 significa que es el primero en BIRD?
No. En la misma edición revisada, las líneas base oficiales de Claude Opus 5.5 (90,00), GPT-6.1 Sol (88,00) y Claude Sonnet 5.5 (86,60) son más altas, y el tablero oficial aún no incluía nuestra entrada cuando lo revisamos.
¿Qué significa entonces el resultado?
Que el mismo modelo pasó de 68,20 con prompt fijo a 83,80 dentro de un sistema que ejecuta y corrige consultas. De las 78 preguntas netas ganadas, 27 son recuperaciones de respuestas vacías o tiempos agotados.
¿Por qué una consulta con lógica incorrecta puede puntuar como correcta?
Porque EX compara resultados, no intenciones. Si dos consultas devuelven las mismas filas en esa base, el evaluador no las distingue, como el caso de > frente a >= en el ejemplo de arriba.
¿Se puede comparar una cifra de antes y después de la revisión del dataset?
No lo recomendamos. La revisión corrigió preguntas, notas de contexto y SQL de referencia, y reemplazó algunas preguntas. Mira siempre la fecha y la edición junto al puntaje.
¿Por qué mi propio cálculo da 418 y no 419?
Por el límite de 60 segundos por consulta: con carga paralela una pregunta supera el tiempo, aunque aislada acierta en 29 s. Calcúlalo con la máquina poco cargada.
Qué me llevo
Después de una revisión de benchmark importa más el contexto del puntaje que el puntaje. Nuestro 83,80 está por debajo de tres líneas base comerciales de la misma edición y no es comparable con entradas anteriores a la revisión. Lo que sí está confirmado: el mismo modelo subió de 68,20 a 83,80 con el sistema, el 30 % de esa ganancia fue recuperar respuestas vacías y tiempos agotados, y 11 preguntas se estropearon. Cuando el tablero oficial muestre el resultado, el que sea, lo compartiremos.
- Ficha y predicciones: FINAL-Bench/Darwin-180B-NL2SQL
- Dataset: birdsql/bird_mini_dev
- Sitio oficial de BIRD: bird-bench.github.io
- Demo pública (coreano e inglés, solo lectura, datos ficticios): ViSQL
Top comments (0)