🐪

Apache Camel × AI ― サービングによる推論 #1: TorchServe

2025/02/12に公開

Camel AI

リリースされたばかりのApache Camel 4.10 LTSでは、AI関連コンポーネントがさらに強化されました。なかでも、AIモデルサービングに関する3つの新しいコンポーネントが追加されています。[1]

以前の記事「Apache Camel AI ― DJLコンポーネントを使ったAIの活用方法」ではDJLコンポーネントを使ってCamelルート内でAIモデルの推論を実行する方法を紹介しましたが、4.10ではこれらの新しいコンポーネントによってCamelルートから外部のモデルサーバーを呼び出して推論を行えるようになります。

Kubeflowなどが提供するMLOpsでは、学習したモデルは最終的にモデルサーバーにデプロイされて使われることになります。サービングのコンポーネントが充実することで、Camelを使ったアプリケーションをMLOpsライフサイクルのModel Servingフェーズに容易に組み込めるようになります。

この記事では、TorchServeコンポーネントの使い方を紹介します。

TorchServeコンポーネント

TorchServeは機械学習フレームワークのPyTorchが提供するサービング機能です。Camel TorchServeコンポーネントを使うことで、TorchServeサーバーが提供するREST APIをCamelルートから呼び出せるようになります。

基本的な使い方

TorchServeの使い方の基本的な流れは、以下の通りです。

  1. PyTorchで学習したモデルをサーバーに登録する
  2. 登録したモデルのメタデータを確認する
  3. メタデータを元にモデルを呼び出して推論を行なう
  4. 使い終わったモデルをサーバーから登録解除する

Camel TorchServeコンポーネントを使う上で、実用上最も重要なのは3番目のステップですが、各ステップをどうやってCamelで実現できるかを一通り見ていきましょう。

準備

まず、Camel CLIがインストールされていなければインストールしてください。

jbang app install camel@apache/camel

インストールできたか動作確認をします。

$ camel --version
4.10.0

次に、TorchServeサーバーが必要です。最も手軽な方法はDockerイメージを使う方法です。

docker run --rm -it --name torchserve \
    -p 8080:8080 -p 8081:8081 -p 8082:8082 \
    pytorch/torchserve \
    torchserve \
        --disable-token-auth \
        --enable-model-api \
        --model-store /home/model-server/model-store

サーバーのヘルスチェック

TorchServeサーバーの動作確認は http://localhost:8080/ping にアクセスすることでできますが、Camel TorchServeコンポーネントを使ってCamelルートから確認することもできます。

torchserve:inference/ping
ping.java
//DEPS org.apache.camel:camel-bom:4.10.0@pom
//DEPS org.apache.camel:camel-core
//DEPS org.apache.camel:camel-torchserve

import org.apache.camel.builder.RouteBuilder;

public class ping extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from("timer:ping?period=10000")
            .to("torchserve:inference/ping")
            .log("Status: ${body}");
    }
}

Camel CLIから以下のように実行します。

camel run ping.java

サーバーが無事立ち上がっていれば、以下のようなステータスが得られるでしょう。

Status: Healthy

モデルの管理

TorchServeには管理APIがあり、そこから基本的な使い方のステップ1、2、4に相当するモデルの管理を行えます。一方、Camel TorchServeコンポーネントもこの管理APIに対応しており、Camelルートからもそれぞれの管理操作を行えます。

モデルの登録

まず、サーバーを立ち上げただけでは何も推論に使用できるモデルがありません。

Camelを使ってモデルを登録してみましょう。ここではPyTorch Model Zooで提供されている学習済みMNIST V2モデルを使います。

torchserve:management/register?url=https://torchserve.pytorch.org/mar_files/mnist_v2.mar
torchserve:management/scale-worker?modelName=mnist_v2
register_model.java
//DEPS org.apache.camel:camel-bom:4.10.0@pom
//DEPS org.apache.camel:camel-core
//DEPS org.apache.camel:camel-torchserve

import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.torchserve.TorchServeConstants;
import org.apache.camel.component.torchserve.client.model.ScaleWorkerOptions;

