Saltar al contenido principal

Tutorial de DuckDB: Construir proyectos de IA

Este tutorial te guía a través de las principales características y aplicaciones prácticas de DuckDB, incluyendo la creación de tablas, la realización de análisis de datos, la creación de una aplicación RAG y el uso de un motor de consultas SQL con LLM.
Actualizado 29 jul 2024  · 13 min de lectura

Recientemente, DuckDB salió de beta y lanzó su versión estable, ganando popularidad rápidamente a medida que varios marcos de datos lo integran en sus ecosistemas. Esto hace que sea un buen momento para aprender DuckDB, de modo que puedas mantenerte al día en el siempre cambiante mundo de los datos y la IA.

En este tutorial, aprenderemos sobre DuckDB y sus principales características con ejemplos de código. Nos centraremos principalmente en cómo podemos integrarlo con los marcos actuales de IA. Para ello, trabajaremos en dos proyectos. En primer lugar, bedificaremos una aplicación de Generación Mejorada por Recuperación (RAG) utilizando DuckDB como base de datos vectorial. A continuación, utilizaremos DuckDB como motor de consulta de IA para analizar datos utilizando lenguaje natural en lugar de SQL .

¿Qué es DuckDB?

DuckDB es un sistema de gestión de bases de datos analíticas (SGBD) en memoria, moderno y de alto rendimiento, diseñado para soportar consultas analíticas complejas. Es un SGBD relacional (orientado a tablas) que admite el Lenguaje de Consulta Estructurado (SQL). 

DuckDB combina la sencillez y facilidad de uso de SQLite con las capacidades de alto rendimiento necesarias para las cargas de trabajo analíticas, lo que lo convierte en una opción excelente para los científicos y analistas de datos.

Características principales

  1. Funcionamiento sencillo: DuckDB no tiene servidor, no tiene dependencias externas y está incrustado dentro de un proceso anfitrión. Esto facilita su instalación y despliegue, ya que sólo requiere un compilador de C++11 para su construcción.
  2. Rico en funciones: Admite amplias funciones de gestión de datos SQL. DuckDB también ofrece una profunda integración con Python y R, lo que lo hace adecuado para la ciencia de datos y el análisis interactivo de datos.
  3. Consultas analíticas rápidas: DuckDB utiliza un motor de ejecución de consultas vectorializado en columnas optimizado para la analítica, que permite el procesamiento paralelo de consultas y el manejo eficaz de grandes conjuntos de datos. 
  4. Libre y de código abierto: Se publica bajo la permisiva Licencia MIT, por lo que es de uso libre y de código abierto. 
  5. Portabilidad: Sin dependencias externas, DuckDB es altamente portable y puede funcionar en varios sistemas operativos (Linux, macOS, Windows) y arquitecturas de CPU (x86, ARM). Incluso puede ejecutarse en navegadores web utilizando DuckDB-Wasm.
  6. Extensibilidad: DuckDB admite un mecanismo de ampliación flexible, que permite añadir nuevos tipos de datos, funciones, formatos de archivo y sintaxis SQL. 
  7. Pruebas minuciosas: Se somete a pruebas intensivas mediante Integración Continua, con un conjunto de pruebas que contiene millones de consultas. Esto garantiza la estabilidad y fiabilidad en diferentes plataformas y compiladores.

Primeros pasos con DuckDB

En esta sección, aprenderemos a configurar DuckDB, cargar archivos CSV, realizar análisis de datos y conocer las relaciones y las funciones de consulta. 

Empezaremos instalando el paquete DuckDB Python.

pip install duckdb --upgrade

Crear la base de datos DuckDB

Para crear la base de datos persistente, sólo tienes que utilizar la función connect y proporcionarle el nombre de la base de datos. 

import duckdb
con = duckdb.connect("datacamp.duckdb")

Creará un archivo de base de datos en tu directorio local. 

Directorio de archivos en el DataLab de DataCamp

Cargaremos un archivo CSV y crearemos una tabla "banco". El conjunto de datos que estamos utilizando está disponible en DataLab y se llama Marketing bancario. Se trata de campañas de marketing directo de una entidad bancaria portuguesa mediante llamadas telefónicas.

Para cargar el archivo CSV, primero tienes que crear una Tabla utilizando SQL y luego utilizar la función read_csv() dentro del script SQL para cargar el archivo. Es así de sencillo. 

