Vector Databases(向量数据库)

  • 向量数据库是一种特殊类型的数据库,在人工智能应用中发挥着重要作用。

  • 在向量数据库中,查询与传统的关系数据库不同。他们执行相似性搜索,而不是精确匹配。当给定向量作为查询时,向量数据库返回与查询向量“相似”的向量。向量相似度中提供了有关如何在高层计算此相似度的更多详细信息。

  • 向量数据库用于将您的数据与 AI 模型集成。使用它们的第一步是将数据加载到向量数据库中。然后,当用户查询要发送到人工智能模型时,首先检索一组相似的文档。然后,这些文档将作为用户问题的上下文,并与用户的查询一起发送到 AI 模型。该技术称为检索增强生成(RAG)

以下部分描述了用于使用多个向量数据库实现的 Spring AI 接口以及一些高级示例用法。

最后一部分旨在揭开向量数据库中相似性搜索的基本方法的神秘面纱。

API 概述

本节是 Spring AI 框架中 VectorStore 接口及其相关类的指南。

Spring AI 提供了一个抽象的 API,用于通过 VectorStore 接口与向量数据库交互。

这是 VectorStore 接口定义:

public interface VectorStore {

    void add(List<Document> documents);

    Optional<Boolean> delete(List<String> idList);

    List<Document> similaritySearch(String query);

    List<Document> similaritySearch(SearchRequest request);
}

以及相关的 SearchRequest 构建器:

public class SearchRequest {

    public final String query;
    private int topK = 4;
    private double similarityThreshold = SIMILARITY_THRESHOLD_ALL;
    private Filter.Expression filterExpression;

    public static SearchRequest query(String query) { return new SearchRequest(query); }

    private SearchRequest(String query) { this.query = query; }

    public SearchRequest withTopK(int topK) {...}
    public SearchRequest withSimilarityThreshold(double threshold) {...}
    public SearchRequest withSimilarityThresholdAll() {...}
    public SearchRequest withFilterExpression(Filter.Expression expression) {...}
    public SearchRequest withFilterExpression(String textExpression) {...}

    public String getQuery() {...}
    public int getTopK() {...}
    public double getSimilarityThreshold() {...}
    public Filter.Expression getFilterExpression() {...}
}

要将数据插入向量数据库,请将其封装在一个Document对象中。该类Document封装来自数据源(例如 PDF 或 Word 文档)的内容,并包括表示为字符串的文本。它还包含键值对形式的元数据,包括文件名等详细信息。

插入向量数据库后,文本内容会被 嵌入模型 转换为数值数组或List<Double>,称为向量嵌入。嵌入模型(例如:Word2VecGLoVEBERT,或 OpenAI text-embedding-ada-002)用于将单词、句子或段落转换为这些向量嵌入

向量数据库的作用是存储和促进这些嵌入的相似性搜索。它本身不会生成嵌入。应该使用EmbeddingClient来创建向量嵌入。

接口中的similaritySearch方法,允许基于给定的查询字符串检索出类似的文档。可以使用以下参数对这些方法进行微调:

  • k:一个整数,指定要返回的类似文档的最大数量。这通常被称为“顶部 K”搜索,或“K 最近邻居”(KNN)。

  • threshold:范围从 0 到 1 的双精度值,其中值越接近 1 表示相似度越高。例如,默认情况下,如果您设置阈值 0.75,则仅返回相似度高于该值的文档。

  • Filter.Expression:用于传递流畅的 DSL(域特定语言)表达式的类,其功能类似于 SQL 中的“where”子句,但它仅适用于Document.

  • filterExpression:基于 ANTLR4 的外部 DSL,接受过滤器表达式作为字符串。例如,对于国家/地区、年份和 等元数据键isActive,您可以使用如下表达式:country == ‘UK’ && year >= 2020 && isActive == true.

可以在 Filter.Expression<<metadata-filters>> 部分查找更多信息。

可用的实现

