OpenAI API 入門:Chat Completions、関数呼び出し、ストリーミング出力の書き方

OpenAI 互換の Chat Completions API の基本を整理します。BASE_URL と OPENAI_API_KEY の設定、messages、tools、tool_choice、stream の組み立て方、非ストリーミング応答とストリーミング応答の読み方を扱います。

多くの大規模モデルサービスは「OpenAI 互換」の API を提供しています。実際に接続するとき、まず確認すべきことは 2 つです。

  1. BASE_URL: サービス提供者が用意した API アドレス。
  2. OPENAI_API_KEY: あなたのアクセスキー。

サービスが Chat Completions API と互換であれば、リクエストの形は通常 OpenAI の /v1/chat/completions に近くなります。ただし、OpenAI は現在 Responses API も推進しています。Chat Completions は今でもよく使われ、特にサードパーティの互換 API では一般的ですが、OpenAI 公式の機能を直接使う新規プロジェクトでは Responses API も確認しておくべきです。

公式参考:

最小リクエスト例

最小の Chat Completions リクエストは、おおよそ次のようになります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [
      {
        "role": "system",
        "content": "You are a helpful assistant."
      },
      {
        "role": "user",
        "content": "Hello!"
      }
    ]
  }'

サードパーティの OpenAI 互換サービスを使う場合、通常は 1 行目を相手の BASE_URL に置き換えるだけです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
curl $BASE_URL/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "your-model-id",
    "messages": [
      {
        "role": "user",
        "content": "Hello!"
      }
    ]
  }'

間違いやすい点は 3 つあります。

  • BASE_URL/v1 を多く付けたり、逆に付け忘れたりする。
  • AuthorizationBearer を付け忘れる。
  • サービス側が実際には対応していない model を指定する。

リクエストボディで重要なフィールド

Chat Completions のリクエストボディは JSON オブジェクトです。基本的でよく使うフィールドは次のとおりです。

model

model は必須フィールドで、呼び出すモデル ID を指定します。

1
2
3
{
  "model": "gpt-4o-mini"
}

OpenAI 互換のサードパーティサービスでは、モデル ID が gpt-4o-mini とは限りません。deepseek-chatqwen-plusllama-3.1-70b のような独自のモデル名を使うサービスもあります。ここはサービス提供者のドキュメントやモデル一覧に従ってください。

messages

messages は必須フィールドで、最初から現在までの会話履歴を表します。配列で、各要素が 1 つのメッセージです。

よく使う role は次のとおりです。

  • system: アシスタントの振る舞いを定義するシステム指示。
  • user: ユーザーのメッセージ。
  • assistant: モデルの前回までの応答。
  • tool: ツール呼び出しの結果。

単純な複数ターンの会話は次のように書けます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "model": "gpt-4o-mini",
  "messages": [
    {
      "role": "system",
      "content": "You are a concise technical assistant."
    },
    {
      "role": "user",
      "content": "什么是 API?"
    },
    {
      "role": "assistant",
      "content": "API 是应用程序之间约定好的调用接口。"
    },
    {
      "role": "user",
      "content": "用一句话解释给非技术人员听。"
    }
  ]
}

system message

system メッセージは通常先頭に置き、モデルにどの役割を担うべきか、どの規則に従うべきかを伝えます。

1
2
3
4
{
  "role": "system",
  "content": "You are a helpful assistant."
}

主なフィールド:

  • role: system 固定。
  • content: システムプロンプトの内容。
  • name: 任意。参加者名を示すために使います。

互換サービスがすべて同じ system behavior を実装しているとは限りません。システムプロンプトが効いていないように見える場合は、まずサービス側が role の扱いを変更していないか確認します。

user message

user メッセージはユーザー入力を表します。最も一般的なのはテキストです。

1
2
3
4
{
  "role": "user",
  "content": "Hello!"
}

マルチモーダル入力をサポートするモデルでは、content を配列にして、テキストと画像を同時に渡すこともできます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4o",
    "messages": [
      {
        "role": "user",
        "content": [
          {
            "type": "text",
            "text": "What is in this image?"
          },
          {
            "type": "image_url",
            "image_url": {
              "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
            }
          }
        ]
      }
    ],
    "max_completion_tokens": 300
  }'

互換 API が画像をサポートするかどうかは、具体的なモデルによります。エンドポイントの形が OpenAI 互換だからといって、必ずマルチモーダルに対応しているとは限りません。

assistant message

assistant メッセージは通常、複数ターンの履歴に含め、モデルが以前に何を返したかを表します。

1
2
3
4
{
  "role": "assistant",
  "content": "Hello, how can I help you today?"
}

モデルがツール呼び出しを選ぶ場合、assistant メッセージには通常のテキストではなく tool_calls が入ることがあります。

tool message

tool メッセージは、ツールの実行結果をモデルに返すために使います。前の assistant メッセージ内のいずれかの tool_calls.id に対応している必要があります。

1
2
3
4
5
{
  "role": "tool",
  "tool_call_id": "call_abc123",
  "content": "{\"temperature\": 22, \"unit\": \"celsius\"}"
}

これは Agent シナリオでよく使います。モデルがまず呼び出す関数を決め、アプリケーションが実際にその関数を実行し、その結果を tool メッセージとしてモデルに返し、モデルが最終回答を生成します。

tools と tool_choice

