mcpField
M
modal

modal

github.com/kalarislabsその他7343 回インストール4 日前に更新
リポジトリ

modal について

Modalは、Pythonコードでクラウド上のサーバーレス処理を定義するプラットフォームで、AIや機械学習の実行に対応します。オンデマンドGPU、自動スケーリング、永続ストレージ、Webエンドポイント、定期実行を備えています。

主な機能

  1. 01オンデマンドGPU計算
  2. 02自動スケーリング関数
  3. 03Pythonで定義するコンテナイメージ
  4. 04永続Volumes
  5. 05Webエンドポイントと定期実行
  6. 06コード実行用の隔離Sandbox

活用シーン

  1. 01モデル推論APIのデプロイ
  2. 02GPU学習やファインチューニング
  3. 03バッチ処理の並列化
  4. 04データパイプラインの定期実行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/kalarislabs/research-agent-skills --skill modal

インストール後、Claude Code で/modalを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
api_reference.md
examples.md
functions.md
getting-started.md
gpu.md
images.md
resources.md
scaling.md
scheduled-jobs.md
secrets.md
volumes.md
web-endpoints.md

詳細

Modal

概要

Modal は、AI/ML ワークロードに重点を置いた、Python コードをサーバーレスで実行するためのクラウドプラットフォームです。主な機能は次のとおりです。

  • GPU コンピューティングを必要に応じて利用可能(T4、L4、A10、L40S、A100、H100、H200、B200)
  • ゼロから数千のコンテナまで自動スケーリングするサーバーレス関数
  • Python コードだけで構築できるカスタムコンテナイメージ
  • モデルの重みやデータセット向けの、Volumes による永続ストレージ
  • モデルや API を提供するWeb エンドポイント
  • cron または固定間隔で実行するスケジュールジョブ
  • 低レイテンシの推論を実現する1 秒未満のコールドスタート

Modal のすべてはコードとして定義されます。YAML や Dockerfile は不要です(どちらもサポートされています)。

このスキルを使うタイミング

次の場合にこのスキルを使用します。

  • AI/ML モデルをクラウドにデプロイまたは提供する
  • GPU アクセラレーションを利用した計算(トレーニング、推論、ファインチューニング)を実行する
  • サーバーレスの Web API やエンドポイントを作成する
  • バッチ処理ジョブを並列にスケーリングする
  • 定期的なタスク(データパイプライン、再トレーニング、スクレイピング)をスケジュールする
  • モデルの重みやデータセット用に永続的なクラウドストレージが必要である
  • カスタムコンテナ環境でコードを実行する
  • ジョブキューや非同期タスク処理システムを構築する

インストールと認証

インストール
uv pip install modal

Modal Python SDK は Python 3.10~3.14 をサポートしています。このスキルは安定版の modal>=1.0 API(現行リリース:1.4.x)を対象としています。

認証

新しい認証情報を作成する前に、既存の認証情報を優先して使用してください。以下の Modal 固有の変数 2 つだけが対象です。それ以外の環境変数や .env ファイルの内容は読み取ったり、読み込んだり、公開したりしないでください。

  1. 現在の環境に MODAL_TOKEN_ID と MODAL_TOKEN_SECRET がすでに設定されているか確認します。
  2. 設定されていない場合は、ローカルの .env ファイルでこの 2 つのキーだけを探し(ほかの項目はすべて無視)、ワークフローに適していれば読み込みます。
  3. どちらの方法でも 2 つの値を取得できない場合に限り、対話形式の modal setup または新しいトークンの生成に進みます。
modal setup

認証のためにブラウザーが開きます。CI/CD 環境やヘッドレス環境では、環境変数を使用してください。

export MODAL_TOKEN_ID=<your-token-id>
export MODAL_TOKEN_SECRET=<your-token-secret>

環境または .env にトークンがすでにない場合は、https://modal.com/settings で生成してください。

Modal は、月額 30 ドル分のクレジットが利用できる無料枠を提供しています。

参考:詳細なセットアップと最初のアプリの手順については、references/getting-started.md を参照してください。

基本概念

