Azure Database for PostgreSQL は、 LangChain などの主要な大規模言語モデル (LLM) オーケストレーション パッケージとシームレスに統合されます。 この統合により、開発者はアプリケーションで高度な AI 機能を使用できます。 LangChain は、生成型 AI アプリケーションの開発が容易になるように、LLM、埋め込みモデル、データベースの管理と使用を合理化できます。
この記事では、Azure Database for PostgreSQL の統合 ベクター データベース を使用して、LangChain を使用してコレクション内のドキュメントを格納および管理する方法について説明します。 また、インデックスを作成し、コサイン距離、L2 距離 (ユークリッド距離)、内部積などの最近隣アルゴリズムを使用してベクトル検索クエリを実行し、クエリ ベクターに近いドキュメントを検索する方法についても説明します。
ベクターのサポート
Azure Database for PostgreSQL を使用すると、PostgreSQL に何百万ものベクター埋め込みを効率的に格納し、クエリを実行できます。 このサービスは、概念実証から運用環境に AI ユース ケースをスケーリングするのに役立ちます。 次の利点があります。
- ベクター埋め込みとリレーショナル データに対してクエリを実行するための使い慣れた SQL インターフェイスを提供します。
-
pgvectorを使用して、1 億を超えるベクター間で高速かつ正確な類似性検索を行うことで、を向上させます。 - リレーショナル メタデータ、ベクター埋め込み、時系列データを 1 つのデータベースに統合することで、操作を簡略化します。
- 堅牢な PostgreSQL エコシステムと Azure クラウド プラットフォームの機能を使用して、レプリケーションや高可用性などのエンタープライズ レベルの機能を実現します。
認証
Azure Database for PostgreSQL では、パスワードベースの 認証と Microsoft Entra (旧称 Azure Active Directory) 認証がサポートされています。
Microsoft Entra 認証を使用すると、Microsoft Entra ID を使用して PostgreSQL サーバーに対する認証を行えます。 Microsoft Entra ID を使用すると、データベース ユーザーの個別のユーザー名とパスワードを管理する必要がなくなります。 これにより、他の Azure サービスに使用するのと同じセキュリティ メカニズムを使用できます。
この記事では、どちらの認証方法も使用できます。
設定
Azure Database for PostgreSQL では、オープンソースの LangChain Postgres サポート を使用して Azure Database for PostgreSQL に接続します。 まず、パートナー パッケージをダウンロードします。
%pip install -qU langchain-azure-postgresql
%pip install -qU langchain-openai
%pip install -qU azure-identity
Azure Database for PostgreSQL で pgvector を有効にする
Azure Database for PostgreSQL での pgvector の有効化と使用に関するページを参照してください。
資格情報を設定する
Azure Database for PostgreSQL 接続の詳細 を取得し、環境変数として追加する必要があります。
Microsoft Entra 認証を使用する場合は、 USE_ENTRA_AUTH フラグを True に設定します。 Microsoft Entra 認証を使用している場合は、ホスト名とデータベース名のみを指定する必要があります。 パスワード認証を使用している場合は、ユーザー名とパスワードも設定する必要があります。
import getpass
import os
USE_ENTRA_AUTH = True
# Supply the connection details for the database
os.environ["DBHOST"] = "<server-name>"
os.environ["DBNAME"] = "<database-name>"
os.environ["SSLMODE"] = "require"
if not USE_ENTRA_AUTH:
# If you're using a username and password, supply them here
os.environ["DBUSER"] = "<username>"
os.environ["DBPASSWORD"] = getpass.getpass("Database Password:")
Azure OpenAI 埋め込みを設定する
os.environ["AZURE_OPENAI_ENDPOINT"] = "<azure-openai-endpoint>"
os.environ["AZURE_OPENAI_API_KEY"] = getpass.getpass("Azure OpenAI API Key:")
AZURE_OPENAI_ENDPOINT = os.environ["AZURE_OPENAI_ENDPOINT"]
AZURE_OPENAI_API_KEY = os.environ["AZURE_OPENAI_API_KEY"]
from langchain_openai import AzureOpenAIEmbeddings
embeddings = AzureOpenAIEmbeddings(
model="text-embedding-3-small",
api_key=AZURE_OPENAI_API_KEY,
azure_endpoint=AZURE_OPENAI_ENDPOINT,
azure_deployment="text-embedding-3-small",
)
初期化
Microsoft Entra 認証を使用する
以下のセクションでは、Microsoft Entra 認証を使用するように LangChain を設定する方法について説明します。 LangChain Azure Postgres パッケージのクラス AzurePGConnectionPool は、DefaultAzureCredential ライブラリの azure.identity を使用して、Azure Database for PostgreSQL サービスのトークンを取得します。
接続は、connection LangChain ベクトル ストアの AzurePGVectorStore パラメーターに渡すことができます。
Azure にサインインする
Azure にサインインするには、 Azure CLI がインストールされていることを確認します。 ターミナルで次のコマンドを実行します。
az login
サインインすると、次のコードによってトークンがフェッチされます。
from langchain_azure_postgresql.common import (
BasicAuth,
AzurePGConnectionPool,
ConnectionInfo,
)
from langchain_azure_postgresql.langchain import AzurePGVectorStore
entra_connection_pool = AzurePGConnectionPool(
azure_conn_info=ConnectionInfo(
host=os.environ["DBHOST"],
dbname=os.environ["DBNAME"]
)
)
パスワード認証を使用する
Microsoft Entra 認証を使用していない場合は、BasicAuth クラスでユーザー名とパスワードを使用できます。
basic_auth_connection_pool = AzurePGConnectionPool(
azure_conn_info=ConnectionInfo(
host=os.environ["DBHOST"],
dbname=os.environ["DBNAME"],
credentials=BasicAuth(
username=os.environ["DBUSER"],
password=os.environ["DBPASSWORD"],
)
)
)
ベクター ストアを作成する
from langchain_core.documents import Document
from langchain_azure_postgresql.langchain import AzurePGVectorStore
collection_name = "my_docs"
# The connection is either using Entra ID or Basic Auth
connection = entra_connection_pool if USE_ENTRA_AUTH else basic_auth_connection_pool
vector_store = AzurePGVectorStore(
embeddings=embeddings,
table_name=table_name,
connection=connection,
)
ベクター ストアの管理
ベクター ストアに項目を追加する
ID でドキュメントを追加すると、その ID に一致する既存のドキュメントが上書きされます。
docs = [
Document(
page_content="there are cats in the pond",
metadata={"doc_id": 1, "___location": "pond", "topic": "animals"},
),
Document(
page_content="ducks are also found in the pond",
metadata={"doc_id": 2, "___location": "pond", "topic": "animals"},
),
Document(
page_content="fresh apples are available at the market",
metadata={"doc_id": 3, "___location": "market", "topic": "food"},
),
Document(
page_content="the market also sells fresh oranges",
metadata={"doc_id": 4, "___location": "market", "topic": "food"},
),
Document(
page_content="the new art exhibit is fascinating",
metadata={"doc_id": 5, "___location": "museum", "topic": "art"},
),
Document(
page_content="a sculpture exhibit is also at the museum",
metadata={"doc_id": 6, "___location": "museum", "topic": "art"},
),
Document(
page_content="a new coffee shop opened on Main Street",
metadata={"doc_id": 7, "___location": "Main Street", "topic": "food"},
),
Document(
page_content="the book club meets at the library",
metadata={"doc_id": 8, "___location": "library", "topic": "reading"},
),
Document(
page_content="the library hosts a weekly story time for kids",
metadata={"doc_id": 9, "___location": "library", "topic": "reading"},
),
Document(
page_content="a cooking class for beginners is offered at the community center",
metadata={"doc_id": 10, "___location": "community center", "topic": "classes"},
),
]
uuids = vector_store.add_documents(docs)
uuids
ベクター ストア内の項目を更新する
updated_docs = [
Document(
page_content="Updated - cooking class for beginners is offered at the community center",
metadata={"doc_id": 10, "___location": "community center", "topic": "classes"},
id=uuids[-1],
)
]
vector_store.add_documents(docs, ids=[uuids[-1]], on_conflict_update=True)
ベクトル ストアの項目を表示する
vector_store.get_by_ids([str(uuids[-1])])
ベクター ストアから項目を削除する
vector_store.delete(ids=[uuids[-1]])
ベクター ストアへのクエリ
ベクター ストアを作成し、関連するドキュメントを追加したら、チェーンまたはエージェントのベクター ストアに対してクエリを実行できます。
フィルター処理のサポート
ベクトル ストアは、FilterCondition パッケージの OrFilter、AndFilter、 を介して、ドキュメントのメタデータ フィールドに適用できる一連のフィルターをサポートしています。
| オペレーター | 意味/カテゴリ |
|---|---|
= |
等式 (==) |
!= |
不等式 (!=) |
< |
未満 (<) |
<= |
以下 (<=) |
> |
より大きい (>) |
>= |
以上または等しい (>=) |
in |
特殊なケース (in) |
not in |
特殊なケース (含まれていない) |
is null |
特定のケース (null の場合) |
is not null |
特定のケース (null ではない) |
between |
特殊なケース (between) |
not between |
特定のケース (範囲外) |
like |
テキスト (類似) |
ilike |
テキスト (大文字と小文字の区別がない類似) |
AND |
論理 (積) |
OR |
論理 (和) |
直接クエリ
単純な類似性検索は、次のように実行できます。
from langchain_azure_postgresql import FilterCondition, AndFilter
results = vector_store.similarity_search(
"kitty",
k=10,
filter=FilterCondition(
column="(metadata->>'doc_id')::int",
operator="in",
value=[1, 5, 2, 9],
),
)
for doc in results:
print(f"* {doc.page_content} [{doc.metadata}]")
* there are cats in the pond [{'doc_id': 1, 'topic': 'animals', '___location': 'pond'}]
* ducks are also found in the pond [{'doc_id': 2, 'topic': 'animals', '___location': 'pond'}]
* the new art exhibit is fascinating [{'doc_id': 5, 'topic': 'art', '___location': 'museum'}]
* the library hosts a weekly story time for kids [{'doc_id': 9, 'topic': 'reading', '___location': 'library'}]
複数のフィールドを持つディクショナリに演算子を指定しない場合、最上位レベルは論理 AND フィルターとして解釈されます。
results = vector_store.similarity_search(
"ducks",
k=10,
filter=AndFilter(
AND=[
FilterCondition(
column="(metadata->>'doc_id')::int",
operator="in",
value=[1, 5, 2, 9],
),
FilterCondition(
column="metadata->>'___location'",
operator="in",
value=["pond", "market"],
),
]
),
)
for doc in results:
print(f"* {doc.page_content} [{doc.metadata}]")
* ducks are also found in the pond [{'topic': 'animals', 'doc_id': 2, '___location': 'pond'}]
* there are cats in the pond [{'topic': 'animals', 'doc_id': 1, '___location': 'pond'}]
類似性検索を実行し、対応するスコアを受け取る場合は、次のコマンドを実行できます。
results = vector_store.similarity_search_with_score(query="cats", k=1)
for doc, score in results:
print(f"* [SIM={score:3f}] {doc.page_content} [{doc.metadata}]")
* [SIM=0.528338] there are cats in the pond [{'doc_id': 1, 'topic': 'animals', '___location': 'pond'}]
ベクトル ストアで最大周辺関連性検索を使用する場合:
results = vector_store.max_marginal_relevance_search(
"query about cats",
k=10,
lambda_mult=0.5,
filter=FilterCondition(
column="(metadata->>'doc_id')::int",
operator="in",
value=[1, 2, 5, 9],
),
)
for doc in results:
print(f"* {doc.page_content} [{doc.metadata}]")
* there are cats in the pond [{'doc_id': 1, 'topic': 'animals', '___location': 'pond'}]
* ducks are also found in the pond [{'doc_id': 2, 'topic': 'animals', '___location': 'pond'}]
* the new art exhibit is fascinating [{'doc_id': 5, 'topic': 'art', '___location': 'museum'}]
* the library hosts a weekly story time for kids [{'doc_id': 9, 'topic': 'reading', '___location': 'library'}]
PGVector ベクター ストアで実行できる検索の完全な一覧については、API リファレンスを参照してください。
取得元への変換
ベクトル ストアをレトリバーに変換して、チェーンで簡単に使用することもできます:
retriever = vector_store.as_retriever(search_type="mmr", search_kwargs={"k": 1})
retriever.invoke("kitty")
[Document(id='9fe8bc1c-9a8e-4f83-b546-9b64527aa79d', metadata={'doc_id': 1, 'topic': 'animals', '___location': 'pond'}, page_content='there are cats in the pond')]