AI 与向量

规模化工程实践

构建企业级向量架构。


向量数据的内容源可能非常庞大。随着业务增长,您应该将向量工作负载分散到多个辅助数据库(有时称为"pods")上运行,这样每个集合都可以独立扩展。

简单工作负载

对于小型工作负载,通常将数据存储在单一数据库中即可。

如果您使用 Vecs 创建了3个不同的集合,可以通过视图将这些集合暴露给您的网页或移动应用:

例如,对于名为docspostsimages的3个集合,我们可以像这样在public模式中暴露"docs"集合:

1
2
3
4
5
6
7
create view public.docs asselect id, embedding, metadata, # 将元数据以JSON格式暴露 (metadata->>'url')::text as url # 提取URL作为字符串from vector

然后您可以使用任何客户端库在应用程序中访问这些集合:

1
2
3
4
const { data, error } = await supabase .from('docs') .select('id, embedding, metadata') .eq('url', '/hello-world')

企业级工作负载

当您进入生产环境时,我们建议将您的集合(collection)拆分到不同的项目中。这样可以让您的向量存储独立于生产数据进行扩展。向量数据通常比业务数据增长得更快,且具有不同的资源需求。将它们运行在独立的数据库上可以消除单点故障。

您可以根据需要管理任意数量的次级数据库。在这种架构下,应用程序访问集合有两种方式:

  1. 直接使用Vecs查询集合
  2. 通过包装器(Wrapper)从主数据库访问集合

您可以同时使用这两种方式来满足您的用例。我们建议尽可能选择方案1,因为它提供了最佳的扩展性。

使用Vecs查询集合

Vecs提供了多种查询集合的方法,既可以使用余弦相似度函数,也可以使用元数据过滤

1
2
3
4
5
6
7
8
9
# 余弦相似度docs.query(query_vector=[0.4,0.5,0.6], limit=5)# 元数据过滤docs.query( query_vector=[0.4,0.5,0.6], limit=5, filters={"year": {"$eq": 2012}}, # 元数据过滤器)

使用包装器访问外部集合

Supabase支持外部数据包装器。包装器允许您将两个数据库连接起来,通过网络进行查询。

这需要两个步骤:从主数据库连接到远程数据库,并创建外部表(Foreign Table)。

连接远程数据库

在主数据库中,我们需要提供访问次级数据库的凭证:

1
2
3
4
5
6
7
8
9
create extension postgres_fdw;create server docs_serverforeign data wrapper postgres_fdwoptions (host 'db.xxx.supabase.co', port '5432', dbname 'postgres');create user mapping for docs_userserver docs_serveroptions (user 'postgres', password 'password');

创建外部表

现在我们可以创建一个外部表来访问次级项目中的数据。

1
2
3
4
5
6
7
8
create foreign table docs ( id text not null, embedding vector(384), metadata jsonb, url text)server docs_serveroptions (schema_name 'public', table_name 'docs');

这与我们上面的视图示例非常相似,您可以继续使用客户端库通过外部表访问集合:

1
2
3
4
const { data, error } = await supabase .from('docs') .select('id, embedding, metadata') .eq('url', '/hello-world')

企业架构

下图展示了一个示例架构,允许您通过我们的客户端库或使用Vecs访问集合。您可以根据需要添加任意数量的次级数据库(本示例仅展示一个):