做AI智能体应用时,最常见的困境是模型本身没有记忆,也不知道你的私有数据。把企业文档、聊天历史、用户画像塞进上下文窗口既贵又不现实,这时候就需要向量数据库来做长期记忆层和知识检索层。Weaviate是一款专为AI应用设计的开源向量数据库,支持向量检索、关键词检索和混合检索,还内置了向量化模块和生成式问答能力。它的云服务Weaviate Cloud Database(WCD)提供了免费沙盒实例,注册即可使用,省去了自建集群的运维成本,非常适合作为智能体的后端存储。

一、Weaviate核心概念与云服务准备
在动手写代码之前,需要先理解几个核心概念。Weaviate中最基本的数据单位是Collection(旧版本叫Class),可以类比为关系型数据库里的表。每个Collection可以配置自己的向量化器,比如text2vec-openai、text2vec-transformers,写入数据时Weaviate会自动调用向量化器把文本转成向量。每条数据称为Object,除了向量之外还可以携带任意JSON属性,检索时可以通过filter对这些属性做精确过滤。
云服务的准备工作很简单。访问Weaviate官网注册账号后,在控制台创建一个SandBox集群,免费且不需要绑卡。创建完成后会得到两个关键信息:一个是集群的URL,形如https://xxxx.weaviate.network;另一个是API Key。把这两个值保存好,后面的连接代码会用到。如果智能体部署在国内,建议检查一下网络连通性,必要时配置代理环境变量。
二、连接云服务并设计Collection
连接Weaviate推荐使用官方的Python客户端v4版本,它采用了全新的连接方式,通过weaviate.connect_to_weaviate_cloud函数建立连接,并支持gRPC通道,读写性能比旧版HTTP接口有明显提升。
import weaviate
from weaviate.classes.init import AdditionalConfig, Timeout
from weaviate.auth import AuthApiKey
import os
# 建立与Weaviate云服务的连接
client = weaviate.connect_to_weaviate_cloud(
cluster_url=os.environ["WCD_URL"], # 集群地址
auth_credentials=AuthApiKey(os.environ["WCD_API_KEY"]),
additional_config=AdditionalConfig(
timeout=Timeout(init=30, query=60, insert=120) # 各阶段超时时间
)
)
try:
# 检查连接是否就绪
print("连接状态:", client.is_ready())
finally:
client.close() # v4客户端需要显式关闭连接
接下来创建Collection。以一个知识库问答智能体为例,每条数据包含文档标题、正文内容和来源信息。这里使用OpenAI的向量化器,需要在header中传入OpenAI的API Key。如果不想依赖外部模型,也可以选择Weaviate内置的本地向量化模块,代价是功能上略有差异。
from weaviate.classes.config import Configure, Property, DataType
if not client.collections.exists("KnowledgeDoc"):
client.collections.create(
name="KnowledgeDoc",
vectorizer_config=Configure.Vectorizer.text2vec_openai(),
properties=[
Property(name="title", data_type=DataType.TEXT),
Property(name="content", data_type=DataType.TEXT),
Property(name="source", data_type=DataType.TEXT, skip_vectorization=True),
]
)
print("Collection创建成功")
注意skip_vectorization这个参数,对于source这类只用做过滤的字段,跳过向量化可以节省token开销。这是一个容易被忽略的细节,当文档量上到十万级别时,向量化的费用差异会非常明显。
三、写入数据与相似度检索
数据写入建议使用批量接口collection.data.insert_many,它会自动分批处理,比逐条插入快得多。写入时只需要提供属性值,向量由服务端自动生成,这大大简化了客户端逻辑。
docs = client.collections.get("KnowledgeDoc")
data_rows = [
{"title": "退款政策", "content": "自购买之日起7天内支持无理由退款,需保留完整包装。", "source": "faq.md"},
{"title": "配送说明", "content": "默认使用顺丰快递,偏远地区预计3到5个工作日送达。", "source": "faq.md"},
]
# 批量写入,服务端自动向量化
result = docs.data.insert_many(data_rows)
print("写入完成", len(result.all_responses))
检索部分是智能体的核心能力。v4客户端采用链式调用风格,near_text做语义检索,limit控制返回条数,with_metadata可以拿到相似度分数。分数越高表示语义越接近,通常低于0.7的结果质量就开始下降,可以在业务层做阈值过滤。
from weaviate.classes.query import MetadataQuery
results = docs.query.near_text(
query="买了东西想退怎么操作",
limit=3,
return_metadata=MetadataQuery(distance=True)
)
for item in results.objects:
print(item.properties["title"], "距离:", item.metadata.distance)
除了纯语义检索,Weaviate还支持混合检索(hybrid search),它同时计算向量的语义相关性和BM25关键词得分,再通过alpha参数控制两者权重。当用户查询里包含专有名词、型号编号这类语义模型难以理解的内容时,混合检索的效果明显好于单一方式。
四、把检索能力封装成智能体工具
有了检索接口,下一步是让大模型智能体能够自主决定何时调用它。主流做法是借助OpenAI的Function Calling机制,把检索函数注册为工具,模型根据用户问题判断是否需要查库。这样智能体就具备了RAG能力:先检索私有知识,再基于检索结果组织回答,有效减少幻觉。
import json
from openai import OpenAI
oa = OpenAI()
def search_knowledge(query: str, top_k: int = 3) -> str:
"""检索知识库,返回最相关的文档内容"""
res = docs.query.near_text(query=query, limit=top_k)
return json.dumps(
[o.properties for o in res.objects], ensure_ascii=False
)
tools = [{
"type": "function",
"function": {
"name": "search_knowledge",
"description": "当用户咨询产品政策、使用说明等问题时调用,检索内部知识库",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "检索关键词或问题"},
},
"required": ["query"]
}
}
}]
messages = [{"role": "user", "content": "你们家退款有什么要求?"}]
resp = oa.chat.completions.create(
model="gpt-4o", messages=messages, tools=tools
)
# 判断模型是否要求调用工具
tool_calls = resp.choices[0].message.tool_calls
if tool_calls:
call = tool_calls[0]
args = json.loads(call.function.arguments)
result = search_knowledge(**args) # 执行检索
messages.append(resp.choices[0].message)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": result,
})
final = oa.chat.completions.create(model="gpt-4o", messages=messages)
print(final.choices[0].message.content)
工具的description字段写得很关键,它直接决定了模型调用工具的准确率。描述越具体、越能区分使用场景,误调用就越少。比如写成“当且仅当用户询问公司内部政策、产品文档内容时调用,闲聊或常识性问题不要调用”,效果会好于一句模糊的“知识库检索”。
五、常见问题与优化建议
集成过程中有几个高频踩坑点值得注意。第一,连接泄漏:v4客户端底层维护了gRPC长连接,如果代码里反复创建客户端且不调用client.close(),连接数会耗尽导致请求超时,建议全局复用一个客户端实例。第二,写入限流:免费沙盒实例对请求频率有限制,批量写入时把batch_size控制在200以内比较稳妥,遇到429错误应实现指数退避重试。第三,中文分词效果:默认的BM25配置对中文支持一般,可以在创建Collection时通过Configure.VectorIndex和tokenization选项做针对性调整,或者直接依赖语义检索规避分词问题。
性能方面,如果检索延迟成为瓶颈,可以从三个方向优化:减少向量维度、使用HNSW索引参数调优(降低ef值换取速度)、以及对热点查询结果做应用层缓存。另外Weaviate支持多租户机制,若智能体服务多个企业客户,开启multi_tenancy_config可以让每个客户的数据逻辑隔离,既满足合规要求又不需要为每个客户建单独的Collection。
整体来看,Weaviate云服务加智能体的组合把最难的基础设施部分托管化了,开发者可以把精力集中在检索质量调优和工具设计上。建议先用小规模数据跑通链路,观察检索的召回质量,再逐步扩量,同时为每次检索记录日志,方便后续分析哪些查询没有命中预期结果,持续迭代知识库内容。