# Serve CLI

`transformers serve` CLIは、ローカルまたはセルフホスト環境向けの軽量なオプションです。vLLMのような専用推論エンジンに伴う追加のランタイムや運用上のオーバーヘッドを回避できます。評価、実験、中程度の負荷のデプロイメントに適しています。[continuous batching](../continuous_batching)などの機能により、スループットが向上し、レイテンシが低減されます。

> [!TIP]
> 大規模な本番環境でのデプロイには、Transformer モデルをバックエンドとして使用し、vLLM または SGLang を利用してください。詳細は [推論バックエンド](../community_integrations/transformers_as_backend) ガイドを参照してください。

`transformers serve` コマンドは、[OpenAI SDK](https://platform.openai.com/docs/overview) と互換性のあるローカルサーバーを起動します。このサーバーは多くのサードパーティ製アプリケーションと連携でき、以下の REST API をサポートしています。

- テキスト、画像、音声、動画のリクエスト用の`/v1/chat/completions`
- `/v1/completions` は、フリーフォームのプロンプトからのレガシーなテキスト補完に使用します
- `/v1/responses` は [Responses API](https://platform.openai.com/docs/api-reference/responses) をサポートしています
- 音声文字起こし用の`/v1/audio/transcriptions`
- `/v1/systemone` は、選択式、スコア、はい/いいえなどの定型質問に対して、許可された各回答の確率を返します
- `/v1/models` は、サードパーティ統合で利用可能なモデルをリストします
- `/load_model` は SSE を介してモデルの読み込み進捗をストリーミングします

サービングの依存関係をインストールします。

```bash
pip install transformers[serving]
```

`transformers serve`を実行してサーバーを起動します。デフォルトのサーバーアドレスはhttp://localhost:8000です。

```shell
transformers serve
```

## v1/chat/completions

`v1/chat/completions` API は [Chat Completions API](https://platform.openai.com/docs/api-reference/chat) に基づいています。LLM、VLM、マルチモーダルモデルのテキスト、画像、音声、動画のリクエストをサポートしています。`curl`、[InferenceClient](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/inference_client#huggingface_hub.InferenceClient)、または [OpenAI](https://platform.openai.com/docs/quickstart) クライアントと組み合わせて使用できます。

### テキストベースの補完

```python
from huggingface_hub import InferenceClient

messages = [{"role": "user", "content": "What is the Transformers library known for?"}]
client = InferenceClient("http://localhost:8000")

result = client.chat_completion(messages, model="Qwen/Qwen2.5-0.5B-Instruct", max_tokens=256)
print(result.choices[0].message.content)
```

[InferenceClient](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/inference_client#huggingface_hub.InferenceClient) は、印刷された文字列を返します。

```shell
The Transformers library is primarily known for its ability to create and manipulate large-scale language models [...]
```

```python
from huggingface_hub import InferenceClient

messages = [{"role": "user", "content": "What is the Transformers library known for?"}]
client = InferenceClient("http://localhost:8000")

stream = client.chat_completion(messages, model="Qwen/Qwen2.5-0.5B-Instruct", max_tokens=256, stream=True)
for chunk in stream:
    token = chunk.choices[0].delta.content
    if token:
        print(token, end="")
```

[InferenceClient](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/inference_client#huggingface_hub.InferenceClient) は、印刷された文字列を返します。

```shell
The Transformers library is primarily known for its ability to create and manipulate large-scale language models [...]
```

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

completion = client.chat.completions.create(
    model="Qwen/Qwen2.5-0.5B-Instruct",
    messages=[
        {
            "role": "user",
            "content": "What is the Transformers library known for?"
        }
    ],
)
print(completion.choices[0].message.content)
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```shell
The Transformers library is primarily known for its ability to create and manipulate large-scale language models [...]
```

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

completion = client.chat.completions.create(
    model="Qwen/Qwen2.5-0.5B-Instruct",
    messages=[
        {
            "role": "user",
            "content": "What is the Transformers library known for?"
        }
    ],
    stream=True,
)

for chunk in completion:
    token = chunk.choices[0].delta.content
    if token:
        print(token, end="")
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```shell
The Transformers library is primarily known for its ability to create and manipulate large-scale language models [...]
```

```shell
curl -X POST http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-0.5B-Instruct",
    "messages": [{"role": "user", "content": "What is the Transformers library known for?"}],
    "temperature": 0.9,
    "max_tokens": 256
  }'
```

このコマンドは JSON 文字列を返します。

```json
{
  "id": "ade3578d-e2c3-47ed-b651-c014991a92f6",
  "choices": [
    {
      "finish_reason": "length",
      "index": 0,
      "message": {
        "content": "The Transformers library is primarily known for its ability to create and manipulate large-scale language models [...]",
        "role": "assistant"
      }
    }
  ],
  "created": 1776184004,
  "model": "Qwen/Qwen2.5-0.5B-Instruct@main",
  "object": "chat.completion",
  "usage": {
    "completion_tokens": 256,
    "prompt_tokens": 37,
    "total_tokens": 293
  }
}
```

```shell
curl -X POST http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-0.5B-Instruct",
    "messages": [{"role": "user", "content": "What is the Transformers library known for?"}],
    "temperature": 0.9,
    "max_tokens": 256,
    "stream": true
  }'
```

このコマンドは、チャンクのストリームを返します。

```shell
data: {"id":"596d3941-754d-43b4-8773-9bf9940049f5","choices":[{"delta":{"role":"assistant"},"index":0}],"created":1776183469,"model":"Qwen/Qwen2.5-0.5B-Instruct@main","object":"chat.completion.chunk","system_fingerprint":""}

data: {"id":"596d3941-754d-43b4-8773-9bf9940049f5","choices":[{"delta":{"content":"The"},"index":0}],"created":1776183469,"model":"Qwen/Qwen2.5-0.5B-Instruct@main","object":"chat.completion.chunk","system_fingerprint":""}

(...)
```

### 画像ベースの補完

```python
from huggingface_hub import InferenceClient

messages = [
    {
        "role": "user",
        "content": [
            {"type": "text", "text": "What's in this image?"},
            {
                "type": "image_url",
                "image_url": {
                    "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
                }
            },
        ],
    }
]
client = InferenceClient("http://localhost:8000")

result = client.chat_completion(messages, model="Qwen/Qwen2.5-VL-7B-Instruct", max_tokens=256)
print(result.choices[0].message.content)
```

[InferenceClient](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/inference_client#huggingface_hub.InferenceClient) は、印刷された文字列を返します。

```xmp
The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon, given the barren, rocky landscape and the dark sky in the background. The astronaut is holding a large egg that has cracked open, revealing a small creature inside. The scene is imaginative and playful, combining elements of space exploration with a whimsical twist involving the egg and the creature.
```

```python
from huggingface_hub import InferenceClient

messages = [
    {
        "role": "user",
        "content": [
            {"type": "text", "text": "What's in this image?"},
            {
                "type": "image_url",
                "image_url": {
                    "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
                }
            },
        ],
    }
]
client = InferenceClient("http://localhost:8000")

stream = client.chat_completion(messages, model="Qwen/Qwen2.5-VL-7B-Instruct", max_tokens=256, stream=True)
for chunk in stream:
    token = chunk.choices[0].delta.content
    if token:
        print(token, end="")
```

[InferenceClient](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/inference_client#huggingface_hub.InferenceClient) は、印刷された文字列を返します。

```xmp
The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon, given the barren, rocky landscape and the dark sky in the background. The astronaut is holding a large egg that has cracked open, revealing a small creature inside. The scene is imaginative and playful, combining elements of space exploration with a whimsical twist involving the egg and the creature.
```

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

completion = client.chat.completions.create(
    model="Qwen/Qwen2.5-VL-7B-Instruct",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "What's in this image?"},
                {
                    "type": "image_url",
                    "image_url": {
                        "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
                    }
                },
            ],
        }
    ],
)
print(completion.choices[0].message.content)
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```xmp
The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon, given the barren, rocky landscape and the dark sky in the background. The astronaut is holding a large egg that has cracked open, revealing a small creature inside. The scene is imaginative and playful, combining elements of space exploration with a whimsical twist involving the egg and the creature.
```

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

completion = client.chat.completions.create(
    model="Qwen/Qwen2.5-VL-7B-Instruct",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "What's in this image?"},
                {
                    "type": "image_url",
                    "image_url": {
                        "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
                    }
                },
            ],
        }
    ],
    stream=True,
)

