PRODPlataforma BaaS soberana europeaAbrir panel →

IA nativa · 8 lectura mínima

Tutorial: cree un punto final NL2SQL en Postgres

Affane Daylami · Fondateur · 28 de agosto de 2026

volver al blog

Este tutorial muestra cómo recibir una pregunta en francés, transformarla en una consulta SQL validada y limitada y luego devolver el resultado, sin siquiera ejecutar SQL no verificado. El SQL realmente generado se muestra en cada paso, no solo el resultado final.

Este texto en inglés se generó automáticamente a partir del original en francés y aún no ha sido revisado.
Esta página fue traducida automáticamente. La versión en inglés es autorizada.

El motor NL2SQL de Aurabase es parte de la IA nativaintegrada en el backend: no es un servicio de terceros para armar. Requisitos previos para seguir esta guía: un proyecto de Aurabase existente, un esquema de base de datos simple para el ejemplo y una clave API del proyecto.

#
Objetivo

que construiras

Un punto final que recibe una pregunta en lenguaje natural, la transforma en una consulta SQL validada y limitada y luego devuelve el resultado. El motor nunca ejecuta SQL generado sin control: cada consulta pasa por una validación sintáctica antes de llegar a la base de datos.

Información

Este tutorial utiliza el SDK de JavaScript @aurabase/aurabase-js y la llamada HTTP sin formato equivalente, para que pueda seguirlo desde cualquier idioma.

#
Debajo del capó

Cómo funciona el motor NL2SQL

La pregunta pasa por un LLM configurado (OpenAI, Anthropic (Claude) o Gemini, los tres proveedores nativos) que genera un SQL candidato. Este SQL nunca se ejecuta tal como está: pasa a través de un validador que analiza su árbol de sintaxis (sqlparser), solo permite consultas SELECT simples y agrega un LIMIT limitado si falta uno.

El validador rechaza explícitamente CTE/WITH, subconsultas, UNION, cláusulas de bloqueo (FOR UPDATE) y cualquier función fuera de una lista blanca (count, sum, avg, min, max, lower, upper, coalesce, date_trunc, now). Se admiten uniones de varias tablas.

Pregunta → LLM (OpenAI / Claude / Gemini) → validación AST (sqlparser) → LÍMITE limitado → ejecución SELECT

El diagrama consultado nunca es proporcionado por su solicitud: se introspecciona desde la base real del proyecto. Un campo schema, allowed_schema o schema_context enviado en el cuerpo de la solicitud se rechaza explícitamente (error 400) en lugar de ignorarse silenciosamente: el servidor decide por sí solo lo que realmente existe.

#
Paso 1

Configurar el punto final NL2SQL

Con el SDK de JavaScript, el cliente de Aurabase expone aura.ai.nl2sql(). La firma es nl2sql(question, options): el esquema no forma parte de él, se introspecciona en el lado del servidor.

app/api/ask/route.tstypescript
import { aura } from '@/lib/aurabase'

export async function POST(req: Request) {
  const { question } = await req.json()

  const { data, error } = await aura.ai.nl2sql(
    question,
    { limit: 50 }
  )

  if (error) return Response.json({ error }, { status: 400 })
  return Response.json(data)
}

En HTTP sin formato, el punto final es POST /v1/ai/{project_id}/nl2sql, autenticado mediante la clave API del proyecto.

terminalbash
curl -X POST https://<votre-gateway>/v1/ai/<project_id>/nl2sql \
  -H "apikey: <votre-cle-api>" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Combien de commandes ont été passées ce mois-ci par des clients premium ?",
    "limit": 50
  }'
Campos rechazados por el servidor

No envíe schema, ni allowed_schema, ni schema_context en el cuerpo de la solicitud: el esquema consultado lo determina el servidor, estos campos se rechazan explícitamente (400) en lugar de sobrescribirse silenciosamente.

#
Paso 2

Prueba con una pregunta real en francés.

