以编程方式使用文档

Azure Database for PostgreSQL 灵活服务器 是一种基于开源 Postgres 数据库引擎的关系型数据库服务。它是一个完全托管的数据库即服务,可以处理关键任务工作负载,具有可预测的性能、安全性、高可用性和动态可扩展性。

本指南向您展示如何利用这个集成的 向量数据库 将文档存储在集合中、创建索引并使用近似最近邻算法(如余弦距离、L2(欧几里得距离)和 IP(内积))执行向量搜索查询,以定位与查询向量接近的文档。

向量支持

Azure Database for PostgreSQL 灵活服务器使您能够高效地存储和查询 PostgreSQL 中的数百万个向量嵌入。同时支持将 AI 用例从 POC 扩展到生产环境:

  • * 提供熟悉的 SQL 接口,用于查询向量嵌入和关系数据。
  • * 通过 pgvector 实现更快、更精确的相似性搜索,可在超过 1 亿个向量中进行搜索,使用 DiskANN 索引算法。
  • * 通过将关系元数据、向量嵌入和时间序列数据集成到单个数据库来简化操作。
  • * 利用强大的 PostgreSQL 生态系统和 Azure 云的企业级功能,包括复制和高可用性。

身份验证

Azure Database for PostgreSQL 灵活服务器支持基于密码的身份验证以及 Microsoft Entra (前身为 Azure Active Directory)身份验证。

Entra 身份验证允许您使用 Entra 身份向 PostgreSQL 服务器进行身份验证。这消除了为数据库用户管理单独用户名和密码的需要,并允许 您利用与其他 Azure 服务相同的安全机制。

本指南设置为使用任一身份验证方法。您可以在笔记本中稍后配置是否使用 Entra 身份验证。

设置

Azure Database for PostgreSQL 基于开源 Postgres。本集成使用专用的 langchain-azure-postgresql 包,提供优化支持,包括 DiskANN 索引和 Microsoft Entra 身份验证。

首先下载合作伙伴包:

pip install -qU langchain-azure-postgresql langchain-openai azure-identity

启用 pgvector

请参阅 启用说明 了解 Azure Database for PostgreSQL 的

设置凭据

您需要提供 Azure Database for PostgreSQL 连接详细信息 并将其添加为环境变量以运行此笔记本。

USE_ENTRA_AUTH 标志设置为 True 如果您想使用 Microsoft Entra 身份验证。如果使用 Entra 身份验证,您只需提供主机和数据库名称。如果使用密码身份验证,您还需要设置用户名和密码。

USE_ENTRA_AUTH = True

# Supply the connection details for the database
os.environ["DBHOST"] = "REPLACE_WITH_SERVER_NAME"
os.environ["DBNAME"] = "REPLACE_WITH_DATABASE_NAME"
os.environ["SSLMODE"] = "require"

if not USE_ENTRA_AUTH:
    # If using a username and password, supply them here
    os.environ["DBUSER"] = "REPLACE_WITH_USERNAME"
    os.environ["DBPASSWORD"] = getpass.getpass("Database Password:")

设置 AzureOpenAIEmbeddings

os.environ["AZURE_OPENAI_ENDPOINT"] = "REPLACE_WITH_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 身份验证

以下部分演示如何设置 LangChain 以使用 Microsoft Entra 身份验证。该类 AzurePGConnectionPool LangChain Azure Postgres 包中的方法通过使用以下方式为 Azure Database for PostgreSQL 服务检索令牌 DefaultAzureCredentialazure.identity library.

连接可以传入 connectionAzurePGVectorStore LangChain 向量存储。

登录 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

table_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(
    embedding=embeddings,
    table_name=table_name,
    connection=connection,
)
Metadata columns are specified as a string, defaulting to 'jsonb' type.
Embedding type is not specified, defaulting to 'vector'.
Embedding dimension is not specified, defaulting to 1536.
Embedding index is not specified, defaulting to 'DiskANN' with 'vector_cosine_ops' opclass.

配置向量存储参数

在初始化时,您可以为元数据类型、嵌入维度、索引类型等覆盖默认参数 AzurePGVectorStore。这允许您根据特定用例和数据定制向量存储。

关键配置选项:

  • - metadata_column_type:元数据列的类型(默认值: 'jsonb')。设置为 'jsonb', 'text'等。
  • - embedding_column_type:嵌入列的类型(默认值: 'vector').
  • - embedding_dimension:嵌入向量的维度(默认值: 1536).
  • - embedding_index_type:向量搜索的索引类型(默认值: 'DiskANN')。其他选项可能包括 'ivfflat', 'hnsw'等。
  • - embedding_index_opclass:索引的运算符类(默认值: 'vector_cosine_ops').

Example:

