Apache Cassandra 向量儲存
本節將引導您設定 CassandraVectorStore 來儲存文件嵌入並執行相似性搜尋。
什麼是 Apache Cassandra?
Apache Cassandra® 是一個真正的開源分散式資料庫,以線性可擴充套件性、久經考驗的容錯性和低延遲而聞名,使其成為任務關鍵型事務資料的完美平臺。
其向量相似性搜尋 (VSS) 基於 JVector 庫,可確保一流的效能和相關性。
在 Apache Cassandra 中執行向量搜尋就像這樣簡單
SELECT content FROM table ORDER BY content_vector ANN OF query_embedding;
有關此內容的更多文件可以在此處閱讀。
此 Spring AI 向量儲存旨在同時適用於全新的 RAG 應用程式,並能夠改造現有資料和表。
該儲存還可以用於現有資料庫中的非 RAG 用例,例如語義搜尋、地理鄰近搜尋等。
該儲存將根據其配置自動建立或增強模式。如果您不希望修改模式,請使用 initializeSchema 配置儲存。
使用 spring-boot-autoconfigure 時,initializeSchema 預設為 false(根據 Spring Boot 標準),您必須透過在 application.properties 檔案中設定 …initialize-schema=true 來選擇模式建立/修改。
什麼是 JVector?
JVector 是一個純 Java 嵌入式向量搜尋引擎。
它在其他 HNSW 向量相似性搜尋實現中脫穎而出,因為它是
-
演算法快速。JVector 使用受 DiskANN 和相關研究啟發的最先進的圖演算法,提供高召回率和低延遲。
-
實現快速。JVector 使用 Panama SIMD API 來加速索引構建和查詢。
-
記憶體高效。JVector 使用乘積量化壓縮向量,使其在搜尋期間可以保留在記憶體中。
-
磁碟感知。JVector 的磁碟佈局旨在在查詢時執行最少必要的 I/O 操作。
-
併發。索引構建線性擴充套件到至少 32 個執行緒。執行緒數加倍,構建時間減半。
-
增量。在構建索引時查詢它。新增向量和在搜尋結果中找到它之間沒有延遲。
-
易於嵌入。API 專為易於嵌入而設計,由在生產環境中使用它的人員開發。
依賴關係
|
Spring AI 自動配置、啟動模組的工件名稱發生了重大變化。請參閱 升級說明 以獲取更多資訊。 |
| 對於依賴管理,我們建議使用 Spring AI BOM,如依賴管理部分所述。 |
將這些依賴項新增到您的專案中
-
僅用於 Cassandra 向量儲存
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-cassandra-store</artifactId>
</dependency>
-
或者,對於 RAG 應用程式所需的一切(使用預設的 ONNX 嵌入模型)
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-cassandra</artifactId>
</dependency>
配置屬性
您可以在 Spring Boot 配置中使用以下屬性來自定義 Apache Cassandra 向量儲存。
| 財產 | 預設值 |
|---|---|
|
springframework |
|
ai_vector_store |
|
假 |
|
|
|
content |
|
embedding |
|
16 |
用法
基本用法
建立 CassandraVectorStore 例項作為 Spring Bean
@Bean
public VectorStore vectorStore(CqlSession session, EmbeddingModel embeddingModel) {
return CassandraVectorStore.builder(embeddingModel)
.session(session)
.keyspace("my_keyspace")
.table("my_vectors")
.build();
}
一旦您擁有向量儲存例項,您就可以新增文件並執行搜尋
// 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'")
);
高階配置
對於更復雜的用例,您可以在 Spring Bean 中配置其他設定
@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 的連線
-
使用注入的 CqlSession(推薦)
@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.INDEXED 配置元資料列。
例如,您可以使用文字表示式語言
vectorStore.similaritySearch(
SearchRequest.builder().query("The World")
.topK(5)
.filterExpression("country in ['UK', 'NL'] && year >= 2020").build());
或透過表示式 DSL 以程式設計方式實現
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 查詢。
高階示例:基於 Wikipedia 資料集的向量儲存
以下示例演示如何在現有模式上使用儲存。這裡我們使用來自 github.com/datastax-labs/colbert-wikipedia-data 專案的模式,該專案附帶完整的 Wikipedia 資料集,已為您準備好向量化。
首先,在 Cassandra 資料庫中建立模式
wget https://s.apache.org/colbert-wikipedia-schema-cql -O colbert-wikipedia-schema.cql
cqlsh -f colbert-wikipedia-schema.cql
然後使用構建器模式配置儲存
@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();
}
載入完整的 Wikipedia 資料集
載入完整的 Wikipedia 資料集
-
從 s.apache.org/simplewiki-sstable-tar 下載
simplewiki-sstable.tar(這將需要一段時間,檔案有幾十 GB) -
載入資料
tar -xf simplewiki-sstable.tar -C ${CASSANDRA_DATA}/data/wikidata/articles-*/
nodetool import wikidata articles ${CASSANDRA_DATA}/data/wikidata/articles-*/
|
訪問原生客戶端
Cassandra 向量儲存實現透過 getNativeClient() 方法提供對底層原生 Cassandra 客戶端 (CqlSession) 的訪問
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
}
原生客戶端允許您訪問 VectorStore 介面可能未公開的 Cassandra 特定功能和操作。