milvus-logo
LFAI
Home
  • Integraciones
    • Ingeniería del conocimiento

Escribir SQL con Vanna y Milvus

Open In Colab GitHub Repository

Vanna es un framework Python RAG (Retrieval-Augmented Generation) de código abierto para la generación de SQL y funcionalidades relacionadas. Milvus es la base de datos vectorial de código abierto más avanzada del mundo, creada para potenciar la búsqueda de similitudes y las aplicaciones de IA.

Vanna funciona en dos sencillos pasos: entrena un "modelo" RAG en tus datos y, a continuación, formula preguntas que devolverán consultas SQL que pueden configurarse para ejecutarse en tu base de datos. Esta guía muestra cómo utilizar Vanna para generar y ejecutar consultas SQL basadas en sus datos almacenados en una base de datos.

Requisitos previos

Antes de ejecutar este cuaderno, asegúrate de tener instaladas las siguientes dependencias:

$ pip install "vanna[milvus,openai]"

Si estás utilizando Google Colab, para habilitar las dependencias que acabas de instalar, puede que necesites reiniciar el tiempo de ejecución (Haz clic en el menú "Tiempo de ejecución" en la parte superior de la pantalla, y selecciona "Reiniciar sesión" en el menú desplegable).

Y necesitas establecer el OPENAI_API_KEY en tus variables de entorno. Puedes obtener la clave API de OpenAI.

import os

os.environ["OPENAI_API_KEY"] = "sk-***********"

Preparación de datos

En primer lugar, necesitamos heredar de las clases Milvus_VectorStore y OpenAI_Chat de Vanna y definir una nueva clase VannaMilvus que combine las capacidades de ambas.

from pymilvus import MilvusClient, model
from vanna.milvus import Milvus_VectorStore
from vanna.openai import OpenAI_Chat


class VannaMilvus(Milvus_VectorStore, OpenAI_Chat):
    def __init__(self, config=None):
        Milvus_VectorStore.__init__(self, config=config)
        OpenAI_Chat.__init__(self, config=config)

Inicializamos la clase VannaMilvus con los parámetros de configuración necesarios. Usamos una instancia de milvus_client para almacenar incrustaciones y la clase model.DefaultEmbeddingFunction() inicializada desde milvus_model para generar incrustaciones.C

En cuanto al argumento de MilvusClient:

  • Configurar el uri como un archivo local, por ejemplo./milvus.db, es el método más conveniente, ya que utiliza automáticamente Milvus Lite para almacenar todos los datos en este archivo.
  • Si tiene una gran escala de datos, puede configurar un servidor Milvus más eficiente en docker o kubernetes. En esta configuración, por favor utilice la uri del servidor, por ejemplohttp://localhost:19530, como su uri.
  • Si desea utilizar Zilliz Cloud, el servicio en la nube totalmente gestionado para Milvus, ajuste el uri y token, que corresponden al punto final público y la clave Api en Zilliz Cloud.
milvus_uri = "./milvus_vanna.db"

milvus_client = MilvusClient(uri=milvus_uri)

vn_milvus = VannaMilvus(
    config={
        "api_key": os.getenv("OPENAI_API_KEY"),
        "model": "gpt-3.5-turbo",
        "milvus_client": milvus_client,
        "embedding_function": model.DefaultEmbeddingFunction(),
        "n_results": 2,  # The number of results to return from Milvus semantic search.
    }
)

Este es un ejemplo sencillo con sólo unas pocas muestras de datos, por lo que ajustamos n_results a 2 para asegurarnos de que buscamos los 2 resultados más similares. En la práctica, debería ajustar n_results a un valor más alto cuando se trate de un conjunto de datos de entrenamiento más grande.

Utilizaremos una base de datos SQLite de ejemplo con algunas tablas que contienen datos de ejemplo.

import sqlite3

sqlite_path = "./my-database.sqlite"
sql_connect = sqlite3.connect(sqlite_path)
c = sql_connect.cursor()

init_sqls = """
CREATE TABLE IF NOT EXISTS Customer (
    ID INTEGER PRIMARY KEY AUTOINCREMENT,
    Name TEXT NOT NULL,
    Company TEXT NOT NULL,
    City TEXT NOT NULL,
    Phone TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS Company (
    ID INTEGER PRIMARY KEY AUTOINCREMENT,
    Name TEXT NOT NULL,
    Industry TEXT NOT NULL,
    Location TEXT NOT NULL,
    EmployeeCount INTEGER NOT NULL
);

CREATE TABLE IF NOT EXISTS User (
    ID INTEGER PRIMARY KEY AUTOINCREMENT,
    Username TEXT NOT NULL UNIQUE,
    Email TEXT NOT NULL UNIQUE
);

INSERT INTO Customer (Name, Company, City, Phone) 
VALUES ('John Doe', 'ABC Corp', 'New York', '123-456-7890');

INSERT INTO Customer (Name, Company, City, Phone) 
VALUES ('Jane Smith', 'XYZ Inc', 'Los Angeles', '098-765-4321');

INSERT INTO Company (Name, Industry, Location, EmployeeCount)
VALUES ('ABC Corp', 'cutting-edge technology', 'New York', 100);

INSERT INTO User (Username, Email)
VALUES ('johndoe123', 'johndoe123@example.com');
"""

