DEV Community

JULIO SAMUEL CORTEZ MAMANI
JULIO SAMUEL CORTEZ MAMANI

Posted on

Vanna AI (El estándar de la industria para Text-to-SQL)

Idea central

Vanna es uno de los frameworks de código abierto más utilizados hoy en día para crear asistentes de SQL con IA. Funciona en dos pasos:

  1. Entrenas un modelo de IA (o un índice vectorial) con tu esquema, documentación y consultas SQL reales pasadas.
  2. El modelo genera código con una precisión quirúrgica. ### Ventajas
  • Se conecta nativamente a Snowflake, BigQuery, PostgreSQL y MySQL.
  • Incluye interfaces gráficas listas para usar en Slack o aplicaciones web.

    Novedades de la versión 2.0

  • Atención al usuario en cada nivel: las consultas se filtran automáticamente según los permisos del usuario.

  • Interfaz web moderna <vanna-chat>: un componente prediseñado de gran belleza.

  • Respuestas en tiempo real: tablas, gráficos y actualizaciones de progreso en tiempo real.

  • Seguridad empresarial: seguridad a nivel de fila (RLS), registros de auditoría y rate limiting.

  • Listo para producción: integración con FastAPI, observabilidad y lifecycle hooks.

    ¿Cómo funciona? (conceptos clave)

  1. User Resolver: define cómo extraer la identidad del usuario de las solicitudes (cookies, JWT, etc.).
  2. Herramientas con reconocimiento de usuario: comprueban automáticamente los permisos según los grupos del usuario.
  3. Componentes de transmisión: el backend transmite componentes de UI estructurados (tablas, gráficos) al frontend en tiempo real.
  4. Interfaz web integrada: el componente <vanna-chat> lo renderiza todo automáticamente. ## Ejemplo de código: configuración de producción con autorización

1. Backend (Python + FastAPI)

from fastapi import FastAPI
from vanna import Agent
from vanna.servers.fastapi.routes import register_chat_routes
from vanna.servers.base import ChatHandler
from vanna.core.user import UserResolver, User, RequestContext
from vanna.integrations.anthropic import AnthropicLlmService
from vanna.tools import RunSqlTool
from vanna.integrations.sqlite import SqliteRunner
from vanna.core.registry import ToolRegistry

# App de FastAPI existente
app = FastAPI()

# 1. Define tu user resolver (usando tu propio sistema de auth)
class MyUserResolver(UserResolver):
    async def resolve_user(self, request_context: RequestContext) -> User:
        # Extraer desde cookies, JWTs o sesión
        token = request_context.get_header('Authorization')
        user_data = self.decode_jwt(token)  # Tu lógica existente

        return User(
            id=user_data['id'],
            email=user_data['email'],
            group_memberships=user_data['groups']  # Usado para permisos
        )

# 2. Configurar el agente con herramientas
llm = AnthropicLlmService(model="claude-3-5-sonnet")
tools = ToolRegistry()
tools.register(RunSqlTool(sql_runner=SqliteRunner("./data.db")))

agent = Agent(
    llm_service=llm,
    tool_registry=tools,
    user_resolver=MyUserResolver()
)

# 3. Añadir las rutas de Vanna a tu aplicación
chat_handler = ChatHandler(agent)
register_chat_routes(app, chat_handler)

# Endpoint listo: POST /api/vanna/v2/chat_sse (streaming)
Enter fullscreen mode Exit fullscreen mode

2. Frontend (componente web)

Agrega esta etiqueta HTML en tu página. Funciona con React, Vue o HTML simple, y utiliza tus cookies/JWT existentes:

<script src="https://img.vanna.ai/vanna-components.js"></script>

<vanna-chat
  sse-endpoint="/api/vanna/v2/chat_sse"
  theme="dark">
</vanna-chat>
Enter fullscreen mode Exit fullscreen mode

Al hacer una pregunta en lenguaje natural, el componente frontend recibe por streaming:

  • Actualizaciones del progreso de la transmisión.
  • Bloque de código SQL (por defecto, solo visible para usuarios admin).
  • Tabla de datos interactiva.
  • Gráficos (visualizaciones de Plotly).
  • Resumen en lenguaje natural. ### 3. Herramientas personalizadas

