Skip to main content
这是使用 postgres 作为后端并利用 pgvector 扩展的 LangChain 向量存储抽象的实现。
代码位于名为 langchain-postgres 的集成包中。

状态

此代码已从 langchain-community 迁移到名为 langchain-postgres 的专用包中。已做出以下变更:
  • langchain-postgres 仅适用于 psycopg3。请将连接字符串从 postgresql+psycopg2://... 更新为 postgresql+psycopg://langchain:langchain@...(注意:驱动名称是 psycopg 而不是 psycopg3,但它会使用 psycopg3)。
  • 嵌入存储和集合的模式已更改,以使 add_documents 在使用用户指定的 ID 时能正确运行。
  • 现在必须传递一个显式的连接对象。
目前没有机制支持在模式变更时轻松进行数据迁移。因此,向量存储的任何模式变更都需要用户重新创建表并重新添加文档。 如果这是一个顾虑,请使用其他向量存储。如果不是,则此实现应该适合你的使用场景。

配置

首先下载合作伙伴包:
pip install -qU langchain-postgres
你可以运行以下命令启动带有 pgvector 扩展的 postgres 容器:
%docker run --name pgvector-container -e POSTGRES_USER=langchain -e POSTGRES_PASSWORD=langchain -e POSTGRES_DB=langchain -p 6024:5432 -d pgvector/pgvector:pg16

凭据

运行本笔记本不需要任何凭据,只需确保你已下载 langchain-postgres 包并正确启动了 postgres 容器。 如果你希望获得最佳的模型调用自动追踪,也可以取消以下注释来设置你的 LangSmith API 密钥:
os.environ["LANGSMITH_API_KEY"] = getpass.getpass("Enter your LangSmith API key: ")
os.environ["LANGSMITH_TRACING"] = "true"

实例化

# | output: false
# | echo: false
from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
from langchain_postgres import PGVector

# See docker command above to launch a postgres instance with pgvector enabled.
connection = "postgresql+psycopg://langchain:langchain@localhost:6024/langchain"  # Uses psycopg3!
collection_name = "my_docs"

vector_store = PGVector(
    embeddings=embeddings,
    collection_name=collection_name,
    connection=connection,
    use_jsonb=True,
)

管理向量存储

向向量存储添加项目

注意:按 ID 添加文档会覆盖与该 ID 匹配的所有现有文档。
from langchain_core.documents import Document

docs = [
    Document(
        page_content="there are cats in the pond",
        metadata={"id": 1, "location": "pond", "topic": "animals"},
    ),
    Document(
        page_content="ducks are also found in the pond",
        metadata={"id": 2, "location": "pond", "topic": "animals"},
    ),
    Document(
        page_content="fresh apples are available at the market",
        metadata={"id": 3, "location": "market", "topic": "food"},
    ),
    Document(
        page_content="the market also sells fresh oranges",
        metadata={"id": 4, "location": "market", "topic": "food"},
    ),
    Document(
        page_content="the new art exhibit is fascinating",
        metadata={"id": 5, "location": "museum", "topic": "art"},
    ),
    Document(
        page_content="a sculpture exhibit is also at the museum",
        metadata={"id": 6, "location": "museum", "topic": "art"},
    ),
    Document(
        page_content="a new coffee shop opened on Main Street",
        metadata={"id": 7, "location": "Main Street", "topic": "food"},
    ),
    Document(
        page_content="the book club meets at the library",
        metadata={"id": 8, "location": "library", "topic": "reading"},
    ),
    Document(
        page_content="the library hosts a weekly story time for kids",
        metadata={"id": 9, "location": "library", "topic": "reading"},
    ),
    Document(
        page_content="a cooking class for beginners is offered at the community center",
        metadata={"id": 10, "location": "community center", "topic": "classes"},
    ),
]

vector_store.add_documents(docs, ids=[doc.metadata["id"] for doc in docs])
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

从向量存储中删除项目

vector_store.delete(ids=["3"])

查询向量存储

创建向量存储并添加相关文档后,通常需要在运行链或代理时对其进行查询。

过滤支持

向量存储支持一组可应用于文档元数据字段的过滤器。
运算符含义/类别
$eq等于 (==)
$ne不等于 (!=)
$lt小于 (<)
$lte小于等于 (<=)
$gt大于 (>)
$gte大于等于 (>=)
$in特殊情况(在列表中)
$nin特殊情况(不在列表中)
$between特殊情况(在两值之间)
$like文本(like)
$ilike文本(不区分大小写 like)
$and逻辑与(and)
$or逻辑或(or)

直接查询

执行简单的相似性搜索,方法如下:
results = vector_store.similarity_search(
    "kitty", k=10, filter={"id": {"$in": [1, 5, 2, 9]}}
)
for doc in results:
    print(f"* {doc.page_content} [{doc.metadata}]")
* there are cats in the pond [{'id': 1, 'topic': 'animals', 'location': 'pond'}]
* the library hosts a weekly story time for kids [{'id': 9, 'topic': 'reading', 'location': 'library'}]
* ducks are also found in the pond [{'id': 2, 'topic': 'animals', 'location': 'pond'}]
* the new art exhibit is fascinating [{'id': 5, 'topic': 'art', 'location': 'museum'}]
如果提供包含多个字段但没有运算符的字典,顶层将被解释为逻辑 AND 过滤器
vector_store.similarity_search(
    "ducks",
    k=10,
    filter={"id": {"$in": [1, 5, 2, 9]}, "location": {"$in": ["pond", "market"]}},
)
[Document(metadata={'id': 1, 'topic': 'animals', 'location': 'pond'}, page_content='there are cats in the pond'),
 Document(metadata={'id': 2, 'topic': 'animals', 'location': 'pond'}, page_content='ducks are also found in the pond')]
vector_store.similarity_search(
    "ducks",
    k=10,
    filter={
        "$and": [
            {"id": {"$in": [1, 5, 2, 9]}},
            {"location": {"$in": ["pond", "market"]}},
        ]
    },
)
[Document(metadata={'id': 1, 'topic': 'animals', 'location': 'pond'}, page_content='there are cats in the pond'),
 Document(metadata={'id': 2, 'topic': 'animals', 'location': 'pond'}, page_content='ducks are also found in the 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.763449] there are cats in the pond [{'id': 1, 'topic': 'animals', 'location': 'pond'}]
有关可在 PGVector 向量存储上执行的不同搜索的完整列表,请参阅 API 参考

转换为检索器后查询

你也可以将向量存储转换为检索器,以便在链中更便捷地使用。
retriever = vector_store.as_retriever(search_type="mmr", search_kwargs={"k": 1})
retriever.invoke("kitty")
[Document(metadata={'id': 1, 'topic': 'animals', 'location': 'pond'}, page_content='there are cats in the pond')]

用于检索增强生成

有关如何将此向量存储用于检索增强生成(RAG)的指南,请参阅以下章节:

API 参考

有关所有 __ModuleName__VectorStore 功能和配置的详细文档,请参阅 API 参考:python.langchain.com/api_reference/postgres/vectorstores/langchain_postgres.vectorstores.PGVector.html