Skip to main content

Evaluation Engine

PromptVault's evaluation engine runs your prompts against datasets using LLMs, scores the results, and tracks costs.

How It Works​

  1. Load the prompt version and dataset
  2. Substitute variables: {question} → actual input values
  3. Call the LLM for each dataset item
  4. Score results (exact match by default)
  5. Track latency, token usage, and cost
  6. Aggregate metrics across all items

Running an Evaluation​

Via CLI​

promptctl eval run my-prompt \
--dataset my-data \
--model-config '{"provider": "gemini", "model": "gemini-3.7-flash"}'

Via API​

curl -X POST http://localhost:8000/api/evaluations \
-H "Content-Type: application/json" \
-d '{
"prompt_name": "my-prompt",
"dataset_name": "my-data",
"llm_config": {"provider": "gemini", "model": "gemini-3.7-flash"}
}'

Via MCP​

evaluation_run(prompt_name="my-prompt", dataset_name="my-data")

Metrics​

MetricDescription
exact_match_rateFraction of outputs matching expected (case-insensitive, stripped)
avg_latency_msAverage response time in milliseconds
avg_costAverage cost per item in USD
total_tokensAggregate {prompt_tokens, completion_tokens, total_tokens}
total_itemsTotal dataset items evaluated
successful_itemsItems completed without error
failed_itemsItems that errored

Scoring​

Default scorer: exact match (case-insensitive, whitespace-stripped).

# "Paris." vs "Paris" → 0.0 (punctuation mismatch)
# "Paris" vs "Paris" → 1.0 (match)
# "paris" vs "Paris" → 1.0 (case-insensitive)

Custom scoring can be added via the model_config.cost_per_1k_tokens override for cost, or by extending the evaluation engine.

Cost Calculation​

Cost is computed automatically based on the model name using the built-in cost table.

Formula:

cost = (prompt_tokens / 1000) * input_price + (completion_tokens / 1000) * output_price

Override Cost​

Provide custom prices in model_config:

{
"provider": "openai",
"model": "my-custom-model",
"cost_per_1k_tokens": {"input": 0.001, "output": 0.002}
}

Pricing Table (per 1K tokens, August 2026)​

OpenAI​

ModelInputOutput
gpt-4o$0.0025$0.01
gpt-4o-mini$0.00015$0.0006
gpt-4.1$0.002$0.008
gpt-4.1-mini$0.0004$0.0016
gpt-4.1-nano$0.0001$0.0004
gpt-5$0.00125$0.01
gpt-5-mini$0.00025$0.002
gpt-5-nano$0.00005$0.0004
o3$0.002$0.008
o3-mini$0.0011$0.0044
o4-mini$0.0011$0.0044

Anthropic​

ModelInputOutput
claude-haiku-4-5$0.001$0.005
claude-sonnet-5$0.002$0.01
claude-opus-5$0.005$0.025
claude-opus-4-7$0.005$0.025

Google Gemini​

ModelInputOutput
gemini-3.7-flash$0.00075$0.00375
gemini-3.6-flash$0.00075$0.00375
gemini-3.5-flash$0.0015$0.009
gemini-3.1-pro$0.002$0.012
gemini-3-flash$0.0005$0.003
gemini-2.5-flash$0.00015$0.0006
gemini-2.5-flash-lite$0.0001$0.0004
gemini-2.0-flash$0.0001$0.0004

Comparing Evaluations​

Run the same prompt with different models or configurations, then compare:

# Run with Gemini
promptctl eval run my-prompt --dataset test \
--model-config '{"provider": "gemini", "model": "gemini-3.7-flash"}'
# → eval-id-1

# Run with OpenAI
promptctl eval run my-prompt --dataset test \
--model-config '{"provider": "openai", "model": "gpt-4.1-mini"}'
# → eval-id-2

# Compare
curl http://localhost:8000/api/evaluations/eval-id-1/report
curl http://localhost:8000/api/evaluations/eval-id-2/report

Example Output​

{
"metrics": {
"avg_latency_ms": 3542,
"avg_cost": 0.000015,
"exact_match_rate": 0.5,
"total_items": 2,
"successful_items": 2,
"failed_items": 0
},
"results": [
{
"input": {"question": "What is 2+2?"},
"expected_output": "4",
"actual_output": "4",
"scores": {"exact_match": 1.0},
"cost": 0.000013,
"latency_ms": 1673
},
{
"input": {"question": "Capital of France?"},
"expected_output": "Paris",
"actual_output": "Paris.",
"scores": {"exact_match": 0.0},
"cost": 0.000017,
"latency_ms": 5412
}
]
}

Note: The second result scored 0.0 because the LLM added a period ("Paris." vs "Paris"). This is the expected behavior of exact match scoring — it catches formatting differences.