一、前言
Weaviate 是由德国公司 SeMI Technologies 开发的开源向量搜索引擎数据库。它结合了向量搜索和图数据库技术,旨在为 AI 应用提供高效的数据存储和检索能力。具有以下的特点:
- 高性能向量搜索
Weaviate 支持高效的向量索引和近似最近邻(ANN)搜索,能够在数百万个对象中实现毫秒级的 10-NN 邻近搜索。
- 图数据模型
Weaviate 采用图数据结构来组织数据,支持复杂的查询和分析。
- 机器学习集成
Weaviate 提供了丰富的机器学习模块支持,能够与 OpenAI、Hugging Face 等流行服务和模型集成,实现数据的自动向量化。
- 模块化与可扩展性
Weaviate 的模块化设计允许开发者根据需求选择不同的功能模块,如文本嵌入、生成式 AI 等。
- 丰富的 API 支持
Weaviate 提供了基于 GraphQL 的强大查询语言,支持复杂的向量和结构化数据查询。
- 云原生与高可用性
Weaviate 支持云原生部署,具备容错性和可扩展性,适合企业级应用。
- 灵活部署
Weaviate 提供了多种部署选项,包括开源版本和全托管的云服务
二、基本操作
1、本地docker部署
Weaviate提供了相关的云服务(包括Weaviate,AWS,Google等),也提供了本地部署包括docker,K8S等,本案例介绍基于docker的部署
(1)镜像拉取
首先要本地下载docker并安装,安装完成后使用如下指令,下载最新版本的weaviate镜像。
docker pull semitechnologies/weaviate:latest
默认使用的是官网的docker镜像地址,如果访问受限,可以配置国内的镜像代理地址。可以设置多个
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn","https://docker.1ms.run","https://docker.m.daocloud.io","https://dockerhub.icu"]
下载完成后,可以通过docker images命令查看下载结果。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
semitechnologies/weaviate latest 5fb27d8e5d1f 2 weeks ago 163MB
(2)启动容器
weaviate的启动配置参数有很多,这里先用默认配置启动
docker run -p 8080:8080 -p 50051:50051 semitechnologies/weaviate:latest
其中8080位http的端口,50051为grpc的端口。启动完成后,可以使用docker ps指令查看启动结果
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6e50d684ae28 semitechnologies/weaviate:latest "/bin/weaviate --hos…" 9 seconds ago Up 7 seconds 0.0.0.0:8080->8080/tcp, 0.0.0.0:50051->50051/tcp quirky_babbage
也可以访问http://localhost:8080/v1/docs确认是否启动成功
2、创建连接并测试
首先要按照 weaviate-client的python包
pip install weaviate-client
创建与服务容器连接的本地client
import weaviate# 连接 Weaviate
client = weaviate.connect_to_local( host="127.0.0.1", port=8080,grpc_port=50051)try:print(client.is_ready())#连接创建成功,则打印Truefinally:# 关闭连接client.close()
3、创建集合
接下来我们创建一个名称my_collect的集合,为了简单起见,先不指定向量化模型(手动输入向量)。
...# 创建一个名为my_collect的集合collection_name = "my_collect"if collection_name not in client.collections.list_all():#判断是否存在,如果已存在就跳过client.collections.create(name=collection_name,vectorizer_config=Configure.Vectorizer.none(),#先不用使用内置向量化器,需要手动提供向量properties=[#包含两个属性,text和content,都是text类型Property(name="text", data_type=DataType.TEXT),Property(name="content", data_type=DataType.TEXT)])
...
其中,使用client.collections.create进行创建集合,
- name,集合名称。
- vectorizer_config,嵌入式向量的配置,Weaviate支持文本,图片以及多模态的嵌入模型。简单起见,这里先设置为none
- properties,记录的属性设置(可以看做关系型数据的列),示例中包含text和content两个属性。
4、插入,查询,删除数据
插入一条测试数据
..#插入一条测试数据 collection = client.collections.get(collection_name)vector_data = [0.1, 0.2, 0.3, 0.4, 0.5] # 示例向量properties = {"title": "Sample Article","content": "This is a sample article content."}# 插入数据时手动传入向量collection.data.insert(properties=properties, vector=vector_data)print("数据插入成功!")
...
根据名称获取集合,并手动指定该条记录的文本和向量数据,调用insert进行插入数据。
接下来,使用向量数据进行近似查询数据
# 查询向量query_vector = [0.1, 0.2, 0.3, 0.4, 0.5] # 示例查询向量results = collection.query.near_vector(near_vector=query_vector,limit=3 # 返回最相似的 3 条数据)print(results)
删除整个集合
client.collections.delete(collection_name)
以下是完整的示例代码
import weaviate
from weaviate.classes.config import Configure, Property, DataType# 连接 Weaviate
client = weaviate.connect_to_local( host="127.0.0.1", port=8080,grpc_port=50051)try:print(client.is_ready())# 创建一个名为my_collect的集合collection_name = "My_collect_1"if collection_name not in client.collections.list_all():#判断是否存在,如果已存在就跳过client.collections.create(name=collection_name,vectorizer_config=Configure.Vectorizer.none(),#先不用使用内置向量化器,需要手动提供向量properties=[#包含两个属性,text和content,都是text类型Property(name="text", data_type=DataType.TEXT),Property(name="content", data_type=DataType.TEXT)])#插入一条测试数据 collection = client.collections.get(collection_name)vector_data = [0.1, 0.2, 0.3, 0.4, 0.5] # 示例向量properties = {"title": "Sample Article","content": "This is a sample article content."}# 插入数据时手动传入向量collection.data.insert(properties=properties, vector=vector_data)print("数据插入成功!")# 查询向量query_vector = [0.1, 0.2, 0.3, 0.4, 0.5] # 示例查询向量results = collection.query.near_vector(near_vector=query_vector,limit=3 # 返回最相似的 3 条数据)print(results)#删除集合client.collections.delete(collection_name)finally:# 关闭连接client.close()
打印的数据如下:
#True
#数据插入成功!
#QueryReturn(objects=[Object(uuid=_WeaviateUUIDInt('4adabf4b-8798-4639-b654-ca8be4c6f52b'), metadata=MetadataReturn(creation_time=None, last_update_time=None, distance=None, certainty=None, score=None, explain_score=None, is_consistent=None, rerank_score=None), properties={'text': None, 'content': 'This is a sample article content.', 'title': 'Sample Article'}, references=None, vector={}, collection='My_collect_1')])
三、案例实践
按照惯例,接下来我们使用一个具体的案例,并通过指定内置的嵌入向量模型进行文档向量化。
1、启动容器
上面我们使用简单的启动指令。这里使用docke的yml配置文件(docker-compose.yml)启动。
---
services:weaviate:command:- --host- 0.0.0.0- --port- '8080'- --scheme- httpimage: semitechnologies/weaviate:latestports:- 8080:8080- 50051:50051restart: on-failure:0environment:TRANSFORMERS_INFERENCE_API: 'http://t2v-transformers:8080'QUERY_DEFAULTS_LIMIT: 25AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true'PERSISTENCE_DATA_PATH: '/var/lib/weaviate'DEFAULT_VECTORIZER_MODULE: 'text2vec-transformers'ENABLE_MODULES: 'text2vec-transformers'CLUSTER_HOSTNAME: 'node1't2v-transformers:image: cr.weaviate.io/semitechnologies/transformers-inference:sentence-transformers-multi-qa-MiniLM-L6-cos-v1environment:ENABLE_CUDA: '0'
volumes:weaviate_data:
启动的配置文件中,主要增加了内嵌向量器text2vec-transformers的环境配置。官网提供了文件生成的工具,可以通过选择相关的模型和参数后,自动生成。
Weaviate支持文本,图片以及多模态的嵌入模型。模型类型如下:
使用如下命令进行启动:
docker compose up -d
如果首次启动,需要下载transformers的模型镜像,耗时较长,需要保持网络的稳定。
2、创建集合
创建集合时,指定嵌入式向量和属性。
if collection_name not in client.collections.list_all():#判断是否存在,如果已存在就跳过client.collections.create(name=collection_name,vectorizer_config=[# 设置嵌入式模型Configure.NamedVectors.text2vec_transformers(name="content",source_properties=["content"], # 可选项,表示对content属性字段进行向量化vector_index_config=Configure.VectorIndex.hnsw() # 可选项,索引算法)],properties=[#包含两个属性,text和content,都是text类型Property(name="content", data_type=DataType.TEXT)])
表示使用text2vec_transformers向量模型对属性为content的值进行向量化处理。
3、插入和检索数据
接下来,插入测试的样本数据,并进行向量化。
#插入测试样本数据 collection = client.collections.get(collection_name)data_objects = [{ "content": "海内存知己,天涯若比邻"},{ "content": "大漠孤烟直,长河落日圆"},{ "content": "春眠不觉晓,处处闻啼鸟"},{ "content": "会当凌绝顶,一览众山小"},{ "content": "海上生明月,天涯共此时"},{ "content": "举头望明月,低头思故乡"},{ "content": "山重水复疑无路,柳暗花明又一村"},{ "content": "不识庐山真面目,只缘身在此山中"},{ "content": "采菊东篱下,悠然见南山"},{ "content": "谁言寸草心,报得三春晖"},{ "content": "忽如一夜春风来,千树万树梨花开"},{ "content": "落霞与孤鹜齐飞,秋水共长天一色"},{ "content": "青山遮不住,毕竟东流去"},{ "content": "春江潮水连海平,海上明月共潮生"},{ "content": "两岸猿声啼不住,轻舟已过万重山"},{ "content": "问渠那得清如许?为有源头活水来"},{ "content": "竹外桃花三两枝,春江水暖鸭先知"},{ "content": "身无彩凤双飞翼,心有灵犀一点通"},{ "content": "众里寻他千百度,蓦然回首,那人却在,灯火阑珊处"},{ "content": "莫愁前路无知己,天下谁人不识君"}]# 插入数据时手动传入向量for data in data_objects:collection.data.insert(properties=data)
插入成功后,进行相似检索,并返回top3的数据
# 查询向量query_text = "明月几时有,把酒问青天"results = collection.query.near_text(query=query_text,limit=3, # 返回最相似的 3 条数据return_metadata=MetadataQuery(distance=True))for o in results.objects:print(o)
搜索的结果如下:
#Object(uuid=_WeaviateUUIDInt('788b83cc-06eb-4167-9ce2-fc0b3b6c54b6'), metadata=MetadataReturn(creation_time=None, last_update_time=None, distance=0.369128942489624, certainty=None, score=None, explain_score=None, is_consistent=None, rerank_score=None), properties={'content': '海上生明月,天涯共此时'}, references=None, vector={}, collection='My_collect_2')
#Object(uuid=_WeaviateUUIDInt('8821cb49-efd4-444f-b459-150979b2910f'), metadata=MetadataReturn(creation_time=None, last_update_time=None, distance=0.4248510003089905, certainty=None, score=None, explain_score=None, is_consistent=None, rerank_score=None), properties={'content': '举头望明月,低头思故乡'}, references=None, vector={}, collection='My_collect_2')
#Object(uuid=_WeaviateUUIDInt('1f1321d9-c47b-4031-895d-c0588923e139'), metadata=MetadataReturn(creation_time=None, last_update_time=None, distance=0.5062708854675293, certainty=None, score=None, explain_score=None, is_consistent=None, rerank_score=None), properties={'content': '竹外桃花三两枝,春江水暖鸭先知'}, references=None, vector={}, collection='My_collect_2')
完整的代码如下:
import weaviate
from weaviate.classes.config import Configure, Property, DataType
from weaviate.classes.query import MetadataQuery# 连接 Weaviate
client = weaviate.connect_to_local( host="127.0.0.1", port=8080,grpc_port=50051)try:print(client.is_ready())# 创建一个名为my_collect的集合collection_name = "My_collect_2"if collection_name not in client.collections.list_all():#判断是否存在,如果已存在就跳过client.collections.create(name=collection_name,vectorizer_config=[# 设置嵌入式模型Configure.NamedVectors.text2vec_transformers(name="content",source_properties=["content"], # 可选项,表示对content属性字段进行向量化vector_index_config=Configure.VectorIndex.hnsw() # 可选项,索引算法)],properties=[#包含两个属性,text和content,都是text类型Property(name="content", data_type=DataType.TEXT)])#插入测试样本数据 collection = client.collections.get(collection_name)data_objects = [{ "content": "海内存知己,天涯若比邻"},{ "content": "大漠孤烟直,长河落日圆"},{ "content": "春眠不觉晓,处处闻啼鸟"},{ "content": "会当凌绝顶,一览众山小"},{ "content": "海上生明月,天涯共此时"},{ "content": "举头望明月,低头思故乡"},{ "content": "山重水复疑无路,柳暗花明又一村"},{ "content": "不识庐山真面目,只缘身在此山中"},{ "content": "采菊东篱下,悠然见南山"},{ "content": "谁言寸草心,报得三春晖"},{ "content": "忽如一夜春风来,千树万树梨花开"},{ "content": "落霞与孤鹜齐飞,秋水共长天一色"},{ "content": "青山遮不住,毕竟东流去"},{ "content": "春江潮水连海平,海上明月共潮生"},{ "content": "两岸猿声啼不住,轻舟已过万重山"},{ "content": "问渠那得清如许?为有源头活水来"},{ "content": "竹外桃花三两枝,春江水暖鸭先知"},{ "content": "身无彩凤双飞翼,心有灵犀一点通"},{ "content": "众里寻他千百度,蓦然回首,那人却在,灯火阑珊处"},{ "content": "莫愁前路无知己,天下谁人不识君"}]# 插入数据时手动传入向量for data in data_objects:collection.data.insert(properties=data)print("数据插入成功!")# 查询向量query_text = "明月几时有,把酒问青天"results = collection.query.near_text(query=query_text,limit=3, # 返回最相似的 3 条数据return_metadata=MetadataQuery(distance=True))for o in results.objects:print(o)client.collections.delete(collection_name)finally:# 关闭连接client.close()
四、总结
本文主要介绍了Weaviate的基本用法,并通过案例,实现了数据的向量化和近似检索。
附件
向量数据库技术系列一-基本原理
向量数据库技术系列二-Milvus介绍
向量数据库技术系列三-Chroma介绍
向量数据库技术系列四-FAISS介绍
向量数据库技术系列五-Weaviate介绍