Timescale Vector x LangChain: Making PostgreSQL A Better Vector Database for AI Applications

Timescale Vector x LangChain:使 PostgreSQL 成为更适合 AI 应用的向量数据库

15 分钟阅读

编者按:这篇文章是与 Timescale Vector 团队合作撰写的。他们与 LangChain 的集成支持将 PostgreSQL 作为您的向量数据库,以实现更快的相似性搜索、用于 RAG 的基于时间的上下文检索和自查询功能。他们还提供 90 天免费试用!

隆重推出用于 LangChain 的 Timescale Vector 集成。Timescale Vector 使 LangChain 开发人员能够使用 PostgreSQL 作为其向量数据库构建更好的 AI 应用程序:具有更快的向量相似性搜索、高效的基于时间的搜索过滤,以及易于使用的单个云 PostgreSQL 数据库的操作简便性,不仅用于向量嵌入,还用于 AI 应用程序的关系数据和时间序列数据。

根据 Stack Overflow 2023 年开发者调查,PostgreSQL 是世界上最受欢迎的数据库。这是有充分理由的:它经过了三十多年的生产使用考验,它稳健可靠,并且拥有丰富的工具、驱动程序和连接器生态系统。

虽然 pgvector(PostgreSQL 上用于向量数据的开源扩展)是一个出色的扩展(并且作为 Timescale Vector 的一部分提供),但这只是为 PostgreSQL 上的 AI 应用程序开发人员提供生产级体验的难题中的一块。在与敏捷初创公司和老牌行业巨头的众多开发人员交谈后,我们看到了增强 pgvector 以满足构建 AI 应用程序的开发人员的性能和运营需求的必要性。

以下是关于 Timescale Vector 如何帮助您使用 LangChain 构建更好的 AI 应用程序的 TL;DR 总结

  • 数百万向量上更快的相似性搜索:得益于受 DiskANN 算法启发的新搜索索引的引入,Timescale Vector 在约 99% 的召回率下实现了比专业数据库 Weaviate 快 243% 的搜索速度, 并且在一个百万 OpenAI 嵌入的数据集上,性能优于所有现有的 PostgreSQL 搜索索引,提升幅度在 39.39% 到 1,590.33% 之间。此外,启用乘积量化可实现与 pgvector 相比节省 10 倍索引空间。Timescale Vector 还提供 pgvector 的分层可导航小世界 (HNSW) 和倒排文件扁平 (IVFFlat) 索引算法。
  • 具有高效的基于时间过滤的相似性搜索:Timescale Vector 优化了基于时间的向量搜索,利用 Timescale 的超表的自动基于时间的分区和索引,以高效地查找最近的嵌入、按时间范围或文档年龄约束向量搜索,并轻松存储和检索大型语言模型 (LLM) 响应和聊天记录。基于时间的语义搜索还使您能够使用检索增强生成 (RAG) 和基于时间的上下文检索,为用户提供更有用的 LLM 响应。
  • 简化的 AI 基础设施堆栈:通过将向量嵌入、关系数据和时间序列数据组合在一个 PostgreSQL 数据库中,Timescale Vector 消除了大规模管理多个数据库系统带来的操作复杂性。
  • 简化的元数据处理和多属性过滤:您可以利用所有 PostgreSQL 数据类型来存储和过滤元数据,并将向量搜索结果与关系数据 JOIN,以获得更符合上下文的响应。在未来的版本中,Timescale Vector 还将支持丰富的多属性过滤,从而在过滤元数据时实现更快的相似性搜索。

除了向量工作负载的这些创新之外,Timescale Vector 还提供了一个稳健、生产就绪的 PostgreSQL 平台,具有灵活的定价、企业级安全性以及免费的专家支持。

在这篇文章的其余部分,我们将深入探讨(使用代码!)Timescale Vector 为希望将 PostgreSQL 用作 LangChain 向量数据库的开发人员提供的独特功能

  • 使用 DiskANN、HNSW 和 IVFFlat 索引类型实现更快的相似性搜索。
  • 在按时间过滤向量时实现高效的相似性搜索。
  • 使用基于时间的上下文检索的检索增强生成 (RAG)。
  • 高级自查询功能。

(如果您想直接查看代码,请浏览本教程)。

🎉 LangChain 用户免费获得 3 个月 Timescale Vector

