> ## Documentation Index
> Fetch the complete documentation index at: https://docs.yourouter.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Chat Completions

> OpenAI 互換 API で主要な会話モデルを統合利用します。

YouRouter でチャットモデルを使う主な方法は次の 2 つです。

1. **OpenAI 互換 API**：ほとんどの用途で推奨。統一インターフェースで多モデルを扱えます。
2. **プロバイダー固有 API**：統一 API に無い上流固有機能が必要な上級用途向け。

モデルとプロバイダーの選び方は [ルーティング](/ja/guides/router) を参照してください。

## OpenAI 互換 API

最もシンプルで柔軟な方法です。慣れた OpenAI SDK を使いつつ、モデルや上流を最小限の変更で切り替えられます。

### 基本的な使い方

次の例は、基本的な chat completion リクエストを送る方法です。`model` と `vendor` ヘッダーを変更することで、別のモデルやプロバイダーを指定できます。

<CodeGroup>
  ```python Python theme={null}
  import os
  from openai import OpenAI

  client = OpenAI(
      api_key=os.environ["YOUROUTER_API_KEY"],
      base_url="https://api.yourouter.ai/v1"
  )

  response = client.chat.completions.create(
      model="gpt-4o",
      messages=[
          {"role": "system", "content": "You are a helpful assistant."},
          {"role": "user", "content": "What is the capital of France?"}
      ],
      extra_headers={"vendor": "openai"}
  )

  print(response.choices[0].message.content)
  ```

  ```javascript Node.js theme={null}
  import OpenAI from 'openai';

  const openai = new OpenAI({
    apiKey: process.env.YOUROUTER_API_KEY,
    baseURL: 'https://api.yourouter.ai/v1',
  });

  const completion = await openai.chat.completions.create({
    messages: [
      { role: 'system', content: 'You are a helpful assistant.' },
      { role: 'user', content: 'What is the capital of France?' }
    ],
    model: 'claude-3-5-sonnet-20240620',
    extraHeaders: { vendor: 'anthropic' }
  });

  console.log(completion.choices[0].message.content);
  ```

  ```bash cURL theme={null}
  curl https://api.yourouter.ai/v1/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $YOUROUTER_API_KEY" \
    -H "vendor: google" \
    -d '{
      "model": "gemini-1.5-pro-latest",
      "messages": [{"role": "user", "content": "What is the capital of France?"}]
    }'
  ```
</CodeGroup>

### 高度な機能

#### マルチターン会話

継続的な会話を維持するには、それまでの会話履歴全体を `messages` 配列に渡します。

<CodeGroup>
  ```python Python theme={null}
  import os
  from openai import OpenAI

  client = OpenAI(
      api_key=os.environ["YOUROUTER_API_KEY"],
      base_url="https://api.yourouter.ai/v1"
  )

  messages = [
      {"role": "system", "content": "You are a witty assistant that tells jokes."},
      {"role": "user", "content": "Tell me a joke about computers."},
      {"role": "assistant", "content": "Why did the computer keep sneezing? It had a virus!"},
      {"role": "user", "content": "That was a good one. Tell me another."}
  ]

  response = client.chat.completions.create(
      model="gpt-4o",
      messages=messages
  )

  print(response.choices[0].message.content)
  ```
</CodeGroup>

#### ストリーミング

チャットボットなどのリアルタイム用途では、生成中のレスポンスをストリーミングできます。リクエストで `stream=True` を設定します。

<CodeGroup>
  ```python Python theme={null}
  import os
  from openai import OpenAI

  client = OpenAI(
      api_key=os.environ["YOUROUTER_API_KEY"],
      base_url="https://api.yourouter.ai/v1"
  )

  stream = client.chat.completions.create(
      model="claude-3-haiku-20240307",
      messages=[{"role": "user", "content": "Write a short poem about the ocean."}],
      stream=True,
      extra_headers={"vendor": "anthropic"}
  )

  for chunk in stream:
      if chunk.choices[0].delta.content is not None:
          print(chunk.choices[0].delta.content, end="")
  ```
</CodeGroup>

#### 関数呼び出し / ツール利用

