1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IBM Spyreで動かす推論サーバーでエンティティ抽出を試してみる

1
Posted at

はじめに

IBM Spyre は、IBM Power サーバーに搭載可能な AI アクセラレーターです。
PCIe 接続の AIU(AI Unit)デバイスとして認識され、vLLM のバックエンドとして大規模言語モデルの推論に利用できます。

これまでに書いたSpyre関連の記事はこちら

今回は Spyre 上で Granite 4.1 モデルを使った推論サーバーを立ち上げ、発注書のテキストからエンティティ(構造化データ)を抽出するシナリオを試してみます。
Red Hat AI Inference(RHAII) は OpenAI 互換 API として起動するため、curl や既存の OpenAI クライアントをそのまま使えるのが便利なところです。
RHAIIは、3.5のEarly access版を使用しています。

環境

  • IBM Spyre アクセラレーター搭載サーバー
  • モデル: granite-4.1-8b-fp8
  • コンテナランタイム: Podman
  • コンテナイメージ: registry.redhat.io/rhaii-early-access/vllm-spyre-rhel9:3.5.0-ea.1-1781067361

推論サーバーの起動

環境変数の設定

利用する AIU デバイスやモデルパス、バッチサイズなどを環境変数で定義します。

# 利用する AIU デバイスの PCIe アドレス(実際の環境のアドレスに変更)
export AIU_IDS="xxxx:xx:xx.x"
# コンテナにマウントするモデルのパス
export VLLM_MODEL_PATH=/models/granite-4.1-8b-fp8
# 使用する AIU の数(テンソル並列度)
export AIU_WORLD_SIZE=1
# モデルが処理する最大トークン長
export MAX_MODEL_LEN=3072
# 同時に処理できるリクエストの最大数
export MAX_BATCH_SIZE=16

Podman でコンテナを起動

以下の podman run コマンドで vLLM サービスを起動します。

podman run -it \
  --name entity-ext \
  --replace \
  --device=/dev/vfio \                    # AIU デバイスへのアクセスを許可
  -v /home/models:/models:Z \             # モデルディレクトリをマウント
  -e AIU_PCIE_IDS="${AIU_IDS}" \          # 使用する AIU の PCIe アドレスを渡す
  -e VLLM_SPYRE_USE_CB=1 \               # Spyre の Continuous Batching を有効化
  --pids-limit 0 \
  --userns=keep-id \
  --group-add=keep-groups \
  --security-opt label=disable \
  --memory 100G \
  --shm-size 64G \
  -p 0.0.0.0:8000:8000 \
  registry.redhat.io/rhaii-early-access/vllm-spyre-rhel9:3.5.0-ea.1-1781067361 \
  --model "${VLLM_MODEL_PATH}" \
  -tp "${AIU_WORLD_SIZE}" \
  --max-model-len "${MAX_MODEL_LEN}" \
  --max-num-seqs ${MAX_BATCH_SIZE} \
  --enable-prefix-caching

主なオプションの補足は以下のとおりです。

オプション 説明
AIU_PCIE_IDS 使用する Spyre(AIU)デバイスの PCIe アドレスを指定
VLLM_SPYRE_USE_CB=1 Spyre 固有の Continuous Batching モードを有効にする
-tp テンソル並列度(使用する AIU 数)を指定
--enable-prefix-caching プレフィックスキャッシュを有効にし、同じシステムプロンプトを再利用する際の効率を上げる

起動後にログへ以下のような出力が流れれば、サービスが正常に起動しています。

INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000

念のため curl で疎通確認しておくと安心です。

curl -s http://xxx.xxx.xxx.xxx:8000/health

{}200 OK が返れば問題ありません。

エンティティ抽出を試してみる

推論サーバーが起動したら、発注書テキストからのエンティティ抽出を試してみます。

プロンプト設計

システムプロンプトで JSON 形式での応答を指示します。

あなたは発注書のテキストから情報を抽出する専門家です。
与えられたテキストから以下のJSONフォーマットで情報を抽出してください。
見つからない情報は空文字または0で補完してください。
必ずJSON形式のみで返答してください。

ユーザーメッセージには、出力スキーマの例と発注書のテキストを合わせて渡します。

