Ricerca semantica vettoriale
Obiettivo
L’app che stiamo creando permette di cercare informazioni in modo più intelligente. Anziché basarsi solo sulle parole esatte che scriviamo, il sistema capisce il significato delle frasi e trova i risultati più pertinenti.
Perché è diversa da una ricerca classica?
Nella ricerca tradizionale, se cerchiamo “mal di schiena”, il sistema trova solo le pagine che contengono esattamente queste parole. Con la nostra app, invece, il sistema capisce che “mal di schiena” è simile a “esercizi per la schiena” e può suggerire informazioni utili anche se le parole non corrispondono esattamente.
Come funziona?
Ecco i passaggi principali:
- Salviamo le informazioni – Ogni contenuto che vogliamo rendere ricercabile viene convertito in una rappresentazione numerica chiamata “vettore”.
- Interpretiamo la domanda – Quando un utente fa una domanda, il sistema trasforma anche questa in un vettore.
- Cerchiamo la risposta migliore – Confrontiamo il vettore della domanda con quelli delle informazioni salvate e troviamo quelle più simili.
- Mostriamo i risultati – L’utente vede i contenuti più pertinenti, anche se le parole non coincidono perfettamente.
Cosa useremo per realizzarla?
- PostgreSQL con pgvector: Un database avanzato che permette di gestire i vettori.
- OpenAI: Per generare i vettori delle parole e delle frasi.
- Rails (Ruby on Rails): Il framework che ci permette di costruire l’app.
- DaisyUI: Per creare un’interfaccia grafica moderna e intuitiva.
Cosa potremo fare con questa tecnologia?
- Creare un motore di ricerca per un blog o un archivio di documenti.
- Offrire risposte personalizzate ai clienti in una chat.
- Organizzare meglio le informazioni in un sito o in un’app.
Questa tecnologia ci permette di migliorare l’esperienza degli utenti, aiutandoli a trovare rapidamente quello di cui hanno bisogno. 🚀
Implementazione di Ricerca Vettoriale in Rails con pgvector e DaisyUI
Questa guida mostra come creare un’app Rails che utilizza pgvector
per la ricerca vettoriale e un’interfaccia con DaisyUI.
1. Configurare il database
Assicurati di avere PostgreSQL con l’estensione pgvector
installata:
psql -d tua_app_db -c "CREATE EXTENSION vector;"
Aggiungi la gemma pgvector
al Gemfile
:
gem 'pgvector', '~> 0.5.0'
Esegui bundle install
per installarla.
2. Creare il modello per salvare le risorse vettoriali
Genera un modello Resource
per salvare i dati:
rails generate model Resource title:string description:text embedding:vector
Esegui la migrazione:
rails db:migrate
3. Ottenere l’embedding da OpenAI
Nel modello Resource
, aggiungi un metodo per generare il vettore:
require 'net/http'
require 'uri'
require 'json'
class Resource < ApplicationRecord
before_create :generate_embedding
def generate_embedding
self.embedding = fetch_openai_embedding(title + " " + description)
end
def fetch_openai_embedding(text)
uri = URI.parse("https://api.openai.com/v1/embeddings")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV['OPENAI_API_KEY']}"
request["Content-Type"] = "application/json"
request.body = { input: text, model: "text-embedding-ada-002" }.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
JSON.parse(response.body)["data"][0]["embedding"]
end
end
Nota: Imposta OPENAI_API_KEY
nel tuo .env
.
4. Cercare una risorsa simile alla query
Quando un utente fa una domanda, calcoliamo il vettore della query e cerchiamo nel database la risorsa più vicina.
class ResourcesController < ApplicationController
def search
query = params[:query]
query_embedding = fetch_openai_embedding(query)
closest_resources = Resource.order(Arel.sql("embedding <=> '#{query_embedding}'::vector")).limit(5)
render json: closest_resources
end
private
def fetch_openai_embedding(text)
uri = URI.parse("https://api.openai.com/v1/embeddings")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV['OPENAI_API_KEY']}"
request["Content-Type"] = "application/json"
request.body = { input: text, model: "text-embedding-ada-002" }.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
JSON.parse(response.body)["data"][0]["embedding"]
end
end
Aggiungi la route nel file config/routes.rb
:
get 'resources/search', to: 'resources#search'
5. Testare l’API
Esegui il server Rails:
rails s
Poi prova la ricerca con una query:
curl "http://localhost:3000/resources/search?query=esercizi per la schiena"
6. Interfaccia con DaisyUI
Ecco un componente React + DaisyUI per cercare risorse.
import { useState } from "react";
export default function SearchApp() {
const [query, setQuery] = useState("");
const [results, setResults] = useState([]);
const searchResources = async () => {
if (query.trim() === "") return;
const response = await fetch(`/resources/search?query=${query}`);
const data = await response.json();
setResults(data);
};
return (
<div className="flex flex-col items-center p-6">
<h1 className="text-2xl font-bold mb-4">Ricerca Risorse</h1>
<div className="flex w-full max-w-lg">
<input
type="text"
className="input input-bordered w-full"
placeholder="Cerca..."
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
<button className="btn btn-primary ml-2" onClick={searchResources}>
Cerca
</button>
</div>
<div className="mt-6 w-full max-w-lg">
{results.length > 0 ? (
<ul className="menu bg-base-200 p-4 rounded-box">
{results.map((resource) => (
<li key={resource.id} className="p-2 border-b">
<h2 className="font-semibold">{resource.title}</h2>
<p className="text-sm text-gray-600">{resource.description}</p>
</li>
))}
</ul>
) : (
<p className="text-gray-500">Nessun risultato trovato.</p>
)}
</div>
</div>
);
}
Salva questo file come app/javascript/components/SearchApp.jsx
e usa Hotwire per renderizzarlo in Rails.
Risultato atteso
Se hai risorse come:
- “Esercizi per la schiena” →
[0.12, -0.98, 0.75]
- “Dieta per dimagrire” →
[0.89, 0.45, -0.32]
E cerchi "mal di schiena"
, il sistema troverà la risorsa più simile basandosi sulla distanza tra vettori.
Prossimi passi
- Integrare la ricerca in una chatbot.
- Usare Hotwire Turbo per aggiornamenti in tempo reale.
- Implementare un’interfaccia più avanzata con filtri.
🚀 Vuoi che ti aiuti a integrare il componente React in Rails?
🔍 1. Ricerca Testuale (Testo su Testo)
Caso d’uso: trovare documenti, articoli, FAQ o contenuti simili a una query testuale.
✅ Migliori modelli di embedding:
- OpenAI
text-embedding-ada-002
(top per accuratezza e semplicità, 1536 dimensioni) - SBERT (Sentence-BERT) (open-source, più leggero, utile se vuoi gestire embedding in locale)
- Cohere Embed (competitore di OpenAI, buona accuratezza)
🔥 Database consigliati per la ricerca vettoriale:
- FAISS (Facebook AI Similarity Search) → Open-source, veloce, locale
- Pinecone → Cloud, zero gestione server
- Weaviate → Open-source con opzioni cloud e AI-native
- Milvus → Open-source, ottimo per grandi dataset
🎥 2. Ricerca Video (Testo su Video o Video su Video)
Caso d’uso: cercare video simili in base a una descrizione o trovare scene simili tra video.
✅ Migliori modelli:
- CLIP (Contrastive Language-Image Pretraining, di OpenAI) → Converte testo e immagini/video nello stesso spazio vettoriale.
- BLIP-2 (Bootstrapped Language-Image Pretraining) → Ancora più avanzato per comprendere il contenuto visivo.
- Google MViT (Multiscale Vision Transformers) → Potente per il matching video su video.
🔥 Database per indicizzare video:
- FAISS + CLIP embeddings → Per ricerca video su video
- Weaviate + CLIP → Per query testo-video
🖼️ 3. Ricerca Immagini (Testo su Immagine o Immagine su Immagine)
Caso d’uso: ricerca di immagini simili o trovare immagini in base a una descrizione testuale.
✅ Migliori modelli di embedding:
- CLIP di OpenAI → Top per associare testo e immagini nello stesso spazio
- DINOv2 (Meta AI) → Ottimo per categorizzazione e clustering di immagini
- DeepFashion (se vuoi una ricerca specifica per vestiti e moda)
🔥 Database per indicizzare immagini:
- FAISS + CLIP (locale e scalabile)
- Pinecone + CLIP (cloud, zero gestione)
- Weaviate + OpenAI embeddings (flessibile e scalabile)
🎵 4. Ricerca Audio (Testo su Audio o Audio su Audio)
Caso d’uso: trovare file audio simili o cercare audio tramite testo.
✅ Migliori modelli:
- Whisper (OpenAI) → Trascrizione e ricerca testuale su audio
- PANNs (Pretrained Audio Neural Networks) → Per confronto audio su audio
- CLAP (Contrastive Language-Audio Pretraining) → Come CLIP, ma per audio!
🔥 Database per indicizzare audio:
- FAISS + CLAP embeddings
- Weaviate + OpenAI Whisper + PANNs
🛒 5. Ricerca su Dati Strutturati (Prodotti, E-commerce, Cataloghi)
Caso d’uso: suggerire prodotti simili in base alla descrizione o alle immagini.
✅ Migliori modelli:
- SBERT + FAISS (se hai solo testo)
- CLIP + FAISS (se hai immagini + testo)
- BERT + XGBoost (se vuoi combinare ricerca testuale con ranking basato su dati)
🔥 Database per indicizzare prodotti:
- Elasticsearch + Dense Vectors
- Pinecone + CLIP/SBERT
- Milvus + multimodali embeddings (testo+immagini)
🌍 6. Ricerca Multimodale (Testo + Immagini + Video + Audio)
Caso d’uso: ricerca avanzata che combina più tipi di dati (es. “Trova un video di una persona che corre sulla spiaggia”).
✅ Migliori modelli:
- CLIP + Whisper + DINOv2 (Testo+Immagini+Audio)
- BLIP-2 + CLAP (ancora più avanzato)
- Giant multimodal models come Flamingo (DeepMind)
🔥 Database per indicizzazione multimodale:
- Weaviate (AI-native, supporta multimodal search)
- Pinecone + OpenAI/Cohere
- Milvus (per combinare diversi tipi di embeddings)
🔮 Quale scegliere per il tuo caso d’uso?
| Tipo di ricerca | Modello consigliato | Database consigliato | |—————-|——————|—————–| | Testo su testo | OpenAI text-embedding-ada-002
, SBERT | FAISS, Pinecone | | Testo su video | CLIP, BLIP-2 | FAISS, Weaviate | | Testo su immagine | CLIP, DINOv2 | FAISS, Pinecone | | Testo su audio | Whisper, CLAP | FAISS, Weaviate | | Audio su audio | PANNs, CLAP | FAISS, Weaviate | | Video su video | MViT, CLIP | FAISS, Weaviate | | Prodotti/E-commerce | SBERT, CLIP | Elasticsearch, Pinecone | | Multimodale (Testo+Media) | CLIP + Whisper + BLIP-2 | Weaviate, Milvus |
🚀 Se vuoi un consiglio pratico:
- Vuoi la soluzione più semplice per ricerca testuale? → OpenAI
text-embedding-ada-002
+ Pinecone - Vuoi una soluzione open-source per testo? → SBERT + FAISS
- Vuoi fare ricerca su immagini/video/audio? → CLIP + FAISS/Pinecone
- Hai un progetto con più tipi di dati? → Weaviate o Milvus
Se hai bisogno di aiuto con l’implementazione, posso fornirti uno script pronto per iniziare! 🚀