11.模型评估测试 (Evaluation Testing)

42 阅读4分钟

模型评估测试 (Evaluation Testing)

前言

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

评估响应的一种方法是使用 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:上下文数据,如来自检索增强生成(Retrieval Augmented Generation),附加到原始输入
  • responseContent:AI 模型的响应内容,作为 String

Relevancy Evaluator

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 的示例,使用 RetrievalAugmentationAdvisor 验证 RAG 流程的结果:

@Test
void evaluateRelevancy() {
    String question = "Anacletus 和 Birba 的冒险发生在哪里?";

    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 占位符,用于接收上下文信息

FactCheckingEvaluator

FactCheckingEvaluatorEvaluator 接口的另一个实现,旨在评估 AI 生成的响应与提供上下文的事实准确性。此评估器通过验证给定陈述(声明)是否得到提供上下文(文档)的逻辑支持,帮助检测和减少 AI 输出中的幻觉。

'声明' 和 '文档' 被呈现给 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 模型响应。

示例

以下是如何将 FactCheckingEvaluator 与基于 Ollama 的 ChatModel 一起使用的示例,特别是 Bespoke-Minicheck 模型:

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

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

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

  // 示例上下文和声明
  String context = "地球是距离太阳的第三颗行星,也是已知唯一存在生命的天体。";
  String claim = "地球是距离太阳的第四颗行星。";

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

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

  assertFalse(evaluationResponse.isPass(), "声明不应得到上下文支持");

}