Timescale 为 LangChain 用户提供 Timescale Vector 的 90 天延长试用期。这使得测试和开发 Timescale Vector 应用程序变得容易,因为在试用期内,您无需为启动的任何云 PostgreSQL 数据库付费。立即免费试用 Timescale Vector

PostgreSQL 中更快的向量相似性搜索

Timescale Vector 加快了大规模向量数据集上的近似最近邻 (ANN) 搜索速度,通过受 DiskANN 算法启发的先进 ANN 索引增强了 pgvector。Timescale Vector 还提供 pgvector 的 HNSW 和 IVFFlat 索引算法,使开发人员可以灵活地为他们的用例选择合适的索引。

我们使用 ANN 基准测试套件进行的性能基准测试表明,在约 99% 的召回率下,Timescale Vector 比所有现有的 PostgreSQL 搜索索引快 39.43% 到 1,590.33%,并且比像 Weaviate 这样的专业向量数据库快 243.77%,数据集为一百万个 OpenAI 嵌入。您可以在此处阅读有关性能基准测试方法和结果的更多信息。

标题:在 100 万个 OpenAI 嵌入上执行 99% 召回率的近似最近邻搜索时,Timescale Vector 的新索引比专业向量数据库 Weaviate 快 243%,并且优于所有现有的 PostgreSQL 索引类型。

在 LangChain 中使用 Timescale Vector 的 DiskANN、HNSW 或 IVFFLAT 索引非常简单。

只需创建一个 Timescale Vector 向量存储,如下所示

from langchain.vectorstores.timescalevector import TimescaleVector

# Create a Timescale Vector instance from the collection of documents
db = TimescaleVector.from_documents(
   embedding=embeddings,
   documents=docs,
   collection_name=COLLECTION_NAME,
   service_url=SERVICE_URL,
)


然后运行

# create an index
# by default this will create a Timescale Vector (DiskANN) index
db.create_index()

这将使用默认参数创建一个 timescale-vector 索引。

我们应该指出,“索引”一词有点过载。对于许多向量数据库,索引是存储数据的东西(在关系数据库中,这通常称为表),但在 PostgreSQL 世界中,索引是加速搜索的东西,我们在这里使用的是后一种含义。

我们还可以在 `create_index` 命令中指定索引创建的确切参数,如下所示

# create an timescale vector index (DiskANN) with specified parameters
db.create_index(index_type="tsv", max_alpha=1.0, num_neighbors=50)

Timescale Vector 新的受 DiskANN 启发的向量搜索索引的优势包括以下几点

  • 在 PostgreSQL 中以高精度实现更快的向量搜索。
  • 针对在磁盘上运行进行了优化,而不仅仅是在内存中使用。
  • 量化优化与 PostgreSQL 兼容,减少了向量大小,从而缩小了索引大小(在某些情况下缩小了 10 倍!)并加快了搜索速度。
  • 高效的混合搜索或过滤其他维度。

有关 DiskANN 以及 Timescale Vector 的新索引如何工作的更多信息,请参阅此博客文章

Pgvector 作为 Timescale Vector 的一部分打包,因此您还可以在 LangChain 应用程序中访问 pgvector 的 HNSW 和 IVFFLAT 索引算法。从 LangChain 应用程序代码方便地创建数据库索引的能力使得创建不同的索引并比较它们的性能变得容易。

# Create an HNSW index. 
# Note: you don't need to specify m and ef_construction parameters as we set smart defaults. 
db.create_index(index_type="hnsw", m=16, ef_construction=64)


# Create an IVFFLAT index 
# Note:you don't need to specify num_lists and num_records parameters as we set smart defaults.
db.create_index(index_type="ivfflat", num_lists=20, num_records=1000)

为您的 LangChain AI 应用程序添加高效的基于时间搜索的功能

Timescale Vector 优化了基于时间的向量搜索, 利用 Timescale 的超表的自动基于时间的分区和索引,以高效地按时间和相似性搜索向量。

时间通常是向量嵌入的重要元数据组件。嵌入的来源(如文档、图像和网页)通常具有与之关联的时间戳,例如,它们的创建日期、发布日期或上次更新日期,仅举几例。

我们可以利用向量嵌入集合中的时间元数据来提高搜索结果的质量和适用性,方法是检索不仅语义相似,而且与特定时间框架相关的向量。

