https://blog.mocobeta.dev/posts/feed.xml

Agents SDKのエージェントオーケストレーションパターン - LLM as a Judge

2025-12-14

生成AIの出力をLLM自身に評価させるLLM-as-a-Judgeパターンを,Agents SDKで実装してみた話です。

LLM-as-a-Judgeとは

LLM-as-a-Judgeは,LLMの出力を評価するのに,LLM自身を評価者として活用する手法です。人間の専門家が手動で評価するよりは低コストで実現でき,また,フィードバックループを自動化してシステムに組み込むことができます。マルチエージェントシステムに応用すると,あるタスクを実行するエージェントが生成した出力を,別のエージェント(ジャッジエージェント)が入力として受け取り,その応答品質を評価する,ということになります。評価に加えて,フィードバックを与えて出力を改善するプロセスまで含めて便宜的にLLM as a Judgeと呼ぶこともあるようです。

LLMによる評価の設計と,評価を行うモデルの評価(メタ評価)についてはサーベイ論文"A Survey on LLM-as-a-Judge"に詳しいです。読まないとな...。

LLM-as-a-Judgeの実装例

Agents SDKのリポジトリに含まれるサンプルを参考にしました: examples/agent_patterns/llm_as_a_judge.py

与えられたテーマについてエッセイを書くライターエージェントと,そのエッセイを評価するジャッジエージェントを用意し,ジャッジエージェントが満足するまで(10点満点中9点以上をつけるまで)ライターエージェントがエッセイを書き直す,というデモアプリです。

ジャッジエージェントのインストラクションがくどいですが,「評価して」というナイーブな指示だと,好意的な評価をするようにバイアスがかかるのか評価者としては甘すぎて役に立たなかったため,少し細かく評価基準を指定しました。

# ライターエージェント
instructions="""
あなたはエッセイライターです。与えられたテーマについてのエッセイを書いてください。
マークアップ言語は使わずプレーンテキストで書くこと。
もしフィードバックが与えられたら,そのフィードバックを反映してエッセイを改善してください。
"""
writer_agent = Agent(
    name="writer_agent",
    model="gpt-4.1",
    instructions=instructions
)

@dataclass
class EvalAndFeedback:
    """ジャッジエージェントのアウトプット型"""
    evaluation: int # 1から10のスコアをつける。評価方法は柔軟に設計してよい
    feedback: str # 改善のためのフィードバックを提供する

# ジャッジエージェント
instructions = """
あなたは経験豊富なエッセイの批評家です。与えられたエッセイを読み,1から10のスケールで評価してください。1が最低評価,10が最高評価です。甘い評価はせず,厳しく評価してください。
エッセイの評価ポイントは以下の通りです:
- タイトルは魅力的かつ独創的か。
- 本文は長すぎず,短すぎないか。エッセイ本文は100語から200語の範囲であるべきです。
- エッセイはテーマに沿っているか
- 文法や使われている単語は正確か。引用されている事実は正確か。
- エッセイの構成は論理的で不自然な飛躍がないか。段落のつながりはスムーズか。不自然な改行や,過剰な接続詞はないか?
- エッセイは読みやすい日本語か。くだけすぎていないか,または堅苦しすぎないか。
- エッセイは過度に抽象的または一般的ではないか。独創的な視点や洞察が含まれているか。
- エッセイは情景を思い浮かべやすく,読者の感情に訴えるか。
エッセイの評価とともに,エッセイを改善するための具体的なフィードバックも提供してください。
"""
evaluator_agent = Agent(
    name="evaluator_agent",
    model="gpt-4.1",
    instructions=instructions,
    output_type=EvalAndFeedback,
)

async def main():
    conversation_id = str(uuid.uuid4().hex[:16])

    msg = input("エッセイのテーマを入力してください: ")
    inputs: list[TResponseInputItem] = [{"content": msg, "role": "user"}]

    with trace("LLM as a Judge", group_id=conversation_id):
        writer_result = await Runner.run(
            writer_agent,
            input=inputs,
        )
        essay_content = writer_result.final_output
        print("\n=== 初回エッセイ ===")
        print(essay_content)

        eval_result = await Runner.run(
            evaluator_agent,
            input=writer_result.to_input_list()
        )
        evaluation: EvalAndFeedback = eval_result.final_output

        turn_count = 1
        while evaluation.evaluation < 9:
            print(f"\n=== {turn_count} 回目の評価点: {evaluation.evaluation} ===")

            inputs.append({
                "content": f"エッセイの評価は{evaluation.evaluation}点です。以下のフィードバックを反映してエッセイを改善してください:{evaluation.feedback}",
                "role": "user"
            })
            writer_result = await Runner.run(
                writer_agent,
                input=inputs,
            )
            essay_content = writer_result.final_output
            eval_result = await Runner.run(
                evaluator_agent,
                input=writer_result.to_input_list()
            )
            evaluation: EvalAndFeedback = eval_result.final_output
            turn_count += 1
        
        print(f"\n=== 評価結果 ===\n評価点: {evaluation.evaluation}")
        print("\n=== 最終エッセイ ===")
        print(essay_content)

