📷 [图片 token=ODG0baag2oN1Qyx95pJcXIT2nQq(未能下载,见飞书原文)]

📷 [图片 token=KS16baPLioXEo1xBXg9cS7TAnqg(未能下载,见飞书原文)]

前言

上一节我们实现了知识库Agent的上半部分,这一节我们来实现知识库的召回功能。

核心代码:SuperBizAgent/src/main/java/org/example/service/VectorSearchService.java

📷 [图片 token=Lowcb5oMoofPIax2BwRcEj2knRg(未能下载,见飞书原文)]

召回

我们之前是将文档存储到了Milvus向量数据库里面,所以召回的时候也是从这个数据库去查询。

  1. 将查询文本向量化

  2. 相似度查询

/**
 * 搜索相似文档
 * 
 * @param query 查询文本
 * @param topK 返回最相似的K个结果
 * @return 搜索结果列表
 */
public List<SearchResult> searchSimilarDocuments(String query, int topK) {
    try {
        logger.info("开始搜索相似文档, 查询: {}, topK: {}", query, topK);
        // 1. 将查询文本向量化
        List<Float> queryVector = embeddingService.generateQueryVector(query);
        // 2. 构建搜索参数
        SearchParam searchParam = SearchParam.newBuilder()build();
        // 3. 执行搜索
        R<SearchResults> searchResponse = milvusClient.search(searchParam);
        // 4. 解析搜索结果
        SearchResultsWrapper wrapper = new SearchResultsWrapper(searchResponse.getData().getResults());
        List<SearchResult> results = new ArrayList<>();
        for (int i = 0; i < wrapper.getRowRecords(0).size(); i++) {
            ///            
            results.add(result);
        }
        return results;
    }
}

首先我们对问题进行向量化,按照Spring AI 的sdk要求,拼接请求参数,然后调用

/**
 * 生成向量嵌入
 * 调用阿里云 DashScope Text Embedding API
 * 
 * @param content 文本内容
 * @return 向量嵌入(浮点数列表)
 */
public List<Float> generateEmbedding(String content) {
    try {
        // 构建请求参数
        TextEmbeddingParam param = TextEmbeddingParam
                .builder()
                .model(model)
                .texts(Collections.singletonList(content))
                .build();
        // 调用 API
        TextEmbeddingResult result = textEmbedding.call(param);
        // 检查结果
        List<Float> floatEmbedding = getFloats(result);
        return floatEmbedding;
    } 
}

然后我们使用Milvus的sdk,进行相似度,获取相似的向量数据

// 2. 构建搜索参数
SearchParam searchParam = SearchParam.newBuilder()
        .withCollectionName(MilvusConstants.MILVUS_COLLECTION_NAME)
        .withVectorFieldName("vector")
        .withVectors(Collections.singletonList(queryVector))
        .withTopK(topK)
        .withMetricType(io.milvus.param.MetricType.L2)
        .withOutFields(List.of("id", "content", "metadata"))
        .withParams("{\"nprobe\":10}")
        .build();

// 3. 执行搜索
R<SearchResults> searchResponse = milvusClient.search(searchParam);

总结:对问题先进行向量化,然后根据向量,调用数据库的向量查询接口进行查询。

总结

至此,RAG的分片、索引、召回功能我们都实现完了。后续会介绍其他Agent是怎么使用知识库,怎么结合召回来与大模型进行交互的。