A continuación, validaremos nuestra tabla ejecutando el script SQL que muestra todas las tablas de la base de datos y utilizando la función fetchdf para mostrar el resultado como un DataFrame pandas

Nota: Estamos utilizando DataLab de DataCamp como editor de código. DataLab es un cuaderno Jupyter en la nube al que puedes acceder gratuitamente si tienes una cuenta en DataCamp. 

con.execute("""
    CREATE TABLE IF NOT EXISTS bank AS 
    SELECT * FROM read_csv('bank-marketing.csv')
""")
con.execute("SHOW ALL TABLES").fetchdf()

Mostrar todas las tablas de la base de datos.

Ahora que hemos creado con éxito nuestra primera tabla, ejecutaremos una consulta de nivel principiante para analizar los datos y mostrar el resultado como un DataFrame.

con.execute("SELECT * FROM bank WHERE duration < 100 LIMIT 5").fetchdf()

resultado de la consulta SQL

DuckDB está integrado de forma nativa en el nuevo DataLab de DataCamp. Obtén más información leyendo el blog "DuckDB hace de SQL un ciudadano de primera clase en DataLab"y utiliza la celda SQL interactiva para analizar datos.

Relaciones DuckDB

Las relaciones DuckDB son esencialmente tablas que pueden consultarse utilizando la API Relacional. Esta API permite encadenar varias operaciones de consulta sobre fuentes de datos como Pandas DataFrames. En lugar de utilizar consultas SQL, lo harás encadenando varias funciones de Python para analizar los datos. 

Por ejemplo, cargaremos un archivo CSV para crear la relación DuckDB. Para analizar la tabla, puedes encadenar las funciones de filtro y límite.

bank_duck = duckdb.read_csv("bank-marketing.csv",sep=";")
bank_duck.filter("duration < 100").limit(3).df()

Resultado de la consulta de relaciones

También podemos crear relaciones cargando la tabla desde la base de datos DuckDB. 

rel = con.table("bank")
rel.columns
['age',
 'job',
 'marital',
 'education',
 'default',
 'housing',
 'loan',
 'contact',
 'month',
 'day_of_week',
 'duration',
 'campaign',
 'pdays',
 'previous',
 'poutcome',
 'emp.var.rate',
 'cons.price.idx',
 'cons.conf.idx',
 'euribor3m',
 'nr.employed',
 'y']

Escribamos una relación que utilice varias funciones para analizar los datos. 

rel.filter("duration < 100").project("job,education,loan").order("job").limit(3).df()

Tenemos tres filas y columnas ordenadas por trabajo y filtradas por la columna de duración.

resultado de la consulta de relaciones

Función de consulta de DuckDB

La función de consulta de DuckDB permite ejecutar consultas SQL dentro de la base de datos, devolviendo resultados que pueden convertirse en varios formatos para su posterior análisis.

En el ejemplo de código, estamos ejecutando la consulta SQL para averiguar los puestos de trabajo de los clientes mayores de 30 años, contar el número de clientes contactados para cada puesto de trabajo y calcular la duración media de la campaña.

Toma el examen Fundamentos de SQL para aprender a gestionar una base de datos relacional y ejecutar consultas para análisis de datos sencillos.

res = duckdb.query("""SELECT 
                            job,
                            COUNT(*) AS total_clients_contacted,
                            AVG(duration) AS avg_campaign_duration,
                        FROM 
                            'bank-marketing.csv'
                        WHERE 
                            age > 30
                        GROUP BY 
                            job
                        ORDER BY 
                            total_clients_contacted DESC;""")
res.df()

resultado de la función de consulta.

Ahora cerraremos la conexión a la base de datos y liberaremos todos los recursos asociados a esa conexión, evitando posibles fugas de memoria y de manejadores de archivo.

con.close()

Si tienes problemas para ejecutar el código anterior, consulta la sección Introducción a DuckDB espacio de trabajo.

Crear una aplicación RAG con DuckDB

En el primer proyecto, aprenderemos a construir una aplicación RAG con LlamaIndex y a utilizar DuckDB como base de datos vectorial y recuperador. 

Puesta en marcha

Instala todos los paquetes Python necesarios que se utilizarán para crear y recuperar el índice. 

%%capture
%pip install duckdb
%pip install llama-index
%pip install llama-index-vector-stores-duckdb