for chunk in completion:
    token = chunk.choices[0].delta.content
    if token:
        print(token, end="")
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```xmp
The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon, given the barren, rocky landscape and the dark sky in the background. The astronaut is holding a large egg that has cracked open, revealing a small creature inside. The scene is imaginative and playful, combining elements of space exploration with a whimsical twist involving the egg and the creature.
```

```shell
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-VL-7B-Instruct",
    "messages": [
      {
        "role": "user",
        "content": [
          {
            "type": "text",
            "text": "What's in this image?"
          },
          {
            "type": "image_url",
            "image_url": {
              "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg"
            }
          }
        ]
      }
    ],
    "max_tokens": 256
  }'
```

このコマンドは JSON 文字列を返します。

```json
{
  "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon [...]",
        "role": "assistant"
      }
    }
  ],
  "created": 1753366665,
  "model": "Qwen/Qwen2.5-VL-7B-Instruct@main",
  "object": "chat.completion",
  "usage": {
    "completion_tokens": 50,
    "prompt_tokens": 120,
    "total_tokens": 170
  }
}
```

```shell
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-VL-7B-Instruct",
    "stream": true,
    "messages": [
      {
        "role": "user",
        "content": [
          {
            "type": "text",
            "text": "What's in this image?"
          },
          {
            "type": "image_url",
            "image_url": {
              "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg"
            }
          }
        ]
      }
    ],
    "max_tokens": 256
  }'
```

このコマンドは、チャンクのストリームを返します。

```shell
data: {"id":"f47ac10b-58cc-4372-a567-0e02b2c3d479","choices":[{"delta":{"role":"assistant"},"index":0}],"created":1753366665,"model":"Qwen/Qwen2.5-VL-7B-Instruct@main","object":"chat.completion.chunk","system_fingerprint":""}

data: {"id":"f47ac10b-58cc-4372-a567-0e02b2c3d479","choices":[{"delta":{"content":"The "},"index":0}],"created":1753366701,"model":"Qwen/Qwen2.5-VL-7B-Instruct@main","object":"chat.completion.chunk","system_fingerprint":""}

(...)
```

### オーディオベースの補完

[Gemma 4](https://huggingface.co/google/gemma-4-E2B-it) や [Qwen2.5-Omni](https://huggingface.co/Qwen/Qwen2.5-Omni-3B) のようなマルチモーダルモデルは、OpenAIの`input_audio`コンテンツタイプを通じて音声入力を受け入れます。音声をBase64エンコードし、形式（`mp3`または`wav`）を指定してください。

```python
import base64
from huggingface_hub.utils import httpx
from huggingface_hub import InferenceClient

audio_url = "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"
audio_b64 = base64.b64encode(httpx.get(audio_url, follow_redirects=True).content).decode()

messages = [
    {
        "role": "user",
        "content": [
            {"type": "text", "text": "Transcribe this audio."},
            {"type": "input_audio", "input_audio": {"data": audio_b64, "format": "mp3"}},
        ],
    }
]
client = InferenceClient("http://localhost:8000")

result = client.chat_completion(messages, model="google/gemma-4-E2B-it", max_tokens=256)
print(result.choices[0].message.content)
```

[InferenceClient](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/inference_client#huggingface_hub.InferenceClient) は、印刷された文字列を返します。

```
This week, I traveled to Chicago to deliver my final farewell address to the nation, following in the tradition of presidents before me. It was an opportunity to say thank you. Whether we've seen eye to eye or rarely agreed at all, my conversations with you, the American people, in living rooms and schools, at farms and on factory floors, at diners, and on distant military outposts, all these conversations are what have kept me honest.
```

```python
import base64
from huggingface_hub.utils import httpx
from huggingface_hub import InferenceClient

audio_url = "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"
audio_b64 = base64.b64encode(httpx.get(audio_url, follow_redirects=True).content).decode()

messages = [
    {
        "role": "user",
        "content": [
            {"type": "text", "text": "Transcribe this audio."},
            {"type": "input_audio", "input_audio": {"data": audio_b64, "format": "mp3"}},
        ],
    }
]
client = InferenceClient("http://localhost:8000")

stream = client.chat_completion(messages, model="google/gemma-4-E2B-it", max_tokens=256, stream=True)
for chunk in stream:
    token = chunk.choices[0].delta.content
    if token:
        print(token, end="")
```

[InferenceClient](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/inference_client#huggingface_hub.InferenceClient) は、印刷された文字列を返します。

```
This week, I traveled to Chicago to deliver my final farewell address to the nation, following in the tradition of presidents before me. It was an opportunity to say thank you. Whether we've seen eye to eye or rarely agreed at all, my conversations with you, the American people, in living rooms and schools, at farms and on factory floors, at diners, and on distant military outposts, all these conversations are what have kept me honest.
```

```python
import base64
from huggingface_hub.utils import httpx
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

audio_url = "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"
audio_b64 = base64.b64encode(httpx.get(audio_url, follow_redirects=True).content).decode()

completion = client.chat.completions.create(
    model="google/gemma-4-E2B-it",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Transcribe this audio."},
                {"type": "input_audio", "input_audio": {"data": audio_b64, "format": "mp3"}},
            ],
        }
    ],
)
print(completion.choices[0].message.content)
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```
This week, I traveled to Chicago to deliver my final farewell address to the nation, following in the tradition of presidents before me. It was an opportunity to say thank you. Whether we've seen eye to eye or rarely agreed at all, my conversations with you, the American people, in living rooms and schools, at farms and on factory floors, at diners, and on distant military outposts, all these conversations are what have kept me honest.
```

```python
import base64
from huggingface_hub.utils import httpx
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

audio_url = "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"
audio_b64 = base64.b64encode(httpx.get(audio_url, follow_redirects=True).content).decode()

completion = client.chat.completions.create(
    model="google/gemma-4-E2B-it",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Transcribe this audio."},
                {"type": "input_audio", "input_audio": {"data": audio_b64, "format": "mp3"}},
            ],
        }
    ],
    stream=True,
)

for chunk in completion:
    token = chunk.choices[0].delta.content
    if token:
        print(token, end="")
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```
This week, I traveled to Chicago to deliver my final farewell address to the nation, following in the tradition of presidents before me. It was an opportunity to say thank you. Whether we've seen eye to eye or rarely agreed at all, my conversations with you, the American people, in living rooms and schools, at farms and on factory floors, at diners, and on distant military outposts, all these conversations are what have kept me honest.
```

```shell
# First, base64-encode the audio file and build the JSON payload
AUDIO_B64=$(curl -sL https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3 | base64 -w 0)

cat <<EOF > /tmp/audio_request.json
{
  "model": "google/gemma-4-E2B-it",
  "messages": [
    {
      "role": "user",
      "content": [
        {"type": "text", "text": "Transcribe this audio."},
        {"type": "input_audio", "input_audio": {"data": "$AUDIO_B64", "format": "mp3"}}
      ]
    }
  ]
}
EOF

curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d @/tmp/audio_request.json
```

このコマンドは JSON 文字列を返します。

```json
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "This week, I traveled to Chicago to deliver my final farewell address to the nation [...]",
        "role": "assistant"
      }
    }
  ],
  "created": 1753366665,
  "model": "google/gemma-4-E2B-it@main",
  "object": "chat.completion",
  "usage": {
    "completion_tokens": 85,
    "prompt_tokens": 200,
    "total_tokens": 285
  }
}
```

```shell
# First, base64-encode the audio file and build the JSON payload
AUDIO_B64=$(curl -sL https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3 | base64 -w 0)

cat <<EOF > /tmp/audio_request.json
{
  "model": "google/gemma-4-E2B-it",
  "stream": true,
  "messages": [
    {
      "role": "user",
      "content": [
        {"type": "text", "text": "Transcribe this audio."},
        {"type": "input_audio", "input_audio": {"data": "$AUDIO_B64", "format": "mp3"}}
      ]
    }
  ]
}
EOF

curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d @/tmp/audio_request.json
```

