UniCycle
May 17, 2026 ยท View on GitHub
UniCycle is a benchmark for text-to-image-to-text (T2I2T) consistency. A model is given a text prompt, generates an image, then answers visual questions about that generated image. The benchmark measures whether the final answers remain consistent with the original text prompt.
What This Benchmark Measures
Each benchmark example contains:
- A text prompt in
short_description - A task/category label in
type - A list of QA pairs in
qa_pairs
The evaluation pipeline is:
- Text prompt -> image generation
- Generated image -> visual question answering
- Model answers -> LLM judge against the original prompt
- Prompt-level metrics aggregation
This benchmark is intended to test whether a model preserves structured information such as:
- Spatial relations
- Negation
- Attributes and materials
- Comparative reasoning
- Action and state consistency
Repository Layout
data/
self_built.jsonl
tiif_style.jsonl
inference/
run_t2t_inference.py
t2t_bagel_inference.py
t2t_janus_inference.py
t2t_showo_inference.py
evaluation/
run_t2t_eval.py
T2T_llm_judge.py
metrics_t2t.py
assets/
*.png
Data
The repository currently includes two benchmark files:
data/tiif_style.jsonl: 1649 examplesdata/self_built.jsonl: 689 examples
Required Fields
type: benchmark category, for exampleaction+textureornegation+3dshort_description: the text prompt used for image generationqa_pairs: ordered list of question-answer dictionaries
Each entry in qa_pairs contain:
question: the visual questionanswer: the reference answer implied by the prompt
Example
{
"type": "action+texture",
"short_description": "A turtle sitting on a wooden log.",
"qa_pairs": [
{
"question": "What is the turtle doing in the image? A. Swimming B. Running C. Sitting D. Flying",
"answer": "C"
},
{
"question": "What material does the log appear to be made of? A. Glass B. Metal C. Wood D. Plastic",
"answer": "C"
}
]
}
Example Cases
The benchmark covers prompt-to-image-to-question consistency cases such as spatial reasoning, negation, materials, and compositional attributes.

Dataset Distribution
The two current splits have different distributions and can be used as complementary evaluation sets.
self_built question distribution:

self_built category-by-question-type distribution:

tiif_style question distribution:

tiif_style category-by-question-type distribution:

Supported Backends
The benchmark runner currently exposes three inference backends:
janusbagelshowo
Important Backend Limitation
This repository currently contains the benchmark wrappers, but does not contain all model source code and weights required by every backend.
janusdepends on the Janus codebase and model weightsbageldepends on BAGEL-related modules and checkpointsshowodepends on Show-o-related modules, transport code, and config files
In particular, the current repository does not include the full local packages referenced by:
inference/t2t_bagel_inference.pyinference/t2t_showo_inference.py
So for open-source users, these backends require additional code/assets in the local environment before they can run successfully.
Installation
1. Create an environment
conda create -n unicycle python=3.10
conda activate unicycle
pip install -r requirements.txt
2. Install backend-specific dependencies
The benchmark runner itself uses standard Python packages plus PyTorch/OpenAI tooling, but actual inference also requires backend-specific model code and checkpoints.
At minimum:
janusrequires the Janus library and model weightsbagelrequires the BAGEL-related libraries/codebase and checkpointsshoworequires the Show-o-related libraries/codebase, checkpoints, and a config file
Backend-Specific Inference Libraries
The three inference backends are wrappers around their corresponding model ecosystems, so running inference requires the relevant backend libraries to already exist in the environment.
janusinference uses Janus-specific modules such asjanus.modelsandjanus.utils.iobagelinference uses BAGEL-specific modules such asmodeling.bagel,modeling.autoencoder, and related local componentsshowoinference uses Show-o-specific modules such asmodels,transport,datasets.utils, and related config/runtime code
In other words:
requirements.txtcovers the shared runtime dependencies used by the benchmark wrappers- backend inference still depends on the corresponding Janus / BAGEL / Show-o libraries and checkpoints
If you want this repository to be fully runnable by external users, you should either:
- Vendor or submodule the required backend codebases into the project, or
- Add explicit setup instructions for each backend library and checkpoint
Minimal Commands
End-to-End Evaluation
The recommended entrypoint is:
python evaluation/run_t2t_eval.py \
--backend janus \
--bench data/self_built.jsonl \
--output_dir output \
--model_path deepseek-ai/Janus-Pro-7B \
--api_key "$OPENAI_API_KEY" \
--judge_model gpt-4o-mini
This command runs:
- Inference
- LLM judging
- Metric aggregation
Inference Only
python inference/run_t2t_inference.py \
--backend janus \
--input data/self_built.jsonl \
--output output/janus_predictions.jsonl \
--out_image_dir output/janus_images \
--model_path deepseek-ai/Janus-1.3B
Shell Wrapper
bash evaluation/run_t2t_eval.sh \
--backend janus \
--bench data/self_built.jsonl \
--output_dir output \
--model_path deepseek-ai/Janus-1.3B \
--api_key "$OPENAI_API_KEY"
Evaluation Outputs
evaluation/run_t2t_eval.py writes the following files into --output_dir:
<run_name>_predictions.jsonl: raw inference output<run_name>_judged.jsonl: question-level rows with LLM judge outputs<run_name>_question_scores.jsonl: question-level file with prompt scores written back<run_name>_prompt_scores.jsonl: prompt-level metrics<run_name>_images/: generated images
Judged Output Fields
Typical fields include:
typeshort_descriptionq_indexquestionreference_answeransweranswer_normllm_judgellm_rawllm_errorif the judge request failed
llm_error means the judge row could not be evaluated normally, typically because the API request failed or the returned content could not be parsed into the expected JSON format.
no_eval is a reserved evaluation value used when a row should be excluded from normal metric computation. It is filtered from standard prompt scoring.
Metric Output
Prompt-level metrics currently include:
soft_scorehard_scorestrict_soft_scorestrict_hard_scorehas_no_evalhas_llm_error
Metric meanings:
soft_score: average prompt-level score over valid evaluated questionshard_score:1.0only if the prompt-level soft score is exactly1.0, otherwise0.0strict_soft_score: if any question under the same prompt hasno_evalorllm_error, the prompt receives0.0; otherwise it matchessoft_scorestrict_hard_score: hard version ofstrict_soft_scorehas_no_eval: whether any question belonging to the prompt was filtered asno_evalhas_llm_error: whether any question belonging to the prompt had a judge failure
The metric implementation is in evaluation/metrics_t2t.py.
Result Visualizations
The repository also includes summary result plots for benchmark reporting:
Soft-score results:

Hard-score results:
