OpenMark Open the app MCP setup

📚 Table of Contents

📋 YAML Task Schema

All the fields you can use in a task YAML file.

task_name
Type: string
Required: ✅ Yes

Unique identifier for the task

Example:

task_name: my_evaluation_task
display_name
Type: string
Required: ❌ No

Human-readable name for display

Example:

display_name: "My Evaluation Task"

Important: This is what appears in the UI task rail.

description
Type: string
Required: ❌ No

Detailed description of the task. Pipeline variables resolve per stability run; each run resets its pipeline context.

Example:

description: "Tests mathematical reasoning with basic arithmetic"
tests
Type: array of test_cases
Required: ✅ Yes

Example:

tests:
  - id: test_1
    prompt: "What is 2 + 2?"
    expected: 4
    scoring:
      mode: exact_match
  - id: test_2  
    prompt: "Calculate 15 * 3"
    expected: 45
    points: 2
attachments_root
Type: string
Required: ❌ No

Base folder for attachments. If relative, resolves from <bench_dir>. Use an absolute path to bypass.

Example:

attachments_root: "./documents"
enable_prompt_placeholders
Type: boolean
Required: ❌ No

Enable {document_content} placeholder rendering for modern format. Text from attachments is injected only when BOTH are true: (1) enable_prompt_placeholders: true AND (2) the prompt contains {document_content}. Otherwise, attachments are passed as file paths (not inlined).

Default: false

Example:

enable_prompt_placeholders: true

When true, allows using {document_content} in prompts.

task_defaults
Type: object
Required: ❌ No

Example:

task_defaults:
  temperature: 0.2

Test-Level Fields

Fields you can use for each test in the tests array:

id
Type: string
Required: ✅ Yes

Unique identifier for the test case

prompt
Type: string
Required: ✅ Yes

The prompt to send to the model

expected
Type: string or number or boolean or array or object
Required: ✅ Yes

Expected output for scoring

points
Type: number
Required: ❌ No

Maximum points this test contributes to the total score. Capped at 999 per test.

Example:

tests:
  - id: complex_task
    prompt: "Solve this complex problem..."
    expected: "Solution"
    points: 5  # This test is worth 5 points

Default: 1.0. Maximum: 999 per test.

scoring
Type: object
Required: ❌ No

Scoring criteria configuration

attachments
Type: array
Required: ❌ No

Files to attach to the prompt. TWO CATEGORIES: (1) TEXT-EXTRACTABLES (.txt, .md, .csv, .json, .xlsx, .xls, .xlsm, .pdf, .docx, .rtf): MUST use {document_content} placeholder. Content counted in preflight token budget. Auto-extracted if libraries present (pandas/PyPDF2/python-docx/striprtf). (2) VISION IMAGES (.png, .jpg, .jpeg, .gif, .webp, .bmp): Attach normally (NOT via {document_content}). Sent as binary to vision models. Conservative vision guard applied (~500 tokens/MP, 256-4096 range). AVIF files auto-convert to JPEG. ⚠️ WARNING: Extractables without {document_content} are NOT preflight-counted and may overflow small contexts. See USER_GUIDE.md#attachments-and-document_content

temperature
Type: number
Required: ❌ No

Override the task default temperature for this test

Example:

temperature: 0.2  # Override task default

🎯 Scoring Modes

How to score model responses - pick the right tool for your evaluation needs!

💰 budget

budget_compliance

Tracks token usage against limits - ensures models stay within token budgets

pricing

Cost efficiency scoring - cheaper models get better scores!

Pricing: Benchmark results already show cost per test and cost/efficiency by default. This scoring mode is for very specific pricing evaluation only.

Parameters:

NameTypeRequiredDefaultDescription
target_usd number No 0.001 Your cost goal per test in US dollars (smaller is cheaper)
min_score number No 0.0 Lowest possible score even if very expensive (0-1)

📌 code

code_quality

Static Python code quality via AST: cyclomatic complexity, long lines, function count

Parameters:

NameTypeRequiredDefaultDescription
source_from string No "attachment" Get code from attachment or model output
attachment_index integer No 0 Which attachment to analyze (0-based)
targets object No {} Target thresholds for metrics (max_avg_cc, max_fn_cc, max_long_lines)
weights object No {"avg_cc": 0.34, "fn_cc": 0.33, "long_lines": 0.33} Relative weights for each metric (avg_cc, fn_cc, long_lines)

