English | 中文
This document describes the standardized Sample structure used by gage-eval, so that dataset onboarding, preprocessing, inference, judging, metrics, and reporting can share a single contract.
- OpenAI-style first:
messagesis the primary input for text, multimodal, and multi-turn tasks. - Explicit task type: use
task_typeso templates/metrics can be selected automatically. - Options vs. answers: keep candidates in
options, keep ground-truth inreferences. - Built-in few-shot: store reproducible few-shot in
few_shot_examples. - Trajectory alignment: store process references in
golden_trajectories(for agent-style evaluation). - Sandbox as top-level: describe execution environments via
sandboxinstead of burying it in metadata. - Debias support: use
unconditioned_inputfor PMI-like debiasing. - Mappable to current code: preprocessors can map legacy fields (
choices/metadata/label/...) into this schema. - Extension-friendly: keep task tags and slicing labels in
metadata/data_tag. - Inputs are read-only: put large/raw objects in
raw_assets; never directly render prompts from raw blobs. - Per-sample eval controls: use
eval_configfor sample-level judge/metric overrides. - Deprecate legacy prompt fields: do not keep
model_prompt_tmpl/model_prompt_placeholder.
Lifecycle
flowchart TD
RawRecord[RawRecord] --> Preprocess[Preprocess]
Preprocess --> Sample[Sample]
Sample --> Inference[Inference]
Sample --> Judge[Judge]
Inference --> PredictResult[PredictResult]
Judge --> EvalResult[EvalResult]
EvalResult --> Report[Report]
Top-level fields below do not include nested fields inside metadata.
| Field | Type | Required | Notes |
|---|---|---|---|
| schema_version | string | yes | Schema version |
| id | string | yes | Unique sample id |
| task_type | string | no | Task/question type |
| messages | list | yes | OpenAI-style messages |
| options | list | no | Multiple-choice candidates |
| references | list | yes | Ground-truth answers |
| label | string | no | String alias of references[0] |
| few_shot_examples | list | no | In-sample few-shot items |
| golden_trajectories | list | no | Process reference trajectories |
| sandbox | object | no | Execution environment config |
| metadata | object | no | Task/runtime metadata |
| data_tag | object | no | Slicing labels for statistics |
| raw_assets | object | no | Raw/large assets store |
| tools | list | no | OpenAI tool definitions |
| tool_choice | string/object | no | Tool choice strategy |
| sampling_params | object | no | Sampling parameters |
| generation_params | object | no | Generation parameters |
| eval_config | object | no | Per-sample evaluation control |
| unconditioned_input | string/list | no | Debiasing input |
| predict_result | list | no | Runtime inference results |
| eval_result | object | no | Runtime evaluation results |
messages follows the OpenAI multimodal message format; content is a list of segments.
| type | Field | Notes |
|---|---|---|
| text | text | Text |
| image_url | image_url.url | Image URL or local path |
| audio_url | audio_url.url | Audio URL or local path |
| video_url | video_url.url | Video URL or local path |
| file_url | file_url.url | Document URL or local path |
Rules:
messagesis the primary entry. If the raw record only containsprompt/text/question, the preprocessor should generatemessages.- Multimodal resources may use relative paths; preprocessing is responsible for path resolution and encoding as needed.
task_type makes the task/question type explicit so prompt renderers and metrics can make better defaults.
Suggested values:
| task_type | Use case |
|---|---|
| multiple-choice | Multiple-choice |
| short-answer | Short QA |
| dialogue | Multi-turn conversation |
| audio-translation | Audio translation |
| image-qa | Image QA |
| video-qa | Video understanding |
| doc-qa | Document understanding |
| text-to-image | Text-to-image |
| image-to-image | Image-to-image |
| text-to-audio | Text-to-audio |
| text-to-video | Text-to-video |
| code-generation | Code generation |
| agent | Agent tool-calling |
Notes:
- If omitted, renderers may infer it from task config or use defaults.
- If legacy data uses
question_type, preprocessors should map it totask_type.
options rules:
optionsis a list; each item containsidandcontent.- List order is the display order (helps reduce position bias).
references rules:
referencesis a list and only contains final answers.- Text tasks can use string arrays; multimodal tasks can use structured objects.
labelis a single-string alias, equivalent toreferences[0](or a normalized string form of it).
Option item:
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | Option identifier |
| content | string | yes | Option text |
Reference item:
| Field | Type | Required | Notes |
|---|---|---|---|
| answer | string/list | yes | Answer content |
| meta | object | no | Answer metadata |
Recommended answer formats:
- For text, prefer
[{"type":"text","text":"..."}]. - A plain string shorthand is allowed and can be normalized during preprocessing.
- For multimodal generation, use
image_url/audio_url/video_url/file_urlsegments. - Keep
labelas string; for multimodal generation it can be a path/id.
few_shot_examplesstores per-sample few-shot to guarantee reproducibility.- Each item is a “compact Sample”, typically only keeping
messages/options/references/label/tools/tool_choice. - Preprocessing can render
references[0](orlabel) into an assistant message and prepend them to the mainmessages. - Nested
few_shot_examplesis not allowed. - Do not include runtime/big fields like
predict_result/eval_result/raw_assets/sandbox.
Few-shot item:
| Field | Type | Required | Notes |
|---|---|---|---|
| messages | list | yes | Few-shot messages |
| options | list | no | Few-shot options |
| references | list | yes | Few-shot ground-truth |
| label | string | no | Alias of references[0] |
| tools | list | no | Tools definitions |
| tool_choice | string/object | no | Tool choice |
Rendering sketch:
flowchart LR
FewShotExamples[FewShotExamples] --> PromptRender[PromptRender]
Messages[Messages] --> PromptRender
PromptRender --> Inference[Inference]
golden_trajectoriesis a list of reference trajectories (each is a full trace).- Trajectory messages use the same structure as
messages, and may includetool_callsandtoolmessages. - Default evaluations often compare only
references; process-level evaluation must enable dedicated metrics.
sandbox describes sample-level execution environment preparation, suitable for code execution and agent tasks.
| Field | Type | Notes |
|---|---|---|
| image | string | Container image |
| files | object | Files to mount/copy |
| setup | string | Init script |
| env | object | Env vars |
Rules:
- Executors should read
sandboxfor environment setup. - In
files, keys are relative target paths; values are URIs or local paths. - If an executor does not support it, preprocessors may map it into
metadata.execution.
Preparation sketch:
flowchart TD
Sample[Sample] --> Sandbox[SandboxPrepare]
Sandbox --> Executor[Executor]
Executor --> Run[RunStep]
metadatais for task/runtime metadata (source ids, split, difficulty, etc.).data_tagis for slicing labels used by statistics and reporting (domain/language/category, etc.).
toolsfollows the OpenAI tool schema.tool_choicecontrols the tool selection strategy.- For agent tasks, preprocessors should keep tool definitions with the sample so that evaluations are reproducible.
raw_assetsstores raw/large objects (documents, images, audio, video, etc.).raw_assetsis not used directly for prompt rendering; preprocessing must convert it intomessages/media segments.
eval_config enables sample-level overrides for judging and metrics (e.g., different judge settings, extra constraints).
In the current implementation, arena reads eval_config for per-sample game controls (such as retry_illegal and max_turns) in src/gage_eval/role/adapters/arena.py.
unconditioned_inputis used by debiasing methods such as PMI.- It can be a string or a list, depending on the task and metric implementation.
At runtime, the framework writes results back to the Sample object:
predict_result: inference outputs (often messages/text/tool calls depending on backend)eval_result: judge outputs and/or metric outputs
predict_result example
{
"predict_result": [
{
"index": 0,
"message": {
"role": "assistant",
"content": [{"type": "text", "text": "B"}]
},
"raw_response": {},
"usage": {"total_tokens": 123},
"latency_ms": 1200
}
]
}eval_result example
{
"eval_result": {
"overall": {"score": 1.0, "passed": true},
"metrics": {
"exact_match": {"score": 1.0},
"bleu": {"score": 0.72}
},
"judge": {
"model": "gpt-4o-mini",
"verdict": "correct",
"reason": "Answer matches the reference"
}
}
}The standardized Sample is designed to be compatible with the current gage-eval implementation through preprocessing mappings.
Typical mappings:
- legacy
question/prompt/text->messagesvianormalize_messages - legacy
choices/options-> normalizedchoices+metadata.option_mapvianormalize_options/map_question_option_answer - legacy
answer/label->labelandmetadata.correct_choice(optionalreferences) - multimodal legacy fields ->
messages[*].content[*]segments +inputs.multi_modal_data
Code excerpt: writing predict_result
def append_predict_result(sample: Dict[str, Any], model_output: Optional[Dict[str, Any]]) -> None:
# Skip empty outputs
if not isinstance(model_output, dict) or not model_output:
return
predict_result = sample.setdefault("predict_result", [])
if not isinstance(predict_result, list):
predict_result = sample["predict_result"] = []
entry = copy.deepcopy(model_output)
entry.setdefault("index", len(predict_result))
if "message" not in entry:
entry["message"] = _build_message(entry)
predict_result.append(entry)Below are example Sample JSON snippets for common task types.
{
"schema_version": "v1",
"id": "qa_0001",
"task_type": "short-answer",
"messages": [
{
"role": "user",
"content": [{"type": "text", "text": "What is the capital of France?"}]
}
],
"references": [{"answer": [{"type": "text", "text": "Paris"}]}],
"label": "Paris",
"metadata": {"dataset": "demo"}
}{
"schema_version": "v1",
"id": "mc_0001",
"task_type": "multiple-choice",
"messages": [
{
"role": "user",
"content": [{"type": "text", "text": "Which one is a mammal?"}]
}
],
"options": [
{"id": "A", "content": "Shark"},
{"id": "B", "content": "Dolphin"}
],
"references": [{"answer": [{"type": "text", "text": "B"}]}],
"label": "B",
"metadata": {"option_map": {"A": "Shark", "B": "Dolphin"}}
}{
"schema_version": "v1",
"id": "dlg_0001",
"task_type": "dialogue",
"messages": [
{"role": "user", "content": [{"type": "text", "text": "Explain recursion."}]},
{"role": "assistant", "content": [{"type": "text", "text": "Recursion is ..."}]},
{"role": "user", "content": [{"type": "text", "text": "Give an example."}]}
],
"references": [{"answer": [{"type": "text", "text": "..." }]}]
}{
"schema_version": "v1",
"id": "imgqa_0001",
"task_type": "image-qa",
"messages": [
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": "inputs/apple_0001.png"}},
{"type": "text", "text": "What fruit is shown in the image?"}
]
}
],
"references": [{"answer": [{"type": "text", "text": "apple"}]}],
"label": "apple"
}{
"schema_version": "v1",
"id": "aud_0001",
"task_type": "audio-translation",
"messages": [
{
"role": "user",
"content": [
{"type": "audio_url", "audio_url": {"url": "inputs/hello.wav"}},
{"type": "text", "text": "Translate the audio into English."}
]
}
],
"references": [{"answer": [{"type": "text", "text": "Hello"}]}],
"label": "Hello"
}{
"schema_version": "v1",
"id": "vid_0001",
"task_type": "video-qa",
"messages": [
{
"role": "user",
"content": [
{"type": "video_url", "video_url": {"url": "inputs/demo.mp4"}},
{"type": "text", "text": "Describe what happens in the video."}
]
}
],
"references": [{"answer": [{"type": "text", "text": "..."}]}]
}{
"schema_version": "v1",
"id": "doc_0001",
"task_type": "doc-qa",
"messages": [
{
"role": "user",
"content": [
{"type": "file_url", "file_url": {"url": "inputs/paper.pdf"}},
{"type": "text", "text": "Summarize section 2."}
]
}
],
"references": [{"answer": [{"type": "text", "text": "..."}]}]
}{
"schema_version": "v1",
"id": "code_0001",
"task_type": "code-generation",
"messages": [
{
"role": "user",
"content": [{"type": "text", "text": "Write Python code to compute Fibonacci numbers."}]
}
],
"sandbox": {
"image": "python:3.10",
"setup": "python -V"
},
"references": [{"answer": [{"type": "text", "text": "..."}]}]
}{
"schema_version": "v1",
"id": "t2i_0001",
"task_type": "text-to-image",
"messages": [
{
"role": "user",
"content": [{"type": "text", "text": "Generate an image of an apple on a table."}]
}
],
"references": [
{"answer": [{"type": "image_url", "image_url": {"url": "refs/apple_0001.png"}}]}
],
"label": "refs/apple_0001.png"
}{
"schema_version": "v1",
"id": "i2i_0001",
"task_type": "image-to-image",
"messages": [
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": "inputs/sketch_0001.png"}},
{"type": "text", "text": "Colorize the sketch."}
]
}
],
"references": [
{"answer": [{"type": "image_url", "image_url": {"url": "refs/color_0001.png"}}]}
],
"label": "refs/color_0001.png"
}{
"schema_version": "v1",
"id": "t2a_0001",
"task_type": "text-to-audio",
"messages": [
{
"role": "user",
"content": [{"type": "text", "text": "Generate an audio clip of ocean waves."}]
}
],
"references": [{"answer": [{"type": "audio_url", "audio_url": {"url": "refs/ocean_0001.wav"}}]}],
"label": "refs/ocean_0001.wav"
}{
"schema_version": "v1",
"id": "t2v_0001",
"task_type": "text-to-video",
"messages": [
{
"role": "user",
"content": [{"type": "text", "text": "Generate a short video of a running dog."}]
}
],
"references": [{"answer": [{"type": "video_url", "video_url": {"url": "refs/dog_0001.mp4"}}]}],
"label": "refs/dog_0001.mp4"
}{
"schema_version": "v1",
"id": "agent_0001",
"task_type": "agent",
"messages": [
{"role": "user", "content": [{"type": "text", "text": "Search the weather and summarize."}]}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}
],
"tool_choice": "auto",
"golden_trajectories": [
[
{
"role": "assistant",
"tool_calls": [
{"id": "call_1", "type": "function", "function": {"name": "get_weather", "arguments": "{\"city\":\"Paris\"}"}}
]
},
{"role": "tool", "tool_call_id": "call_1", "content": "Sunny, 22C"},
{"role": "assistant", "content": [{"type": "text", "text": "Paris is sunny at 22C."}]}
]
],
"references": [{"answer": [{"type": "text", "text": "Paris is sunny at 22C."}]}]
}Agent execution flow
sequenceDiagram
participant User
participant Model
participant Tool
User->>Model: messages and tools
Model->>Tool: tool_call
Tool-->>Model: tool_result
Model-->>User: final_answer
- Preprocessors can emit a dict or a
Sampledataclass.DataManagerwill validate and normalize before yielding dicts to the runtime. - The default envelope validator requires
schema_version,id, andmessages(src/gage_eval/assets/datasets/validation.py). - Use
normalize_sampleandmerge_multimodal_inputsto standardize messages and media fields.
Minimal validation config example:
datasets:
- dataset_id: demo
loader: jsonl
params:
path: /path/to/data.jsonl
schema:
mode: warn- Inference and arena steps append outputs via
append_predict_result(src/gage_eval/evaluation/sample_envelope.py). - Judge outputs are merged via
update_eval_result, and downstream metrics resolve them throughresolve_model_output/resolve_judge_output.
- Current runtime utilities normalize
choices; if you maintainoptions, map them intochoicesandmetadata.option_mapduring preprocessing. labelandmetadata.correct_choiceare commonly used by multiple-choice metrics and judge adapters.