Lzh on GitHub

评估测试

测试 AI 应用程序需要评估生成的内容,以确保 AI 模型没有产生幻觉式的响应。

测试 AI 应用程序需要评估生成的内容,以确保 AI 模型没有产生幻觉式的响应。

评估响应的一种方法是使用 AI 模型本身进行评估。选择用于评估的最佳 AI 模型,该模型可能与用于生成响应的模型不同。

Spring AI 用于评估响应的接口是 Evaluator,定义如下:

@FunctionalInterface
public interface Evaluator {
    EvaluationResponse evaluate(EvaluationRequest evaluationRequest);
}

评估的输入为 EvaluationRequest,定义如下:

public class EvaluationRequest {

    private final String userText;

    private final List<Content> dataList;

    private final String responseContent;

    public EvaluationRequest(String userText, List<Content> dataList, String responseContent) {
        this.userText = userText;
        this.dataList = dataList;
        this.responseContent = responseContent;
    }

  ...
}
  • userText:用户的原始输入,类型为 String
  • dataList:上下文数据,例如从增强检索生成(RAG)中获取的内容,并附加到原始输入中
  • responseContent:AI 模型生成的响应内容,类型为 String

相关性评估器

RelevancyEvaluatorEvaluator 接口的一个实现,用于评估 AI 生成的响应与提供的上下文的相关性。该评估器有助于通过判断 AI 模型的响应是否与检索到的上下文相关,从而评估 RAG 流程的质量。

评估基于用户输入、AI 模型的响应以及上下文信息。它使用提示模板来询问 AI 模型响应是否与用户输入和上下文相关。

这是 RelevancyEvaluator 使用的默认提示模板:

Your task is to evaluate if the response for the query
is in line with the context information provided.

You have two options to answer. Either YES or NO.

Answer YES, if the response for the query
is in line with context information otherwise NO.

Query:
{query}

Response:
{response}

Context:
{context}

Answer:
您可以通过 .promptTemplate() 构建器方法提供自己的 PromptTemplate 对象来自定义提示模板。详情请参见 自定义模板

在集成测试中的使用

下面是 RelevancyEvaluator 在集成测试中的使用示例,用于验证 RAG 流程的结果,使用了 RetrievalAugmentationAdvisor

@Test
void evaluateRelevancy() {
    String question = "Where does the adventure of Anacletus and Birba take place?";

    RetrievalAugmentationAdvisor ragAdvisor = RetrievalAugmentationAdvisor.builder()
        .documentRetriever(VectorStoreDocumentRetriever.builder()
            .vectorStore(pgVectorStore)
            .build())
        .build();

    ChatResponse chatResponse = ChatClient.builder(chatModel).build()
        .prompt(question)
        .advisors(ragAdvisor)
        .call()
        .chatResponse();

    EvaluationRequest evaluationRequest = new EvaluationRequest(
        // 原始用户问题
        question,
        // RAG 流程中检索到的上下文
        chatResponse.getMetadata().get(RetrievalAugmentationAdvisor.DOCUMENT_CONTEXT),
        // AI 模型的响应
        chatResponse.getResult().getOutput().getText()
    );

    RelevancyEvaluator evaluator = new RelevancyEvaluator(ChatClient.builder(chatModel));

    EvaluationResponse evaluationResponse = evaluator.evaluate(evaluationRequest);

    assertThat(evaluationResponse.isPass()).isTrue();
}

在 Spring AI 项目中,有多个集成测试使用 RelevancyEvaluator 来测试 QuestionAnswerAdvisor(见 测试)和 RetrievalAugmentationAdvisor(见 测试)的功能。

自定义模板

RelevancyEvaluator 使用默认模板向 AI 模型发送提示进行评估。你可以通过 .promptTemplate() 构建器方法提供自定义的 PromptTemplate 对象来定制此行为。

自定义的 PromptTemplate 可以使用任何 TemplateRenderer 实现(默认使用基于 StringTemplate 引擎的 StPromptTemplate)。重要的要求是模板必须包含以下占位符:

  • 一个 query 占位符,用于接收用户问题。
  • 一个 response 占位符,用于接收 AI 模型的响应。
  • 一个 context 占位符,用于接收上下文信息。

事实核查评估器

FactCheckingEvaluatorEvaluator 接口的另一个实现,旨在评估 AI 生成响应的事实准确性与提供的上下文是否一致。该评估器有助于检测和减少 AI 输出中的幻觉,通过验证给定陈述(claim)是否由提供的上下文(document)逻辑支持来实现。

“claim” 和 “document” 会被提供给 AI 模型进行评估。也有专门用于此目的的小型高效 AI 模型可用,例如 Bespoke 的 Minicheck,相比 GPT-4 等旗舰模型,它能降低执行这些检查的成本。Minicheck 也可通过 Ollama 使用。

使用方法

FactCheckingEvaluator 的构造函数以 ChatClient.Builder 作为参数:

public FactCheckingEvaluator(ChatClient.Builder chatClientBuilder) {
  this.chatClientBuilder = chatClientBuilder;
}

该评估器使用以下提示模板进行事实核查:

Document: {document}
Claim: {claim}

其中 {document} 表示上下文信息,{claim} 表示需要评估的 AI 模型响应。

示例

以下是如何使用基于 Ollama 的 ChatModel(具体为 Bespoke-Minicheck 模型)使用 FactCheckingEvaluator 的示例:

@Test
void testFactChecking() {
  // 设置 Ollama API
  OllamaApi ollamaApi = new OllamaApi("http://localhost:11434");

  ChatModel chatModel = new OllamaChatModel(ollamaApi,
        OllamaChatOptions.builder()
            .model(BESPOKE_MINICHECK)
            .numPredict(2)
            .temperature(0.0d)
            .build());

  // 创建 FactCheckingEvaluator
  var factCheckingEvaluator = new FactCheckingEvaluator(ChatClient.builder(chatModel));

  // 示例上下文和声明
  String context = "The Earth is the third planet from the Sun and the only astronomical object known to harbor life.";
  String claim = "The Earth is the fourth planet from the Sun.";

  // 创建 EvaluationRequest
  EvaluationRequest evaluationRequest = new EvaluationRequest(context, Collections.emptyList(), claim);

  // 执行评估
  EvaluationResponse evaluationResponse = factCheckingEvaluator.evaluate(evaluationRequest);

  assertFalse(evaluationResponse.isPass(), "该声明不应被上下文支持");
}