📦 json

json_field_match

JSON field comparison - check specific parts of JSON data

Parameters:

NameTypeRequiredDefaultDescription
fields array No [] Top-level JSON fields to check (e.g., ['name', 'score']). Nested paths NOT supported.
partial_credit boolean No false Give partial points if some fields match

json_schema

JSON structure validation - ensures responses match expected format

Parameters:

NameTypeRequiredDefaultDescription
schema object No {} JSON Schema that the response must match
partial_credit boolean No false Give partial points even if schema validation has errors
extract_json_from_text boolean No true Find and extract JSON from text (e.g., from code blocks)

📋 list

contains_all

Must include ALL items - perfect for checklists and requirements

Parameters:

NameTypeRequiredDefaultDescription
partial_credit boolean No false Give partial points if some items are found
case_insensitive boolean No true Ignore uppercase/lowercase when finding items
order_matters boolean No false Items must appear in the listed order
invert boolean No false Score high when items are NOT found (useful for safety tests)
delimiter string No "," Character to split items (e.g., ',' for comma-separated)

contains_any

Must include AT LEAST ONE item - flexible multiple-choice checking

Parameters:

NameTypeRequiredDefaultDescription
partial_credit boolean No true Give partial points based on how many items found
case_insensitive boolean No true Ignore uppercase/lowercase when finding items
invert boolean No false Score high when items are NOT found (useful for safety tests)

list_matching

Compare lists of items - choose if order matters or not

Parameters:

NameTypeRequiredDefaultDescription
order_sensitive boolean No true Items must be in the same order to match
partial_credit boolean No false Give partial points for partially correct lists
case_insensitive boolean No true Ignore uppercase/lowercase in list items

set_contains_at_least

Checks that at least K items from expected are present in the model output. Supports aliases and normalization.

Parameters:

NameTypeRequiredDefaultDescription
min_hits integer No 1 Minimum number of items that must be found
aliases object No {} Map of canonical names to equivalent forms
lower boolean No true Convert to lowercase before matching
strip_punct boolean No true Remove punctuation before matching
collapse_ws boolean No true Collapse multiple spaces to single space

set_f1

Smart list comparison - uses F1 score for unordered sets

Parameters:

NameTypeRequiredDefaultDescription
case_insensitive boolean No true Ignore case when comparing items
dedupe boolean No true Remove duplicate items before calculating F1 score

🔢 numeric

numeric_from_text

Find numbers in text - extracts and compares numeric values from prose

Parameters:

NameTypeRequiredDefaultDescription
tolerance number No 0.0 How close the number can be (e.g., 0.01 allows ±0.01)
extract_strategy string No "first" Which number to pick: first one, last one, or largest
require_unit boolean No false Only accept if a valid unit is present (e.g., 'kg', 'meters')
unit_aliases array No [] Accepted unit strings (e.g., ['J', 'joule', 'joules'])
unit_proximity integer No 5 How many words away the unit can be from the number
method string No "abs" 'abs' = exact difference, 'rel' = percentage difference
range object No "N/A" Accept values in a range (e.g., {'min': 10, 'max': 20})

numeric_tolerance

Number comparison with wiggle room - allows small differences

Parameters:

NameTypeRequiredDefaultDescription
tolerance number No 1e-06 How close numbers must be (e.g., 0.01 allows ±0.01)
parse_from_text boolean No false Find and extract numbers from text answers

⚡ ops

speed

Response time scoring - faster models get better scores!

Speed: Benchmark results already show timing for each test by default. This scoring mode is for speed-specific evaluation only.

Parameters:

NameTypeRequiredDefaultDescription
source string No "runtime" Use actual runtime, model's rated speed, or both
target_ms number No 1000 Your response time goal in milliseconds (smaller is faster)
curve string No "softcap" 'softcap' = full points if under target, 'linear' = gradual decrease
min_score number No 0.0 Lowest possible score even if very slow (0-1)
combine string No "weighted" How to mix actual and rated speed: 'weighted' or 'sum'
latency_weight number No 0.25 How much to trust rated speed vs actual (0=actual only, 1=rated only)

