Skip to content

Multimodal Eval

Dataset.from_jsonl(...) recognises typed parts in an item's input field and resolves file paths into real Image / PDF objects at load time.

JSONL syntax

Each line is a single test case; input may be a string (legacy / text-only) or a list of typed parts:

{"input": "What is 2 + 2?", "expected": "4"}
{"input": [{"type": "text", "text": "Letters in this image?"}, {"type": "image", "path": "fixtures/cat.jpg"}], "expected": "CAT"}
{"input": [{"type": "text", "text": "Summarise this contract."}, {"type": "pdf", "path": "fixtures/contract.pdf"}], "expected": "Two-year service agreement"}
{"input": [{"type": "text", "text": "Describe."}, {"type": "image", "url": "https://example.com/x.png"}], "expected": "..."}

Supported part types:

Type Required keys Optional keys
text text
image path or url detail
pdf path or url

Paths are resolved relative to the JSONL file's directory — moving the dataset moves its referenced media along with it.

Running an eval

from fastaiagent import Agent, LLMClient, evaluate, Dataset

agent = Agent(name="vision-eval", llm=LLMClient(provider="openai", model="gpt-4o"))

ds = Dataset.from_jsonl("eval/multimodal_cases.jsonl")
results = evaluate(
    agent_fn=lambda mm_input: agent.run(mm_input).output,
    dataset=ds,
    scorers=["exact_match", "contains"],
)
print(results.summary())

evaluate() calls agent_fn with each item's input value (not the whole item dict) — already a list of str | Image | PDF once the dataset is loaded — so agent.run(mm_input) works without any transformation. You can also pass agent_fn=agent.run directly. See examples/78_multimodal_eval.py for a runnable script.

Vision-quality scoring

The built-in scorers (exact_match, contains, similarity) operate on the agent's text output and are unchanged by multimodal input. For vision-quality scoring (e.g. "did the agent identify the right object?") write a custom LLM-as-Judge scorer using the existing scorer framework.