モデルにツールや関数を使わせ、外部システムと連携できます。一般的な流れは次の複数ステップです。

1. 利用可能なツール一覧を含めてリクエストを送ります。
2. モデルが、呼び出したい 1 つ以上のツールを返します。
3. アプリケーション側のコードでツールを実行します。
4. ツールの実行結果をモデルへ返し、モデルが最終的な自然言語の回答を生成します。

<CodeGroup>
  ```python Python theme={null}
  import json
  import os
  from openai import OpenAI

  client = OpenAI(
      api_key=os.environ["YOUROUTER_API_KEY"],
      base_url="https://api.yourouter.ai/v1"
  )

  def get_current_weather(location, unit="celsius"):
      """Get the current weather in a given location"""
      if "boston" in location.lower():
          return json.dumps({"location": "Boston", "temperature": "10", "unit": unit})
      else:
          return json.dumps({"location": location, "temperature": "unknown"})

  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"]
              }
          }
      }
  ]

  messages = [{"role": "user", "content": "What's the weather like in Boston, MA?"}]

  response = client.chat.completions.create(
      model="gpt-4o",
      messages=messages,
      tools=tools,
      tool_choice="auto"
  )

  response_message = response.choices[0].message
  tool_calls = response_message.tool_calls

  if tool_calls:
      available_functions = {
          "get_current_weather": get_current_weather,
      }
      messages.append(response_message)

      for tool_call in tool_calls:
          function_name = tool_call.function.name
          function_to_call = available_functions[function_name]
          function_args = json.loads(tool_call.function.arguments)

          function_response = function_to_call(
              location=function_args.get("location"),
              unit=function_args.get("unit"),
          )

          messages.append(
              {
                  "tool_call_id": tool_call.id,
                  "role": "tool",
                  "name": function_name,
                  "content": function_response,
              }
          )

      second_response = client.chat.completions.create(
          model="gpt-4o",
          messages=messages,
      )

      final_response = second_response.choices[0].message.content
      print(final_response)
  ```
</CodeGroup>

#### ビジョン（マルチモーダル）

多くのモデルはマルチモーダル入力に対応しており、リクエストに画像を含められます。画像説明、画像分析、視覚的な Q\&A などに便利です。この機能は特定のプロバイダーだけのものではなく、`gpt-4o`、`claude-3-5-sonnet-20240620`、`gemini-1.5-pro-latest` などのモデルがビジョン機能を持っています。

<CodeGroup>
  ```python Python theme={null}
  import base64
  import os
  from openai import OpenAI

  client = OpenAI(
      api_key=os.environ["YOUROUTER_API_KEY"],
      base_url="https://api.yourouter.ai/v1"
  )

  def encode_image(image_path):
    with open(image_path, "rb") as image_file:
      return base64.b64encode(image_file.read()).decode('utf-8')

  image_path = "image.jpg"
  base64_image = encode_image(image_path)

  response = client.chat.completions.create(
      model="claude-3-5-sonnet-20240620",
      messages=[
          {
              "role": "user",
              "content": [
                  {"type": "text", "text": "What’s in this image?"},
                  {
                      "type": "image_url",
                      "image_url": {
                          "url": f"data:image/jpeg;base64,{base64_image}"
                      }
                  }
              ]
          }
      ],
      max_tokens=300,
      extra_headers={"vendor": "anthropic"}
  )

  print(response.choices[0].message.content)
  ```
</CodeGroup>

### パラメータ（代表）

