modal について
Modalは、Pythonコードでクラウド上のサーバーレス処理を定義するプラットフォームで、AIや機械学習の実行に対応します。オンデマンドGPU、自動スケーリング、永続ストレージ、Webエンドポイント、定期実行を備えています。
主な機能
- 01オンデマンドGPU計算
- 02自動スケーリング関数
- 03Pythonで定義するコンテナイメージ
- 04永続Volumes
- 05Webエンドポイントと定期実行
- 06コード実行用の隔離Sandbox
活用シーン
- 01モデル推論APIのデプロイ
- 02GPU学習やファインチューニング
- 03バッチ処理の並列化
- 04データパイプラインの定期実行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ kalarislabs/ research-agent-skills --skill modalインストール後、Claude Code で/modalを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/api_reference.mdexamples.mdfunctions.mdgetting-started.mdgpu.mdimages.mdresources.mdscaling.mdscheduled-jobs.mdsecrets.mdvolumes.mdweb-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 ファイルの内容は読み取ったり、読み込んだり、公開したりしないでください。
- 現在の環境に
MODAL_TOKEN_IDとMODAL_TOKEN_SECRETがすでに設定されているか確認します。 - 設定されていない場合は、ローカルの
.envファイルでこの 2 つのキーだけを探し(ほかの項目はすべて無視)、ワークフローに適していれば読み込みます。 - どちらの方法でも 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 setup | Modal で認証します |
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— 認証情報、環境変数、dotenvreferences/web-endpoints.md— FastAPI、ASGI/WSGI、ストリーミング、認証、WebSocketsreferences/scheduled-jobs.md— Cron、定期スケジュール、管理references/scaling.md— オートスケーリング、並行処理、.map()、制限references/resources.md— CPU、メモリ、ディスク、タイムアウトの設定references/examples.md— 一般的なユースケースとパターンreferences/api_reference.md— 主要な API クラスとメソッド
この概要を超える詳細情報が必要な場合は、これらのファイルを参照してください。
エージェントの実行手順
- 環境を確認します。 Python 環境とライブラリのバージョン(
python -c "import pkg; print(pkg.__version__)")を確認し、データの形状、型、欠損値を調べます。 - 入力を特定します。 データまたはユーザーに確認して、形式、識別子、パラメーターを確定します。結果に影響する値は推測せず、確認してください。
- まず小規模に実行します。 サンプルまたは単一のフォールドで実行し、実行時間とメモリ使用量を確認します。
- 上記の手順と参考情報に従って、タスク全体を実行します。
- 結果を検証します。 ホールドアウトデータ、固定した乱数シード、適切な指標を使い、データリークがないか確認して、不確実性(信頼区間、シード間の標準偏差)を報告します。
- 報告します。 実行内容(バージョン、コマンド、パラメーター)、確認した内容、未確定の点を伝えます。
| このような場合 | 対応 |
|---|---|
| メモリ不足、または実行が非常に遅い | サブサンプリング、チャンク処理または遅延計算を使用するか、モデルサイズを小さくし、変更内容をユーザーに伝えます。 |
| これらの手順に記載された関数、フラグ、エンドポイントがインストール済みバージョンにない | インストール済みバージョンのドキュメント(help()、--help、公式ドキュメント)を確認して対応し、ユーザーに伝えます。API を捏造してはいけません。 |
| 必須の入力、識別子、パラメーターが曖昧 | ユーザーに確認するか、実行前に仮定を明示します。 |
誠実性に関するルール
- 結果、パラメーター、識別子、引用、統計値を捏造してはいけません。実行または検証できない場合は、その旨を明確に伝えます。
- このセッションで計算していない指標を報告してはいけません。すべての数値について、その算出に使ったコードパスを示します。
- ここにあるバージョン固有の詳細は古くなっている可能性があるものとして扱い、インストール済みバージョンの公式ドキュメントで確認します。
- 費用が発生する、共有 GPU やクラウドのクォータを消費する、個人情報や患者データを扱う、または取り消せない操作を行う前に、ユーザーに確認します。
関連スキル
modal-serverless-gpu:ML ワークロードを実行するためのサーバーレス GPU クラウドプラットフォームです。tensorrt-llm:NVIDIA TensorRT を使用して LLM 推論を最適化し、最大スループットと最小レイテンシーを実現します。serving-llms-vllm:vLLM の PagedAttention と連続バッチ処理を使用して、高スループットで LLM を提供します。