以下の発注書テキストから情報を抽出し、次のJSONスキーマに従って返答してください。

スキーマ例:
{
  "customer_name": "顧客名",
  "customer_email": "メールアドレス",
  "customer_address": "住所",
  "items": [{ "product_name": "商品名", "quantity": 1, "unit_price": 1000 }],
  "total_amount": 1000,
  "notes": "備考"
}

発注書テキスト:
発注書
発注日: 2025年7月1日
発注者: 株式会社テック商事
メール: order@example.co.jp
住所: 東京都千代田区丸の内1-2-3
品目:
- ノートPC  5台  120,000円
- マウス    10個   3,000円
合計金額: 630,000円
備考: 納期2週間以内

curl での実行

エンドポイントの URL とモデル名を変数で定義しておきます。

INFERENCE_API_BASE_URL="http://xxx.xxx.xxx.xxx:8000"
INFERENCE_API_KEY=""
INFERENCE_MODEL_NAME="/models/granite-4.1-8b-fp8"

response_formatjson_object を指定することで、モデルが JSON のみを返すように制御できます。
なお、この機能はモデルによって対応が異なります。Granite 4.1 では問題なく動作しましたが、別モデルを使う場合は事前に確認してください。

curl -s -X POST "${INFERENCE_API_BASE_URL}/v1/chat/completions" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${INFERENCE_API_KEY}" \
  -d "{
    \"model\": \"${INFERENCE_MODEL_NAME}\",
    \"response_format\": { \"type\": \"json_object\" },
    \"messages\": [
      {
        \"role\": \"system\",
        \"content\": \"あなたは発注書のテキストから情報を抽出する専門家です。与えられたテキストから以下のJSONフォーマットで情報を抽出してください。見つからない情報は空文字または0で補完してください。必ずJSON形式のみで返答してください。\"
      },
      {
        \"role\": \"user\",
        \"content\": \"以下の発注書テキストから情報を抽出し、次のJSONスキーマに従って返答してください。\nスキーマ例:\n{\\\"customer_name\\\":\\\"顧客名\\\",\\\"customer_email\\\":\\\"メールアドレス\\\",\\\"customer_address\\\":\\\"住所\\\",\\\"items\\\":[{\\\"product_name\\\":\\\"商品名\\\",\\\"quantity\\\":1,\\\"unit_price\\\":1000}],\\\"total_amount\\\":1000,\\\"notes\\\":\\\"備考\\\"}\n\n発注書テキスト:\n発注書\n発注日: 2025年7月1日\n発注者: 株式会社テック商事\nメール: order@example.co.jp\n住所: 東京都千代田区丸の内1-2-3\n品目:\n- ノートPC  5台  120,000円\n- マウス    10個   3,000円\n合計金額: 630,000円\n備考: 納期2週間以内\"
      }
    ]
  }" | jq '.choices[0].message.content | fromjson'

実行結果

以下のような JSON が返ってきます。
品目ごとに商品名・数量・単価が正しく分解され、合計金額・備考も含めて構造化されていることが確認できます。

{
  "customer_name": "株式会社テック商事",
  "customer_email": "order@example.co.jp",
  "customer_address": "東京都千代田区丸の内1-2-3",
  "items": [
    {
      "product_name": "ノートPC",
      "quantity": 5,
      "unit_price": 120000
    },
    {
      "product_name": "マウス",
      "quantity": 10,
      "unit_price": 3000
    }
  ],
  "total_amount": 630000,
  "notes": "納期2週間以内"
}

自然言語で書かれた発注書から、構造化された JSON を正確に抽出できています。

まとめ

IBM Spyre 上の vLLM を使って、発注書テキストからのエンティティ抽出を試してみました。

OpenAI 互換 API を利用しているため、response_format: json_object を指定するだけで JSON 出力を強制でき、後続のパース処理をシンプルに保てます。
プロンプトにスキーマ例を含めることで、フィールド構成が変わっても柔軟に対応できるのも利点です。

実際の業務利用に向けては、以下の点を考慮しておくと良いと思います。

Spyre の起動さえ済んでしまえば、あとは通常の OpenAI 互換クライアントと同じ感覚で使えるので、既存の処理パイプラインへの組み込みもしやすいと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?