Importa el paquete Python necesario con las funciones. 

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.vector_stores.duckdb import DuckDBVectorStore
from llama_index.core import StorageContext

from IPython.display import Markdown, display

Configurar el GPT-4o y el modelo de incrustación

Para el modelo lingüístico, utilizaremos el último modelo GPT4o y la API OpenAI. Para crear el cliente del gran modelo lingüístico (LLM), sólo tienes que proporcionar un nombre de modelo y clave API.

import os
from llama_index.llms.openai import OpenAI

llm = OpenAI(model="gpt-4o",api_key=os.environ["OPENAI_API_KEY"])

A continuación, crearemos el cliente del modelo de incrustación utilizando el modelo OpenAI text-embedding-3-small

Nota: Proporcionar una clave de la API de OpenAI es opcional si la variable de entorno se establece con el nombre "OPENAI_API_KEY" en tu entorno de desarrollo.  

from llama_index.embeddings.openai import OpenAIEmbedding
embed_model = OpenAIEmbedding(
    model="text-embedding-3-small",
)

Haremos que los modelos LLM e Incrustación de OpenAI sean globales para que los utilicen todas las funciones de LlamaIndex. En resumen, estos modelos se establecerán por defecto.

from llama_index.core import Settings

Settings.llm = llm
Settings.embed_model = embed_model

Utilizar DuckDB como base de datos vectorial

Para nuestro proyecto, cargaremos los archivos PDF desde la carpeta de datos. Estos archivos PDF son tutoriales de DataCamp que se guardan como archivos PDF utilizando la función de impresión del navegador. 

Proporciona el directorio de carpetas a la función SimpleDirectoryReader y carga los datos. 

documents = SimpleDirectoryReader("Data").load_data()

lista de archivos de la carpeta Datos

A continuación, crea el almacén vectorial llamado "blog" utilizando una base de datos existente llamada "datacamp.duckdb". Después, convierte los datos del PDF en incrustaciones y almacénalos en el almacén vectorial.

vector_store = DuckDBVectorStore(database_name = "datacamp.duckdb",table_name = "blog",persist_dir="./", embed_dim=1536)
storage_context = StorageContext.from_defaults(vector_store=vector_store)

index = VectorStoreIndex.from_documents(
    documents, storage_context=storage_context
)

Para comprobar si nuestro almacén vectorial se ha creado correctamente, conectaremos la base de datos utilizando la API Python de DuckDB y ejecutaremos la consulta SQL para mostrar todas las tablas de la base de datos. 

import duckdb
con = duckdb.connect("datacamp.duckdb")

con.execute("SHOW ALL TABLES").fetchdf()

Tenemos dos tablas: una tabla promocional "banco" y una tabla "blog", que es un almacén de vectores. La tabla "blog" tiene una columna "incrustación" donde se almacenan todas las incrustaciones.

Mostrar todas las tablas de la DuckDB

Crear una aplicación RAG sencilla

Convierte el índice en el motor de consulta, que primero buscará automáticamente documentos similares en la base de datos vectorial y utilizará el contexto adicional para generar la respuesta. 

Para probar el motor de consulta RAG, haremos la pregunta sobre el tutorial. 

query_engine = index.as_query_engine()
response = query_engine.query("Who wrote 'GitHub Actions and MakeFile: A Hands-on Introduction'?")
display(Markdown(f"<b>{response}</b>"))

Y la respuesta es correcta.

The author of "GitHub Actions and MakeFile: A Hands-on Introduction" is Abid Ali Awan.

Crear un chatbot RAG con memoria

Ahora, vamos a crear una aplicación RAG avanzada que utilice el historial de conversaciones para generar la respuesta. Para ello, tenemos que crear un búfer de memoria de chat y luego un motor de chat con memoria, LLM y recuperador de almacenes vectoriales. 

from llama_index.core.memory import ChatMemoryBuffer
from llama_index.core.chat_engine import CondensePlusContextChatEngine

memory = ChatMemoryBuffer.from_defaults(token_limit=3900)

chat_engine = CondensePlusContextChatEngine.from_defaults(
    index.as_retriever(),
    memory=memory,
    llm=llm
)

response = chat_engine.chat(
    "What is the easiest way of finetuning the Llama 3 model? Please provide step-by-step instructions."
)

