Tuesday, November 28, 2023
HomeAISemantic Search with PostgreSQL and OpenAI Embeddings | by Dima Timofeev |...

Semantic Search with PostgreSQL and OpenAI Embeddings | by Dima Timofeev | Nov, 2023

Picture by Igor Omilaev on Unsplash

Implementing semantic search inside company databases could be difficult and requires vital effort. Nonetheless, does it must be this fashion? On this article, I exhibit how one can make the most of PostgreSQL together with OpenAI Embeddings to implement semantic search in your information. Should you favor to not use OpenAI Embeddings API, I’ll give you hyperlinks to free embedding fashions.

On a really excessive stage, vector databases with LLMs enable to do semantic search on accessible information (saved in databases, paperwork, and so on.) Thank to the “Environment friendly Estimation of Phrase Representations in Vector Area” paper (often known as “Word2Vec Paper”) co-authored by legendary Jeff Dean, we all know the way to characterize phrases as real-valued vectors. Phrase embeddings are dense vector representations of phrases in a vector house the place phrases with related meanings are nearer to one another. Phrase embeddings seize semantic relationships between phrases and there are multiple approach to create them.

Picture by the creator

Let’s observe and use OpenAI’s text-embedding-ada mannequin! The selection of distance perform sometimes doesn’t matter a lot. OpenAI recommends cosine similarity. Should you don’t wish to use OpenAI embeddings and like working a distinct mannequin domestically as a substitute of creating API calls, I counsel contemplating one of many SentenceTransformers pretrained fashions. Select your mannequin properly.

import os

import openai
from openai.embeddings_utils import cosine_similarity

openai.api_key = os.getenv("OPENAI_API_KEY")

def get_embedding(textual content: str) -> record:
response = openai.Embedding.create(
enter=textual content,
return response['data'][0]['embedding']

good_ride = "good experience"
good_ride_embedding = get_embedding(good_ride)
# [0.0010935445316135883, -0.01159335020929575, 0.014949149452149868, -0.029251709580421448, -0.022591838613152504, 0.006514389533549547, -0.014793967828154564, -0.048364896327257156, -0.006336577236652374, -0.027027441188693047, ...]
# 1536

Now that now we have developed an understanding of what an embedding is, let’s put it to use to type some opinions.

good_ride_review_1 = "I actually loved the journey! The experience was extremely easy, the pick-up location was handy, and the drop-off level was proper in entrance of the espresso store."
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 snug. I felt safe all through the journey and drastically appreciated the on-board leisure, which allowed me to have some enjoyable whereas the automotive was in movement."
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 exhausting brake on the intersection actually caught me off guard and careworn me out. I wasn't ready for it. Moreover, I observed some trash left within the cabin from a earlier rider."
bad_ride_review_embedding = get_embedding(bad_ride_review)
cosine_similarity(bad_ride_review_embedding, good_ride_embedding)
# 0.7950041130579355

Whereas absolutely the distinction might seem small, think about a sorting perform with 1000’s and 1000’s of opinions. In such instances, we are able to prioritize highlighting solely the constructive ones on the prime.

As soon as a phrase or a doc has been reworked into an embedding, it may be saved in a database. This motion, nonetheless, doesn’t routinely classify the database as a vector database. It’s solely when the database begins to assist quick operations on the vector that we are able to rightfully label it as a vector database.

There are quite a few industrial and open-source vector databases, making it a extremely mentioned matter. I’ll exhibit the functioning of vector databases utilizing a pgvector, an open-source PostgreSQL extension that allows vector similarity search functionalities for arguably the most well-liked database.

Let’s run the PostgreSQL container with pgvector:

docker pull ankane/pgvector

docker run --env "POSTGRES_PASSWORD=postgres" --name "postgres-with-pgvector" --publish 5432:5432 --detach ankane/pgvector

Let’s begin pgcli to connect with the database (pgcli postgres://postgres:postgres@localhost:5432) and create a desk, insert the embeddings we computed above, after which choose related objects:

-- Allow pgvector extension.

-- Create a vector column with 1536 dimensions.
-- The `text-embedding-ada-002` mannequin has 1536 dimensions.
CREATE TABLE opinions (textual content TEXT, embedding vector(1536));

-- Insert three opinions from the above. I omitted the enter in your convinience.
INSERT INTO opinions (textual content, embedding) VALUES ('I actually loved the journey! The experience was extremely easy, the pick-up location was handy, and the drop-off level was proper in entrance of the espresso store.', '[-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 |
-- +-------+

We are prepared to search for similar documents now. I have shortened the embedding for “good ride” again because printing 1536 dimensions is excessive.

--- 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... |
-- +--------------------------------------------------------------------------+
Time: 0.024s

Completed! As you can observe, we have computed embeddings for multiple documents, stored them in the database, and conducted vector similarity searches. The potential applications are vast, ranging from corporate searches to features in medical record systems for identifying patients with similar symptoms. Furthermore, this method is not restricted to texts; similarity can also be calculated for other types of data such as sound, video, and images.




Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments