Ricerca semantica con incorporamenti PostgreSQL e OpenAI |  di Dima Timofeev |  Novembre 2023

 | Intelligenza-Artificiale

Immagine di Igor Omilaev SU Unsplash

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.

Immagine dell’autore

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 os

import 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.8300454513797334

good_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/pgvector

docker 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

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *