記事一覧に戻る

Quentin Gallouédec's avatar

Hugging Faceのインフラ上で、1つのコマンドだけでプライベートでOpenAI互換のLLMエンドポイントを立ち上げられます — サーバーのプロビジョニング不要、Kubernetes不要、秒単位の従量課金。起動後はノートPCやノートブックなど、どこからでもクエリを実行できます。

テストや評価、バッチ生成用にモデルを素早く立ち上げるのに最適な方法です。(代わりに管理された本番向けサービスが必要な場合は、Inference Endpointsをご利用ください — どちらを選ぶかの詳細は記事末尾で解説します。)

以下でエンドツーエンドの流れを紹介します。

前提条件

  • 支払い方法の登録、または前払いクレジットの残高が正の値であること(Jobsはハードウェア使用量に応じて分単位で課金されます)。
  • huggingface_hub >= 1.20.0pip install -U "huggingface_hub>=1.20.0"
  • ローカルでログイン済み: hf auth login

サーバーを起動する

hf jobs run はHFインフラ向けの docker run です。公式の vllm/vllm-openai イメージを使用し、--flavor でGPUを指定、--expose でvLLMのポートを公開します:

hf jobs run --flavor a10g-large --expose 8000 --timeout 2h \
  vllm/vllm-openai:latest \
  vllm serve Qwen/Qwen3-4B --host 0.0.0.0 --port 8000

--expose 8000 はコンテナのポートをHFの公開Jobsプロキシ経由でルーティングします(完全なリファレンスはServe Models guideを参照)。コマンドを実行すると、サーバーにアクセスできるURLが表示されます:

✓ Job started
  id: 6a381ca1953ed90bfb947332
  url: https://huggingface.co/jobs/qgallouedec/6a381ca1953ed90bfb947332
Hint: Exposed ports are reachable at (requires an HF token with read access to the job):
  https://6a381ca1953ed90bfb947332--8000.hf.jobs

6a381ca1953ed90bfb947332 はジョブIDです。後で必要になるので控えておいてください。以降の説明では <job_id> として扱います。

重みのダウンロードと起動に数分かかります。ログに Application startup complete と表示されたら利用可能になります。

どこからでもクエリを実行する

vLLMはOpenAI APIと互換性があり、リクエストにはHFトークンをBearerトークンとして指定するだけです。最も簡単な方法はcurlです:

curl https://<job_id>--8000.hf.jobs/v1/chat/completions \
  -H "Authorization: Bearer $(hf auth token)" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen3-4B",
    "messages": [{"role": "user", "content": "Hello!"}],
    "chat_template_kwargs": {"enable_thinking": false}
  }'

通常のOpenAI形式のJSONが返され、choices[0].message.content"Hello! How can I assist you today? 😊" が含まれます。

Pythonから利用する場合は、OpenAIクライアントのベースURLに公開URLを指定し、APIキーにトークンを渡します:

from huggingface_hub import get_token
from openai import OpenAI

client = OpenAI(
    base_url="https://<job_id>--8000.hf.jobs/v1",
    api_key=get_token(),
)
resp = client.chat.completions.create(
    model="Qwen/Qwen3-4B",
    messages=[{"role": "user", "content": "Hello!"}],
    extra_body={"chat_template_kwargs": {"enable_thinking": False}},
)
print(resp.choices[0].message.content)
Hello! How can I assist you today? 😊

起動前の簡単なヘルスチェック: curl https://<job_id>--8000.hf.jobs/v1/models -H "Authorization: Bearer $(hf auth token)" でモデル一覧が取得できることを確認してください。

🔐 エンドポイントは公開ではなく、ゲートされています。 すべてのリクエストにはジョブの名前空間への読み取り権限を持つHFトークンが必要です。ブラウザで直接アクセスすると拒否されます。実質的にJobsプロキシがAPIゲートウェイとして機能し、アクセスはあなた(および所属組織)に限定されます。プライベート用途では問題ありませんが、URLは共有せず、トークンを信頼できない場所に貼り付けないでください。より細かい制御や公開アクセスが必要な場合は、適切なゲートウェイを前面に配置してください。あるいはHF JobsとInference Endpointsの違いを参照してください。

クリーンアップ

Jobsは秒単位で課金されるため、使い終わったらサーバーを停止してください:

hf jobs cancel <job_id>

--timeout は安全装置として機能しますが(自動停止されます)、明示的にキャンセルした方が安価です。a10g-large は $1.50/時間 で動作します — 完全な料金表は hf jobs hardware で確認し、モデルに合った最小のフレーバーを選択してください。

さらに進む:より大きなモデル

同じコマンドでより大きなモデルにも対応できます — より強力な --flavor を選び、--tensor-parallel-size でモデルを複数GPUに分割します。例として、122BパラメータのQwen3.5 Mixture-of-Expertsモデルを2×H200で実行する場合:

hf jobs run --flavor h200x2 --expose 8000 --timeout 2h \
  vllm/vllm-openai:latest \
  vllm serve Qwen/Qwen3.5-122B-A10B \
  --host 0.0.0.0 --port 8000 --tensor-parallel-size 2 \
  --max-model-len 32768 --max-num-seqs 256

--tensor-parallel-size はフレーバーのGPU数と一致させる必要があります(h200x2 → 2、h200x8 → 8)。利用可能なハードウェアは hf jobs hardware で確認でき、大きなモデルにはダウンロードと読み込みに時間がかかるため、--timeout を長めに設定してください。大規模モデルではH200フレーバーが最もコストパフォーマンスが良いことが多いです。

