当前位置:   article > 正文

Spring AI教程(十六):检索增强生成(RAG)与函数调用 | Spring AI教程(十七):实现RAG技术与评估AI响应

spring ai

Spring AI教程(十六):检索增强生成(RAG)与函数调用

在前面的文章中,我们讨论了Prompt模板、嵌入技术和Token管理。这篇文章将进一步探讨检索增强生成(Retrieval Augmented Generation, RAG)和函数调用技术,帮助你将Spring AI的功能发挥到极致。

检索增强生成(RAG)

检索增强生成(RAG)是一种结合信息检索和生成模型的技术,用于将相关数据嵌入到Prompts中,以提高AI模型的响应准确性。该方法包括一个批处理风格的编程模型,读取未结构化的数据,将其转换,然后写入向量数据库。总体上,这是一个ETL(Extract, Transform, Load)管道。向量数据库在RAG技术中用于检索部分。

RAG的关键步骤
  1. 分割文档

将原始文档分割成较小的部分,同时保持内容的语义边界。例如,对于包含段落和表格的文档,避免在段落或表格中间进行分割。对于代码,避免在方法实现中间进行分割。

  1. 调整部分大小

将文档的部分进一步分割成更小的部分,其大小应为AI模型Token限制的一小部分。

示例:实现RAG
  1. 创建分割服务

创建一个服务类,用于分割文档并保持语义边界:

import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;

@Service
public class DocumentSplitService {

