跳转到内容

Agno 向量数据库统一抽象层

Agno 向量数据库统一抽象层

学习目标

本章将分析 Agno 的向量数据库架构:

  • VectorDb 统一抽象接口
  • 15+ 向量数据库后端概览
  • 距离度量的统一(cosine/Euclidean/dot)
  • 嵌入器和重排器的可插拔设计

项目实践

VectorDb 统一抽象

Agno 的向量数据库层围绕统一接口构建:

# 伪代码:VectorDb 抽象
class VectorDb(ABC):
@abstractmethod
def create(self) -> None: ...
@abstractmethod
def insert(self, documents: List[Document]) -> None: ...
@abstractmethod
def search(
self,
query: str,
limit: int = 10,
metric: str = "cosine", # cosine / euclidean / dot
) -> List[Document]: ...
@abstractmethod
def delete(self, ids: List[str]) -> None: ...
@abstractmethod
def drop(self) -> None: ...

15+ 向量数据库后端

后端目录特点
pgvectorvectordb/pgvector/PostgreSQL 扩展,最常用
Qdrantvectordb/qdrant/高性能,REST + gRPC
Pineconevectordb/pineconedb/托管服务
Milvusvectordb/milvus/大规模分布式
Chromavectordb/chroma/轻量,适合开发
Weaviatevectordb/weaviate/语义搜索引擎
LanceDBvectordb/lancedb/嵌入式,基于 Lance 格式
Redisvectordb/redis/缓存 + 向量
MongoDBvectordb/mongodb/文档数据库向量搜索
Couchbasevectordb/couchbase/分布式 NoSQL
Cassandravectordb/cassandra/分布式宽列存储
ClickHousevectordb/clickhouse/OLAP + 向量
SingleStorevectordb/singlestore/分布式 SQL
SurrealDBvectordb/surrealdb/多模型数据库
Upstashvectordb/upstashdb/Serverless Redis + 向量

距离度量统一

Agno 支持三种距离度量,所有后端统一使用字符串标识:

度量字符串适用场景
余弦相似度cosine文本嵌入(归一化后余弦 = 点积)
欧氏距离euclidean空间向量
点积dot已归一化向量(等效于余弦)

嵌入器可插拔设计

knowledge/embedder/ 提供嵌入器抽象:

# 伪代码:Embedder 抽象
class Embedder(ABC):
@abstractmethod
def get_embedding(self, text: str) -> List[float]: ...
@abstractmethod
async def aget_embedding(self, text: str) -> List[float]: ...
@property
@abstractmethod
def dimensions(self) -> int: ...

内置嵌入器:

  • FastEmbed:本地嵌入,无需 API Key
  • OpenAI:text-embedding-3-small/large
  • Cohere:embed-v3/v4

重排器可插拔设计

knowledge/reranker/ 提供重排器抽象:

# 伪代码:Reranker 抽象
class Reranker(ABC):
@abstractmethod
def rerank(
self,
query: str,
documents: List[Document],
top_k: int = 5,
) -> List[Document]: ...

重排器在向量搜索后对结果重新排序,提高相关性。

问题与规避

1. 维度不匹配

不同嵌入器产生不同维度的向量(OpenAI 3072 维,FastEmbed 384 维)。

规避:VectorDb 创建时指定维度,嵌入器与向量数据库的维度必须一致。Agno 在初始化时检查维度匹配。

2. 后端功能差异

某些后端支持元数据过滤(pgvector),某些不支持(Chroma)。

规避:在抽象接口中只定义通用操作。后端特定的功能通过子类方法暴露。

3. 嵌入器的 API 成本

OpenAI 嵌入每次调用都有成本。

规避

  • 使用 FastEmbed 本地嵌入降低成本
  • 缓存嵌入结果(相同文本的嵌入不变)
  • 批量嵌入(一次调用嵌入多段文本)

设计取舍

为什么支持这么多向量数据库后端?

优势:用户可以选择已有的基础设施 代价:维护成本高 替代方案:只支持 pgvector + Qdrant——覆盖 80% 场景

为什么距离度量使用字符串而非枚举?

优势:灵活——新度量不需要修改枚举 代价:拼写错误不易发现 替代方案:枚举——类型安全但扩展性差

参考来源