【Azure OpenAI】Structured Outputsを試してイメージを掴む

2024/09/07に公開2

はじめに

8月にOpenAI社からStructured Outputsが発表されました。
最近、Azure Open AIでも利用できるようになったので試してみる。

https://techcommunity.microsoft.com/t5/ai-azure-ai-services-blog/introducing-gpt-4o-2024-08-06-api-with-structured-outputs-on/ba-p/4232684

細かい仕様については、以下の記事を参考にしてください。

https://zenn.dev/microsoft/articles/azure-openai-structured-outputs

執筆日

2024/9/7

前提

2024/9/7時点では、以下のモデル/バージョンのみ対応

  • モデル:gpt-4o
  • モデルのバージョン:2024-08-06 以上
  • APIのバージョン:2024-08-01-preview 以上
    ※モデルのバージョン 2024-08-06は、US regions と Sweden Centralで利用可能です。

試してみる(サンプルコード)

Docsのコードを実行してみる

https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/structured-outputs?tabs=rest

main.py
from enum import Enum
from typing import Union
from pydantic import BaseModel
import openai
from openai import AzureOpenAI

client = AzureOpenAI(
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
  api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
  api_version="2024-08-01-preview"
)

class GetDeliveryDate(BaseModel):
    order_id: str

tools = [openai.pydantic_function_tool(GetDeliveryDate)]

messages = []
messages.append({"role": "system", "content": "You are a helpful customer support assistant. Use the supplied tools to assist the user."})
messages.append({"role": "user", "content": "Hi, can you tell me the delivery date for my order #12345?"}) 

response = client.chat.completions.create(
    model="MODEL_DEPLOYMENT_NAME", # replace with the model deployment name of your gpt-4o 2024-08-06 deployment
    messages=messages,
    tools=tools
)

print(response.choices[0].message.tool_calls[0].function)
print(response.model_dump_json(indent=2))
Function(arguments='{"order_id":"12345"}', name='GetDeliveryDate')
{
  "id": "chatcmpl-A47QkwkdQUatI6aC1yBfAmpdqmdsc",
  "choices": [
    {
      "finish_reason": "tool_calls",
      "index": 0,
      "logprobs": null,
      "message": {
        "content": null,
        "refusal": null,
        "role": "assistant",
        "function_call": null,
        "tool_calls": [
          {
            "id": "call_ltgJdAbQ0afXl2h0bGYl0cKB",
            "function": {
              "arguments": "{\"order_id\":\"12345\"}",
              "name": "GetDeliveryDate"
            },
            "type": "function"
          }
        ]
      },
      "content_filter_results": {}
    }
  ],
  "created": 1725545238,
  "model": "gpt-4o-2024-08-06",
  "object": "chat.completion",
  "service_tier": null,
  "system_fingerprint": "fp_b2ffeb16ee",
  "usage": {
    "completion_tokens": 17,
    "prompt_tokens": 81,
    "total_tokens": 98
  },
  "prompt_filter_results": [
    {
      "prompt_index": 0,
      "content_filter_results": {
        "hate": {
          "filtered": false,
          "severity": "safe"
        },
        "jailbreak": {
          "filtered": false,
          "detected": false
        },
        "self_harm": {
          "filtered": false,
          "severity": "safe"
        },
        "sexual": {
          "filtered": false,
          "severity": "safe"
        },
        "violence": {
          "filtered": false,
          "severity": "safe"
        }
      }
    }
  ]
}

コードを書いてみる

以下の記事を参考にコードを書いてみる

https://zenn.dev/chips0711/articles/ab49bde721375e

コード1(リスクを抽出)

main.py
from enum import Enum
from typing import Union
from pydantic import BaseModel
import openai
from openai import AzureOpenAI

client = AzureOpenAI(
  azure_endpoint = "AZURE_OPENAI_ENDPOINT", 
  api_key="AZURE_OPENAI_API_KEY",  
  api_version="2024-08-01-preview"
)

class risk(BaseModel):
    risk: str
    describe: str

completion = client.beta.chat.completions.parse(
    model="MODEL_DEPLOYMENT_NAME", # replace with the model deployment name of your gpt-4o 2024-08-06 deployment
    messages=[
        {"role": "system", "content": "リスクの情報を抽出してください。"},
        {"role": "user", "content": "最近、サイバー攻撃のリスクが増加しており、企業はセキュリティ対策の強化を迫られています。特に金融機関は標的になりやすく、注意が必要です。。"},
    ],
    response_format=risk,
)

event = completion.choices[0].message.parsed

print(completion.choices[0].message)
ParsedChatCompletionMessage[risk](content='{"risk":"サイバー攻撃のリスク増加","describe":"企業、特に金融機関へのサイバー攻撃が増加しており、それに伴いセキュリティ対策の強化が求められる。"}', refusal=None, role='assistant', function_call=None, tool_calls=[], parsed=risk(risk='サイバー攻撃のリスク増加', describe='企業、特に金融機関へのサイバー攻撃が増加しており、それに伴いセキュリティ対策の強化が求められる。'))

コード2(topicを抽出)

main.py
from enum import Enum
from typing import Union
from pydantic import BaseModel
import openai
from openai import AzureOpenAI

client = AzureOpenAI(
  azure_endpoint = "AZURE_OPENAI_ENDPOINT", 
  api_key="AZURE_OPENAI_API_KEY",  
  api_version="2024-08-01-preview"
)

class topic(BaseModel):
    topic: str
    describe: str

completion = client.beta.chat.completions.parse(
    model="MODEL_DEPLOYMENT_NAME", # replace with the model deployment name of your gpt-4o 2024-08-06 deployment
    messages=[
        {"role": "system", "content": "トピックを抽出してください。"},
        {"role": "user", "content": "最近、再生可能エネルギーの導入が進展しており、各国が脱炭素社会を目指しています。特に太陽光と風力発電の技術革新が注目されています。"},
    ],
    response_format=topic,
)

event = completion.choices[0].message.parsed

print(completion.choices[0].message)
arsedChatCompletionMessage[topic](content='{"topic":"再生可能エネルギーの進展","describe":"世界各国が脱炭素
社会を目指す中、再生可能エネルギーの導入が加速しています。太陽光発電は効率的なパネル技術やエネルギー貯蔵シス テムの改善を通じて進化しています。一方、風力発電はオフショア技術の発展により、海洋での設置や小規模地域での活 用が広がっています。両者の技術革新は、コスト削減と発電効率の向上を促進し、持続可能なエネルギー供給に貢献して います。"}', refusal=None, role='assistant', function_call=None, tool_calls=[], parsed=topic(topic='再生可能 エネルギーの進展', describe='世界各国が脱炭素社会を目指す中、再生可能エネルギーの導入が加速しています。太陽光発電は効率的なパネル技術やエネルギー貯蔵システムの改善を通じて進化しています。一方、風力発電はオフショア技術 の発展により、海洋での設置や小規模地域での活用が広がっています。両者の技術革新は、コスト削減と発電効率の向上 を促進し、持続可能なエネルギー供給に貢献しています。'))

まとめ

実際にコードを書いてみると、イメージができました。
あらかじめ、データのスキーマを定義すれば100%そのように返ってくるのかー。
今までだと、プロンプトで頑張るしかなかったのでこれは革命的だ。

ヘッドウォータース

Discussion