このコマンドは、チャンクのストリームを返します。

```shell
data: {"id":"cb997e1d-98b9-414a-be89-1880288610ef","choices":[{"delta":{"role":"assistant"},"index":0}],"created":1776254856,"model":"google/gemma-4-E2B-it@main","object":"chat.completion.chunk","system_fingerprint":""}

data: {"id":"cb997e1d-98b9-414a-be89-1880288610ef","choices":[{"delta":{"content":"This"},"index":0}],"created":1776254856,"model":"google/gemma-4-E2B-it@main","object":"chat.completion.chunk","system_fingerprint":""}

(...)
```

> [!WARNING]
> `audio_url`コンテンツタイプはOpenAI標準の一部ではない拡張機能であり、将来のバージョンで変更される可能性があります。

`audio_url` コンテンツタイプを指定してURLでオーディオを渡すこともでき、これによりbase64エンコードを省略できます。

```python
completion = client.chat.completions.create(
    model="google/gemma-4-E2B-it",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Transcribe this audio."},
                {"type": "audio_url", "audio_url": {"url": "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"}},
            ],
        }
    ],
)
```

### Videoベースの補完

> [!WARNING]
> `video_url`コンテンツタイプはOpenAI標準の一部ではない拡張機能であり、将来のバージョンで変更される可能性があります。

動画の入力には、`video_url`コンテンツタイプを使用します。モデルがオーディオをサポートしている場合（例: Gemma 4、Qwen2.5-Omni）、サーバーは動画からオーディオトラックを抽出し、ビジュアルフレームとともに処理します。

> [!TIP]
> Video処理には[torchcodec](https://github.com/pytorch/torchcodec)が必要です。`pip install torchcodec`でインストールしてください。

```python
from huggingface_hub import InferenceClient

messages = [
    {
        "role": "user",
        "content": [
            {"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
            {"type": "text", "text": "What is happening in the video and what is the song about?"},
        ],
    }
]
client = InferenceClient("http://localhost:8000")

result = client.chat_completion(messages, model="google/gemma-4-E2B-it", max_tokens=256)
print(result.choices[0].message.content)
```

[InferenceClient](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/inference_client#huggingface_hub.InferenceClient) は、印刷された文字列を返します。

```
The video captures a live music performance at a music festival or a large concert. There are several musicians on stage, including a central figure playing an acoustic guitar and singing. The foreground is filled with the backs of the audience, indicating a large crowd watching the show. The stage is dramatically lit with bright spotlights and blue and white stage lighting, with haze and smoke creating an immersive atmosphere.

The lyrics of the song are: "I don't care 'bout street, from that fresh street, 'cause there's no problem, another one I want to be, in the storm..."
```

```python
from huggingface_hub import InferenceClient

messages = [
    {
        "role": "user",
        "content": [
            {"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
            {"type": "text", "text": "What is happening in the video and what is the song about?"},
        ],
    }
]
client = InferenceClient("http://localhost:8000")

stream = client.chat_completion(messages, model="google/gemma-4-E2B-it", max_tokens=256, stream=True)
for chunk in stream:
    token = chunk.choices[0].delta.content
    if token:
        print(token, end="")
```

[InferenceClient](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/inference_client#huggingface_hub.InferenceClient) は、印刷された文字列を返します。

```
The video captures a live music performance at a music festival or a large concert. There are several musicians on stage, including a central figure playing an acoustic guitar and singing. The foreground is filled with the backs of the audience, indicating a large crowd watching the show. The stage is dramatically lit with bright spotlights and blue and white stage lighting, with haze and smoke creating an immersive atmosphere.

The lyrics of the song are: "I don't care 'bout street, from that fresh street, 'cause there's no problem, another one I want to be, in the storm..."
```

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

completion = client.chat.completions.create(
    model="google/gemma-4-E2B-it",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
                {"type": "text", "text": "What is happening in the video and what is the song about?"},
            ],
        }
    ],
    max_tokens=256,
)
print(completion.choices[0].message.content)
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```
The video captures a live music performance at a music festival or a large concert. There are several musicians on stage, including a central figure playing an acoustic guitar and singing. The foreground is filled with the backs of the audience, indicating a large crowd watching the show. The stage is dramatically lit with bright spotlights and blue and white stage lighting, with haze and smoke creating an immersive atmosphere.

The lyrics of the song are: "I don't care 'bout street, from that fresh street, 'cause there's no problem, another one I want to be, in the storm..."
```

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

completion = client.chat.completions.create(
    model="google/gemma-4-E2B-it",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
                {"type": "text", "text": "What is happening in the video and what is the song about?"},
            ],
        }
    ],
    max_tokens=256,
    stream=True,
)

for chunk in completion:
    token = chunk.choices[0].delta.content
    if token:
        print(token, end="")
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```
The video captures a live music performance at a music festival or a large concert. There are several musicians on stage, including a central figure playing an acoustic guitar and singing. The foreground is filled with the backs of the audience, indicating a large crowd watching the show. The stage is dramatically lit with bright spotlights and blue and white stage lighting, with haze and smoke creating an immersive atmosphere.

The lyrics of the song are: "I don't care 'bout street, from that fresh street, 'cause there's no problem, another one I want to be, in the storm..."
```

```shell
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/gemma-4-E2B-it",
    "messages": [
      {
        "role": "user",
        "content": [
          {"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
          {"type": "text", "text": "What is happening in the video and what is the song about?"}
        ]
      }
    ],
    "max_tokens": 256
  }'
```

このコマンドは JSON 文字列を返します。

```json
{
  "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "choices": [
    {
      "finish_reason": "length",
      "index": 0,
      "message": {
        "content": "The video captures a live music performance at a music festival or a large concert [...]",
        "role": "assistant"
      }
    }
  ],
  "created": 1753366665,
  "model": "google/gemma-4-E2B-it@main",
  "object": "chat.completion",
  "usage": {
    "completion_tokens": 256,
    "prompt_tokens": 350,
    "total_tokens": 606
  }
}
```

```shell
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/gemma-4-E2B-it",
    "stream": true,
    "messages": [
      {
        "role": "user",
        "content": [
          {"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
          {"type": "text", "text": "What is happening in the video and what is the song about?"}
        ]
      }
    ],
    "max_tokens": 256
  }'
```

このコマンドは、チャンクのストリームを返します。

```shell
data: {"id":"cb997e1d-98b9-414a-be89-1880288610ef","choices":[{"delta":{"role":"assistant"},"index":0}],"created":1776254856,"model":"google/gemma-4-E2B-it@main","object":"chat.completion.chunk","system_fingerprint":""}

data: {"id":"cb997e1d-98b9-414a-be89-1880288610ef","choices":[{"delta":{"content":"Based"},"index":0}],"created":1776254856,"model":"google/gemma-4-E2B-it@main","object":"chat.completion.chunk","system_fingerprint":""}

(...)
```

### マルチターン会話[[completions]]

マルチターン会話を行うには、`messages`リストに、`user`と`assistant`のロールが交互に並ぶ完全な会話履歴を含めてください。OpenAI互換のサーバーと同様に、このAPIはステートレスであるため、すべてのリクエストに完全な会話履歴を含める必要があります。

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

completion = client.chat.completions.create(
    model="Qwen/Qwen2.5-0.5B-Instruct",
    messages=[
        {"role": "user", "content": "What is the capital of France?"},
        {"role": "assistant", "content": "The capital of France is Paris."},
        {"role": "user", "content": "How many people live there?"},
    ],
)
print(completion.choices[0].message.content)
```

フォローアップの質問「そこに何人が住んでいますか？」は、それまでの文脈に依存しているため、モデルはパリについて回答します。

```
As of 2021, the population of Paris is approximately 2.2 million people.
```

## v1/completions

`v1/completions` API は、[レガシーの Completions API](https://platform.openai.com/docs/api-reference/completions) に基づいています。`/v1/chat/completions` とは異なり、チャットメッセージではなく自由形式のテキストである `prompt` を受け取り、生成されたテキストを `choices[].text` に返します。これは、チャットテンプレートが不要なベース（非インストラクト）モデルやテキスト補完タスクに有用です。また、fill-in-the-middle によるテキスト挿入のための `suffix` もサポートしています。

```shell
curl -X POST http://localhost:8000/v1/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-0.5B",
    "prompt": "The capital of France is",
    "max_tokens": 20
  }'