App と関数

Modal の App は、関連する関数をまとめます。@app.function() でデコレートされた関数は、クラウド上でリモート実行されます。

import modal

app = modal.App("my-app")

@app.function()
def square(x):
    return x ** 2

@app.local_entrypoint()
def main():
    # .remote() runs in the cloud
    print(square.remote(42))

modal run script.py で実行します。modal deploy script.py でデプロイします。

参考:ライフサイクルフック、クラス、.map()、.spawn() などについては、references/functions.md を参照してください。

コンテナイメージ

Modal は Python コードからコンテナイメージを構築します。推奨されるパッケージインストーラーは uv です。

image = (
    modal.Image.debian_slim(python_version="3.11")
    .uv_pip_install("torch==2.12.0", "transformers==5.9.0", "accelerate==1.13.0")
    .apt_install("git")
)

@app.function(image=image)
def inference(prompt):
    from transformers import pipeline
    pipe = pipeline("text-generation", model="meta-llama/Llama-3-8B")
    return pipe(prompt)

主なイメージメソッド:

  • .uv_pip_install() — uv で Python パッケージをインストールします(推奨)
  • .pip_install() — pip でインストールします(代替手段)
  • .apt_install() — システムパッケージをインストールします
  • .run_commands() — ビルド中にシェルコマンドを実行します
  • .run_function() — ビルド中に Python を実行します(例:モデルの重みをダウンロード)
  • .add_local_python_source() — ローカルモジュールを追加します
  • .env() — 環境変数を設定します

参考:Dockerfile、micromamba、キャッシュ、GPU ビルド手順については、references/images.md を参照してください。

GPU コンピューティング

gpu パラメーターで GPU を指定します。

@app.function(gpu="H100")
def train_model():
    import torch
    device = torch.device("cuda")
    # GPU training code here

# Multiple GPUs
@app.function(gpu="H100:4")
def distributed_training():
    ...

# GPU fallback chain
@app.function(gpu=["H100", "A100-80GB", "A100-40GB"])
def flexible_inference():
    ...

利用可能な GPU:T4、L4、A10、L40S、A100-40GB、A100-80GB、RTX-PRO-6000、H100、H200、B200、B200+

  • GPU は常に文字列として指定します(例:gpu="H100"、gpu="H100:4")。従来の modal.gpu.* オブジェクトは v0.73.31 で非推奨になりました。
  • コンテナごとに最大 8 基の GPU を利用できます(A10 は最大 4 基)
  • 推論には L40S が推奨されます(コストと性能のバランスに優れ、VRAM は 48 GB)
  • H100/A100 は、追加費用なしで H200/A100-80GB に自動アップグレードされる場合があります
  • 自動アップグレードを防ぐには、gpu="H100!" を使用します

参考:GPU の選び方とマルチ GPU トレーニングについては、references/gpu.md を参照してください。

ボリューム(永続ストレージ)

ボリュームは、分散型の永続ファイルストレージを提供します。

vol = modal.Volume.from_name("model-weights", create_if_missing=True)

@app.function(volumes={"/data": vol})
def save_model():
    # Write to the mounted path
    with open("/data/model.pt", "wb") as f:
        torch.save(model.state_dict(), f)

@app.function(volumes={"/data": vol})
def load_model():
    model.load_state_dict(torch.load("/data/model.pt"))
  • 一度書き込み、何度も読み込むワークロード(モデルの重み、データセット)向けに最適化されています
  • CLI でアクセスできます:modal volume ls、modal volume put、modal volume get
  • 数秒ごとにバックグラウンドで自動コミットされます
  • vol.with_mount_options(read_only=True, sub_path="subset") を使って、読み取り専用でマウントするか、サブディレクトリに制限できます

リファレンス:v2 ボリューム、同時書き込み、ベストプラクティスについては、references/volumes.md を参照してください。

シークレット

認証情報を関数に安全に渡します。

@app.function(secrets=[modal.Secret.from_name("my-api-keys")])
def call_api():
    import os
    api_key = os.environ["API_KEY"]
    # Use the key