display(Markdown(response.response))

Preguntamos al motor de chat cómo afinar el modelo Llama 3, y utilizó el almacén vectorial para dar una respuesta muy precisa.

Resultado del chatbot RAG con memoria

Para comprobar si el búfer de memoria funciona correctamente, haremos una pregunta complementaria.

response = chat_engine.chat(
    "Could you please provide more details about the Post Fine-Tuning Steps?"
)
display(Markdown(response.response))

El motor del chat recordaba la conversación anterior y respondía en consecuencia. 

resultado del chatbot RAG con memoria con pregunta de seguimiento.

Si tienes problemas para ejecutar el código anterior, echa un vistazo a la sección Crear una aplicación RAG con DuckDB espacio de trabajo.

Construir un motor de consulta SQL DuckDB utilizando un LLM

En el segundo proyecto, utilizaremos DuckDB como motor de consulta SQL. Se trata de integrar el motor de la base de datos con el modelo GPT-4o para generar respuestas en lenguaje natural a preguntas sobre la base de datos. 

Instala duckdb-engine para crear un motor de base de datos utilizando SQLAlchemy.

%pip install duckdb-engine -q

Cargar la base de datos DuckDB

Cargaremos la base de datos DuckDB utilizando la función create_engine y luego escribiremos una consulta SQL sencilla para comprobar si se ha cargado correctamente. 

from sqlalchemy import create_engine

engine = create_engine("duckdb:///datacamp.duckdb")
with engine.connect() as connection:
    cursor = connection.exec_driver_sql("SELECT * FROM bank LIMIT 3")
    print(cursor.fetchall())

Prefecto. Nuestro motor de base de datos DuckDB está listo para ser utilizado. 

[(56, 'housemaid', 'married', 'basic.4y', 'no', 'no', 'no', 'telephone', 'may', 'mon', 261, 1, 999, 0, 'nonexistent', 1.1, 93.994, -36.4, 4.857, 5191.0, 'no'), (57, 'services', 'married', 'high.school', 'unknown', 'no', 'no', 'telephone', 'may', 'mon', 149, 1, 999, 0, 'nonexistent', 1.1, 93.994, -36.4, 4.857, 5191.0, 'no'), (37, 'services', 'married', 'high.school', 'no', 'yes', 'no', 'telephone', 'may', 'mon', 226, 1, 999, 0, 'nonexistent', 1.1, 93.994, -36.4, 4.857, 5191.0, 'no')]

Ahora, tenemos que crear una Herramienta de base de datos utilizando la función SQLDatabase. Proporciónale un objeto motor y un nombre de tabla. 

from llama_index.core import SQLDatabase
sql_database = SQLDatabase(engine, include_tables=["bank"])

Construir el motor de consulta SQL

Crea el motor de consultas SQL utilizando la función NLSQLTableQueryEngine proporcionándole el objeto de base de datos SQL LlamaIndex.

from llama_index.core.query_engine import NLSQLTableQueryEngine

query_engine = NLSQLTableQueryEngine(sql_database)

Haz la pregunta del motor de consulta sobre la tabla "banco" en lenguaje natural. 

response = query_engine.query("Which is the longest running campaign?")


print(response.response)

En respuesta, obtendremos la respuesta a tu consulta en lenguaje natural. Esto es impresionante, ¿no crees?

The longest running campaign in the database has a duration of 4918 days.

Formulemos una pregunta compleja.

response = query_engine.query("Which type of job has the most housing loan?")
print(response.response)

La respuesta es precisa, con información adicional.  

The job type with the most housing loans is 'admin.' with 5559 housing loans. This is followed by 'blue-collar' with 4710 housing loans and 'technician' with 3616 housing loans. Other job types with significant housing loans include 'services', 'management', 'retired', 'entrepreneur', and 'self-employed'.

Para comprobar lo que ocurre en el back end, imprimiremos los metadatos. 

print(response.metadata)

Como vemos, GPT-4o genera primero la consulta SQL, ejecuta la consulta para obtener el resultado y utiliza el resultado para generar la respuesta. Este proceso de varios pasos se consigue mediante dos líneas de código. 