```

このコマンドは、以下のレスポンスを返します。

```json
{
  "id": "chatcmpl-abc123",
  "object": "text_completion",
  "created": 1234567890,
  "model": "Qwen/Qwen2.5-0.5B@main",
  "choices": [
    {
      "text": " Paris, and the capital of the United States is Washington, D.C.",
      "index": 0,
      "logprobs": null,
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 5,
    "completion_tokens": 16,
    "total_tokens": 21
  }
}
```

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

# Non-streaming
completion = client.completions.create(
    model="Qwen/Qwen2.5-0.5B",
    prompt="The capital of France is",
    max_tokens=20,
)
print(completion.choices[0].text)
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、以下を返します。

```shell
 Paris, and the capital of the United States is Washington, D.C.
```

ストリーミングもサポートされています。

```python
stream = client.completions.create(
    model="Qwen/Qwen2.5-0.5B",
    prompt="The capital of France is",
    max_tokens=20,
    stream=True,
)
for chunk in stream:
    print(chunk.choices[0].text, end="")
```

## v1/responses

[Responses API](https://platform.openai.com/docs/api-reference/responses)は、OpenAIの生成用の最新APIエンドポイントです。ステートフルなインタラクションをサポートし、組み込みツールを統合してモデルの機能を拡張できます。OpenAIは、新規プロジェクトではChat Completions APIよりもResponses APIの使用を[推奨](https://platform.openai.com/docs/guides/migrate-to-responses)しています。

`v1/responses` API は、`curl` コマンドおよび [OpenAI](https://platform.openai.com/docs/quickstart) クライアントを通じて、テキスト、画像、音声、動画のリクエストをサポートしています。

### テキストベースの応答

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

response = client.responses.create(
    model="Qwen/Qwen2.5-0.5B-Instruct",
    input="Tell me a three sentence bedtime story about a unicorn.",
    max_output_tokens=256,
    stream=False,
)
print(response.output[0].content[0].text)
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```shell
Once upon a time, in a faraway land, there lived a beautiful unicorn named Luna [...]
```

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

response = client.responses.create(
    model="Qwen/Qwen2.5-0.5B-Instruct",
    input="Tell me a three sentence bedtime story about a unicorn.",
    max_output_tokens=256,
    stream=True,
)

for event in response:
    if hasattr(event, "delta") and event.delta:
        print(event.delta, end="")
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```shell
Once upon a time, in a faraway land, there lived a beautiful unicorn named Luna [...]
```

```shell
curl http://localhost:8000/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-0.5B-Instruct",
    "input": "Tell me a three sentence bedtime story about a unicorn.",
    "max_output_tokens": 256,
    "stream": false
  }'
```

このコマンドは JSON 文字列を返します。

```json
{
  "id": "resp_8693af9b-b561-4267-bd1a-22d1b43284cb",
  "created_at": 1776258580.7114341,
  "model": "Qwen/Qwen2.5-0.5B-Instruct@main",
  "object": "response",
  "output": [
    {
      "id": "msg_8693af9b-b561-4267-bd1a-22d1b43284cb",
      "content": [
        {
          "annotations": [],
          "text": "Once upon a time, in a faraway land, there lived a beautiful unicorn named Luna [...]",
          "type": "output_text"
        }
      ],
      "role": "assistant",
      "status": "completed",
      "type": "message"
    }
  ],
  "status": "completed"
}
```

```shell
curl http://localhost:8000/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-0.5B-Instruct",
    "stream": true,
    "input": "Tell me a three sentence bedtime story about a unicorn.",
    "max_output_tokens": 256
  }'
```

このコマンドは、チャンクのストリームを返します。

```shell
data: {"response":{"id":"resp_req_0","created_at":1754059817.783648,"model":"Qwen/Qwen2.5-0.5B-Instruct@main","object":"response","output":[],"status":"queued"},"sequence_number":0,"type":"response.created"}

data: {"content_index":0,"delta":"Once ","item_id":"msg_req_0","output_index":0,"sequence_number":5,"type":"response.output_text.delta"}

data: {"content_index":0,"delta":"upon ","item_id":"msg_req_0","output_index":0,"sequence_number":6,"type":"response.output_text.delta"}

(...)
```

### 画像ベースの応答

Responses API は、画像、音声、動画の入力もサポートしています。

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

response = client.responses.create(
    model="Qwen/Qwen2.5-VL-7B-Instruct",
    input=[
        {"type": "input_text", "text": "What's in this image?"},
        {
            "type": "input_image",
            "image_url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
        },
    ],
    max_output_tokens=256,
    stream=False,
)
print(response.output[0].content[0].text)
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```xmp
The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon, given the barren, rocky landscape and the dark sky in the background. The astronaut is holding a large egg that has cracked open, revealing a small creature inside. The scene is imaginative and playful, combining elements of space exploration with a whimsical twist involving the egg and the creature.
```

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

response = client.responses.create(
    model="Qwen/Qwen2.5-VL-7B-Instruct",
    input=[
        {"type": "input_text", "text": "What's in this image?"},
        {
            "type": "input_image",
            "image_url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
        },
    ],
    max_output_tokens=256,
    stream=True,
)

for event in response:
    if hasattr(event, "delta") and event.delta:
        print(event.delta, end="")
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```xmp
The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon, given the barren, rocky landscape and the dark sky in the background. The astronaut is holding a large egg that has cracked open, revealing a small creature inside. The scene is imaginative and playful, combining elements of space exploration with a whimsical twist involving the egg and the creature.
```

```shell
curl http://localhost:8000/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-VL-7B-Instruct",
    "input": [
      {"type": "input_text", "text": "What'\''s in this image?"},
      {"type": "input_image", "image_url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg"}
    ],
    "max_output_tokens": 256,
    "stream": false
  }'
```

このコマンドは JSON 文字列を返します。

```json
{
  "id": "resp_f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "created_at": 1776258580.7114341,
  "model": "Qwen/Qwen2.5-VL-7B-Instruct@main",
  "object": "response",
  "output": [
    {
      "id": "msg_f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "content": [
        {
          "annotations": [],
          "text": "The image depicts an astronaut in a space suit standing on what appears to be the surface of the moon [...]",
          "type": "output_text"
        }
      ],
      "role": "assistant",
      "status": "completed",
      "type": "message"
    }
  ],
  "status": "completed"
}
```

```shell
curl http://localhost:8000/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-VL-7B-Instruct",
    "stream": true,
    "input": [
      {"type": "input_text", "text": "What'\''s in this image?"},
      {"type": "input_image", "image_url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg"}
    ],
    "max_output_tokens": 256
  }'
```

このコマンドは、チャンクのストリームを返します。

```shell
data: {"response":{"id":"resp_f47ac10b-58cc-4372-a567-0e02b2c3d479","created_at":1776258580.7114341,"model":"Qwen/Qwen2.5-VL-7B-Instruct@main","object":"response","output":[],"status":"queued"},"sequence_number":0,"type":"response.created"}

data: {"content_index":0,"delta":"The ","item_id":"msg_f47ac10b","output_index":0,"sequence_number":5,"type":"response.output_text.delta"}

(...)
```

### 音声ベースの応答

```python
import base64
from huggingface_hub.utils import httpx
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

audio_url = "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"
audio_b64 = base64.b64encode(httpx.get(audio_url, follow_redirects=True).content).decode()

response = client.responses.create(
    model="google/gemma-4-E2B-it",
    input=[
        {"type": "input_text", "text": "Transcribe this audio."},
        {"type": "input_audio", "input_audio": {"data": audio_b64, "format": "mp3"}},
    ],
    max_output_tokens=256,
    stream=False,
)
print(response.output[0].content[0].text)
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```
This week, I traveled to Chicago to deliver my final farewell address to the nation, following in the tradition of presidents before me. It was an opportunity to say thank you. Whether we've seen eye to eye or rarely agreed at all, my conversations with you, the American people, in living rooms and schools, at farms and on factory floors, at diners, and on distant military outposts, all these conversations are what have kept me honest.
```

