Convert spaces to tabs
This commit is contained in:
@@ -9,89 +9,89 @@ import de.extio.lmlib.profile.ModelCategory;
|
|||||||
import de.extio.lmlib.profile.ModelProfile;
|
import de.extio.lmlib.profile.ModelProfile;
|
||||||
|
|
||||||
public record Agent(String name,
|
public record Agent(String name,
|
||||||
AgentType agentType,
|
AgentType agentType,
|
||||||
ModelCategory modelCategory,
|
ModelCategory modelCategory,
|
||||||
ModelProfile modelProfile,
|
ModelProfile modelProfile,
|
||||||
String systemPrompt,
|
String systemPrompt,
|
||||||
String textTemplate,
|
String textTemplate,
|
||||||
AgentResponseHandler responseHandler,
|
AgentResponseHandler responseHandler,
|
||||||
Consumer<AgentContext> preProcessor,
|
Consumer<AgentContext> preProcessor,
|
||||||
Consumer<AgentContext> postProcessor,
|
Consumer<AgentContext> postProcessor,
|
||||||
Function<List<AgentContext>,
|
Function<List<AgentContext>,
|
||||||
List<AgentContext>> merger,
|
List<AgentContext>> merger,
|
||||||
Function<AgentContext, AgentNext> chooseNext) implements BaseAgent {
|
Function<AgentContext, AgentNext> chooseNext) implements BaseAgent {
|
||||||
|
|
||||||
public Agent {
|
public Agent {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
throw new IllegalArgumentException("Name cannot be null");
|
throw new IllegalArgumentException("Name cannot be null");
|
||||||
}
|
}
|
||||||
if (agentType == null) {
|
if (agentType == null) {
|
||||||
throw new IllegalArgumentException("Agent type cannot be null");
|
throw new IllegalArgumentException("Agent type cannot be null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AgentType agentType(final AgentContext context) {
|
public AgentType agentType(final AgentContext context) {
|
||||||
if (agentType != null) {
|
if (agentType != null) {
|
||||||
return agentType;
|
return agentType;
|
||||||
}
|
}
|
||||||
return BaseAgent.super.agentType(context);
|
return BaseAgent.super.agentType(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModelCategory modelCategory(final AgentContext context) {
|
public ModelCategory modelCategory(final AgentContext context) {
|
||||||
if (modelCategory != null) {
|
if (modelCategory != null) {
|
||||||
return modelCategory;
|
return modelCategory;
|
||||||
}
|
}
|
||||||
return BaseAgent.super.modelCategory(context);
|
return BaseAgent.super.modelCategory(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModelProfile modelProfile(final AgentContext context) {
|
public ModelProfile modelProfile(final AgentContext context) {
|
||||||
if (modelProfile != null) {
|
if (modelProfile != null) {
|
||||||
return modelProfile;
|
return modelProfile;
|
||||||
}
|
}
|
||||||
return BaseAgent.super.modelProfile(context);
|
return BaseAgent.super.modelProfile(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AgentResponseHandler responseHandler(final AgentContext context) {
|
public AgentResponseHandler responseHandler(final AgentContext context) {
|
||||||
if (responseHandler != null) {
|
if (responseHandler != null) {
|
||||||
return responseHandler;
|
return responseHandler;
|
||||||
}
|
}
|
||||||
return BaseAgent.super.responseHandler(context);
|
return BaseAgent.super.responseHandler(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preProcess(final AgentContext context) {
|
public void preProcess(final AgentContext context) {
|
||||||
if (preProcessor != null) {
|
if (preProcessor != null) {
|
||||||
preProcessor.accept(context);
|
preProcessor.accept(context);
|
||||||
}
|
}
|
||||||
BaseAgent.super.preProcess(context);
|
BaseAgent.super.preProcess(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postProcess(final AgentContext context) {
|
public void postProcess(final AgentContext context) {
|
||||||
if (postProcessor != null) {
|
if (postProcessor != null) {
|
||||||
postProcessor.accept(context);
|
postProcessor.accept(context);
|
||||||
}
|
}
|
||||||
BaseAgent.super.postProcess(context);
|
BaseAgent.super.postProcess(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AgentContext> merge(final List<AgentContext> contexts) {
|
public List<AgentContext> merge(final List<AgentContext> contexts) {
|
||||||
if (merger != null) {
|
if (merger != null) {
|
||||||
return merger.apply(contexts);
|
return merger.apply(contexts);
|
||||||
}
|
}
|
||||||
return BaseAgent.super.merge(contexts);
|
return BaseAgent.super.merge(contexts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AgentNext chooseNextAgent(final AgentContext context) {
|
public AgentNext chooseNextAgent(final AgentContext context) {
|
||||||
if (chooseNext != null) {
|
if (chooseNext != null) {
|
||||||
return chooseNext.apply(context);
|
return chooseNext.apply(context);
|
||||||
}
|
}
|
||||||
return BaseAgent.super.chooseNextAgent(context);
|
return BaseAgent.super.chooseNextAgent(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ package de.extio.lmlib.agent;
|
|||||||
|
|
||||||
public final record AgentNext(String name, Boolean gradingPassed) {
|
public final record AgentNext(String name, Boolean gradingPassed) {
|
||||||
|
|
||||||
public static final AgentNext END = new AgentNext(null, null);
|
public static final AgentNext END = new AgentNext(null, null);
|
||||||
|
|
||||||
public static AgentNext end(final AgentContext context) {
|
public static AgentNext end(final AgentContext context) {
|
||||||
return END;
|
return END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,164 +13,164 @@ import de.extio.lmlib.client.Conversation;
|
|||||||
|
|
||||||
public class CsvAgentResponseHandler implements AgentResponseHandler {
|
public class CsvAgentResponseHandler implements AgentResponseHandler {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(CsvAgentResponseHandler.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(CsvAgentResponseHandler.class);
|
||||||
|
|
||||||
private final List<String> headings;
|
private final List<String> headings;
|
||||||
|
|
||||||
private final String keyPrefix;
|
private final String keyPrefix;
|
||||||
|
|
||||||
private final String fieldSeparator;
|
private final String fieldSeparator;
|
||||||
|
|
||||||
private final String fieldSeparatorQuoted;
|
private final String fieldSeparatorQuoted;
|
||||||
|
|
||||||
private final String errorPromptSuffix;
|
private final String errorPromptSuffix;
|
||||||
|
|
||||||
public CsvAgentResponseHandler(final List<String> headings, final String keyPrefix) {
|
public CsvAgentResponseHandler(final List<String> headings, final String keyPrefix) {
|
||||||
this(headings, keyPrefix, ";");
|
this(headings, keyPrefix, ";");
|
||||||
}
|
}
|
||||||
|
|
||||||
public CsvAgentResponseHandler(final List<String> headings, final String keyPrefix, final String fieldSeparator) {
|
public CsvAgentResponseHandler(final List<String> headings, final String keyPrefix, final String fieldSeparator) {
|
||||||
if (headings == null || headings.isEmpty()) {
|
if (headings == null || headings.isEmpty()) {
|
||||||
throw new IllegalArgumentException("Headings list cannot be null or empty");
|
throw new IllegalArgumentException("Headings list cannot be null or empty");
|
||||||
}
|
}
|
||||||
this.headings = List.copyOf(headings);
|
this.headings = List.copyOf(headings);
|
||||||
this.keyPrefix = keyPrefix != null ? keyPrefix : "";
|
this.keyPrefix = keyPrefix != null ? keyPrefix : "";
|
||||||
this.fieldSeparator = fieldSeparator;
|
this.fieldSeparator = fieldSeparator;
|
||||||
this.fieldSeparatorQuoted = Pattern.quote(fieldSeparator);
|
this.fieldSeparatorQuoted = Pattern.quote(fieldSeparator);
|
||||||
|
|
||||||
this.errorPromptSuffix = "\n\nThe previous response could not be fully processed or validated. " +
|
this.errorPromptSuffix = "\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. " +
|
||||||
"Expected columns: " + String.join(", ", headings) + ". One row per line.";
|
"Expected columns: " + String.join(", ", headings) + ". One row per line.";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handle(final Completion completion, final AgentContext context) {
|
public boolean handle(final Completion completion, final AgentContext context) {
|
||||||
final String resp = completion.response();
|
final String resp = completion.response();
|
||||||
if (resp == null || resp.isBlank()) {
|
if (resp == null || resp.isBlank()) {
|
||||||
LOGGER.warn("Empty completion response for CSV parsing");
|
LOGGER.warn("Empty completion response for CSV parsing");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
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);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
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);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean parseCsv(final String csvText, final AgentContext context) {
|
private boolean parseCsv(final String csvText, final AgentContext context) {
|
||||||
final String[] lines = csvText.split("\n");
|
final String[] lines = csvText.split("\n");
|
||||||
|
|
||||||
int startLine = 0;
|
int startLine = 0;
|
||||||
|
|
||||||
for (int i = 0; i < lines.length; i++) {
|
for (int i = 0; i < lines.length; i++) {
|
||||||
final String line = lines[i].trim();
|
final String line = lines[i].trim();
|
||||||
|
|
||||||
if (line.isEmpty()) {
|
if (line.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!line.contains(this.fieldSeparator)) {
|
if (!line.contains(this.fieldSeparator)) {
|
||||||
startLine = i + 1;
|
startLine = i + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String lowerLine = line.toLowerCase();
|
final String lowerLine = line.toLowerCase();
|
||||||
boolean isHeader = false;
|
boolean isHeader = false;
|
||||||
for (final String heading : this.headings) {
|
for (final String heading : this.headings) {
|
||||||
if (lowerLine.contains(heading.toLowerCase())) {
|
if (lowerLine.contains(heading.toLowerCase())) {
|
||||||
isHeader = true;
|
isHeader = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isHeader) {
|
if (isHeader) {
|
||||||
startLine = i + 1;
|
startLine = i + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<List<String>> columnData = new ArrayList<>();
|
final List<List<String>> columnData = new ArrayList<>();
|
||||||
for (int i = 0; i < this.headings.size(); i++) {
|
for (int i = 0; i < this.headings.size(); i++) {
|
||||||
columnData.add(new ArrayList<>());
|
columnData.add(new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
int rowCount = 0;
|
int rowCount = 0;
|
||||||
for (int i = startLine; i < lines.length; i++) {
|
for (int i = startLine; i < lines.length; i++) {
|
||||||
final String line = lines[i].trim();
|
final String line = lines[i].trim();
|
||||||
|
|
||||||
if (line.isEmpty()) {
|
if (line.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!line.contains(this.fieldSeparator)) {
|
if (!line.contains(this.fieldSeparator)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final String[] parts = line.split(this.fieldSeparatorQuoted, -1);
|
final String[] parts = line.split(this.fieldSeparatorQuoted, -1);
|
||||||
if (parts.length != this.headings.size()) {
|
if (parts.length != this.headings.size()) {
|
||||||
LOGGER.debug("Column count mismatch: expected {}, got {} for line '{}'",
|
LOGGER.debug("Column count mismatch: expected {}, got {} for line '{}'",
|
||||||
this.headings.size(), parts.length, line);
|
this.headings.size(), parts.length, line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int col = 0; col < parts.length; col++) {
|
for (int col = 0; col < parts.length; col++) {
|
||||||
final String value = this.stripQuotes(parts[col].trim());
|
final String value = this.stripQuotes(parts[col].trim());
|
||||||
columnData.get(col).add(value);
|
columnData.get(col).add(value);
|
||||||
}
|
}
|
||||||
rowCount++;
|
rowCount++;
|
||||||
}
|
}
|
||||||
catch (final Exception ex) {
|
catch (final Exception ex) {
|
||||||
LOGGER.debug("Failed to parse line '{}': {}", line, ex.getMessage());
|
LOGGER.debug("Failed to parse line '{}': {}", line, ex.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rowCount == 0) {
|
if (rowCount == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < this.headings.size(); i++) {
|
for (int i = 0; i < this.headings.size(); i++) {
|
||||||
final String key = this.keyPrefix + this.headings.get(i);
|
final String key = this.keyPrefix + this.headings.get(i);
|
||||||
context.setStringValues(key, columnData.get(i));
|
context.setStringValues(key, columnData.get(i));
|
||||||
LOGGER.debug("Stored {} values in context key '{}'", columnData.get(i).size(), key);
|
LOGGER.debug("Stored {} values in context key '{}'", columnData.get(i).size(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.debug("Parsed {} CSV rows into {} columns", rowCount, this.headings.size());
|
LOGGER.debug("Parsed {} CSV rows into {} columns", rowCount, this.headings.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCsvResponseErrorPrompt(final AgentContext context) {
|
private void addCsvResponseErrorPrompt(final AgentContext context) {
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String stripQuotes(final String value) {
|
private String stripQuotes(final String value) {
|
||||||
if (value == null || value.length() < 2) {
|
if (value == null || value.length() < 2) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((value.startsWith("\"")
|
if ((value.startsWith("\"")
|
||||||
&& value.endsWith("\""))
|
&& value.endsWith("\""))
|
||||||
|| (value.startsWith("'")
|
|| (value.startsWith("'")
|
||||||
&& value.endsWith("'"))) {
|
&& value.endsWith("'"))) {
|
||||||
return value.substring(1, value.length() - 1);
|
return value.substring(1, value.length() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,259 +18,259 @@ import de.extio.lmlib.client.Conversation;
|
|||||||
|
|
||||||
public class CsvUnmarshallingAgentResponseHandler implements AgentResponseHandler {
|
public class CsvUnmarshallingAgentResponseHandler implements AgentResponseHandler {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(CsvUnmarshallingAgentResponseHandler.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(CsvUnmarshallingAgentResponseHandler.class);
|
||||||
|
|
||||||
private final Class<?> targetClass;
|
private final Class<?> targetClass;
|
||||||
|
|
||||||
private final String contextKey;
|
private final String contextKey;
|
||||||
|
|
||||||
private final String fieldSeparator;
|
private final String fieldSeparator;
|
||||||
|
|
||||||
private final String listSeparator;
|
private final String listSeparator;
|
||||||
|
|
||||||
private final Field[] fields;
|
private final Field[] fields;
|
||||||
|
|
||||||
private final List<String> fieldNames;
|
private final List<String> fieldNames;
|
||||||
|
|
||||||
private final Constructor<?> constructor;
|
private final Constructor<?> constructor;
|
||||||
|
|
||||||
private final String fieldSeparatorQuoted;
|
private final String fieldSeparatorQuoted;
|
||||||
|
|
||||||
private final String listSeparatorQuoted;
|
private final String listSeparatorQuoted;
|
||||||
|
|
||||||
private final String errorPromptSuffix;
|
private final String errorPromptSuffix;
|
||||||
|
|
||||||
public CsvUnmarshallingAgentResponseHandler(final Class<?> targetClass, final String contextKey) {
|
public CsvUnmarshallingAgentResponseHandler(final Class<?> targetClass, final String contextKey) {
|
||||||
this(targetClass, contextKey, ";", ",");
|
this(targetClass, contextKey, ";", ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
public CsvUnmarshallingAgentResponseHandler(final Class<?> targetClass, final String contextKey,
|
public CsvUnmarshallingAgentResponseHandler(final Class<?> targetClass, final String contextKey,
|
||||||
final String fieldSeparator, final String listSeparator) {
|
final String fieldSeparator, final String listSeparator) {
|
||||||
this.targetClass = targetClass;
|
this.targetClass = targetClass;
|
||||||
this.contextKey = contextKey;
|
this.contextKey = contextKey;
|
||||||
this.fieldSeparator = fieldSeparator;
|
this.fieldSeparator = fieldSeparator;
|
||||||
this.listSeparator = listSeparator;
|
this.listSeparator = listSeparator;
|
||||||
|
|
||||||
// Pre-compute static data
|
// Pre-compute static data
|
||||||
this.fields = targetClass.getDeclaredFields();
|
this.fields = targetClass.getDeclaredFields();
|
||||||
this.fieldNames = Arrays.stream(this.fields)
|
this.fieldNames = Arrays.stream(this.fields)
|
||||||
.map(Field::getName)
|
.map(Field::getName)
|
||||||
.toList();
|
.toList();
|
||||||
this.constructor = this.findRecordConstructor();
|
this.constructor = this.findRecordConstructor();
|
||||||
if (this.constructor == null) {
|
if (this.constructor == null) {
|
||||||
throw new IllegalStateException("No suitable constructor found for " + targetClass.getName());
|
throw new IllegalStateException("No suitable constructor found for " + targetClass.getName());
|
||||||
}
|
}
|
||||||
this.fieldSeparatorQuoted = Pattern.quote(fieldSeparator);
|
this.fieldSeparatorQuoted = Pattern.quote(fieldSeparator);
|
||||||
this.listSeparatorQuoted = (listSeparator != null && !listSeparator.isEmpty())
|
this.listSeparatorQuoted = (listSeparator != null && !listSeparator.isEmpty())
|
||||||
? Pattern.quote(listSeparator)
|
? Pattern.quote(listSeparator)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
// Pre-compute error message suffix
|
// Pre-compute error message suffix
|
||||||
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.errorPromptSuffix = "\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.";
|
||||||
}
|
}
|
||||||
|
|
||||||
private Constructor<?> findRecordConstructor() {
|
private Constructor<?> findRecordConstructor() {
|
||||||
final Field[] targetFields = this.targetClass.getDeclaredFields();
|
final Field[] targetFields = this.targetClass.getDeclaredFields();
|
||||||
for (final Constructor<?> ctor : this.targetClass.getDeclaredConstructors()) {
|
for (final Constructor<?> ctor : this.targetClass.getDeclaredConstructors()) {
|
||||||
if (ctor.getParameterCount() == targetFields.length) {
|
if (ctor.getParameterCount() == targetFields.length) {
|
||||||
return ctor;
|
return ctor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handle(final Completion completion, final AgentContext context) {
|
public boolean handle(final Completion completion, final AgentContext context) {
|
||||||
final String resp = completion.response();
|
final String resp = completion.response();
|
||||||
if (resp == null || resp.isBlank()) {
|
if (resp == null || resp.isBlank()) {
|
||||||
LOGGER.warn("Empty completion response for CSV parsing");
|
LOGGER.warn("Empty completion response for CSV parsing");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
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);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.setValues(this.contextKey, parsedObjects);
|
context.setValues(this.contextKey, parsedObjects);
|
||||||
LOGGER.debug("Parsed {} CSV objects", parsedObjects.size());
|
LOGGER.debug("Parsed {} CSV objects", parsedObjects.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
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);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Object> parseCsv(final String csvText) throws Exception {
|
private List<Object> parseCsv(final String csvText) throws Exception {
|
||||||
final List<Object> result = new ArrayList<>();
|
final List<Object> result = new ArrayList<>();
|
||||||
final String[] lines = csvText.split("\n");
|
final String[] lines = csvText.split("\n");
|
||||||
|
|
||||||
int startLine = 0;
|
int startLine = 0;
|
||||||
|
|
||||||
for (int i = 0; i < lines.length; i++) {
|
for (int i = 0; i < lines.length; i++) {
|
||||||
final String line = lines[i].trim();
|
final String line = lines[i].trim();
|
||||||
|
|
||||||
if (line.isEmpty()) {
|
if (line.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!line.contains(this.fieldSeparator)) {
|
if (!line.contains(this.fieldSeparator)) {
|
||||||
startLine = i + 1;
|
startLine = i + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String lowerLine = line.toLowerCase();
|
final String lowerLine = line.toLowerCase();
|
||||||
boolean isHeader = false;
|
boolean isHeader = false;
|
||||||
for (final String fieldName : this.fieldNames) {
|
for (final String fieldName : this.fieldNames) {
|
||||||
if (lowerLine.contains(fieldName.toLowerCase())) {
|
if (lowerLine.contains(fieldName.toLowerCase())) {
|
||||||
isHeader = true;
|
isHeader = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isHeader) {
|
if (isHeader) {
|
||||||
startLine = i + 1;
|
startLine = i + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = startLine; i < lines.length; i++) {
|
for (int i = startLine; i < lines.length; i++) {
|
||||||
final String line = lines[i].trim();
|
final String line = lines[i].trim();
|
||||||
|
|
||||||
if (line.isEmpty()) {
|
if (line.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!line.contains(this.fieldSeparator)) {
|
if (!line.contains(this.fieldSeparator)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final Object obj = this.parseLine(line);
|
final Object obj = this.parseLine(line);
|
||||||
if (obj != null) {
|
if (obj != null) {
|
||||||
result.add(obj);
|
result.add(obj);
|
||||||
LOGGER.debug("Parsed CSV object: {}", obj);
|
LOGGER.debug("Parsed CSV object: {}", obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (final Exception ex) {
|
catch (final Exception ex) {
|
||||||
LOGGER.debug("Failed to parse line '{}': {}", line, ex.getMessage());
|
LOGGER.debug("Failed to parse line '{}': {}", line, ex.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object parseLine(final String line) throws Exception {
|
private Object parseLine(final String line) throws Exception {
|
||||||
final String[] parts = line.split(this.fieldSeparatorQuoted, -1);
|
final String[] parts = line.split(this.fieldSeparatorQuoted, -1);
|
||||||
if (parts.length != this.fields.length) {
|
if (parts.length != this.fields.length) {
|
||||||
LOGGER.debug("Field count mismatch: expected {}, got {} for line '{}'",
|
LOGGER.debug("Field count mismatch: expected {}, got {} for line '{}'",
|
||||||
this.fields.length, parts.length, line);
|
this.fields.length, parts.length, line);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Object[] args = new Object[this.fields.length];
|
final Object[] args = new Object[this.fields.length];
|
||||||
|
|
||||||
for (int i = 0; i < this.fields.length; i++) {
|
for (int i = 0; i < this.fields.length; i++) {
|
||||||
final String value = parts[i].trim();
|
final String value = parts[i].trim();
|
||||||
args[i] = this.parseValue(value, this.fields[i]);
|
args[i] = this.parseValue(value, this.fields[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.constructor.newInstance(args);
|
return this.constructor.newInstance(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object parseValue(final String value, final Field field) {
|
private Object parseValue(final String value, final Field field) {
|
||||||
final String cleanValue = this.stripQuotes(value);
|
final String cleanValue = this.stripQuotes(value);
|
||||||
final Class<?> fieldType = field.getType();
|
final Class<?> fieldType = field.getType();
|
||||||
|
|
||||||
if (cleanValue.isEmpty() || cleanValue.equalsIgnoreCase("null")) {
|
if (cleanValue.isEmpty() || cleanValue.equalsIgnoreCase("null")) {
|
||||||
if (fieldType == List.class) {
|
if (fieldType == List.class) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldType == String.class) {
|
if (fieldType == String.class) {
|
||||||
return cleanValue;
|
return cleanValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldType == Integer.class || fieldType == int.class) {
|
if (fieldType == Integer.class || fieldType == int.class) {
|
||||||
return Integer.parseInt(cleanValue);
|
return Integer.parseInt(cleanValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldType == Long.class || fieldType == long.class) {
|
if (fieldType == Long.class || fieldType == long.class) {
|
||||||
return Long.parseLong(cleanValue);
|
return Long.parseLong(cleanValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldType == Double.class || fieldType == double.class) {
|
if (fieldType == Double.class || fieldType == double.class) {
|
||||||
return Double.parseDouble(cleanValue);
|
return Double.parseDouble(cleanValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldType == Boolean.class || fieldType == boolean.class) {
|
if (fieldType == Boolean.class || fieldType == boolean.class) {
|
||||||
return Boolean.parseBoolean(cleanValue);
|
return Boolean.parseBoolean(cleanValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldType == List.class) {
|
if (fieldType == List.class) {
|
||||||
if (this.listSeparatorQuoted == null) {
|
if (this.listSeparatorQuoted == null) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
final Type genericType = field.getGenericType();
|
final Type genericType = field.getGenericType();
|
||||||
if (genericType instanceof ParameterizedType) {
|
if (genericType instanceof ParameterizedType) {
|
||||||
final ParameterizedType paramType = (ParameterizedType) genericType;
|
final ParameterizedType paramType = (ParameterizedType) genericType;
|
||||||
final Type[] typeArgs = paramType.getActualTypeArguments();
|
final Type[] typeArgs = paramType.getActualTypeArguments();
|
||||||
|
|
||||||
if (typeArgs.length > 0 && typeArgs[0] == String.class) {
|
if (typeArgs.length > 0 && typeArgs[0] == String.class) {
|
||||||
if (cleanValue.isEmpty()) {
|
if (cleanValue.isEmpty()) {
|
||||||
return new ArrayList<String>();
|
return new ArrayList<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
final String[] items = cleanValue.split(this.listSeparatorQuoted);
|
final String[] items = cleanValue.split(this.listSeparatorQuoted);
|
||||||
final List<String> list = new ArrayList<>();
|
final List<String> list = new ArrayList<>();
|
||||||
for (final String item : items) {
|
for (final String item : items) {
|
||||||
final String trimmed = item.trim();
|
final String trimmed = item.trim();
|
||||||
if (!trimmed.isEmpty()) {
|
if (!trimmed.isEmpty()) {
|
||||||
list.add(trimmed);
|
list.add(trimmed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String stripQuotes(final String value) {
|
private String stripQuotes(final String value) {
|
||||||
if (value == null || value.length() < 2) {
|
if (value == null || value.length() < 2) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((value.startsWith("\"")
|
if ((value.startsWith("\"")
|
||||||
&& value.endsWith("\""))
|
&& value.endsWith("\""))
|
||||||
|| (value.startsWith("'")
|
|| (value.startsWith("'")
|
||||||
&& value.endsWith("'"))) {
|
&& value.endsWith("'"))) {
|
||||||
return value.substring(1, value.length() - 1);
|
return value.substring(1, value.length() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import de.extio.lmlib.client.Chunk;
|
|||||||
|
|
||||||
public interface StreamedAgentResponseHandler extends AgentResponseHandler {
|
public interface StreamedAgentResponseHandler extends AgentResponseHandler {
|
||||||
|
|
||||||
void beforeStream(AgentContext context);
|
void beforeStream(AgentContext context);
|
||||||
|
|
||||||
boolean handleChunk(Chunk chunk, AgentContext context);
|
boolean handleChunk(Chunk chunk, AgentContext context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,19 @@ package de.extio.lmlib.client;
|
|||||||
|
|
||||||
public enum CompletionFinishReason {
|
public enum CompletionFinishReason {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regular completion
|
* Regular completion
|
||||||
*/
|
*/
|
||||||
DONE,
|
DONE,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Completion was stopped because the token limit was reached. You may continue the conversation.
|
* Completion was stopped because the token limit was reached. You may continue the conversation.
|
||||||
*/
|
*/
|
||||||
TOKEN_LIMIT_REACHED,
|
TOKEN_LIMIT_REACHED,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Completion was stopped because the content was filtered.
|
* Completion was stopped because the content was filtered.
|
||||||
*/
|
*/
|
||||||
CONTENT_FILTERED
|
CONTENT_FILTERED
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ package de.extio.lmlib.client.oai.completion;
|
|||||||
|
|
||||||
public final class FinishReasons {
|
public final class FinishReasons {
|
||||||
|
|
||||||
public static final String FINISH_REASON_STOP = "stop";
|
public static final String FINISH_REASON_STOP = "stop";
|
||||||
|
|
||||||
public static final String FINISH_REASON_LENGTH = "length";
|
public static final String FINISH_REASON_LENGTH = "length";
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
|
|
||||||
public class StreamOptions {
|
public class StreamOptions {
|
||||||
|
|
||||||
protected boolean includeUsage;
|
protected boolean includeUsage;
|
||||||
|
|
||||||
@JsonProperty("include_usage")
|
@JsonProperty("include_usage")
|
||||||
public boolean isIncludeUsage() {
|
public boolean isIncludeUsage() {
|
||||||
return includeUsage;
|
return includeUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIncludeUsage(final boolean includeUsage) {
|
public void setIncludeUsage(final boolean includeUsage) {
|
||||||
this.includeUsage = includeUsage;
|
this.includeUsage = includeUsage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,108 +4,108 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
|
|
||||||
public final class Timings {
|
public final class Timings {
|
||||||
|
|
||||||
private int cacheN;
|
private int cacheN;
|
||||||
|
|
||||||
private int predictedN;
|
private int predictedN;
|
||||||
|
|
||||||
private double predictedMs;
|
private double predictedMs;
|
||||||
|
|
||||||
private double predictedPerTokenMs;
|
private double predictedPerTokenMs;
|
||||||
|
|
||||||
private double predictedPerSecond;
|
private double predictedPerSecond;
|
||||||
|
|
||||||
private int promptN;
|
private int promptN;
|
||||||
|
|
||||||
private double promptMs;
|
private double promptMs;
|
||||||
|
|
||||||
private double promptPerTokenMs;
|
private double promptPerTokenMs;
|
||||||
|
|
||||||
private double promptPerSecond;
|
private double promptPerSecond;
|
||||||
|
|
||||||
@JsonProperty("cache_n")
|
@JsonProperty("cache_n")
|
||||||
public int getCacheN() {
|
public int getCacheN() {
|
||||||
return this.cacheN;
|
return this.cacheN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCacheN(final int cacheN) {
|
public void setCacheN(final int cacheN) {
|
||||||
this.cacheN = cacheN;
|
this.cacheN = cacheN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("predicted_n")
|
@JsonProperty("predicted_n")
|
||||||
public int getPredictedN() {
|
public int getPredictedN() {
|
||||||
return this.predictedN;
|
return this.predictedN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPredictedN(final int predictedN) {
|
public void setPredictedN(final int predictedN) {
|
||||||
this.predictedN = predictedN;
|
this.predictedN = predictedN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("predicted_ms")
|
@JsonProperty("predicted_ms")
|
||||||
public double getPredictedMs() {
|
public double getPredictedMs() {
|
||||||
return this.predictedMs;
|
return this.predictedMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPredictedMs(final double predictedMs) {
|
public void setPredictedMs(final double predictedMs) {
|
||||||
this.predictedMs = predictedMs;
|
this.predictedMs = predictedMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("predicted_per_token_ms")
|
@JsonProperty("predicted_per_token_ms")
|
||||||
public double getPredictedPerTokenMs() {
|
public double getPredictedPerTokenMs() {
|
||||||
return this.predictedPerTokenMs;
|
return this.predictedPerTokenMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPredictedPerTokenMs(final double predictedPerTokenMs) {
|
public void setPredictedPerTokenMs(final double predictedPerTokenMs) {
|
||||||
this.predictedPerTokenMs = predictedPerTokenMs;
|
this.predictedPerTokenMs = predictedPerTokenMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("predicted_per_second")
|
@JsonProperty("predicted_per_second")
|
||||||
public double getPredictedPerSecond() {
|
public double getPredictedPerSecond() {
|
||||||
return this.predictedPerSecond;
|
return this.predictedPerSecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPredictedPerSecond(final double predictedPerSecond) {
|
public void setPredictedPerSecond(final double predictedPerSecond) {
|
||||||
this.predictedPerSecond = predictedPerSecond;
|
this.predictedPerSecond = predictedPerSecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("prompt_n")
|
@JsonProperty("prompt_n")
|
||||||
public int getPromptN() {
|
public int getPromptN() {
|
||||||
return this.promptN;
|
return this.promptN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPromptN(final int promptN) {
|
public void setPromptN(final int promptN) {
|
||||||
this.promptN = promptN;
|
this.promptN = promptN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("prompt_ms")
|
@JsonProperty("prompt_ms")
|
||||||
public double getPromptMs() {
|
public double getPromptMs() {
|
||||||
return this.promptMs;
|
return this.promptMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPromptMs(final double promptMs) {
|
public void setPromptMs(final double promptMs) {
|
||||||
this.promptMs = promptMs;
|
this.promptMs = promptMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("prompt_per_token_ms")
|
@JsonProperty("prompt_per_token_ms")
|
||||||
public double getPromptPerTokenMs() {
|
public double getPromptPerTokenMs() {
|
||||||
return this.promptPerTokenMs;
|
return this.promptPerTokenMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPromptPerTokenMs(final double promptPerTokenMs) {
|
public void setPromptPerTokenMs(final double promptPerTokenMs) {
|
||||||
this.promptPerTokenMs = promptPerTokenMs;
|
this.promptPerTokenMs = promptPerTokenMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("prompt_per_second")
|
@JsonProperty("prompt_per_second")
|
||||||
public double getPromptPerSecond() {
|
public double getPromptPerSecond() {
|
||||||
return this.promptPerSecond;
|
return this.promptPerSecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPromptPerSecond(final double promptPerSecond) {
|
public void setPromptPerSecond(final double promptPerSecond) {
|
||||||
this.promptPerSecond = promptPerSecond;
|
this.promptPerSecond = promptPerSecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Timings [cacheN=" + this.cacheN + ", predictedN=" + this.predictedN + ", predictedMs=" + this.predictedMs + ", predictedPerTokenMs=" + this.predictedPerTokenMs + ", predictedPerSecond=" + this.predictedPerSecond + ", promptN=" + this.promptN + ", promptMs=" + this.promptMs + ", promptPerTokenMs=" + this.promptPerTokenMs + ", promptPerSecond=" + this.promptPerSecond + "]";
|
return "Timings [cacheN=" + this.cacheN + ", predictedN=" + this.predictedN + ", predictedMs=" + this.predictedMs + ", predictedPerTokenMs=" + this.predictedPerTokenMs + ", predictedPerSecond=" + this.predictedPerSecond + ", promptN=" + this.promptN + ", promptMs=" + this.promptMs + ", promptPerTokenMs=" + this.promptPerTokenMs + ", promptPerSecond=" + this.promptPerSecond + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,120 +4,120 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
|
|
||||||
public final class Usage {
|
public final class Usage {
|
||||||
|
|
||||||
private int completionTokens;
|
private int completionTokens;
|
||||||
|
|
||||||
private int promptTokens;
|
private int promptTokens;
|
||||||
|
|
||||||
private int totalTokens;
|
private int totalTokens;
|
||||||
|
|
||||||
private InputTokensDetails inputTokensDetails;
|
private InputTokensDetails inputTokensDetails;
|
||||||
|
|
||||||
private OutputTokensDetails outputTokensDetails;
|
private OutputTokensDetails outputTokensDetails;
|
||||||
|
|
||||||
@JsonProperty("completion_tokens")
|
@JsonProperty("completion_tokens")
|
||||||
public int getCompletionTokens() {
|
public int getCompletionTokens() {
|
||||||
return this.completionTokens;
|
return this.completionTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCompletionTokens(final int completionTokens) {
|
public void setCompletionTokens(final int completionTokens) {
|
||||||
this.completionTokens = completionTokens;
|
this.completionTokens = completionTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("output_tokens")
|
@JsonProperty("output_tokens")
|
||||||
public void setOutputTokens(final int outputTokens) {
|
public void setOutputTokens(final int outputTokens) {
|
||||||
this.completionTokens = outputTokens;
|
this.completionTokens = outputTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("prompt_tokens")
|
@JsonProperty("prompt_tokens")
|
||||||
public int getPromptTokens() {
|
public int getPromptTokens() {
|
||||||
return this.promptTokens;
|
return this.promptTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPromptTokens(final int promptTokens) {
|
public void setPromptTokens(final int promptTokens) {
|
||||||
this.promptTokens = promptTokens;
|
this.promptTokens = promptTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("input_tokens")
|
@JsonProperty("input_tokens")
|
||||||
public void setInputTokens(final int inputTokens) {
|
public void setInputTokens(final int inputTokens) {
|
||||||
this.promptTokens = inputTokens;
|
this.promptTokens = inputTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("total_tokens")
|
@JsonProperty("total_tokens")
|
||||||
public int getTotalTokens() {
|
public int getTotalTokens() {
|
||||||
return this.totalTokens;
|
return this.totalTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTotalTokens(final int totalTokens) {
|
public void setTotalTokens(final int totalTokens) {
|
||||||
this.totalTokens = totalTokens;
|
this.totalTokens = totalTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("input_tokens_details")
|
@JsonProperty("input_tokens_details")
|
||||||
public InputTokensDetails getInputTokensDetails() {
|
public InputTokensDetails getInputTokensDetails() {
|
||||||
return this.inputTokensDetails;
|
return this.inputTokensDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInputTokensDetails(final InputTokensDetails inputTokensDetails) {
|
public void setInputTokensDetails(final InputTokensDetails inputTokensDetails) {
|
||||||
this.inputTokensDetails = inputTokensDetails;
|
this.inputTokensDetails = inputTokensDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("output_tokens_details")
|
@JsonProperty("output_tokens_details")
|
||||||
public OutputTokensDetails getOutputTokensDetails() {
|
public OutputTokensDetails getOutputTokensDetails() {
|
||||||
return this.outputTokensDetails;
|
return this.outputTokensDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOutputTokensDetails(final OutputTokensDetails outputTokensDetails) {
|
public void setOutputTokensDetails(final OutputTokensDetails outputTokensDetails) {
|
||||||
this.outputTokensDetails = outputTokensDetails;
|
this.outputTokensDetails = outputTokensDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCachedTokens() {
|
public int getCachedTokens() {
|
||||||
return this.inputTokensDetails != null ? this.inputTokensDetails.getCachedTokens() : 0;
|
return this.inputTokensDetails != null ? this.inputTokensDetails.getCachedTokens() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getReasoningTokens() {
|
public int getReasoningTokens() {
|
||||||
return this.outputTokensDetails != null ? this.outputTokensDetails.getReasoningTokens() : 0;
|
return this.outputTokensDetails != null ? this.outputTokensDetails.getReasoningTokens() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Usage [completionTokens=" + this.completionTokens + ", promptTokens=" + this.promptTokens + ", totalTokens=" + this.totalTokens + ", inputTokensDetails=" + this.inputTokensDetails + ", outputTokensDetails=" + this.outputTokensDetails + "]";
|
return "Usage [completionTokens=" + this.completionTokens + ", promptTokens=" + this.promptTokens + ", totalTokens=" + this.totalTokens + ", inputTokensDetails=" + this.inputTokensDetails + ", outputTokensDetails=" + this.outputTokensDetails + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class InputTokensDetails {
|
public static final class InputTokensDetails {
|
||||||
|
|
||||||
private int cachedTokens;
|
private int cachedTokens;
|
||||||
|
|
||||||
@JsonProperty("cached_tokens")
|
@JsonProperty("cached_tokens")
|
||||||
public int getCachedTokens() {
|
public int getCachedTokens() {
|
||||||
return this.cachedTokens;
|
return this.cachedTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCachedTokens(final int cachedTokens) {
|
public void setCachedTokens(final int cachedTokens) {
|
||||||
this.cachedTokens = cachedTokens;
|
this.cachedTokens = cachedTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "InputTokensDetails [cachedTokens=" + this.cachedTokens + "]";
|
return "InputTokensDetails [cachedTokens=" + this.cachedTokens + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class OutputTokensDetails {
|
public static final class OutputTokensDetails {
|
||||||
|
|
||||||
private int reasoningTokens;
|
private int reasoningTokens;
|
||||||
|
|
||||||
@JsonProperty("reasoning_tokens")
|
@JsonProperty("reasoning_tokens")
|
||||||
public int getReasoningTokens() {
|
public int getReasoningTokens() {
|
||||||
return this.reasoningTokens;
|
return this.reasoningTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReasoningTokens(final int reasoningTokens) {
|
public void setReasoningTokens(final int reasoningTokens) {
|
||||||
this.reasoningTokens = reasoningTokens;
|
this.reasoningTokens = reasoningTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "OutputTokensDetails [reasoningTokens=" + this.reasoningTokens + "]";
|
return "OutputTokensDetails [reasoningTokens=" + this.reasoningTokens + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,45 +4,45 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
|
|
||||||
final class ChatMessage {
|
final class ChatMessage {
|
||||||
|
|
||||||
private String role;
|
private String role;
|
||||||
|
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
private String reasoningContent;
|
private String reasoningContent;
|
||||||
|
|
||||||
public ChatMessage() {
|
public ChatMessage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChatMessage(final String role, final String content, final String reasoningContent) {
|
public ChatMessage(final String role, final String content, final String reasoningContent) {
|
||||||
this.role = role;
|
this.role = role;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
this.reasoningContent = reasoningContent;
|
this.reasoningContent = reasoningContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("role")
|
@JsonProperty("role")
|
||||||
public String getRole() {
|
public String getRole() {
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRole(final String role) {
|
public void setRole(final String role) {
|
||||||
this.role = role;
|
this.role = role;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("content")
|
@JsonProperty("content")
|
||||||
public String getContent() {
|
public String getContent() {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContent(final String content) {
|
public void setContent(final String content) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("reasoning_content")
|
@JsonProperty("reasoning_content")
|
||||||
public String getReasoningContent() {
|
public String getReasoningContent() {
|
||||||
return reasoningContent;
|
return reasoningContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReasoningContent(final String reasoningContent) {
|
public void setReasoningContent(final String reasoningContent) {
|
||||||
this.reasoningContent = reasoningContent;
|
this.reasoningContent = reasoningContent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ public class AnswerGrader2 {
|
|||||||
else {
|
else {
|
||||||
context.setStringValue("qaOutputFormat", "Provide no preamble. Return the response in JSON format with the following field only: {\"qaRating\": rating}");
|
context.setStringValue("qaOutputFormat", "Provide no preamble. Return the response in JSON format with the following field only: {\"qaRating\": rating}");
|
||||||
}
|
}
|
||||||
context.getContext().remove("qaRating");
|
context.getContext().remove("qaRating");
|
||||||
context.getContext().remove("qaExplanation");
|
context.getContext().remove("qaExplanation");
|
||||||
},
|
},
|
||||||
context -> {
|
context -> {
|
||||||
if (!context.getContext().containsKey("qaRating")) {
|
if (!context.getContext().containsKey("qaRating")) {
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ public class AnswerGraderBinary {
|
|||||||
else {
|
else {
|
||||||
context.setStringValue("qaOutputFormat", "Return a JSON object with exactly this key: {\"qaPassed\": boolean}");
|
context.setStringValue("qaOutputFormat", "Return a JSON object with exactly this key: {\"qaPassed\": boolean}");
|
||||||
}
|
}
|
||||||
context.getContext().remove("qaPassed");
|
context.getContext().remove("qaPassed");
|
||||||
context.getContext().remove("qaExplanation");
|
context.getContext().remove("qaExplanation");
|
||||||
},
|
},
|
||||||
context -> {
|
context -> {
|
||||||
if (!context.getContext().containsKey("qaPassed")) {
|
if (!context.getContext().containsKey("qaPassed")) {
|
||||||
@@ -70,7 +70,7 @@ public class AnswerGraderBinary {
|
|||||||
context.getContext().put("qaPassed", List.of(qaPassed));
|
context.getContext().put("qaPassed", List.of(qaPassed));
|
||||||
|
|
||||||
if (!qaPassed && (int) context.getContext().get("qaIteration").get(0) < 2) {
|
if (!qaPassed && (int) context.getContext().get("qaIteration").get(0) < 2) {
|
||||||
context.setStringValue("qaFeedback", "Feedback from the previous attempt to consider: " + context.getStringValue("qaExplanation"));
|
context.setStringValue("qaFeedback", "Feedback from the previous attempt to consider: " + context.getStringValue("qaExplanation"));
|
||||||
return new AgentNext(context.getStringValue("qaFeedbackLoopDestination"), Boolean.FALSE);
|
return new AgentNext(context.getStringValue("qaFeedbackLoopDestination"), Boolean.FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,106 +5,106 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
public class GptOssPromptStrategy implements PromptStrategy {
|
public class GptOssPromptStrategy implements PromptStrategy {
|
||||||
|
|
||||||
private static final String finalMarker = "<|channel|>final<|message|>";
|
private static final String finalMarker = "<|channel|>final<|message|>";
|
||||||
|
|
||||||
private static final String startMarker = "<|start|>";
|
private static final String startMarker = "<|start|>";
|
||||||
|
|
||||||
private static final String assistantStart = startMarker + "assistant";
|
private static final String assistantStart = startMarker + "assistant";
|
||||||
|
|
||||||
private static final String analysisMarker = "<|channel|>analysis<|message|>";
|
private static final String analysisMarker = "<|channel|>analysis<|message|>";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StringBuilder start(final String system, final String user) {
|
public StringBuilder start(final String system, final String user) {
|
||||||
final StringBuilder prompt = new StringBuilder();
|
final StringBuilder prompt = new StringBuilder();
|
||||||
if (!system.isEmpty()) {
|
if (!system.isEmpty()) {
|
||||||
prompt.append("<|start|>system<|message|>");
|
prompt.append("<|start|>system<|message|>");
|
||||||
prompt.append(system);
|
prompt.append(system);
|
||||||
prompt.append("<|end|>");
|
prompt.append("<|end|>");
|
||||||
}
|
}
|
||||||
prompt.append("<|start|>user<|message|>");
|
prompt.append("<|start|>user<|message|>");
|
||||||
prompt.append(user);
|
prompt.append(user);
|
||||||
prompt.append("<|end|>");
|
prompt.append("<|end|>");
|
||||||
prompt.append(assistantStart);
|
prompt.append(assistantStart);
|
||||||
|
|
||||||
return prompt;
|
return prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void next(final StringBuilder prompt, final String assistant, final String user) {
|
public void next(final StringBuilder prompt, final String assistant, final String user) {
|
||||||
final String assistantContent = assistant == null ? "" : assistant;
|
final String assistantContent = assistant == null ? "" : assistant;
|
||||||
if (assistantContent.startsWith(assistantStart)) {
|
if (assistantContent.startsWith(assistantStart)) {
|
||||||
final int assistantStartLength = assistantStart.length();
|
final int assistantStartLength = assistantStart.length();
|
||||||
if (prompt.length() >= assistantStartLength) {
|
if (prompt.length() >= assistantStartLength) {
|
||||||
boolean endsWithAssistantStart = true;
|
boolean endsWithAssistantStart = true;
|
||||||
for (int i = 0; i < assistantStartLength; i++) {
|
for (int i = 0; i < assistantStartLength; i++) {
|
||||||
if (prompt.charAt(prompt.length() - assistantStartLength + i) != assistantStart.charAt(i)) {
|
if (prompt.charAt(prompt.length() - assistantStartLength + i) != assistantStart.charAt(i)) {
|
||||||
endsWithAssistantStart = false;
|
endsWithAssistantStart = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (endsWithAssistantStart) {
|
if (endsWithAssistantStart) {
|
||||||
prompt.setLength(prompt.length() - assistantStartLength);
|
prompt.setLength(prompt.length() - assistantStartLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (assistantContent.contains(finalMarker)) {
|
if (assistantContent.contains(finalMarker)) {
|
||||||
prompt.append(assistantContent);
|
prompt.append(assistantContent);
|
||||||
if (!assistantContent.endsWith("<|end|>")) {
|
if (!assistantContent.endsWith("<|end|>")) {
|
||||||
prompt.append("<|end|>");
|
prompt.append("<|end|>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
prompt.append("<|channel|>final<|message|>");
|
prompt.append("<|channel|>final<|message|>");
|
||||||
prompt.append(assistantContent);
|
prompt.append(assistantContent);
|
||||||
prompt.append("<|end|>");
|
prompt.append("<|end|>");
|
||||||
}
|
}
|
||||||
prompt.append("<|start|>user<|message|>");
|
prompt.append("<|start|>user<|message|>");
|
||||||
prompt.append(user == null ? "" : user);
|
prompt.append(user == null ? "" : user);
|
||||||
prompt.append("<|end|>");
|
prompt.append("<|end|>");
|
||||||
prompt.append(assistantStart);
|
prompt.append(assistantStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String removeEOT(final String prompt) {
|
public String removeEOT(final String prompt) {
|
||||||
return prompt.strip().replace("<|end|>", "").replace("<|return|>", "");
|
return prompt.strip().replace("<|end|>", "").replace("<|return|>", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPromptName() {
|
public String getPromptName() {
|
||||||
return "gpt-oss";
|
return "gpt-oss";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getResponse(final String prompt) {
|
public String getResponse(final String prompt) {
|
||||||
if (prompt == null) {
|
if (prompt == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final int markerIndex = prompt.indexOf(finalMarker);
|
final int markerIndex = prompt.indexOf(finalMarker);
|
||||||
if (markerIndex == -1) {
|
if (markerIndex == -1) {
|
||||||
return prompt;
|
return prompt;
|
||||||
}
|
}
|
||||||
final int start = markerIndex + finalMarker.length();
|
final int start = markerIndex + finalMarker.length();
|
||||||
int end = prompt.indexOf(startMarker, start);
|
int end = prompt.indexOf(startMarker, start);
|
||||||
if (end == -1) {
|
if (end == -1) {
|
||||||
end = prompt.length();
|
end = prompt.length();
|
||||||
}
|
}
|
||||||
return prompt.substring(start, end).strip();
|
return prompt.substring(start, end).strip();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getReasoning(final String prompt) {
|
public String getReasoning(final String prompt) {
|
||||||
if (prompt == null) {
|
if (prompt == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final int markerIndex = prompt.indexOf(analysisMarker);
|
final int markerIndex = prompt.indexOf(analysisMarker);
|
||||||
if (markerIndex == -1) {
|
if (markerIndex == -1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final int start = markerIndex + analysisMarker.length();
|
final int start = markerIndex + analysisMarker.length();
|
||||||
int end = prompt.indexOf(startMarker, start);
|
int end = prompt.indexOf(startMarker, start);
|
||||||
if (end == -1) {
|
if (end == -1) {
|
||||||
end = prompt.length();
|
end = prompt.length();
|
||||||
}
|
}
|
||||||
return prompt.substring(start, end).strip();
|
return prompt.substring(start, end).strip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,31 +5,31 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
public class NoPromptStrategy implements PromptStrategy {
|
public class NoPromptStrategy implements PromptStrategy {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPromptName() {
|
public String getPromptName() {
|
||||||
return "noop";
|
return "noop";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StringBuilder start(final String system, final String user) {
|
public StringBuilder start(final String system, final String user) {
|
||||||
final var sb = new StringBuilder();
|
final var sb = new StringBuilder();
|
||||||
if (system != null && !system.isBlank()) {
|
if (system != null && !system.isBlank()) {
|
||||||
sb.append(system);
|
sb.append(system);
|
||||||
}
|
}
|
||||||
if (system != null && !system.isBlank() && user != null && !user.isBlank()) {
|
if (system != null && !system.isBlank() && user != null && !user.isBlank()) {
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
}
|
}
|
||||||
if (user != null && !user.isBlank()) {
|
if (user != null && !user.isBlank()) {
|
||||||
sb.append(user);
|
sb.append(user);
|
||||||
}
|
}
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void next(final StringBuilder prompt, final String assistant, final String user) {
|
public void next(final StringBuilder prompt, final String assistant, final String user) {
|
||||||
prompt.append(assistant);
|
prompt.append(assistant);
|
||||||
prompt.append("\n");
|
prompt.append("\n");
|
||||||
prompt.append(user);
|
prompt.append(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,307 +16,307 @@ import de.extio.lmlib.client.Conversation;
|
|||||||
|
|
||||||
public class CsvAgentResponseHandlerTest {
|
public class CsvAgentResponseHandlerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleCsvParsing() {
|
public void testSimpleCsvParsing() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "xy_");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "xy_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
1;2;3
|
1;2;3
|
||||||
4;5;6
|
4;5;6
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
final List<String> aValues = context.getStringValues("xy_a");
|
final List<String> aValues = context.getStringValues("xy_a");
|
||||||
final List<String> bValues = context.getStringValues("xy_b");
|
final List<String> bValues = context.getStringValues("xy_b");
|
||||||
final List<String> cValues = context.getStringValues("xy_c");
|
final List<String> cValues = context.getStringValues("xy_c");
|
||||||
|
|
||||||
assertNotNull(aValues);
|
assertNotNull(aValues);
|
||||||
assertNotNull(bValues);
|
assertNotNull(bValues);
|
||||||
assertNotNull(cValues);
|
assertNotNull(cValues);
|
||||||
|
|
||||||
assertEquals(List.of("1", "4"), aValues);
|
assertEquals(List.of("1", "4"), aValues);
|
||||||
assertEquals(List.of("2", "5"), bValues);
|
assertEquals(List.of("2", "5"), bValues);
|
||||||
assertEquals(List.of("3", "6"), cValues);
|
assertEquals(List.of("3", "6"), cValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWithHeader() {
|
public void testWithHeader() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("name", "age", "city"), "person_");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("name", "age", "city"), "person_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
name;age;city
|
name;age;city
|
||||||
Alice;30;Berlin
|
Alice;30;Berlin
|
||||||
Bob;25;Munich
|
Bob;25;Munich
|
||||||
Charlie;35;Hamburg
|
Charlie;35;Hamburg
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
final List<String> names = context.getStringValues("person_name");
|
final List<String> names = context.getStringValues("person_name");
|
||||||
final List<String> ages = context.getStringValues("person_age");
|
final List<String> ages = context.getStringValues("person_age");
|
||||||
final List<String> cities = context.getStringValues("person_city");
|
final List<String> cities = context.getStringValues("person_city");
|
||||||
|
|
||||||
assertEquals(List.of("Alice", "Bob", "Charlie"), names);
|
assertEquals(List.of("Alice", "Bob", "Charlie"), names);
|
||||||
assertEquals(List.of("30", "25", "35"), ages);
|
assertEquals(List.of("30", "25", "35"), ages);
|
||||||
assertEquals(List.of("Berlin", "Munich", "Hamburg"), cities);
|
assertEquals(List.of("Berlin", "Munich", "Hamburg"), cities);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWithEmptyPrefix() {
|
public void testWithEmptyPrefix() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("x", "y"), "");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("x", "y"), "");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
10;20
|
10;20
|
||||||
30;40
|
30;40
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
assertEquals(List.of("10", "30"), context.getStringValues("x"));
|
assertEquals(List.of("10", "30"), context.getStringValues("x"));
|
||||||
assertEquals(List.of("20", "40"), context.getStringValues("y"));
|
assertEquals(List.of("20", "40"), context.getStringValues("y"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWithNullPrefix() {
|
public void testWithNullPrefix() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("col1", "col2"), null);
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("col1", "col2"), null);
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
a;b
|
a;b
|
||||||
c;d
|
c;d
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
assertEquals(List.of("a", "c"), context.getStringValues("col1"));
|
assertEquals(List.of("a", "c"), context.getStringValues("col1"));
|
||||||
assertEquals(List.of("b", "d"), context.getStringValues("col2"));
|
assertEquals(List.of("b", "d"), context.getStringValues("col2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWithExtraTextBeforeData() {
|
public void testWithExtraTextBeforeData() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "test_");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "test_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
Here is the CSV data:
|
Here is the CSV data:
|
||||||
|
|
||||||
a;b;c
|
a;b;c
|
||||||
1;2;3
|
1;2;3
|
||||||
4;5;6
|
4;5;6
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
assertEquals(List.of("1", "4"), context.getStringValues("test_a"));
|
assertEquals(List.of("1", "4"), context.getStringValues("test_a"));
|
||||||
assertEquals(List.of("2", "5"), context.getStringValues("test_b"));
|
assertEquals(List.of("2", "5"), context.getStringValues("test_b"));
|
||||||
assertEquals(List.of("3", "6"), context.getStringValues("test_c"));
|
assertEquals(List.of("3", "6"), context.getStringValues("test_c"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWithEmptyLines() {
|
public void testWithEmptyLines() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b"), "data_");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b"), "data_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
1;2
|
1;2
|
||||||
|
|
||||||
3;4
|
3;4
|
||||||
|
|
||||||
5;6
|
5;6
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
assertEquals(List.of("1", "3", "5"), context.getStringValues("data_a"));
|
assertEquals(List.of("1", "3", "5"), context.getStringValues("data_a"));
|
||||||
assertEquals(List.of("2", "4", "6"), context.getStringValues("data_b"));
|
assertEquals(List.of("2", "4", "6"), context.getStringValues("data_b"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWithWhitespace() {
|
public void testWithWhitespace() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "ws_");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "ws_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
1 ; 2 ; 3
|
1 ; 2 ; 3
|
||||||
4 ; 5 ; 6
|
4 ; 5 ; 6
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
assertEquals(List.of("1", "4"), context.getStringValues("ws_a"));
|
assertEquals(List.of("1", "4"), context.getStringValues("ws_a"));
|
||||||
assertEquals(List.of("2", "5"), context.getStringValues("ws_b"));
|
assertEquals(List.of("2", "5"), context.getStringValues("ws_b"));
|
||||||
assertEquals(List.of("3", "6"), context.getStringValues("ws_c"));
|
assertEquals(List.of("3", "6"), context.getStringValues("ws_c"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWithCustomSeparator() {
|
public void testWithCustomSeparator() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "custom_", ",");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "custom_", ",");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
1,2,3
|
1,2,3
|
||||||
4,5,6
|
4,5,6
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
assertEquals(List.of("1", "4"), context.getStringValues("custom_a"));
|
assertEquals(List.of("1", "4"), context.getStringValues("custom_a"));
|
||||||
assertEquals(List.of("2", "5"), context.getStringValues("custom_b"));
|
assertEquals(List.of("2", "5"), context.getStringValues("custom_b"));
|
||||||
assertEquals(List.of("3", "6"), context.getStringValues("custom_c"));
|
assertEquals(List.of("3", "6"), context.getStringValues("custom_c"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testColumnCountMismatch() {
|
public void testColumnCountMismatch() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "mismatch_");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b", "c"), "mismatch_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
1;2;3
|
1;2;3
|
||||||
4;5
|
4;5
|
||||||
7;8;9
|
7;8;9
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
// Only rows with correct column count should be included
|
// Only rows with correct column count should be included
|
||||||
assertEquals(List.of("1", "7"), context.getStringValues("mismatch_a"));
|
assertEquals(List.of("1", "7"), context.getStringValues("mismatch_a"));
|
||||||
assertEquals(List.of("2", "8"), context.getStringValues("mismatch_b"));
|
assertEquals(List.of("2", "8"), context.getStringValues("mismatch_b"));
|
||||||
assertEquals(List.of("3", "9"), context.getStringValues("mismatch_c"));
|
assertEquals(List.of("3", "9"), context.getStringValues("mismatch_c"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEmptyResponse() {
|
public void testEmptyResponse() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b"), "empty_");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b"), "empty_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final Completion completion = new Completion("", null, null, null);
|
final Completion completion = new Completion("", null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertFalse(result);
|
assertFalse(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNullResponse() {
|
public void testNullResponse() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b"), "null_");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b"), "null_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final Completion completion = new Completion(null, null, null, null);
|
final Completion completion = new Completion(null, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertFalse(result);
|
assertFalse(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoValidData() {
|
public void testNoValidData() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b"), "nodata_");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("a", "b"), "nodata_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
This is just text
|
This is just text
|
||||||
without any valid CSV data
|
without any valid CSV data
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertFalse(result);
|
assertFalse(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleRow() {
|
public void testSingleRow() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("x", "y", "z"), "single_");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("x", "y", "z"), "single_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = "100;200;300";
|
final String csvResponse = "100;200;300";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
assertEquals(List.of("100"), context.getStringValues("single_x"));
|
assertEquals(List.of("100"), context.getStringValues("single_x"));
|
||||||
assertEquals(List.of("200"), context.getStringValues("single_y"));
|
assertEquals(List.of("200"), context.getStringValues("single_y"));
|
||||||
assertEquals(List.of("300"), context.getStringValues("single_z"));
|
assertEquals(List.of("300"), context.getStringValues("single_z"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleHeaders() {
|
public void testMultipleHeaders() {
|
||||||
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("id", "value"), "multi_");
|
final CsvAgentResponseHandler handler = new CsvAgentResponseHandler(List.of("id", "value"), "multi_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
id;value
|
id;value
|
||||||
ID;VALUE
|
ID;VALUE
|
||||||
1;100
|
1;100
|
||||||
2;200
|
2;200
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
// Should skip both header rows
|
// Should skip both header rows
|
||||||
assertEquals(List.of("1", "2"), context.getStringValues("multi_id"));
|
assertEquals(List.of("1", "2"), context.getStringValues("multi_id"));
|
||||||
assertEquals(List.of("100", "200"), context.getStringValues("multi_value"));
|
assertEquals(List.of("100", "200"), context.getStringValues("multi_value"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNullHeadingsList() {
|
public void testNullHeadingsList() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
new CsvAgentResponseHandler(null, "prefix_");
|
new CsvAgentResponseHandler(null, "prefix_");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEmptyHeadingsList() {
|
public void testEmptyHeadingsList() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
new CsvAgentResponseHandler(List.of(), "prefix_");
|
new CsvAgentResponseHandler(List.of(), "prefix_");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,250 +14,250 @@ import de.extio.lmlib.client.Conversation;
|
|||||||
|
|
||||||
public class CsvUnmarshallingAgentResponseHandlerTest {
|
public class CsvUnmarshallingAgentResponseHandlerTest {
|
||||||
|
|
||||||
public static record TestObject(String name, List<String> tags, Integer value) {
|
public static record TestObject(String name, List<String> tags, Integer value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleCsvParsing() {
|
public void testSimpleCsvParsing() {
|
||||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
item1;tag1,tag2;42
|
item1;tag1,tag2;42
|
||||||
item2;tag3;100
|
item2;tag3;100
|
||||||
item3;;50
|
item3;;50
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||||
assertEquals(3, objects.size());
|
assertEquals(3, objects.size());
|
||||||
|
|
||||||
assertEquals("item1", objects.get(0).name());
|
assertEquals("item1", objects.get(0).name());
|
||||||
assertEquals(List.of("tag1", "tag2"), objects.get(0).tags());
|
assertEquals(List.of("tag1", "tag2"), objects.get(0).tags());
|
||||||
assertEquals(42, objects.get(0).value());
|
assertEquals(42, objects.get(0).value());
|
||||||
|
|
||||||
assertEquals("item2", objects.get(1).name());
|
assertEquals("item2", objects.get(1).name());
|
||||||
assertEquals(List.of("tag3"), objects.get(1).tags());
|
assertEquals(List.of("tag3"), objects.get(1).tags());
|
||||||
assertEquals(100, objects.get(1).value());
|
assertEquals(100, objects.get(1).value());
|
||||||
|
|
||||||
assertEquals("item3", objects.get(2).name());
|
assertEquals("item3", objects.get(2).name());
|
||||||
assertTrue(objects.get(2).tags().isEmpty());
|
assertTrue(objects.get(2).tags().isEmpty());
|
||||||
assertEquals(50, objects.get(2).value());
|
assertEquals(50, objects.get(2).value());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCsvWithHeader() {
|
public void testCsvWithHeader() {
|
||||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
name;tags;value
|
name;tags;value
|
||||||
item1;tag1,tag2;42
|
item1;tag1,tag2;42
|
||||||
item2;tag3;100
|
item2;tag3;100
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||||
assertEquals(2, objects.size());
|
assertEquals(2, objects.size());
|
||||||
|
|
||||||
assertEquals("item1", objects.get(0).name());
|
assertEquals("item1", objects.get(0).name());
|
||||||
assertEquals("item2", objects.get(1).name());
|
assertEquals("item2", objects.get(1).name());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCsvWithPreamble() {
|
public void testCsvWithPreamble() {
|
||||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
Here is the result:
|
Here is the result:
|
||||||
|
|
||||||
item1;tag1,tag2;42
|
item1;tag1,tag2;42
|
||||||
item2;tag3;100
|
item2;tag3;100
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||||
assertEquals(2, objects.size());
|
assertEquals(2, objects.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCsvWithHeaderAndPreamble() {
|
public void testCsvWithHeaderAndPreamble() {
|
||||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
Here are the results in CSV format:
|
Here are the results in CSV format:
|
||||||
|
|
||||||
name;tags;value
|
name;tags;value
|
||||||
item1;tag1,tag2;42
|
item1;tag1,tag2;42
|
||||||
item2;tag3;100
|
item2;tag3;100
|
||||||
item3;;50
|
item3;;50
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||||
assertEquals(3, objects.size());
|
assertEquals(3, objects.size());
|
||||||
|
|
||||||
assertEquals("item1", objects.get(0).name());
|
assertEquals("item1", objects.get(0).name());
|
||||||
assertEquals(List.of("tag1", "tag2"), objects.get(0).tags());
|
assertEquals(List.of("tag1", "tag2"), objects.get(0).tags());
|
||||||
assertEquals(42, objects.get(0).value());
|
assertEquals(42, objects.get(0).value());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCsvWithEmptyLines() {
|
public void testCsvWithEmptyLines() {
|
||||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
|
|
||||||
item1;tag1,tag2;42
|
item1;tag1,tag2;42
|
||||||
|
|
||||||
item2;tag3;100
|
item2;tag3;100
|
||||||
|
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||||
assertEquals(2, objects.size());
|
assertEquals(2, objects.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCsvWithNullValues() {
|
public void testCsvWithNullValues() {
|
||||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TestObject.class, "_test_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
item1;tag1,tag2;
|
item1;tag1,tag2;
|
||||||
item2;;100
|
item2;;100
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
final List<TestObject> objects = context.getValues("_test_", TestObject.class);
|
||||||
assertEquals(2, objects.size());
|
assertEquals(2, objects.size());
|
||||||
|
|
||||||
assertEquals("item1", objects.get(0).name());
|
assertEquals("item1", objects.get(0).name());
|
||||||
assertNotNull(objects.get(0).tags());
|
assertNotNull(objects.get(0).tags());
|
||||||
assertEquals(null, objects.get(0).value());
|
assertEquals(null, objects.get(0).value());
|
||||||
|
|
||||||
assertEquals("item2", objects.get(1).name());
|
assertEquals("item2", objects.get(1).name());
|
||||||
assertTrue(objects.get(1).tags().isEmpty());
|
assertTrue(objects.get(1).tags().isEmpty());
|
||||||
assertEquals(100, objects.get(1).value());
|
assertEquals(100, objects.get(1).value());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static record TagObject(String tag, List<String> aliases, Integer importance) {
|
public static record TagObject(String tag, List<String> aliases, Integer importance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTagObjectExample() {
|
public void testTagObjectExample() {
|
||||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TagObject.class, "_tag_");
|
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(TagObject.class, "_tag_");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
location_dark_forest;location_forest,location_shadow_woods;25
|
location_dark_forest;location_forest,location_shadow_woods;25
|
||||||
location_ancient_shrine;location_shrine,location_vine_shrine;65
|
location_ancient_shrine;location_shrine,location_vine_shrine;65
|
||||||
combat_dragon;combat_wyrm,combat_ancient_dragon;65
|
combat_dragon;combat_wyrm,combat_ancient_dragon;65
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
final List<TagObject> objects = context.getValues("_tag_", TagObject.class);
|
final List<TagObject> objects = context.getValues("_tag_", TagObject.class);
|
||||||
assertEquals(3, objects.size());
|
assertEquals(3, objects.size());
|
||||||
|
|
||||||
assertEquals("location_dark_forest", objects.get(0).tag());
|
assertEquals("location_dark_forest", objects.get(0).tag());
|
||||||
assertEquals(List.of("location_forest", "location_shadow_woods"), objects.get(0).aliases());
|
assertEquals(List.of("location_forest", "location_shadow_woods"), objects.get(0).aliases());
|
||||||
assertEquals(25, objects.get(0).importance());
|
assertEquals(25, objects.get(0).importance());
|
||||||
|
|
||||||
assertEquals("combat_dragon", objects.get(2).tag());
|
assertEquals("combat_dragon", objects.get(2).tag());
|
||||||
assertEquals(List.of("combat_wyrm", "combat_ancient_dragon"), objects.get(2).aliases());
|
assertEquals(List.of("combat_wyrm", "combat_ancient_dragon"), objects.get(2).aliases());
|
||||||
assertEquals(65, objects.get(2).importance());
|
assertEquals(65, objects.get(2).importance());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCustomSeparators() {
|
public void testCustomSeparators() {
|
||||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(
|
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(
|
||||||
TagObject.class, "_custom_", "|", ":");
|
TagObject.class, "_custom_", "|", ":");
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
location_dark_forest|location_forest:location_shadow_woods|25
|
location_dark_forest|location_forest:location_shadow_woods|25
|
||||||
location_ancient_shrine|location_shrine:location_vine_shrine|65
|
location_ancient_shrine|location_shrine:location_vine_shrine|65
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
final List<TagObject> objects = context.getValues("_custom_", TagObject.class);
|
final List<TagObject> objects = context.getValues("_custom_", TagObject.class);
|
||||||
assertEquals(2, objects.size());
|
assertEquals(2, objects.size());
|
||||||
|
|
||||||
assertEquals("location_dark_forest", objects.get(0).tag());
|
assertEquals("location_dark_forest", objects.get(0).tag());
|
||||||
assertEquals(List.of("location_forest", "location_shadow_woods"), objects.get(0).aliases());
|
assertEquals(List.of("location_forest", "location_shadow_woods"), objects.get(0).aliases());
|
||||||
assertEquals(25, objects.get(0).importance());
|
assertEquals(25, objects.get(0).importance());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoListSeparator() {
|
public void testNoListSeparator() {
|
||||||
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(
|
final CsvUnmarshallingAgentResponseHandler handler = new CsvUnmarshallingAgentResponseHandler(
|
||||||
TestObject.class, "_nolist_", ";", null);
|
TestObject.class, "_nolist_", ";", null);
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
context.setConversation(Conversation.create("test"));
|
context.setConversation(Conversation.create("test"));
|
||||||
|
|
||||||
final String csvResponse = """
|
final String csvResponse = """
|
||||||
item1;tag1,tag2,tag3;42
|
item1;tag1,tag2,tag3;42
|
||||||
item2;ignored;100
|
item2;ignored;100
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Completion completion = new Completion(csvResponse, null, null, null);
|
final Completion completion = new Completion(csvResponse, null, null, null);
|
||||||
final boolean result = handler.handle(completion, context);
|
final boolean result = handler.handle(completion, context);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
||||||
final List<TestObject> objects = context.getValues("_nolist_", TestObject.class);
|
final List<TestObject> objects = context.getValues("_nolist_", TestObject.class);
|
||||||
assertEquals(2, objects.size());
|
assertEquals(2, objects.size());
|
||||||
|
|
||||||
assertEquals("item1", objects.get(0).name());
|
assertEquals("item1", objects.get(0).name());
|
||||||
assertTrue(objects.get(0).tags().isEmpty());
|
assertTrue(objects.get(0).tags().isEmpty());
|
||||||
assertEquals(42, objects.get(0).value());
|
assertEquals(42, objects.get(0).value());
|
||||||
|
|
||||||
assertEquals("item2", objects.get(1).name());
|
assertEquals("item2", objects.get(1).name());
|
||||||
assertTrue(objects.get(1).tags().isEmpty());
|
assertTrue(objects.get(1).tags().isEmpty());
|
||||||
assertEquals(100, objects.get(1).value());
|
assertEquals(100, objects.get(1).value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ public class JsonAgentResponseHandlerTest {
|
|||||||
assertTrue(value.contains("clown"));
|
assertTrue(value.contains("clown"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSanitizeUnescapedQuotesInString2() {
|
public void testSanitizeUnescapedQuotesInString2() {
|
||||||
final JsonAgentResponseHandler handler = new JsonAgentResponseHandler();
|
final JsonAgentResponseHandler handler = new JsonAgentResponseHandler();
|
||||||
final AgentContext context = new AgentContext();
|
final AgentContext context = new AgentContext();
|
||||||
|
|||||||
Reference in New Issue
Block a user