ai-eval-ci
CI/CDパイプライン内でAIエージェントとLLM評価を実行し、AI出力品質が低下した際にビルドを失敗させる自動化された品質ゲートを構築できます。「AIエージェントをテストしたい」「CIに評価機能を追加したい」「プロンプトの劣化を検出したい」「モデルを比較したい」「LLM出力品質を評価したい」「AI品質ゲートをセットアップしたい」「デプロイ前にエージェントをベンチマークしたい」といった要望に対応します。Cobalt、Promptfoo、Braintrustなどの評価フレームワーク、LLM-as-judge スコアリング、閾値ベースのアサーション、GitHub Actionsとの連携に対応しています。
description の原文を見る
Run AI agent and LLM evaluations in CI/CD pipelines — automated quality gates that fail the build when AI output quality drops. Use when someone asks to "test my AI agent", "add evals to CI", "catch prompt regressions", "compare models", "evaluate LLM output quality", "set up AI quality gates", or "benchmark my agent before deploying". Covers eval frameworks (Cobalt, Promptfoo, Braintrust), LLM-as-judge scoring, threshold-based assertions, and GitHub Actions integration.
SKILL.md 本文
CI における AI Eval
概要
コードをテストするのと同じ方法で AI エージェントと LLM 出力をテストします。CI で実行される自動評価により、ベースラインと比較し、品質が低下したときにビルドを失敗させることができます。ダッシュボードを手動でチェックする必要はありません。npx eval run --ci を実行して、赤または緑のビルドが表示されるだけです。
使用する場合
- AI 機能を本番環境にデプロイする前に品質ゲートを追加する
- システムプロンプトまたはモデルが変更されたときにプロンプト回帰をキャッチする
- モデルパフォーマンスを比較する(GPT-4o vs Claude Sonnet vs ローカル Llama)
- RAG パイプラインの精度をテストデータセットに対して検証する
- エージェントツール呼び出しの精度とレイテンシをベンチマークする
手順
戦略 1: Promptfoo(構成駆動型評価)
Promptfoo は最も人気のあるオープンソース評価フレームワークです。YAML でテストケースを定義し、複数のプロバイダーに対して実行し、比較マトリックスを取得します。
# promptfooconfig.yaml — 評価構成
# 3 つのモデル全体で顧客サポートエージェントをテストし、品質アサーションを実施
description: "Customer support agent eval"
providers:
- id: openai:gpt-4o
- id: anthropic:messages:claude-sonnet-4-20250514
- id: ollama:llama3.1:8b
prompts:
- |
You are a customer support agent for a SaaS product.
Respond helpfully and accurately. If you don't know, say so.
Customer message: {{message}}
tests:
- vars:
message: "How do I reset my password?"
assert:
- type: llm-rubric
value: "Response explains the password reset process clearly"
- type: not-contains
value: "I don't know"
- type: latency
threshold: 3000 # Must respond within 3 seconds
- vars:
message: "Can I get a refund for my annual plan?"
assert:
- type: llm-rubric
value: "Response acknowledges the refund request and explains the policy"
- type: not-contains
value: "I'm an AI" # Don't break character
- vars:
message: "Your product deleted all my data!"
assert:
- type: llm-rubric
value: "Response shows empathy, takes the issue seriously, and offers next steps"
- type: sentiment
threshold: 0.3 # Must not be dismissive
- vars:
message: "What's the weather in Tokyo?"
assert:
- type: llm-rubric
value: "Response politely redirects to product-related topics"
- type: not-contains
value: "Tokyo" # Should not answer off-topic questions
# 評価をローカルで実行
npx promptfoo@latest eval
# しきい値付きで CI で実行 — いずれかのテストが失敗した場合はゼロ以外で終了
npx promptfoo@latest eval --ci --output results.json
# 2 つのプロンプトバージョンを比較
npx promptfoo@latest eval --prompts prompt-v1.txt prompt-v2.txt --share
戦略 2: カスタム評価フレームワーク(TypeScript)
完全な制御が必要な場合 — カスタムスコアリングロジック、データベースバックアップテストセット、ドメイン固有メトリクス。
// eval.ts — CI 統合を備えたカスタム AI 評価フレームワーク
/**
* AI エージェント/LLM に対して評価スイートを実行します。
* 各評価は入力、期待される動作、およびスコアリング基準を定義します。
* スコアがしきい値を下回った場合、コード 1 で終了します。
*/
import OpenAI from "openai";
interface EvalCase {
name: string;
input: string;
rubric: string; // 「良い」状態の定義
threshold: number; // 最小スコア 0-1
metadata?: Record<string, unknown>;
}
interface EvalResult {
name: string;
score: number;
pass: boolean;
output: string;
reasoning: string;
latencyMs: number;
}
const openai = new OpenAI();
/**
* LLM-as-judge を使用して AI 出力をスコアリングします。
* スコア 0-1 と推論を返します。
*/
async function judge(output: string, rubric: string): Promise<{ score: number; reasoning: string }> {
const response = await openai.chat.completions.create({
model: "gpt-4o-mini", // 判定用の低コストモデル
messages: [
{
role: "system",
content: `You are an eval judge. Score the AI output against the rubric.
Return JSON: {"score": 0.0-1.0, "reasoning": "brief explanation"}
Score 1.0 = perfect match. Score 0.0 = complete failure.`,
},
{
role: "user",
content: `Rubric: ${rubric}\n\nAI Output:\n${output}`,
},
],
response_format: { type: "json_object" },
temperature: 0, // 決定的な判定
});
return JSON.parse(response.choices[0].message.content!);
}
/**
* AI エージェントに対して単一の評価ケースを実行します。
*/
async function runEval(
agentFn: (input: string) => Promise<string>,
evalCase: EvalCase
): Promise<EvalResult> {
const start = Date.now();
const output = await agentFn(evalCase.input);
const latencyMs = Date.now() - start;
const { score, reasoning } = await judge(output, evalCase.rubric);
return {
name: evalCase.name,
score,
pass: score >= evalCase.threshold,
output: output.slice(0, 200),
reasoning,
latencyMs,
};
}
/**
* すべての評価を実行し、CI に対して適切なコードで終了します。
*/
async function runSuite(
agentFn: (input: string) => Promise<string>,
cases: EvalCase[]
): Promise<void> {
console.log(`Running ${cases.length} evals...\n`);
const results: EvalResult[] = [];
for (const evalCase of cases) {
const result = await runEval(agentFn, evalCase);
results.push(result);
const icon = result.pass ? "✅" : "❌";
console.log(`${icon} ${result.name}: ${result.score.toFixed(2)} (threshold: ${evalCase.threshold}) [${result.latencyMs}ms]`);
if (!result.pass) {
console.log(` Reasoning: ${result.reasoning}`);
}
}
// 概要
const passed = results.filter((r) => r.pass).length;
const failed = results.filter((r) => !r.pass).length;
const avgScore = results.reduce((s, r) => s + r.score, 0) / results.length;
console.log(`\n📊 Results: ${passed} passed, ${failed} failed (avg score: ${avgScore.toFixed(2)})`);
// CI 終了コード
if (failed > 0) {
console.log("\n❌ Eval suite FAILED — quality below threshold");
process.exit(1);
} else {
console.log("\n✅ Eval suite PASSED");
}
}
export { runSuite, EvalCase };
戦略 3: GitHub Actions 統合
# .github/workflows/ai-eval.yml
name: AI Eval
on:
pull_request:
paths:
- "prompts/**"
- "src/agents/**"
- "eval/**"
jobs:
eval:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
- name: Run AI evals
run: npx tsx eval/run.ts --ci
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
- name: Post results to PR
if: always()
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('eval/results.json'));
const body = results.map(r =>
`${r.pass ? '✅' : '❌'} **${r.name}**: ${r.score.toFixed(2)} (${r.latencyMs}ms)`
).join('\n');
github.rest.issues.createComment({
...context.repo,
issue_number: context.issue.number,
body: `## AI Eval Results\n\n${body}`
});
例
例 1: RAG チャットボットに品質ゲートを追加
ユーザープロンプト: 「RAG カスタマーサポートボット向けの自動評価を設定してください。50 個の既知の Q&A ペアの精度をテストし、精度が 85% を下回った場合はデプロイを失敗させるべきです。」
エージェントが実行すること:
- 50 個の既知の Q&A ペアからテストデータセットを作成する
- 各テストに対して llm-rubric アサーションを含む promptfoo 構成を書く
- 合格しきい値を 0.85 に設定する
prompts/またはsrc/agents/への PR で実行する GitHub Actions ワークフローを追加する- PR コメントとして評価結果を投稿する
例 2: 切り替え前にモデルを比較
ユーザープロンプト: 「GPT-4o から Claude Sonnet への切り替えを検討しています。評価スイートを両方のモデルに対して実行し、どちらがより優れたパフォーマンスを発揮しているかを示してください。」
エージェントが実行すること:
- 両方のプロバイダーで promptfoo を構成する
- 既存の評価スイートを両方のモデルに対して実行する
- テストごとのスコア、レイテンシ、およびコストを含む比較テーブルを生成する
- スコアとコスト比に基づいて推奨する
ガイドライン
- すべてのプロンプト変更を評価する — プロンプトをコードのように扱い、デプロイ前にテストする
- LLM-as-judge で十分です — GPT-4o-mini は数セント程度で、人間の判断とよく相関します
- 判定には temperature 0 を使用する — 決定的なスコアリングはノイズを削減します
- テストセットを多様に保つ — ハッピーパス、エッジケース、敵対的入力、オフトピック
- 現実的なしきい値を設定する — 0.7 から始めて、エージェントが改善するにつれて厳しくする
- 時間経過に伴うスコアを追跡する — 結果をログに記録して徐々的な品質低下を検出する
- 評価コストを本番コストから分離する — 評価は安価な判定モデルを使用し、本番は最良のものを使用する
- 評価結果をキャッシュする — 変更されていないテストを再実行しない; 入力 + プロンプトをハッシュしてキャッシュキーにする
- PR で評価を実行する(主要ブランチだけではなく) — マージ前に回帰をキャッチする
ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- TerminalSkills
- ライセンス
- Apache-2.0
- 最終更新
- 2026/5/4
Source: https://github.com/TerminalSkills/skills / ライセンス: Apache-2.0
関連スキル
agent-browser
AI エージェント向けのブラウザ自動化 CLI です。ウェブサイトとの対話が必要な場合に使用します。ページ遷移、フォーム入力、ボタンクリック、スクリーンショット取得、データ抽出、ウェブアプリのテスト、ブラウザ操作の自動化など、あらゆるブラウザタスクに対応できます。「ウェブサイトを開く」「フォームに記入する」「ボタンをクリックする」「スクリーンショットを取得する」「ページからデータを抽出する」「このウェブアプリをテストする」「サイトにログインする」「ブラウザ操作を自動化する」といった要求や、プログラマティックなウェブ操作が必要なタスクで起動します。
anyskill
AnySkill — あなたのプライベート・スキルクラウド。GitHubを基盤としたリポジトリからエージェントスキルを管理、同期、動的にロードできます。自然言語でクラウドスキルを検索し、オンデマンドでプロンプトを自動ロード、カスタムスキルのアップロードと共有、スキルバンドルの一括インストールが可能です。OpenClaw、Antigravity、Claude Code、Cursorに対応しています。
engram
AIエージェント向けの永続的なメモリシステムです。バグ修正、意思決定、発見、設定変更の後はmem_saveを使用してください。ユーザーが「覚えている」「記憶している」と言及した場合、または以前のセッションと重複する作業を開始する際はmem_searchを使用します。セッション終了前にmem_session_summaryを使用して、コンテキストを保持してください。
skyvern
AI駆動のブラウザ自動化により、任意のウェブサイトを自動化できます。フォーム入力、データ抽出、ファイルダウンロード、ログイン、複数ステップのワークフロー実行など、ユーザーがウェブサイトと連携する必要があるときに使用します。Skyvernは、LLMとコンピュータビジョンを活用して、未知のサイトも自動操作可能です。Python SDK、TypeScript SDK、REST API、MCPサーバー、またはCLIを通じて統合できます。
pinchbench
PinchBenchベンチマークを実行して、OpenClawエージェントの実世界タスクにおけるパフォーマンスを評価できます。モデルの機能テスト、モデル間の比較、ベンチマーク結果のリーダーボード提出、またはOpenClawのセットアップがカレンダー、メール、リサーチ、コーディング、複数ステップのワークフローにどの程度対応しているかを確認する際に使用します。
openui
OpenUIとOpenUI Langを使用してジェネレーティブUIアプリを構築できます。これらはLLM生成インターフェースのためのトークン効率的なオープン標準です。OpenUI、@openuidev、ジェネレーティブUI、LLMからのストリーミングUI、AI向けコンポーネントライブラリ、またはjson-render/A2UIの置き換えについて述べる際に使用します。スキャフォルディング、defineComponent、システムプロンプト、Renderer、およびOpenUI Lang出力のデバッグに対応しています。