public class register_model extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from("timer:register?repeatCount=1")
            .to("torchserve:management/register?url=https://torchserve.pytorch.org/mar_files/mnist_v2.mar")
            .log("Status: ${body}")
            .to("direct:scale-worker");

        // Set up workers for the model after registration to make it available for inference
        from("direct:scale-worker")
            .setHeader(TorchServeConstants.SCALE_WORKER_OPTIONS,
                constant(ScaleWorkerOptions.builder().minWorker(1).maxWorker(2).build()))
            .to("torchserve:management/scale-worker?modelName=mnist_v2")
            .log("Status: ${body}");
    }
}

Camel CLIから以下のように実行します。

camel run register_model.java

モデルが無事登録されれば、以下のようなステータスが得られるでしょう。

Status: Model "mnist_v2" Version: 2.0 registered with 0 initial workers. Use scale workers API to add workers for the model.
Status: Processing worker updates...

デフォルトバージョンの設定

通常、推論のためにはモデル名とバージョンの指定が必要です。しかし、モデルのデフォルトバージョンを設定することでバージョンを省略できるようになります。

torchserve:management/set-default?modelName=mnist_v2&modelVersion=2.0
set_default.java
//DEPS org.apache.camel:camel-bom:4.10.0@pom
//DEPS org.apache.camel:camel-core
//DEPS org.apache.camel:camel-torchserve

import org.apache.camel.builder.RouteBuilder;

public class set_default extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from("timer:set-default?repeatCount=1")
            .to("torchserve:management/set-default?modelName=mnist_v2&modelVersion=2.0")
            .log("Status: ${body}");
    }
}

Camel CLIから以下のように実行します。

camel run set_default.java

設定が無事成功すれば、以下のようなステータスが得られるでしょう。

Status: Default version successfully updated for model "mnist_v2" to "2.0"

モデル詳細の取得

すでに登録されているモデルの詳細情報を取得することもできます。

torchserve:management/describe?modelName=mnist_v2
describe_model.java
//DEPS org.apache.camel:camel-bom:4.10.0@pom
//DEPS org.apache.camel:camel-core
//DEPS org.apache.camel:camel-torchserve

import org.apache.camel.builder.RouteBuilder;

public class describe_model extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from("timer:describe?repeatCount=1")
            .to("torchserve:management/describe?modelName=mnist_v2")
            .log("${body[0]}");
    }
}

Camel CLIから以下のように実行します。

camel run describe_model.java

成功すれば、以下のような結果が得られるでしょう。

ModelDetail {
    modelName: mnist_v2
    modelVersion: 2.0
    modelUrl: https://torchserve.pytorch.org/mar_files/mnist_v2.mar
    minWorkers: 1
    maxWorkers: 2
    batchSize: 1
    maxBatchDelay: 100
    status: null
    workers: [Worker { id: 9000, startTime: 2025-02-10T11:08:36.160Z, gpu: false, status: READY }]
    metrics: null
    jobQueueStatus: JobQueueStatus { remainingCapacity: 1000, pendingRequests: 0 }
}

モデル一覧の取得

モデルサーバーに登録されているモデルの一覧を取得することもできます。

torchserve:management/list
list_models.java
//DEPS org.apache.camel:camel-bom:4.10.0@pom
//DEPS org.apache.camel:camel-core
//DEPS org.apache.camel:camel-torchserve

import org.apache.camel.builder.RouteBuilder;

public class list_models extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from("timer:list?repeatCount=1")
            .to("torchserve:management/list")
            .log("${body.models}");
    }
}

Camel CLIから以下のように実行します。

camel run list_models.java

成功すれば、以下のような結果が得られるでしょう。今回はまだ1つしかモデルを登録していないので、一覧にも1つしかモデルがありません。

