Phoenix Evals
GitHubOfficialFirst committed by jimbobbennettDistributed by GitHub
- Skill
- Tool integration
- Software development
- Apache-2.0
- Low risk
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
Phoenix Evals provides a structured approach to building, running, and validating evaluators for AI and LLM applications. It supports both Python and TypeScript, offering tools for code-based and LLM-based evaluation, experiment management, and error analysis. The framework emphasizes a code-first approach, encouraging developers to define deterministic evaluations before moving to LLM-based judges, and provides mechanisms to validate evaluator accuracy against human-labeled data.
What it does
- Builds custom code-based and LLM-based evaluators for AI applications.
- Supports batch evaluation of datasets using structured dataframes.
- Facilitates experiment management, including dataset creation and synthetic data generation.
- Provides tools for error analysis, including axial coding and failure taxonomy creation.
- Enables validation of evaluator accuracy against human-provided labels.
- Integrates with tracing and observability to sample and review application traces.
When to use it
- When you need to systematically evaluate the performance of LLM application outputs.
- When building RAG systems that require specific retrieval and faithfulness metrics.
- When you need to categorize and analyze failure patterns in AI agent workflows.
- When transitioning from manual testing to automated, repeatable evaluation experiments.
- When you need to validate that your automated judges align with human expectations.
Advantages
- Supports a code-first approach to evaluation for deterministic results.
- Provides a clear path for validating judge model accuracy.
- Offers structured methods for building failure taxonomies.
- Enables consistent evaluation across both Python and TypeScript environments.
- Integrates directly with tracing data for context-aware evaluation.
Usage examples
- “How do I build a custom LLM evaluator in Python?”
- The skill provides guidance on using the LLM class and custom templates to define evaluators that assess specific model outputs.
- “How can I categorize failures in my AI agent?”
- The skill outlines an axial coding process to group failure notes into structured taxonomies like planning, tool selection, or execution errors.
- “How do I run a batch evaluation on my dataset?”
- The skill demonstrates using the evaluate_dataframe function to process a dataframe and return scores for defined metrics.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/github/phoenix-evals/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip phoenix-evals.zip -d .agents/skills
Documentation by jimbobbennett
Phoenix Evals
Build evaluators for AI/LLM applications. Code first, LLM for nuance, validate against humans.
Quick Reference
Workflows
Starting Fresh: observe-tracing-setup → error-analysis → axial-coding → evaluators-overview
Building Evaluator: fundamentals → common-mistakes-python → evaluators-{code|llm}-{python|typescript} → validation-evaluators-{python|typescript}
RAG Systems: evaluators-rag → evaluators-code-* (retrieval) → evaluators-llm-* (faithfulness)
Production: production-overview → production-guardrails → production-continuous
Reference Categories
| Prefix | Description |
|---|---|
fundamentals-* | Types, scores, anti-patterns |
observe-* | Tracing, sampling |
error-analysis-* | Finding failures |
axial-coding-* | Categorizing failures |
evaluators-* | Code, LLM, RAG evaluators |
experiments-* | Datasets, running experiments |
validation-* | Validating evaluator accuracy against human labels |
production-* | CI/CD, monitoring |
Key Principles
| Principle | Action |
|---|---|
| Error analysis first | Can't automate what you haven't observed |
| Custom > generic | Build from your failures |
| Code first | Deterministic before LLM |
| Validate judges | >80% TPR/TNR |
| Binary > Likert | Pass/fail, not 1-5 |
Files
- ATTRIBUTION.mdAdded by AutoGineer931 B
- LICENSEAdded by AutoGineer10.0 KiB
- SKILL.md4.5 KiB
- references/axial-coding.md2.3 KiB
- references/common-mistakes-python.md7.0 KiB
- references/error-analysis-multi-turn.md1.3 KiB
- references/error-analysis.md4.2 KiB
- references/evaluate-dataframe-python.md4.4 KiB
- references/evaluators-code-python.md3.0 KiB
- references/evaluators-code-typescript.md1.2 KiB
- references/evaluators-custom-templates.md1.2 KiB
- references/evaluators-llm-python.md2.6 KiB
- references/evaluators-llm-typescript.md1.4 KiB
- references/evaluators-overview.md1.1 KiB
- references/evaluators-pre-built.md2.4 KiB
- references/evaluators-rag.md3.1 KiB
- references/experiments-datasets-python.md4.8 KiB
- references/experiments-datasets-typescript.md2.7 KiB
- references/experiments-overview.md1.7 KiB
- references/experiments-running-python.md2.9 KiB
- references/experiments-running-typescript.md3.1 KiB
- references/experiments-synthetic-python.md1.8 KiB
- references/experiments-synthetic-typescript.md2.2 KiB
- references/fundamentals-anti-patterns.md1.6 KiB
- references/fundamentals-model-selection.md1.4 KiB
- references/fundamentals.md1.8 KiB
- references/observe-sampling-python.md2.4 KiB
- references/observe-sampling-typescript.md3.9 KiB
- references/observe-tracing-setup.md3.3 KiB
- references/production-continuous.md3.6 KiB
- references/production-guardrails.md1.3 KiB
- references/production-overview.md2.3 KiB
- references/setup-python.md1.9 KiB
- references/setup-typescript.md981 B
- references/validation-evaluators-python.md1.0 KiB
- references/validation-evaluators-typescript.md4.4 KiB
- references/validation.md1.7 KiB
references/validation-evaluators-typescript.md
Validating Evaluators (TypeScript)
Validate an LLM evaluator against human-labeled examples before deploying it. Target: >80% TPR and >80% TNR.
Roles are inverted compared to a normal task experiment:
| Normal experiment | Evaluator validation |
|---|---|
| Task = agent logic | Task = run the evaluator under test |
| Evaluator = judge output | Evaluator = exact-match vs human ground truth |
| Dataset = agent examples | Dataset = golden hand-labeled examples |
Golden Dataset
Use a separate dataset name so validation experiments don't mix with task experiments in Phoenix.
Store human ground truth in metadata.groundTruthLabel. Aim for ~50/50 balance:
import type { Example } from "@arizeai/phoenix-client/types/datasets";
const goldenExamples: Example[] = [
{ input: { q: "Capital of France?" }, output: { answer: "Paris" }, metadata: { groundTruthLabel: "correct" } },
{ input: { q: "Capital of France?" }, output: { answer: "Lyon" }, metadata: { groundTruthLabel: "incorrect" } },
{ input: { q: "Capital of France?" }, output: { answer: "Major city..." }, metadata: { groundTruthLabel: "incorrect" } },
];
const VALIDATOR_DATASET = "my-app-qa-evaluator-validation"; // separate from task dataset
const POSITIVE_LABEL = "correct";
const NEGATIVE_LABEL = "incorrect";Validation Experiment
import { createClient } from "@arizeai/phoenix-client";
import { createOrGetDataset, getDatasetExamples } from "@arizeai/phoenix-client/datasets";
import { asExperimentEvaluator, runExperiment } from "@arizeai/phoenix-client/experiments";
import { myEvaluator } from "./myEvaluator.js";
const client = createClient();
const { datasetId } = await createOrGetDataset({ client, name: VALIDATOR_DATASET, examples: goldenExamples });
const { examples } = await getDatasetExamples({ client, dataset: { datasetId } });
const groundTruth = new Map(examples.map((ex) => [ex.id, ex.metadata?.groundTruthLabel as string]));
// Task: invoke the evaluator under test
const task = async (example: (typeof examples)[number]) => {
const result = await myEvaluator.evaluate({ input: example.input, output: example.output, metadata: example.metadata });
return result.label ?? "unknown";
};
// Evaluator: exact-match against human ground truth
const exactMatch = asExperimentEvaluator({
name: "exact-match", kind: "CODE",
evaluate: ({ output, metadata }) => {
const expected = metadata?.groundTruthLabel as string;
const predicted = typeof output === "string" ? output : "unknown";
return { score: predicted === expected ? 1 : 0, label: predicted, explanation: `Expected: ${expected}, Got: ${predicted}` };
},
});
const experiment = await runExperiment({
client, experimentName: `evaluator-validation-${Date.now()}`,
dataset: { datasetId }, task, evaluators: [exactMatch],
});
// Compute confusion matrix
const runs = Object.values(experiment.runs);
const predicted = new Map((experiment.evaluationRuns ?? [])
.filter((e) => e.name === "exact-match")
.map((e) => [e.experimentRunId, e.result?.label ?? null]));
let tp = 0, fp = 0, tn = 0, fn = 0;
for (const run of runs) {
if (run.error) continue;
const p = predicted.get(run.id), a = groundTruth.get(run.datasetExampleId);
if (!p || !a) continue;
if (a === POSITIVE_LABEL && p === POSITIVE_LABEL) tp++;
else if (a === NEGATIVE_LABEL && p === POSITIVE_LABEL) fp++;
else if (a === NEGATIVE_LABEL && p === NEGATIVE_LABEL) tn++;
else if (a === POSITIVE_LABEL && p === NEGATIVE_LABEL) fn++;
}
const total = tp + fp + tn + fn;
const tpr = tp + fn > 0 ? (tp / (tp + fn)) * 100 : 0;
const tnr = tn + fp > 0 ? (tn / (tn + fp)) * 100 : 0;
console.log(`TPR: ${tpr.toFixed(1)}% TNR: ${tnr.toFixed(1)}% Accuracy: ${((tp + tn) / total * 100).toFixed(1)}%`);Results & Quality Rules
| Metric | Target | Low value means |
|---|---|---|
| TPR (sensitivity) | >80% | Misses real failures (false negatives) |
| TNR (specificity) | >80% | Flags good outputs (false positives) |
| Accuracy | >80% | General weakness |
Golden dataset rules: ~50/50 balance · include edge cases · human-labeled only · never mutate (append new versions) · 20–50 examples is enough.
Re-validate when: prompt template changes · judge model changes · criteria updated · production FP/FN spike.
See Also
validation.md— Metric definitions and conceptsexperiments-running-typescript.md—runExperimentAPIexperiments-datasets-typescript.md—createOrGetDataset/getDatasetExamples
Requirements and compatibility
Written for: GitHub Copilot
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Python
The author says: Requires Phoenix server. Python skills need phoenix and openai packages; TypeScript skills need @arizeai/phoenix-client.
Security
What our scanner noticed· Low risk
- Instructions that use the network
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- First committed by
jimbobbennett
- Publisher
- GitHub (Official)
- Distributed by
- GitHub
- Source
- github/awesome-copilot · skills/phoenix-evals · commit 797337f
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (written by AutoGineer)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Contributors
- jimbobbennett, stbenjam
AutoGineer is not affiliated with or endorsed by jimbobbennett or GitHub.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download phoenix-evals.zip