CLI でシークレットを作成します:modal secret create my-api-keys API_KEY=sk-xxx

または、.env ファイルから作成します:modal.Secret.from_dotenv()

リファレンス:ダッシュボードでの設定、複数のシークレット、テンプレートについては、references/secrets.md を参照してください。

Web エンドポイント

モデルや API を Web エンドポイントとして提供します。

@app.function()
@modal.fastapi_endpoint()
def predict(text: str):
    return {"result": model.predict(text)}
  • modal serve script.py — ホットリロードと一時 URL を使った開発
  • modal deploy script.py — 固定 URL を使った本番環境へのデプロイ
  • FastAPI、ASGI(Starlette、FastHTML)、WSGI(Flask、Django)、WebSocket をサポートします
  • リクエストボディは最大 4 GiB、レスポンスサイズは無制限です

リファレンス:ASGI/WSGI アプリ、ストリーミング、認証、WebSocket については、references/web-endpoints.md を参照してください。

スケジュール済みジョブ

スケジュールに沿って関数を実行します。

@app.function(schedule=modal.Cron("0 9 * * *"))  # Daily at 9 AM UTC
def daily_pipeline():
    # ETL, retraining, scraping, etc.
    ...

@app.function(schedule=modal.Period(hours=6))
def periodic_check():
    ...

スケジュールを有効にするには、modal deploy script.py でデプロイします。

  • modal.Cron("...") — 標準的な cron 構文で、デプロイ後もスケジュールが維持されます
  • modal.Period(hours=N) — 固定間隔で実行され、再デプロイ時にリセットされます
  • 実行状況は Modal ダッシュボードで監視できます

リファレンス:cron 構文と管理については、references/scheduled-jobs.md を参照してください。

スケーリングと並行処理

Modal はコンテナを自動的にオートスケールします。上限を設定します。

@app.function(
    max_containers=100,    # Upper limit
    min_containers=2,      # Keep warm for low latency
    buffer_containers=5,   # Reserve capacity
    scaledown_window=300,  # Idle seconds before shutdown
)
def process(data):
    ...

.map() を使って入力を並列処理します。

results = list(process.map([item1, item2, item3, ...]))

@modal.concurrent を使うと、コンテナごとの同時リクエスト処理を有効にできます。スケールアップ時に余裕を持たせるため、target_inputs(オートスケーラーがコンテナごとに目標とする値)を max_inputs(ハード上限)より小さく設定します。

@app.function()
@modal.concurrent(max_inputs=10, target_inputs=8)
async def handle_request(req):
    ...

デプロイ済みの Function または Cls は、再デプロイせずに呼び出し時に再設定できます。Function.with_options()/Function.with_concurrency()/Function.with_batching()(および Cls.with_options())を使用します。

Model = modal.Cls.from_name("my-app", "Model")
fast = Model.with_options(gpu="H200", max_containers=20)
fast().generate.remote(prompt)

リファレンス:.map()、.starmap()、.spawn()、制限については、references/scaling.md を参照してください。

リソース設定
@app.function(
    cpu=4.0,              # Physical cores (not vCPUs)
    memory=16384,         # MiB
    ephemeral_disk=51200, # MiB (up to 3 TiB)
    timeout=3600,         # Seconds
)
def heavy_computation():
    ...

デフォルト値:CPU コア 0.125 個、メモリ 128 MiB。課金額はリクエスト量と使用量の大きい方に基づきます。

リファレンス:制限と課金の詳細については、references/resources.md を参照してください。

ライフサイクルフックを持つクラス

状態を保持するワークロード(例:モデルを一度読み込み、多数のリクエストに対応する場合)向けです。

@app.cls(gpu="L40S", image=image)
class Predictor:
    @modal.enter()
    def load_model(self):
        self.model = load_heavy_model()  # Runs once on container start

    @modal.method()
    def predict(self, text: str):
        return self.model(text)

    @modal.exit()
    def cleanup(self):
        ...  # Runs on container shutdown

次のように呼び出します:Predictor().predict.remote("hello")

サンドボックス