```python
import base64
from huggingface_hub.utils import httpx
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

audio_url = "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"
audio_b64 = base64.b64encode(httpx.get(audio_url, follow_redirects=True).content).decode()

response = client.responses.create(
    model="google/gemma-4-E2B-it",
    input=[
        {"type": "input_text", "text": "Transcribe this audio."},
        {"type": "input_audio", "input_audio": {"data": audio_b64, "format": "mp3"}},
            ],
        }
    ],
    max_output_tokens=256,
    stream=True,
)

for event in response:
    if hasattr(event, "delta") and event.delta:
        print(event.delta, end="")
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```
This week, I traveled to Chicago to deliver my final farewell address to the nation, following in the tradition of presidents before me. It was an opportunity to say thank you. Whether we've seen eye to eye or rarely agreed at all, my conversations with you, the American people, in living rooms and schools, at farms and on factory floors, at diners, and on distant military outposts, all these conversations are what have kept me honest.
```

```shell
# First, base64-encode the audio file and build the JSON payload
AUDIO_B64=$(curl -sL https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3 | base64 -w 0)

cat <<EOF > /tmp/audio_request.json
{
  "model": "google/gemma-4-E2B-it",
  "input": [
    {"type": "input_text", "text": "Transcribe this audio."},
    {"type": "input_audio", "input_audio": {"data": "$AUDIO_B64", "format": "mp3"}}
  ],
  "max_output_tokens": 256,
  "stream": false
}
EOF

curl http://localhost:8000/v1/responses \
  -H "Content-Type: application/json" \
  -d @/tmp/audio_request.json
```

このコマンドは JSON 文字列を返します。

```json
{
  "id": "resp_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "created_at": 1776258580.7114341,
  "model": "google/gemma-4-E2B-it@main",
  "object": "response",
  "output": [
    {
      "id": "msg_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "content": [
        {
          "annotations": [],
          "text": "This week, I traveled to Chicago to deliver my final farewell address to the nation [...]",
          "type": "output_text"
        }
      ],
      "role": "assistant",
      "status": "completed",
      "type": "message"
    }
  ],
  "status": "completed"
}
```

```shell
# First, base64-encode the audio file and build the JSON payload
AUDIO_B64=$(curl -sL https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3 | base64 -w 0)

cat <<EOF > /tmp/audio_request.json
{
  "model": "google/gemma-4-E2B-it",
  "stream": true,
  "input": [
    {"type": "input_text", "text": "Transcribe this audio."},
    {"type": "input_audio", "input_audio": {"data": "$AUDIO_B64", "format": "mp3"}}
  ],
  "max_output_tokens": 256
}
EOF

curl http://localhost:8000/v1/responses \
  -H "Content-Type: application/json" \
  -d @/tmp/audio_request.json
```

このコマンドは、チャンクのストリームを返します。

```shell
data: {"response":{"id":"resp_a1b2c3d4-e5f6-7890-abcd-ef1234567890","created_at":1776258580.7114341,"model":"google/gemma-4-E2B-it@main","object":"response","output":[],"status":"queued"},"sequence_number":0,"type":"response.created"}

data: {"content_index":0,"delta":"This ","item_id":"msg_a1b2c3d4","output_index":0,"sequence_number":5,"type":"response.output_text.delta"}

(...)
```

> [!WARNING]
> `audio_url`コンテンツタイプはOpenAI標準の一部ではない拡張機能であり、将来のバージョンで変更される可能性があります。

`audio_url` コンテンツタイプを指定してURLでオーディオを渡すこともでき、これによりbase64エンコードを省略できます。

```python
response = client.responses.create(
    model="google/gemma-4-E2B-it",
    input=[
        {"type": "input_text", "text": "Transcribe this audio."},
        {"type": "audio_url", "audio_url": {"url": "https://huggingface.co/datasets/hf-internal-testing/dummy-audio-samples/resolve/main/obama_first_45_secs.mp3"}},
    ],
    max_output_tokens=256,
    stream=False,
)
```

### ビデオベースの応答

> [!WARNING]
> `video_url`コンテンツタイプはOpenAI標準の一部ではない拡張機能であり、将来のバージョンで変更される可能性があります。

> [!TIP]
> Video処理には[torchcodec](https://github.com/pytorch/torchcodec)が必要です。`pip install torchcodec`でインストールしてください。

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

response = client.responses.create(
    model="google/gemma-4-E2B-it",
    input=[
        {"type": "input_text", "text": "What is happening in the video and what is the song about?"},
        {"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
    ],
    max_output_tokens=256,
    stream=False,
)
print(response.output[0].content[0].text)
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```
The video captures a live music performance at a music festival or a large concert. There are several musicians on stage, including a central figure playing an acoustic guitar and singing. The foreground is filled with the backs of the audience, indicating a large crowd watching the show. The stage is dramatically lit with bright spotlights and blue and white stage lighting, with haze and smoke creating an immersive atmosphere.

The lyrics of the song are: "I don't care 'bout street, from that fresh street, 'cause there's no problem, another one I want to be, in the storm..."
```

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

response = client.responses.create(
    model="google/gemma-4-E2B-it",
    input=[
        {"type": "input_text", "text": "What is happening in the video and what is the song about?"},
        {"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}},
    ],
    max_output_tokens=256,
    stream=True,
)

for event in response:
    if hasattr(event, "delta") and event.delta:
        print(event.delta, end="")
```

[OpenAI](https://platform.openai.com/docs/quickstart)クライアントは、印刷された文字列を返します。

```
The video captures a live music performance at a music festival or a large concert. There are several musicians on stage, including a central figure playing an acoustic guitar and singing. The foreground is filled with the backs of the audience, indicating a large crowd watching the show. The stage is dramatically lit with bright spotlights and blue and white stage lighting, with haze and smoke creating an immersive atmosphere.

The lyrics of the song are: "I don't care 'bout street, from that fresh street, 'cause there's no problem, another one I want to be, in the storm..."
```

```shell
curl http://localhost:8000/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/gemma-4-E2B-it",
    "input": [
      {"type": "input_text", "text": "What is happening in the video and what is the song about?"},
      {"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}}
    ],
    "max_output_tokens": 256,
    "stream": false
  }'
```

このコマンドは JSON 文字列を返します。

```json
{
  "id": "resp_b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "created_at": 1776258580.7114341,
  "model": "google/gemma-4-E2B-it@main",
  "object": "response",
  "output": [
    {
      "id": "msg_b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "content": [
        {
          "annotations": [],
          "text": "The video captures a live music performance at a music festival or a large concert [...]",
          "type": "output_text"
        }
      ],
      "role": "assistant",
      "status": "completed",
      "type": "message"
    }
  ],
  "status": "completed"
}
```

```shell
curl http://localhost:8000/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/gemma-4-E2B-it",
    "stream": true,
    "input": [
      {"type": "input_text", "text": "What is happening in the video and what is the song about?"},
      {"type": "video_url", "video_url": {"url": "https://huggingface.co/datasets/merve/vlm_test_images/resolve/main/concert.mp4"}}
    ],
    "max_output_tokens": 256
  }'
```

このコマンドは、チャンクのストリームを返します。

```shell
data: {"response":{"id":"resp_b2c3d4e5-f6a7-8901-bcde-f12345678901","created_at":1776258580.7114341,"model":"google/gemma-4-E2B-it@main","object":"response","output":[],"status":"queued"},"sequence_number":0,"type":"response.created"}

data: {"content_index":0,"delta":"Based ","item_id":"msg_b2c3d4e5","output_index":0,"sequence_number":5,"type":"response.output_text.delta"}

(...)
```

### マルチターン会話[[responses]]

マルチターン会話では、`input`フィールドに`role`キーを持つメッセージのリストを渡します。OpenAI互換サーバーと同様に、このAPIはステートレスであるため、各リクエストには完全な会話履歴を含める必要があります。

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<random_string>")

response = client.responses.create(
    model="Qwen/Qwen2.5-0.5B-Instruct",
    input=[
        {"role": "user", "content": "What is the capital of France?"},
        {"role": "assistant", "content": "The capital of France is Paris."},
        {"role": "user", "content": "How many people live there?"},
    ],
    max_output_tokens=256,
    stream=False,
)
print(response.output[0].content[0].text)
```

フォローアップの質問「そこに何人が住んでいますか？」は、それまでの文脈に依存しているため、モデルはパリについて回答します。

```
As of 2021, Paris has a population of approximately 2.8 million people.
```

## v1/systemone

`v1/systemone` エンドポイントは、[TypeSafe の System One API](https://api.typesafe.ai/openapi.json) に従い、共有された `state` に関する型付きの質問に回答します。サポートチケットのルーティング、緊急性の評価、アクションの選択などの判断に使用します。

モデルは、テキストを生成せずに、1回のバッチ化されたフォワードパスで許可された回答にスコアを付けます。このエンドポイントは、チャットテンプレートを持つ自己回帰モデルをサポートしています。

モデル、評価する状態、および名前をキーとする質問を送信します:

```shell
curl http://localhost:8000/v1/systemone \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-1.5B-Instruct",
    "state": "Our integration has been failing for 3 days and we are losing sales!",
    "questions": {
      "team": {
        "type": "choice",
        "instructions": "Which team handles this?",
        "criteria": {"billing": null, "technical": "Bugs or integration problems"}
      },
      "urgency": {
        "type": "score",
        "instructions": "How urgent is this ticket?",
        "criteria": ["low", "medium", "high"]
      },
      "upset": {"type": "noul", "instructions": "Is the customer upset?"}
    }
  }'
