Azure OpenAIの新仕様Responses APIを使ってみる

OpenAI公式からResponse APIが発表されて2週間後の3月27日、Azure OpenAIの公式ドキュメントにもResponse APIの更新がありました。そこで、実際に使ってみた結果を以下にまとめます。

## 主な変更点
- **chat.completions APIとassistants APIの統合**  
  プレビュー版で提供されていた`assistants API` が、`chat.completions API` と統合され、`Assistant API` は2026年中に収束される見込みです

- **ステートフルな仕組みの導入**  
  リソース内での会話の保存・呼び出しが可能になっています

- **`computer-use-preview` モデルのサポート**  

## Azure各リージョンでの対応状況

**対応リージョン**

- australiaeast
- eastus
- eastus2
- francecentral
- japaneast
- norwayeast
- southindia
- swedencentral
- uaenorth
- uksouth
- westus
- westus3

**APIバージョン**  
`2025-03-01-preview` 以降が対象です。

**対応モデル**

- `gpt-4o` (バージョン: `2024-11-20`、`2024-08-06`、`2024-05-13`)
- `gpt-4o-mini` (バージョン: `2024-07-18`)
- `computer-use-preview`

なお、先日東日本リージョンでGAとなった `o1` や `o3-mini` は、現時点では非対応です（本家OpenAIでは対応済み）。

---

### 現在対応していない機能

以下のAssistants API機能は、まだ完全にはResponses APIへ置き換えられていません：

- **Structured outputs**
- **tool_choice**
- **インターネット上の画像URL（image_url）**
- **web search tool**（対象のAPIバージョン(0301)がそもそも非対応）

---

### Response APIを試してみる

#### 1. 最新版OpenAI SDKのインストール

ターミナルで以下のコマンドを実行して、最新版にアップグレードします。

```bash
uv add --upgrade openai
```

（4月10日時点でバージョン `1.72.0` がインストールされました。）

#### 2. レスポンスの作成

以前までのチャット応答と同様の使い勝手です。

```python
client = AzureOpenAI(
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),
    api_version="2025-03-01-preview",
    azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
)

response = client.responses.create(
    model=gpt-4o-2024-11-20,  # ご利用のモデルデプロイ名に置き換え
    input="This is a test.",
)

print(response)
# print(response.to_json())
```

実行結果のレスポンス例は以下の通りです：

```json
{
  "id": "resp_xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "created_at": 1744175590.0,
  "error": null,
  "incomplete_details": null,
  "instructions": null,
  "metadata": {},
  "model": "gpt-4o-2024-11-20",
  "object": "response",
  "output": [
    {
      "id": "msg_xxxxxxxxxxxxxxxxxxxxxxxxxx",
      "content": [
        {
          "annotations": [],
          "text": "Hello! Let me know how I can assist you with your test. 😊",
          "type": "output_text"
        }
      ],
      "role": "assistant",
      "status": "completed",
      "type": "message"
    }
  ],
  "parallel_tool_calls": true,
  "temperature": 1.0,
  "tool_choice": "auto",
  "tools": [],
  "top_p": 1.0,
  "max_output_tokens": null,
  "previous_response_id": null,
  "reasoning": {
    "effort": null,
    "generate_summary": null
  },
  "status": "completed",
  "text": {
    "format": {
      "type": "text"
    }
  },
  "truncation": "disabled",
  "usage": {
    "input_tokens": 29,
    "input_tokens_details": {
      "cached_tokens": 0
    },
    "output_tokens": 24,
    "output_tokens_details": {
      "reasoning_tokens": 0
    },
    "total_tokens": 53
  },
  "user": null,
  "store": true
}
```

#### 3. レスポンスの呼び出し

以前のレスポンスを取得するには、`responses.retrieve` メソッドを使用します。以下の例では、先ほどのレスポンスIDを指定して同じレスポンスを取得します。

```python
response_id = "resp_xxxxxxxxxxxxxxxxxxxx"

response = client.responses.retrieve(response_id=response_id)

print(response.output.to_json())
```

#### 4. 推論モデルの未対応状況について

先述の通り、`o1` や `o3-mini` などのモデルはまだResponse APIに対応していないため、4月10日現在、推論モデルを指定すると空文字（`response:str = ''`）が返却されます。

---

### API パラメータについて

従来は `messages` 内の `role` で指定していた情報を、今回のAPIでは `instructions` や `input` クエリで指定できるようになりました。

```python
response = client.responses.create(
    model="gpt-4o",
    instructions="Talk like a pirate.",
    input="Are semicolons optional in JavaScript?",
)
```

また、以前のように `messages` の形式でリクエストすることも可能です：

```python
response = client.responses.create(
    model="gpt-4o",
    input=[
        {
            "role": "developer",
            "content": "Talk like a pirate."
        },
        {
            "role": "user",
            "content": "Are semicolons optional in JavaScript?"
        }
    ]
)
```
他にも推論モデル用のパラメータが追加されていたり多少異なる点があります。詳細は公式APIドキュメントを。

https://learn.microsoft.com/en-us/azure/ai-services/openai/reference-preview#responses-api---create

---

### 参考文献

- [Azure OpenAI Responses API (Preview) - Microsoft公式ドキュメント](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/responses?tabs=python-secure)