メインコンテンツへスキップ
Hero Image

OpenAI Agents SDK で出力形式の指定を試してみた

OpenAI-Agents-SDK

結論

多少込み入った形式でも、プロンプトを丁寧に書けば意図したとおりの出力形式が得られる。

OpenAI Agents SDK の output_type を指定したときの出力結果は以下のとおり。

  • ◯: 意図したとおりの出力形式が得られた
  • △: 意図したとおりの出力形式が得られることもある
  • ✗: 意図したとおりの出力形式が得られなかった
  • -: 実行できず(API エラーが発生)
LLM簡単なプロンプト丁寧なプロンプト
openai/gpt-oss-20b
openai/gpt-oss-120b
openai/gpt-5.1
anthropic/claude-3.5-haiku
anthropic/claude-3.7-sonnet
anthropic/claude-sonnet-4.5--
anthropic/claude-opus-4.5--
google/gemini-2.5-flash
google/gemini-2.5-pro
google/gemini-3-pro-preview

※ 具体的なプロンプトは後述。

ソースコード

https://github.com/gnkm/try.openai-agents-sdk

背景

OpenAI Agents SDK では、output_type を使って出力の形式を指定することができる。 これで本当に指定した形式で出力されるのか試してみたかった。

やりたいこと

構造化された文書を生成させて、そのメタデータを取得したい。 例えば以下の文書が出力されたとする。

# コンテンツ

## 導入

ここでは導入をおこなう。

## メインコンテンツ

メインコンテンツを扱う。

### サブコンテンツ 1

サブコンテンツ 1 を扱う。

### サブコンテンツ 2

サブコンテンツ 2 を扱う。

## まとめ

ここではまとめをおこなう。

このとき、以下の出力を得たい。

{
    'contents': [
        {
            'level': 2,
            'text': '導入',
            'children': [
                {
                    'content': 'ここでは導入をおこなう。'
                },
            ],
        },
        {
            'level': 2,
            'text': 'メインコンテンツ',
            'children': [
                {'content': 'メインコンテンツを扱う。'},
                {'level': 3, 'text': 'サブコンテンツ 1', 'children': [{'content': 'サブコンテンツ 1 を扱う。'}]},
                {'level': 3, 'text': 'サブコンテンツ 2', 'children': [{'content': 'サブコンテンツ 2 を扱う。'}]},
            ],
        },
        {
            'level': 2,
            'text': 'まとめ',
            'children': [
                {
                    'content': 'ここではまとめをおこなう。'
                },
            ],

        }
    ]
}

やったこと

環境

pyproject.toml

requires-python = ">=3.13"
dependencies = [
    "dspy>=3.0.4",
    "openai-agents[litellm]>=0.6.1",
    "pydantic>=2.12.4",
    "rich>=13.0.0",
    "typer>=0.20.0",
]

システムプロンプト

2 種類のシステムプロンプトを準備した。

システムプロンプト(1)

ユーザーの要求に基づいて、構造化されたマークダウン文書を生成してください。
文書は見出し(Heading)と本文(Content)で構成され、見出しは階層構造を持つことができます。
見出しのレベル(1-6)を適切に設定し、各セクションに適切な本文を配置してください。
見出しには子要素として、さらに下位の見出しや本文を含めることができます。

システムプロンプト(2)

ユーザーの要求に基づいて、構造化されたマークダウン文書を生成します。

    文書は見出し(Heading)と本文(Content)で構成され、見出しは階層構造を持つことができます。
    見出しのレベル(1-6)を適切に設定し、各セクションに適切な本文を配置してください。
    見出しには子要素として、さらに下位の見出しや本文を含めることができます。

    出力は必ず JSON 形式で、以下の構造に従ってください:
    {
        "contents": [
            {
                "level": 2,
                "text": "見出しテキスト",
                "children": [
                    {"content": "本文テキスト"},
                    {
                        "level": 3,
                        "text": "サブ見出し",
                        "children": [{"content": "サブセクションの本文"}]
                    }
                ]
            }
        ]
    }

準備

出力の型を定めるクラスを定義する。

class Content(BaseModel):
    """コンテンツ"""

    content: str = Field(
        ...,
        description="本文のテキスト",
        examples=["ここでは導入をおこなう。", "メインコンテンツを扱う。"],
    )

class Heading(BaseModel):
    """見出しのメタデータ"""

    level: int = Field(
        ...,
        description="見出しのレベル(例: 1, 2, 3)",
        examples=[2, 3],
    )
    text: str = Field(
        ...,
        description="見出しのテキスト",
        examples=["導入", "まとめ"],
    )
    children: list[Union[Content, Heading]] = Field(
        ...,
        description="子要素のリスト",
        examples=[
            # ...
        ]
    )

class MarkdownDocument(BaseModel):
    """マークダウン文書の構造を定義します。"""

    contents: list[Union[Content, Heading]] = Field(
        ...,
        description="本文のリスト",
        examples=[
            # ...
        ],
    )

OpenAI Agents SDK の output_type を使う

OpenAI Agents SDK では、output_type を使って出力の形式を指定することができる。 これを使うと、出力の形式を厳密に指定することができる。 まず、出力の型を定めるクラスを定義する。

出力を output_type で指定する。

    agent = Agent(
        name="Markdown Generator",
        instructions=system_prompt,
        model=LitellmModel(model=llm, api_key=api_key),
        model_settings=ModelSettings(temperature=temperature),
        output_type=MarkdownDocument,
    )

実行して得られた出力の一部を抜粋する。

        {
          "level": 2,
          "text": "生成AIの種類と機能",
          "children": []
        },
        {
          "level": 3,
          "text": "テキスト生成AI",
          "children": []
        },
        {
          "content": "GPTシリーズに代表されるテキスト生成AIは、与えられたプロンプトに基づいて、自然な文章を生成します。記事の執筆、メール作成、コード生成、翻訳、要約など、その用途は多岐にわたります。人間のような対話能力を持つことで、カスタマーサポートや教育分野での活用も期待されています。"
        },

children の中に入っていてほしいものが外にある。

Gemini 特有の現象

https://github.com/openai/openai-agents-python/issues/1575

Gemini を使うと、output_type を使っても意図したとおりの出力形式が得られないという現象があるらしい。

あとがき

Anthropic の新しいモデルで軒並み API エラーになってしまって使えなかったのが残念。 またあらためて試してみたい。