📊 performance

stability

Consistency matters - measures how stable results are across runs

Parameters:

NameTypeRequiredDefaultDescription
stability_metric string No "range" How to measure consistency: 'range' = max-min, 'stdev' = spread, 'variance' = squared

✍️ text

case_insensitive

Flexible text match - ignores uppercase/lowercase differences

exact_match

Perfect text match - must be exactly the same (ignoring extra whitespace)

Parameters:

NameTypeRequiredDefaultDescription
case_insensitive boolean No false Ignore uppercase/lowercase differences
trim_whitespace boolean No true Remove extra spaces at start/end before checking

regex_match

Pattern matching with regex - powerful text extraction and validation

Parameters:

NameTypeRequiredDefaultDescription
pattern string No "N/A" Pattern to find in text (regex syntax)
flags array No [] Advanced regex options (e.g., ['IGNORECASE'])
match_mode string No "all" 'all' = every pattern must match, 'any' = at least one
partial_credit boolean No false Give partial points based on patterns matched

word_overlap

How many words match? Measures overlap between responses

Parameters:

NameTypeRequiredDefaultDescription
min_overlap number No 0.5 Minimum word match ratio to pass (0.5 = 50% match)
partial_credit boolean No false Give partial points based on how many words match
case_insensitive boolean No true Ignore uppercase/lowercase when matching words

🔗 Pipeline Variables

Chain your tests together! Export values from one test and use them in the next - perfect for multi-step workflows.

Overview

How to chain results between tests.

Exporting Values

Use the exports field in a test to capture values:

tests:
  - id: test_1
    prompt: "What is 15 + 27?"
    expected: 42
    exports:
      - name: result1
        mode: raw  # Capture full response

Using Exported Values

Reference exported values in subsequent tests with {var:name}:

tests:
  - id: test_2
    prompt: "Multiply {var:result1} by 3"
    expected: 126

Common Mistakes

❌ Incorrect variable syntax:

# WRONG:
{{exports.test_1.result1}}  # Don't use
{{exports.result1}}         # Don't use
{{result1}}                 # Don't use

# CORRECT:
{var:result1}               # Use this!

📄 Document Placeholders

Attach PDFs, text files, spreadsheets, and more to your tests. Document content is automatically included when benchmarking.

The {document_content} Placeholder

Use {document_content} to control exactly where attachment text appears in your prompt. Without it, content is added automatically:

enable_prompt_placeholders: true
tests:
  - id: doc_analysis
    prompt: |
      Analyze this document and extract the main topic:
      
      {document_content}
    attachments:
      - report.pdf
    expected: "Financial analysis"

Supported File Types

Text-Extractable Documents

Auto-Readable Text Files

Vision Model Attachments

Note: Document content is tokenized and may be truncated based on model limits.

🚀 Complete Examples

Minimal Valid Task

task_name: simple_math
display_name: "Simple Math Test"
tests:
  - prompt: "What is 2 + 2?"
    expected: 4

Chained Math with Pipeline Variables

task_name: chained_math
display_name: Chained Math Example
description: Demonstrates pipeline variables
tests:
  - id: addition
    prompt: "Calculate 15 + 27. Return ONLY the number."
    expected: 42
    scoring:
      mode: exact_match
    exports:
      - name: sum_result
        mode: raw
  
  - id: multiplication
    prompt: "Multiply {var:sum_result} by 3. Return ONLY the number."
    expected: 126
    scoring:
      mode: numeric_from_text

Vision Model Evaluation

task_name: vision_emotional_detection
display_name: Vision - Emotion Detection
description: Evaluate model ability to detect emotions in images
attachments_root: test_data/images

tests:
  - id: happy_detection
    prompt: |
      Look at the attached image and answer with only the word "happy" or "sad".
    expected: happy
    points: 10
    attachments:
      - family_photo.jpg
    scoring:
      mode: case_insensitive

  - id: sad_detection
    prompt: |
      Look at the attached image and answer with only the word "happy" or "sad".
    expected: sad
    points: 10
    attachments:
      - memorial_photo.jpg
    scoring:
      mode: case_insensitive
      
  - id: count_people
    prompt: |
      Count the number of people in the attached image.
      Return ONLY the number (digits only).
    expected: 4
    points: 20
    attachments:
      - group_photo.png
    scoring:
      mode: numeric_from_text
      tolerance: 0