以下是一些示例,其中基于时间的向量检索可以改进您的 LangChain 应用程序

  • 聊天记录:存储和检索 LLM 响应历史记录。例如,聊天机器人聊天记录。
  • 查找最近的嵌入:查找与查询向量最相似的最新嵌入。例如,查找与选举相关的最新新闻、文档或社交媒体帖子。
  • 在时间范围内搜索:将相似性搜索限制为仅在相关时间范围内的向量。例如,提出关于知识库的基于时间的问题(“2023 年 1 月至 3 月之间添加了哪些新功能?”)。

让我们看一个在 git log 数据集上执行基于时间搜索的示例。在 git log 中,每个条目都有一个时间戳、作者以及一些关于提交的信息。

为了说明如何使用 TimescaleVector 基于时间的向量搜索功能,我们将询问有关 TimescaleDB 的 git log 历史记录的问题。每个 git 提交条目都有一个与之关联的时间戳,以及一条消息和其他元数据(例如,作者)。

加载文本并提取元数据

首先,我们使用 LangChain 的 JSON Loader 加载 git log。

# Load data from JSON file and extract metadata
loader = JSONLoader(
   file_path=FILE_PATH,
   jq_schema='.commit_history[]',
   text_content=False,
   metadata_func=extract_metadata
)
documents = loader.load()

请注意,我们如何提供名为 `extract_metadata` 的函数作为 JSONLoader 的参数。此函数使我们不仅可以以向量化形式存储 JSON 的内容,还可以存储有关嵌入的元数据。正是在此函数中,我们将指定 git log 条目的时间戳,以用于我们基于时间的向量搜索。

为文档创建基于时间的标识符

为了在 LangChain 中进行基于时间的搜索,Timescale Vector 使用 UUID v1 的“datetime”部分将向量放置在正确的时间分区中。Timescale Vector 的 Python 客户端库提供了一个易于使用的名为 `uuid_from_time` 的函数,用于从 Python `datetime` 对象创建 UUID v1,然后您可以将其传递给 Timescale Vector 向量存储构造函数,我们将在下面的代码片段中看到。以下是我们如何使用 `uuid_from_time` 辅助函数

from timescale_vector import client
# Function to take in a date string in the past and return a uuid v1
def create_uuid(date_string: str):
   if date_string is None:
       return None
   time_format = '%a %b %d %H:%M:%S %Y %z'
   datetime_obj = datetime.strptime(date_string, time_format)
   uuid = client.uuid_from_time(datetime_obj)
   return str(uuid)

以下是我们传递给 JSONLoader 的 `extract_metdata()` 函数,指定了我们希望在向量集合中每个向量嵌入的元数据中包含的字段

# Metadata extraction function to extract metadata from a JSON record
def extract_metadata(record: dict, metadata: dict) -> dict:
   record_name, record_email = split_name(record["author"])
   metadata["id"] = create_uuid(record["date"])
   metadata["date"] = create_date(record["date"])
   metadata["author_name"] = record_name
   metadata["author_email"] = record_email
   metadata["commit_hash"] = record["commit"]
   return metadata

注意:上面的代码引用了两个辅助函数,用于将内容放入正确的格式 (`split_name()` 和 `create_date()`),为了简洁起见,我们省略了这两个函数。完整代码包含在本帖末尾的资源部分链接的教程中。

接下来,我们将从上面加载到 JSONLoader 中的文档集合创建一个 Timescale Vector 实例。

将向量和元数据加载到 Timescale Vector

最后,我们将从我们加载的一组文档中创建 Timescale Vector 实例。

为了利用 Timescale Vector 高效的基于时间搜索,我们需要在创建 Timescale Vector 向量存储时指定 `time_partition_interval` 参数。此参数表示按时间对数据进行分区的每个间隔的长度。每个分区将包含在指定时间长度内的数据。

在下面的示例中,为了简单起见,我们使用了七天,但您可以选择对您的用例有意义的任何值——例如,如果您经常查询最近的向量,您可能希望使用较小的时间增量(例如一天),或者如果您查询跨越十年时间段的向量,那么您可能希望使用较大的时间增量,例如六个月或一年。作为经验法则,常用查询应仅触及几个分区,同时您的完整数据集应适合 1000 个分区内,但不要太紧张——系统对此值不是很敏感。