for sql in init_sqls.split(";"):
    c.execute(sql)

sql_connect.commit()

# Connect to the SQLite database
vn_milvus.connect_to_sqlite(sqlite_path)

Entrenar con datos

Podemos entrenar el modelo con los datos DDL de la base de datos SQLite. Obtenemos los datos DDL y los introducimos en la función train.

# If there exists training data, we should remove it before training.
existing_training_data = vn_milvus.get_training_data()
if len(existing_training_data) > 0:
    for _, training_data in existing_training_data.iterrows():
        vn_milvus.remove_training_data(training_data["id"])

# Get the DDL of the SQLite database
df_ddl = vn_milvus.run_sql("SELECT type, sql FROM sqlite_master WHERE sql is not null")

# Train the model on the DDL data
for ddl in df_ddl["sql"].to_list():
    vn_milvus.train(ddl=ddl)
Adding ddl: CREATE TABLE Customer (
    ID INTEGER PRIMARY KEY AUTOINCREMENT,
    Name TEXT NOT NULL,
    Company TEXT NOT NULL,
    City TEXT NOT NULL,
    Phone TEXT NOT NULL
)
Adding ddl: CREATE TABLE sqlite_sequence(name,seq)
Adding ddl: CREATE TABLE Company (
    ID INTEGER PRIMARY KEY AUTOINCREMENT,
    Name TEXT NOT NULL,
    Industry TEXT NOT NULL,
    Location TEXT NOT NULL,
    EmployeeCount INTEGER NOT NULL
)
Adding ddl: CREATE TABLE User (
    ID INTEGER PRIMARY KEY AUTOINCREMENT,
    Username TEXT NOT NULL UNIQUE,
    Email TEXT NOT NULL UNIQUE
)

Además de entrenar con los datos DDL, también podemos entrenar con la documentación y las consultas SQL de la base de datos.

# Add documentation about your business terminology or definitions.
vn_milvus.train(
    documentation="ABC Corp specializes in cutting-edge technology solutions and innovation."
)
vn_milvus.train(
    documentation="XYZ Inc is a global leader in manufacturing and supply chain management."
)

# You can also add SQL queries to your training data.
vn_milvus.train(sql="SELECT * FROM Customer WHERE Name = 'John Doe'")
Adding documentation....
Adding documentation....
Using model gpt-3.5-turbo for 65.0 tokens (approx)
Question generated with sql: What are the details of the customer named John Doe? 
Adding SQL...





'595b185c-e6ad-47b0-98fd-0e93ef9b6a0a-sql'

Echemos un vistazo a los datos de entrenamiento.

