{"id":16222,"date":"2025-12-06T03:08:04","date_gmt":"2025-12-06T02:08:04","guid":{"rendered":"https:\/\/hopla.tech\/?p=16222"},"modified":"2025-12-10T10:35:47","modified_gmt":"2025-12-10T09:35:47","slug":"busqueda-semantica-ollama-postgresql","status":"publish","type":"post","link":"https:\/\/hopla.tech\/en\/busqueda-semantica-ollama-postgresql\/","title":{"rendered":"B\u00fasqueda sem\u00e1ntica estilo ChatGPT con Ollama y PostgreSQL"},"content":{"rendered":"\n<p style=\"line-height:1.8\">Para empezar, \u00bfsab\u00edas que puedes construir tu propio motor de b\u00fasqueda sem\u00e1ntica, similar al que utiliza ChatGPT, directamente en tu infraestructura, sin depender de servicios en la nube?<\/p>\n\n\n\n<p style=\"line-height:1.8\">Gracias a <strong>Ollama<\/strong>, una herramienta <em>open source<\/em> que permite ejecutar modelos de lenguaje grandes (LLMs) de forma local, y a <strong>PostgreSQL<\/strong> con su extensi\u00f3n <strong>pgvector<\/strong>, es posible crear un sistema capaz de comprender el significado del texto, no s\u00f3lo las palabras.<\/p>\n\n\n\n<p style=\"line-height:1.8\">A continuaci\u00f3n te mostraremos c\u00f3mo integrar Ollama y PostgreSQL para crear una b\u00fasqueda inteligente: desde generar embeddings locales, hasta almacenarlos y consultarlos en tu base de datos con pgvector.<br>De este modo, todo sin enviar tus datos fuera de tu entorno.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-entorno\"><strong>Entorno<\/strong><\/h3>\n\n\n\n<p style=\"line-height:1.8\"><strong>En particular,<\/strong> para reproducir este ejemplo se utiliz\u00f3 el siguiente entorno:<\/p>\n\n\n\n<ul style=\"line-height:1.8\" class=\"wp-block-list\">\n<li>Rocky Linux 8<br><\/li>\n\n\n\n<li>PostgreSQL 15<br><\/li>\n\n\n\n<li>Extensi\u00f3n pgvector<br><\/li>\n\n\n\n<li>Ollama 0.12.3 corriendo localmente (ollama server)<\/li>\n<\/ul>\n\n\n\n<ul style=\"line-height:1.8\" class=\"wp-block-list\">\n<li>Modelo de embeddings:<br><\/li>\n<\/ul>\n\n\n\n<p>ollama pull nomic-embed-text<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Python 3.6.8 con las siguientes librer\u00edas:<br><\/li>\n<\/ul>\n\n\n\n<p>pip3 install psycopg2-binary requests<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-arquitectura-general\"><strong>Arquitectura general<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Componente<\/strong><\/td><td><strong>Funci\u00f3n<\/strong><\/td><\/tr><tr><td>Ollama + nomic-embed-text<\/td><td>Genera embeddings de texto localmente<\/td><\/tr><tr><td>PostgreSQL + pgvector&nbsp;<\/td><td>Almacena y compara embeddings mediante distancia coseno<\/td><\/tr><tr><td>Python<\/td><td>Intermediario entre Ollama y PostgreSQL<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-crear-tabla-en-postgresql\"><strong>Crear tabla en PostgreSQL<\/strong><\/h3>\n\n\n\n<p style=\"line-height:1.8\">CREATE EXTENSION IF NOT EXISTS vector;<\/p>\n\n\n\n<p style=\"line-height:1.8\">CREATE TABLE docs (<\/p>\n\n\n\n<p style=\"line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;id serial PRIMARY KEY,<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;content text,<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;embedding vector(1536)<\/p>\n\n\n\n<p>);<\/p>\n\n\n\n<p style=\"line-height:1.8\"><strong>En concreto,<\/strong> el tama\u00f1o 1536 en vector(1536) corresponde a la dimensi\u00f3n de embedding generado por el modelo nomic-embed-text de Ollama.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-insertar-datos-y-generar-embeddings-insert-py\"><strong>Insertar datos y generar embeddings (<\/strong><strong>insert.py<\/strong><strong>)<\/strong><\/h3>\n\n\n\n<p>En resumen, este script realiza tres tareas principales:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li style=\"line-height:1.8\">Comienza por conectarse a PostgreSQL.<\/li>\n\n\n\n<li style=\"line-height:1.8\">A continuaci\u00f3n env\u00eda cada texto a Ollama para generar su embedding.<\/li>\n\n\n\n<li style=\"line-height:1.8\">Para finalizar inserta el texto y su vector en la base de datos.<\/li>\n<\/ol>\n\n\n\n<div style=\"height:43px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<blockquote class=\"wp-block-quote is-style-default has-background is-layout-flow wp-block-quote-is-layout-flow\" style=\"border-top-left-radius:49px;border-top-right-radius:49px;border-bottom-left-radius:49px;border-bottom-right-radius:49px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:169;padding-right:169;padding-bottom:169;padding-left:169\">\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">  #!\/usr\/bin\/env python3<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">import requests<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">import json<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">import psycopg2<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\"># Configuraci\u00f3n de PostgreSQL<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">DB_NAME = \u00abpostgres\u00bb<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">DB_USER = \u00abpostgres\u00bb<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">DB_PASSWORD = \u00abpg123\u00bb<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">DB_HOST = \u00ablocalhost\u00bb<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">DB_PORT = 5432<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\"># Conexi\u00f3n a PostgreSQL<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">conn = psycopg2.connect(<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;dbname=DB_NAME,<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;user=DB_USER,<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;password=DB_PASSWORD,<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;host=DB_HOST,<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;port=DB_PORT<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">)<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">cur = conn.cursor()<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\"># Textos a insertar<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">texts = [<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;\u00abPostgreSQL es un motor de base de datos potente y de c\u00f3digo abierto.\u00bb,<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;\u00abPython es un lenguaje de programaci\u00f3n muy popular.\u00bb,<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;\u00abEl cielo es azul debido a la dispersi\u00f3n de Rayleigh.\u00bb<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">]<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">for text in texts:<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;# Generar embedding usando Ollama<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;response = requests.post(<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\u00abhttp:\/\/localhost:11434\/api\/embeddings\u00bb,<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data=json.dumps({<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\u00abmodel\u00bb: \u00abnomic-embed-text\u00bb,<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\u00abprompt\u00bb: text<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}),<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;headers={\u00abContent-Type\u00bb: \u00abapplication\/json\u00bb}<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;)<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;# Validar la respuesta<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;if response.status_code != 200:<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(\u00abError al obtener embedding:\u00bb, response.text)<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue&nbsp; # Saltar este texto y continuar con los dem\u00e1s<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;embedding = list(map(float, response.json()[\u00abembedding\u00bb]))<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;# Insertar texto y embedding en PostgreSQL<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;cur.execute(<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\u00abINSERT INTO docs (content, embedding) VALUES (%s, %s)\u00bb,<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(text, embedding)<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;)<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\"># Confirmar cambios y cerrar conexi\u00f3n<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">conn.commit()<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">cur.close()<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">conn.close()<\/p>\n\n\n\n<p class=\"has-text-align-left has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">print(\u00abEmbeddings insertados correctamente\u00bb)<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-busqueda-semantica-search-py\"><strong>B\u00fasqueda sem\u00e1ntica (<\/strong><strong>search.py<\/strong><strong>)<\/strong><\/h3>\n\n\n\n<p>Del mismo modo este script realiza tres tareas principales:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li style=\"line-height:1.8\">Primero se conecta a PostgreSQL.<\/li>\n\n\n\n<li style=\"line-height:1.8\">Despu\u00e9s genera el embedding del texto de b\u00fasqueda usando Ollama.<\/li>\n\n\n\n<li style=\"line-height:1.8\">Para finalizar compara el embedding con los documentos existentes mediante <strong>pgvector<\/strong> y devuelve los resultados m\u00e1s similares.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">  #!\/usr\/bin\/env python3 <\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\"># Librer\u00edas para llamadas HTTP y manejo de JSON<br>import requests<br>import json<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\"><br># Librer\u00eda para conectarse a PostgreSQL <\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">import psycopg2<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\"><br># Configuraci\u00f3n de PostgreSQL<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">DB_NAME = \u00abpostgres\u00bb<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">DB_USER = \u00abpostgres\u00bb<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">DB_PASSWORD = \u00abpg123\u00bb<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">DB_HOST = \u00ablocalhost\u00bb<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">DB_PORT = 5432<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\"># Conexi\u00f3n a PostgreSQL<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">conn = psycopg2.connect(<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;dbname=DB_NAME,<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;user=DB_USER,<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;password=DB_PASSWORD,<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;host=DB_HOST,<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;port=DB_PORT<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">)<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">cur = conn.cursor()<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\"># Texto de b\u00fasqueda<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">query_text = \u00ab\u00bfPor qu\u00e9 el cielo es azul?\u00bb<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\"># Obtener embedding desde Ollama<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">response = requests.post(<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;\u00abhttp:\/\/localhost:11434\/api\/embeddings\u00bb,<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;headers={\u00abContent-Type\u00bb: \u00abapplication\/json\u00bb},<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;data=json.dumps({<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\u00abmodel\u00bb: \u00abnomic-embed-text\u00bb,<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\u00abprompt\u00bb: query_text<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;})<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">)<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\"># Validar la respuesta<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">if response.status_code != 200:<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;print(\u00abError al obtener embedding:\u00bb, response.text)<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;exit(1)<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">query_embedding = list(map(float, response.json()[\u00abembedding\u00bb]))<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\"># Consulta sem\u00e1ntica en PostgreSQL<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">cur.execute(\u00ab\u00bb\u00bb<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;SELECT content, embedding &lt;=&gt; %s::vector AS similarity<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;FROM docs<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;ORDER BY similarity<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;LIMIT 3<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">\u00ab\u00bb\u00bb, (query_embedding,))<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">print(\u00abResultados de b\u00fasqueda sem\u00e1ntica:\\n\u00bb)<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">for content, similarity in cur.fetchall():<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">&nbsp;&nbsp;&nbsp;&nbsp;print(f\u00bbContenido: {content}\\nSimilitud: {similarity}\\n\u00bb)<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">cur.close()<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">conn.close()<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-ejemplo-de-salida\"><strong>Ejemplo de salida<\/strong><\/h3>\n\n\n\n<p><strong>Por ejemplo,<\/strong> resultados de b\u00fasqueda sem\u00e1ntica:<\/p>\n\n\n\n<p>Contenido: El cielo es azul debido a la dispersi\u00f3n de Rayleigh.<\/p>\n\n\n\n<p>Similitud: 0.22066058643992392<\/p>\n\n\n\n<p>Contenido: Python es un lenguaje de programaci\u00f3n muy popular.<\/p>\n\n\n\n<p>Similitud: 0.5083679530423353<\/p>\n\n\n\n<p>Contenido: PostgreSQL es un motor de base de datos potente y de c\u00f3digo abierto.<\/p>\n\n\n\n<p>Similitud: 0.543805990239008<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-crear-un-indice-para-acelerar-las-busquedas-opcional\"><strong>Crear un \u00edndice para acelerar las b\u00fasquedas (opcional)<\/strong><\/h3>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">CREATE INDEX ON docs USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);<\/p>\n\n\n\n<p class=\"has-background\" style=\"border-style:none;border-width:0px;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background-color:#eeeeee;margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:80;padding-right:72;padding-bottom:103;padding-left:150;line-height:1.8\">ANALYZE docs;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-conclusion\"><strong>Conclusi\u00f3n<\/strong><\/h3>\n\n\n\n<p style=\"line-height:1.8\"><strong>En conclusi\u00f3n,<\/strong> con Python y PostgreSQL, puedes construir tu propio motor de b\u00fasqueda sem\u00e1ntica completamente local, privado y extensible. PostgreSQL, junto con su extensi\u00f3n pgvector, act\u00faa como el coraz\u00f3n del sistema, almacenando y comparando los embeddings de manera eficiente y confiable. <strong>De este modo,<\/strong> este enfoque te permite aprovechar el poder de los modelos de lenguaje modernos sin depender de servicios externos ni exponer tus datos.<br><br>Adem\u00e1s, la arquitectura es f\u00e1cilmente ampliable: puedes integrar modelos como Llama3 de Meta AI a trav\u00e9s de Ollama, de manera que tu sistema no solo busque informaci\u00f3n, sino que tambi\u00e9n genere respuestas contextuales y razonadas en tiempo real, con todo el control y la seguridad que ofrece una base de datos como PostgreSQL.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"850\" src=\"https:\/\/hopla.tech\/wp-content\/uploads\/2025\/12\/image-1024x850.png\" alt=\"\" class=\"wp-image-16223\" srcset=\"https:\/\/hopla.tech\/wp-content\/uploads\/2025\/12\/image-1024x850.png 1024w, https:\/\/hopla.tech\/wp-content\/uploads\/2025\/12\/image.png 1600w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Diagrama de arquitectura de b\u00fasqueda sem\u00e1ntica con Python, Ollama (nomic-embed-text), PostgreSQL y pgvector<\/figcaption><\/figure>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A continuaci\u00f3n te mostraremos c\u00f3mo integrar Ollama y PostgreSQL para crear una b\u00fasqueda inteligente: desde generar embeddings locales, hasta almacenarlos y consultarlos en tu base de datos con pgvector.<br \/>\nDe este modo, todo sin enviar tus datos fuera de tu entorno.<\/p>","protected":false},"author":3,"featured_media":16249,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[284],"tags":[771,769,770,177],"class_list":["post-16222","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-postgresql","tag-busqueda-semantica","tag-ollama","tag-pgvector","tag-postgresql"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.4 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>B\u00fasqueda sem\u00e1ntica con Ollama y PostgreSQL<\/title>\n<meta name=\"description\" content=\"Crea una b\u00fasqueda sem\u00e1ntica con Ollama y PostgreSQL usando pgvector y Python para generar embeddings estilo ChatGPT en local.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/hopla.tech\/en\/busqueda-semantica-ollama-postgresql\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"B\u00fasqueda sem\u00e1ntica estilo ChatGPT con Ollama y PostgreSQL\" \/>\n<meta property=\"og:description\" content=\"Crea una b\u00fasqueda sem\u00e1ntica con Ollama y PostgreSQL usando pgvector y Python para generar embeddings estilo ChatGPT en local.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/hopla.tech\/en\/busqueda-semantica-ollama-postgresql\/\" \/>\n<meta property=\"og:site_name\" content=\"Hopla! Tech\" \/>\n<meta property=\"article:published_time\" content=\"2025-12-06T02:08:04+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-12-10T09:35:47+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/hopla.tech\/wp-content\/uploads\/2025\/12\/Busqueda-semantica-estilo-ChatGPT-con-Ollama-y-PostgreSQL.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"675\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Hopla!\u00a0Tech\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@HoplaSoftware\" \/>\n<meta name=\"twitter:site\" content=\"@HoplaSoftware\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Hopla!\u00a0Tech\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/hopla.tech\\\/busqueda-semantica-ollama-postgresql\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hopla.tech\\\/busqueda-semantica-ollama-postgresql\\\/\"},\"author\":{\"name\":\"Hopla!\u00a0Tech\",\"@id\":\"https:\\\/\\\/hopla.tech\\\/#\\\/schema\\\/person\\\/9cf81e385f7a2f68085449a2e16e1d22\"},\"headline\":\"B\u00fasqueda sem\u00e1ntica estilo ChatGPT con Ollama y PostgreSQL\",\"datePublished\":\"2025-12-06T02:08:04+00:00\",\"dateModified\":\"2025-12-10T09:35:47+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/hopla.tech\\\/busqueda-semantica-ollama-postgresql\\\/\"},\"wordCount\":1159,\"publisher\":{\"@id\":\"https:\\\/\\\/hopla.tech\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/hopla.tech\\\/busqueda-semantica-ollama-postgresql\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hopla.tech\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/Busqueda-semantica-estilo-ChatGPT-con-Ollama-y-PostgreSQL.jpg\",\"keywords\":[\"b\u00fasqueda sem\u00e1ntica\",\"Ollama\",\"pgvector\",\"postgresql\"],\"articleSection\":[\"Postgresql\"],\"inLanguage\":\"en-GB\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/hopla.tech\\\/busqueda-semantica-ollama-postgresql\\\/\",\"url\":\"https:\\\/\\\/hopla.tech\\\/busqueda-semantica-ollama-postgresql\\\/\",\"name\":\"B\u00fasqueda sem\u00e1ntica con Ollama y PostgreSQL\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hopla.tech\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/hopla.tech\\\/busqueda-semantica-ollama-postgresql\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/hopla.tech\\\/busqueda-semantica-ollama-postgresql\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hopla.tech\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/Busqueda-semantica-estilo-ChatGPT-con-Ollama-y-PostgreSQL.jpg\",\"datePublished\":\"2025-12-06T02:08:04+00:00\",\"dateModified\":\"2025-12-10T09:35:47+00:00\",\"description\":\"Crea una b\u00fasqueda sem\u00e1ntica con Ollama y PostgreSQL usando pgvector y Python para generar embeddings estilo ChatGPT en local.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/hopla.tech\\\/busqueda-semantica-ollama-postgresql\\\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/hopla.tech\\\/busqueda-semantica-ollama-postgresql\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/hopla.tech\\\/busqueda-semantica-ollama-postgresql\\\/#primaryimage\",\"url\":\"https:\\\/\\\/hopla.tech\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/Busqueda-semantica-estilo-ChatGPT-con-Ollama-y-PostgreSQL.jpg\",\"contentUrl\":\"https:\\\/\\\/hopla.tech\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/Busqueda-semantica-estilo-ChatGPT-con-Ollama-y-PostgreSQL.jpg\",\"width\":1200,\"height\":675,\"caption\":\"B\u00fasqueda sem\u00e1ntica estilo ChatGPT con Ollama y PostgreSQL\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/hopla.tech\\\/busqueda-semantica-ollama-postgresql\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\\\/\\\/hopla.tech\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"B\u00fasqueda sem\u00e1ntica estilo ChatGPT con Ollama y PostgreSQL\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/hopla.tech\\\/#website\",\"url\":\"https:\\\/\\\/hopla.tech\\\/\",\"name\":\"Hopla! Tech\",\"description\":\"The enterprise software and consultancy company\",\"publisher\":{\"@id\":\"https:\\\/\\\/hopla.tech\\\/#organization\"},\"alternateName\":\"Hopla!\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/hopla.tech\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/hopla.tech\\\/#organization\",\"name\":\"Hopla! Tech\",\"alternateName\":\"Hopla!\",\"url\":\"https:\\\/\\\/hopla.tech\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/hopla.tech\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/hopla.tech\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/Hopla-by-BTW-b-3.webp\",\"contentUrl\":\"https:\\\/\\\/hopla.tech\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/Hopla-by-BTW-b-3.webp\",\"width\":274,\"height\":115,\"caption\":\"Hopla! Tech\"},\"image\":{\"@id\":\"https:\\\/\\\/hopla.tech\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/HoplaSoftware\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/hopla-software\\\/\",\"https:\\\/\\\/www.youtube.com\\\/@hoplasoftware7485\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/hopla.tech\\\/#\\\/schema\\\/person\\\/9cf81e385f7a2f68085449a2e16e1d22\",\"name\":\"Hopla!\u00a0Tech\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/74a9053adf21148080273a18b879a3392f96e141e511a337179a4438f6bde966?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/74a9053adf21148080273a18b879a3392f96e141e511a337179a4438f6bde966?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/74a9053adf21148080273a18b879a3392f96e141e511a337179a4438f6bde966?s=96&d=mm&r=g\",\"caption\":\"Hopla!\u00a0Tech\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"B\u00fasqueda sem\u00e1ntica con Ollama y PostgreSQL","description":"Crea una b\u00fasqueda sem\u00e1ntica con Ollama y PostgreSQL usando pgvector y Python para generar embeddings estilo ChatGPT en local.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/hopla.tech\/en\/busqueda-semantica-ollama-postgresql\/","og_locale":"en_GB","og_type":"article","og_title":"B\u00fasqueda sem\u00e1ntica estilo ChatGPT con Ollama y PostgreSQL","og_description":"Crea una b\u00fasqueda sem\u00e1ntica con Ollama y PostgreSQL usando pgvector y Python para generar embeddings estilo ChatGPT en local.","og_url":"https:\/\/hopla.tech\/en\/busqueda-semantica-ollama-postgresql\/","og_site_name":"Hopla! Tech","article_published_time":"2025-12-06T02:08:04+00:00","article_modified_time":"2025-12-10T09:35:47+00:00","og_image":[{"width":1200,"height":675,"url":"https:\/\/hopla.tech\/wp-content\/uploads\/2025\/12\/Busqueda-semantica-estilo-ChatGPT-con-Ollama-y-PostgreSQL.jpg","type":"image\/jpeg"}],"author":"Hopla!\u00a0Tech","twitter_card":"summary_large_image","twitter_creator":"@HoplaSoftware","twitter_site":"@HoplaSoftware","twitter_misc":{"Written by":"Hopla!\u00a0Tech","Estimated reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/hopla.tech\/busqueda-semantica-ollama-postgresql\/#article","isPartOf":{"@id":"https:\/\/hopla.tech\/busqueda-semantica-ollama-postgresql\/"},"author":{"name":"Hopla!\u00a0Tech","@id":"https:\/\/hopla.tech\/#\/schema\/person\/9cf81e385f7a2f68085449a2e16e1d22"},"headline":"B\u00fasqueda sem\u00e1ntica estilo ChatGPT con Ollama y PostgreSQL","datePublished":"2025-12-06T02:08:04+00:00","dateModified":"2025-12-10T09:35:47+00:00","mainEntityOfPage":{"@id":"https:\/\/hopla.tech\/busqueda-semantica-ollama-postgresql\/"},"wordCount":1159,"publisher":{"@id":"https:\/\/hopla.tech\/#organization"},"image":{"@id":"https:\/\/hopla.tech\/busqueda-semantica-ollama-postgresql\/#primaryimage"},"thumbnailUrl":"https:\/\/hopla.tech\/wp-content\/uploads\/2025\/12\/Busqueda-semantica-estilo-ChatGPT-con-Ollama-y-PostgreSQL.jpg","keywords":["b\u00fasqueda sem\u00e1ntica","Ollama","pgvector","postgresql"],"articleSection":["Postgresql"],"inLanguage":"en-GB"},{"@type":"WebPage","@id":"https:\/\/hopla.tech\/busqueda-semantica-ollama-postgresql\/","url":"https:\/\/hopla.tech\/busqueda-semantica-ollama-postgresql\/","name":"B\u00fasqueda sem\u00e1ntica con Ollama y PostgreSQL","isPartOf":{"@id":"https:\/\/hopla.tech\/#website"},"primaryImageOfPage":{"@id":"https:\/\/hopla.tech\/busqueda-semantica-ollama-postgresql\/#primaryimage"},"image":{"@id":"https:\/\/hopla.tech\/busqueda-semantica-ollama-postgresql\/#primaryimage"},"thumbnailUrl":"https:\/\/hopla.tech\/wp-content\/uploads\/2025\/12\/Busqueda-semantica-estilo-ChatGPT-con-Ollama-y-PostgreSQL.jpg","datePublished":"2025-12-06T02:08:04+00:00","dateModified":"2025-12-10T09:35:47+00:00","description":"Crea una b\u00fasqueda sem\u00e1ntica con Ollama y PostgreSQL usando pgvector y Python para generar embeddings estilo ChatGPT en local.","breadcrumb":{"@id":"https:\/\/hopla.tech\/busqueda-semantica-ollama-postgresql\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/hopla.tech\/busqueda-semantica-ollama-postgresql\/"]}]},{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/hopla.tech\/busqueda-semantica-ollama-postgresql\/#primaryimage","url":"https:\/\/hopla.tech\/wp-content\/uploads\/2025\/12\/Busqueda-semantica-estilo-ChatGPT-con-Ollama-y-PostgreSQL.jpg","contentUrl":"https:\/\/hopla.tech\/wp-content\/uploads\/2025\/12\/Busqueda-semantica-estilo-ChatGPT-con-Ollama-y-PostgreSQL.jpg","width":1200,"height":675,"caption":"B\u00fasqueda sem\u00e1ntica estilo ChatGPT con Ollama y PostgreSQL"},{"@type":"BreadcrumbList","@id":"https:\/\/hopla.tech\/busqueda-semantica-ollama-postgresql\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/hopla.tech\/"},{"@type":"ListItem","position":2,"name":"B\u00fasqueda sem\u00e1ntica estilo ChatGPT con Ollama y PostgreSQL"}]},{"@type":"WebSite","@id":"https:\/\/hopla.tech\/#website","url":"https:\/\/hopla.tech\/","name":"Hopla! Tech","description":"The enterprise software and consultancy company","publisher":{"@id":"https:\/\/hopla.tech\/#organization"},"alternateName":"Hopla!","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/hopla.tech\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Organization","@id":"https:\/\/hopla.tech\/#organization","name":"Hopla! Tech","alternateName":"Hopla!","url":"https:\/\/hopla.tech\/","logo":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/hopla.tech\/#\/schema\/logo\/image\/","url":"https:\/\/hopla.tech\/wp-content\/uploads\/2025\/12\/Hopla-by-BTW-b-3.webp","contentUrl":"https:\/\/hopla.tech\/wp-content\/uploads\/2025\/12\/Hopla-by-BTW-b-3.webp","width":274,"height":115,"caption":"Hopla! Tech"},"image":{"@id":"https:\/\/hopla.tech\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/HoplaSoftware","https:\/\/www.linkedin.com\/company\/hopla-software\/","https:\/\/www.youtube.com\/@hoplasoftware7485"]},{"@type":"Person","@id":"https:\/\/hopla.tech\/#\/schema\/person\/9cf81e385f7a2f68085449a2e16e1d22","name":"Hopla!\u00a0Tech","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/secure.gravatar.com\/avatar\/74a9053adf21148080273a18b879a3392f96e141e511a337179a4438f6bde966?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/74a9053adf21148080273a18b879a3392f96e141e511a337179a4438f6bde966?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/74a9053adf21148080273a18b879a3392f96e141e511a337179a4438f6bde966?s=96&d=mm&r=g","caption":"Hopla!\u00a0Tech"}}]}},"_links":{"self":[{"href":"https:\/\/hopla.tech\/en\/wp-json\/wp\/v2\/posts\/16222","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hopla.tech\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hopla.tech\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hopla.tech\/en\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/hopla.tech\/en\/wp-json\/wp\/v2\/comments?post=16222"}],"version-history":[{"count":9,"href":"https:\/\/hopla.tech\/en\/wp-json\/wp\/v2\/posts\/16222\/revisions"}],"predecessor-version":[{"id":16250,"href":"https:\/\/hopla.tech\/en\/wp-json\/wp\/v2\/posts\/16222\/revisions\/16250"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hopla.tech\/en\/wp-json\/wp\/v2\/media\/16249"}],"wp:attachment":[{"href":"https:\/\/hopla.tech\/en\/wp-json\/wp\/v2\/media?parent=16222"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hopla.tech\/en\/wp-json\/wp\/v2\/categories?post=16222"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hopla.tech\/en\/wp-json\/wp\/v2\/tags?post=16222"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}