信頼できないコードや動的に生成されたコード(たとえば AI エージェントの出力やコードインタープリター)を実行するには、modal.Sandbox を使用します。装飾された Function ではなく、プログラムから作成して制御する隔離コンテナです。

app = modal.App.lookup("sandbox-demo", create_if_missing=True)

# Isolated container; restrict egress for untrusted workloads
sb = modal.Sandbox.create(
    app=app,
    image=modal.Image.debian_slim(),
    outbound_cidr_allowlist=["10.0.0.0/8"],
)

# Stream files in/out via the filesystem API (beta)
sb.filesystem.write_text("print(2 ** 10)\n", "/tmp/job.py")
contents = sb.filesystem.read_text("/tmp/job.py")

sb.terminate()
  • サンドボックス内で exec メソッドを使ってコマンド(例:python /tmp/job.py)を実行し、戻り値のプロセスハンドルから標準出力を読み取ります。詳しくは references/api_reference.md を参照してください
  • outbound_cidr_allowlist=[...]/inbound_cidr_allowlist=[...] で接続を制限します
  • sb.snapshot_filesystem() でファイルシステムのスナップショットを作成し、ベースイメージとして再利用できます
  • コードインタープリター、エージェントによるツール実行、ユーザーごとの分離に最適です

一般的なワークフローパターン

GPU モデル推論サービス
import modal

app = modal.App("llm-service")

image = (
    modal.Image.debian_slim(python_version="3.11")
    .uv_pip_install("vllm")
)

@app.cls(gpu="H100", image=image, min_containers=1)
class LLMService:
    @modal.enter()
    def load(self):
        from vllm import LLM
        self.llm = LLM(model="meta-llama/Llama-3-70B")

    @modal.method()
    @modal.fastapi_endpoint(method="POST")
    def generate(self, prompt: str, max_tokens: int = 256):
        outputs = self.llm.generate([prompt], max_tokens=max_tokens)
        return {"text": outputs[0].outputs[0].text}
バッチ処理パイプライン
app = modal.App("batch-pipeline")
vol = modal.Volume.from_name("pipeline-data", create_if_missing=True)

@app.function(volumes={"/data": vol}, cpu=4.0, memory=8192)
def process_chunk(chunk_id: int):
    import pandas as pd
    df = pd.read_parquet(f"/data/input/chunk_{chunk_id}.parquet")
    result = heavy_transform(df)
    result.to_parquet(f"/data/output/chunk_{chunk_id}.parquet")
    return len(result)

@app.local_entrypoint()
def main():
    chunk_ids = list(range(100))
    results = list(process_chunk.map(chunk_ids))
    print(f"Processed {sum(results)} total rows")
スケジュール済みデータパイプライン
app = modal.App("etl-pipeline")

@app.function(
    schedule=modal.Cron("0 */6 * * *"),  # Every 6 hours
    secrets=[modal.Secret.from_name("db-credentials")],
)
def etl_job():
    import os
    db_url = os.environ["DATABASE_URL"]
    # Extract, transform, load
    ...

CLI リファレンス

コマンド説明
modal setupModal で認証します
modal run script.pyスクリプトのローカルエントリーポイントを実行します
modal serve script.pyホットリロード対応の開発サーバー
modal deploy script.py本番環境にデプロイします
modal volume ls <name>ボリューム内のファイルを一覧表示します
modal volume put <name> <file>ファイルをボリュームにアップロードします
modal volume get <name> <file>ボリュームからファイルをダウンロードします
modal secret create <name> K=Vシークレットを作成します
modal secret listシークレットを一覧表示します
modal app listデプロイ済みアプリを一覧表示します
modal app stop <name>デプロイ済みアプリを停止します