    public List<String> splitDocument(String document, int tokenLimit) {
        List<String> parts = new ArrayList<>();
        // 假设每个段落作为一个独立部分
        String[] paragraphs = document.split("\n\n");
        StringBuilder currentPart = new StringBuilder();

        for (String paragraph : paragraphs) {
            if (currentPart.length() + paragraph.length() <= tokenLimit) {
                currentPart.append(paragraph).append("\n\n");
            } else {
                parts.add(currentPart.toString());
                currentPart = new StringBuilder(paragraph).append("\n\n");
            }
        }

        if (currentPart.length() > 0) {
            parts.add(currentPart.toString());
        }

        return parts;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  1. 创建RAG服务

创建一个服务类,用于处理用户输入并使用RAG技术生成响应:

import org.springframework.stereotype.Service;
import com.example.springai.OpenAiChatService;
import com.example.springai.VectorDatabaseService;

import java.util.List;

@Service
public class RagService {

    private final OpenAiChatService openAiChatService;
    private final VectorDatabaseService vectorDatabaseService;
    private final DocumentSplitService documentSplitService;

    public RagService(OpenAiChatService openAiChatService, VectorDatabaseService vectorDatabaseService, DocumentSplitService documentSplitService) {
        this.openAiChatService = openAiChatService;
        this.vectorDatabaseService = vectorDatabaseService;
        this.documentSplitService = documentSplitService;
    }

    public String generateResponse(String userPrompt) {
        String retrievedInformation = vectorDatabaseService.search(userPrompt);
        List<String> documentParts = documentSplitService.splitDocument(retrievedInformation, 1000);  // 假设Token限制为1000

        StringBuilder combinedPrompt = new StringBuilder(userPrompt);
        for (String part : documentParts) {
            combinedPrompt.append(" 相关信息:").append(part);
        }

        return openAiChatService.chat(combinedPrompt.toString());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  1. 使用RAG服务

创建一个控制器,使用RAG服务生成响应:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RagController {

    @Autowired
    private RagService ragService;

    @GetMapping("/generate-rag-response")
    public String generateRagResponse(@RequestParam String prompt) {
        return ragService.generateResponse(prompt);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

函数调用(Function Calling)

函数调用技术允许注册自定义的用户函数,将大型语言模型连接到外部系统的API。Spring AI大大简化了支持函数调用所需的代码。

示例:实现函数调用
  1. 创建自定义函数

创建一个自定义函数,供AI模型调用:

import org.springframework.stereotype.Service;

@Service
public class CustomFunctionService {

    public String customFunction(String input) {
        // 执行自定义逻辑
        return "自定义函数处理的结果:" + input;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  1. 注册自定义函数

在Spring AI中注册自定义函数:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.example.springai.FunctionRegistry;

@Configuration
public class FunctionConfig {

    @Bean
    public FunctionRegistry functionRegistry(CustomFunctionService customFunctionService) {
        FunctionRegistry registry = new FunctionRegistry();
        registry.register("customFunction", customFunctionService::customFunction);
        return registry;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  1. 调用自定义函数

创建一个控制器,调用自定义函数:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.example.springai.FunctionRegistry;

@RestController
public class FunctionController {

    @Autowired
    private FunctionRegistry functionRegistry;

    @GetMapping("/call-custom-function")
    public String callCustomFunction(@RequestParam String input) {
        return functionRegistry.call("customFunction", input);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

结论

通过理解和应用检索增强生成(RAG)和函数调用技术,Spring AI可以处理更复杂的任务和更大规模的数据。这些技术不仅提高了AI模型的响应准确性,还扩展了其功能。希望这篇文章能帮助你在实际项目中应用这些技术,并激发你更多的创意。

下一篇文章中,我们将继续探讨更多实际应用场景和高级功能,帮助你进一步掌握这一强大的工具。

Spring AI教程(十七):实现RAG技术与评估AI响应

在前面的文章中,我们探讨了Prompt模板、嵌入技术和函数调用。这篇文章将进一步深入探讨如何在Spring AI中实现检索增强生成(RAG)技术,并评估AI响应的质量。

实现RAG技术

RAG技术通过将相关数据嵌入到Prompts中,提高AI模型的响应准确性。以下是实现RAG技术的关键概念和步骤:

RAG的关键概念
  • DocumentReader:一个Java函数接口,负责从数据源加载List<Document>。常见的数据源包括PDF、Markdown和JSON。
  • Document:数据源的文本表示形式,包含描述内容的元数据。
  • DocumentTransformer:负责以各种方式处理数据(例如,将文档分割成较小的部分或向Document添加额外的元数据)。
  • DocumentWriter:允许将Document持久化到数据库中(通常是向量数据库)。
  • Embedding:将数据表示为List<Double>,用于向量数据库计算用户查询与相关文档的相似性。
示例:实现RAG
  1. 创建DocumentReader

创建一个DocumentReader接口和其实现类,用于从数据源加载文档:

import java.util.List;

public interface DocumentReader {
    List<Document> readDocuments();
}

@Service
public class PdfDocumentReader implements DocumentReader {

    @Override
    public List<Document> readDocuments() {
        // 从PDF文件中读取文档的实现逻辑
        // 示例代码省略
        return List.of(new Document("Example content", "metadata"));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  1. 创建DocumentTransformer

创建一个DocumentTransformer接口和其实现类,用于分割文档并添加元数据:

import java.util.List;

public interface DocumentTransformer {
    List<Document> transform(Document document);
}

@Service
public class SimpleDocumentTransformer implements DocumentTransformer {

    @Override
    public List<Document> transform(Document document) {
        // 分割文档的实现逻辑
        // 示例代码省略
        return List.of(document);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  1. 创建DocumentWriter

创建一个DocumentWriter接口和其实现类,用于将文档写入向量数据库:

import java.util.List;

public interface DocumentWriter {
    void writeDocuments(List<Document> documents);
}

@Service
public class VectorDatabaseDocumentWriter implements DocumentWriter {

    @Override
    public void writeDocuments(List<Document> documents) {
        // 将文档写入向量数据库的实现逻辑
        // 示例代码省略
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  1. 实现RAG服务

创建一个服务类,结合以上组件实现RAG技术:

import org.springframework.stereotype.Service;
import com.example.springai.OpenAiChatService;

import java.util.List;

@Service
public class RagService {

    private final DocumentReader documentReader;
    private final DocumentTransformer documentTransformer;
    private final DocumentWriter documentWriter;
    private final OpenAiChatService openAiChatService;

    public RagService(DocumentReader documentReader, DocumentTransformer documentTransformer, DocumentWriter documentWriter, OpenAiChatService openAiChatService) {
        this.documentReader = documentReader;
        this.documentTransformer = documentTransformer;
        this.documentWriter = documentWriter;
        this.openAiChatService = openAiChatService;
    }

    public String generateResponse(String userPrompt) {
        List<Document> documents = documentReader.readDocuments();
        for (Document document : documents) {
            List<Document> transformedDocuments = documentTransformer.transform(document);
            documentWriter.writeDocuments(transformedDocuments);
        }

        String retrievedInformation = "retrieved information"; // 示例代码省略
        String combinedPrompt = userPrompt + " 相关信息:" + retrievedInformation;
        return openAiChatService.chat(combinedPrompt);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  1. 使用RAG服务

创建一个控制器,使用RAG服务生成响应:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RagController {

    @Autowired
    private RagService ragService;

    @GetMapping("/generate-rag-response")
    public String generateRagResponse(@RequestParam String prompt) {
        return ragService.generateResponse(prompt);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

函数调用(Function Calling)

函数调用技术允许注册自定义的用户函数,将大型语言模型连接到外部系统的API。Spring AI简化了支持函数调用所需的代码。

示例:实现函数调用
  1. 创建自定义函数

创建一个自定义函数,供AI模型调用:

import org.springframework.stereotype.Service;

@Service
public class CustomFunctionService {

    public String customFunction(String input) {
        // 执行自定义逻辑
        return "自定义函数处理的结果:" + input;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  1. 注册自定义函数

在Spring AI中注册自定义函数:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.example.springai.FunctionRegistry;

@Configuration
public class FunctionConfig {

    @Bean
    public FunctionRegistry functionRegistry(CustomFunctionService customFunctionService) {
        FunctionRegistry registry = new FunctionRegistry();
        registry.register("customFunction", customFunctionService::customFunction);
        return registry;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  1. 调用自定义函数

创建一个控制器,调用自定义函数:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.example.springai.FunctionRegistry;

@RestController
public class FunctionController {

    @Autowired
    private FunctionRegistry functionRegistry;

    @GetMapping("/call-custom-function")
    public String callCustomFunction(@RequestParam String input) {
        return functionRegistry.call("customFunction", input);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

评估AI响应

有效评估AI系统的输出是确保其质量和可靠性的关键步骤。以下是评估AI响应的一些方法:

1. 人工评估

通过人工评估AI的响应,可以判断其准确性和相关性。虽然这种方法耗时,但对于关键任务非常重要。

2. 自动化评估

使用自动化工具和指标,如BLEU、ROUGE等,可以快速评估AI响应的质量。这种方法适合于大规模的测试和评估。

3. 用户反馈

收集用户反馈,了解AI响应的实际效果和改进空间。这种方法能够帮助开发者不断优化和改进AI模型。

结论

通过理解和应用检索增强生成(RAG)技术和函数调用,Spring AI可以处理更复杂的任务和更大规模的数据。此外,有效评估AI响应能够确保其质量和可靠性。希望这篇文章能帮助你在实际项目中应用这些技术,并激发你更多的创意。

下一篇文章中,我们将继续探讨更多实际应用场景和高级功能,帮助你进一步掌握这一强大的工具。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/743784
推荐阅读
相关标签
  

闽ICP备14008679号