Vector Embeddings and RAG Demystified: Leveraging Amazon Bedrock, Aurora, and LangChain - Part 2
Explore the transformative world of vector embeddings in AI, and learn how Amazon Bedrock, Amazon Aurora, and LangChain revolutionize data handling and machine learning applications.
pgvector
as a vector store.pgvector
. This isn't just another technical add-on; it's a community-driven extension that transforms the way we handle vectors in databases. Think of pgvector
as a bridge connecting the robustness of relational databases with the dynamic world of vector data.pgvector
shines, making it practical by optimizing indexing for up to 2,000 dimensions, thus tailoring your similarity search performance to be both efficient and effective. It's like having a superpower in your database toolkit, especially if you're already a fan of PostgreSQL and have your data neatly structured.pgvector
introduces approximate nearest neighbor (ANN) indexing methods, including the cutting-edge IVFFLAT and HNSW (hierarchical navigable small worlds), which we discussed earlier. It’s like navigating a complex maze with a highly detailed map. These methods help you zip through massive datasets, finding those near-perfect matches swiftly, without compromising much on the quality of your results. It's all about striking that sweet balance, crucial for applications in generative AI. For more details check this detailed blog on Performance benchmarking and data ingestion with pgvector and HNSW on Amazon RDS for PostgreSQL.Before running the code, ensure an 'Aurora instance' is configured and all details are added to the '.env file'. Create the pgvector extension on your Aurora PostgreSQL database cluster:
1CREATE EXTENSION vector;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from langchain.embeddings import BedrockEmbeddings
from langchain.llms import Bedrock
from langchain.vectorstores.pgvector import PGVector, DistanceStrategy
from dotenv import load_dotenv
import os
# Load environment variables from a .env file
load_dotenv()
# Define the collection name for storing vectors
COLLECTION_NAME = "my_collection"
# Construct the connection string to the PostgreSQL database
CONNECTION_STRING = PGVector.connection_string_from_db_param(
driver=os.getenv("PGVECTOR_DRIVER"),
user=os.getenv("PGVECTOR_USER"),
password=os.getenv("PGVECTOR_PASSWORD"),
host=os.getenv("PGVECTOR_HOST"),
port=os.getenv("PGVECTOR_PORT"),
database=os.getenv("PGVECTOR_DATABASE"),
)
# Initialize the text embedding model
embeddings = BedrockEmbeddings()
# Create a PGVector instance for the vector database
store = PGVector(
collection_name=COLLECTION_NAME,
connection_string=CONNECTION_STRING,
embedding_function=embeddings,
distance_strategy=DistanceStrategy.EUCLIDEAN
)
pgvector
for PostgreSQL on Amazon Aurora.- Import Statements: We import classes from
langchain
for handling embeddings, connecting to Bedrock LLM, and interfacing with a PostgreSQL database. - Collection Name: We define the table in the database where vector embeddings will be stored.
- Connection String: We construct a connection string using environment variables.
- Text Embedding Model: We initialize
BedrockEmbeddings
, likely a pre-trained model for generating vector embeddings from text. - Vector Database Store Instance: We create an instance of
PGVector
, configured with the collection name, connection string, embedding function, and distance strategy.
LangChain
creates two tables in the Aurora database: langchain_pg_collection
and langchain_pg_embedding
.my_collection
.1
2
3
4
5
6
7
8
9
10
# List of textual data for vector embedding conversion
texts = ["New Delhi is the capital of India", "Welcome to India", "I am going to play football today"]
# Create a PGVector database instance and populate it with vector embeddings
store.from_texts(
texts=texts,
collection_name=COLLECTION_NAME,
connection_string=CONNECTION_STRING,
embedding=embeddings
)
BedrockEmbeddings
, and store the entire book in the Aurora database using LangChain's document_loaders
module.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# Import necessary modules and classes for document loading, text splitting, embedding, and vector storage
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import BedrockEmbeddings
from langchain.vectorstores.pgvector import PGVector
from dotenv import load_dotenv
import os
# Load environment variables from a .env file
load_dotenv()
# Define the file path for the PDF document
file_path = 'ESL.pdf'
# Initialize a loader for PDF documents
loader = PyPDFLoader(file_path=file_path)
# Initialize a text splitter for dividing text into chunks
text_splitter = RecursiveCharacterTextSplitter(chunk_size=2000, chunk_overlap=100)
# Load and split the document
data = loader.load_and_split(text_splitter=text_splitter)
# Define the collection name for storing embeddings
COLLECTION_NAME = "eslbook"
# Construct the connection string to the PostgreSQL database
CONNECTION_STRING = PGVector.connection_string_from_db_params(
driver=os.getenv("PGVECTOR_DRIVER"),
user=os.getenv("PGVECTOR_USER"),
password=os.getenv("PGVECTOR_PASSWORD"),
host=os.getenv("PGVECTOR_HOST"),
port=os.getenv("PGVECTOR_PORT"),
database=os.getenv("PGVECTOR_DATABASE"),
)
# Initialize the text embedding model
embeddings = BedrockEmbeddings()
# Create a vector database store instance and populate it with document data and embeddings
db = PGVector.from_documents(
documents=data,
embedding=embeddings,
collection_name=COLLECTION_NAME,
connection_string=CONNECTION_STRING
)
1
2
3
4
5
6
SELECT * FROM langchain_pg_embedding
WHERE langchain_pg_embedding.collection_id = (
SELECT uuid
FROM langchain_pg_collection
WHERE name = 'eslbook'
);
LangChain
.pgvector
and LangChain
for storage and retrieval of vector embeddings.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from langchain.llms import Bedrock
from langchain.chains import RetrievalQA
from langchain.callbacks import StdOutCallbackHandler
# Initialize the language model
llm = Bedrock(
model_id='anthropic.claude-v2',
model_kwargs={'max_tokens_to_sample': 4096}
)
# Set up the retrieval chain with the language model and database retriever
chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=db.as_retriever(),
verbose=True
)
# Initialize the output callback handler
handler = StdOutCallbackHandler()
# Run the retrieval chain with a query
chain.run(
'What is machine learning?',
callbacks=[handler]
)
- We first import the necessary components from
LangChain
. - We initialize a
Bedrock
language model with specific parameters. - We then create a
RetrievalQA
chain that incorporates our vector store retriever and the language model. - We define a
StdOutCallbackHandler
to handle the output. - Finally, we execute the
run
method on our chain with a query about machine learning.
RetrievalQA
chain conducts a two-step process:- Retrieval: It uses the
db.as_retriever()
function to query the vector store for embeddings that are similar to the query. - Question Answering: The retrieved embeddings are then provided to the language model to help it generate a relevant and informed response.
chain.run
method with a question, we are effectively using our vector store to enhance the context available to the language model, leading to more accurate and contextually relevant answers.LangChain
and pgvector
can be applied to numerous applications, from customer service bots to complex analytical tools. It is a testament to how vector search and AI language models are being integrated to deliver advanced solutions in the realm of natural language processing and beyond.LangChain
and extensions like pgvector
will become increasingly valuable in building intelligent, context-aware systems. Whether you are a developer, data scientist, or product manager, understanding and utilizing these tools can significantly enhance the capabilities of your applications and services.pgvector
, showcasing how these tools can effectively manage high-dimensional vector data. By exploring the setup and use of vector stores in Amazon Aurora and employing LangChain, we demonstrated how to create, store, and utilize vector embeddings for complex data retrieval and processing tasks.Any opinions in this post are those of the individual author and may not reflect the opinions of AWS.