Puedes extender Vanna con herramientas específicas para tu caso de uso de negocio, por ejemplo, enviar un correo automático con los resultados:

from vanna.core.tool import Tool, ToolContext, ToolResult
from pydantic import BaseModel, Field
from typing import Type

class EmailArgs(BaseModel):
    recipient: str = Field(description="Email recipient")
    subject: str = Field(description="Email subject")

class EmailTool(Tool[EmailArgs]):
    @property
    def name(self) -> str:
        return "send_email"

    @property
    def access_groups(self) -> list[str]:
        return ["send_email"]  # Verificación de permisos

    def get_args_schema(self) -> Type[EmailArgs]:
        return EmailArgs

    async def execute(self, context: ToolContext, args: EmailArgs) -> ToolResult:
        user = context.user  # Inyectado automáticamente por Vanna

        # Tu lógica de negocio
        await self.email_service.send(
            from_email=user.email,
            to=args.recipient,
            subject=args.subject
        )

        return ToolResult(success=True, result_for_llm=f"Email sent to {args.recipient}")

# Registrar tu herramienta personalizada
tools.register(EmailTool())
Enter fullscreen mode Exit fullscreen mode

Características avanzadas y casos de uso

Vanna 2.0 incluye potentes funciones empresariales para producción:

  • Lifecycle Hooks: agrega comprobación de cuotas, registro personalizado y filtrado de contenido.
  • Middlewares de LLM: implementa caching, ingeniería de prompts o seguimiento de costos.
  • Almacenamiento de conversaciones: guarda y recupera el historial por usuario.

    ¿Para qué casos es ideal?

  • Aplicaciones de análisis de datos con interfaces de lenguaje natural.

  • SaaS multiusuario que requiere permisos con reconocimiento de usuario (RLS).

  • Aplicaciones empresariales con requisitos estrictos de seguridad y auditoría.

    Flujo de arquitectura

El siguiente flujo detalla el ciclo de vida de una solicitud en Vanna 2.0, desde que el usuario hace la pregunta hasta que se renderizan los componentes visuales:

  1. El usuario escribe una pregunta como "Show Q4 sales" en el componente <vanna-chat>.
  2. El frontend envía un POST al endpoint /api/vanna/v2/chat_sse de tu servidor FastAPI, adjuntando las credenciales de autenticación.
  3. Tu servidor resuelve la identidad del usuario (ej. Alice) y sus grupos de acceso (read_sales), y se los pasa al Agente.
  4. El Agente invoca la herramienta de ejecución de SQL (User-Aware Tool).
  5. La herramienta aplica automáticamente las reglas de seguridad a nivel de fila (RLS) según el grupo del usuario.
  6. La base de datos retorna únicamente los resultados filtrados y autorizados al Agente.
  7. El Agente transmite (streams) la respuesta en bloques estructurados (Tabla → Gráfico → Resumen) de vuelta al componente web. ## Comparativa rápida de enfoques
Enfoque Complejidad Mejor para Herramientas clave
LLM + Python puro Baja Prototipos rápidos, scripts internos API de OpenAI, sqlite3
Agentes (smolagents) Media-Alta Consultas complejas, autocorrección Hugging Face, smolagents
Streamlit + HF Media Paneles para usuarios no técnicos Streamlit, transformers
RAG Dinámico Alta Entornos enterprise con cientos de tablas BD vectoriales, DB-GPT
Vanna AI Media-Alta Producción escalable, UI web lista y segura Vanna, FastAPI

Conclusiones y buenas prácticas

  • Nunca ejecutes SQL generado por IA sin validarlo. Usa listas de operaciones permitidas (SELECT solamente) y usuarios de base de datos de solo lectura.
  • El contexto del esquema es clave. Cuanto más claro y completo sea el esquema que le das al modelo, mejor será el SQL generado.
  • Los agentes brillan en tareas multipaso, pero cuestan más tokens y latencia que una llamada simple.
  • Streamlit es la vía más rápida para llevar un prototipo a manos de usuarios no técnicos.

Top comments (0)