[Model { modelName: mnist_v2, modelUrl: https://torchserve.pytorch.org/mar_files/mnist_v2.mar }]

モデルの登録解除

まだこのモデルで推論を行っていないので実行はしませんが、モデルを使い終わったら登録解除できます。

torchserve:management/unregister?modelName=mnist_v2
unregister_model.java
//DEPS org.apache.camel:camel-bom:4.10.0@pom
//DEPS org.apache.camel:camel-core
//DEPS org.apache.camel:camel-torchserve

import org.apache.camel.builder.RouteBuilder;

public class unregister_model extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from("timer:unregister?repeatCount=1")
            .to("torchserve:management/unregister?modelName=mnist_v2")
            .log("Status: ${body}");
    }
}

Camel CLIから以下のように実行します。

camel run unregister_model.java

成功すれば、以下のようなステータスが得られるでしょう。

Status: Model "mnist_v2" unregistered

推論

さて、本題の推論です。最初に基本的な使い方でも書いたように、実際のCamelルートで主に使うのはこの操作(エンドポイント)です。

この記事ではMNISTモデルを使っています。28x28のグレースケールの手書きの画像を数字として認識させるモデルです。TorchServeのGitHubリポジトリにあるテストデータを使って、それをCamelルートからTorchServeに推論させてみましょう。

MNISTによる手書き数字の認識
MNISTによる手書き数字の認識

推論には以下のエンドポイントを使います。

torchserve:inference/predictions?modelName=mnist_v2
predictions.java
//DEPS org.apache.camel:camel-bom:4.10.0@pom
//DEPS org.apache.camel:camel-core
//DEPS org.apache.camel:camel-torchserve

import org.apache.camel.builder.RouteBuilder;

public class predictions extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from("file:data?noop=true&recursive=true&include=.*\\.png")
            .to("torchserve:inference/predictions?modelName=mnist_v2")
            .log("${headers.camelFileName} => ${body}");
    }
}

テストデータをローカルのdata/ディレクトリにダウンロードした後、Camel CLIから以下のように実行します。

camel run predictions.java

成功すれば、以下のような結果が得られるでしょう。手書きの数字が正しく認識されていることが確認できます。

8.png => 8
9.png => 9
4.png => 4
5.png => 5
7.png => 7
6.png => 6
2.png => 2
3.png => 3
1.png => 1
0.png => 0

メトリクス

最後にTorchServeのメトリクスAPIについても触れておきましょう。TorchServeには、モデルの使用状況をPrometheus形式のメトリクスとして出力する機能もあります。

torchserve:metrics/metrics?metricsName=MemoryUsed
metrics.java
//DEPS org.apache.camel:camel-bom:4.10.0@pom
//DEPS org.apache.camel:camel-core
//DEPS org.apache.camel:camel-torchserve

import org.apache.camel.builder.RouteBuilder;

public class metrics extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from("timer:metrics?period=10000")
            .to("torchserve:metrics/metrics?metricsName=MemoryUsed")
            .log("${body}");
    }
}

Camel CLIから以下のように実行します。

camel run metrics.java

成功すれば、以下のようにPrometheus形式で指定のメトリクスが得られるでしょう。

# HELP MemoryUsed Torchserve prometheus gauge metric with unit: Megabytes
# TYPE MemoryUsed gauge
MemoryUsed{Level="Host",Hostname="6f4ed8f42a64",} 821.91796875

まとめ

最新のCamel 4.10.0 LTSリリースで使えるAIモデルサービングコンポーネントの1つ、TorchServeコンポーネントの機能を一通り見てきました。

TorchServeコンポーネントを使えば、PyTorchで学習したAIモデルをTorchServeにデプロイし、すぐにCamelアプリケーションから利用できるようになります。Camelには既に300以上のコンポーネントが用意されており、様々な外部システムやサービスを繋いだインテグレーションのアプリケーションを開発できます。PyTorchのAIモデルをそうしたアプリケーションの中に組み込んで、これまでは難しかったより創造的なAIベースのインテグレーションを構築できるようになります。

次回の記事では、残り2つのサービングコンポーネントも紹介します。

サンプルコード

今回紹介したCamel×AIのサンプルコードは、このリポジトリで公開しています。

https://github.com/megacamelus/camel-ai-examples

脚注
  1. Camel TorchServeコンポーネントは4.9から。 ↩︎

Discussion