```

Node.js 20以降で[TypeSafe SDK](https://github.com/typesafe-ai/typesafe-sdk-js)をインストールします:

```shell
npm install @typesafe-ai/sdk
```

`baseURL`をサーバーのルートに設定してください。SDKは`/v1/systemone`を自動的に付加します。SDKにはAPIキーが必要ですが、ローカルサーバーではプレースホルダーでも動作します。

```typescript
import { choice, noul, score, TypeSafeClient } from "@typesafe-ai/sdk";

const client = new TypeSafeClient({
  baseURL: "http://localhost:8000",
  apiKey: "<random_string>",
});

const response = await client.systemOne({
  model: "Qwen/Qwen2.5-1.5B-Instruct",
  state: "Our integration has been failing for 3 days and we are losing sales!",
  questions: {
    team: choice("Which team handles this?", {
      billing: null,
      technical: "Bugs or integration problems",
    }),
    urgency: score("How urgent is this ticket?", ["low", "medium", "high"]),
    upset: noul("Is the customer upset?"),
  },
});

console.log(response.answers.team.choice);
console.log(response.answers.urgency.score);
console.log(response.answers.upset.noul);
```

クライアントは、選択されたチーム、緊急性スコア、および顧客が不満を抱いている確率を出力します。例:

```shell
technical
1.6739138662815094
0.851952850818634
```

回答には同じ質問名が使用されます。例:

```json
{
  "model": "Qwen/Qwen2.5-1.5B-Instruct",
  "answers": {
    "team": {"type": "choice", "choice": "technical", "probabilities": {"billing": 0.000006962256520637311, "technical": 0.999993085861206}, "confidence": 0.9999861717224121},
    "urgency": {"type": "score", "score": 1.6739138662815094, "legend": {"0": "low", "1": "medium", "2": "high"}, "probabilities": {"0": 0.0031353600788861513, "1": 0.31981542706489563, "2": 0.6770492196083069}, "confidence": 0.5108707791659981},
    "upset": {"type": "noul", "noul": 0.851952850818634}
  },
  "usage": {"input_tokens": 213, "output_tokens": 0}
}
```

| 質問の種類 | `criteria` | 回答 |
| :--- | :--- | :--- |
| `choice` | 説明にマッピングされたオプション名。`null`の場合もあります。 | 最も可能性の高い選択肢、各選択肢の確率、および信頼度。 |
| `score` | レベルの説明を、低いものから高いものへ順に並べたものです。 | 確率重み付きレベルインデックス、確率、凡例、および信頼度。 |
| `noul` | `true` と `false` に対する任意の説明。 | `true`である確率。 |

`state`、任意の`instructions`、および説明には、テキストまたは JSON オブジェクトと配列を含めることができます。各リクエストは最大 64 個の質問を受け入れ、質問ごとに 1〜26 個の選択肢またはスコアレベルを指定できます。

ビジョン対応モデルでは、`data:image/...;base64,...` 形式の URL を最大 4 件含む `images` 配列を追加します。すべての質問に同じ画像が渡されます。モデルのプロセッサーとチャットテンプレートが画像をサポートしている必要があります。リモート画像 URL は受け付けられません。

### 決定設定

Decisionモデルには、プロンプト、回答ラベル、キャリブレーション設定を保存するための標準はまだ存在しません。これらはモデルの実装によって異なるため、`--decision-config` を使用して明示的に指定できます。カスタムの decision head を持つモデルには、互換性のある実装が引き続き必要です。このファイルは、プロンプトのフォーマットと next-token スコアリングの設定のみを行います。

デフォルトでは、質問にはフォールバックプロンプトと、思考機能が無効化されたモデルのチャットテンプレートが使用されます。選択肢およびスコアの回答ラベルは`A`〜`Z`、ブール値の回答ラベルは`Yes`/`No`です。確率は、これらのラベルに対する温度1のsoftmaxです。

モデルのこれらのデフォルトを上書きするには、`--decision-config` を渡します:

```shell
transformers serve openjev/openjev --decision-config decision.json
```

JSONファイルには、3つの任意フィールドがサポートされています。

| フィールド | 意味 |
| :--- | :--- |
| `labels` | `noul` の場合は、選択肢の順序に従って（`true`、次に `false`）、問題タイプごとに回答ラベルを指定します。各ラベルは、互いに異なる既知の単一トークンである必要があります。 |
| `temperature` | 質問タイプごとの正の温度。これは`softmax(label_logits / temperature)`として適用されます。 |
| `chat_template` | チャット形式やアシスタントプレフィックスを含む完全なプロンプトを置き換えるインラインの Jinja テンプレート。 |

例えば、デフォルトのプロンプトを維持したまま、ラベルとキャリブレーションを変更するには:

```json
{
  "labels": {"noul": ["A", "B"]},
  "temperature": {"choice": 0.85, "score": 0.85, "noul": 1.5547129}
}
```

カスタムテンプレートは、通常の`messages`に加えて、生の`state`、`images`、`question`フィールドを受け取ります。questionは`name`、`type`、`instructions`、`options`、`labels`、`descriptions`、`legend`を公開します。options、labels、descriptionsは同じ順序を共有しています。これらのフィールドを使用してフォールバックの文言を置き換え、構造化された値をレンダリングするには`tojson`を使用します。画像入力用のテンプレートには、モデルの画像プレースホルダーを含める必要があります。

このファイルは起動時に読み込まれ、`/v1/systemone` にのみ適用されます。省略された設定はデフォルト値が維持され、チェックポイントから決定設定が自動的に読み込まれることはありません。

## v1/audio/transcriptions

`v1/audio/transcriptions` エンドポイントは、音声認識モデルを使用して音声を文字起こしします。[Audio transcription API](https://platform.openai.com/docs/api-reference/audio/createTranscription) のフォーマットに従います。

```shell
curl -X POST http://localhost:8000/v1/audio/transcriptions \
  -H "Content-Type: multipart/form-data" \
  -F "file=@/path/to/audio.wav" \
  -F "model=openai/whisper-large-v3"
