forgecode / benchmarks /README.md
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
1244914 verified
|
Raw
History Blame Contribute Delete
7.9 kB
# Forge Code Evaluations
A flexible evaluation framework for running automated tests and benchmarks against Forge Code commands.
## Quick Start
### Setup
Before running evaluations, create a `forgee` symlink to the debug binary:
```bash
# Create symlink in your PATH (e.g., ~/bin or /usr/local/bin)
ln -sf /path/to/code-forge/target/debug/forge ~/forgee
# Or if ~/bin is in your PATH
ln -sf $(pwd)/target/debug/forge ~/bin/forgee
```
**Why is this needed?** Tasks execute in temporary directories, so relative paths like `../../target/debug/forge` won't work. The `forgee` symlink provides a stable absolute path that works from any directory.
### Running Evaluations
```bash
# Run an evaluation
npm run eval ./evals/create_skill/task.yml
# Set custom log level
LOG_LEVEL=debug npm run eval ./evals/create_skill/task.yml
```
## How It Works
The evaluation system executes commands based on task definitions and validates their output. It supports:
- **Parallel execution** with configurable concurrency
- **Timeout handling** for long-running tasks
- **Data-driven testing** using CSV files
- **Output validation** using regex patterns
- **Debug artifacts** stored with timestamps
## Project Structure
```
benchmarks/
β”œβ”€β”€ cli.ts # Main CLI entry point
β”œβ”€β”€ command-generator.ts # Command template rendering
β”œβ”€β”€ task-executor.ts # Task execution with timeout support
β”œβ”€β”€ model.ts # TypeScript types for tasks
β”œβ”€β”€ parse.ts # CLI argument parsing
└── evals/ # Evaluation definitions
└── create_skill/
β”œβ”€β”€ task.yml # Task definition
β”œβ”€β”€ create_skill_tasks.csv # Test data
└── debug/ # Debug outputs (timestamped)
```
## Creating an Evaluation
### 1. Create an Evaluation Directory
```bash
mkdir -p evals/my_eval
```
### 2. Create a `task.yml` File
The task file defines how to run your evaluation:
```yaml
# Optional: Commands to run before evaluation starts
before_run:
- cargo build
- npm install
# Required: Command(s) to execute for each test case
# Single command
run: forgee -p '{{prompt}}'
# Or multiple commands (executed sequentially)
run:
- echo "Step 1: {{task}}"
- forgee -p '{{prompt}}'
- echo "Step 2: Complete"
# Execution configuration
parallelism: 10 # Number of tasks to run in parallel (default: 1)
timeout: 60 # Timeout in seconds (optional)
early_exit: true # Stop execution when validations pass (optional)
# Optional: Validations to run on output
validations:
- name: "Check success message"
type: regex
regex: \[[0-9:]*\] Skill create-skill
# Required: Data sources for test cases
sources:
- csv: my_tasks.csv
```
#### Task File Schema
**`before_run`** (optional): Array of shell commands to execute before running tasks
- Runs sequentially before the main command execution
- Executes in a temporary directory created for the evaluation run
- Useful for building binaries or setting up dependencies
**`run`** (required): Command(s) to execute for each test case
- Can be a single string or an array of strings
- Commands support template placeholders (e.g., `{{variable}}`)
- Multiple commands are executed sequentially
- If any command fails, subsequent commands are skipped
**`parallelism`** (optional): Number of tasks to run concurrently (default: 1)
**`timeout`** (optional): Maximum execution time in seconds per task
**`early_exit`** (optional): Stop command execution when all validations pass
**`validations`** (optional): Array of validation rules
- `name`: Human-readable description
- `type`: Validation type. Supported values:
- `regex`: Match output against a regular expression pattern
- `shell`: Execute a shell command with output as stdin
- For `regex` type:
- `regex`: Regular expression pattern to match in output
- For `shell` type:
- `command`: Shell command to execute (receives task output via stdin)
- `exit_code`: Expected exit code (default: 0)
**`sources`** (required): Array of data sources
- Currently supports CSV files: `- csv: filename.csv`
- Future: Command output: `- cmd: command`
### 3. Create Test Data (CSV)
Create a CSV file with columns matching your template variables:
```csv
prompt,expected_output
"Create a backup script","backup.sh"
"Generate API client","api_client.py"
```
The column names (e.g., `prompt`, `expected_output`) become template variables you can use in your command with `{{column_name}}`.
### 4. Run the Evaluation
```bash
npm run eval ./evals/my_eval/task.yml
```
## Template Variables
Commands support Handlebars template syntax. Variables are populated from CSV columns:
```yaml
run:
command: ./tool --input '{{input_file}}' --format {{format}} --verbose
```
With CSV:
```csv
input_file,format
data1.txt,json
data2.txt,yaml
```
## Output and Debugging
### Debug Artifacts
Each run creates a timestamped debug directory:
```
evals/my_eval/debug/2025-11-23T10-30-45-123Z/
β”œβ”€β”€ task-1.log
β”œβ”€β”€ task-2.log
└── task-3.log
```
Each log file contains the full output (stdout + stderr) from the command execution.
### Task Status
Tasks can have four statuses:
- **`passed`**: Task completed successfully and passed all validations
- **`validation_failed`**: Task completed but failed one or more validations
- **`timeout`**: Task exceeded the timeout limit
- **`failed`**: Task execution failed (non-zero exit code)
### Logging
**Human-readable output (default):**
```bash
npm run eval ./evals/my_eval/task.yml
```
**Machine-readable JSON output:**
```bash
LOG_JSON=1 npm run eval ./evals/my_eval/task.yml | jq .
```
**Debug logging:**
```bash
LOG_LEVEL=debug npm run eval ./evals/my_eval/task.yml
```
## Examples
### Example 1: Simple Sequential Execution
```yaml
run: echo "Processing {{name}}"
sources:
- csv: names.csv
```
```csv
name
Alice
Bob
Charlie
```
### Example 2: Parallel Execution with Timeout
```yaml
run: ./slow_task --id {{task_id}}
parallelism: 5
timeout: 30
sources:
- csv: tasks.csv
```
### Example 3: Multiple Commands
```yaml
run:
- echo "Starting task {{id}}"
- ./process --input {{file}}
- echo "Task {{id}} complete"
parallelism: 3
timeout: 120
sources:
- csv: tasks.csv
```
### Example 4: Shell Command Validation
```yaml
run: echo "{{message}}"
parallelism: 3
validations:
# Using grep to check if output contains specific text
- name: "Contains 'test' word"
type: shell
command: grep -q "test"
exit_code: 0
# Count words and ensure it's greater than 2
- name: "More than 2 words"
type: shell
command: test $(wc -w | awk '{print $1}') -gt 2
exit_code: 0
# Traditional regex validation (for comparison)
- name: "Contains test or validation"
type: regex
regex: "test|validation"
sources:
- csv: messages.csv
```
### Example 5: Regex Validation
```yaml
run: cargo test {{test_name}}
validations:
- name: "All tests passed"
type: regex
regex: test result:\s+ok
sources:
- csv: tests.csv
```
## Tips
1. **Use quotes in commands**: When passing CSV values with spaces, wrap them in quotes:
```yaml
command: forge -p '{{prompt}}'
```
2. **Build before running**: Use `before_run` to ensure binaries are up-to-date:
```yaml
before_run:
- cargo build
```
3. **Start with low parallelism**: Test with `parallelism: 1` first, then increase:
```yaml
parallelism: 1 # Start here
```
4. **Set appropriate timeouts**: Add timeouts to prevent hanging:
```yaml
timeout: 60 # seconds
```
5. **Check debug logs**: When tasks fail, check the debug directory for full output:
```bash
cat evals/my_eval/debug/*/task-1.log
```
## Exit Codes
The CLI exits with:
- **0**: All tasks passed
- **1**: One or more tasks failed (excluding timeouts and validation failures)