![Ricerca semantica con incorporamenti PostgreSQL e OpenAI | di Dima Timofeev | Novembre 2023
| Intelligenza-Artificiale Ricerca semantica con incorporamenti PostgreSQL e OpenAI | di Dima Timofeev | Novembre 2023
| Intelligenza-Artificiale](https://intelligenza-artificiale.eu/wp-content/uploads/2023/11/Ricerca-semantica-con-incorporamenti-PostgreSQL-e-OpenAI-di-Dima.jpeg)
L’implementazione della ricerca semantica all’interno dei database aziendali può essere impegnativa e richiede uno sforzo significativo. Tuttavia, deve essere così? In questo articolo dimostrerò come utilizzare PostgreSQL insieme a OpenAI Embeddings per implementare la ricerca semantica sui tuoi dati. Se preferisci non utilizzare l’API OpenAI Embeddings, ti fornirò collegamenti a modelli di incorporamento gratuiti.
Ad un livello molto alto, i database vettoriali con LLM consentono di effettuare ricerche semantiche sui dati disponibili (memorizzati in database, documenti, ecc.) Grazie al “Stima efficiente delle rappresentazioni di parole nello spazio vettoriale” (noto anche come “Word2Vec Paper”) scritto in collaborazione con Legendary Jeff Deansappiamo come rappresentare le parole come vettori a valori reali. Gli incorporamenti di parole sono rappresentazioni vettoriali dense di parole in uno spazio vettoriale in cui le parole con significati simili sono più vicine tra loro. Gli incorporamenti di parole catturano le relazioni semantiche tra le parole ed esiste più di una tecnica per crearle.
Facciamo pratica e usiamo OpenAI text-embedding-ada modello! La scelta della funzione distanza in genere non ha molta importanza. OpenAI consiglia la somiglianza del coseno. Se non desideri utilizzare gli incorporamenti OpenAI e preferisci eseguire localmente un modello diverso invece di effettuare chiamate API, suggerisco di considerare uno dei Modelli preaddestrati di SentenceTransformers. Scegli saggiamente il tuo modello.
import osimport openai
from openai.embeddings_utils import cosine_similarity
openai.api_key = os.getenv("OPENAI_API_KEY")
def get_embedding(text: str) -> list:
response = openai.Embedding.create(
input=text,
model="text-embedding-ada-002"
)
return response('data')(0)('embedding')
good_ride = "good ride"
good_ride_embedding = get_embedding(good_ride)
print(good_ride_embedding)
# (0.0010935445316135883, -0.01159335020929575, 0.014949149452149868, -0.029251709580421448, -0.022591838613152504, 0.006514389533549547, -0.014793967828154564, -0.048364896327257156, -0.006336577236652374, -0.027027441188693047, ...)
len(good_ride_embedding)
# 1536
Ora che abbiamo capito cos’è un incorporamento, utilizziamolo per ordinare alcune recensioni.
good_ride_review_1 = "I really enjoyed the trip! The ride was incredibly smooth, the pick-up location was convenient, and the drop-off point was right in front of the coffee shop."
good_ride_review_1_embedding = get_embedding(good_ride_review_1)
cosine_similarity(good_ride_review_1_embedding, good_ride_embedding)
# 0.8300454513797334good_ride_review_2 = "The drive was exceptionally comfortable. I felt secure throughout the journey and greatly appreciated the on-board entertainment, which allowed me to have some fun while the car was in motion."
good_ride_review_2_embedding = get_embedding(good_ride_review_2)
cosine_similarity(good_ride_review_2_embedding, good_ride_embedding)
# 0.821774476808789
bad_ride_review = "A sudden hard brake at the intersection really caught me off guard and stressed me out. I wasn't prepared for it. Additionally, I noticed some trash left in the cabin from a previous rider."
bad_ride_review_embedding = get_embedding(bad_ride_review)
cosine_similarity(bad_ride_review_embedding, good_ride_embedding)
# 0.7950041130579355
Sebbene la differenza assoluta possa sembrare piccola, considera una funzione di ordinamento con migliaia e migliaia di recensioni. In questi casi, possiamo dare la priorità evidenziando solo quelli positivi in alto.
Una volta che una parola o un documento è stato trasformato in un incorporamento, può essere archiviato in un database. Questa azione, tuttavia, non classifica automaticamente il database come database vettoriale. È solo quando il database inizia a supportare operazioni veloci sul vettore che possiamo giustamente etichettarlo come database vettoriale.
Esistono numerosi database vettoriali commerciali e open source, che lo rendono un argomento molto discusso. Dimostrerò il funzionamento dei database vettoriali utilizzando a pgvettoreun’estensione PostgreSQL open source che abilita funzionalità di ricerca per somiglianza vettoriale per il database probabilmente più popolare.
Eseguiamo il contenitore PostgreSQL con pgvettor:
docker pull ankane/pgvectordocker run --env "POSTGRES_PASSWORD=postgres" --name "postgres-with-pgvector" --publish 5432:5432 --detach ankane/pgvector
Iniziamo pgcli per connettersi al database (pgcli postgres://postgres:postgres@localhost:5432) e crea una tabella, inserisci gli incorporamenti che abbiamo calcolato sopra, quindi seleziona elementi simili:
-- Enable pgvector extension.
CREATE EXTENSION vector;-- Create a vector column with 1536 dimensions.
-- The `text-embedding-ada-002` model has 1536 dimensions.
CREATE TABLE reviews (text TEXT, embedding vector(1536));
-- Insert three reviews from the above. I omitted the input for your convinience.
INSERT INTO reviews (text, embedding) VALUES ('I really enjoyed the trip! The ride was incredibly smooth, the pick-up location was convenient, and the drop-off point was right in front of the coffee shop.', '(-0.00533589581027627, -0.01026702206581831, 0.021472081542015076, -0.04132508486509323, ...');
INSERT INTO reviews (text, embedding) VALUES ('The drive was exceptionally comfortable. I felt secure throughout the journey and greatly appreciated the on-board entertainment, which allowed me to have some fun while the car was in motion.', '(0.0001858668401837349, -0.004922827705740929, 0.012813017703592777, -0.041855424642562866, ...');
INSERT INTO reviews (text, embedding) VALUES ('A sudden hard brake at the intersection really caught me off guard and stressed me out. I was not prepared for it. Additionally, I noticed some trash left in the cabin from a previous rider.', '(0.00191772251855582, -0.004589076619595289, 0.004269456025213003, -0.0225954819470644, ...');
-- sanity check
select count(1) from reviews;
-- +-------+
-- | count |
-- |-------|
-- | 3 |
-- +-------+
Siamo pronti a cercare documenti simili ora. Ho accorciato di nuovo l’incorporamento per “buon giro” perché stampare dimensioni 1536 è eccessivo.
--- The embedding we use here is for "good ride"
SELECT substring(text, 0, 80) FROM reviews ORDER BY embedding <-> '(0.0010935445316135883, -0.01159335020929575, 0.014949149452149868, -0.029251709580421448, ...';-- +--------------------------------------------------------------------------+
-- | substring |
-- |--------------------------------------------------------------------------|
-- | I really enjoyed the trip! The ride was incredibly smooth, the pick-u... |
-- | The drive was exceptionally comfortable. I felt secure throughout the... |
-- | A sudden hard brake at the intersection really caught me off guard an... |
-- +--------------------------------------------------------------------------+
SELECT 3
Time: 0.024s
Completato! Come puoi osservare, abbiamo calcolato gli incorporamenti per più documenti, li abbiamo archiviati nel database e condotto ricerche di somiglianza vettoriale. Le potenziali applicazioni sono vaste e vanno dalle ricerche aziendali alle funzionalità dei sistemi di cartelle cliniche per identificare pazienti con sintomi simili. Inoltre, questo metodo non è limitato ai testi; la somiglianza può essere calcolata anche per altri tipi di dati come suoni, video e immagini.
Godere!
Fonte: towardsdatascience.com