下面是 VectorStore 接口一些可用的实现。

  • Azure Vector Search - Azure 向量存储。
  • ChromaVectorStore - Chroma 向量存储。
  • MilvusVectorStore - Milvus 向量存储.
  • Neo4jVectorStore - Neo4j 向量存储。
  • PgVectorStore - PostgreSQL/PGVector 向量存储。
  • PineconeVectorStore - PineCone 向量存储.
  • QdrantVectorStore -Qdrant 向量存储.
  • RedisVectorStore - Redis 向量存储。
  • WeaviateVectorStore - Weaviate 向量存储.
  • SimpleVectorStore - 持久向量存储的简单实现,适用于教育目的。

未来版本可能会支持更多实现。

如果您有一个需要 Spring AI 支持的矢量数据库,请在 GitHub 上提出问题,或者更好的是提交带有实现的拉取请求。

有关每个 VectorStore 实现的信息可以在本章的小节中找到。

用法示例

要计算向量数据库的嵌入,您需要选择一个与所使用的高级人工智能模型匹配的嵌入模型。

例如,通过 OpenAI 的 ChatGPT,我们可以选择 OpenAiEmbeddingClienttext-embedding-ada-002 模型 。

Spring Boot 启动器 对 OpenAI 的自动配置使得 EmbeddingClient 在 Spring 应用程序上下文中可以实现依赖注入。

将数据加载到向量存储中的一般用法是在类似批处理的作业中执行的操作,首先将数据加载到 Spring AI 的 Document 类中,然后调用该 save 方法。

给定对源文件的“String”引用,该源文件表示一个JSON文件,其中包含我们要加载到向量数据库中的数据,我们使用Spring AI的“JsonReader”加载JSON中的特定字段,该字段将它们拆分为小块,然后将这些小块传给向量存储实现。

该 VectorStore 实现计算嵌入 并将 JSON 和嵌入存储在向量数据库中:

  @Autowired
  VectorStore vectorStore;

  void load(String sourceFile) {
            JsonReader jsonReader = new JsonReader(new FileSystemResource(sourceFile),
                    "price", "name", "shortDescription", "description", "tags");
            List<Document> documents = jsonReader.get();
            this.vectorStore.add(documents);
  }

随后,当用户问题被传递到人工智能模型中时,系统会进行相似性搜索来检索相似的文档,然后将这些文档“填充”到提示中作为用户问题的上下文。

   String question = <question from user>
   List<Document> similarDocuments = store.similaritySearch(question);

可以将其他选项传递到 similaritySearch 方法中以定义要检索的文档数量以及相似性搜索的阈值

Metadata Filters [[metadata-filters]]

本节介绍可针对查询结果使用的各种过滤器。

Filter String

你可以传入类似 SQL 的过滤表达式作为String 参数,重载 similaritySearch 方法。

参考以下示例:

  • "country == 'BG'"
  • "genre == 'drama' && year >= 2020"
  • "genre in ['comedy', 'documentary', 'drama']"

Filter.Expression

你可以基于 FilterExpressionBuilder 使用流式API 创建一个 Filter.Expression 实例,下面是简单的示例:

FilterExpressionBuilder b = new FilterExpressionBuilder();
Expression expression = b.eq("country", "BG").build();

您可以使用以下运算符构建复杂的表达式:

EQUALS: '=='
MINUS : '-'
PLUS: '+'
GT: '>'
GE: '>='
LT: '<'
LE: '<='
NE: '!='

您可以使用以下运算符组合表达式:

AND: 'AND' | 'and' | '&&';
OR: 'OR' | 'or' | '||';

参考以下示例:

Expression exp = b.and(b.eq("genre", "drama"), b.gte("year", 2020)).build();

您还可以使用以下运算符:

IN: 'IN' | 'in';
NIN: 'NIN' | 'nin';
NOT: 'NOT' | 'not';

参考以下示例:

Expression exp = b.and(b.eq("genre", "drama"), b.gte("year", 2020)).build();

Understanding Vectors

xref:api/vectordbs/understand-vectordbs.adoc[Understanding Vectors]

作者:Jeebiz  创建时间:2024-04-05 23:12
最后编辑:Jeebiz  更新时间:2024-07-06 19:00