| パラメータ               | 型                | 説明                                                        | 既定値     |
| ------------------- | ---------------- | --------------------------------------------------------- | ------- |
| `model`             | string           | 使用するモデル ID。                                               | 必須      |
| `messages`          | array            | これまでの会話を構成するメッセージ一覧。                                      | 必須      |
| `max_tokens`        | integer          | chat completion で生成する最大トークン数。                             | `null`  |
| `temperature`       | number           | 使用するサンプリング温度。通常は 0 から 2 の範囲です。                            | `1`     |
| `top_p`             | number           | temperature の代替となる nucleus sampling の指定。                  | `1`     |
| `n`                 | integer          | 入力メッセージごとに生成する chat completion 候補数。                       | `1`     |
| `stream`            | boolean          | 設定すると、ChatGPT と同様に部分的な message delta を順次送信します。            | `false` |
| `stop`              | string or array  | 最大 4 つの停止シーケンス。API は該当箇所でそれ以上のトークン生成を停止します。               | `null`  |
| `presence_penalty`  | number           | -2.0 から 2.0 の値。正の値は、これまでのテキストに出現したかどうかに基づいて新しいトークンを抑制します。 | `0`     |
| `frequency_penalty` | number           | -2.0 から 2.0 の値。正の値は、これまでのテキスト内での出現頻度に基づいて新しいトークンを抑制します。   | `0`     |
| `logit_bias`        | map              | 指定したトークンが completion に出現する確率を調整します。                       | `null`  |
| `user`              | string           | エンドユーザーを表す一意の識別子。監視や不正利用検知に役立ちます。                         | `null`  |
| `tool_choice`       | string or object | モデルがツールを使うか、どのように使うかを制御します。                               | `none`  |
| `tools`             | array            | モデルが呼び出せるツールの一覧。                                          | `null`  |

***

## プロバイダー固有 API

統一 API に無いパラメータや挙動が必要な場合、上流のネイティブエンドポイントへ直接リクエストできます。**この場合は `vendor` ヘッダーが必須**です。

<Note>
  YouRouter は `Authorization` 以外のヘッダーとリクエストボディを可能な限りそのまま上流へ転送します。詳細は [リクエスト転送](/ja/features/request-forwarding) を参照してください。
</Note>

### Gemini（Google）

#### Generate Content

**Endpoint:** `POST /v1/projects/cognition/locations/us/publishers/google/models/{model}:generateContent`

<CodeGroup>
  ```python Python theme={null}
  import os
  import requests
  import json

  url = "https://api.yourouter.ai/v1/projects/cognition/locations/us/publishers/google/models/gemini-1.5-pro-latest:generateContent"

  headers = {
      "Authorization": f"Bearer {os.environ['YOUROUTER_API_KEY']}",
      "Content-Type": "application/json",
      "vendor": "google"
  }

  data = {
      "contents": [{
          "parts": [{"text": "Write a short story about a time-traveling historian."}]
      }]
  }

  response = requests.post(url, headers=headers, json=data)

  print(json.dumps(response.json(), indent=2))
  ```
</CodeGroup>

#### Safety Settings