training_data = vn_milvus.get_training_data()
training_data
# id pregunta contenido
0 595b185c-e6ad-47b0-98fd-0e93ef9b6a0a-sql ¿Cuáles son los datos del cliente llamado Joh... SELECT * FROM Cliente WHERE Nombre = 'Juan Pérez'
0 25f4956c-e370-4097-994f-996f22d145fa-ddl Ninguno CREAR TABLA Empresa (\n ID INTEGER PRIMARY...
1 b95ecc66-f65b-49dc-a9f1-c1842ad230ff-ddl Ninguno CREAR TABLA Cliente (\n ID INTEGER PRIMAR...
2 fcc73d15-30a5-4421-9d73-b8c3b0ed5305-ddl Ninguno CREATE TABLE sqlite_sequence(name,seq)
3 feae618c-5910-4f6f-8b4b-6cc3e03aec06-ddl Ninguno CREATE TABLE User (\n ID INTEGER PRIMARY KE...
0 79a48db1-ba1f-4fd5-be99-74f2ca2eaeeb-doc Ninguno XYZ Inc es un líder mundial en la fabricación y...
1 9f9df1b8-ae62-4823-ad28-d7e0f2d1f4c0-doc Ninguno ABC Corp se especializa en tecnología de punta...

Generar SQLs y ejecutarlos

Como hemos entrenado con los datos DDL, la estructura de la tabla ya está disponible para generar consultas SQL.

Probemos con una consulta sencilla.

sql = vn_milvus.generate_sql("what is the phone number of John Doe?")
vn_milvus.run_sql(sql)
SQL Prompt: [{'role': 'system', 'content': "You are a SQLite expert. Please help to generate a SQL query to answer the question. Your response should ONLY be based on the given context and follow the response guidelines and format instructions. \n===Tables \nCREATE TABLE Customer (\n    ID INTEGER PRIMARY KEY AUTOINCREMENT,\n    Name TEXT NOT NULL,\n    Company TEXT NOT NULL,\n    City TEXT NOT NULL,\n    Phone TEXT NOT NULL\n)\n\nCREATE TABLE User (\n    ID INTEGER PRIMARY KEY AUTOINCREMENT,\n    Username TEXT NOT NULL UNIQUE,\n    Email TEXT NOT NULL UNIQUE\n)\n\n\n===Additional Context \n\nABC Corp specializes in cutting-edge technology solutions and innovation.\n\nXYZ Inc is a global leader in manufacturing and supply chain management.\n\n===Response Guidelines \n1. If the provided context is sufficient, please generate a valid SQL query without any explanations for the question. \n2. If the provided context is almost sufficient but requires knowledge of a specific string in a particular column, please generate an intermediate SQL query to find the distinct strings in that column. Prepend the query with a comment saying intermediate_sql \n3. If the provided context is insufficient, please explain why it can't be generated. \n4. Please use the most relevant table(s). \n5. If the question has been asked and answered before, please repeat the answer exactly as it was given before. \n"}, {'role': 'user', 'content': 'What are the details of the customer named John Doe?'}, {'role': 'assistant', 'content': "SELECT * FROM Customer WHERE Name = 'John Doe'"}, {'role': 'user', 'content': 'what is the phone number of John Doe?'}]
Using model gpt-3.5-turbo for 367.25 tokens (approx)
LLM Response: SELECT Phone FROM Customer WHERE Name = 'John Doe'
# Teléfono
0 123-456-7890

He aquí una pregunta más compleja. La información del nombre de la empresa de fabricación se encuentra en los datos del documento, que es información de fondo. La consulta SQL generada recuperará la información del cliente basándose en el nombre específico de la empresa de fabricación.

sql = vn_milvus.generate_sql("which customer works for a manufacturing corporation?")
vn_milvus.run_sql(sql)
SQL Prompt: [{'role': 'system', 'content': "You are a SQLite expert. Please help to generate a SQL query to answer the question. Your response should ONLY be based on the given context and follow the response guidelines and format instructions. \n===Tables \nCREATE TABLE Company (\n    ID INTEGER PRIMARY KEY AUTOINCREMENT,\n    Name TEXT NOT NULL,\n    Industry TEXT NOT NULL,\n    Location TEXT NOT NULL,\n    EmployeeCount INTEGER NOT NULL\n)\n\nCREATE TABLE Customer (\n    ID INTEGER PRIMARY KEY AUTOINCREMENT,\n    Name TEXT NOT NULL,\n    Company TEXT NOT NULL,\n    City TEXT NOT NULL,\n    Phone TEXT NOT NULL\n)\n\n\n===Additional Context \n\nXYZ Inc is a global leader in manufacturing and supply chain management.\n\nABC Corp specializes in cutting-edge technology solutions and innovation.\n\n===Response Guidelines \n1. If the provided context is sufficient, please generate a valid SQL query without any explanations for the question. \n2. If the provided context is almost sufficient but requires knowledge of a specific string in a particular column, please generate an intermediate SQL query to find the distinct strings in that column. Prepend the query with a comment saying intermediate_sql \n3. If the provided context is insufficient, please explain why it can't be generated. \n4. Please use the most relevant table(s). \n5. If the question has been asked and answered before, please repeat the answer exactly as it was given before. \n"}, {'role': 'user', 'content': 'What are the details of the customer named John Doe?'}, {'role': 'assistant', 'content': "SELECT * FROM Customer WHERE Name = 'John Doe'"}, {'role': 'user', 'content': 'which customer works for a manufacturing corporation?'}]
Using model gpt-3.5-turbo for 384.25 tokens (approx)
LLM Response: SELECT * 
FROM Customer 
WHERE Company = 'XYZ Inc'
# ID Nombre Empresa Ciudad Teléfono
0 2 Jane Smith XYZ Inc Los Angeles 098-765-4321

Desconéctate de SQLite y Milvus y elimínalos para liberar recursos.

sql_connect.close()
milvus_client.close()

os.remove(sqlite_path)
if os.path.exists(milvus_uri):
    os.remove(milvus_uri)

Traducido porDeepLogo

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started
Feedback

¿Fue útil esta página?