在上一篇文章中,我们了解了什么是向量数据库,并以开源向量数据库Weaviate为例,介绍了它的使用安装和基本使用方法。
本文将继续回到LangChain框架的用法上,详细分析在LangChain中,如何使用VectorStore组件将向量数据存储到向量数据库中。
文中所有示例代码:github.com/wzycoding/l…
一、VectorStore组件介绍
对非结构化数据的存储与检索,最常用的方法是先将文本进行嵌入,转换为向量后存储到向量数据库中;在查询时,同样将查询文本嵌入生成向量,再将该向量传递给向量数据库,由数据库完成后续的相似度计算与检索过程。
在 LangChain 中,这一过程由顶层接口 VectorStore 统一管理,不同类型的向量数据库只需实现该接口中的抽象方法即可完成集成。VectorStore 接口提供了多个常用方法,例如:
add_texts:将文本列表转换为向量,并存储到向量数据库。add_documents:将文档列表转换为向量,并存储到向量数据库。as_retriever:返回向量数据库初始化的检索器。similarity_search_with_relevance_scores:进行相似性检索,返回文档及其相关性得分(范围在[0, 1]之间)。delete:根据向量id删除向量数据from_texts:传入文本列表、元数据信息、文本嵌入模型,返回创建好的VectorStore。VectorStore接口,常用的实现类如下:
| 类名 | 描述 |
|---|---|
| InMemoryVectorStore | 基于内存实现的向量数据库 |
| ElasticsearchStore | Elasticsearch为基础实现的向量数据库 |
| TencentVectorDB | 腾讯向量数据库,当前类还在community包下,没有独立出来 |
| PineconeVectorStore | Pinecone向量数据库 |
| WeaviateVectorStore | Weaviate向量数据库 |
二、 WeaviateVectorStore数据存储
WeaviateVectorStore 是 VectorStore 接口的一个实现类,下面将以它为例介绍 VectorStore 的用法。在使用 WeaviateVectorStore 之前,需要先安装 langchain-weaviate 依赖:
pip install langchain-weaviate==0.0.2执行命令,生成依赖版本快照
pip freeze > requirements.txt接下来,先展示如何使用 WeaviateVectorStore 进行数据存储。示例程序如下:在构造 WeaviateVectorStore 对象时,需要传入 Weaviate Client 对象、text_key、文本嵌入对象以及 Weaviate 集合名称。其中,text_key 表示存储原文的 key 名,这里命名为 text_key。
Weaviate 数据库支持将文本片段的原文直接保存到 Weaviate 中,这样在检索时就可以直接获取原文,避免了通过元数据中的 segment_id 再去关系型数据库查询的额外操作。这种方式适用于文本数量较少的情况;当文本数量较大时,建议将原文保存到关系型数据库中,更便于管理和维护。
构建好 WeaviateVectorStore 后,将准备好的文本信息和元数据信息通过 add_texts() 方法添加到向量数据库中。WeaviateVectorStore 会使用传入的文本嵌入模型自动对文本进行嵌入,并在对象创建成功后返回对应的 UUID 列表。
import dotenvimport weaviatefrom langchain_openai import OpenAIEmbeddingsfrom langchain_weaviate import WeaviateVectorStore# 读取env配置dotenv.load_dotenv()# 1.创建Weaviate客户端client = weaviate.connect_to_local( host="localhost", port=8080, grpc_port=50051,)# 2.创建文本嵌入模型embeddings = OpenAIEmbeddings(model="text-embedding-3-small")# 3.创建Weaviate向量数据库vector_store = WeaviateVectorStore( client=client, text_key="text_key", embedding=embeddings, index_name="Database")# 4.准备好要保存的文本数据、元数据texts = [ "光明科技公司总部位于北京市朝阳区,是一家专注于人工智能与大数据分析的高新技术企业,现有员工500人。", "公司董事长张三,男,40岁,籍贯黑龙江漠河市,毕业于清北大学,曾在硅谷工作十年,现负责公司战略规划与重大项目决策。", "总经理李四,男,38岁,江苏南京人,拥有十五年软件工程经验,主导过多个国家重点科技项目。", "副总经理王五,男,35岁,四川成都人,负责公司运营管理与市场拓展。", "技术部拥有120名开发人员,主要从事机器学习模型训练、数据挖掘、云计算平台研发等工作。", "光明科技公司在2024年获得国家科技进步二等奖,并与多所高校建立产学研合作关系。", "公司设有技术部、市场部、运营部和人力资源部,其中技术部是公司的核心部门。", "张三不仅担任董事长,还热衷公益事业,曾多次捐助贫困地区教育项目。", "李四毕业于上海交通大学计算机系,擅长分布式系统与云架构设计。", "王五在加入光明科技公司前,曾任某知名互联网企业运营总监,具有丰富的企业管理经验。"]metadatas = [ {"segment_id": "1"}, {"segment_id": "2"}, {"segment_id": "3"}, {"segment_id": "4"}, {"segment_id": "5"}, {"segment_id": "6"}, {"segment_id": "7"}, {"segment_id": "8"}, {"segment_id": "9"}, {"segment_id": "10"},]# 5.存储数据到向量数据库uuids = vector_store.add_texts(texts, metadatas)# 6.打印返回的uuid列表print(f"存储到Weaviate向量数据库的对象的uuid列表:{uuids}")执行结果如下,返回了创建对象的uuid列表。
存储到Weaviate向量数据库的对象的uuid列表:['61adde43-8fac-4ed9-82ae-79b73b7eaf94', 'a9864354-80b5-4426-98c4-30e0da4e5cd7', 'f8b3f2e5-dda8-493d-9e73-00763dd5e274', '5dbf58ab-5db8-4e7a-94aa-d1d2dba0d9af', '9d12f56c-96f4-4867-8ee9-a5f05757dfc8', '63f94a88-160e-4b1e-b049-245af8f20962', 'df850306-45ae-4d70-ab48-01e00a652a7a', '61634caf-e65c-4b4c-a1b5-4d44d855d70a', '8b0e22f1-652f-4ef5-b5a1-3be03673d833', '0529d236-9253-4a22-a413-72798c5f4f27']三、WeaviateVectorStore数据检索
在上面的示例程序中,我们将文本信息和元数据信息都保存到了数据库中。接下来,使用 VectorStore的similarity_search_with_relevance_scores() 方法进行相似性检索。在调用该方法时,传入查询文本 query,并指定 k=3,即返回匹配分数最高的三条数据(k 的默认值为 4)。
import dotenvimport weaviatefrom langchain_openai import OpenAIEmbeddingsfrom langchain_weaviate import WeaviateVectorStore# 读取env配置dotenv.load_dotenv()# 1.创建Weaviate客户端client = weaviate.connect_to_local( host="localhost", port=8080, grpc_port=50051,)# 2.创建文本嵌入模型embeddings = OpenAIEmbeddings(model="text-embedding-3-small")# 3.创建Weaviate向量数据库vector_store = WeaviateVectorStore( client=client, text_key="text_key", embedding=embeddings, index_name="Database")# 4、进行数据检索search_result = vector_store.similarity_search_with_relevance_scores(query="光明公司的董事长是谁?", k=3)# 5、打印检索结果for document, score in search_result: print(f"文档内容:{document.page_content}") print(f"文档元数据信息:{document.metadata}") print(f"相关度得分:{score}") print("=================================")执行结果如下,返回了3个与查询文本最相关的文本信息。
文档内容:王五在加入光明科技公司前,曾任某知名互联网企业运营总监,具有丰富的企业管理经验。文档元数据信息:{'segment_id': '10', 'text': None}相关度得分:0.6681877695251427=================================文档内容:公司董事长张三,男,40岁,籍贯黑龙江漠河市,毕业于清北大学,曾在硅谷工作十年,现负责公司战略规划与重大项目决策。文档元数据信息:{'segment_id': '2', 'text': None}相关度得分:0.6405468061607247=================================文档内容:光明科技公司总部位于北京市朝阳区,是一家专注于人工智能与大数据分析的高新技术企业,现有员工500人。文档元数据信息:{'segment_id': '1', 'text': None}相关度得分:0.6342571121423872=================================四、总结
本文详细介绍了 LangChain 的 VectorStore 接口,VectorStore提供了add_texts、similarity_search_with_relevance_scores、delete 等常用方法,该接口有多种数据库(Weaviate、Pinecone、Elasticsearch 等)的实现类。
接下来,以WeaviateVectorStore介绍了如何进行向量数据的存储,在存储完成后,使用similarity_search_with_relevance_scores 进行带得分的相似性检索,分数越高表示越相关,检索结果同时返回文档内容与元数据,方便后续处理。
通过本文可以快速掌握 LangChain的VectorStore组件,以及LangChain如何集成 Weaviate 的基本流程,从数据存储、向量化,到检索查询,掌握完整的数据存储检索流程,在下一篇文章中,将会继续介绍LangChain中Retrievers检索器组件的用法,欢迎持续关注。