我们将 `ids` 参数指定为我们在上述预处理步骤中创建并存储在我们元数据的 ID 字段中的 UUID v1 列表。我们这样做是因为我们希望 UUID 的时间部分反映过去的日期。如果我们希望将当前日期和时间与我们的文档关联,我们可以删除 `id` 参数,并且将自动创建带有当前日期和时间的 UUID。

# Define collection name
COLLECTION_NAME = "timescale_commits"
embeddings = OpenAIEmbeddings()

# Create a Timescale Vector instance from the collection of documents
db = TimescaleVector.from_documents(
     embedding=embeddings,
     ids = [doc.metadata["id"] for doc in docs],
     documents=docs,
     collection_name=COLLECTION_NAME,
     service_url=SERVICE_URL,
     time_partition_interval=timedelta(days = 7),)

使用时间过滤器进行高效的相似性搜索

现在我们已将向量数据和元数据加载到 Timescale Vector 向量存储中,并在存储我们的向量和元数据的表上启用了自动基于时间的分区,我们可以使用基于时间的过滤器查询我们的向量存储,如下所示

start_dt = datetime(2023, 8, 1, 22, 10, 35)
end_dt = datetime(2023, 8, 30, 22, 10, 35)
query = "What's new with TimescaleDB functions?"
docs_with_score = db.similarity_search_with_score(query, start_date=start_dt, end_date=end_dt)
--------------------------------------------------------------------------------
Score:  0.17487859725952148
Date:  Tue Aug 29 18:13:24 2023 +0200
{"commit": " e4facda540286b0affba47ccc63959fefe2a7b26", "author": "Sven Klemm<sven@timescale.com>", "date": "Tue Aug 29 18:13:24 2023 +0200", "change summary": "Add compatibility layer for _timescaledb_internal functions", "change details": "With timescaledb 2.12 ..."}
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Score:  0.17487859725952148
Date:  Tue Aug 29 18:13:24 2023 +0200
{"commit": " e4facda540286b0affba47ccc63959fefe2a7b26", "author": "Sven Klemm<sven@timescale.com>", "date": "Tue Aug 29 18:13:24 2023 +0200", "change summary": "Add compatibility layer for _timescaledb_internal functions", "change details": "With timescaledb 2.12 all the functions... "}
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Score:  0.18100780248641968
Date:  Sun Aug 20 22:47:10 2023 +0200
{"commit": " 0a66bdb8d36a1879246bd652e4c28500c4b951ab", "author": "Sven Klemm<sven@timescale.com>", "date": "Sun Aug 20 22:47:10 2023 +0200", "change summary": "Move functions to _timescaledb_functions schema", "change details": "To increase schema security we do ..."}
--------------------------------------------------------------------------------

成功!请注意,结果中仅包含时间戳在 2023 年 8 月 1 日至 2023 年 8 月 30 日的指定开始和结束日期范围内的向量。

我们还可以使用提供的开始日期和稍后的时间增量指定时间过滤器

start_dt = datetime(2023, 8, 1, 22, 10, 35)
td = timedelta(days=7)
query = "What's new with TimescaleDB functions?"

docs_with_score = db.similarity_search_with_score(query, start_date=start_dt, time_delta=td)

并在提供的 end_date 和更早的时间增量内指定时间过滤器

end_dt = datetime(2023, 8, 30, 22, 10, 35)
td = timedelta(days=7)
query = "What's new with TimescaleDB functions?"

docs_with_score = db.similarity_search_with_score(query, end_date=end_dt, time_delta=td)

幕后发生了什么

以下是一些关于为什么 Timescale Vector 的基于时间的分区加快了带有基于时间过滤器的 ANN 查询的直觉

Timescale Vector 按时间对数据进行分区,并在每个分区上单独创建 ANN 索引。然后,在搜索期间,我们执行一个三步过程

  • 步骤 1:过滤掉与时间谓词不匹配的分区。
  • 步骤 2:在所有匹配的分区上执行相似性搜索。
  • 步骤 3:合并步骤 2 中每个分区的所有结果,重新排序,并按时间过滤掉结果。

Timescale Vector 利用 TimescaleDB 的超表,它自动按时间戳对向量和关联的元数据进行分区。这使得可以高效地按与查询向量的相似性和时间查询向量,因为查询的时间窗口中不包含的分区将被忽略,从而通过一次性过滤掉大量数据来使搜索效率更高。

