Add Evaluator
This commit is contained in:
@@ -5,14 +5,14 @@ import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
||||
import org.springframework.ai.chat.ChatClient;
|
||||
import org.springframework.ai.chat.agent.DefaultChatAgent;
|
||||
import org.springframework.ai.chat.agent.PromptContext;
|
||||
|
||||
import org.springframework.ai.chat.agent.transformer.QAPromptContextTransformer;
|
||||
|
||||
import org.springframework.ai.chat.agent.transformer.VectorStorePromptContextTransformer;
|
||||
|
||||
import org.springframework.ai.chat.messages.UserMessage;
|
||||
import org.springframework.ai.chat.prompt.Prompt;
|
||||
import org.springframework.ai.embedding.EmbeddingClient;
|
||||
import org.springframework.ai.evaluation.EvaluationRequest;
|
||||
import org.springframework.ai.evaluation.EvaluationResponse;
|
||||
import org.springframework.ai.evaluation.RelevancyEvaluator;
|
||||
import org.springframework.ai.openai.OpenAiChatClient;
|
||||
import org.springframework.ai.openai.OpenAiEmbeddingClient;
|
||||
import org.springframework.ai.openai.api.OpenAiApi;
|
||||
@@ -61,16 +61,13 @@ public class OpenAiDefaultChatAgentIT {
|
||||
var agentResponse = chatAgent.call(promptContext);
|
||||
System.out.println(agentResponse.getChatResponse().getResult().getOutput().getContent());
|
||||
|
||||
// RelevancyEvaluator relevancyEvaluator = new
|
||||
// RelevancyEvaluator(this.chatClient);
|
||||
// EvaluationRequest evaluationRequest = new EvaluationRequest(
|
||||
// agentResponse.getPromptContext().getOriginalPrompt(),
|
||||
// agentResponse.getPromptContext().getDataList(),
|
||||
// agentResponse.getChatResponse());
|
||||
//
|
||||
// EvaluationResponse evaluationResponse =
|
||||
// relevancyEvaluator.evaluate(evaluationRequest);
|
||||
// System.out.println(evaluationResponse);
|
||||
RelevancyEvaluator relevancyEvaluator = new RelevancyEvaluator(this.chatClient);
|
||||
EvaluationRequest evaluationRequest = new EvaluationRequest(
|
||||
agentResponse.getPromptContext().getPromptHistory().get(0), agentResponse.getPromptContext().getNodes(),
|
||||
agentResponse.getChatResponse());
|
||||
|
||||
EvaluationResponse evaluationResponse = relevancyEvaluator.evaluate(evaluationRequest);
|
||||
System.out.println(evaluationResponse);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.springframework.ai.evaluation;
|
||||
|
||||
import org.springframework.ai.chat.ChatResponse;
|
||||
import org.springframework.ai.chat.prompt.Prompt;
|
||||
import org.springframework.ai.node.Node;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class EvaluationRequest {
|
||||
|
||||
private Prompt prompt;
|
||||
|
||||
private List<Node<?>> dataList;
|
||||
|
||||
private ChatResponse chatResponse;
|
||||
|
||||
public EvaluationRequest(Prompt prompt, List<Node<?>> dataList, ChatResponse chatResponse) {
|
||||
this.prompt = prompt;
|
||||
this.dataList = dataList;
|
||||
this.chatResponse = chatResponse;
|
||||
}
|
||||
|
||||
public Prompt getPrompt() {
|
||||
return prompt;
|
||||
}
|
||||
|
||||
public List<Node<?>> getDataList() {
|
||||
return dataList;
|
||||
}
|
||||
|
||||
public ChatResponse getChatResponse() {
|
||||
return chatResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EvaluationRequest{" + "prompt=" + prompt + ", dataList=" + dataList + ", chatResponse=" + chatResponse
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof EvaluationRequest that))
|
||||
return false;
|
||||
return Objects.equals(prompt, that.prompt) && Objects.equals(dataList, that.dataList)
|
||||
&& Objects.equals(chatResponse, that.chatResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(prompt, dataList, chatResponse);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.springframework.ai.evaluation;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class EvaluationResponse {
|
||||
|
||||
private boolean pass;
|
||||
|
||||
private float score;
|
||||
|
||||
private String feedback;
|
||||
|
||||
Map<String, Object> metadata;
|
||||
|
||||
public EvaluationResponse(boolean pass, float score, String feedback, Map<String, Object> metadata) {
|
||||
this.pass = pass;
|
||||
this.score = score;
|
||||
this.feedback = feedback;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public boolean isPass() {
|
||||
return pass;
|
||||
}
|
||||
|
||||
public float getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public String getFeedback() {
|
||||
return feedback;
|
||||
}
|
||||
|
||||
public Map<String, Object> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EvaluationResponse{" + "pass=" + pass + ", score=" + score + ", feedback='" + feedback + '\''
|
||||
+ ", metadata=" + metadata + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof EvaluationResponse that))
|
||||
return false;
|
||||
return pass == that.pass && Float.compare(score, that.score) == 0 && Objects.equals(feedback, that.feedback)
|
||||
&& Objects.equals(metadata, that.metadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(pass, score, feedback, metadata);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.springframework.ai.evaluation;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Evaluator {
|
||||
|
||||
EvaluationResponse evaluate(EvaluationRequest evaluationRequest);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.springframework.ai.evaluation;
|
||||
|
||||
import org.springframework.ai.chat.ChatClient;
|
||||
import org.springframework.ai.chat.ChatResponse;
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
import org.springframework.ai.chat.messages.MessageType;
|
||||
import org.springframework.ai.chat.prompt.Prompt;
|
||||
import org.springframework.ai.chat.prompt.PromptTemplate;
|
||||
import org.springframework.ai.node.Node;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class RelevancyEvaluator implements Evaluator {
|
||||
|
||||
private static final String DEFAULT_EVALUATION_PROMPT_TEXT = """
|
||||
Your task is to evaluate if the response for the query
|
||||
is in line with the context information provided.\\n
|
||||
You have two options to answer. Either YES/ NO.\\n
|
||||
Answer - YES, if the response for the query
|
||||
is in line with context information otherwise NO.\\n
|
||||
Query: \\n {query}\\n
|
||||
Response: \\n {response}\\n
|
||||
Context: \\n {context}\\n
|
||||
Answer: "
|
||||
""";
|
||||
|
||||
private ChatClient chatClient;
|
||||
|
||||
public RelevancyEvaluator(ChatClient chatClient) {
|
||||
this.chatClient = chatClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvaluationResponse evaluate(EvaluationRequest evaluationRequest) {
|
||||
var query = doGetUserQuestion(evaluationRequest);
|
||||
var response = doGetResponse(evaluationRequest);
|
||||
var context = doGetSupportingData(evaluationRequest);
|
||||
|
||||
var promptTemplate = new PromptTemplate(DEFAULT_EVALUATION_PROMPT_TEXT);
|
||||
Message message = promptTemplate
|
||||
.createMessage(Map.of("query", query, "response", response, "context", context));
|
||||
|
||||
ChatResponse chatResponse = this.chatClient.call(new Prompt(message));
|
||||
|
||||
var evaluationResponse = chatResponse.getResult().getOutput().getContent();
|
||||
boolean passing = false;
|
||||
float score = 0;
|
||||
if (evaluationResponse.toLowerCase().contains("yes")) {
|
||||
passing = true;
|
||||
score = 1;
|
||||
}
|
||||
|
||||
return new EvaluationResponse(passing, score, "", Collections.emptyMap());
|
||||
}
|
||||
|
||||
protected String doGetResponse(EvaluationRequest evaluationRequest) {
|
||||
return evaluationRequest.getChatResponse().getResult().getOutput().getContent();
|
||||
}
|
||||
|
||||
protected String doGetSupportingData(EvaluationRequest evaluationRequest) {
|
||||
List<Node<?>> data = evaluationRequest.getDataList();
|
||||
String supportingData = data.stream()
|
||||
.filter(node -> node != null && node.getContent() instanceof String)
|
||||
.map(node -> (Node<String>) node)
|
||||
.map(Node::getContent)
|
||||
.collect(Collectors.joining("\n"));
|
||||
return supportingData;
|
||||
}
|
||||
|
||||
protected String doGetUserQuestion(EvaluationRequest evaluationRequest) {
|
||||
List<Message> instructions = evaluationRequest.getPrompt().getInstructions();
|
||||
String userMessage = instructions.stream()
|
||||
.filter(m -> m.getMessageType() == MessageType.USER)
|
||||
.map(m -> m.getContent())
|
||||
.collect(Collectors.joining(System.lineSeparator()));
|
||||
return userMessage;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user