此版本仍在开发中,尚未被视为稳定版。为了获取最新的快照版本,请使用Spring AI 1.1.3spring-doc.cadn.net.cn

Apache Cassandra Vector Store

本节将引导您完成配置CassandraVectorStore以存储文档嵌入并执行相似性搜索的过程。spring-doc.cadn.net.cn

什么是阿帕奇·卡斯丹纳?What is Apache Cassandra?

Apache Cassandra® 是一款真正开放源代码的分布式数据库,以其线性可扩展性、 proven fault-tolerance 和低延迟著称,是实现关键事务数据的完美平台。spring-doc.cadn.net.cn

其向量相似性搜索(VSS)基于JVector库,能够确保最佳级别的性能和相关性。spring-doc.cadn.net.cn

在Apache Cassandra中进行向量搜索实现起来非常简单:spring-doc.cadn.net.cn

SELECT content FROM table ORDER BY content_vector ANN OF query_embedding;

更多文档在此处阅读 这里.spring-doc.cadn.net.cn

本Spring AI向量存储旨在支持全新的RAG应用,并且能够嵌入现有数据和表。spring-doc.cadn.net.cn

该存储库还可以在现有数据库中用于非RAG场景,例如语义搜索、地理位置搜索等。spring-doc.cadn.net.cn

The store will automatically create, or enhance, the schema as needed according to its configuration. If you don’t want the schema modifications, configure the store with initializeSchema.spring-doc.cadn.net.cn

当使用 spring-boot-autoconfigure 0,默认会设置为 1,按照 Spring Boot 标准。并且,您必须启用数据库创建或修改功能,通过在 3 文件中设置 2。spring-doc.cadn.net.cn

什么是JVector?

JVector 是一个基于Java的嵌入式向量搜索引擎。spring-doc.cadn.net.cn

它之所以脱颖而出,是因为它是高效率且可扩展的相似性搜索框架(Java版本)。spring-doc.cadn.net.cn

  • 算法快速版。JVector采用了最先进的图算法,这些算法受到DiskANN及相关研究的启发,并且在高召回率和低延迟方面表现优异。spring-doc.cadn.net.cn

  • 实现非常快速。JVector使用PANAMA SIMD API来加速索引构建和查询。spring-doc.cadn.net.cn

  • 内存高效。JVector通过乘积量化方法压缩向量,以便在搜索过程中保持内存中的状态。spring-doc.cadn.net.cn

  • 磁盘意识的。JVector的磁盘布局设计为尽量减少查询时所需的I/O操作。spring-doc.cadn.net.cn

  • 多线程池规模按线性方式增长,当线程数达到至少32个时,线程数加倍,构建时间减半。spring-doc.cadn.net.cn

  • 增量式。在构建索引的同时实时查询。无需在添加向量和搜索结果之间有任何延迟。spring-doc.cadn.net.cn

  • 易嵌入。API是为易嵌入而设计的,由使用它在生产中的人开发的。spring-doc.cadn.net.cn

前提条件

  1. A EmbeddingModel 实例来计算文档嵌入。通常,这会被配置为SpringBean。有几个选项可用:spring-doc.cadn.net.cn

  2. 一个Apache Cassandra实例,版本号5.0-内测版spring-doc.cadn.net.cn

    1. DIY快速上手指南spring-doc.cadn.net.cn

    2. 对于一个托管的提供方案,阿斯塔数据库提供了一个健康的免费版本。spring-doc.cadn.net.cn

依赖项

There has been a significant change in the Spring AI auto-configuration, starter modules' artifact names. Please refer to the 升级说明以获取更多信息。spring-doc.cadn.net.cn

对于依赖管理,我们推荐使用Spring AI BOM,如《依赖管理》部分所述。

将这些依赖项添加到您的项目中:spring-doc.cadn.net.cn

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-cassandra-store</artifactId>
</dependency>
  • 或者,对于一个使用默认ONNX嵌入模型的检索增强生成应用(RAG)来说,您需要的所有内容是:spring-doc.cadn.net.cn

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-vector-store-cassandra</artifactId>
</dependency>

配置属性

你可以使用以下属性在Spring Boot配置中自定义Apache Cassandra向量存储。spring-doc.cadn.net.cn

