rag - 文档向量知识库(Repository)
2026年6月10日 下午7:23:31
文档知识库,一般是基于向量数据库封装的并提供文档存储与相似搜索的接口(所以也叫,文档向量知识库)。其实,不基于向量数据库封装也行,比如基于本文搜索。
1、内置的适配(可以根据业务,按需定制)
| 知识库 | 所在插件 | 描述 |
|---|---|---|
| InMemoryRepository | solon-ai | 内存知识库(数据在 map 里) |
| WebSearchRepository | solon-ai | 联网搜索知识库 |
| ChromaRepository | solon-ai-repo-chroma | Chroma 矢量存储知识库 |
| DashVectorRepository | solon-ai-repo-dashvector | DashVector 矢量存储知识库 |
| ElasticsearchRepository | solon-ai-repo-elasticsearch | ElasticSearch 矢量存储知识库 |
| MilvusRepository | solon-ai-repo-milvus | Milvus 矢量存储知识库 |
| QdrantRepository | solon-ai-repo-qdrant | Qdrant 矢量存储知识库 |
| RedisRepository | solon-ai-repo-redis | Redis Search 矢量存储知识库 |
| TcVectorDbRepository | solon-ai-repo-tcvectordb | TcVectorDb 腾讯云矢量存储知识库 |
相关配置,参考具体插件介绍。
2、Repository 接口
只读知识库接口。比如封装网络搜索,只读接口即可
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);
}
}
可写知识库接口(可读,可写)
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、简单示例
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);
}