refactor: update error prompt handling in CSV and JSON response handlers for improved clarity and consistency

This commit is contained in:
extio-de
2026-06-18 17:18:32 +02:00
parent 967cd43f87
commit cadc1b3a1c
3 changed files with 41 additions and 23 deletions

View File

@@ -27,7 +27,7 @@ public class CsvAgentResponseHandler implements StreamedAgentResponseHandler {
private final String fieldSeparatorQuoted; private final String fieldSeparatorQuoted;
private final String errorPromptSuffix; private final String errorPrompt;
private final String reasoningKey; private final String reasoningKey;
@@ -52,9 +52,9 @@ public class CsvAgentResponseHandler implements StreamedAgentResponseHandler {
this.reasoningKey = this.keyPrefix + "_reasoning"; this.reasoningKey = this.keyPrefix + "_reasoning";
this.afterChunkUpdate = afterChunkUpdate; this.afterChunkUpdate = afterChunkUpdate;
this.errorPromptSuffix = "\n\nThe previous response could not be fully processed or validated. " + this.errorPrompt = "\n\nThe previous response could not be fully processed or validated. " +
"Please format the response as CSV with '" + fieldSeparator + "' as field separator.\n" + "Please format the response as CSV with '" + fieldSeparator + "' as field separator.\n" +
"Expected columns: " + String.join(", ", headings) + " \nOne row per line."; "Expected columns: " + String.join(this.fieldSeparator, headings) + " \nOne row per line.";
} }
@Override @Override
@@ -69,7 +69,7 @@ public class CsvAgentResponseHandler implements StreamedAgentResponseHandler {
final boolean success = this.parseCsv(resp, context); final boolean success = this.parseCsv(resp, context);
if (!success) { if (!success) {
LOGGER.warn("No valid CSV data parsed from response"); LOGGER.warn("No valid CSV data parsed from response");
this.addCsvResponseErrorPrompt(context); this.addCsvResponseErrorPrompt(context, resp);
return false; return false;
} }
@@ -77,7 +77,7 @@ public class CsvAgentResponseHandler implements StreamedAgentResponseHandler {
} }
catch (final Exception ex) { catch (final Exception ex) {
LOGGER.warn("Failed to parse CSV response", ex); LOGGER.warn("Failed to parse CSV response", ex);
this.addCsvResponseErrorPrompt(context); this.addCsvResponseErrorPrompt(context, resp);
return false; return false;
} }
} }
@@ -185,11 +185,17 @@ public class CsvAgentResponseHandler implements StreamedAgentResponseHandler {
return true; return true;
} }
private void addCsvResponseErrorPrompt(final AgentContext context) { private void addCsvResponseErrorPrompt(final AgentContext context, final String csvResponse) {
final var turn = context.getConversation().getConversation().getLast(); // final var turn = context.getConversation().getConversation().getLast();
context.getConversation().replaceTurn(new Conversation.Turn( // context.getConversation().replaceTurn(new Conversation.Turn(
turn.type(), // turn.type(),
turn.text() + this.errorPromptSuffix)); // turn.text() + this.errorPromptSuffix));
context.getConversation().addTurn(new Conversation.Turn(
Conversation.TurnType.ASSISTANT,
csvResponse != null ? csvResponse : ""));
context.getConversation().addTurn(new Conversation.Turn(
Conversation.TurnType.USER,
this.errorPrompt));
} }
private String stripQuotes(final String value) { private String stripQuotes(final String value) {

View File

@@ -39,7 +39,7 @@ public class CsvUnmarshallingAgentResponseHandler implements AgentResponseHandle
private final String listSeparatorQuoted; private final String listSeparatorQuoted;
private final String errorPromptSuffix; private final String errorPrompt;
public CsvUnmarshallingAgentResponseHandler(final Class<?> targetClass, final String contextKey) { public CsvUnmarshallingAgentResponseHandler(final Class<?> targetClass, final String contextKey) {
this(targetClass, contextKey, ";", ","); this(targetClass, contextKey, ";", ",");
@@ -70,7 +70,7 @@ public class CsvUnmarshallingAgentResponseHandler implements AgentResponseHandle
final String listInfo = (listSeparator != null && !listSeparator.isEmpty()) final String listInfo = (listSeparator != null && !listSeparator.isEmpty())
? " and '" + listSeparator + "' for list items" ? " and '" + listSeparator + "' for list items"
: ""; : "";
this.errorPromptSuffix = "\n\nThe previous response could not be fully processed or validated. " + this.errorPrompt = "\n\nThe previous response could not be fully processed or validated. " +
"Please format the response as CSV with '" + fieldSeparator + "' as field separator" + "Please format the response as CSV with '" + fieldSeparator + "' as field separator" +
listInfo + ". One object per line."; listInfo + ". One object per line.";
} }
@@ -97,7 +97,7 @@ public class CsvUnmarshallingAgentResponseHandler implements AgentResponseHandle
final List<Object> parsedObjects = this.parseCsv(resp); final List<Object> parsedObjects = this.parseCsv(resp);
if (parsedObjects.isEmpty()) { if (parsedObjects.isEmpty()) {
LOGGER.warn("No valid CSV data parsed from response"); LOGGER.warn("No valid CSV data parsed from response");
this.addCsvResponseErrorPrompt(context); this.addCsvResponseErrorPrompt(context, resp);
return false; return false;
} }
@@ -107,7 +107,7 @@ public class CsvUnmarshallingAgentResponseHandler implements AgentResponseHandle
} }
catch (final Exception ex) { catch (final Exception ex) {
LOGGER.warn("Failed to parse CSV response", ex); LOGGER.warn("Failed to parse CSV response", ex);
this.addCsvResponseErrorPrompt(context); this.addCsvResponseErrorPrompt(context, resp);
return false; return false;
} }
} }
@@ -253,11 +253,17 @@ public class CsvUnmarshallingAgentResponseHandler implements AgentResponseHandle
throw new IllegalArgumentException("Unsupported field type: " + fieldType.getName()); throw new IllegalArgumentException("Unsupported field type: " + fieldType.getName());
} }
private void addCsvResponseErrorPrompt(final AgentContext context) { private void addCsvResponseErrorPrompt(final AgentContext context, final String csvResponse) {
final var turn = context.getConversation().getConversation().getLast(); // final var turn = context.getConversation().getConversation().getLast();
context.getConversation().replaceTurn(new Conversation.Turn( // context.getConversation().replaceTurn(new Conversation.Turn(
turn.type(), // turn.type(),
turn.text() + this.errorPromptSuffix)); // turn.text() + this.errorPromptSuffix));
context.getConversation().addTurn(new Conversation.Turn(
Conversation.TurnType.ASSISTANT,
csvResponse != null ? csvResponse : ""));
context.getConversation().addTurn(new Conversation.Turn(
Conversation.TurnType.USER,
this.errorPrompt));
} }
private String stripQuotes(final String value) { private String stripQuotes(final String value) {

View File

@@ -107,7 +107,7 @@ public class JsonAgentResponseHandler implements StreamedAgentResponseHandler {
} }
catch (final Exception e2) { catch (final Exception e2) {
LOGGER.warn("Cannot parse json response even after sanitization: {}", completion.response()); LOGGER.warn("Cannot parse json response even after sanitization: {}", completion.response());
addJsonResponseErrorPrompt(context); addJsonResponseErrorPrompt(context, completion.response());
return false; return false;
} }
} }
@@ -153,9 +153,15 @@ public class JsonAgentResponseHandler implements StreamedAgentResponseHandler {
} }
} }
private void addJsonResponseErrorPrompt(final AgentContext context) { private void addJsonResponseErrorPrompt(final AgentContext context, final String jsonResponse) {
final var turn = context.getConversation().getConversation().getLast(); // final var turn = context.getConversation().getConversation().getLast();
context.getConversation().replaceTurn(new Conversation.Turn(turn.type(), turn.text() + "\n\nThe previous response could not be fully processed or validated. Please make sure to format the response in valid JSON syntax with properly escaped characters.")); // context.getConversation().replaceTurn(new Conversation.Turn(turn.type(), turn.text() + "\n\nThe previous response could not be fully processed or validated. Please make sure to format the response in valid JSON structure with properly escaped characters."));
context.getConversation().addTurn(new Conversation.Turn(
Conversation.TurnType.ASSISTANT,
jsonResponse != null ? jsonResponse : ""));
context.getConversation().addTurn(new Conversation.Turn(
Conversation.TurnType.USER,
"The previous response could not be fully processed or validated. Please make sure to format the response in valid JSON structure with properly escaped characters."));
} }
private String sanitizeJson(final String json) { private String sanitizeJson(final String json) {