属性 默认值

spring.ai.vectorstore.cassandra.keyspacespring-doc.cadn.net.cn

Spring Frameworkspring-doc.cadn.net.cn

spring.ai.vectorstore.cassandra.tablespring-doc.cadn.net.cn

ai_vector_storespring-doc.cadn.net.cn

spring.ai.vectorstore.cassandra.initialize-schemaspring-doc.cadn.net.cn

falsespring-doc.cadn.net.cn

spring.ai.vectorstore.cassandra.index-namespring-doc.cadn.net.cn

spring.ai.vectorstore.cassandra.content-column-namespring-doc.cadn.net.cn

内容spring-doc.cadn.net.cn

spring.ai.vectorstore.cassandra.embedding-column-namespring-doc.cadn.net.cn

嵌入spring-doc.cadn.net.cn

spring.ai.vectorstore.cassandra.fixed-thread-pool-executor-sizespring-doc.cadn.net.cn

16spring-doc.cadn.net.cn

用法

基本用法

创建一个Cassandra向量存储实例作为SpringBean:spring-doc.cadn.net.cn

@Bean
public VectorStore vectorStore(CqlSession session, EmbeddingModel embeddingModel) {
    return CassandraVectorStore.builder(embeddingModel)
        .session(session)
        .keyspace("my_keyspace")
        .table("my_vectors")
        .build();
}

当你有了向量存储实例时,你可以添加文档并执行搜索:spring-doc.cadn.net.cn

// Add documents
vectorStore.add(List.of(
    new Document("1", "content1", Map.of("key1", "value1")),
    new Document("2", "content2", Map.of("key2", "value2"))
));

// Search with filters
List<Document> results = vectorStore.similaritySearch(
    SearchRequest.query("search text")
        .withTopK(5)
        .withSimilarityThreshold(0.7f)
        .withFilterExpression("metadata.key1 == 'value1'")
);

高级配置

对于更复杂的场景,您可以在您的SpringBean中配置额外的设置:spring-doc.cadn.net.cn

@Bean
public VectorStore vectorStore(CqlSession session, EmbeddingModel embeddingModel) {
    return CassandraVectorStore.builder(embeddingModel)
        .session(session)
        .keyspace("my_keyspace")
        .table("my_vectors")
        // Configure primary keys
        .partitionKeys(List.of(
            new SchemaColumn("id", DataTypes.TEXT),
            new SchemaColumn("category", DataTypes.TEXT)
        ))
        .clusteringKeys(List.of(
            new SchemaColumn("timestamp", DataTypes.TIMESTAMP)
        ))
        // Add metadata columns with optional indexing
        .addMetadataColumns(
            new SchemaColumn("category", DataTypes.TEXT, SchemaColumnTags.INDEXED),
            new SchemaColumn("score", DataTypes.DOUBLE)
        )
        // Customize column names
        .contentColumnName("text")
        .embeddingColumnName("vector")
        // Performance tuning
        .fixedThreadPoolExecutorSize(32)
        // Schema management
        .initializeSchema(true)
        // Custom batching strategy
        .batchingStrategy(new TokenCountBatchingStrategy())
        .build();
}

连接配置

配置Cassandra连接有两种方式:spring-doc.cadn.net.cn

@Bean
public VectorStore vectorStore(CqlSession session, EmbeddingModel embeddingModel) {
    return CassandraVectorStore.builder(embeddingModel)
        .session(session)
        .keyspace("my_keyspace")
        .table("my_vectors")
        .build();
}
@Bean
public VectorStore vectorStore(EmbeddingModel embeddingModel) {
    return CassandraVectorStore.builder(embeddingModel)
        .contactPoint(new InetSocketAddress("localhost", 9042))
        .localDatacenter("datacenter1")
        .keyspace("my_keyspace")
        .build();
}

元数据过滤

你可以利用CassandraVectorStore的通用、可移植的元数据过滤器。要使元数据列可搜索,它们必须是主键或SAI索引。要使非主键列索引,配置元数据列属性为SchemaColumnTags.INDEXEDspring-doc.cadn.net.cn

例如,你可以使用文本表达式语言:spring-doc.cadn.net.cn