リクエストに `safetySettings` オブジェクトを含めることで、コンテンツの安全性しきい値を設定できます。カテゴリとしきい値の完全な一覧は、公式の [Google AI ドキュメント](https://ai.google.dev/docs/safety_setting_gemini) を参照してください。

<CodeGroup>
  ```python Python theme={null}
  import os
  import requests
  import json

  url = "https://api.yourouter.ai/v1/projects/cognition/locations/us/publishers/google/models/gemini-pro:generateContent"

  headers = {
      "Authorization": f"Bearer {os.environ['YOUROUTER_API_KEY']}",
      "Content-Type": "application/json",
      "vendor": "google"
  }

  data = {
      "contents": [{"parts": [{"text": "Tell me a potentially controversial joke."}]}],
      "safetySettings": [
          {
              "category": "HARM_CATEGORY_HATE_SPEECH",
              "threshold": "BLOCK_LOW_AND_ABOVE"
          },
          {
              "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
              "threshold": "BLOCK_MEDIUM_AND_ABOVE"
          }
      ]
  }

  response = requests.post(url, headers=headers, json=data)

  print(json.dumps(response.json(), indent=2))
  ```
</CodeGroup>

### Claude（Anthropic）

#### Messages API

**Endpoint:** `POST /v1/messages`

<CodeGroup>
  ```python Python theme={null}
  import os
  import requests
  import json

  url = "https://api.yourouter.ai/v1/messages"

  headers = {
      "Authorization": f"Bearer {os.environ['YOUROUTER_API_KEY']}",
      "Content-Type": "application/json",
      "anthropic-version": "2023-06-01",
      "vendor": "anthropic"
  }

  data = {
      "model": "claude-3-5-sonnet-20240620",
      "max_tokens": 1024,
      "messages": [
          {"role": "user", "content": "Explain the concept of neural networks to a 5-year-old."}
      ]
  }

  response = requests.post(url, headers=headers, json=data)

  print(json.dumps(response.json(), indent=2))
  ```
</CodeGroup>

#### Claude のツール利用

Claude にツールセットを渡すと、ユーザーのリクエストに答えるためにいつツールを使うべきかをモデルが判断します。この処理は複数ターンの会話で構成され、コード側でツールを実行し、その結果を Claude に返します。

以下は、ツール利用のライフサイクル全体を示す完全な例です。

<CodeGroup>
  ```python Python theme={null}
  import os
  import requests
  import json

  def get_weather(location):
      if "san francisco" in location.lower():
          return json.dumps({"location": "San Francisco", "temperature": "15°C", "forecast": "Cloudy"})
      else:
          return json.dumps({"location": location, "temperature": "unknown"})

  tools = [
      {
          "name": "get_weather",
          "description": "Get the current weather in a given location.",
          "input_schema": {
              "type": "object",
              "properties": {
                  "location": {
                      "type": "string",
                      "description": "The city and state, e.g. San Francisco, CA"
                  }
              },
              "required": ["location"]
          }
      }
  ]

  messages = [{"role": "user", "content": "What is the weather like in San Francisco?"}]

  initial_data = {
      "model": "claude-3-opus-20240229",
      "max_tokens": 1024,
      "tools": tools,
      "messages": messages
  }

  response = requests.post(
      "https://api.yourouter.ai/v1/messages",
      headers={
          "Authorization": f"Bearer {os.environ['YOUROUTER_API_KEY']}",
          "Content-Type": "application/json",
          "anthropic-version": "2023-06-01",
          "vendor": "anthropic"
      },
      json=initial_data
  )

  response_data = response.json()

  if response_data.get("stop_reason") == "tool_use":
      tool_use_block = next(
          (block for block in response_data["content"] if block.get("type") == "tool_use"), None
      )

      if tool_use_block:
          tool_name = tool_use_block["name"]
          tool_input = tool_use_block["input"]
          tool_use_id = tool_use_block["id"]

          if tool_name == "get_weather":
              tool_result = get_weather(tool_input.get("location", ""))

              messages.append({"role": "assistant", "content": response_data["content"]})
              messages.append({
                  "role": "user",
                  "content": [
                      {
                          "type": "tool_result",
                          "tool_use_id": tool_use_id,
                          "content": tool_result,
                      }
                  ],
              })

              final_data = {
                  "model": "claude-3-opus-20240229",
                  "max_tokens": 1024,
                  "tools": tools,
                  "messages": messages
              }

              final_response = requests.post(
                  "https://api.yourouter.ai/v1/messages",
                  headers={
                      "Authorization": f"Bearer {os.environ['YOUROUTER_API_KEY']}",
                      "Content-Type": "application/json",
                      "anthropic-version": "2023-06-01",
                      "vendor": "anthropic"
                  },
                  json=final_data
              ).json()

              final_text = next(
                  (block["text"] for block in final_response["content"] if block.get("type") == "text"),
                  "No final text response found."
              )
              print(final_text)
  ```
</CodeGroup>

***

## ベストプラクティス

* **ルーティング**：本番アプリケーションでは、高可用性のために `auto` ルーティングモードを使います。特定のモデルバージョンや機能が必要な場合は手動ルーティングを使います。詳細は [ルーティング](/ja/guides/router) を参照してください。
* **エラー処理**：ネットワーク問題やプロバイダー障害は起こり得ます。特に長時間実行されるタスクでは、堅牢なエラー処理と指数バックオフ付きの再試行を実装してください。
* **UX のためのストリーミング**：ユーザー向けアプリケーションでは、応答性の高いリアルタイム体験を提供するためにストリーミングを使います。
* **システムプロンプト**：よく設計された system prompt は、モデルの振る舞い、口調、パーソナリティを導くうえで重要です。十分にテストし、継続的に改善してください。
* **トークン管理**：入力コンテキストと出力生成の両方について、常にトークン上限を意識してください。API レスポンスの `usage` データを監視し、コストを追跡しながら予期しない切り詰めを避けます。
