Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@

package org.springframework.ai.chat.evaluation;

import java.util.Collections;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.evaluation.EvaluationRequest;
import org.springframework.ai.evaluation.EvaluationResponse;
import org.springframework.ai.evaluation.Evaluator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

import java.util.Collections;

/**
* Implementation of {@link Evaluator} used to evaluate the factual accuracy of Large
Expand Down Expand Up @@ -59,6 +61,7 @@
*
* @author Eddú Meléndez
* @author Mark Pollack
* @author guan xu
* @see Evaluator
* @see EvaluationRequest
* @see EvaluationResponse
Expand All @@ -69,13 +72,20 @@ public class FactCheckingEvaluator implements Evaluator {
private static final String DEFAULT_EVALUATION_PROMPT_TEXT = """
Evaluate whether or not the following claim is supported by the provided document.
Respond with "yes" if the claim is supported, or "no" if it is not.
Document: \\n {document}\\n
Claim: \\n {claim}

Document:
{document}

Claim:
{claim}
""";

private static final String BESPOKE_EVALUATION_PROMPT_TEXT = """
Document: \\n {document}\\n
Claim: \\n {claim}
Document:
{document}

Claim:
{claim}
""";

private final ChatClient.Builder chatClientBuilder;
Expand All @@ -89,7 +99,7 @@ public class FactCheckingEvaluator implements Evaluator {
* evaluation
*/
public FactCheckingEvaluator(ChatClient.Builder chatClientBuilder) {
this(chatClientBuilder, DEFAULT_EVALUATION_PROMPT_TEXT);
this(chatClientBuilder, null);
}

/**
Expand All @@ -99,9 +109,10 @@ public FactCheckingEvaluator(ChatClient.Builder chatClientBuilder) {
* evaluation
* @param evaluationPrompt The prompt text to use for evaluation
*/
public FactCheckingEvaluator(ChatClient.Builder chatClientBuilder, String evaluationPrompt) {
public FactCheckingEvaluator(ChatClient.Builder chatClientBuilder, @Nullable String evaluationPrompt) {
Assert.notNull(chatClientBuilder, "chatClientBuilder cannot be null");
this.chatClientBuilder = chatClientBuilder;
this.evaluationPrompt = evaluationPrompt;
this.evaluationPrompt = evaluationPrompt != null ? evaluationPrompt : DEFAULT_EVALUATION_PROMPT_TEXT;
}

/**
Expand Down Expand Up @@ -138,4 +149,33 @@ public EvaluationResponse evaluate(EvaluationRequest evaluationRequest) {
return new EvaluationResponse(passing, "", Collections.emptyMap());
}

public static FactCheckingEvaluator.Builder builder() {
return new FactCheckingEvaluator.Builder();
}

public static final class Builder {

private ChatClient.Builder chatClientBuilder;

private String evaluationPrompt;

private Builder() {
}

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

public FactCheckingEvaluator.Builder evaluationPrompt(String evaluationPrompt) {
this.evaluationPrompt = evaluationPrompt;
return this;
}

public FactCheckingEvaluator build() {
return new FactCheckingEvaluator(this.chatClientBuilder, this.evaluationPrompt);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2023-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.ai.chat.evaluation;

import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;

/**
* Unit tests for {@link FactCheckingEvaluator}.
*
* @author guan xu
*/
class FactCheckingEvaluatorTests {

@Test
void whenChatClientBuilderIsNullThenThrow() {
assertThatThrownBy(() -> new FactCheckingEvaluator(null)).isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("chatClientBuilder cannot be null");

assertThatThrownBy(() -> FactCheckingEvaluator.builder().chatClientBuilder(null).build())
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("chatClientBuilder cannot be null");
}

@Test
void whenEvaluationPromptIsNullThenUseDefaultEvaluationPromptText() {
FactCheckingEvaluator evaluator = new FactCheckingEvaluator(ChatClient.builder(mock(ChatModel.class)));
assertThat(evaluator).isNotNull();

evaluator = FactCheckingEvaluator.builder()
.chatClientBuilder(ChatClient.builder(mock(ChatModel.class)))
.build();
assertThat(evaluator).isNotNull();
}

@Test
void whenForBespokeMinicheckThenUseBespokeEvaluationPromptText() {
FactCheckingEvaluator evaluator = FactCheckingEvaluator.forBespokeMinicheck(ChatClient.builder(mock(ChatModel.class)));
assertThat(evaluator).isNotNull();
}

}
Loading