--max-model-len 32768 --max-num-seqs 256 はこのモデル固有の設定です:Qwen3.5-122BはハイブリッドMamba/attentionアーキテクチャで、256Kトークンのデフォルトコンテキストを持ちますが、vLLMのデフォルトバッチ設定ではメモリが不足します。コンテキスト長と同時シーケンス数を制限することでGPUメモリ内に収められます。モデル起動時にメモリ不足やキャッシュブロックエラーが発生した場合は、まずこの2つの値を下げてみてください。その他の部分(公開URL、OpenAIクライアント、トークン認証)は完全に同じです。

さらに進む:UIでチャットする

curlではなくチャットウィンドウで使いたい場合は、Gradioを数行書くだけで同じエンドポイントを利用できます。vllm serve コマンドに --reasoning-parser deepseek_r1 を追加すると、Qwen3の思考プロセスが別フィールドとして返されるようになります(必須ではありませんが便利です)。その後、以下のコードをローカルで実行してください(ジョブIDだけが必要です):

import gradio as gr
from gradio import ChatMessage
from huggingface_hub import get_token
from openai import OpenAI

client = OpenAI(base_url="https://<job_id>--8000.hf.jobs/v1", api_key=get_token())

def chat(message, history):
    messages = [{"role": m["role"], "content": m["content"]} for m in history if not m.get("metadata")]
    messages.append({"role": "user", "content": message})
    stream = client.chat.completions.create(model="Qwen/Qwen3-4B", messages=messages, stream=True)

    thinking, answer = "", ""
    for chunk in stream:
        delta = chunk.choices[0].delta
        thinking += delta.model_extra.get("reasoning", "")
        answer += delta.content or ""
        out = []
        if thinking.strip():
            status = "done" if answer.strip() else "pending"
            out.append(ChatMessage(role="assistant", content=thinking, metadata={"title": "💭 Thinking", "status": status}))
        if answer.strip():
            out.append(ChatMessage(role="assistant", content=answer))
        yield out

gr.ChatInterface(chat).launch()

実行後、http://127.0.0.1:7860 を開いてチャットしてください — 思考プロセスは折りたたみ可能なパネルに、回答は下部にストリーミングされます。

さらに進む:実行中のサーバーにSSH接続する

起動失敗のデバッグ、GPUメモリの監視、ログのインタラクティブな追跡が必要な場合は、実行中のジョブに直接シェルを開けます。--ssh を付けて起動し、公開鍵を huggingface.co/settings/keys に登録しておいてください:

hf jobs run --flavor a10g-large --expose 8000 --timeout 2h --ssh \
  vllm/vllm-openai:latest \
  vllm serve Qwen/Qwen3-4B --host 0.0.0.0 --port 8000

その後、ジョブIDで接続します:

hf jobs ssh <job_id>

これでコンテナ内に入り、nvidia-smi の実行、プロセスの確認、モデルへの直接アクセスが可能になります。外部からログを読むよりもデバッグや監視が容易になります。SSHサポートには huggingface_hub >= 1.20.0 が必要です。

さらに進む:Piでコーディングエージェントのバックエンドとして利用する

同じエンドポイントをターミナル型コーディングエージェントのバックエンドとして利用できます。Piはプロバイダー非依存のエージェントフレームワークです。ジョブを指定するだけで、Read/Write/Edit/Bashエージェントが自己ホストしたモデル上で動作します。

最初に設定が必要な点:エージェントはツール呼び出しを通じてモデルを駆動しますが、vLLMはツール呼び出しが有効化された状態でサーバーを起動した場合のみ受け付けます。そのため、--enable-auto-tool-choice とモデルファミリに合った --tool-call-parser(Qwen3の場合は hermes)を付けて再起動してください。より強力なモデルの方がエージェントにも有利なので、ここで大きなモデルを使うのがおすすめです:

hf jobs run --flavor h200x2 --expose 8000 --timeout 2h \
  vllm/vllm-openai:latest \
  vllm serve Qwen/Qwen3.5-122B-A10B \
  --host 0.0.0.0 --port 8000 --tensor-parallel-size 2 \
  --max-model-len 32768 --max-num-seqs 256 \
  --reasoning-parser deepseek_r1 \
  --enable-auto-tool-choice --tool-call-parser hermes

次に、~/.pi/agent/models.json にカスタムプロバイダーとしてジョブを追加します:

{
  "providers": {
    "hf-jobs": {
      "baseUrl": "https://<job_id>--8000.hf.jobs/v1",
      "api": "openai-completions",
      "apiKey": "!hf auth token",
      "models": [
        { "id": "Qwen/Qwen3.5-122B-A10B" }
      ]
    }
  }
}

その後、エージェントを起動します:

pi

数コマンド前に起動したモデルが、今度はターミナルでインタラクティブなコーディングエージェントを駆動します。

HF JobsとInference Endpointsの違い

HF JobsはHugging Face上でモデルをサーブする唯一の方法ではありません。Inference Endpointsは同じ目的のためのマネージド製品で、どちらが適するかは目的によって異なります。

HF Jobsは最大の柔軟性と制御を求める場合に選択してください:これはHFインフラ上の単なる docker run なので、イメージ、vllm serve の正確なフラグ、ハードウェアを自由に選び、ジョブの実行時間に対して秒単位で課金されます。実験、1回限りの評価、バッチ生成、またはモデルのお試しに最適です。

Inference Endpointsは本番環境向けのサービスを求める場合に選択してください。長期間稼働するサービスに必要な運用機能が追加されます:より細かいアクセス制御(エンドポイントを公開・保護・非公開に設定可能)、scale-to-zero(非アクティブ期間は課金されない)。耐久性のあるエンドポイントを立ち上げる場合はこちらを利用してください。

参考資料

この記事ではvLLMを中心に解説しましたが、同じポート公開パターンは任意のOpenAI互換サーバーで利用可能です。llama.cppでGGUFをサーブする場合やSGLangを実行する場合は、Serve Models on Jobs guideを参照してください。