在 LangChain 应用程序中使用 Timescale Vector 为检索增强生成提供支持,并进行基于时间的上下文检索

让我们将所有内容放在一起,看看如何使用 Timescale Vector 为我们上面检查的 git log 数据集上的检索增强生成 (RAG) 提供支持。

Timescale Vector 有助于基于时间的上下文检索,我们希望在指定的时间范围内找到最相关的向量,以用作回答用户查询的上下文。让我们看一下下面的示例,使用 Timescale Vector 作为检索器。

首先,我们从 TimescaleVector 存储创建一个检索器。

# Set timescale vector as a retriever and specify start and end dates via kwargs
retriever = db.as_retriever(search_kwargs={"start_date": start_dt, "end_date": end_dt})

在创建检索器时,我们可以通过将 Timescale Vector 的时间过滤器参数作为 `search_kwargs` 传递来将搜索限制在相关时间范围内。

然后,我们将通过传递我们的检索器和我们想要用于生成响应的 LLM,从 Stuff chain 创建一个 RetrievalQA chain

from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(temperature = 0.1, model = 'gpt-3.5-turbo-16k')

from langchain.chains import RetrievalQA
qa_stuff = RetrievalQA.from_chain_type(
   llm=llm,
   chain_type="stuff",
   retriever=retriever,
   verbose=True,
)

然后我们可以查询 RetrievalQA chain,它将使用 Timescale Vector 支持的检索器,使用时间范围内最相关的文档来回答您的查询


query = "What's new with the timescaledb functions? Tell me when these changes were made."
response = qa_stuff.run(query)
print(response)


> 进入新的 RetrievalQA chain...

> 完成 chain。

对 timescaledb 函数进行了以下更改
1. “为 _timescaledb_internal 函数添加兼容性层” - 此更改于 2023 年 8 月 29 日星期二 18:13:24 +0200 进行。
2. “将函数移动到 _timescaledb_functions schema” - 此更改于 2023 年 8 月 20 日星期日 22:47:10 +0200 进行。
3. “将实用程序函数移动到 _timescaledb_functions schema” - 此更改于 2023 年 8 月 22 日星期二 12:01:19 +0200 进行。
4. “将分区函数移动到 _timescaledb_functions schema” - 此更改于 2023 年 8 月 29 日星期二 10:49:47 +0200 进行。

成功!请注意,LLM 用于组成答案的上下文仅来自指定日期范围内的检索文档。

这是一个强大概念的简单示例——在您的 RAG 应用程序中使用基于时间的上下文检索可以帮助为您的用户提供更相关的答案。这种基于时间的上下文检索对于任何具有自然语言和时间组件的数据集都很有用。Timescale Vector 凭借其高效的基于时间的相似性搜索功能独特地实现了这一点,并且由于 Timescale Vector 集成,在您的 LangChain 应用程序中利用它很容易。

具有 Timescale Vector 的高级 LangChain 自查询功能

Timescale Vector 还支持 LangChain 最酷的功能之一:自查询检索器

以下是它的工作原理:我们从 Timescale Vector 向量存储创建一个检索器,并向其提供带有查询语句和过滤器(单个或复合)的自然语言查询。然后,检索器使用查询构造 LLM chain 编写 SQL 查询,并将其应用于 Timescale Vector 向量存储中底层的 PostgreSQL 数据库。

借助 Timescale Vector,您可以使用自查询检索器询问带有 limit、元数据和基于时间过滤器的查询。让我们看一个在 git log 数据集上使用自查询的示例。

首先,我们实例化我们的 TimescaleVector 向量存储

COLLECTION_NAME = "timescale_commits"
vectorstore = TimescaleVector(
   embedding_function=OpenAIEmbeddings(),
   collection_name=COLLECTION_NAME,
   service_url=SERVICE_URL,
)


其次,让我们从 LLM 创建自查询检索器,并将以下参数传递给它

  • `llm`:我们希望自查询检索器用于构造查询的 LLM。
  • `vectorstore`:我们的 TimescaleVector 向量存储,如上所述实例化。
  • `document_content_description`:与我们的向量嵌入关联的内容的描述。在本例中,它是关于 git log 条目的信息。
  • `metadata_field_info`:AttributeInfo 对象的列表,它向 LLM 提供有关我们的向量集合中元数据字段的信息。
  • `enable_limit`:将此设置为“true”使我们能够询问带有隐含限制的问题,这有助于约束返回的结果数量。