セキュリティに関する注意事項

  • 認証情報: 認証に必要なのは MODAL_TOKEN_ID と MODAL_TOKEN_SECRET のみです。それ以外の環境変数や .env のエントリーを読み取ったり、ログに記録したり、転送したりしないでください。
  • サブプロセス/カスタムサーバー: ここで紹介する一部のパターン(マルチGPU トレーニングランチャー、@modal.web_server アプリ)は、ビルド中に subprocess.run/subprocess.Popen またはシェルコマンドを呼び出します。引数リストは固定し、ハードコードしてください。サニタイズされていないユーザー入力からサブプロセスやシェルの引数を構築しないでください。信頼できない値はコマンド引数ではなく、データ(ファイル、環境変数、標準入力)として渡してください。
  • 信頼できないコード: ユーザーまたはモデルが生成したコードは、通常の Function ではなく modal.Sandbox(上記参照)内で実行し、CIDR の許可リストを使用してネットワークアクセスを制限してください。

参照ファイル

各トピックの詳細なドキュメント:

  • references/getting-started.md — インストール、認証、最初のアプリ
  • references/functions.md — 関数、クラス、ライフサイクルフック、リモート実行
  • references/images.md — コンテナーイメージ、パッケージのインストール、キャッシュ
  • references/gpu.md — GPU の種類、選択、マルチGPU、トレーニング
  • references/volumes.md — 永続ストレージ、ファイル管理、v2 ボリューム
  • references/secrets.md — 認証情報、環境変数、dotenv
  • references/web-endpoints.md — FastAPI、ASGI/WSGI、ストリーミング、認証、WebSockets
  • references/scheduled-jobs.md — Cron、定期スケジュール、管理
  • references/scaling.md — オートスケーリング、並行処理、.map()、制限
  • references/resources.md — CPU、メモリ、ディスク、タイムアウトの設定
  • references/examples.md — 一般的なユースケースとパターン
  • references/api_reference.md — 主要な API クラスとメソッド

この概要を超える詳細情報が必要な場合は、これらのファイルを参照してください。

エージェントの実行手順

  1. 環境を確認します。 Python 環境とライブラリのバージョン(python -c "import pkg; print(pkg.__version__)")を確認し、データの形状、型、欠損値を調べます。
  2. 入力を特定します。 データまたはユーザーに確認して、形式、識別子、パラメーターを確定します。結果に影響する値は推測せず、確認してください。
  3. まず小規模に実行します。 サンプルまたは単一のフォールドで実行し、実行時間とメモリ使用量を確認します。
  4. 上記の手順と参考情報に従って、タスク全体を実行します。
  5. 結果を検証します。 ホールドアウトデータ、固定した乱数シード、適切な指標を使い、データリークがないか確認して、不確実性(信頼区間、シード間の標準偏差)を報告します。
  6. 報告します。 実行内容(バージョン、コマンド、パラメーター)、確認した内容、未確定の点を伝えます。
このような場合対応
メモリ不足、または実行が非常に遅いサブサンプリング、チャンク処理または遅延計算を使用するか、モデルサイズを小さくし、変更内容をユーザーに伝えます。
これらの手順に記載された関数、フラグ、エンドポイントがインストール済みバージョンにないインストール済みバージョンのドキュメント(help()、--help、公式ドキュメント)を確認して対応し、ユーザーに伝えます。API を捏造してはいけません。
必須の入力、識別子、パラメーターが曖昧ユーザーに確認するか、実行前に仮定を明示します。

誠実性に関するルール

  • 結果、パラメーター、識別子、引用、統計値を捏造してはいけません。実行または検証できない場合は、その旨を明確に伝えます。
  • このセッションで計算していない指標を報告してはいけません。すべての数値について、その算出に使ったコードパスを示します。
  • ここにあるバージョン固有の詳細は古くなっている可能性があるものとして扱い、インストール済みバージョンの公式ドキュメントで確認します。
  • 費用が発生する、共有 GPU やクラウドのクォータを消費する、個人情報や患者データを扱う、または取り消せない操作を行う前に、ユーザーに確認します。

関連スキル

  • modal-serverless-gpu:ML ワークロードを実行するためのサーバーレス GPU クラウドプラットフォームです。
  • tensorrt-llm:NVIDIA TensorRT を使用して LLM 推論を最適化し、最大スループットと最小レイテンシーを実現します。
  • serving-llms-vllm:vLLM の PagedAttention と連続バッチ処理を使用して、高スループットで LLM を提供します。

コメント