#!/usr/bin/env python3 """ demo-sqlite-vec.py — Demo de sqlite-vec + Ollama embeddings Uso: pip install sqlite-vec ollama python demo-sqlite-vec.py Descripción: Demuestra cómo usar sqlite-vec para almacenar y buscar vectores de embeddings generados por Ollama. Este es el fundamento del RAG local que exploraremos en episodios posteriores. Flujo: 1. Carga la extensión sqlite-vec 2. Crea una tabla virtual para vectores de 768 dimensiones 3. Genera embeddings con Ollama (nomic-embed-text) 4. Inserta documentos con sus vectores 5. Busca por similitud semántica Requiere: - Ollama instalado y corriendo - Modelo nomic-embed-text descargado (ollama pull nomic-embed-text) - Python 3.10+ - pip install sqlite-vec ollama Referencia: https://github.com/asg017/sqlite-vec """ import sqlite3 import sys def main(): # --- Comprobar que tenemos los modelos necesarios -------------------- print("=" * 50) print("Demo: sqlite-vec + Ollama embeddings") print("=" * 50) print() # --- 1. Conectar a SQLite en memoria -------------------------------- print("[1/5] Conectando a SQLite en memoria...") conn = sqlite3.connect(":memory:") conn.enable_load_extension(True) try: conn.load_extension("vec0") print(" ✓ Extensión sqlite-vec cargada") except sqlite3.OperationalError as e: print(f" ✗ No se pudo cargar vec0: {e}") print(" Asegúrate de tener sqlite-vec instalado:") print(" pip install sqlite-vec") sys.exit(1) # --- 2. Crear tabla vectorial --------------------------------------- print() print("[2/5] Creando tabla vectorial vec_docs (768 dimensiones)...") conn.execute(""" CREATE VIRTUAL TABLE vec_docs USING vec0( embedding float[768] ) """) print(" ✓ Tabla vec_docs creada") # --- 3. Preparar documentos ----------------------------------------- print() print("[3/5] Preparando documentos de ejemplo...") documentos = [ { "id": 1, "titulo": "Linux", "texto": "Linux es un sistema operativo libre y de código abierto " "basado en el kernel de Linux. Fue creado por Linus Torvalds " "en 1991 y se distribuye bajo la GPL.", }, { "id": 2, "titulo": "Python", "texto": "Python es un lenguaje de programación interpretado, " "multiparadigma y de alto nivel. Creado por Guido van Rossum " "en 1991, es conocido por su sintaxis clara y legible.", }, { "id": 3, "titulo": "IA Local", "texto": "La inteligencia artificial local permite ejecutar modelos " "de lenguaje en tu propio hardware sin conexión a internet. " "Herramientas como Ollama facilitan este proceso.", }, { "id": 4, "titulo": "Docker", "texto": "Docker es una plataforma de contenedores que permite " "empaquetar aplicaciones y sus dependencias en unidades " "portables llamadas contenedores.", }, ] for doc in documentos: print(f" - [{doc['id']}] {doc['titulo']}") # --- 4. Generar embeddings e insertar -------------------------------- print() print("[4/5] Generando embeddings con Ollama (nomic-embed-text)...") print(" (Esto puede tardar unos segundos por documento)") print() try: import ollama except ImportError: print(" ✗ No se pudo importar ollama. Instálalo con:") print(" pip install ollama") sys.exit(1) for doc in documentos: # Generar embedding response = ollama.embeddings(model="nomic-embed-text", prompt=doc["texto"]) vector = response["embedding"] # Insertar en sqlite-vec conn.execute( "INSERT INTO vec_docs(rowid, embedding) VALUES (?, ?)", [doc["id"], str(vector)], ) print(f" ✓ Embedding generado para: {doc['titulo']}") # --- 5. Búsqueda semántica ------------------------------------------- print() print("[5/5] Búsqueda semántica...") print() # Consulta de ejemplo consulta = "¿Qué sistema operativo libre puedo usar?" print(f' Consulta: "{consulta}"') print() # Generar embedding de la consulta response = ollama.embeddings(model="nomic-embed-text", prompt=consulta) query_vector = response["embedding"] # Buscar en sqlite-vec cursor = conn.execute( """ SELECT rowid, distance FROM vec_docs WHERE embedding match ? ORDER BY distance LIMIT 3 """, [str(query_vector)], ) resultados = cursor.fetchall() print(" Resultados (más cercano primero):") print() for rowid, distancia in resultados: doc = documentos[rowid - 1] # rowid empieza en 1 print(f" [{rowid}] {doc['titulo']} (distancia: {distancia:.4f})") print(f" {doc['texto'][:80]}...") print() # --- Cerrar conexión ------------------------------------------------ conn.close() print("=" * 50) print("Demo completada") print() print(" Este es el fundamento del RAG local.") print(" En episodios posteriores veremos cómo:") print(" - Indexar documentos completos") print(" - Combinar búsqueda semántica + keywords") print(" - Integrar con Ollama para respuestas contextuales") print("=" * 50) if __name__ == "__main__": main()