{'d4ddf03c-337e-4ee6-957a-5fd2cfaa4b1c': {}, 'sql_query': "SELECT job, COUNT(housing) AS housing_loan_count\nFROM bank\nWHERE housing = 'yes'\nGROUP BY job\nORDER BY housing_loan_count DESC;", 'result': [('admin.', 5559), ('blue-collar', 4710), ('technician', 3616), ('services', 2050), ('management', 1490), ('retired', 892), ('entrepreneur', 779), ('self-employed', 740), ('unemployed', 557), ('housemaid', 540), ('student', 471), ('unknown', 172)], 'col_keys': ['job', 'housing_loan_count']}

Cierra el motor cuando hayas terminado con el proyecto. 

engine.close()

Si tienes problemas para ejecutar el código anterior, echa un vistazo a la página Motor de consultas SQL DuckDB espacio de trabajo.

Conclusión

DuckDB es rápido, fácil de usar y se integra perfectamente con numerosos marcos de datos e IA. Como científico de datos, descubrirás que sólo te llevará unos minutos acostumbrarte a su API y empezar a utilizarlo como cualquier otro paquete de Python. Una de las mejores características de DuckDB es que no tiene dependencias, lo que significa que puedes utilizarlo prácticamente en cualquier sitio sin preocuparte del alojamiento o de configuraciones adicionales.

En este tutorial, hemos aprendido sobre DuckDB y sus principales características. También hemos explorado la API Python de DuckDB, utilizándola para crear una tabla y realizar análisis de datos sencillos. La segunda mitad del tutorial abarcó dos proyectos: uno sobre una aplicación de Generación Mejorada por Recuperación (RAG) con DuckDB como base de datos vectorial y otro demostrando DuckDB como motor de consulta SQL.

Antes de lanzarte a utilizar un motor de consulta SQL o a integrar una base de datos con la IA, necesitas unos conocimientos básicos de SQL y análisis de datos. Puedes escribir la consulta, pero ¿cómo sabrías qué pregunta hacer? Aquí es donde entran en juego unos conocimientos básicos de análisis de datos y SQL. Puedes adquirir estos conocimientos completando el Analista de Datos Asociado en SQL en SQL.

Temas

Los mejores cursos de DataCamp

curso

Vector Databases for Embeddings with Pinecone

3 hr
369
Discover how the Pinecone vector database is revolutionizing AI application development!
Ver detallesRight Arrow
Comienza el curso
Ver másRight Arrow
Relacionado
An AI juggles tasks

blog

Cinco proyectos que puedes crear con modelos de IA generativa (con ejemplos)

Aprende a utilizar modelos de IA generativa para crear un editor de imágenes, un chatbot similar a ChatGPT con pocos recursos y una aplicación clasificadora de aprobación de préstamos y a automatizar interacciones PDF y un asistente de voz con GPT.
Abid Ali Awan's photo

Abid Ali Awan

10 min

blog

7 proyectos de IA para todos los niveles

Desarrolla tu portafolio y mejora tus habilidades para crear soluciones innovadoras a problemas complejos trabajando en proyectos de IA.
Abid Ali Awan's photo

Abid Ali Awan

8 min

tutorial

Tutorial de la API de OpenAI Assistants

Una visión completa de la API Assistants con nuestro artículo, que ofrece una mirada en profundidad a sus características, usos en la industria, guía de configuración y las mejores prácticas para maximizar su potencial en diversas aplicaciones empresariales.
Zoumana Keita 's photo

Zoumana Keita

14 min

tutorial

Guía para principiantes de la API de OpenAI: Tutorial práctico y prácticas recomendadas

Este tutorial te presenta la API de OpenAI, sus casos de uso, un enfoque práctico para utilizar la API y todas las prácticas recomendadas que debes seguir.
Arunn Thevapalan's photo

Arunn Thevapalan

13 min

tutorial

Introducción al uso de DALL-E 3: Consejos, ejemplos y funciones

Descubre cómo utilizar DALL-E 3 para crear imágenes. Descubre qué es DALL-E 3, sus principales características y cómo utilizar las instrucciones para obtener los mejores resultados.
Kurtis Pykes 's photo

Kurtis Pykes

16 min

tutorial

Tutorial sobre cómo crear aplicaciones LLM con LangChain

Explore el potencial sin explotar de los grandes modelos lingüísticos con LangChain, un marco Python de código abierto para crear aplicaciones avanzadas de IA.
Moez Ali's photo

Moez Ali

12 min

Ver másVer más