IFStruct is an eval for instruction-following on structured output tasks.
It tests whether a model can produce valid JSON or YAML that matches a target schema:
"Produce a recipe for blueberry muffins in JSON with this schema..."
"Generate five entries in a code review log for a llama.cpp PR, in valid YAML following this schema..."
The IFStruct test set is included in this repo at data/test.jsonl, and also on Huggingface at: https://huggingface.co/datasets/LiquidAI/ifstruct-v1.0
Frontier models can produce more or less perfect JSON and YAML to a schema, but small models still struggle, producing unparseable outputs and ignoring schema constraints. This is a very learnable task for even tiny (350M) models, however there are few evals targeting structured output and its common failure modes.
The difficulty of IFStruct is calibrated so that frontier models are expected to score near 100%. The tasks contain challenges such as:
Each response is run through a multi-stage verification pipeline:
[...] vs. wrapped object {"key": [...]}), and does the wrapper key name match?A sample passes only if all checks produce zero errors (score = 1). Any error means a fail (score = 0). The overall score is the pass rate across the test set.
The results file also reports pass rates sliced by output format (JSON vs. YAML), top-level structure (bare list vs. wrapper key), and entity type, along with the ten most common error categories.
git clone https://github.com/Liquid4All/ifstruct.git
cd ifstruct
uv sync
Create a local env file from the example:
cp .env.example .env
Set these values in .env:
BASE_URL=https://openrouter.ai/api/v1
API_KEY=your-api-key-here
The CLI automatically loads .env if it exists, and it also works if BASE_URL and API_KEY are already exported in your shell.
uv run ifstruct-eval \
--model google/gemini-3.5-flash \
--dataset data/test.jsonl \
--results-file results/latest.json \
--n-threads 64 \
-v
You can still override either setting explicitly with --base-url or --api-key.
--results-file writes a JSON artifact with run metadata, aggregate summary stats, and per-sample prompts, responses, and validation results.
IFStruct uses a 2,000-example test set in data/test.jsonl. Each example includes a prompt, a target schema, and explicit structural requirements for the response.
The eval sends each prompt to an OpenAI-compatible chat completions endpoint, captures the model response, and validates it against:
The CLI prints aggregate pass rates and can also write a full results artifact containing run metadata plus every prompt, response, and validation result.
Each JSONL row contains:
seedentity_typepromptjson_schematop_level_counttop_level_keyrequire_wrapper_keyrequire_code_blockrequire_no_commentaryoutput_format@article{liquidAI2026IFStruct,
author = {Liquid AI},
title = {IFStruct: Measuring structured-output compliance},
journal = {Liquid AI Blog},
year = {2026},
note = {www.liquid.ai/blog/ifstruct-v1.0}
}
Python
100.0%
IFStruct is an eval for instruction-following on structured output tasks.
It tests whether a model can produce valid JSON or YAML that matches a target schema:
"Produce a recipe for blueberry muffins in JSON with this schema..."
"Generate five entries in a code review log for a llama.cpp PR, in valid YAML following this schema..."
The IFStruct test set is included in this repo at data/test.jsonl, and also on Huggingface at: https://huggingface.co/datasets/LiquidAI/ifstruct-v1.0
Frontier models can produce more or less perfect JSON and YAML to a schema, but small models still struggle, producing unparseable outputs and ignoring schema constraints. This is a very learnable task for even tiny (350M) models, however there are few evals targeting structured output and its common failure modes.
The difficulty of IFStruct is calibrated so that frontier models are expected to score near 100%. The tasks contain challenges such as:
Each response is run through a multi-stage verification pipeline:
[...] vs. wrapped object {"key": [...]}), and does the wrapper key name match?A sample passes only if all checks produce zero errors (score = 1). Any error means a fail (score = 0). The overall score is the pass rate across the test set.
The results file also reports pass rates sliced by output format (JSON vs. YAML), top-level structure (bare list vs. wrapper key), and entity type, along with the ten most common error categories.
git clone https://github.com/Liquid4All/ifstruct.git
cd ifstruct
uv sync
Create a local env file from the example:
cp .env.example .env
Set these values in .env:
BASE_URL=https://openrouter.ai/api/v1
API_KEY=your-api-key-here
The CLI automatically loads .env if it exists, and it also works if BASE_URL and API_KEY are already exported in your shell.
uv run ifstruct-eval \
--model google/gemini-3.5-flash \
--dataset data/test.jsonl \
--results-file results/latest.json \
--n-threads 64 \
-v
You can still override either setting explicitly with --base-url or --api-key.
--results-file writes a JSON artifact with run metadata, aggregate summary stats, and per-sample prompts, responses, and validation results.
IFStruct uses a 2,000-example test set in data/test.jsonl. Each example includes a prompt, a target schema, and explicit structural requirements for the response.
The eval sends each prompt to an OpenAI-compatible chat completions endpoint, captures the model response, and validates it against:
The CLI prints aggregate pass rates and can also write a full results artifact containing run metadata plus every prompt, response, and validation result.
Each JSONL row contains:
seedentity_typepromptjson_schematop_level_counttop_level_keyrequire_wrapper_keyrequire_code_blockrequire_no_commentaryoutput_format@article{liquidAI2026IFStruct,
author = {Liquid AI},
title = {IFStruct: Measuring structured-output compliance},
journal = {Liquid AI Blog},
year = {2026},
note = {www.liquid.ai/blog/ifstruct-v1.0}
}
Python
100.0%