使用Bedrock和Aurora Serverless PostgreSQL的pgvector来进行RAG(Retrieve, Aggregate, Generate)- 在Amazon Titan Embeddings中学习向量
我们将使用Aurora Serverless PostgreSQL的pgvector作为Vector DB来构建RAG。
概念图

建筑蓝图

无需配置的Aurora Serverless PostgreSQL







Cloud 9的构成
创建一个名为Cloud9的实例。默认设置即可。
将Cloud9的安全组添加到PostgreSQL的安全组(默认安全组)的入站规则中。暂时允许所有的流量。
安装PostgreSQL客户端。
sudo amazon-linux-extras install postgresql14
启用pgvector
我将使用psql连接到编写器端点。
psql -h vector-test.cluster-xxxxxxxxxxxx.us-east-1.rds.amazonaws.com -U postgres -p 5432
请输入密码并按Enter键。
Password for user postgres:
psql (14.8, server 15.4)
WARNING: psql major version 14, server major version 15.
Some psql features might not work.
SSL connection (protocol: TLSv1.2, cipher: AES128-SHA256, bits: 128, compression: off)
Type "help" for help.
postgres=>
只要是这次的用途,不必担心警告,没问题的。
然后按照以下方式输入,开启了pgvector。
postgres=> CREATE EXTENSION vector;
CREATE EXTENSION
由于LangChain已创建了表格等内容,因此无需在此处进行创建。之后只需要确认并离开即可。
postgres=> \dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+--------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
vector | 0.5.0 | public | vector data type and ivfflat access method
(2 rows)
postgres=> exit
Python环境的配置
安装必要的库。
pip install boto3
pip install langchain
pip install pgvector
pip install psycopg2-binary
pip install pypdf
pip install streamlit
创建向量数据库
将这个PDF文件存储到PostgreSQL中。
首先,将以上文件上传到Cloud9。
在这个例子中,我们将其放置在/home/ec2-user/environment/bedrock-ug.pdf位置上。
我将创建并运行以下程序。
请设置CONNECTION_STRING的{password}为PostgreSQL的主密码。请设置vector-test.cluster-xxxxxxxxxxxx.us-east-1.rds.amazonaws.com作为读取端点。
from langchain.embeddings import BedrockEmbeddings
from langchain.vectorstores.pgvector import PGVector
from langchain.document_loaders import PyPDFLoader
# 接続文字列の定義
CONNECTION_STRING = "postgresql+psycopg2://postgres:{password}@vector-test.cluster-xxxxxxxxxxxx.us-east-1.rds.amazonaws.com:5432"
# Embeddingsの定義
embeddings = BedrockEmbeddings(model_id="amazon.titan-embed-text-v1")
# PostgreSQLの定義
db = PGVector(
connection_string=CONNECTION_STRING,
embedding_function=embeddings
)
# PDFファイルをDBに追加
loader = PyPDFLoader(r"/home/ec2-user/environment/bedrock-ug.pdf")
pages = loader.load_and_split()
db.add_documents(documents=pages)
这个过程应该会将上述的PDF文件按照一页一页地分割,并通过Titan Embeddings进行嵌入,然后存储到PostgreSQL中。
顺便提一下,PGVector的接口如下。
确认存储内容
使用psql连接到leader节点的终端。
psql -h vector-test.cluster-xx-xxxxxxxxxxxx.us-east-1.rds.amazonaws.com -U postgres -p 5432
通过使用LangChain创建的表格进行确认。
postgres=> \d
List of relations
Schema | Name | Type | Owner
--------+-------------------------+-------+----------
public | langchain_pg_collection | table | postgres
public | langchain_pg_embedding | table | postgres
(2 rows)
postgres=>
通过LangChain分别创建了langchain_pg_collection和langchain_pg_embedding两个表格。
确认收藏
确认langchain_pg_collection。
postgres=> \d langchain_pg_collection;
Table "public.langchain_pg_collection"
Column | Type | Collation | Nullable | Default
-----------+-------------------+-----------+----------+---------
name | character varying | | |
cmetadata | json | | |
uuid | uuid | | not null |
Indexes:
"langchain_pg_collection_pkey" PRIMARY KEY, btree (uuid)
Referenced by:
TABLE "langchain_pg_embedding" CONSTRAINT "langchain_pg_embedding_collection_id_fkey" FOREIGN KEY (collection_id) REFERENCES langchain_pg_collection(uuid) ON DELETE CASCADE
postgres=> select * from langchain_pg_collection;
name | cmetadata | uuid
-----------+-----------+--------------------------------------
langchain | null | 79292fae-56a5-4934-ad94-6e1f2b7a9185
(1 row)
已创建了一个记录。
name的langchain属性是LangChain的默认值。因为在此次程序创建时没有指定值,所以变成了默认值。但也可以通过参数指定来创建。同时,该记录还被分配了一个作为uuid的ID,被称为“Collection”。
确认嵌入表
我要确认一下langchain_pg_embedding。
postgres=> \d langchain_pg_embedding;
Table "public.langchain_pg_embedding"
Column | Type | Collation | Nullable | Default
---------------+-------------------+-----------+----------+---------
collection_id | uuid | | |
embedding | vector | | |
document | character varying | | |
cmetadata | json | | |
custom_id | character varying | | |
uuid | uuid | | not null |
Indexes:
"langchain_pg_embedding_pkey" PRIMARY KEY, btree (uuid)
Foreign-key constraints:
"langchain_pg_embedding_collection_id_fkey" FOREIGN KEY (collection_id) REFERENCES langchain_pg_collection(uuid) ON DELETE CASCADE
postgres=>
我会确认数量。
postgres=> select count(*) from langchain_pg_embedding;
count
-------
156
(1 row)
postgres=>
可以看到已创建与PDF文件页数相对应的记录。
稍微查看一下。由于嵌入是存储向量值的巨大列,所以首先进行排除搜索。
postgres=> select collection_id,document,custom_id,uuid from langchain_pg_embedding;
collection_id | document
| custom_id | uuid
--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------
---------------------------+--------------------------------------+--------------------------------------
79292fae-56a5-4934-ad94-6e1f2b7a9185 | Amazon Bedrock
+| d5f0a7e4-7bc8-11ee-8460-06a674c2adb7 | 28d92844-45e8-4880-a6f8-79379a981e62
| ユーザーガイド
| |
79292fae-56a5-4934-ad94-6e1f2b7a9185 | Amazon Bedrock ユーザーガイド
+| d5f0a992-7bc8-11ee-8460-06a674c2adb7 | 90199c78-cd20-4143-adc7-6d11e474a972
| Amazon Bedrock: ユーザーガイド
+| |
| Copyright © 2023 Amazon Web Services, Inc. and/or its affiliates. All rights reserved.
+| |
| Amazon の商標およびトレードドレスは、顧客に混乱を招く可能性がある態様、または Amazon の信用を傷つけ
+| |
| たり、失わせたりする態様において、Amazon のものではない製品またはサービスに関連して使用してはなりませ
+| |
| ん。Amazon が所有しない商標はすべてそれぞれの所有者に所属します。所有者は必ずしも Amazon との提携や関連
+| |
| があるわけではありません。また、Amazon の支援を受けているとは限りません。
| |
79292fae-56a5-4934-ad94-6e1f2b7a9185 | Amazon Bedrock ユーザーガイド
+| d5f0aa50-7bc8-11ee-8460-06a674c2adb7 | ee5cde36-2e92-4b2a-9f7d-415032315a6b
| Table of Contents
+| |
| アマゾン・ベッドロックとは? ..................................................................................................
...........1 +| |
| Bedrock モデルにアクセスしてください。 .....................................................................................1
+| |
尽管文字数较多,可能有些难以理解,但collection_id中存储了集合的uuid。
document中存储了每个页面的文本。
uuid是为每条记录分配的不同ID。
查看嵌入内容中存储的信息。
postgres=> select embedding from langchain_pg_embedding;
[0.18457031,0.38671875,0.484375,-0.022338867,0.7578125,0.63671875,-0.18652344,-0.00037384033,0.012207031,-0.3515625,-0.095703125,0.69140625,0.4765625,0.140625,-0.3710
9375,-0.083984375,-0.47460938,0.29492188,-0.30078125,-0.029541016,-0.76171875,0.98828125,0.053466797,0.9453125,-0.42773438,0.625,0.08691406,-0.37890625,-0.609375,-0.31
054688,-0.75,0.65234375,-0.2578125,-0.56640625,-0.20019531,-0.12890625,0.19726562,-1.1015625,-0.65234375,0.69921875,-0.0859375,-0.5546875,-0.123046875,0.21386719,0.279
29688,-0.36132812,0.07128906,0.29101562,1.171875,0.67578125,-0.03149414,0.0026855469,0.21484375,0.30273438,0.16796875,0.26367188,0.50390625,-0.47265625,0.65625,0.26757
812,-0.024169922,0.35546875,-0.13085938,0.25390625,0.4296875,0.0859375,0.80078125,-0.30859375,-0.52734375,0.92578125,-0.671875,0.94140625,0.27148438,-0.2265625,-0.0986
3281,0.48632812,-0.41015625,0.47070312,0.828125,0.056152344,-0.21972656,0.5703125,0.20214844,0.29101562,-0.39257812,-0.51953125,-0.45898438,0.29296875,0.00013828278,
因为没有意义,所以我会在中途停下来,但是可以看出嵌入中存储了向量值。
换句话说,当进行向量搜索时,可以从嵌入中获取相似度较高的记录,并获取到实际的文档内容。
RAG的实施
创建并执行以下程序。
与之前相同,我们将使用VectorDB和Titan Embeddings作为搜索内容的嵌入,并使用Claude2进行最后的句子整理。
为了方便执行,我们使用了Streamlit作为外层框架。
除程序的定义部分外,其他部分与上一版的ChromaDB程序没有变化。
请设置 CONNECTION_STRING 中的 {password} 为 PostgreSQL 的主密码。请设置 vector-test.cluster-xx-xxxxxxxxxxxx.us-east-1.rds.amazonaws.com 作为读取端点。
from langchain.embeddings import BedrockEmbeddings
from langchain.vectorstores.pgvector import PGVector
from langchain.llms import Bedrock
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
import streamlit as st
# 接続文字列の定義
CONNECTION_STRING = "postgresql+psycopg2://postgres:{password}@vector-test.cluster-xx-xxxxxxxxxxxx.us-east-1.rds.amazonaws.com:5432"
# Embeddingsの定義
embeddings = BedrockEmbeddings(model_id="amazon.titan-embed-text-v1")
# PostgreSQLの定義
db = PGVector(
connection_string=CONNECTION_STRING,
embedding_function=embeddings
)
# LLMの定義
llm = Bedrock(
model_id="anthropic.claude-v2",
model_kwargs={"max_tokens_to_sample": 1000},
)
# promptの定義
prompt_template = """
<documents>{context}</documents>
\n\nHuman: 上記の内容を参考文書として、質問の内容に対して詳しく説明してください。言語の指定が無い場合は日本語で答えてください。
もし質問の内容が参考文書に無かった場合は「文書にありません」と答えてください。回答内容には質問自体やタグは含めないでください。
Take a deep breath and work on this problem step-by-step.
<question>{question}</question>
\n\nAssistant:"""
PROMPT = PromptTemplate(template=prompt_template, input_variables=["context", "question"])
chain_type_kwargs = {"prompt": PROMPT}
# Chainの定義。検索結果の上位15件を使用
qa = RetrievalQA.from_chain_type(llm,retriever=db.as_retriever(search_kwargs={"k": 15}),chain_type_kwargs=chain_type_kwargs)
# Streamlit
st.title("PostgreSQL PGVectoRAG")
input_text = st.text_input("入力された文字列でVectorDBを検索し回答します")
send_button = st.button("送信")
if send_button:
# 実行
st.write(qa.run(input_text))
请按照以下方式执行。
python -m streamlit run pgv_search.py --server.port 8080

通过启用Aurora Serverless PostgreSQL中的pgvector,我们可以将其作为Vector DB(Vector存储)来使用,并实现RAG。
这一次LangChain在处理上做得非常好,但是如果Agents for Amazon Bedrock开始运作,它们会以同样良好的方式处理吗?