if __name__ == "__main__":
    asyncio.run(main())

テーマとして「クリスマス」を与えてエッセイを書かせると,以下のような出力になりました。

$ uv run python ./14-llm-as-a-judge.py
エッセイのテーマを入力してください: クリスマス

=== 初回エッセイ ===
クリスマス

クリスマスは、毎年12月25日に世界中で祝われるイベントです。キリスト教の行事として知られていますが、宗教的な意味合いを超え、多くの国や地域で一般的な祝日、または冬の一大イベントとして親しまれています。クリスマスの由来は、イエス・キリストの誕生を祝うことにありますが、現在では家族や友人と楽しい時間を過ごす日としての性格も強くなっています。

日本でも、クリスマスは特別な日として定着しています。イルミネーションが街を彩り、クリスマスソングが街角やショッピングモールで流れると、一気に冬の雰囲気が高まります。クリスマスケーキやチキンをみんなで囲み、プレゼント交換などをするのが日本流の楽しみ方です。恋人同士で過ごす「ロマンチックな日」というイメージも強く、クリスマスイブには特別なディナーやデートを計画する人も多いです。

一方、クリスマスの本来の意味や背景については、意外と知られていないこともあります。例えば、欧米では家族で過ごすのが一般的であり、プレゼントもサンタクロースからだけでなく、家族や友人から送られることが多いです。また、キリスト教の伝統としては、教会でミサに参加する人や、ボランティア活動をして困っている人々と時間を分かち合うという過ごし方も根付いています。

クリスマスは、ただ楽しく賑やかに過ごすだけの日ではなく、誰かを思いやる気持ちや感謝の気持ちを大切にする日でもあります。家族や友人、そして身近な人々との絆を深め、新しい年を迎える前に心をあたためる、そんな貴重な時間がクリスマスには広がっています。多様な形で祝われるクリスマスですが、どの国でも共通しているのは、「大切な人と優しい時間を過ごす」という思いなのかもしれません。

=== 1 回目の評価点: 6 ===

=== 2 回目の評価点: 8 ===

=== 3 回目の評価点: 9 ===

=== 最終エッセイ ===
プレゼントの包み紙を破る音が響いたあの夜

12月24日の夜、部屋にはオレンジ色の豆電球がやさしく灯り、キッチンからは母が焼いているチキンの香ばしい匂いが漂っていました。子どもの頃の私は、枕元に靴下を置いて眠りにつく直前、壁に映る電飾のきらめきと、父と母の静かな笑い声をぼんやりと聴いていました。

目覚めた朝、家はまだひんやりと静かで、私はそっとリビングへ抜け出します。するとソファの上に小さな包みが置かれていて、深紅のリボンが光っていました。わくわくしながら包み紙を破くと、中からはピカピカの青い文房具セット。消しゴムにはサンタのイラスト、ノートには金色の雪の結晶――どれも、子どもの私には宝物でした。プレゼントのインクの匂い、手に伝わる新しい文具の感触は、今でも鮮明に思い出せます。

家族とケーキを囲みながら過ごしたあの静かなクリスマスの朝。その温かな空気や、チキンの香り、プレゼントを開ける手の震えさえも、今では私の心の中にゆっくりと残る冬の灯りです。

最終版の文章の質が良いのかどうかはさておき,2回のフィードバックを経て,初版とはだいぶ違う出力になっています。

ジャッジエージェントはどんなフィードバックを与えているのか

OpenAIダッシュボードのログから確認すると,ジャッジエージェントはこのようなフィードバックを返していました。確かに,与えたインストラクションに忠実に従ってフィードバックをしている。

エッセイの評価は6点です。以下のフィードバックを反映してエッセイを改善してください:タイトル『クリスマス』はシンプルすぎて、独創性や魅力に欠けます。本文の長さは約350語と、指定された100語から200語を大幅に超えています。テーマにはしっかり沿っており、クリスマスの由来や日本と欧米の違いも適切に触れられていますが、全体的に一般的な説明にとどまっており、独創的な視点や個人的なエピソードが不足しています。

文法や語彙は正確で、読みやすい日本語が使われていますが、抽象的・説明的な部分が多く、情景描写や感情への訴えかけが弱いです。また、段落ごとのつながりは自然ですが、構成としてやや冗長さを感じます。

改善点:
1. タイトルに独自性を持たせて、読者の興味を引きましょう。
2. 文章量を減らし、要点を絞ってください。
3. ご自身や特定の場面に焦点を当てるなど、体験や感情を交えることで独創性と情緒性を高めましょう。
4. クリスマスの『どんな景色』『どんな音や香り』『どんな思い出』が印象に残っているか、五感や具体的な描写を使うと印象的なエッセイになります。

これは Agents SDK+αのTipsを一人で書いていくアドカレ Advent Calendar 2025の14日目の記事です。