Come cercare immagini e testo con MongoDB Vector Search e FastAPI
Crea un'app end-to-end di vector search con FastAPI e MongoDB Atlas. Impara a generare, archiviare e interrogare embedding di testo e immagini in questo tutorial pratico.
La ricerca basata su keyword funziona bene per le ricerche semplici, ma va rapidamente in crisi quando conta il significato più che le parole esatte. Se un documento parla di “aumentare i tempi di risposta” e un altro di “migliorare le prestazioni”, un motore di ricerca tradizionale li considera non correlati, anche se descrivono la stessa idea. Perdiamo le relazioni semantiche solo perché la formulazione è diversa.
La vector search risolve questo limite rappresentando testi e immagini come embedding: vettori numerici generati da modelli di machine learning che catturano contesto, intento e similarità semantica. Una volta archiviati questi embedding in MongoDB, possiamo interrogarli per trovare elementi davvero correlati, indipendentemente dai termini esatti utilizzati.
In questo tutorial costruiremo un esempio pratico end-to-end di questo flusso usando FastAPI e MongoDB Atlas Vector Search. Genereremo embedding di testo con SentenceTransformers e embedding di immagini con un modello basato su CLIP, li archivieremo in MongoDB ed eseguiremo ricerche per similarità su entrambi. Alla fine avrai una base funzionante che può supportare ricerca semantica di articoli, raccomandazioni di prodotti, strumenti per similarità visiva e molte altre applicazioni reali.
Detto questo, iniziamo.
Prerequisiti
Prima di costruire, ci servono alcune cose. Questo tutorial presume una familiarità di base con Python, FastAPI e MongoDB, ma non useremo nulla di avanzato: tutto ciò che serve verrà introdotto lungo il percorso.
Ecco cosa ci serve:
Python 3.10+
Un cluster MongoDB Atlas con Vector Search abilitata
Ambiente FastAPI
Postman o cURL
Accesso a Internet per scaricare modelli ed embedding
Librerie Python che useremo
Le installeremo durante il setup:
FastAPI: il nostro web framework
uvicorn: server di sviluppo
pymongo: driver MongoDB
sentence-transformers: modello di embedding testuale
open_clip: modello di embedding di immagini basato su CLIP
torch: richiesto da CLIP e SentenceTransformers
Pillow: supporto per l'elaborazione di immagini (PIL)
Questi strumenti ci danno tutto il necessario per generare embedding, archiviarli in MongoDB e interrogarli in modo efficiente con la vector search.
Capire la Vector Search
Prima di scrivere codice, è utile capire cosa succede davvero sotto il cofano. La vector search non è complicata una volta scomposta; conoscere le basi rende il resto del tutorial molto più facile da seguire.
Cos'è un embedding?
Un embedding è semplicemente un elenco di numeri (un vettore) che rappresenta il significato di un dato.
Per il testo, l'embedding cattura elementi come contesto e intento. Per le immagini, cattura pattern e caratteristiche visive.
Un esempio molto semplificato di embedding è questo:
Due elementi semanticamente simili—per esempio, due frasi che descrivono la stessa idea o due immagini con oggetti simili—avranno vettori matematicamente vicini. La vector search misura proprio questa vicinanza.
Come MongoDB usa gli embedding
MongoDB in sé non genera embedding. Invece, si concentra su ciò che fa meglio:
Archiviare vettori di embedding
Indicizzarli usando un vector index
Recuperare in modo efficiente i vicini più prossimi
In altre parole, i nostri modelli generano gli embedding e MongoDB gestisce la ricerca.
Questa separazione netta rende il sistema sia flessibile sia scalabile.
Tipi di modelli di embedding
Possiamo scegliere qualsiasi modello di embedding, purché produca un vettore numerico. Modelli diversi sono specializzati per diversi tipi di dati:
Tipo di dato
Modello di esempio
Note
Testo
all-MiniLM-L6-v2
Leggero e molto usato per NLP
Immagine
CLIP/OpenCLIP
Converte le immagini in vettori semantici
Multimodale
Multimodale
Gestisce testo e immagini insieme
Questo è il workflow che implementeremo con FastAPI e MongoDB Atlas.
Una volta configurato, potremo cercare testi e immagini per significato—qualcosa che la ricerca per keyword tradizionale non può fare.
Configurare MongoDB Atlas
Prima di costruire l'applicazione FastAPI, ci serve un posto dove archiviare e interrogare i nostri embedding. MongoDB Atlas lo rende semplice, e creare indici vettoriali richiede solo pochi minuti.
1. Crea un cluster
Se non ne hai già uno, crea un nuovo cluster in MongoDB Atlas. Un cluster free-tier (M0) va benissimo per questo tutorial. Consulta la documentazione MongoDB per maggiori dettagli su come creare un cluster.
2. Crea un database e le collection
All'interno del cluster:
Crea un database. Lo chiameremo vector_db. Per maggiori dettagli, vedi la documentazione.
Crea due collection al suo interno:
texts: dove archiviare i documenti di testo e i loro embedding
images: dove archiviare i nomi file e gli embedding delle immagini
Abbiamo separato la collection delle immagini da quella dei testi perché usano modelli di embedding e dimensioni dei vettori differenti.
3. Crea gli indici vettoriali
MongoDB ha bisogno di un vector index per eseguire ricerche per similarità veloci. Creeremo un indice per gli embedding di testo e uno per gli embedding di immagini.
Puoi crearli in Atlas → Collections → Search Indexes. Iniziamo configurando la collection dei testi.
L'immagine seguente spiega meglio il processo.
Nella schermata successiva, fai clic su Vector Search ->JSON Editor -> Next. L'immagine seguente ti aiuterà a capire meglio il processo
Indice vettoriale per il testo
Nel vector search index, modifica il testo JSON per allinearlo al nostro codice.
Usiamo il modello all-MiniLM-L6-v2 per il testo, che produce embedding a 384 dimensioni.
Ecco la definizione JSON:
{"fields":[{"type":"vector","path":"embedding","numDimensions":384,"similarity":"cosine"}]}Offerto da
Dai a questo indice un nome: vector_texts_searche salva.
Questo consente a MongoDB di eseguire ricerche con similarità coseno sugli embedding testuali. L'immagine sotto illustra il processo più nel dettaglio.
Indice vettoriale per le immagini
Per le immagini, usiamo un modello basato su CLIP che produce vettori a 512 dimensioni, quindi l'indice per le immagini deve rispecchiare quella dimensione. La definizione JSON deve corrispondere al codice qui sotto. A parte questo, il resto del flusso è identico.
{"fields":[{"type":"vector","path":"embedding","numDimensions":512,"similarity":"cosine"}]}Offerto da
Dai a questo indice il nome: vector_images_search.
Una volta che entrambi gli indici sono attivi, MongoDB Atlas è pronto per le query di vector search.
Configurare il progetto FastAPI
Ora che il cluster MongoDB Atlas e gli indici vettoriali sono pronti, possiamo configurare l'app FastAPI che genererà gli embedding e li archivierà in MongoDB. Terremo la struttura del progetto piccola e focalizzata, dato che l'obiettivo è capire il flusso più che costruire un servizio production-ready completo.
1. Installa le dipendenze necessarie
Installeremo FastAPI, Uvicorn, il driver Python per MongoDB e le librerie necessarie per generare embedding di testo e immagini. Esegui:
IMAGE_COLLECTION—dove verranno salvati gli embedding delle immagini
FastAPI caricherà questi valori all'avvio dell'app, mantenendo la configurazione separata dal codice.
Implementare la ricerca testuale
Con il progetto FastAPI configurato, possiamo partire costruendo il flusso per la ricerca testuale. Questa parte introduce l'idea alla base della vector search: generiamo gli embedding del testo, li salviamo in MongoDB e li interroghiamo usando il vector index creato in precedenza.
Lo faremo in due piccoli passaggi, così sarà facile testare ed effettuare il debug man mano.
a. Aggiungi testo e genera embedding
Il primo endpoint accetta un titolo e del contenuto testuale. Uniremo entrambi i campi in una stringa, genereremo un embedding con SentenceTransformers e salveremo il documento insieme al vettore di embedding.
Ecco come appare in codice:
# main.py (excerpt)from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from pymongo import MongoClient
from sentence_transformers import SentenceTransformer
from dotenv import load_dotenv
import os
load_dotenv()
app = FastAPI()# --- DB setup ---
client = MongoClient(os.getenv("MONGODB_URI"))
db = client[os.getenv("DB_NAME")]
texts_coll = db[os.getenv("TEXT_COLLECTION")]
Images_coll = db[os.getenv("IMAGE_COLLECTION")]# --- text embedding model ---
MODEL_NAME ="all-MiniLM-L6-v2"
text_model = SentenceTransformer(MODEL_NAME)# --- request schema ---classAddTextRequest(BaseModel):
title:str
content:str@app.post("/add-text")defadd_text(payload: AddTextRequest):try:# Combine fields for richer embeddings
text =f"{payload.title}\n\n{payload.content}"# Generate text embedding
embedding = text_model.encode(text).tolist()# Store document in MongoDB
doc ={"title": payload.title,"content": payload.content,"embedding": embedding,"model": MODEL_NAME,}
result = texts_coll.insert_one(doc)return{"inserted_id":str(result.inserted_id),"title": payload.title
}except Exception as e:raise HTTPException(status_code=500, detail=str(e))Offerto da
Come testare questo endpoint
cURL, Postman e strumenti simili possono essere usati per il test. In questo tutorial useremo Postman.
Dovremo anche esporre il nostro endpoint FastAPI su Internet per testarlo con Postman sul web. Useremo Ngrok per questo. Se sei nuovo a Ngrok, visita la documentazione. Per testare, esegui prima il codice FastAPI con il comando seguente:
Questo genererà un URL da usare per i test, come nell'immagine seguente:
Invia una richiesta POST con Postman all'endpoint add-text. L'immagine sotto illustra ulteriormente l'invio della richiesta e la risposta attesa.
Risposta attesa:
{
"inserted_id": "65f...",
"title": "Why FastAPI is great."
}Offerto da
Questo conferma che il modello di embedding è stato caricato correttamente e che MongoDB ha salvato il vettore. Se funziona, la pipeline testuale è operativa.
b. Cerca testo con la vector search
Ora che possiamo aggiungere testo, il passo successivo è cercarlo usando lo stage $vectorSearch di MongoDB. Qui:
Convertiamo la query dell'utente in un embedding.
Chiediamo a MongoDB di recuperare i vettori più vicini.
Restituiamo i documenti più simili.
Aggiungi il seguente endpoint a main.py:
classSearchTextRequest(BaseModel):
query:str
limit:int=5@app.post("/search-text")defsearch_text(payload: SearchTextRequest):try:# Convert search query to embedding
query_vector = text_model.encode(payload.query).tolist()# Vector search pipeline
pipeline =[{"$vectorSearch":{"queryVector": query_vector,"path":"embedding","numCandidates":100,"limit": payload.limit,"index":"vector_texts_search"# field MUST match the index name in Atlas exactly}},{"$project":{"title":1,"content":1,"score":{"$meta":"vectorSearchScore"},"_id":0}}]
results =list(texts_coll.aggregate(pipeline))return{"results": results}except Exception as e:raise HTTPException(status_code=500, detail=str(e))Offerto da
> Il parametro numCandidates determina quanti possibili match vengono valutati prima di restituire i risultati migliori.
> Valori più alti migliorano l'accuratezza ma aumentano i tempi di query. Una buona regola pratica è 10–20× il tuo limit.
Come testare la ricerca testuale
Dopo aver aggiunto uno o più documenti, invia una richiesta POST all'endpoint /search-text tramite Postman usando il link generato da Ngrok, come nell'immagine seguente:
Output atteso:
{
"results": [
{
"title": "Why FastAPI is great",
"content": "FastAPI makes building APIs simple and fast.",
"score": 0.85
}
]
}Offerto da
Se vedi un risultato con uno score di similarità, la pipeline di vector search per il testo funziona end-to-end. Una volta che questa parte è stabile, possiamo passare al flusso per le immagini.
Implementare la ricerca per immagini
Ora che il flusso per il testo funziona, possiamo estendere la stessa idea alle immagini. Il flusso generale è simile: l'unica grande differenza è come generiamo gli embedding. Invece di SentenceTransformers, useremo un modello basato su CLIP, progettato per convertire le immagini in vettori a 512 dimensioni.
Come prima, implementeremo tutto passo dopo passo, così è facile testare e fare debug.
a. Aggiungi immagine e genera embedding
Questo endpoint accetta un file immagine caricato, lo converte in un tensore comprensibile da CLIP, genera un embedding a 512 dimensioni e lo salva in MongoDB.
Ecco come appare:
# --- CLIP model setup ---import torch
import open_clip
from PIL import Image
import io
from fastapi import UploadFile, File
# Load CLIP model once when the app starts
clip_model, _, preprocess = open_clip.create_model_and_transforms("ViT-B-32",
pretrained="openai")
device ="cuda"if torch.cuda.is_available()else"cpu"
clip_model.to(device)@app.post("/add-image")asyncdefadd_image(file: UploadFile = File(...)):"""
Upload an image, generate its CLIP embedding, and store in MongoDB.
"""try:# Read file contents
image_bytes =awaitfile.read()
image = Image.open(io.BytesIO(image_bytes)).convert("RGB")# Preprocess for CLIP and encode
image_tensor = preprocess(image).unsqueeze(0).to(device)with torch.no_grad():
image_embedding = clip_model.encode_image(image_tensor)# Normalize the embedding (important for cosine similarity)
image_embedding /= image_embedding.norm(dim=-1, keepdim=True)
vector = image_embedding.cpu().numpy().flatten().tolist()# Store in MongoDB
doc ={"filename":file.filename,"embedding": vector
}
result = images_coll.insert_one(doc)return{"inserted_id":str(result.inserted_id),"filename":file.filename
}except Exception as e:raise HTTPException(status_code=500, detail=str(e))Offerto da
Perché la normalizzazione è importante
Gli embedding di CLIP funzionano al meglio con la similarità coseno. Per rendere i confronti accurati e stabili, normalizziamo i vettori:
image_embedding /= image_embedding.norm(dim=-1, keepdim=True)Offerto da
Questo assicura che la distanza coseno rifletta la similarità reale.
Testa l'endpoint di upload immagini
Per testare la funzionalità in Postman, invia una richiesta POST all'endpoint /add-image. Invia una form-data come body della richiesta con un'immagine .jpg o .png. L'immagine sotto mostra il processo.
Se tutto funziona, dovresti ottenere qualcosa del tipo:
{
"inserted_id": "692454f6156fbb762ed865a0",
"filename": "file-name.png"
}Offerto da
A questo punto, i tuoi embedding delle immagini sono stati salvati correttamente in MongoDB.
b. Cerca immagini con la vector search
Ora possiamo creare l'endpoint che prende un'immagine di query caricata, la converte in un embedding e trova le immagini salvate più vicine usando il nostro indice vettoriale per le immagini.
@app.post("/search-image")asyncdefsearch_image(file: UploadFile = File(...)):"""
Upload an image and find the most visually similar images in MongoDB.
"""try:# Read the uploaded file
image_bytes =awaitfile.read()
image = Image.open(io.BytesIO(image_bytes)).convert("RGB")# Generate embedding for the query image
image_tensor = preprocess(image).unsqueeze(0).to(device)with torch.no_grad():
query_embedding = clip_model.encode_image(image_tensor)
query_embedding /= query_embedding.norm(dim=-1, keepdim=True)
query_vector = query_embedding.cpu().numpy().flatten().tolist()# Vector search pipeline
pipeline =[{"$vectorSearch":{"queryVector": query_vector,"path":"embedding","numCandidates":100,"limit":5,"index":"vector_images_search"}},{"$project":{"filename":1,"score":{"$meta":"vectorSearchScore"},"_id":0}}]
results =list(images_coll.aggregate(pipeline))return{"results": results}except Exception as e:raise HTTPException(status_code=500, detail=str(e))Offerto da
Testa l'endpoint di ricerca immagini
Per testare in Postman, invia una richiesta POST all'endpoint /search-image. Invia la form data come body della richiesta con un'immagine simile a quelle caricate in precedenza. L'immagine sotto mostra il processo.
L'output atteso dovrebbe essere simile a:
{"results":[{"filename":"image1.png","score":1.0},{"filename":"image2.png","score":0.81}]}Offerto da
Uno score di 1.0 significa che ha trovato la stessa immagine. Valori vicini (0,7–0,9) indicano una forte similarità visiva.
Se vedi un array con dei risultati, la tua vector search per immagini è operativa.
A questo punto, se tutto funziona, abbiamo un sistema di ricerca semantica completo sia per testo che per immagini.
Conclusione
In questo tutorial abbiamo costruito un intero workflow di ricerca semantica con FastAPI e MongoDB Atlas. Abbiamo generato embedding testuali con SentenceTransformers, creato embedding di immagini con un modello CLIP, archiviato tutto in MongoDB e interrogato i dati usando la Vector Search di MongoDB e Postman. Questo pattern è la base per applicazioni come ricerca semantica di documenti, strumenti di similarità di immagini, sistemi di raccomandazione e funzionalità AI multimodali.
La forza di questa architettura sta nella sua flessibilità: MongoDB non ti vincola a modelli specifici. Finché gli embedding sono vettori numerici e le dimensioni corrispondono alla configurazione dell'indice, puoi collegare qualsiasi modello testuale, di immagini o multimodale adatto al tuo caso d'uso.
Con queste basi, puoi estendere ulteriormente il progetto: archivia metadati, costruisci una logica di ranking o integra il tutto in app per l'utente finale. Lo stesso workflow scala senza sforzo grazie ai servizi completamente gestiti di MongoDB Atlas.
Puoi trovare il progetto completo e funzionante su GitHub.
Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
La ricerca basata su keyword funziona bene per le ricerche semplici, ma va rapidamente in crisi quando conta il significato più che le parole esatte. Se un documento parla di “aumentare i tempi di risposta” e un altro di “migliorare le prestazioni”, un motore di ricerca tradizionale li considera non correlati, anche se descrivono la stessa idea. Perdiamo le relazioni semantiche solo perché la formulazione è diversa.
La vector search risolve questo limite rappresentando testi e immagini come embedding: vettori numerici generati da modelli di machine learning che catturano contesto, intento e similarità semantica. Una volta archiviati questi embedding in MongoDB, possiamo interrogarli per trovare elementi davvero correlati, indipendentemente dai termini esatti utilizzati.
In questo tutorial costruiremo un esempio pratico end-to-end di questo flusso usando FastAPI e MongoDB Atlas Vector Search. Genereremo embedding di testo con SentenceTransformers e embedding di immagini con un modello basato su CLIP, li archivieremo in MongoDB ed eseguiremo ricerche per similarità su entrambi. Alla fine avrai una base funzionante che può supportare ricerca semantica di articoli, raccomandazioni di prodotti, strumenti per similarità visiva e molte altre applicazioni reali.
Detto questo, iniziamo.
Prerequisiti
Prima di costruire, ci servono alcune cose. Questo tutorial presume una familiarità di base con Python, FastAPI e MongoDB, ma non useremo nulla di avanzato: tutto ciò che serve verrà introdotto lungo il percorso.
Ecco cosa ci serve:
Librerie Python che useremo
Le installeremo durante il setup:
Questi strumenti ci danno tutto il necessario per generare embedding, archiviarli in MongoDB e interrogarli in modo efficiente con la vector search.
Capire la Vector Search
Prima di scrivere codice, è utile capire cosa succede davvero sotto il cofano. La vector search non è complicata una volta scomposta; conoscere le basi rende il resto del tutorial molto più facile da seguire.
Cos'è un embedding?
Un embedding è semplicemente un elenco di numeri (un vettore) che rappresenta il significato di un dato.
Per il testo, l'embedding cattura elementi come contesto e intento. Per le immagini, cattura pattern e caratteristiche visive.
Un esempio molto semplificato di embedding è questo:
Due elementi semanticamente simili—per esempio, due frasi che descrivono la stessa idea o due immagini con oggetti simili—avranno vettori matematicamente vicini. La vector search misura proprio questa vicinanza.
Come MongoDB usa gli embedding
MongoDB in sé non genera embedding. Invece, si concentra su ciò che fa meglio:
In altre parole, i nostri modelli generano gli embedding e MongoDB gestisce la ricerca.
Questa separazione netta rende il sistema sia flessibile sia scalabile.
Tipi di modelli di embedding
Possiamo scegliere qualsiasi modello di embedding, purché produca un vettore numerico. Modelli diversi sono specializzati per diversi tipi di dati:
Tipo di dato
Modello di esempio
Note
Testo
all-MiniLM-L6-v2Leggero e molto usato per NLP
Immagine
CLIP/OpenCLIP
Converte le immagini in vettori semantici
Multimodale
Multimodale
Gestisce testo e immagini insieme
Questo è il workflow che implementeremo con FastAPI e MongoDB Atlas.
Una volta configurato, potremo cercare testi e immagini per significato—qualcosa che la ricerca per keyword tradizionale non può fare.
Configurare MongoDB Atlas
Prima di costruire l'applicazione FastAPI, ci serve un posto dove archiviare e interrogare i nostri embedding. MongoDB Atlas lo rende semplice, e creare indici vettoriali richiede solo pochi minuti.
1. Crea un cluster
Se non ne hai già uno, crea un nuovo cluster in MongoDB Atlas. Un cluster free-tier (M0) va benissimo per questo tutorial. Consulta la documentazione MongoDB per maggiori dettagli su come creare un cluster.
2. Crea un database e le collection
All'interno del cluster:
vector_db. Per maggiori dettagli, vedi la documentazione.texts: dove archiviare i documenti di testo e i loro embeddingimages: dove archiviare i nomi file e gli embedding delle immaginiConsulta la documentazione per maggiori dettagli su come creare una collection.
Abbiamo separato la collection delle immagini da quella dei testi perché usano modelli di embedding e dimensioni dei vettori differenti.
3. Crea gli indici vettoriali
MongoDB ha bisogno di un vector index per eseguire ricerche per similarità veloci. Creeremo un indice per gli embedding di testo e uno per gli embedding di immagini.
Puoi crearli in Atlas → Collections → Search Indexes. Iniziamo configurando la collection dei testi.
L'immagine seguente spiega meglio il processo.
Nella schermata successiva, fai clic su Vector Search ->JSON Editor -> Next. L'immagine seguente ti aiuterà a capire meglio il processo
Indice vettoriale per il testo
Nel vector search index, modifica il testo JSON per allinearlo al nostro codice.
Usiamo il modello
all-MiniLM-L6-v2per il testo, che produce embedding a 384 dimensioni.Ecco la definizione JSON:
Dai a questo indice un nome:
vector_texts_searche salva.Questo consente a MongoDB di eseguire ricerche con similarità coseno sugli embedding testuali. L'immagine sotto illustra il processo più nel dettaglio.
Indice vettoriale per le immagini
Per le immagini, usiamo un modello basato su CLIP che produce vettori a 512 dimensioni, quindi l'indice per le immagini deve rispecchiare quella dimensione. La definizione JSON deve corrispondere al codice qui sotto. A parte questo, il resto del flusso è identico.
Dai a questo indice il nome:
vector_images_search.Una volta che entrambi gli indici sono attivi, MongoDB Atlas è pronto per le query di vector search.
Configurare il progetto FastAPI
Ora che il cluster MongoDB Atlas e gli indici vettoriali sono pronti, possiamo configurare l'app FastAPI che genererà gli embedding e li archivierà in MongoDB. Terremo la struttura del progetto piccola e focalizzata, dato che l'obiettivo è capire il flusso più che costruire un servizio production-ready completo.
1. Installa le dipendenze necessarie
Installeremo FastAPI, Uvicorn, il driver Python per MongoDB e le librerie necessarie per generare embedding di testo e immagini. Esegui:
Breve panoramica del perché ci servono:
.envUna volta installato tutto, possiamo impostare il progetto.
2. Struttura del progetto
Terremo tutto in un unico file Python, con la configurazione gestita tramite variabili d'ambiente:
main.py conterrà l'intera applicazione: gli endpoint per il testo, quelli per le immagini e la connessione a MongoDB.
FastAPI caricherà questi valori all'avvio dell'app, mantenendo la configurazione separata dal codice.
Implementare la ricerca testuale
Con il progetto FastAPI configurato, possiamo partire costruendo il flusso per la ricerca testuale. Questa parte introduce l'idea alla base della vector search: generiamo gli embedding del testo, li salviamo in MongoDB e li interroghiamo usando il vector index creato in precedenza.
Lo faremo in due piccoli passaggi, così sarà facile testare ed effettuare il debug man mano.
a. Aggiungi testo e genera embedding
Il primo endpoint accetta un titolo e del contenuto testuale. Uniremo entrambi i campi in una stringa, genereremo un embedding con SentenceTransformers e salveremo il documento insieme al vettore di embedding.
Ecco come appare in codice:
Come testare questo endpoint
cURL, Postman e strumenti simili possono essere usati per il test. In questo tutorial useremo Postman.
Dovremo anche esporre il nostro endpoint FastAPI su Internet per testarlo con Postman sul web. Useremo Ngrok per questo. Se sei nuovo a Ngrok, visita la documentazione. Per testare, esegui prima il codice FastAPI con il comando seguente:
Poi, crea un tunnel dal tuo
localhosta Internet con il comando Ngrok qui sotto:Questo genererà un URL da usare per i test, come nell'immagine seguente:
Invia una richiesta
POSTcon Postman all'endpointadd-text. L'immagine sotto illustra ulteriormente l'invio della richiesta e la risposta attesa.Risposta attesa:
Questo conferma che il modello di embedding è stato caricato correttamente e che MongoDB ha salvato il vettore. Se funziona, la pipeline testuale è operativa.
b. Cerca testo con la vector search
Ora che possiamo aggiungere testo, il passo successivo è cercarlo usando lo stage $vectorSearch di MongoDB. Qui:
Aggiungi il seguente endpoint a
main.py:> Il parametro numCandidates determina quanti possibili match vengono valutati prima di restituire i risultati migliori.
> Valori più alti migliorano l'accuratezza ma aumentano i tempi di query. Una buona regola pratica è 10–20× il tuo limit.
Come testare la ricerca testuale
Dopo aver aggiunto uno o più documenti, invia una richiesta POST all'endpoint
/search-texttramite Postman usando il link generato da Ngrok, come nell'immagine seguente:Output atteso:
Se vedi un risultato con uno score di similarità, la pipeline di vector search per il testo funziona end-to-end. Una volta che questa parte è stabile, possiamo passare al flusso per le immagini.
Implementare la ricerca per immagini
Ora che il flusso per il testo funziona, possiamo estendere la stessa idea alle immagini. Il flusso generale è simile: l'unica grande differenza è come generiamo gli embedding. Invece di SentenceTransformers, useremo un modello basato su CLIP, progettato per convertire le immagini in vettori a 512 dimensioni.
Come prima, implementeremo tutto passo dopo passo, così è facile testare e fare debug.
a. Aggiungi immagine e genera embedding
Questo endpoint accetta un file immagine caricato, lo converte in un tensore comprensibile da CLIP, genera un embedding a 512 dimensioni e lo salva in MongoDB.
Ecco come appare:
Perché la normalizzazione è importante
Gli embedding di CLIP funzionano al meglio con la similarità coseno. Per rendere i confronti accurati e stabili, normalizziamo i vettori:
Questo assicura che la distanza coseno rifletta la similarità reale.
Testa l'endpoint di upload immagini
Per testare la funzionalità in Postman, invia una richiesta
POSTall'endpoint/add-image. Invia una form-data come body della richiesta con un'immagine.jpgo.png. L'immagine sotto mostra il processo.Se tutto funziona, dovresti ottenere qualcosa del tipo:
A questo punto, i tuoi embedding delle immagini sono stati salvati correttamente in MongoDB.
b. Cerca immagini con la vector search
Ora possiamo creare l'endpoint che prende un'immagine di query caricata, la converte in un embedding e trova le immagini salvate più vicine usando il nostro indice vettoriale per le immagini.
Aggiungi questo a
main.py:Testa l'endpoint di ricerca immagini
Per testare in Postman, invia una richiesta
POSTall'endpoint/search-image. Invia la form data come body della richiesta con un'immagine simile a quelle caricate in precedenza. L'immagine sotto mostra il processo.L'output atteso dovrebbe essere simile a:
Uno score di 1.0 significa che ha trovato la stessa immagine. Valori vicini (0,7–0,9) indicano una forte similarità visiva.
Se vedi un array con dei risultati, la tua vector search per immagini è operativa.
A questo punto, se tutto funziona, abbiamo un sistema di ricerca semantica completo sia per testo che per immagini.
Conclusione
In questo tutorial abbiamo costruito un intero workflow di ricerca semantica con FastAPI e MongoDB Atlas. Abbiamo generato embedding testuali con SentenceTransformers, creato embedding di immagini con un modello CLIP, archiviato tutto in MongoDB e interrogato i dati usando la Vector Search di MongoDB e Postman. Questo pattern è la base per applicazioni come ricerca semantica di documenti, strumenti di similarità di immagini, sistemi di raccomandazione e funzionalità AI multimodali.
La forza di questa architettura sta nella sua flessibilità: MongoDB non ti vincola a modelli specifici. Finché gli embedding sono vettori numerici e le dimensioni corrispondono alla configurazione dell'indice, puoi collegare qualsiasi modello testuale, di immagini o multimodale adatto al tuo caso d'uso.
Con queste basi, puoi estendere ulteriormente il progetto: archivia metadati, costruisci una logica di ranking o integra il tutto in app per l'utente finale. Lo stesso workflow scala senza sforzo grazie ai servizi completamente gestiti di MongoDB Atlas.
Puoi trovare il progetto completo e funzionante su GitHub.