Output files: json, csv and junit
The table is for you. Everything else that wants these results, a dashboard, a spreadsheet, a build server, wants a file.
-o takes a path and picks the format from the extension. The same run can write several.
promptfoo eval -o results.json -o results.csv -o results.junit.xmlWhat is in the JSON
The JSON is the complete record: the config that ran, every answer, every assertion with its score and reason, and a summary. Two parts of it are worth knowing by name.
promptfoo eval -o results.json > /dev/null
python3 -c "
import json
d = json.load(open('results.json'))
print(json.dumps(d['results']['stats']['successes']), 'passed')
print(json.dumps(d['results']['stats']['failures']), 'failed')
print(d['results']['prompts'][0]['metrics']['namedScores'])
"stats holds the counts, which is what a pass rate is built from. namedScores holds the metrics you named in lesson 11, one number each. Those two are what a dashboard reads; everything else in the file is detail for when a number looks wrong.
The other two formats
CSV is one row per result, for the people who want to sort and filter in a spreadsheet. It is the natural partner of the CSV tests from lesson 7: questions go in as a spreadsheet, answers come out as one.
JUnit XML is the format every build server already understands. Write it and your evals appear in the same test report as your unit tests, with names and failure messages, which is the shortest path to making them visible to a team that does not run promptfoo.
-o results.json and keep it as an artifact.- Write
results.csvas well and open it in a spreadsheet. - Add a second named metric and watch it appear in
namedScores. - Find the
reasonof a failed assertion inside the JSON.
This is what real progress feels like.