向量数据库技术系列五-Weaviate介绍
一、前言
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())#连接创建成功,则打印True
finally:
# 关闭连接
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
- http
image: semitechnologies/weaviate:latest
ports:
- 8080:8080
- 50051:50051
restart: on-failure:0
environment:
TRANSFORMERS_INFERENCE_API: 'http://t2v-transformers:8080'
QUERY_DEFAULTS_LIMIT: 25
AUTHENTICATION_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-v1
environment:
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介绍