tools は、モデルが呼び出せるツールを伝えるために使います。最も一般的なのは関数ツールです。

天気を問い合わせる例です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [
      {
        "role": "user",
        "content": "What is the weather like in Boston today?"
      }
    ],
    "tools": [
      {
        "type": "function",
        "function": {
          "name": "get_current_weather",
          "description": "Get the current weather in a given location",
          "parameters": {
            "type": "object",
            "properties": {
              "location": {
                "type": "string",
                "description": "The city and state, e.g. San Francisco, CA"
              },
              "unit": {
                "type": "string",
                "enum": ["celsius", "fahrenheit"]
              }
            },
            "required": ["location"]
          }
        }
      }
    ],
    "tool_choice": "auto"
  }'

モデルがツールが必要だと判断すると、レスポンスに次のような内容が含まれることがあります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "tool_calls": [
          {
            "id": "call_abc123",
            "type": "function",
            "function": {
              "name": "get_current_weather",
              "arguments": "{\"location\":\"Boston, MA\"}"
            }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ]
}

ここで重要なのは 2 点です。

  1. モデルは「関数を呼ぶべきだ」と提案しているだけで、あなたのプログラムの代わりに本当に関数を実行するわけではありません。
  2. arguments はモデルが生成した JSON 文字列です。使う前に必ず検証してください。

tool_choice はモデルがツールを呼び出すかどうかを制御します。

  • "none": ツールを呼ばず、テキストだけを生成する。
  • "auto": テキスト生成かツール呼び出しかをモデルに選ばせる。
  • "required": 1 つ以上のツール呼び出しを要求する。
  • 特定の関数を指定: 具体的なツール呼び出しを強制する。

旧 API の functionsfunction_call は、toolstool_choice に置き換えられています。古いプロジェクトを保守しているとまだ見かけるかもしれませんが、新しいコードでは新しい書き方を優先するのがおすすめです。

stream ストリーミング出力

stream は任意の boolean 値です。true にすると、API は SSE で内容を少しずつ返します。リアルタイムチャット UI に向いています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "model": "gpt-4o-mini",
  "messages": [
    {
      "role": "user",
      "content": "写一句欢迎语"
    }
  ],
  "stream": true
}

非ストリーミング応答は、モデルが最後まで生成してからまとめて返します。ストリーミング応答は chunk を継続的に返します。典型的な断片は次のようになります。

1
2
3
4
5
data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}

data: {"id":"chatcmpl-123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}

data: [DONE]

フロントエンドまたはバックエンドは data: 行を読み続け、それぞれの delta.content を連結し、[DONE] を受け取ったら終了します。

非ストリーミング応答の読み方

非ストリーミングの Chat Completions 応答には、通常次のようなフィールドが含まれます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "id": "chatcmpl-123",
  "object": "chat.completion",
  "created": 1677652288,
  "model": "gpt-4o-mini",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Hello there, how may I assist you today?"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 9,
    "completion_tokens": 12,
    "total_tokens": 21
  }
}

よく使うのは次のフィールドです。

  • choices[0].message.content: モデルの最終応答。
  • choices[0].message.tool_calls: モデルが呼び出したいツール。
  • choices[0].finish_reason: 停止理由。
  • usage: token 使用量。

finish_reason のよくある値:

  • stop: 自然停止。
  • length: token 上限に到達。
  • tool_calls: モデルがツール呼び出しを要求。
  • content_filter: 内容がフィルタリングされた。

互換 API 接続時のチェックリスト

サードパーティの OpenAI 互換サービスに接続するときは、パスが同じかどうかだけで判断しないほうが安全です。次の項目を確認しましょう。

  1. BASE_URL/v1 が含まれているか。
  2. OPENAI_API_KEY が現在のサービス提供者に対応しているか。
  3. model が有効なモデル ID か。
  4. system メッセージをサポートしているか。
  5. マルチモーダル image_url をサポートしているか。
  6. toolstool_choice をサポートしているか。
  7. stream: true をサポートしているか。
  8. token 制限フィールドが max_completion_tokens か、古い max_tokens か。
  9. エラー応答の形式が OpenAI と完全に同じか。
  10. 追加のレート制限、同時実行制限、地域制限があるか。

「OpenAI 互換」は通常、呼び出し方が似ているという意味です。すべてのモデル能力、フィールドの意味、エラー形式が完全に同じという意味ではありません。

結論

最も基本的なチャット用途だけなら、Chat Completions の中心フィールドは実質的に 3 つです。

1
2
3
4
5
{
  "model": "your-model-id",
  "messages": [],
  "stream": false
}

Agent や業務自動化を作るなら、さらに次を理解する必要があります。

  • tools: 使える関数をモデルに伝える。
  • tool_choice: モデルがツールを呼ぶかどうかを制御する。
  • tool_calls: モデルが何を呼びたいかを読み取る。
  • tool message: 実際のツール結果をモデルに返す。
  • stream: 応答をリアルタイム出力にする。

OpenAI 互換 API では、まず最小のテキストリクエストを通し、次にストリーミングを追加し、最後にツール呼び出しを接続するのが最も安全です。能力を 1 つ追加するたびに、本物のモデルと本物のサービス提供者で検証してください。フィールド名だけで互換性を推測しないことが大切です。

记录并分享
Hugo で構築されています。
テーマ StackJimmy によって設計されています。