Document Extraction with Scoring

task_name: excel_data_analysis
display_name: Excel Data Analysis
description: Extract and analyze data from spreadsheet
enable_prompt_placeholders: true
attachments_root: test_data/spreadsheets

tests:
  - id: count_items
    prompt: |
      Analyze the attached Excel file.
      Count how many times "apple" appears in the 'Product' column.
      Return ONLY the number.
      
      {document_content}
    expected: 5
    points: 25
    attachments:
      - sales_data.xlsx
    scoring:
      mode: numeric_from_text
      tolerance: 0
      
  - id: sum_values  
    prompt: |
      From the same data, calculate the total revenue for "apple" products.
      Return ONLY the number (no currency symbols).
      
      {document_content}
    expected: 2500
    points: 35
    attachments:
      - sales_data.xlsx
    scoring:
      mode: numeric_tolerance
      tolerance: 0.01
      method: abs

Knowledge Testing with Flexible Scoring

task_name: philosophy_knowledge
display_name: Ancient Philosophy Knowledge Test
description: Test knowledge of ancient Greek philosophers

tests:
  - id: name_philosophers
    prompt: List 5 ancient Greek philosophers. Separate names with commas.
    expected:
      - Socrates
      - Plato
      - Aristotle
      - Epicurus
      - Thales
      - Diogenes
      - Pythagoras
      - Heraclitus
    points: 20
    scoring:
      mode: contains_any
      partial_credit: true
      case_insensitive: true
      
  - id: socratic_method
    prompt: |
      In one sentence, what is the Socratic method?
    expected:
      - questioning
      - dialogue
      - inquiry
      - assumptions
    points: 30
    scoring:
      mode: contains_all
      partial_credit: true
      case_insensitive: true

Multiple Choice Questions

task_name: science_quiz
display_name: Science Knowledge Quiz
description: Multiple choice questions testing scientific knowledge

tests:
  - id: periodic_table_mcq
    prompt: |
      What is the chemical symbol for Gold?
      
      A) Au
      B) Ag
      C) Fe
      D) Cu
      
      Return ONLY the letter of the correct answer.
    expected: A
    points: 10
    scoring:
      mode: exact_match
      case_insensitive: true
      trim_whitespace: true
      
  - id: astronomy_mcq
    prompt: |
      Which planet is known as the "Red Planet"?
      
      A) Venus
      B) Jupiter
      C) Mars
      D) Saturn
      
      Return ONLY the letter of the correct answer.
    expected: C
    points: 10
    scoring:
      mode: exact_match
      case_insensitive: true
      trim_whitespace: true
      
  - id: biology_mcq
    prompt: |
      What is the powerhouse of the cell?
      
      A) Nucleus
      B) Ribosome
      C) Mitochondria
      D) Golgi apparatus
      
      Return ONLY the letter of the correct answer.
    expected: C
    points: 10
    scoring:
      mode: exact_match
      case_insensitive: true
      trim_whitespace: true

💡 Prompt Examples

Examples showing different ways to describe your benchmark tasks. The AI agent will interpret your intent and generate test cases automatically. These examples progress from simple one-liners to more detailed specifications.

Example 1: Just Say What You Want

I want to test if AI models can do basic math.

That's it! The AI agent will generate appropriate math questions and expected answers for you.

Example 2: Add Some Detail

Test if models can add 234 + 567, subtract 89 from 456, and multiply 23 by 4.

Example 3: Organized List Style

Create a geography quiz with these questions:

1. What's the capital of France? (Answer: Paris)
2. Name the longest river in the world (Answer: Nile or Amazon, accept either)
3. Which continent has the most countries? Give options:
   A) Asia
   B) Africa
   C) Europe
   D) North America
   The correct answer is B

Make the first two worth 15 points each and the multiple choice worth 20 points.

Example 4: Structured Requirements Style

Build a task to evaluate reading comprehension using an attached article.txt file.

Test 1: Count how many times the word "innovation" appears in the document
Expected: 12 occurrences
Points: 20

Test 2: Extract the main author's name from the first paragraph
Expected: "Dr. Sarah Johnson"
Points: 15