vector_store = AzurePGVectorStore(
    embedding=embeddings,
    table_name=table_name,
    connection=connection,
    metadata_column_type="jsonb",           # or "text"
    embedding_column_type="vector",
    embedding_dimension=768,                # set to match your model's output
    embedding_index_type="DiskANN",         # or "ivfflat", "hnsw", etc.
    embedding_index_opclass="vector_cosine_ops",  # or "vector_l2_ops", etc.
)

初始化 DiskANN 向量索引以实现更高效的向量搜索

DiskANN 是一种可扩展的近似最近邻搜索算法,用于在任何规模下进行高效的向量搜索。它提供高召回率、高每秒查询数和低查询延迟,即使对于十亿级数据集也是如此。这些特性使其成为处理大量数据的强大工具。

vector_store.create_index()
True

管理向量存储

添加项目

请注意,通过 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
['00e2cfe6-6e58-4733-9ebf-a708fd16488a',
 '224a22a8-567f-4e12-ac0f-5cfe4f0a4480',
 '62058e25-8f5e-4388-81c2-a5b7348ffef0',
 '1d37d282-504d-4d28-855a-8d39694b0265',
 '1fffcd2e-6fce-423f-bac3-ee5dc9084673',
 'b99efbab-2247-418f-b80d-d865f01d3c9e',
 'd2a86d1b-5d81-4c53-b3d2-a6b1e5189a3f',
 'a9577242-823e-42bc-9b0f-01670dbec190',
 'eaa45ae8-a84b-46eb-8a27-bf8652148d17',
 '7d7f04fd-6fb8-4a29-8708-b9f835ef270a']

更新项目

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(updated_docs, ids=[uuids[-1]], on_conflict_update=True)
['7d7f04fd-6fb8-4a29-8708-b9f835ef270a']

检索项目

vector_store.get_by_ids([str(uuids[3])])
[Document(id='1d37d282-504d-4d28-855a-8d39694b0265', metadata={'topic': 'food', 'doc_id': 4, 'location': 'market'}, page_content='the market also sells fresh oranges')]

删除项目

vector_store.delete(ids=[uuids[3]])
True

查询向量存储

创建向量存储并添加相关文档后,您可以在链或代理中查询向量存储。

过滤

向量存储支持一组过滤器,可通过 FilterCondition, OrFilterAndFilter 中的 LangChain Azure PostgreSQL package:

OperatorMeaning/Category
=相等
!=不相等
<小于
<=小于或等于
>大于
>=大于等于
in特殊情况 (in)
not in特殊情况 (not in)
is null特殊情况 (is null)
is not null特殊情况 (is not null)
between特殊情况 (between)
not between特殊情况 (not between)
like文本 (like)
ilike文本 (不区分大小写 like)
AND逻辑 (and)
OR逻辑 (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("* " + doc.page_content + " [" + str(doc.metadata) + "]")
* there are cats in the pond [{'topic': 'animals', 'doc_id': 1, 'location': 'pond'}]
* ducks are also found in the pond [{'topic': 'animals', 'doc_id': 2, 'location': 'pond'}]
* the new art exhibit is fascinating [{'topic': 'art', 'doc_id': 5, 'location': 'museum'}]
* the library hosts a weekly story time for kids [{'topic': 'reading', 'doc_id': 9, '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("* " + doc.page_content + " [" + str(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.528167] there are cats in the pond [{'topic': 'animals', 'doc_id': 1, 'location': 'pond'}]

转换为检索器进行查询

你还可以将向量存储转换为检索器,以便在链中更方便地使用。

retriever = vector_store.as_retriever(search_kwargs={"k": 1})
retriever.invoke("kitty")
[Document(id='00e2cfe6-6e58-4733-9ebf-a708fd16488a', metadata={'topic': 'animals', 'doc_id': 1, 'location': 'pond'}, page_content='there are cats in the 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("* " + doc.page_content + " [" + str(doc.metadata) + "]")
* there are cats in the pond [{'topic': 'animals', 'doc_id': 1, 'location': 'pond'}]
* the new art exhibit is fascinating [{'topic': 'art', 'doc_id': 5, 'location': 'museum'}]
* the library hosts a weekly story time for kids [{'topic': 'reading', 'doc_id': 9, 'location': 'library'}]
* ducks are also found in the pond [{'topic': 'animals', 'doc_id': 2, 'location': 'pond'}]

有关你可以在 AzurePGVectorStore 向量存储上执行的不同搜索的完整列表,请参阅 文档.

用于检索增强生成

有关如何使用此向量存储进行检索增强生成 (RAG) 的指南,请参阅以下部分:

API 参考

有关所有 AzurePGVectorStore features and configurations head to the API reference: https://github.com/langchain-ai/langchain-azure/tree/main/libs/azure-postgresql/src/langchain_azure_postgresql/langchain