from langchain.llms import OpenAI
from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain.chains.query_constructor.base import AttributeInfo

# Give LLM info about the metadata fields
metadata_field_info = [
   AttributeInfo(
       name="id",
       description="A UUID v1 generated from the date of the commit",
       type="uuid",
   ),
   AttributeInfo(
       name="date",
       description="The date of the commit in timestamptz format",
       type="timestamptz",
   ),
   AttributeInfo(
       name="author_name",
       description="The name of the author of the commit",
       type="string",
   ),
   AttributeInfo(
       name="author_email",
       description="The email address of the author of the commit",
       type="string",
   )
]
document_content_description = "The git log commit summary containing the commit hash, author, date of commit, change summary and change details"

# Instantiate the self-query retriever from an LLM
llm = OpenAI(temperature=0)
retriever = SelfQueryRetriever.from_llm(
   llm, vectorstore, document_content_description, metadata_field_info, enable_limit=True, verbose=True
)

现在到了有趣的部分,让我们查询我们的自查询检索器。

自查询示例:查询和元数据过滤器

这是一个在自然语言中指定的简单元数据过滤器的示例。在本例中,我们要求查找特定人员添加的提交

retriever.get_relevant_documents("What commits about timescaledb_functions did Sven Klemm add?")

以下是 LLM chain 的详细输出,显示了自然语言查询被翻译成的查询参数

query='timescaledb_functions' filter=Comparison(comparator=<Comparator.EQ: 'eq'>, attribute='author_name', value='Sven Klemm') limit=None


自查询示例:基于时间的过滤器

这是一个使用基于时间过滤器的问题的示例。获取结果以回答此问题的查询将利用 Timescale Vector 高效的基于时间的分区。

# This example specifies a time-based filter
retriever.get_relevant_documents("What commits were added in July 2023?")

以下是 LangChain 的自查询检索器关于自然语言查询被翻译成的 SQL 查询参数的详细解释

query=' ' filter=Operation(operator=<Operator.AND: 'and'>, arguments=[Comparison(comparator=<Comparator.GTE: 'gte'>, attribute='date', value='2023-07-01T00:00:00Z'), Comparison(comparator=<Comparator.LTE: 'lte'>, attribute='date', value='2023-07-31T23:59:59Z')]) limit=None


以下是结果的片段

[Document(page_content='{"commit": " 5cf354e2469ee7e43248bed382a4b49fc7ccfecd", "author": "Markus Engel<engel@sero-systems.de>", "date": "Mon Jul 31 11:28:25 2023 +0200",...


Document(page_content='{"commit": " 88aaf23ae37fe7f47252b87325eb570aa417c607", "author": "noctarius aka Christoph Engelbert<me@noctarius.com>", "date": "Wed Jul 12 14:53:40 2023 +0200", . . .


Document(page_content='{"commit": " d5268c36fbd23fa2a93c0371998286e8688247bb", "author": "Alexander Kuzmenkov<36882414+akuzm@users.noreply.github.com>", "date": "Fri Jul 28 13:35:05 2023 +0200",...


请注意,您如何在自然语言中指定查询、过滤器和复合过滤器(带有 AND、OR 的过滤器),并且自查询检索器会将该查询转换为 SQL 并在 Timescale Vector (PostgreSQL) 向量存储上执行搜索。

这说明了自查询检索器的强大功能。您可以使用它对您的向量存储执行复杂的搜索,而无需您或您的用户直接编写任何 SQL。

更重要的是,您可以将自查询检索器与 LangChain RetrievalQA chain 结合使用,为 RAG 应用程序提供支持!

资源和后续步骤

现在您已经了解了 Timescale Vector 如何帮助您使用 PostgreSQL 为 AI 应用程序提供支持,现在轮到您深入了解了。通过阅读以下资源集中的教程之一或博客文章之一,迈出您学习之旅的下一步

🎉 还有一个提醒: LangChain 用户免费获得 3 个月 Timescale Vector

Timescale 为 LangChain 用户提供 Timescale Vector 的 90 天延长试用期。这使得测试和开发 Timescale Vector 应用程序变得容易,因为在试用期内,您无需为启动的任何云 PostgreSQL 数据库付费。立即免费试用 Timescale Vector