SpringAi集成ChromaDb遇到的问题

65 阅读2分钟

一、背景

学习SpringAi框架时使用ChromaDb作为向量数据库,使用过程中并非一帆风顺,此文便是记录一下使用中的问题以及排查过程。

环境如下

ChromaDbdocker版本:latest
SpringAi1.0.0.2

二、问题

2.1 需要显性创建数据库

未通过Chroma提供的Swagger Api 显式创建 Collection,直接通过Spirng Ai 官网所写配置参数启动项目时,不会创建相应 Collection,从而导致项目启动失败。

可以通过源码观察,其封装 Rest 请求获取 Chroma 的连接

@Nullable
public Collection getCollection(String tenantName, String databaseName, String collectionName) {

    try {
        return this.restClient.get()
            .uri("/api/v2/tenants/{tenant_name}/databases/{database_name}/collections/{collection_name}",
                    tenantName, databaseName, collectionName)
            .headers(this::httpHeaders)
            .retrieve()
            .toEntity(Collection.class)
            .getBody();
    }
    catch (HttpServerErrorException | HttpClientErrorException e) {
        String msg = this.getErrorMessage(e);
        if (String.format("Collection [%s] does not exists", collectionName).equals(msg)) {
            return null;
        }
        throw new RuntimeException(msg, e);
    }
}

Swagger Api文档为: http://部署ip:8000/docs,如下图:

2.2 已创建并配置 Collection,仍然 404

由于Chroma还有两个概念,**tenant** 和 **database**,所以需要创建并配置此两项。再启动时,发现初始化创建与 ChromaDb 服务端的连接时,其 tenant 和 database 未生效,还是默认值。

由于是通过配置类(ChromaVectorStoreProperties)进行管理,肯定会有一个Spring自动配置类将其注入Spring容器进行管理。可以看到在ChromaVectorStoreAutoConfiguration类中注入ChromaVectorStore过程中仅赋值collectionName属性,而根据Api文档,三个参数都是路径参数是必需的。

@Bean
@ConditionalOnMissingBean
public ChromaVectorStore vectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi,
        ChromaVectorStoreProperties storeProperties, ObjectProvider<ObservationRegistry> observationRegistry,
        ObjectProvider<VectorStoreObservationConvention> customObservationConvention,
        BatchingStrategy chromaBatchingStrategy) {
    return ChromaVectorStore.builder(chromaApi, embeddingModel)
        .collectionName(storeProperties.getCollectionName())
        .initializeSchema(storeProperties.isInitializeSchema())
        .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
        .customObservationConvention(customObservationConvention.getIfAvailable(() -> null))
        .batchingStrategy(chromaBatchingStrategy)
        .build();
}

解决方案,在项目中自定义注入ChromaVectorStore即可。

@Bean
public ChromaVectorStore vectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi,
                                     ChromaVectorStoreProperties storeProperties, ObjectProvider<ObservationRegistry> observationRegistry,
                                     ObjectProvider<VectorStoreObservationConvention> customObservationConvention,
                                     BatchingStrategy chromaBatchingStrategy) {
    return ChromaVectorStore.builder(chromaApi, embeddingModel)
            .tenantName(storeProperties.getTenantName())
            .databaseName(storeProperties.getDatabaseName())
            .collectionName(storeProperties.getCollectionName())
            .initializeSchema(storeProperties.isInitializeSchema())
            .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
            .customObservationConvention(customObservationConvention.getIfAvailable(() -> null))
            .batchingStrategy(chromaBatchingStrategy)
            .build();
}

三、结语

通过对框架代码进行分析以及Debug慢慢解决问题,使我收获良多。其次现在AI相关更新迭代太快,此次可能就是chromaDb一直在迭代,从而导致使用的版本框架代码报错,所以这也是记录本文的原因,希望能帮助大家。

参考资料:

docs.springframework.org.cn/spring-ai/r…