Embedding testuali per RAG e ricerca - Python, Ollama, API compatibili con OpenAI

Embedding RAG - Python, Ollama, API OpenAI.

Indice

Se stai approfondendo la generazione potenziata dal recupero (RAG), questa sezione illustra le embeddings testuali in termini semplici: cosa sono, come si integrano nella ricerca e nel recupero, e come invocare due configurazioni locali comuni da Python utilizzando Ollama o un’API HTTP compatibile con OpenAI (come espongono molti server basati su llama.cpp).

Embeddings testuali e recupero

Per i client in Go e i confronti di SDK per Ollama, consulta SDK Go per Ollama — confronto con esempi.

Cos’è un embedding testuale?

Un embedding testuale è un vettore (una lista di numeri in virgola mobile) prodotto da un modello di embedding. Il modello mappa testo di lunghezza variabile in uno spazio a dimensioni fisse in modo che i testi con significato simile tendano a trovarsi vicini secondo una misura di distanza o similarità (spesso similarità del coseno su vettori normalizzati L2).

Gli embeddings non sono gli stessi degli ID dei token e non sono la stessa cosa di una chat di completamento. Sono uno strato di rappresentazione che si utilizza per la ricerca, il clustering, la deduplicazione e, nella RAG, per il recupero.

Casi d’uso comuni

Caso d’uso Ruolo degli embeddings
Ricerca semantica / Recupero RAG Embedding delle query e dei frammenti dei documenti; ordinamento per similarità per recuperare passaggi pertinenti.
Reranking con modelli di embedding Embedding della query e di ogni candidato; punteggio delle coppie in base alla similarità (vedi Reranking con modelli di embedding).
Clustering e deduplicazione Raggruppare o deduplicare elementi nello spazio degli embedding senza etichettare manualmente ogni esempio.
Punteggio in stile classificazione Confrontare il testo con descrizioni prototipo o nomi di classi nello stesso spazio (le variano in base al modello).

Per impostazioni multimodali (immagine-testo e concetti correlati), vedi Embeddings cross-modali.

Embeddings all’interno di una pipeline RAG

Un percorso offline tipico è:

  1. Suddividere (chunking) i documenti (dimensione, sovrapposizione e struttura contano — vedi Strategie di chunking nella RAG).
  2. Creare l’embedding di ogni frammento; opzionalmente memorizzare metadati (ID sorgente, sezione, ACL).
  3. Indicizzare i vettori in memoria, in un indice di libreria o in un database vettoriale (compromessi in Archivi vettoriali per la RAG — confronto).

Al momento della query:

  1. Creare l’embedding della query dell’utente (una stringa breve o un piccolo batch).
  2. Recuperare i k frammenti più simili tramite ricerca vettoriale (opzionalmente più ricerca ibrida/keyword).
  3. Costruire un prompt dai frammenti di testo puro recuperati e invocare il modello di chat.

Sfumatura importante: i grandi modelli linguistici nelle API di chat consumano testo (e strumenti), non tensori di embedding arbitrari. Si usano gli embeddings per scegliere quale testo iniettare. Se vedi “interrogare il LLM con embedding precalcollati”, nella pratica ciò significa recuperare con gli embedding, poi inviare il testo selezionato al LLM.

Ottenere embeddings con Ollama (Python)

Ollama espone un’API HTTP. Per gli embedding, chiama POST /api/embed sul tuo host Ollama (default http://127.0.0.1:11434). Il corpo JSON include un nome model e un input (una stringa o una lista di stringhe). La risposta include embeddings, una lista di vettori allineata con i tuoi input.

Installa httpx (o usa requests allo stesso modo).

import httpx

OLLAMA = "http://127.0.0.1:11434"
MODEL = "nomic-embed-text"  # sostituisci con un modello di embedding che hai scaricato

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 = "Cos'è la generazione potenziata dal recupero?"
    chunks = [
        "La RAG combina il recupero con la generazione.",
        "Gli embeddings mappano il testo in uno spazio vettoriale per la ricerca per similarità.",
    ]
    qv = embed_ollama([q])[0]
    doc_vs = embed_ollama(chunks)
    print(len(qv), len(doc_vs), len(doc_vs[0]))

Note operative

Ottenere embeddings con un server compatibile OpenAI (Python)

Molti server locali (incluse le comuni configurazioni HTTP di llama.cpp) espongono route compatibili con OpenAI come POST /v1/embeddings. Puoi utilizzare il pacchetto Python ufficiale openai e puntare base_url alla radice …/v1 del tuo server.

from openai import OpenAI

# Esempio — sostituisci host, porta e ID modello con i valori del tuo server
client = OpenAI(
    base_url="http://127.0.0.1:8080/v1",
    api_key="not-needed",  # molti server locali ignorano questo
)

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("ciao da llama.cpp", "your-embedding-model-id")
    print(len(v))

Perché mantenere entrambi i pattern in una pagina? I concetti (chunk, embed, indicizza, query, recupera testo) sono identici; cambia solo la superficie HTTP. Un articolo in stile workshop evita di duplicare la stessa narrazione sotto due URL.

Persistere vettori e interrogarli

Al minimo, devi memorizzare tre cose per frammento: vettore, testo e metadati (ID sorgente, offset, ACL). Per un prototipo rapido puoi tenere tutto in una lista Python e usare la similarità del coseno con NumPy o scikit-learn. Per dati in crescita, usa un database vettoriale o un indice di libreria (FAISS, ecc.); vedi Archivi vettoriali per la RAG — confronto per i compromessi a livello di prodotto.

Ciclo di query concettuale:

  1. query_vec = embed(query)
  2. neighbors = index.search(query_vec, k)
  3. context = "\n\n".join(chunk.text for chunk in neighbors)
  4. Invia context e la domanda dell’utente alla tua API di chat.

Reranking dopo il recupero

Un reranker (spesso un cross-encoder o un secondo modello di punteggio) può riordinare i candidati migliori dopo il recupero vettoriale. Questo sito ha esempi in Python e Go, inclusi Reranking con modelli di embedding e Reranking con Ollama e Qwen3 Embedding in Go.

Su questo sito — articoli correlati

Argomento Articolo
Architettura RAG completa Tutorial RAG — architettura, implementazione, produzione
Chunking prima di creare l’embedding Strategie di chunking nella RAG
Scelta del DB vettoriale Archivi vettoriali per la RAG — confronto
Qwen3 su Ollama Embedding e Reranker Qwen3 su Ollama
Cross-modale Embeddings cross-modali
CLI e consigli Ollama Ollama cheatsheet
Go + Ollama Utilizzo di Ollama in Go — confronto SDK