Files
promptfoo--promptfoo/.claude/skills/promptfoo-evals/references/cheatsheet.md
T
wehub-resource-sync 0d3cb498a3
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Waiting to run
Test and Publish Multi-arch Docker Image / test (push) Waiting to run
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Blocked by required conditions
CI / Shell Format Check (push) Waiting to run
CI / Check Ruby (3.4) (push) Waiting to run
CI / CI Config (push) Waiting to run
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Blocked by required conditions
CI / Build on Node ${{ matrix.node }} (push) Blocked by required conditions
CI / Style Check (push) Waiting to run
CI / Generate Assets (push) Waiting to run
CI / Check Python (3.14) (push) Waiting to run
CI / Check Python (3.9) (push) Waiting to run
CI / Build Docs (push) Waiting to run
CI / Code Scan Action (push) Waiting to run
CI / Site tests (push) Waiting to run
CI / webui tests (push) Waiting to run
CI / Run Integration Tests (push) Waiting to run
CI / Run Smoke Tests (push) Waiting to run
CI / Go Tests (push) Waiting to run
CI / Share Test (push) Waiting to run
CI / Redteam (Production API) (push) Waiting to run
CI / Redteam (Staging API) (push) Waiting to run
CI / GitHub Actions Lint (push) Waiting to run
CI / Check Ruby (3.0) (push) Waiting to run
release-please / release-please (push) Waiting to run
release-please / build (push) Blocked by required conditions
release-please / publish-npm (push) Blocked by required conditions
release-please / publish-npm-backfill (push) Waiting to run
release-please / docker (push) Blocked by required conditions
release-please / publish-code-scan-action (push) Blocked by required conditions
release-please / attest-code-scan-action (push) Blocked by required conditions
Validate Renovate Config / Validate Renovate Configuration (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:24:08 +08:00

10 KiB

Promptfoo Eval Cheatsheet

Config structure

Field order: description, env, prompts, providers, defaultTest, scenarios, tests.

# yaml-language-server: $schema=https://promptfoo.dev/config-schema.json
description: 'Summarization quality' # 3-10 words

prompts:
  - file://prompts/main.txt # plain text with {{variables}}
  - file://prompts/chat.json # chat format [{role, content}]

providers:
  - openai:chat:gpt-4.1-mini # model ID shorthand
  - id: anthropic:messages:claude-sonnet-4-6
    label: claude # display name in results
    config:
      temperature: 0

defaultTest: # shared across all tests
  assert:
    - type: cost
      threshold: 0.01
    - type: latency
      threshold: 5000

tests:
  - file://tests/*.yaml # glob loads all test files

Environment variables in configs

Use Nunjucks syntax with quotes — shell syntax ($VAR) does not work:

# ✅ Correct
apiKey: '{{env.OPENAI_API_KEY}}'
baseUrl: '{{env.API_BASE_URL}}'

# ❌ Wrong
apiKey: $OPENAI_API_KEY

Assertion types

Deterministic (use first)

Type What it checks
equals Exact match
contains / icontains Substring (case-sensitive / insensitive)
contains-all / contains-any All or any substrings
icontains-all / icontains-any Case-insensitive variants
starts-with Prefix match
regex Regex pattern
is-json Valid JSON (optional JSON Schema in value)
contains-json Output contains valid JSON
javascript value: "output.length < 100" (return bool or {pass, score, reason})
python Same as javascript but Python
cost threshold: 0.01 (max cost in dollars)
latency threshold: 5000 (max ms)
word-count Validate word count

All deterministic types support not- prefix: not-contains, not-regex, etc.

Similarity

Type What it checks
similar Cosine similarity (set threshold: 0.8)
levenshtein Edit distance
rouge-n ROUGE score (summarization)
bleu BLEU score (translation)

Model-graded (use sparingly — costs money, non-deterministic)

Type When to use
llm-rubric Custom criteria: value: "Is helpful, accurate, and concise"
factuality Check factual accuracy against a reference
answer-relevance Is the answer relevant to the query
context-faithfulness Is the response grounded in provided context
context-recall Does the context contain needed info
model-graded-closedqa Closed-domain QA scoring

Tool/function call

Type What it checks
is-valid-openai-tools-call Valid OpenAI tools call format
is-valid-openai-function-call Valid function call format

Classification

Type What it checks
moderation OpenAI moderation API
is-refusal Model refused to answer
classifier Custom text classification

Special

Type What it does
select-best Compare all outputs, pick best
human Manual grading via web UI
webhook External validation endpoint

Assertion options

Assertions support these optional fields:

assert:
  - type: icontains
    value: 'expected text'
    weight: 2 # relative importance for scoring (default: 1)
    threshold: 0.8 # assertion-specific (e.g. min score for graded; max for cost/latency)
    metric: 'relevance' # custom metric name for reporting

Model-graded provider selection

Pin the grader model/provider explicitly for stable scoring:

defaultTest:
  options:
    provider: openai:gpt-5-mini

tests:
  - description: 'Quality check'
    assert:
      - type: llm-rubric
        value: 'Accurate and concise'
        # Optional per-assertion override:
        # provider: anthropic:messages:claude-sonnet-4-6

Provider patterns

LLM providers

# OpenAI
- openai:chat:gpt-4.1-2025-04-14
- openai:chat:gpt-4.1-mini
- openai:responses:gpt-4.1

# Anthropic
- anthropic:messages:claude-sonnet-4-6
- anthropic:messages:claude-haiku-4-5-20251001

# Google
- google:gemini-2.5-pro
- google:gemini-2.5-flash
- google:gemini-2.0-flash

# AWS Bedrock
- bedrock:anthropic.claude-sonnet-4-6
- bedrock:anthropic.claude-haiku-4-5-20251001-v1:0

# Other
- azure:chat:my-deployment
- groq:llama-3.3-70b-versatile
- ollama:chat:llama3.3
- mistral:mistral-large-latest
- togetherai:meta-llama/Llama-4-Scout-Instruct

HTTP endpoint

providers:
  - id: https
    label: my-api
    config:
      url: 'https://api.example.com/generate'
      method: POST
      headers:
        Content-Type: application/json
      body:
        prompt: '{{prompt}}'
      transformResponse: 'json.output'

Python provider

providers:
  - file://provider.py
# provider.py
def call_api(prompt, options, context):
    # Call your system under test
    result = my_system(prompt)
    return {"output": result}

JavaScript provider

providers:
  - file://provider.js
// provider.js
module.exports = {
  id: () => 'my-provider',
  callApi: async (prompt) => {
    const result = await mySystem(prompt);
    return { output: result };
  },
};

Echo (testing assertions without an LLM)

providers:
  - echo # Returns the prompt as output

JSON mode (force structured output)

providers:
  - id: openai:chat:gpt-4.1-mini
    config:
      temperature: 0
      response_format:
        type: json_object

Test patterns

Basic test

- description: 'Returns correct answer'
  vars:
    question: 'What is 2+2?'
  assert:
    - type: contains
      value: '4'

JSON output validation

- description: 'Returns valid structured output'
  vars:
    input: 'Banana'
  assert:
    - type: is-json
      value:
        type: object
        required: [color]
        properties:
          color: { type: string }
    - type: javascript
      value: "JSON.parse(output).color.toLowerCase() === 'yellow'"

Faithfulness check (include source in rubric)

- description: 'Summary is grounded in source'
  vars:
    article: 'MIT researchers developed an aluminum-sulfur battery...'
  assert:
    - type: llm-rubric
      value: |
        The summary only states facts from this source:
        "{{article}}"
        It does not add, infer, or fabricate any claims.

Transform output before assertions

When models wrap JSON in markdown fences or add extra text, use options.transform to clean the output before assertions run:

- description: 'Parses JSON from markdown output'
  vars:
    input: 'Give me a JSON object'
  options:
    transform: "output.replace(/```json\\n?|```/g, '').trim()"
  assert:
    - type: is-json

Dataset-driven tests (scale)

# CSV/JSONL/XLSX datasets
tests: file://tests.csv

# Script-generated tests
tests: file://generate_tests.py:create_tests

Reusable assertion templates

assertionTemplates:
  noHallucination: &noHallucination
    type: llm-rubric
    value: 'Response only contains information supported by the context'

tests:
  - description: 'Grounded response'
    vars: { query: 'What is our refund policy?' }
    assert:
      - *noHallucination

Default test with shared constraints

defaultTest:
  assert:
    - type: not-icontains
      value: 'As an AI'
    - type: cost
      threshold: 0.005
    - type: latency
      threshold: 3000

Weighted scoring

- description: 'Balanced quality check'
  vars:
    question: 'Explain quantum computing'
  assert:
    - type: llm-rubric
      value: 'Technically accurate'
      weight: 3
      metric: accuracy
    - type: llm-rubric
      value: 'Easy to understand for a beginner'
      weight: 1
      metric: clarity
    - type: javascript
      value: "output.split(' ').length <= 200"
      weight: 1
      metric: conciseness

CLI commands

Always use --no-cache during development to avoid stale results.

npx promptfoo@latest validate config -c path/to/promptfooconfig.yaml
npx promptfoo@latest eval -c path/to/promptfooconfig.yaml -o output.json --no-cache --no-share

For CI/non-UI workflows, use -o output.json and check success, score, and error fields.

Inside the promptfoo repo, use the local build:

source ~/.nvm/nvm.sh && nvm use
npm run local -- validate config -c path/to/promptfooconfig.yaml
npm run local -- eval -c path/to/promptfooconfig.yaml -o output.json --no-cache --no-share

Add --env-file .env only when the eval needs local credentials and that file exists.

Do not run npm run local -- view unless explicitly asked.