Pregunta enviada: "¿Cuántos pedidos realizaron este mes los clientes premium?". Esta es la forma del SQL realmente representado (los nombres de las tablas y las columnas dependen de su esquema):

respuesta (extracto)json
{
  "data": {
    "sql": "SELECT count(*) FROM orders WHERE customer_plan = 'premium' AND created_at >= date_trunc('month', now()) LIMIT 50",
    "explanation": "Compte les commandes de ce mois pour les clients premium.",
    "confidence": 0.85,
    "tables": ["orders"],
    "columns": ["customer_plan", "created_at"],
    "limit": 50,
    "limit_injected": false
  },
  "meta": null
}

limit_injected indica si LIMIT proviene de la plantilla o fue agregado por el servidor. confidence es una heurística sobre la forma de la respuesta (bloque SQL bien formado o no), no una medida de corrección semántica del SQL generado. Una pregunta mal redactada devuelve un error explícito en lugar de un SQL alucinado: por ejemplo, si el SQL generado consulta una tabla que no está en su esquema, el mensaje nombra las tablas realmente disponibles.

#
Paso 3

Producción segura

Tres comprobaciones antes de la implementación: si el límite de filas (LIMIT) está adaptado a su volumen, si la función de Postgres utilizada por el motor permanece restringida al esquema del proyecto y si las tablas confidenciales tienen una política RLS activa: NL2SQL consulta la misma base de datos que el resto de su aplicación, no tiene derechos de acceso extendidos de forma predeterminada.

  • El límite de línea predeterminado se puede configurar en el lado del servidor; un valor solicitado por encima del límite del servidor se niega explícitamente en lugar de reducirse silenciosamente.
  • El validador bloquea el acceso al catálogo del sistema (pg_catalog, information_schema) y a los esquemas que no son del proyecto, independientemente de sus políticas RLS.
  • RLS sigue siendo su última línea de defensa en tablas confidenciales: el validador limita la forma del SQL, no los derechos comerciales sobre los datos.
#
honestidad

Límites actuales a tener en cuenta

El motor es estrictamente legible: solo se aceptan solicitudes SELECT. Cualquier intento deINSERT, UPDATE, DELETE, DROP, CREATE o ALTER generado por la plantilla se rechaza antes de la ejecución; esta no es una convención de solicitud, es una regla impuesta en el nivel del árbol de sintaxis.

Otros límites estructurales: sin subconsultas, sin CTE/WITH, sin UNION y una lista blanca cerrada de diez funciones SQL. Una pregunta que naturalmente requiere una subconsulta (“clientes que nunca han realizado pedidos”) debe reformularse para que encaje en un SELECTsimple, o manejarse de manera diferente en el lado de la aplicación.

#
ir más lejos

RAG y agentes

NL2SQL cubre preguntas estructuradas sobre sus datos relacionales. Para preguntas sobre contenido no estructurado (documentos, notas, tickets), el RAG nativo de Aurabase se basa en pgvector y una búsqueda HNSW. Ambas capacidades, y cómo combinarlas en un agente, se detallan en la página AI nativa en Postgres.

#
Preguntas frecuentes

Preguntas frecuentes

¿NL2SQL funciona con un esquema complejo (múltiples uniones)?+
El validador admite uniones de varias tablas. Por otro lado, las subconsultas y CTE/WITH se rechazan explícitamente: una pregunta que naturalmente requiere una subconsulta debe reformularse para encajar en un SELECT simple con combinaciones, o manejarse de otra manera en el lado de la aplicación.
¿Qué proveedor de LLM elegir para NL2SQL?+
Los tres proveedores nativos (OpenAI, Anthropic/Claude, Gemini) son tratados por igual por el validador: ninguno tiene una ventaja estructural en la validación del SQL generado. El costo y la latencia dependen del modelo específico configurado para su proyecto; compárelos en su propio volumen en lugar de seguir una recomendación genérica.

¿LISTO PARA IMPLEMENTAR?

Tu backend en cinco minutos.

No se requiere tarjeta de crédito · 500 MB gratis · 50,000 MAU