```

このコマンドは、以下のレスポンスを返します。

```shell
{
  "text": "Transcribed text from the audio file",
}
```

## v1/models

`v1/models` エンドポイントは、ローカルの Hugging Face キャッシュをスキャンし、ダウンロード済みのモデルのリストを OpenAI 互換形式で返します。サードパーティ製ツールは、このエンドポイントを使用して利用可能なモデルを検出します。

`transformers serve`を実行する前に、モデルをダウンロードしてください。

```bash
transformers download Qwen/Qwen2.5-0.5B-Instruct
```

ダウンロードが完了すると、モデルは`/v1/models`のレスポンスに表示されます。

```shell
curl http://localhost:8000/v1/models
```

エンドポイントは、利用可能なモデルを含む JSON オブジェクトを返します。

## モデルの読み込み

`/load_model` エンドポイントはモデルを事前ロードし、[Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) (SSE) を介して進捗をストリーミングします。`transformers chat` CLI はこれを自動的に使用するため、ユーザーはハングしたプロンプトの代わりに、ダウンロードおよびロードの進捗を確認できます。推論リクエストを送信する前にモデルをウォームアップするために使用してください。

### リクエスト

```shell
curl -N -X POST http://localhost:8000/load_model \
  -H "Content-Type: application/json" \
  -d '{"model": "Qwen/Qwen2.5-0.5B-Instruct"}'
```

`model` フィールドは、Hugging Face のモデル識別子です。必要に応じて `@revision` サフィックスを付与できます（`Qwen/Qwen2.5-0.5B-Instruct@main`）。revision を省略した場合、デフォルトで `main` が使用されます。

### 応答

レスポンスは SSE ストリーム（`Content-Type: text/event-stream`）です。各フレームは `data:` 行に配置された JSON オブジェクトです。

```
data: {"status": "loading", "model": "Qwen/Qwen2.5-0.5B-Instruct@main", "stage": "processor"}
```

すべてのイベントには、最低限`status`と`model`フィールドが含まれます。追加のフィールドは、ステータスによって異なります。

| フィールド | 存在する場合 | 説明 |
|-------|-------------|-------------|
| `status` | 常に | `loading`、`ready`、または `error` |
| `model` | 常に | 正規の`model_id@revision` |
| `stage` | `status == "loading"` | `processor`、`config`、`download`、`weights` のいずれか（以下のステージを参照） |
| `progress` | `download` ステージと `weights` ステージ | `current` と `total`（整数または null）を持つオブジェクト |
| `cached` | `status == "ready"` | モデルがすでにメモリ内に存在していた場合は`true` |
| `message` | `status == "error"` | エラーの説明 |

### ステージ

読み込みはこれらのステージの順に進みます。一部のステージはスキップされる場合があります（`download`は、ファイルがローカルにキャッシュ済みの場合にスキップされます）。

| ステージ | 進捗はありますか? | 説明 |
|-------|---------------|-------------|
| `processor` | いいえ | トークナイザ/プロセッサの読み込み |
| `config` | いいえ | モデル設定の読み込み |
| `download` | はい（バイト） | モデルファイルのダウンロード |
| `weights` | はい（項目） | 重みテンソルをメモリに読み込む |

ストリームは、必ず1つのターミナルイベント、`ready`（成功）または`error`（失敗）で終了します。

## タイムアウト

`transformers serve` は、すべてのモデルのリクエストを処理します。各モデルはオンデマンドで読み込まれ、GPU メモリに保持されます。300 秒間アクティブでないと、GPU メモリを解放するためにモデルは自動的にアンロードされます。`--model-timeout` を別の秒数に設定するか、`-1` を指定してアンロードを無効にできます。

```shell
transformers serve --model-timeout 400
```

### 例の読み込み

以下の例は、新規にダウンロードしたモデル、ローカルキャッシュから読み込まれたモデル（ダウンロード段階をスキップ）、そしてメモリに既に存在するモデルに対する応答を示しています。

```
data: {"status": "loading", "model": "org/model@main", "stage": "processor"}
data: {"status": "loading", "model": "org/model@main", "stage": "config"}
data: {"status": "loading", "model": "org/model@main", "stage": "download", "progress": {"current": 0, "total": 269100000}}
data: {"status": "loading", "model": "org/model@main", "stage": "download", "progress": {"current": 134600000, "total": 269100000}}
data: {"status": "loading", "model": "org/model@main", "stage": "download", "progress": {"current": 269100000, "total": 269100000}}
data: {"status": "loading", "model": "org/model@main", "stage": "weights", "progress": {"current": 1, "total": 272}}
data: {"status": "loading", "model": "org/model@main", "stage": "weights", "progress": {"current": 272, "total": 272}}
data: {"status": "ready", "model": "org/model@main", "cached": false}
```

```
data: {"status": "loading", "model": "org/model@main", "stage": "processor"}
data: {"status": "loading", "model": "org/model@main", "stage": "config"}
data: {"status": "loading", "model": "org/model@main", "stage": "weights", "progress": {"current": 1, "total": 272}}
data: {"status": "loading", "model": "org/model@main", "stage": "weights", "progress": {"current": 272, "total": 272}}
data: {"status": "ready", "model": "org/model@main", "cached": false}
```

```
data: {"status": "ready", "model": "org/model@main", "cached": true}
```

## ツール呼び出し

`transformers serve`サーバーは、OpenAIスタイルの関数呼び出しをサポートしています。ツール使用のために学習されたモデルは、アプリケーションが実行する構造化された関数呼び出しを生成します。

> [!NOTE]
> Tool calling は、トークナイザーが tool call トークンを宣言しているモデルであればすべてで動作します。Qwen と Gemma 4 はそのまま利用できます。特定のモデルでのサポートを希望する場合は、[issue](https://github.com/huggingface/transformers/issues/new/choose) を作成してください。

OpenAI形式に従い、関数仕様のリストとしてツールを定義します。

```py
import json
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<KEY>")

tools = [
  {
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Get the current weather in a location",
      "parameters": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string",
            "description": "The city name, e.g. San Francisco"
          },
          "unit": {
            "type": "string",
            "enum": ["celsius", "fahrenheit"],
            "description": "temperature unit"
          }
        },
        "required": ["location"]
      }
    }
  }
]
```

[create](https://platform.openai.com/docs/api-reference/responses/create) の `extra_body` 引数に [GenerationConfig](/docs/transformers/main/ja/main_classes/text_generation#transformers.GenerationConfig) パラメータを渡すことで、生成をカスタマイズできます。

```py
generation_config = {
  "max_new_tokens": 512,
  "temperature": 0.7,
  "top_p": 0.9,
  "top_k": 50,
  "do_sample": True,
  "repetition_penalty": 1.1,
  "no_repeat_ngram_size": 3,
}

response = client.responses.create(
  model="Qwen/Qwen2.5-7B-Instruct",
  instructions="You are a helpful weather assistant. Use the get_weather tool to answer questions.",
  input="What's the weather like in San Francisco?",
  tools=tools,
  stream=True,
  extra_body={"generation_config": json.dumps(generation_config)}
)

for event in response:
  print(event)
```

### マルチターンツール呼び出し

モデルがツール呼び出しを返した後、関数をローカルで実行し、その結果をフォローアップリクエストとして送信して、モデルの最終的な回答を取得します。このパターンは、2つのAPI間でわずかに異なります。完全な仕様については、[OpenAI function calling guide](https://developers.openai.com/api/docs/guides/function-calling?api-mode=chat)を参照してください。

以下の例では、上記で定義された`tools`リストを再利用します。

ツール結果を、対応する`tool_call_id`を持つ`role: "tool"`メッセージとして渡します。

```py
# Model returns a tool call
messages = [{"role": "user", "content": "What's the weather like in San Francisco?"}]
response = client.chat.completions.create(
    model="Qwen/Qwen2.5-7B-Instruct",
    messages=messages,
    tools=tools,
)
assistant_message = response.choices[0].message

# Execute the tool locally
tool_call = assistant_message.tool_calls[0]
result = {"temperature": 22, "condition": "sunny"}  # your actual function call here

# Send the tool result back
messages.append(assistant_message)
messages.append({
    "role": "tool",
    "tool_call_id": tool_call.id,
    "content": json.dumps(result),
})
final_response = client.chat.completions.create(
    model="Qwen/Qwen2.5-7B-Instruct",
    messages=messages,
    tools=tools,
)
print(final_response.choices[0].message.content)
```

フォローアップリクエストの`input`リストに、ツール結果を`function_call_output`アイテムとして渡します。

```py
user_message = {"role": "user", "content": "What's the weather like in San Francisco?"}
response = client.responses.create(
    model="Qwen/Qwen2.5-7B-Instruct",
    input=[user_message],
    tools=tools,
    stream=False,
)
tool_call = next(item for item in response.output if item.type == "function_call")