Test 3: List three key technologies mentioned in the article
Expected answers should include at least 3 of: artificial intelligence, quantum computing, biotechnology, renewable energy, nanotechnology
Points: 30

Example 5: Advanced Multi-Step Task

Design a chained calculation task for testing multi-step reasoning:

Step 1: "A store has 156 apples. If they sell 40% of them, how many are left?"
- Expected: 94 (accept 93.6 with rounding)
- Points: 25
- Save this result for the next step

Step 2: "If each remaining apple costs $0.75, what's the total value of remaining inventory?"
- Expected: 70.50 or 70.5
- Points: 35
- This should use the result from step 1

Step 3: "If apples are packed 6 per box, how many full boxes can be made?"
- Expected: 15
- Points: 40
- Should use the quantity from step 1

Example 6: Expert Technical Specification

Comprehensive JSON API response validation task:

test_1: Validate user profile JSON structure
prompt: "Generate a JSON object representing a user profile with fields: name (string), age (integer), email (string), active (boolean)"
expected: JSON schema with required fields and correct types
scoring: json_schema validation
points: 30

test_2: Extract nested values
prompt: "From this JSON: {'company': {'name': 'TechCorp', 'employees': {'count': 250, 'departments': ['Engineering', 'Sales', 'HR']}}}, extract the employee count"
expected: 250
scoring: numeric_from_text with tolerance 0
points: 20

test_3: Array manipulation
prompt: "Given the departments array from the previous JSON, return all departments that start with 'E'"
expected: ["Engineering"]
scoring: exact_match for JSON array
points: 25

🧠 Tips & Best Practices

Practical advice to help you create effective benchmarks and get the most out of your evaluations.

1. Start Simple: Often That's All You Need

You don't always need complex scoring modes. In many cases, just providing an expected value is enough: the system defaults to exact_match automatically.

# This works! No scoring mode needed.
tests:
  - id: capital_city
    prompt: "What is the capital of Japan? Answer with the city name only."
    expected: Tokyo

Add scoring modes only when you need specific behavior (numeric tolerance, partial matching, etc.).

2. Multiple Choice Questions Are Your Friend

Instead of crafting complex prompts with elaborate scoring rules, consider using multiple choice questions (MCQ). They're:

  • Easy to score definitively (A, B, C, or D)
  • Less ambiguous than free-form answers
  • Great for testing knowledge and reasoning
- id: science_mcq
  prompt: |
    Which planet is closest to the Sun?
    
    A) Venus
    B) Mercury
    C) Mars
    D) Earth
    
    Return ONLY the letter.
  expected: B

3. A Clear Prompt Beats Complex Scoring

Rather than relying on sophisticated scoring modes to handle ambiguous outputs, invest in writing clear, specific prompts. A prompt like:

"Return ONLY the number, no words or units."

...is more reliable than trying to extract numbers from verbose responses with complex parsing rules.

4. Use Benchmarks to Test Your Prompts

If your task scores consistently high across multiple models, that's a sign your prompt is well-crafted: clear, unambiguous, and easy to follow.

If scores are inconsistent or surprisingly low, the prompt might be ambiguous or the expected answer too strict. This is valuable feedback for refining your prompts!

Pro tip: A good benchmark task is also a good prompt engineering exercise.

5. When Results Surprise You, Check Model Responses

If a model scores lower than expected, don't guess why. Look at what it actually said:

  1. Click any row in the results table
  2. The detail panel opens on the right
  3. Expand "Test Results" to see each test
  4. Click a test to reveal the actual model response

This often reveals the issue immediately. Maybe the model gave the right answer but with extra text, or interpreted the question differently.

This is essential for iterating. Model responses tell you exactly how to refine your prompts and expected values.

6. Be Forgiving With Text Answers

Models may return "Paris" or "paris" or "Paris.", so use case_insensitive: true to avoid false negatives:

scoring:
  mode: exact_match
  case_insensitive: true
  trim_whitespace: true

7. Test With a Few Models First

Before running a full benchmark across all models, test with 2-3 models first. This lets you:

  • Catch prompt issues early
  • Refine expected values based on actual outputs
  • Save time and API costs while iterating

Once your task works well with a small set, expand to the full model list.