LangChain-RAG必备:向量数据库如何CRUD

RAG是目前大语言模型从工具走向生产力实践的最热门的方式,它可以实现从海量的文本数据中检索相关的信息,并用于生成高质量的文本输出。而聊到RAG,我们就很难避开使用RAG的基础设施-向量数据库。

今天我将带领大家,以最为基础的CRUD入手来看看向量数据库应该如何使用。考虑到目前市面上的向量数据库众多,每个数据库的操作方式也无统一标准。本文将基于LangChain提供的VectorStore类中的统一操作方法,以chroma向量数据库作为示例进行演示。

向量数据库-新增

LangChain的VectorStore类是一个通用的向量数据库的接口,它可以对接不同的底层向量数据库,如chroma、faiss、annoy等,实现统一的操作方法和API。VectorStore类还提供了一些高级的功能,如语义检索、最大边际相关性(MMR)等,可以帮助我们更好地利用向量数据库的能力。

要想向向量数据库中新增数据,我们首先需要创建一个VectorStore对象,并在创建时配置好embedding function,即用于将原始数据转换为向量的函数。如下所示:

python 复制代码
# 通过HuggingFace创建embedding_function
embeddings = HuggingFaceEmbeddings(model_name=model)
# 创建VectorStore的具体实现类Chroma对象,并指定collection_name和持久化目录
vector = Chroma(collection_name = 'cname', embedding_function=embeddings,persist_directory='/vs')

创建好VectorStore对象后,我们就可以使用add_documents方法来向向量数据库中插入数据了。add_documents方法接受doc对象的list作为参数,doc对象的page_content为要插入的文本内容,同时,我们还可以在doc对象中添加一些其他的元数据,用于后续的查询或过滤。例如,我们可以向向量数据库中插入以下doc对象:

python 复制代码
# 先将文本拆分并转化为doc
loader = TextLoader(url,autodetect_encoding = True)

docs = loader.load()

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
# 插入向量数据库
vector.add_documents(documents=splits)

add_documents方法会返回一个id列表,这个id是doc的索引,用于唯一标识插入的doc对象。我们可以根据需要记录这个id,并与原始文件关联,一般来说,一个file对应多个doc,例如,我们可以将一个长文本拆分为多个段落,然后将每个段落作为一个doc插入到向量数据库中,这样可以提高检索的效率和精度。

向量数据库-删除

要想从向量数据库中删除数据,我们可以使用delete方法,delete方法接受一个id或一个id列表作为参数,然后根据id来删除对应的doc对象。例如,我们可以使用以下代码来删除id为1的doc对象:

python 复制代码
# 删除id为1的doc对象
vector.delete('1')

如果我们不知道要删除的doc对象的id,但是知道它的一些元数据,我们可以先使用metadata中的字段来查询到id,然后再使用delete方法来批量删除。例如,我们可以使用以下代码来删除所有category为功能的doc对象:

python 复制代码
# 根据file_id的条件,查询到所有符合的doc对象的id
reuslt = vector.get(where={"file_id":file_id}) 
# 使用delete方法,批量删除这些id对应的doc对象
if reuslt['ids'] :
    vector.delete(reuslt['ids'])

向量数据库-更新

VectorStore类没有提供专门的更新方法,因为更新一个doc对象相当于先删除它,然后再插入一个新的doc对象。因此,我们可以使用delete和insert方法来实现文档的更新。例如,我们可以使用以下代码来更新id为2的doc对象,将它的source从文档改为官网:

python 复制代码
# 删除id为2的doc对象
vector.delete('2')

# 插入新的doc对象
vector.add_documents(new_doc)

向量数据库-查询

VectorStore类提供了多种查询方法,用于根据不同的需求和场景来检索向量数据库中的数据。查询方法主要分为两种类型:similarity和mmr。similarity类型的查询方法是基于向量之间的相似度来进行检索的,它可以接受一个字符串或一个向量作为查询,然后返回最相似的doc对象以及相似度。mmr类型的查询方法是基于最大边际相关性(MMR)来进行检索的,它可以接受一个字符串或一个向量作为查询,然后返回一个多样化的doc对象列表,这些doc对象既与查询相关,又尽量不相似。