vectorStore.similaritySearch(
    SearchRequest.builder().query("The World")
        .topK(5)
        .filterExpression("country in ['UK', 'NL'] && year >= 2020").build());

或使用表达式DSL以编程方式:spring-doc.cadn.net.cn

Filter.Expression f = new FilterExpressionBuilder()
    .and(
        f.in("country", "UK", "NL"),
        f.gte("year", 2020)
    ).build();

vectorStore.similaritySearch(
    SearchRequest.builder().query("The World")
        .topK(5)
        .filterExpression(f).build());

可以自动转换为 CQL 查询spring-doc.cadn.net.cn

高级示例:在维基百科数据集上构建向量存储

The following example demonstrates how to use the store on an existing schema. Here we use the schema from the github.com/datastax-labs/colbert-wikipedia-data project which comes with the full wikipedia dataset ready vectorized for you.spring-doc.cadn.net.cn

首先,在Cassandra数据库中创建表结构:spring-doc.cadn.net.cn

wget https://s.apache.org/colbert-wikipedia-schema-cql -O colbert-wikipedia-schema.cql
cqlsh -f colbert-wikipedia-schema.cql

然后使用构建器模式配置存储:spring-doc.cadn.net.cn

@Bean
public VectorStore vectorStore(CqlSession session, EmbeddingModel embeddingModel) {
    List<SchemaColumn> partitionColumns = List.of(
        new SchemaColumn("wiki", DataTypes.TEXT),
        new SchemaColumn("language", DataTypes.TEXT),
        new SchemaColumn("title", DataTypes.TEXT)
    );

    List<SchemaColumn> clusteringColumns = List.of(
        new SchemaColumn("chunk_no", DataTypes.INT),
        new SchemaColumn("bert_embedding_no", DataTypes.INT)
    );

    List<SchemaColumn> extraColumns = List.of(
        new SchemaColumn("revision", DataTypes.INT),
        new SchemaColumn("id", DataTypes.INT)
    );

    return CassandraVectorStore.builder()
        .session(session)
        .embeddingModel(embeddingModel)
        .keyspace("wikidata")
        .table("articles")
        .partitionKeys(partitionColumns)
        .clusteringKeys(clusteringColumns)
        .contentColumnName("body")
        .embeddingColumnName("all_minilm_l6_v2_embedding")
        .indexName("all_minilm_l6_v2_ann")
        .initializeSchema(false)
        .addMetadataColumns(extraColumns)
        .primaryKeyTranslator((List<Object> primaryKeys) -> {
            if (primaryKeys.isEmpty()) {
                return "test§¶0";
            }
            return String.format("%s§¶%s", primaryKeys.get(2), primaryKeys.get(3));
        })
        .documentIdTranslator((id) -> {
            String[] parts = id.split("§¶");
            String title = parts[0];
            int chunk_no = parts.length > 1 ? Integer.parseInt(parts[1]) : 0;
            return List.of("simplewiki", "en", title, chunk_no, 0);
        })
        .build();
}

@Bean
public EmbeddingModel embeddingModel() {
    // default is ONNX all-MiniLM-L6-v2 which is what we want
    return new TransformersEmbeddingModel();
}

载入完整的维基百科数据集

加载整个维基百科数据集:spring-doc.cadn.net.cn

  1. Download from s.apache.org/simplewiki-sstable-tar (这会花一些时间,文件大小为几十GB)spring-doc.cadn.net.cn

  2. 加载数据:spring-doc.cadn.net.cn

tar -xf simplewiki-sstable.tar -C ${CASSANDRA_DATA}/data/wikidata/articles-*/
nodetool import wikidata articles ${CASSANDRA_DATA}/data/wikidata/articles-*/

访问原生客户端

Cassandra向量存储实现通过提供的内建的Cassandra客户端(0)实现了(1)方法。spring-doc.cadn.net.cn

CassandraVectorStore vectorStore = context.getBean(CassandraVectorStore.class);
Optional<CqlSession> nativeClient = vectorStore.getNativeClient();

if (nativeClient.isPresent()) {
    CqlSession session = nativeClient.get();
    // Use the native client for Cassandra-specific operations
}

native client提供访问 Cassandra 特定功能和操作的方式,这些功能和操作可能不会通过 VectorStore 接口暴露出来。spring-doc.cadn.net.cn