Skip to content
Merged
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
81 changes: 81 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,87 @@ The UI runs on `http://localhost:3000` and proxies `/api` to the backend.
| Database | SQLite |
| Deployment | Docker Compose |

## Writing Evals for a Skill

Arctiq discovers evals from a file named `evals/evals.json` inside each skill's directory in the Git repository.

### File location

```
your-skill-repo/
└── your-skill/
├── skill.md # skill instructions
└── evals/
└── evals.json # eval test cases
```

### Format

```json
{
"evals": [
{
"id": 1,
"name": "optional case name",
"prompt": "The input prompt sent to the model",
"assertions": [
{ "id": "a1", "text": "Response is concise and under 100 words", "weight": 1.0 },
{ "id": "a2", "text": "Answer mentions the correct library name", "weight": 2.0 }
]
}
]
}
```

### Fields

| Field | Required | Description |
|---|---|---|
| `evals[].id` | Yes | Integer — unique identifier for the test case |
| `evals[].prompt` | Yes | The prompt sent to the model under test |
| `evals[].name` | No | Human-readable label shown in the UI |
| `evals[].assertions` | No | List of criteria judged by the LLM judge |
| `assertions[].id` | Yes | String — unique identifier for the assertion |
| `assertions[].text` | Yes | The criterion evaluated by the judge model (YES/NO) |
| `assertions[].weight` | No | Scoring weight (default `1.0`). Higher = more impact on the final score |

### Scoring

Each assertion is evaluated independently by a judge model using a strict YES/NO prompt. The final score is a weighted percentage:

```
score = sum(weight of passed assertions) / sum(weight of all assertions) × 100
```

An eval case with no assertions is recorded but produces no score.

### Example

```json
{
"evals": [
{
"id": 1,
"name": "Summarise a short article",
"prompt": "Summarise the following article in 2–3 sentences:\n\nThe James Webb Space Telescope...",
"assertions": [
{ "id": "s1", "text": "Summary is 2 to 3 sentences long", "weight": 1.0 },
{ "id": "s2", "text": "Summary does not introduce facts not present in the article", "weight": 2.0 },
{ "id": "s3", "text": "Summary is written in plain English", "weight": 1.0 }
]
},
{
"id": 2,
"name": "Empty input handling",
"prompt": "Summarise the following article:\n\n",
"assertions": [
{ "id": "e1", "text": "Model asks for or acknowledges missing input rather than hallucinating a summary", "weight": 1.0 }
]
}
]
}
```

## License

[MIT](LICENSE)
Expand Down
Loading