# Weaviate 向量数据库实践:开源检索引擎与 LangChain 生产封装
Weaviate 是一个开源向量数据库,适合做语义搜索、RAG 知识库、多模态检索、推荐召回和带 metadata 过滤的检索服务。
它和 FAISS、Pinecone、TCVectorDB 的定位不太一样。FAISS 更像本地检索内核,Pinecone 和 TCVectorDB 更偏托管服务,Weaviate 则在“可自建、可上云、功能完整、生态开放”之间取得了平衡。团队既可以用 Weaviate Cloud 快速上线,也可以用 Docker、Kubernetes 在自己的环境里部署。
但 Weaviate 不是只跑一个容器就能生产可用。真正要设计的是:collection schema、向量化策略、gRPC 端口、metadata 过滤、多租户、批量写入、索引版本、备份恢复、LangChain 和原生 client 的边界。
# Weaviate 的核心层级
Weaviate v4 Python client 以 collection 为核心入口。可以把它理解成传统数据库里的表,但它同时绑定了属性字段、向量配置、倒排索引、向量索引和多租户配置。
| 概念 | 作用 | 生产理解 |
|---|---|---|
| Cluster | Weaviate 服务集群 | 部署、网络、认证、资源和高可用边界 |
| Collection | 数据集合 | 同一 schema、同一向量配置和索引策略的数据容器 |
| Object | 数据对象 | 一条业务记录,包含 properties、uuid、vector |
| Property | 属性字段 | 正文、来源、租户、状态、页码等 metadata |
| Vector index | 向量索引 | 决定相似度检索速度、召回和资源消耗 |
| Inverted index | 倒排索引 | 支撑关键词、过滤和混合检索 |
生产设计里,collection 是最关键的边界。不同 Embedding 维度、不同业务 schema、不同强隔离要求的数据,不应该随便混到一个 collection 里。
# 部署方式怎么选
Weaviate 常见部署方式有四种。
| 部署方式 | 适用场景 | 注意点 |
|---|---|---|
| Weaviate Cloud | 快速上线、少运维、海外云环境 | 关注地域、账单、数据合规和 API key 管理 |
| Docker | 本地开发、功能验证、小型内网服务 | 必须挂载 volume,否则数据随容器删除丢失 |
| Kubernetes | 生产自建、私有化、多副本 | 需要补监控、备份、滚动升级和容量规划 |
| Embedded | 本地实验和测试 | 平台支持有限,不适合作为通用生产方案 |
本地开发最小启动:
docker run -d --name weaviate-dev \
-p 8080:8080 \
-p 50051:50051 \
cr.weaviate.io/semitechnologies/weaviate:latest
2
3
4
注意两个端口:
8080是 HTTP/REST 访问端口。50051是 gRPC 端口,Weaviate Python v4 client 和 LangChain 当前集成会用到它。
如果线上用 Docker 或 Kubernetes,一定要配置持久化卷、认证、网络访问控制和备份。没有持久化卷的容器只适合本地试验。
# 安装与当前包路径
新项目建议使用 Weaviate Python v4 client 和独立 LangChain 集成包:
pip install -U weaviate-client langchain-weaviate langchain-openai
当前 LangChain 官方文档使用:
from langchain_weaviate import WeaviateVectorStore
不要把旧路径作为新项目主路径:
from langchain.vectorstores import Weaviate
旧路径属于早期写法。当前更清晰的方式是 langchain-weaviate 加 weaviate-client v4。
# 连接 Weaviate
连接本地服务:
import weaviate
client = weaviate.connect_to_local(
host="localhost",
port=8080,
grpc_port=50051,
)
2
3
4
5
6
7
8
连接 Weaviate Cloud:
import os
import weaviate
from weaviate.auth import AuthApiKey
client = weaviate.connect_to_weaviate_cloud(
cluster_url=os.environ["WEAVIATE_URL"],
auth_credentials=AuthApiKey(os.environ["WEAVIATE_API_KEY"]),
headers={
"X-OpenAI-Api-Key": os.environ["OPENAI_API_KEY"],
},
)
2
3
4
5
6
7
8
9
10
11
12
13
如果使用外部 Embedding,headers 里不一定需要传模型供应商密钥,因为向量化发生在业务侧。只有使用 Weaviate 内置 vectorizer 或 generative module 时,才需要把相应供应商密钥传给 Weaviate。
服务关闭时要释放连接:
client.close()
# 创建 Collection
Weaviate Python client v4.16.0 之后,向量配置 API 有过更新。新项目应使用 vector_config,自带向量模式使用 Configure.Vectors.self_provided()。
from weaviate.classes.config import Configure, DataType, Property, VectorDistances
if not client.collections.exists("HelpCenter"):
client.collections.create(
name="HelpCenter",
vector_config=Configure.Vectors.self_provided(
vector_index_config=Configure.VectorIndex.hnsw(
distance_metric=VectorDistances.COSINE,
)
),
properties=[
Property(name="text", data_type=DataType.TEXT),
Property(name="tenant_id", data_type=DataType.TEXT),
Property(name="knowledge_base_id", data_type=DataType.TEXT),
Property(name="document_id", data_type=DataType.TEXT),
Property(name="status", data_type=DataType.TEXT),
Property(name="page", data_type=DataType.INT),
Property(name="source", data_type=DataType.TEXT),
],
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
生产里不建议在 Web 服务启动时自动创建 collection。更稳的是把 schema 创建放到基础设施脚本或发布流程中,并把 collection schema 版本写入 manifest。
# 外部 Embedding 还是内置 Vectorizer
Weaviate 支持两类模式。
| 模式 | 做法 | 适合场景 |
|---|---|---|
| 外部 Embedding | 业务侧生成向量,写入 Weaviate | 模型版本可控、跨库迁移、统一缓存和评估 |
| 内置 Vectorizer | Weaviate 根据配置调用模型模块 | 快速接入、希望简化入库链路 |
生产 RAG 更常见的是外部 Embedding。这样可以把文档切分、Embedding 缓存、限流、重试、模型版本、向量维度和评估集放在自己的数据流水线里管理。
使用内置 vectorizer 时,要确认服务端模块、供应商密钥、模型维度、地域、限流和账单。不要只看能不能写入成功,还要看后续是否能迁移、回放和离线评估。
# 接入 LangChain
用 langchain-weaviate 连接已有 collection:
import weaviate
from langchain_openai import OpenAIEmbeddings
from langchain_weaviate import WeaviateVectorStore
client = weaviate.connect_to_local()
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vector_store = WeaviateVectorStore(
client=client,
index_name="HelpCenter",
text_key="text",
embedding=embeddings,
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
写入文本:
texts = [
"企业用户可以在控制台申请发票,审批通过后进入开票流程。",
"退款申请需要提交订单号、付款凭证和问题描述。",
"知识库索引更新后,需要通过评估集验证召回质量。",
]
metadatas = [
{
"tenant_id": "tenant-a",
"knowledge_base_id": "kb-help-center",
"document_id": "invoice-policy",
"status": "published",
"page": 1,
"source": "invoice.md",
},
{
"tenant_id": "tenant-a",
"knowledge_base_id": "kb-help-center",
"document_id": "refund-policy",
"status": "published",
"page": 2,
"source": "refund.md",
},
{
"tenant_id": "tenant-a",
"knowledge_base_id": "kb-rag",
"document_id": "rag-eval",
"status": "draft",
"page": 3,
"source": "rag.md",
},
]
ids = [
"invoice-policy:v1:chunk-0001",
"refund-policy:v1:chunk-0001",
"rag-eval:v1:chunk-0001",
]
vector_store.add_texts(
texts=texts,
metadatas=metadatas,
ids=ids,
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
生产里强烈建议显式传 ids。稳定 id 能让文档更新、删除、去重、重放和审计变得可控。
# 相似度搜索与分数
普通检索:
docs = vector_store.similarity_search(
"发票怎么申请",
k=5,
)
2
3
4
带分数:
results = vector_store.similarity_search_with_score(
"发票怎么申请",
k=5,
)
for doc, score in results:
print(score, doc.page_content, doc.metadata)
2
3
4
5
6
7
不要把分数当成全局绝对阈值。Weaviate 的结果分数会受到检索模式、距离策略、Embedding 模型、是否混合检索、查询语种和数据分布影响。生产里要用固定评估集校准阈值,而不是凭一次试问决定。
# metadata 过滤
Weaviate Python v4 的过滤使用 Filter 对象。
from weaviate.classes.query import Filter
filters = (
Filter.by_property("tenant_id").equal("tenant-a")
& Filter.by_property("knowledge_base_id").equal("kb-help-center")
& Filter.by_property("status").equal("published")
)
docs = vector_store.similarity_search(
"发票怎么申请",
k=5,
filters=filters,
)
2
3
4
5
6
7
8
9
10
11
12
13
14
数值范围:
filters = Filter.by_property("page").greater_or_equal(1) & Filter.by_property("page").less_or_equal(10)
docs = vector_store.similarity_search(
"售后流程",
k=5,
filters=filters,
)
2
3
4
5
6
7
多值条件:
filters = (
Filter.by_property("tenant_id").equal("tenant-a")
& Filter.by_property("knowledge_base_id").contains_any(["kb-help-center", "kb-product"])
& Filter.by_property("status").equal("published")
)
2
3
4
5
权限过滤必须由服务端生成。前端可以传“想查哪个知识库”,但服务端要基于登录态和授权表重新计算可访问范围,不能把用户传来的 filter 原样交给 Weaviate。
# 混合检索
Weaviate 的强项之一是混合检索。它可以把关键词检索和向量检索结合起来,适合产品名、术语、编号、错误码、合同条款这类既需要字面命中又需要语义泛化的场景。
LangChain 的 similarity_search 可以把额外参数传给底层检索,例如调整 alpha:
docs = vector_store.similarity_search(
"ERR_401 如何处理",
k=5,
alpha=0.5,
filters=filters,
)
2
3
4
5
6
alpha 越接近 1,越偏向向量语义;越接近 0,越偏向关键词。生产里不要拍脑袋固定一个值,建议按评估集分别测试纯向量、纯关键词、混合检索和 reranker 后的效果。
# 原生 Collection 操作
LangChain 封装适合 RAG 检索,但 Weaviate 原生 client 能力更完整。可以通过 client 获取 collection:
from weaviate.classes.query import MetadataQuery
collection = client.collections.get("HelpCenter")
response = collection.query.near_text(
query="invoice process",
limit=5,
return_metadata=MetadataQuery(distance=True),
)
for item in response.objects:
print(item.properties)
print(item.metadata.distance)
2
3
4
5
6
7
8
9
10
11
12
13
14
如果 collection 使用 self_provided 向量而没有配置内置 vectorizer,就不要调用 near_text,而应该使用向量检索:
query_vector = embeddings.embed_query("invoice process")
response = collection.query.near_vector(
near_vector=query_vector,
limit=5,
filters=filters,
return_metadata=MetadataQuery(distance=True),
)
2
3
4
5
6
7
8
这点很重要。很多错误来自“collection 没有 vectorizer,却调用了 near_text”。外部 Embedding 模式下,查询侧也要自己生成 query vector。
# 多租户设计
Weaviate 支持多租户,同一个 collection schema 下可以隔离多个 tenant。
LangChain 接入时可以传 tenant:
tenant_store = WeaviateVectorStore.from_documents(
documents,
embeddings,
client=client,
index_name="HelpCenter",
text_key="text",
tenant="tenant-a",
)
docs = tenant_store.similarity_search(
"发票怎么申请",
tenant="tenant-a",
)
2
3
4
5
6
7
8
9
10
11
12
13
多租户不是越早越复杂越好。可以按数据规模和安全边界选择:
| 方案 | 适用场景 |
|---|---|
| metadata 过滤 | 小规模租户、权限风险可控、查询需要跨知识库 |
| Weaviate tenant | SaaS 多用户隔离、同 schema 多租户 |
| 独立 collection | 大客户、高敏数据、独立生命周期 |
| 独立集群 | 强合规、独立运维、资源隔离要求高 |
# 删除与更新
LangChain VectorStore 可以覆盖常见写入和检索,但批量删除、按条件删除、更新属性、备份恢复,建议使用原生 collection。
按 id 删除:
collection = client.collections.get("HelpCenter")
collection.data.delete_by_id("invoice-policy:v1:chunk-0001")
2
按条件删除要非常谨慎:
collection.data.delete_many(
where=Filter.by_property("document_id").equal("invoice-policy")
)
2
3
生产里删除必须有审计:记录操作者、租户、知识库、删除条件、任务 id、影响数量和执行时间。重要知识库更新更推荐“新 collection 构建、评估、切流、旧 collection 下线”的版本化流程。
# 和 FAISS 的区别
| 维度 | FAISS | Weaviate |
|---|---|---|
| 形态 | 本地向量检索库 | 独立向量数据库服务 |
| 部署 | 单机文件或进程内 | Cloud、Docker、Kubernetes |
| metadata 过滤 | 主要靠封装层 | 原生过滤和倒排索引 |
| 混合检索 | 需要额外组合 BM25 | 原生支持关键词和向量结合 |
| 多租户 | 自己拆索引 | 支持 tenant 和 collection 设计 |
| 运维 | 自己维护文件和发布 | 需要服务运维或使用云托管 |
FAISS 适合轻量、本地、离线和小中规模。Weaviate 更像完整在线检索服务,适合多人、多租户、在线更新和混合检索。
# 和 Pinecone、TCVectorDB 的区别
| 维度 | Weaviate | Pinecone | TCVectorDB |
|---|---|---|---|
| 开源属性 | 开源,可自建 | 托管服务 | 腾讯云托管服务 |
| 部署选择 | Cloud、Docker、Kubernetes | 云端托管 | 腾讯云环境 |
| LangChain 包 | langchain-weaviate | langchain-pinecone | Community 集成 |
| 特色能力 | 混合检索、schema、模块生态 | 托管弹性、namespace | 国内云、腾讯云生态 |
| 运维责任 | 自建时自己负责 | 平台负责 | 平台负责 |
如果团队想要开源可控、私有化部署、混合检索和较完整的数据模型,Weaviate 很值得考虑。如果希望少运维,托管产品会更省心。
# 生产封装建议
建议把 Weaviate 封装成工厂和服务层,不要让业务代码到处散落连接、collection 名称和 filter 拼接。
from dataclasses import dataclass
import weaviate
from langchain_weaviate import WeaviateVectorStore
@dataclass(frozen=True)
class WeaviateSettings:
url: str
api_key: str | None
collection_name: str
text_key: str
embedding_model: str
dimension: int
distance_metric: str
def build_weaviate_store(settings: WeaviateSettings, embeddings):
client = weaviate.connect_to_local()
store = WeaviateVectorStore(
client=client,
index_name=settings.collection_name,
text_key=settings.text_key,
embedding=embeddings,
)
return client, store
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
同时保存 manifest:
{
"collection_name": "HelpCenter",
"text_key": "text",
"embedding_model": "text-embedding-3-small",
"dimension": 1536,
"distance_metric": "cosine",
"chunk_version": "chunk-v3",
"schema_version": "schema-v2"
}
2
3
4
5
6
7
8
9
manifest 不是形式主义。线上召回变差时,你需要快速知道是哪次 schema、chunk、Embedding 或索引参数变化引入了问题。
# 上线前检查清单
- Weaviate 服务是否开启并暴露 HTTP 和 gRPC 端口。
- Cloud 或自建集群是否配置认证、网络访问控制和备份。
- Collection schema 是否固定并版本化。
text_key是否和 collection 的正文属性一致。- 外部 Embedding 的维度是否和 collection 向量配置一致。
- 是否明确使用
near_vector还是near_text。 - metadata 字段是否能支撑租户、知识库、状态、来源、页码过滤。
- 多租户隔离使用 metadata、tenant、collection 还是独立集群。
- 写入 id 是否稳定可重放。
- 是否记录 query、filters、alpha、k、score、latency 和命中文档 id。
- 是否有评估集验证 Recall@K、MRR、答案忠实度和延迟。
# 问题
Weaviate 常见问题集中在版本、向量化和 schema。
第一,旧代码路径过时。新项目应使用 langchain-weaviate,不要继续沿用早期 langchain.vectorstores.Weaviate。
第二,v3 client 和 v4 client API 混用。v4 是 collection-based API,过滤、创建 collection、查询方式都和旧写法不同。
第三,没有配置 vectorizer 却调用 near_text。外部 Embedding 模式下应先生成 query vector,再走 near_vector 或通过 LangChain embedding 封装检索。
第四,Docker 本地启动没有持久化卷。容器删除后数据会丢,不适合生产。
第五,metadata 字段设计随意。过滤字段、权限字段、状态字段、版本字段不稳定,会让检索治理变得很痛苦。
# 拓展
Weaviate 值得继续深入几个方向。
第一,混合检索。调优 vector、keyword、alpha 和 reranker,解决专业术语和语义泛化之间的冲突。
第二,多租户。比较 metadata 过滤、tenant、collection、cluster 四种隔离方式的成本和安全边界。
第三,多向量。给标题、正文、摘要、图片等字段配置不同向量,适合复杂文档和多模态检索。
第四,备份与迁移。把 collection schema、数据对象、向量版本和评估结果一起纳入发布流程。
# 实际生产是否使用
会使用。
Weaviate 在生产里适合企业知识库、智能客服、语义搜索、推荐召回、多模态检索和需要混合检索的 RAG 系统。它的优势是开源、可自建、schema 能力完整、过滤和混合检索能力强。
但生产里不会只跑一个默认容器。自建 Weaviate 要补齐持久化、认证、备份、监控、容量规划、滚动升级和故障恢复。使用 Cloud 则要重点关注地域、账单、密钥、网络和数据合规。
# 现在是否抛弃
没有抛弃。
Weaviate 仍然是主流向量数据库之一,LangChain 当前也有独立的 langchain-weaviate 集成。真正应该抛弃的是旧导入路径、v3 client 写法、无持久化 Docker 玩法,以及不区分 near_text 和 near_vector 的示例式接入。
当前更值得注意的是 Weaviate Python client v4.16.0 之后 collection 向量配置 API 的变化。新代码应按当前官方文档使用 vector_config 和 Configure.Vectors.self_provided() 等新接口。
# 最新生产如何实现
当前更推荐这样落地:
第一,使用 Weaviate Python v4 client,collection schema 由发布流程创建和审计。
第二,使用 langchain-weaviate 的 WeaviateVectorStore 接入 RAG 检索链路。
第三,外部 Embedding 由业务侧统一生成、缓存、限流和评估。
第四,正文存入稳定的 text_key,metadata 明确包含租户、知识库、文档、状态、来源和版本字段。
第五,权限过滤由服务端根据认证态生成 Filter,不接受客户端直接传入过滤对象。
第六,复杂数据治理走原生 collection API,LangChain 只负责在线检索和 retriever 抽象。
最小生产查询结构:
from weaviate.classes.query import Filter
def build_acl_filter(auth_context, knowledge_base_id: str):
if knowledge_base_id not in auth_context.allowed_knowledge_base_ids:
raise PermissionError("knowledge base not allowed")
return (
Filter.by_property("tenant_id").equal(auth_context.tenant_id)
& Filter.by_property("knowledge_base_id").equal(knowledge_base_id)
& Filter.by_property("status").equal("published")
)
def search_knowledge(vector_store: WeaviateVectorStore, query: str, auth_context, knowledge_base_id: str):
return vector_store.similarity_search_with_score(
query,
k=5,
filters=build_acl_filter(auth_context, knowledge_base_id),
alpha=0.75,
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
真实上线时,还要把 alpha、k、过滤条件、耗时、命中文档、score 和最终答案质量写入 trace,配合固定评估集持续回归。
# 总结
Weaviate 的优势是开源、可自建、可上云、schema 能力完整、混合检索强、LangChain 集成清晰。它适合从本地实验走向线上 RAG 服务,尤其适合需要私有化部署和混合检索的团队。
但 Weaviate 不会自动解决知识库工程问题。生产质量仍然取决于 schema 设计、Embedding 版本、稳定 id、权限过滤、索引版本、备份恢复、评估集和可观测闭环。
参考: