---
title: "rag - 文档向量知识库（Repository）"
---

文档知识库，一般是基于向量数据库封装的并提供文档存储与相似搜索的接口（所以也叫，文档向量知识库）。其实，不基于向量数据库封装也行，比如基于本文搜索。


### 1、内置的适配（可以根据业务，按需定制）

| 知识库                              | 所在插件                                | 描述                                         |
| --------------------- | ------------------------ | ------------------------- |
| InMemoryRepository         | solon-ai                                  | 内存知识库（数据在 map 里）     |
| WebSearchRepository       | solon-ai                                  | 联网搜索知识库                        |
| | | |
| ChromaRepository             | [solon-ai-repo-chroma](/article/988)              | Chroma 矢量存储知识库                |
| DashVectorRepository             | [solon-ai-repo-dashvector](/article/1024)              | DashVector 矢量存储知识库                |
| ElasticsearchRepository     | [solon-ai-repo-elasticsearch](/article/989)      | ElasticSearch 矢量存储知识库                |
| MilvusRepository               | [solon-ai-repo-milvus](/article/941)               | Milvus 矢量存储知识库                |
| QdrantRepository              | [solon-ai-repo-qdrant](/article/990)               | Qdrant 矢量存储知识库                |
| RedisRepository                | [solon-ai-repo-redis](/article/942)                 | Redis Search 矢量存储知识库       |
| TcVectorDbRepository       | [solon-ai-repo-tcvectordb](/article/991)         | TcVectorDb 腾讯云矢量存储知识库                |


相关配置，参考具体插件介绍。


### 2、Repository 接口

只读知识库接口。比如封装网络搜索，只读接口即可

```java
package org.noear.solon.ai.rag;

import org.noear.solon.ai.chat.message.ChatMessage;
import org.noear.solon.ai.rag.util.QueryCondition;
import org.noear.solon.lang.Preview;

import java.io.IOException;
import java.util.List;

/**
 * 知识库（可检索）
 */
public interface Repository {
    /**
     * 检索
     *
     * @param query 查询字符串
     */
    default List<Document> search(String query) throws IOException {
        return search(new QueryCondition(query));
    }

    /**
     * 检索
     *
     * @param condition 查询条件
     */
    List<Document> search(QueryCondition condition) throws IOException;

    /**
     * 提示词简单增强
     */
    default ChatMessage promptAugment(String query) throws IOException {
        List<Document> context = search(query);
        return ChatMessage.ofUserAugment(query, context);
    }
}
```

可写知识库接口（可读，可写）

```java
package org.noear.solon.ai.rag;

import org.noear.solon.core.util.RunUtil;
import org.noear.solon.lang.Preview;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;

/**
 * 可存储的知识库（可存储）
 */
public interface RepositoryStorable extends Repository {
    /**
     * 异步保存文档
     *
     * @param documents        文档集
     * @param progressCallback 进度回调
     * @since 3.5
     */
    default CompletableFuture<Void> asyncSave(List<Document> documents, BiConsumer<Integer, Integer> progressCallback) {
        CompletableFuture<Void> future = new CompletableFuture<>();

        RunUtil.async(() -> {
            try {
                save(documents, progressCallback);
                future.complete(null);
            } catch (Throwable ex) {
                future.completeExceptionally(ex);
            }
        });

        return future;
    }

    /**
     * 保存文档
     *
     * @param documents        文档集
     * @param progressCallback 进度回调
     * @since 3.5
     */
    void save(List<Document> documents, BiConsumer<Integer, Integer> progressCallback) throws IOException;


    /**
     * 保存文档
     *
     * @param documents 文档集
     * @since 3.5
     */
    default void save(List<Document> documents) throws IOException {
        save(documents, null);
    }

    /**
     * 保存文档
     *
     * @param documents 文档集
     * @since 3.5
     */
    default void save(Document... documents) throws IOException {
        save(Arrays.asList(documents));
    }

    /**
     * 删除文档
     *
     * @param ids 文档IDs
     * @since 3.5
     */
    void deleteById(String... ids) throws IOException;

    /**
     * 是否存在文档
     *
     * @param id 文档ID
     * @since 3.5
     */
    boolean existsById(String id) throws IOException;
}
```


### 3、简单示例

```java
private void load(RepositoryStorable repository, String file) throws IOException {
    //加载器
    HtmlSimpleLoader loader = new HtmlSimpleLoader(new File(file));
    
    //加载后再分割（按需）
    List<Document> documents = new SplitterPipeline() 
            .next(new RegexTextSplitter("\n\n"))
            .next(new TokenSizeTextSplitter(500))
            .split(loader.load());
    
    //入库
    repository.save(documents); 
}
```