接下来,我们将介绍以下四个查询方法:

  • similarity_search:这个方法是最基本的相似度查询方法,它接受一个字符串作为查询,以及一个可选的top_n参数,用于指定返回的doc对象的数量,默认为4,然后返回最相似的doc对象或它们的id。例如,我们可以使用以下代码来查询与"语义检索"最相似的doc对象:
python 复制代码
# 查询与"语义检索"最相似的doc对象
docs = vector.similarity_search("语义检索")

# 打印查询结果
for doc in docs:
    print(doc)
  • similarity_search_with_score:这个方法与similarity_search类似,但是它会同时返回向量之间的距离,距离越小表示越相似。例如,我们可以使用以下代码来查询与"语义检索"最相似的doc对象,并打印它们的分数:
python 复制代码
# 查询与"语义检索"最相似的doc对象,并返回分数
docs_with_score = vector.similarity_search_with_score("语义检索")

# 打印查询结果和分数
for doc_with_score in docs_with_score:
    print(doc_with_score[0], doc_with_score[1])
  • similarity_search_with_relevance_scores:这个方法与similarity_search_with_score类似,但是它会将分数转换为一个介于0和1之间的相关度评分,这个评分表示查询和doc对象之间的语义相关程度,评分越高越相似。代码与similarity_search_with_score类似,不再额外示例

  • max_marginal_relevance_search:这个方法是基于最大边际相关性(MMR)来进行查询的,最大边际相关性(MMR)是一种用于检索或摘要的方法,它既考虑了查询和文档之间的相似度,又考虑了文档之间的多样性,从而避免返回重复或冗余的结果。它接受一个字符串或一个向量作为查询,以及一个可选的top_n参数,用于指定返回的doc对象的数量,默认为10,然后返回一个多样化的doc对象列表,这些doc对象既与查询相关,又尽量不相似。这个方法可以用于生成摘要、提取关键信息、避免重复内容等场景。例如,我们可以使用以下代码来查询与"LangChain"相关的但不相似的doc对象:

python 复制代码
# 查询与"LangChain"相关的但不相似的doc对象
docs = vector.max_marginal_relevance_search("LangChain")

# 打印查询结果
for doc in docs:
    print(doc)

结语

**CRUD只是操作向量数据库的基础手段,想要用好RAG必须在CRUD的基础上掌握语义检索的相关原理。**比如文档拆分时需要按语义尽可能的拆分为小的单元,而在召回时,则需要基于召回的单元尽可能的补充完整的窗口上下文,才能在最终使用LLM时得到尽可能好的结果。这些都需要在crud的基础上执行一些额外操作,我将在下次给大家讲述,希望你持续关注。

以上就是本文的全部内容,我希望你能从中学到一些有用的知识,也欢迎你在评论区留下你的反馈或问题。谢谢你的阅读,下次再见。😊

相关推荐
szhf784 小时前
SpringBoot Test详解
spring boot·后端·log4j
无尽的沉默4 小时前
SpringBoot整合Redis
spring boot·redis·后端
摸鱼的春哥4 小时前
春哥的Agent通关秘籍07:5分钟实现文件归类助手【实战】
前端·javascript·后端
Victor3564 小时前
MongoDB(2)MongoDB与传统关系型数据库的主要区别是什么?
后端
JaguarJack4 小时前
PHP 应用遭遇 DDoS 攻击时会发生什么 从入门到进阶的防护指南
后端·php·服务端
BingoGo4 小时前
PHP 应用遭遇 DDoS 攻击时会发生什么 从入门到进阶的防护指南
后端
Victor3564 小时前
MongoDB(3)什么是文档(Document)?
后端
牛奔6 小时前
Go 如何避免频繁抢占?
开发语言·后端·golang
想用offer打牌11 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
KYGALYX13 小时前
服务异步通信
开发语言·后端·微服务·ruby