Add CsvAgentResponseHandler
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -4,7 +4,7 @@
|
||||
<artifactId>lm-lib</artifactId>
|
||||
<groupId>de.extio</groupId>
|
||||
<name>lm-lib</name>
|
||||
<version>1.9.2</version>
|
||||
<version>1.9.4</version>
|
||||
|
||||
<properties>
|
||||
<java.version>21</java.version>
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
package de.extio.lmlib.agent.responsehandler;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -20,68 +15,32 @@ public class CsvAgentResponseHandler implements AgentResponseHandler {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CsvAgentResponseHandler.class);
|
||||
|
||||
private final Class<?> targetClass;
|
||||
private final List<String> headings;
|
||||
|
||||
private final String contextKey;
|
||||
private final String keyPrefix;
|
||||
|
||||
private final String fieldSeparator;
|
||||
|
||||
private final String listSeparator;
|
||||
|
||||
private final Field[] fields;
|
||||
|
||||
private final List<String> fieldNames;
|
||||
|
||||
private final Constructor<?> constructor;
|
||||
|
||||
private final String fieldSeparatorQuoted;
|
||||
|
||||
private final String listSeparatorQuoted;
|
||||
|
||||
private final String errorPromptSuffix;
|
||||
|
||||
public CsvAgentResponseHandler(final Class<?> targetClass, final String contextKey) {
|
||||
this(targetClass, contextKey, ";", ",");
|
||||
public CsvAgentResponseHandler(final List<String> headings, final String keyPrefix) {
|
||||
this(headings, keyPrefix, ";");
|
||||
}
|
||||
|
||||
public CsvAgentResponseHandler(final Class<?> targetClass, final String contextKey,
|
||||
final String fieldSeparator, final String listSeparator) {
|
||||
this.targetClass = targetClass;
|
||||
this.contextKey = contextKey;
|
||||
public CsvAgentResponseHandler(final List<String> headings, final String keyPrefix, final String fieldSeparator) {
|
||||
if (headings == null || headings.isEmpty()) {
|
||||
throw new IllegalArgumentException("Headings list cannot be null or empty");
|
||||
}
|
||||
this.headings = List.copyOf(headings);
|
||||
this.keyPrefix = keyPrefix != null ? keyPrefix : "";
|
||||
this.fieldSeparator = fieldSeparator;
|
||||
this.listSeparator = listSeparator;
|
||||
|
||||
// Pre-compute static data
|
||||
this.fields = targetClass.getDeclaredFields();
|
||||
this.fieldNames = Arrays.stream(this.fields)
|
||||
.map(Field::getName)
|
||||
.toList();
|
||||
this.constructor = this.findRecordConstructor();
|
||||
if (this.constructor == null) {
|
||||
throw new IllegalStateException("No suitable constructor found for " + targetClass.getName());
|
||||
}
|
||||
this.fieldSeparatorQuoted = Pattern.quote(fieldSeparator);
|
||||
this.listSeparatorQuoted = (listSeparator != null && !listSeparator.isEmpty())
|
||||
? Pattern.quote(listSeparator)
|
||||
: null;
|
||||
|
||||
// Pre-compute error message suffix
|
||||
final String listInfo = (listSeparator != null && !listSeparator.isEmpty())
|
||||
? " and '" + listSeparator + "' for list items"
|
||||
: "";
|
||||
this.errorPromptSuffix = "\n\nThe previous response could not be fully processed or validated. " +
|
||||
"Please format the response as CSV with '" + fieldSeparator + "' as field separator" +
|
||||
listInfo + ". One object per line.";
|
||||
}
|
||||
|
||||
private Constructor<?> findRecordConstructor() {
|
||||
final Field[] targetFields = this.targetClass.getDeclaredFields();
|
||||
for (final Constructor<?> ctor : this.targetClass.getDeclaredConstructors()) {
|
||||
if (ctor.getParameterCount() == targetFields.length) {
|
||||
return ctor;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
"Please format the response as CSV with '" + fieldSeparator + "' as field separator. " +
|
||||
"Expected columns: " + String.join(", ", headings) + ". One row per line.";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,15 +52,13 @@ public class CsvAgentResponseHandler implements AgentResponseHandler {
|
||||
}
|
||||
|
||||
try {
|
||||
final List<Object> parsedObjects = this.parseCsv(resp);
|
||||
if (parsedObjects.isEmpty()) {
|
||||
final boolean success = this.parseCsv(resp, context);
|
||||
if (!success) {
|
||||
LOGGER.warn("No valid CSV data parsed from response");
|
||||
this.addCsvResponseErrorPrompt(context);
|
||||
return false;
|
||||
}
|
||||
|
||||
context.setValues(this.contextKey, parsedObjects);
|
||||
LOGGER.debug("Parsed {} CSV objects", parsedObjects.size());
|
||||
return true;
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
@@ -111,8 +68,7 @@ public class CsvAgentResponseHandler implements AgentResponseHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private List<Object> parseCsv(final String csvText) throws Exception {
|
||||
final List<Object> result = new ArrayList<>();
|
||||
private boolean parseCsv(final String csvText, final AgentContext context) {
|
||||
final String[] lines = csvText.split("\n");
|
||||
|
||||
int startLine = 0;
|
||||
@@ -131,8 +87,8 @@ public class CsvAgentResponseHandler implements AgentResponseHandler {
|
||||
|
||||
final String lowerLine = line.toLowerCase();
|
||||
boolean isHeader = false;
|
||||
for (final String fieldName : this.fieldNames) {
|
||||
if (lowerLine.contains(fieldName.toLowerCase())) {
|
||||
for (final String heading : this.headings) {
|
||||
if (lowerLine.contains(heading.toLowerCase())) {
|
||||
isHeader = true;
|
||||
break;
|
||||
}
|
||||
@@ -146,6 +102,12 @@ public class CsvAgentResponseHandler implements AgentResponseHandler {
|
||||
break;
|
||||
}
|
||||
|
||||
final List<List<String>> columnData = new ArrayList<>();
|
||||
for (int i = 0; i < this.headings.size(); i++) {
|
||||
columnData.add(new ArrayList<>());
|
||||
}
|
||||
|
||||
int rowCount = 0;
|
||||
for (int i = startLine; i < lines.length; i++) {
|
||||
final String line = lines[i].trim();
|
||||
|
||||
@@ -158,97 +120,36 @@ public class CsvAgentResponseHandler implements AgentResponseHandler {
|
||||
}
|
||||
|
||||
try {
|
||||
final Object obj = this.parseLine(line);
|
||||
if (obj != null) {
|
||||
result.add(obj);
|
||||
LOGGER.debug("Parsed CSV object: {}", obj);
|
||||
final String[] parts = line.split(this.fieldSeparatorQuoted, -1);
|
||||
if (parts.length != this.headings.size()) {
|
||||
LOGGER.debug("Column count mismatch: expected {}, got {} for line '{}'",
|
||||
this.headings.size(), parts.length, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int col = 0; col < parts.length; col++) {
|
||||
final String value = parts[col].trim();
|
||||
columnData.get(col).add(value);
|
||||
}
|
||||
rowCount++;
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
LOGGER.debug("Failed to parse line '{}': {}", line, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
if (rowCount == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private Object parseLine(final String line) throws Exception {
|
||||
final String[] parts = line.split(this.fieldSeparatorQuoted, -1);
|
||||
if (parts.length != this.fields.length) {
|
||||
LOGGER.debug("Field count mismatch: expected {}, got {} for line '{}'",
|
||||
this.fields.length, parts.length, line);
|
||||
return null;
|
||||
for (int i = 0; i < this.headings.size(); i++) {
|
||||
final String key = this.keyPrefix + this.headings.get(i);
|
||||
context.setStringValues(key, columnData.get(i));
|
||||
LOGGER.debug("Stored {} values in context key '{}'", columnData.get(i).size(), key);
|
||||
}
|
||||
|
||||
final Object[] args = new Object[this.fields.length];
|
||||
|
||||
for (int i = 0; i < this.fields.length; i++) {
|
||||
final String value = parts[i].trim();
|
||||
args[i] = this.parseValue(value, this.fields[i]);
|
||||
}
|
||||
|
||||
return this.constructor.newInstance(args);
|
||||
}
|
||||
|
||||
private Object parseValue(final String value, final Field field) {
|
||||
final Class<?> fieldType = field.getType();
|
||||
|
||||
if (value.isEmpty() || value.equalsIgnoreCase("null")) {
|
||||
if (fieldType == List.class) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (fieldType == String.class) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (fieldType == Integer.class || fieldType == int.class) {
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
|
||||
if (fieldType == Long.class || fieldType == long.class) {
|
||||
return Long.parseLong(value);
|
||||
}
|
||||
|
||||
if (fieldType == Double.class || fieldType == double.class) {
|
||||
return Double.parseDouble(value);
|
||||
}
|
||||
|
||||
if (fieldType == Boolean.class || fieldType == boolean.class) {
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
if (fieldType == List.class) {
|
||||
if (this.listSeparatorQuoted == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
final Type genericType = field.getGenericType();
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
final ParameterizedType paramType = (ParameterizedType) genericType;
|
||||
final Type[] typeArgs = paramType.getActualTypeArguments();
|
||||
|
||||
if (typeArgs.length > 0 && typeArgs[0] == String.class) {
|
||||
if (value.isEmpty()) {
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
|
||||
final String[] items = value.split(this.listSeparatorQuoted);
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (final String item : items) {
|
||||
final String trimmed = item.trim();
|
||||
if (!trimmed.isEmpty()) {
|
||||
list.add(trimmed);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unsupported field type: " + fieldType.getName());
|
||||
LOGGER.debug("Parsed {} CSV rows into {} columns", rowCount, this.headings.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addCsvResponseErrorPrompt(final AgentContext context) {
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
package de.extio.lmlib.agent.responsehandler;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.extio.lmlib.agent.AgentContext;
|
||||
import de.extio.lmlib.client.Completion;
|
||||
import de.extio.lmlib.client.Conversation;
|
||||
|
||||
public class CsvUnmarshallingAgentResponseHandler implements AgentResponseHandler {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CsvUnmarshallingAgentResponseHandler.class);
|
||||
|
||||
private final Class<?> targetClass;
|
||||
|
||||
private final String contextKey;
|
||||
|
||||
private final String fieldSeparator;
|
||||
|
||||
private final String listSeparator;
|
||||
|
||||
private final Field[] fields;
|
||||
|
||||
private final List<String> fieldNames;
|
||||
|
||||
private final Constructor<?> constructor;
|
||||
|
||||
private final String fieldSeparatorQuoted;
|
||||
|
||||
private final String listSeparatorQuoted;
|
||||
|
||||
private final String errorPromptSuffix;
|
||||
|
||||
public CsvUnmarshallingAgentResponseHandler(final Class<?> targetClass, final String contextKey) {
|
||||
this(targetClass, contextKey, ";", ",");
|
||||
}
|
||||
|
||||
public CsvUnmarshallingAgentResponseHandler(final Class<?> targetClass, final String contextKey,
|
||||
final String fieldSeparator, final String listSeparator) {
|
||||
this.targetClass = targetClass;
|
||||
this.contextKey = contextKey;
|
||||
this.fieldSeparator = fieldSeparator;
|
||||
this.listSeparator = listSeparator;
|
||||
|
||||
// Pre-compute static data
|
||||
this.fields = targetClass.getDeclaredFields();
|
||||
this.fieldNames = Arrays.stream(this.fields)
|
||||
.map(Field::getName)
|
||||
.toList();
|
||||
this.constructor = this.findRecordConstructor();
|
||||
if (this.constructor == null) {
|
||||
throw new IllegalStateException("No suitable constructor found for " + targetClass.getName());
|
||||
}
|
||||
this.fieldSeparatorQuoted = Pattern.quote(fieldSeparator);
|
||||
this.listSeparatorQuoted = (listSeparator != null && !listSeparator.isEmpty())
|
||||
? Pattern.quote(listSeparator)
|
||||
: null;
|
||||
|
||||
// Pre-compute error message suffix
|
||||
final String listInfo = (listSeparator != null && !listSeparator.isEmpty())
|
||||
? " and '" + listSeparator + "' for list items"
|
||||
: "";
|
||||
this.errorPromptSuffix = "\n\nThe previous response could not be fully processed or validated. " +
|
||||
"Please format the response as CSV with '" + fieldSeparator + "' as field separator" +
|
||||
listInfo + ". One object per line.";
|
||||
}
|
||||
|
||||
private Constructor<?> findRecordConstructor() {
|
||||
final Field[] targetFields = this.targetClass.getDeclaredFields();
|
||||
for (final Constructor<?> ctor : this.targetClass.getDeclaredConstructors()) {
|
||||
if (ctor.getParameterCount() == targetFields.length) {
|
||||
return ctor;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(final Completion completion, final AgentContext context) {
|
||||
final String resp = completion.response();
|
||||
if (resp == null || resp.isBlank()) {
|
||||
LOGGER.warn("Empty completion response for CSV parsing");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
final List<Object> parsedObjects = this.parseCsv(resp);
|
||||
if (parsedObjects.isEmpty()) {
|
||||
LOGGER.warn("No valid CSV data parsed from response");
|
||||
this.addCsvResponseErrorPrompt(context);
|
||||
return false;
|
||||
}
|
||||
|
||||
context.setValues(this.contextKey, parsedObjects);
|
||||
LOGGER.debug("Parsed {} CSV objects", parsedObjects.size());
|
||||
return true;
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
LOGGER.warn("Failed to parse CSV response", ex);
|
||||
this.addCsvResponseErrorPrompt(context);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Object> parseCsv(final String csvText) throws Exception {
|
||||
final List<Object> result = new ArrayList<>();
|
||||
final String[] lines = csvText.split("\n");
|
||||
|
||||
int startLine = 0;
|
||||
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
final String line = lines[i].trim();
|
||||
|
||||
if (line.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!line.contains(this.fieldSeparator)) {
|
||||
startLine = i + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
final String lowerLine = line.toLowerCase();
|
||||
boolean isHeader = false;
|
||||
for (final String fieldName : this.fieldNames) {
|
||||
if (lowerLine.contains(fieldName.toLowerCase())) {
|
||||
isHeader = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isHeader) {
|
||||
startLine = i + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = startLine; i < lines.length; i++) {
|
||||
final String line = lines[i].trim();
|
||||
|
||||
if (line.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!line.contains(this.fieldSeparator)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
final Object obj = this.parseLine(line);
|
||||
if (obj != null) {
|
||||
result.add(obj);
|
||||
LOGGER.debug("Parsed CSV object: {}", obj);
|
||||
}
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
LOGGER.debug("Failed to parse line '{}': {}", line, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Object parseLine(final String line) throws Exception {
|
||||
final String[] parts = line.split(this.fieldSeparatorQuoted, -1);
|
||||
if (parts.length != this.fields.length) {
|
||||
LOGGER.debug("Field count mismatch: expected {}, got {} for line '{}'",
|
||||
this.fields.length, parts.length, line);
|
||||
return null;
|
||||
}
|
||||
|
||||
final Object[] args = new Object[this.fields.length];
|
||||
|
||||
for (int i = 0; i < this.fields.length; i++) {
|
||||
final String value = parts[i].trim();
|
||||
args[i] = this.parseValue(value, this.fields[i]);
|
||||
}
|
||||
|
||||
return this.constructor.newInstance(args);
|
||||
}
|
||||
|
||||
private Object parseValue(final String value, final Field field) {
|
||||
final Class<?> fieldType = field.getType();
|
||||
|
||||
if (value.isEmpty() || value.equalsIgnoreCase("null")) {
|
||||
if (fieldType == List.class) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (fieldType == String.class) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (fieldType == Integer.class || fieldType == int.class) {
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
|
||||
if (fieldType == Long.class || fieldType == long.class) {
|
||||
return Long.parseLong(value);
|
||||
}
|
||||
|
||||
if (fieldType == Double.class || fieldType == double.class) {
|
||||
return Double.parseDouble(value);
|
||||
}
|
||||
|
||||
if (fieldType == Boolean.class || fieldType == boolean.class) {
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
if (fieldType == List.class) {
|
||||
if (this.listSeparatorQuoted == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
final Type genericType = field.getGenericType();
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
final ParameterizedType paramType = (ParameterizedType) genericType;
|
||||
final Type[] typeArgs = paramType.getActualTypeArguments();
|
||||
|
||||
if (typeArgs.length > 0 && typeArgs[0] == String.class) {
|
||||
if (value.isEmpty()) {
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
|
||||
final String[] items = value.split(this.listSeparatorQuoted);
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (final String item : items) {
|
||||
final String trimmed = item.trim();
|
||||
if (!trimmed.isEmpty()) {
|
||||
list.add(trimmed);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unsupported field type: " + fieldType.getName());
|
||||
}
|
||||
|
||||
private void addCsvResponseErrorPrompt(final AgentContext context) {
|
||||
final var turn = context.getConversation().getConversation().getLast();
|
||||
context.getConversation().replaceTurn(new Conversation.Turn(
|
||||
turn.type(),
|
||||
turn.text() + this.errorPromptSuffix));
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package de.extio.lmlib.agent.responsehandler;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
@@ -14,19 +16,15 @@ import de.extio.lmlib.client.Conversation;
|
||||
|
||||
public class CsvAgentResponseHandlerTest {
|
||||
|
||||
public static record TestObject(String name, List<String> tags, Integer value) {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleCsvParsing() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(TestObject.class, "_test_");
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "xy_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
item1;tag1,tag2;42
|
||||
item2;tag3;100
|
||||
item3;;50
|
||||
1;2;3
|
||||
4;5;6
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
@@ -34,32 +32,30 @@ public class CsvAgentResponseHandlerTest {
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||
assertEquals(3, objects.size());
|
||||
final List<String> aValues = context.getStringValues("xy_a");
|
||||
final List<String> bValues = context.getStringValues("xy_b");
|
||||
final List<String> cValues = context.getStringValues("xy_c");
|
||||
|
||||
assertEquals("item1", objects.get(0).name());
|
||||
assertEquals(List.of("tag1", "tag2"), objects.get(0).tags());
|
||||
assertEquals(42, objects.get(0).value());
|
||||
assertNotNull(aValues);
|
||||
assertNotNull(bValues);
|
||||
assertNotNull(cValues);
|
||||
|
||||
assertEquals("item2", objects.get(1).name());
|
||||
assertEquals(List.of("tag3"), objects.get(1).tags());
|
||||
assertEquals(100, objects.get(1).value());
|
||||
|
||||
assertEquals("item3", objects.get(2).name());
|
||||
assertTrue(objects.get(2).tags().isEmpty());
|
||||
assertEquals(50, objects.get(2).value());
|
||||
assertEquals(List.of("1", "4"), aValues);
|
||||
assertEquals(List.of("2", "5"), bValues);
|
||||
assertEquals(List.of("3", "6"), cValues);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCsvWithHeader() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(TestObject.class, "_test_");
|
||||
public void testWithHeader() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("name", "age", "city"), "person_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
name;tags;value
|
||||
item1;tag1,tag2;42
|
||||
item2;tag3;100
|
||||
name;age;city
|
||||
Alice;30;Berlin
|
||||
Bob;25;Munich
|
||||
Charlie;35;Hamburg
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
@@ -67,24 +63,24 @@ public class CsvAgentResponseHandlerTest {
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||
assertEquals(2, objects.size());
|
||||
final List<String> names = context.getStringValues("person_name");
|
||||
final List<String> ages = context.getStringValues("person_age");
|
||||
final List<String> cities = context.getStringValues("person_city");
|
||||
|
||||
assertEquals("item1", objects.get(0).name());
|
||||
assertEquals("item2", objects.get(1).name());
|
||||
assertEquals(List.of("Alice", "Bob", "Charlie"), names);
|
||||
assertEquals(List.of("30", "25", "35"), ages);
|
||||
assertEquals(List.of("Berlin", "Munich", "Hamburg"), cities);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCsvWithPreamble() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(TestObject.class, "_test_");
|
||||
public void testWithEmptyPrefix() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("x", "y"), "");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
Here is the result:
|
||||
|
||||
item1;tag1,tag2;42
|
||||
item2;tag3;100
|
||||
10;20
|
||||
30;40
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
@@ -92,23 +88,19 @@ public class CsvAgentResponseHandlerTest {
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||
assertEquals(2, objects.size());
|
||||
assertEquals(List.of("10", "30"), context.getStringValues("x"));
|
||||
assertEquals(List.of("20", "40"), context.getStringValues("y"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCsvWithHeaderAndPreamble() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(TestObject.class, "_test_");
|
||||
public void testWithNullPrefix() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("col1", "col2"), null);
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
Here are the results in CSV format:
|
||||
|
||||
name;tags;value
|
||||
item1;tag1,tag2;42
|
||||
item2;tag3;100
|
||||
item3;;50
|
||||
a;b
|
||||
c;d
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
@@ -116,26 +108,22 @@ public class CsvAgentResponseHandlerTest {
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||
assertEquals(3, objects.size());
|
||||
|
||||
assertEquals("item1", objects.get(0).name());
|
||||
assertEquals(List.of("tag1", "tag2"), objects.get(0).tags());
|
||||
assertEquals(42, objects.get(0).value());
|
||||
assertEquals(List.of("a", "c"), context.getStringValues("col1"));
|
||||
assertEquals(List.of("b", "d"), context.getStringValues("col2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCsvWithEmptyLines() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(TestObject.class, "_test_");
|
||||
public void testWithExtraTextBeforeData() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "test_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
Here is the CSV data:
|
||||
|
||||
item1;tag1,tag2;42
|
||||
|
||||
item2;tag3;100
|
||||
|
||||
a;b;c
|
||||
1;2;3
|
||||
4;5;6
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
@@ -143,19 +131,23 @@ public class CsvAgentResponseHandlerTest {
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||
assertEquals(2, objects.size());
|
||||
assertEquals(List.of("1", "4"), context.getStringValues("test_a"));
|
||||
assertEquals(List.of("2", "5"), context.getStringValues("test_b"));
|
||||
assertEquals(List.of("3", "6"), context.getStringValues("test_c"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCsvWithNullValues() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(TestObject.class, "_test_");
|
||||
public void testWithEmptyLines() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b"), "data_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
item1;tag1,tag2;
|
||||
item2;;100
|
||||
1;2
|
||||
|
||||
3;4
|
||||
|
||||
5;6
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
@@ -163,31 +155,19 @@ public class CsvAgentResponseHandlerTest {
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||
assertEquals(2, objects.size());
|
||||
|
||||
assertEquals("item1", objects.get(0).name());
|
||||
assertNotNull(objects.get(0).tags());
|
||||
assertEquals(null, objects.get(0).value());
|
||||
|
||||
assertEquals("item2", objects.get(1).name());
|
||||
assertTrue(objects.get(1).tags().isEmpty());
|
||||
assertEquals(100, objects.get(1).value());
|
||||
}
|
||||
|
||||
public static record TagObject(String tag, List<String> aliases, Integer importance) {
|
||||
assertEquals(List.of("1", "3", "5"), context.getStringValues("data_a"));
|
||||
assertEquals(List.of("2", "4", "6"), context.getStringValues("data_b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTagObjectExample() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(TagObject.class, "_tag_");
|
||||
public void testWithWhitespace() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "ws_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
location_dark_forest;location_forest,location_shadow_woods;25
|
||||
location_ancient_shrine;location_shrine,location_vine_shrine;65
|
||||
combat_dragon;combat_wyrm,combat_ancient_dragon;65
|
||||
1 ; 2 ; 3
|
||||
4 ; 5 ; 6
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
@@ -195,28 +175,20 @@ public class CsvAgentResponseHandlerTest {
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TagObject> objects = context.getValues("_tag_", TagObject.class);
|
||||
assertEquals(3, objects.size());
|
||||
|
||||
assertEquals("location_dark_forest", objects.get(0).tag());
|
||||
assertEquals(List.of("location_forest", "location_shadow_woods"), objects.get(0).aliases());
|
||||
assertEquals(25, objects.get(0).importance());
|
||||
|
||||
assertEquals("combat_dragon", objects.get(2).tag());
|
||||
assertEquals(List.of("combat_wyrm", "combat_ancient_dragon"), objects.get(2).aliases());
|
||||
assertEquals(65, objects.get(2).importance());
|
||||
assertEquals(List.of("1", "4"), context.getStringValues("ws_a"));
|
||||
assertEquals(List.of("2", "5"), context.getStringValues("ws_b"));
|
||||
assertEquals(List.of("3", "6"), context.getStringValues("ws_c"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomSeparators() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(
|
||||
TagObject.class, "_custom_", "|", ":");
|
||||
public void testWithCustomSeparator() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "custom_", ",");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
location_dark_forest|location_forest:location_shadow_woods|25
|
||||
location_ancient_shrine|location_shrine:location_vine_shrine|65
|
||||
1,2,3
|
||||
4,5,6
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
@@ -224,24 +196,21 @@ public class CsvAgentResponseHandlerTest {
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TagObject> objects = context.getValues("_custom_", TagObject.class);
|
||||
assertEquals(2, objects.size());
|
||||
|
||||
assertEquals("location_dark_forest", objects.get(0).tag());
|
||||
assertEquals(List.of("location_forest", "location_shadow_woods"), objects.get(0).aliases());
|
||||
assertEquals(25, objects.get(0).importance());
|
||||
assertEquals(List.of("1", "4"), context.getStringValues("custom_a"));
|
||||
assertEquals(List.of("2", "5"), context.getStringValues("custom_b"));
|
||||
assertEquals(List.of("3", "6"), context.getStringValues("custom_c"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoListSeparator() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(
|
||||
TestObject.class, "_nolist_", ";", null);
|
||||
public void testColumnCountMismatch() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "mismatch_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
item1;tag1,tag2,tag3;42
|
||||
item2;ignored;100
|
||||
1;2;3
|
||||
4;5
|
||||
7;8;9
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
@@ -249,15 +218,105 @@ public class CsvAgentResponseHandlerTest {
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_nolist_", TestObject.class);
|
||||
assertEquals(2, objects.size());
|
||||
// Only rows with correct column count should be included
|
||||
assertEquals(List.of("1", "7"), context.getStringValues("mismatch_a"));
|
||||
assertEquals(List.of("2", "8"), context.getStringValues("mismatch_b"));
|
||||
assertEquals(List.of("3", "9"), context.getStringValues("mismatch_c"));
|
||||
}
|
||||
|
||||
assertEquals("item1", objects.get(0).name());
|
||||
assertTrue(objects.get(0).tags().isEmpty());
|
||||
assertEquals(42, objects.get(0).value());
|
||||
@Test
|
||||
public void testEmptyResponse() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b"), "empty_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
assertEquals("item2", objects.get(1).name());
|
||||
assertTrue(objects.get(1).tags().isEmpty());
|
||||
assertEquals(100, objects.get(1).value());
|
||||
final Completion completion = new Completion("", null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullResponse() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b"), "null_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final Completion completion = new Completion(null, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoValidData() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b"), "nodata_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
This is just text
|
||||
without any valid CSV data
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleRow() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("x", "y", "z"), "single_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = "100;200;300";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
assertEquals(List.of("100"), context.getStringValues("single_x"));
|
||||
assertEquals(List.of("200"), context.getStringValues("single_y"));
|
||||
assertEquals(List.of("300"), context.getStringValues("single_z"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleHeaders() {
|
||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("id", "value"), "multi_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
id;value
|
||||
ID;VALUE
|
||||
1;100
|
||||
2;200
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
// Should skip both header rows
|
||||
assertEquals(List.of("1", "2"), context.getStringValues("multi_id"));
|
||||
assertEquals(List.of("100", "200"), context.getStringValues("multi_value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullHeadingsList() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
new CsvAgentResponseHandler(null, "prefix_");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyHeadingsList() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
new CsvAgentResponseHandler(List.of(), "prefix_");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
package de.extio.lmlib.agent.responsehandler;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import de.extio.lmlib.agent.AgentContext;
|
||||
import de.extio.lmlib.client.Completion;
|
||||
import de.extio.lmlib.client.Conversation;
|
||||
|
||||
public class CsvUnmarshallingAgentResponseHandlerTest {
|
||||
|
||||
public static record TestObject(String name, List<String> tags, Integer value) {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleCsvParsing() {
|
||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
item1;tag1,tag2;42
|
||||
item2;tag3;100
|
||||
item3;;50
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||
assertEquals(3, objects.size());
|
||||
|
||||
assertEquals("item1", objects.get(0).name());
|
||||
assertEquals(List.of("tag1", "tag2"), objects.get(0).tags());
|
||||
assertEquals(42, objects.get(0).value());
|
||||
|
||||
assertEquals("item2", objects.get(1).name());
|
||||
assertEquals(List.of("tag3"), objects.get(1).tags());
|
||||
assertEquals(100, objects.get(1).value());
|
||||
|
||||
assertEquals("item3", objects.get(2).name());
|
||||
assertTrue(objects.get(2).tags().isEmpty());
|
||||
assertEquals(50, objects.get(2).value());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCsvWithHeader() {
|
||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
name;tags;value
|
||||
item1;tag1,tag2;42
|
||||
item2;tag3;100
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||
assertEquals(2, objects.size());
|
||||
|
||||
assertEquals("item1", objects.get(0).name());
|
||||
assertEquals("item2", objects.get(1).name());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCsvWithPreamble() {
|
||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
Here is the result:
|
||||
|
||||
item1;tag1,tag2;42
|
||||
item2;tag3;100
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||
assertEquals(2, objects.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCsvWithHeaderAndPreamble() {
|
||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
Here are the results in CSV format:
|
||||
|
||||
name;tags;value
|
||||
item1;tag1,tag2;42
|
||||
item2;tag3;100
|
||||
item3;;50
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||
assertEquals(3, objects.size());
|
||||
|
||||
assertEquals("item1", objects.get(0).name());
|
||||
assertEquals(List.of("tag1", "tag2"), objects.get(0).tags());
|
||||
assertEquals(42, objects.get(0).value());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCsvWithEmptyLines() {
|
||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
|
||||
item1;tag1,tag2;42
|
||||
|
||||
item2;tag3;100
|
||||
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||
assertEquals(2, objects.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCsvWithNullValues() {
|
||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
item1;tag1,tag2;
|
||||
item2;;100
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||
assertEquals(2, objects.size());
|
||||
|
||||
assertEquals("item1", objects.get(0).name());
|
||||
assertNotNull(objects.get(0).tags());
|
||||
assertEquals(null, objects.get(0).value());
|
||||
|
||||
assertEquals("item2", objects.get(1).name());
|
||||
assertTrue(objects.get(1).tags().isEmpty());
|
||||
assertEquals(100, objects.get(1).value());
|
||||
}
|
||||
|
||||
public static record TagObject(String tag, List<String> aliases, Integer importance) {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTagObjectExample() {
|
||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TagObject.class, "_tag_");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
location_dark_forest;location_forest,location_shadow_woods;25
|
||||
location_ancient_shrine;location_shrine,location_vine_shrine;65
|
||||
combat_dragon;combat_wyrm,combat_ancient_dragon;65
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TagObject> objects = context.getValues("_tag_", TagObject.class);
|
||||
assertEquals(3, objects.size());
|
||||
|
||||
assertEquals("location_dark_forest", objects.get(0).tag());
|
||||
assertEquals(List.of("location_forest", "location_shadow_woods"), objects.get(0).aliases());
|
||||
assertEquals(25, objects.get(0).importance());
|
||||
|
||||
assertEquals("combat_dragon", objects.get(2).tag());
|
||||
assertEquals(List.of("combat_wyrm", "combat_ancient_dragon"), objects.get(2).aliases());
|
||||
assertEquals(65, objects.get(2).importance());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomSeparators() {
|
||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(
|
||||
TagObject.class, "_custom_", "|", ":");
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
location_dark_forest|location_forest:location_shadow_woods|25
|
||||
location_ancient_shrine|location_shrine:location_vine_shrine|65
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TagObject> objects = context.getValues("_custom_", TagObject.class);
|
||||
assertEquals(2, objects.size());
|
||||
|
||||
assertEquals("location_dark_forest", objects.get(0).tag());
|
||||
assertEquals(List.of("location_forest", "location_shadow_woods"), objects.get(0).aliases());
|
||||
assertEquals(25, objects.get(0).importance());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoListSeparator() {
|
||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(
|
||||
TestObject.class, "_nolist_", ";", null);
|
||||
final AgentContext context = new AgentContext();
|
||||
context.setConversation(Conversation.create("test"));
|
||||
|
||||
final String csvResponse = """
|
||||
item1;tag1,tag2,tag3;42
|
||||
item2;ignored;100
|
||||
""";
|
||||
|
||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||
final boolean result = handler.handle(completion, context);
|
||||
|
||||
assertTrue(result);
|
||||
|
||||
final List<TestObject> objects = context.getValues("_nolist_", TestObject.class);
|
||||
assertEquals(2, objects.size());
|
||||
|
||||
assertEquals("item1", objects.get(0).name());
|
||||
assertTrue(objects.get(0).tags().isEmpty());
|
||||
assertEquals(42, objects.get(0).value());
|
||||
|
||||
assertEquals("item2", objects.get(1).name());
|
||||
assertTrue(objects.get(1).tags().isEmpty());
|
||||
assertEquals(100, objects.get(1).value());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user