Incrustaciones de texto para RAG y búsqueda: Python, Ollama, APIs compatibles con OpenAI
Incrustaciones RAG: Python, Ollama y las APIs de OpenAI.
Si estás trabajando en generación aumentada con recuperación (RAG), esta sección explica los incrustados de texto (text embeddings) en términos sencillos: qué son, cómo se integran en la búsqueda y la recuperación, y cómo llamar a dos configuraciones locales comunes desde Python usando Ollama o una API HTTP compatible con OpenAI (como la que exponen muchos servidores basados en llama.cpp).

Para clientes en Go y comparaciones de SDK de Ollama, consulta SDK de Go para Ollama: comparación con ejemplos.
¿Qué es un incrustado de texto?
Un incrustado de texto es un vector (una lista de números de punto flotante) generado por un modelo de incrustación. El modelo mapea texto de longitud variable a un espacio de dimensión fija, de modo que los textos con significado similar tienden a quedar cerca entre sí según una medida de distancia o similitud (a menudo similitud coseno en vectores normalizados L2).
Los incrustados no son lo mismo que los identificadores de tokens ni lo mismo que una finalización de chat. Son una capa de representación que utilizas para búsqueda, agrupamiento, eliminación de duplicados y, en RAG, para la recuperación.
Casos de uso comunes
| Caso de uso | Rol de los incrustados |
|---|---|
| Búsqueda semántica / recuperación RAG | Incrusta las consultas y los fragmentos de documentos; clasifica por similitud para obtener los pasajes relevantes. |
| Reordenamiento con modelos de incrustación | Incrusta la consulta y cada candidato; puntuar pares por similitud (consulta Reordenamiento con modelos de incrustación). |
| Agrupamiento y eliminación de duplicados | Agrupa o elimina duplicados en el espacio de incrustados sin etiquetar cada ejemplo manualmente. |
| Puntuación estilo clasificación | Compara texto con descripciones de prototipos o nombres de clases en el mismo espacio (los patrones varían según el modelo). |
Para configuraciones multimodales (imagen-texto e ideas relacionadas), consulta Incrustados intermodales.
Incrustados dentro de un pipeline RAG
Un flujo offline típico es:
- Fragmentar documentos (el tamaño, la superposición y la estructura importan; consulta Estrategias de fragmentación en RAG).
- Incrustar cada fragmento; opcionalmente, almacenar metadatos (id de fuente, sección, ACL).
- Indexar vectores en memoria, en un índice de biblioteca o en una base de datos vectorial (compensaciones en Almacenes vectoriales para RAG: comparación).
En el momento de la consulta:
- Incrustar la consulta del usuario (una cadena corta o un lote pequeño).
- Recuperar los k fragmentos más similares mediante búsqueda vectorial (opcionalmente más búsqueda de palabras clave / híbrida).
- Construir una instrucción (prompt) a partir de los fragmentos de texto plano recuperados y llamar a tu modelo de chat.
Matiz importante: los modelos de lenguaje grandes en las APIs de chat consumen texto (y herramientas), no tensores de incrustación arbitrarios. Utilizas los incrustados para elegir qué texto inyectar. Si ves “consultar al LLM con incrustados precálculados”, en la práctica eso significa recuperar con incrustados y luego enviar el texto seleccionado al LLM.
Obtener incrustados con Ollama (Python)
Ollama expone una API HTTP. Para incrustados, llama a POST /api/embed en tu host de Ollama (por defecto http://127.0.0.1:11434). El cuerpo JSON incluye un nombre de model y un input (una cadena o una lista de cadenas). La respuesta incluye embeddings, una lista de vectores alineados con tus entradas.
Instala httpx (o usa requests de la misma manera).
import httpx
OLLAMA = "http://127.0.0.1:11434"
MODEL = "nomic-embed-text" # reemplaza con un modelo de incrustación que hayas descargado
def embed_ollama(texts: list[str]) -> list[list[float]]:
r = httpx.post(
f"{OLLAMA}/api/embed",
json={"model": MODEL, "input": texts},
timeout=120.0,
)
r.raise_for_status()
data = r.json()
return data["embeddings"]
if __name__ == "__main__":
q = "¿Qué es la generación aumentada con recuperación?"
chunks = [
"RAG combina la recuperación con la generación.",
"Los incrustados mapean texto al espacio vectorial para búsqueda de similitud.",
]
qv = embed_ollama([q])[0]
doc_vs = embed_ollama(chunks)
print(len(qv), len(doc_vs), len(doc_vs[0]))
Notas operativas
- Descarga el modelo primero (
ollama pull …para tu etiqueta elegida). Para modelos de la clase Qwen3 en Ollama, consulta Modelos de Incrustación y Reordenamiento Qwen3 en Ollama. - Bajo carga, el rendimiento de incrustación interactúa con cómo Ollama programa el trabajo; consulta Cómo Ollama maneja solicitudes paralelas.
Obtener incrustados con un servidor compatible con OpenAI (Python)
Muchos servidores locales (incluidas las configuraciones HTTP comunes de llama.cpp) exponen rutas compatibles con OpenAI, como POST /v1/embeddings. Puedes usar el paquete oficial openai de Python y apuntar base_url a la raíz …/v1 de tu servidor.
from openai import OpenAI
# Ejemplo: reemplaza el host, el puerto y el id del modelo con los valores de tu servidor
client = OpenAI(
base_url="http://127.0.0.1:8080/v1",
api_key="not-needed", # muchos servidores locales ignoran esto
)
def embed_openai_compatible(text: str, model: str) -> list[float]:
r = client.embeddings.create(model=model, input=text)
return r.data[0].embedding
if __name__ == "__main__":
v = embed_openai_compatible("hola desde llama.cpp", "your-embedding-model-id")
print(len(v))
¿Por qué mantener ambos patrones en una sola página? Los conceptos (fragmentar, incrustar, indexar, consultar, recuperar texto) son idénticos; solo cambia la superficie HTTP. Un artículo estilo taller evita duplicar la misma narrativa en dos URLs.
Persistir vectores y consultarlos
Como mínimo, debes almacenar tres cosas por fragmento: el vector, el texto y los metadatos (id de fuente, desplazamientos, ACL). Para un prototipo rápido, puedes mantener todo en una lista de Python y usar similitud coseno con NumPy o scikit-learn. Para datos en crecimiento, usa una base de datos vectorial o un índice de biblioteca (FAISS, etc.); consulta Almacenes vectoriales para RAG: comparación para las compensaciones a nivel de producto.
Bucle de consulta conceptual:
query_vec = embed(query)neighbors = index.search(query_vec, k)context = "\n\n".join(chunk.text for chunk in neighbors)- Enviar
contexty la pregunta del usuario a tu API de chat.
Reordenamiento después de la recuperación
Un reordenador (a menudo un codificador cruzado o un segundo modelo de puntuación) puede reordenar los mejores candidatos después de la recuperación vectorial. Este sitio tiene ejemplos en Python y Go, incluyendo Reordenamiento con modelos de incrustación y Reordenamiento con Ollama e Incrustación Qwen3 en Go.
En este sitio — artículos relacionados
| Tema | Artículo |
|---|---|
| Arquitectura completa RAG | Tutorial RAG: arquitectura, implementación, producción |
| Fragmentación antes de incrustar | Estrategias de fragmentación en RAG |
| Elección de BD vectorial | Almacenes vectoriales para RAG: comparación |
| Qwen3 en Ollama | Incrustación y Reordenamiento Qwen3 en Ollama |
| Intermodal | Incrustados intermodales |
| CLI y consejos de Ollama | Hoja de trucos de Ollama |
| Go + Ollama | Uso de Ollama en Go: comparación de SDK |
Enlaces útiles
- Ollama — modelos y entorno de ejecución
- API de Ollama — incrustar — referencia de API aguas arriba para
/api/embed - Biblioteca de Python de OpenAI — funciona con cualquier
base_urlcompatible con OpenAI