result = {"temperature": 22, "condition": "sunny"}

final_response = client.responses.create(
    model="Qwen/Qwen2.5-7B-Instruct",
    input=[
        user_message,
        tool_call.model_dump(exclude_none=True),
        {"type": "function_call_output", "call_id": tool_call.call_id, "output": json.dumps(result)},
    ],
    tools=tools,
    stream=False,
)
print(final_response.output_text)
```

## 推論

推論モデルは、最終的な回答の前に隠された思考連鎖を出力します。サーバーはこれらの思考スパンを検出し、表示される回答から区切り記号を除去し、推論テキストを専用のフィールドに表示することで、クライアントがそれを別々にレンダリングできるようにします。

- Chat Completions は、アシスタントメッセージの `reasoning_content` に推論を返します。
- Responses API は、`message` アイテムの前に `reasoning` 出力アイテムとして推論を返します。

推論の検出は[レスポンステンプレート](../chat_response_parsing)に依存しており、これによりサーバーは思考区間の開始位置と終了位置を特定します。サーバーは、以下の2つの場所を順に確認します。

1. モデルに同梱されている場合、トークナイザーの`response_template`属性。
2. モデルアーキテクチャに一致する組み込みのフォールバック。テンプレートがまだ同梱されていないトークナイザー向けです。

どちらの機能も持たないモデルは、レスポンスの解析なしで提供されます。生テキストがデコードされて `content` として返され、モデルが `<think>...</think>` タグを出力した場合でも、reasoning フィールドは表示されません。

### サーバーで推論を有効にする

`--reasoning` を使用して、チャットテンプレートが思考トークンを出力するかどうかを制御します。

| 値 | 動作 |
|---|---|
| `auto`（デフォルト） | チャットテンプレートのデフォルトに従います。 |
| `on` | チャットテンプレートの kwargs で `enable_thinking=True` を設定して、思考を強制オンにします。 |
| `off` | `enable_thinking=False` を設定して、思考を無効にします。 |

```sh
transformers serve Qwen/Qwen3-1.7B --reasoning on
```

> [!WARNING]
> すべてのモデルが推論をサポートしているわけではありません。`--reasoning` は、モデルのチャットテンプレートが `enable_thinking` 変数を処理する場合（またはそのトークナイザーが思考区切り文字を宣言している場合）にのみ機能します。その他のモデルでは、このフラグは黙って無視されます。

`--reasoning on` と `--reasoning off` は、チャットテンプレートの変数 `enable_thinking` を設定することで動作します。一部のチャットテンプレートでは、思考の切り替えに異なる変数名を使用したり、プロンプトのレンダリング方法を変更する追加の変数を受け入れたりします。`--chat-template-kwargs` を JSON オブジェクトとして渡すことで、任意のチャットテンプレート変数を直接指定できます。

```sh
transformers serve Qwen/Qwen3-1.7B \
  --chat-template-kwargs '{"enable_thinking": true}'
```

クライアントは、`chat_template_kwargs` をリクエストボディに含めることで、サーバーを再起動せずに、単一のリクエストに対してサーバーのデフォルト値を上書きできます。

### Chat Completions

非ストリーミングレスポンスでは、アシスタントメッセージに`reasoning_content`が`content`とともに含まれます。

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="<KEY>")

completion = client.chat.completions.create(
    model="Qwen/Qwen3-1.7B",
    messages=[{"role": "user", "content": "What is 17 * 23?"}],
)
message = completion.choices[0].message
print("reasoning:", message.reasoning_content)
print("answer:", message.content)
```

Streaming では、`content` のデルタの前に `reasoning_content` のデルタが出力されます。各フィールドをそれぞれ個別に連結してください。

```python
chunks = list(
    client.chat.completions.create(
        model="Qwen/Qwen3-1.7B",
        messages=[{"role": "user", "content": "What is 17 * 23?"}],
        stream=True,
    )
)
reasoning = "".join(getattr(c.choices[0].delta, "reasoning_content", None) or "" for c in chunks)
content = "".join(c.choices[0].delta.content or "" for c in chunks)
```

```shell
curl -X POST http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen3-1.7B",
    "messages": [{"role": "user", "content": "What is 17 * 23?"}],
    "chat_template_kwargs": {"enable_thinking": true}
  }'
```

レスポンスには、アシスタントメッセージに`reasoning_content`が含まれます。

```json
{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "17 * 23 = 391.",
        "reasoning_content": "Let me compute 17 * 23. 17 * 20 = 340, 17 * 3 = 51, so 340 + 51 = 391."
      },
      "finish_reason": "stop",
      "index": 0
    }
  ]
}
```

### Responses API

Responses API は、`message` アイテムの前に配置される独立した `reasoning` 出力アイテムとして推論を返します。

```python
response = client.responses.create(
    model="Qwen/Qwen3-1.7B",
    input="What is 17 * 23?",
    stream=False,
)
reasoning_item = next(i for i in response.output if i.type == "reasoning")
message_item = next(i for i in response.output if i.type == "message")
print("reasoning:", reasoning_item.content[0].text)
print("answer:", message_item.content[0].text)
```

Streaming では、まず reasoning アイテムを開いて `response.reasoning_text.delta` イベントを出力し、次にそれを閉じて message アイテムを開き、`response.output_text.delta` イベントを出力します。

```python
stream = client.responses.create(
    model="Qwen/Qwen3-1.7B",
    input="What is 17 * 23?",
    stream=True,
)

for event in stream:
    if event.type == "response.reasoning_text.delta":
        print(event.delta, end="")
    elif event.type == "response.output_text.delta":
        print(event.delta, end="")
```

### マルチターン往復

マルチターン会話では、前の応答の推論テキストを次のリクエストに含めてください。サーバーはこれをチャットテンプレートに渡し、テンプレートが以前のアシスタントターンの一部としてレンダリングすることで、モデルが自身の以前の思考過程を確認できるようにします。

`reasoning_content`を直前のアシスタントメッセージに付与します。

```python
first = client.chat.completions.create(
    model="Qwen/Qwen3-1.7B",
    messages=[{"role": "user", "content": "What is 17 * 23?"}],
).choices[0].message

second = client.chat.completions.create(
    model="Qwen/Qwen3-1.7B",
    messages=[
        {"role": "user", "content": "What is 17 * 23?"},
        {
            "role": "assistant",
            "content": first.content,
            "reasoning_content": first.reasoning_content,
        },
        {"role": "user", "content": "Now multiply that result by 2."},
    ],
)
print(second.choices[0].message.content)
```

アシスタントメッセージの前に、以前の`reasoning`アイテムを入力アイテムとして再度渡します。

```python
first = client.responses.create(
    model="Qwen/Qwen3-1.7B",
    input="What is 17 * 23?",
    stream=False,
)
reasoning_item = next(i for i in first.output if i.type == "reasoning")
message_item = next(i for i in first.output if i.type == "message")

second = client.responses.create(
    model="Qwen/Qwen3-1.7B",
    input=[
        {"role": "user", "content": "What is 17 * 23?"},
        reasoning_item.model_dump(exclude_none=True),
        {"role": "assistant", "content": message_item.content[0].text},
        {"role": "user", "content": "Now multiply that result by 2."},
    ],
    stream=False,
)
print(second.output_text)
```

## ポートフォワーディング

ポートフォワーディングを使用すると、リモートサーバーからモデルを配信できます。サーバーへのSSHアクセスが可能であることを確認し、ローカルマシンでこのコマンドを実行してください。

```bash
ssh -N -f -L 8000:localhost:8000 your_server_account@your_server_IP -p port_to_ssh_into_your_server
```

## 再現性

モデルを位置引数として渡すことで、リクエストごとのモデルヒントを回避し、安定して再現可能な実行を実現できます。

```sh
transformers serve Qwen/Qwen2.5-0.5B-Instruct \
  --continuous-batching \
  --dtype "bfloat16"
```

