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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions agenteval-datasets/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.agenteval</groupId>
<artifactId>agenteval-parent</artifactId>
<version>0.1.0-SNAPSHOT</version>
</parent>

<artifactId>agenteval-datasets</artifactId>
<name>AgentEval Datasets</name>
<description>Dataset loading, management, and serialization</description>

<dependencies>
<dependency>
<groupId>com.agenteval</groupId>
<artifactId>agenteval-core</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.agenteval.datasets;

/**
* Unchecked exception for dataset loading/writing errors.
*/
public class DatasetException extends RuntimeException {

private static final long serialVersionUID = 1L;

public DatasetException(String message) {
super(message);
}

public DatasetException(String message, Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.agenteval.datasets;

import java.io.InputStream;
import java.nio.file.Path;

/**
* Interface for loading evaluation datasets from various sources.
*/
public interface DatasetLoader {

/**
* Loads a dataset from a file path.
*
* @param path the path to the dataset file
* @return the loaded dataset
* @throws DatasetException if loading fails
*/
EvalDataset load(Path path);

/**
* Loads a dataset from an input stream.
*
* @param inputStream the input stream to read from
* @return the loaded dataset
* @throws DatasetException if loading fails
*/
EvalDataset load(InputStream inputStream);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.agenteval.datasets;

import java.io.OutputStream;
import java.nio.file.Path;

/**
* Interface for writing evaluation datasets to various targets.
*/
public interface DatasetWriter {

/**
* Writes a dataset to a file path.
*
* @param dataset the dataset to write
* @param path the target file path
* @throws DatasetException if writing fails
*/
void write(EvalDataset dataset, Path path);

/**
* Writes a dataset to an output stream.
*
* @param dataset the dataset to write
* @param outputStream the target output stream
* @throws DatasetException if writing fails
*/
void write(EvalDataset dataset, OutputStream outputStream);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.agenteval.datasets;

import com.agenteval.core.model.AgentTestCase;
import com.agenteval.datasets.json.JsonDatasetWriter;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;

import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
* An immutable collection of evaluation test cases with metadata.
*/
@JsonDeserialize(builder = EvalDataset.Builder.class)
public final class EvalDataset {

private final String name;
private final String version;
private final List<AgentTestCase> testCases;
private final Map<String, Object> metadata;

private EvalDataset(Builder builder) {
this.name = builder.name;
this.version = builder.version;
this.testCases = builder.testCases == null ? List.of() : List.copyOf(builder.testCases);
this.metadata = builder.metadata == null ? Map.of() : Map.copyOf(builder.metadata);
}

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

public String getName() { return name; }
public String getVersion() { return version; }
public List<AgentTestCase> getTestCases() { return testCases; }
public Map<String, Object> getMetadata() { return metadata; }

/**
* Returns the number of test cases in this dataset.
*/
public int size() {
return testCases.size();
}

/**
* Saves this dataset to a JSON file.
*
* @param path the target file path
* @throws DatasetException if writing fails
*/
public void save(Path path) {
new JsonDatasetWriter().write(this, path);
}

@JsonPOJOBuilder(withPrefix = "")
public static final class Builder {
private String name;
private String version;
private List<AgentTestCase> testCases;
private Map<String, Object> metadata;

private Builder() {}

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

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

public Builder testCases(List<AgentTestCase> testCases) {
this.testCases = testCases;
return this;
}

public Builder metadata(Map<String, Object> metadata) {
this.metadata = metadata;
return this;
}

public EvalDataset build() {
Objects.requireNonNull(testCases, "testCases must not be null");
return new EvalDataset(this);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.agenteval.datasets.json;

import com.agenteval.core.model.AgentTestCase;
import com.agenteval.datasets.DatasetException;
import com.agenteval.datasets.DatasetLoader;
import com.agenteval.datasets.EvalDataset;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

/**
* Loads evaluation datasets from JSON files.
*
* <p>Supports two formats:</p>
* <ul>
* <li><strong>Envelope format:</strong> {@code {"name":"...","testCases":[...]}}</li>
* <li><strong>Bare array format:</strong> {@code [{...}, ...]}</li>
* </ul>
*
* <p>Auto-detects the format by inspecting the first non-whitespace character.</p>
*/
public final class JsonDatasetLoader implements DatasetLoader {

private static final Logger LOG = LoggerFactory.getLogger(JsonDatasetLoader.class);
private static final TypeReference<List<AgentTestCase>> TEST_CASE_LIST =
new TypeReference<>() { };

private final ObjectMapper mapper;

public JsonDatasetLoader() {
this(new ObjectMapper());
}

public JsonDatasetLoader(ObjectMapper mapper) {
this.mapper = mapper;
}

@Override
public EvalDataset load(Path path) {
LOG.debug("Loading dataset from {}", path);
try {
byte[] bytes = Files.readAllBytes(path);
return parse(bytes);
} catch (IOException e) {
throw new DatasetException("Failed to load dataset from " + path, e);
}
}

@Override
public EvalDataset load(InputStream inputStream) {
LOG.debug("Loading dataset from input stream");
try {
byte[] bytes = inputStream.readAllBytes();
return parse(bytes);
} catch (IOException e) {
throw new DatasetException("Failed to load dataset from input stream", e);
}
}

private EvalDataset parse(byte[] bytes) throws IOException {
if (isBareArray(bytes)) {
LOG.debug("Detected bare array format");
List<AgentTestCase> testCases = mapper.readValue(bytes, TEST_CASE_LIST);
return EvalDataset.builder()
.testCases(testCases)
.build();
}
LOG.debug("Detected envelope format");
return mapper.readValue(bytes, EvalDataset.class);
}

private static boolean isBareArray(byte[] bytes) {
for (byte b : bytes) {
if (!Character.isWhitespace(b)) {
return b == '[';
}
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.agenteval.datasets.json;

import com.agenteval.datasets.DatasetException;
import com.agenteval.datasets.DatasetWriter;
import com.agenteval.datasets.EvalDataset;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;

/**
* Writes evaluation datasets to JSON files in envelope format with pretty-printing.
*/
public final class JsonDatasetWriter implements DatasetWriter {

private static final Logger LOG = LoggerFactory.getLogger(JsonDatasetWriter.class);

private final ObjectMapper mapper;

public JsonDatasetWriter() {
this(new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT));
}

public JsonDatasetWriter(ObjectMapper mapper) {
this.mapper = mapper;
}

@Override
public void write(EvalDataset dataset, Path path) {
LOG.debug("Writing dataset '{}' to {}", dataset.getName(), path);
try (OutputStream out = Files.newOutputStream(path)) {
write(dataset, out);
} catch (IOException e) {
throw new DatasetException("Failed to write dataset to " + path, e);
}
}

@Override
public void write(EvalDataset dataset, OutputStream outputStream) {
try {
mapper.writeValue(outputStream, dataset);
} catch (IOException e) {
throw new DatasetException("Failed to write dataset to output stream", e);
}
}
}
Loading