关于 modal-compute-knowledge
modal-compute-knowledge 是面向 Modal 用户的参考指南,整理 Python 无服务器计算平台的功能、配置和实践。它涵盖 GPU 函数、容器、存储、调度、并行任务、CLI 与计费信息。
主要功能
- 01配置 Python 函数与容器
- 02参考 GPU 和镜像构建设置
- 03管理卷、密钥及分布式存储
- 04设置 Web 端点与定时任务
- 05使用并行处理和 CLI 命令
- 06查阅定价与部署实践
适用场景
- 01部署 GPU 加速的推理任务
- 02创建 Web API 或定时任务
- 03并行处理批量数据
- 04管理应用部署、存储和密钥
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ josiahsiegel/ claude-plugin-marketplace --skill modal-compute-knowledge安装后在 Claude Code 中输入/modal-compute-knowledge确认已加载。
附带文件references/batched-dynamic-batching.mdreferences/scaling-autoscaler.md
详细介绍
Modal 知识技能
全面介绍 Modal.com 平台的知识,涵盖所有功能、定价和最佳实践。当用户需要详细了解 Modal 的无服务器云平台时,激活此技能。
激活条件
用户询问以下内容时,激活此技能:
- Modal.com 平台的功能与能力
- GPU 加速的 Python 函数
- 无服务器容器配置
- Modal 定价和账单
- Modal CLI 命令
- Modal 上的 Web 端点和 API
- Modal 上的定时/cron 任务
- Modal 卷、密钥和存储
- 使用 Modal 进行并行处理
- Modal 部署和 CI/CD
平台概览
Modal 是一个无服务器云平台,可用于运行 Python 代码,并针对 AI/ML 工作负载进行了优化,具有以下特点:
- 零配置:所有内容均通过 Python 代码定义
- GPU 快速启动:容器启动约需 1 秒
- 自动扩展:可缩减至零,也可扩展至数千个实例
- 按秒计费:仅需为活跃计算付费
- 多云:AWS、GCP、Oracle Cloud Infrastructure
核心组件参考
应用和函数
import modal
app = modal.App("app-name")
@app.function()
def basic_function(arg: str) -> str:
return f"Result: {arg}"
@app.local_entrypoint()
def main():
result = basic_function.remote("test")
print(result)
函数装饰器参数
| 参数 | 类型 | 描述 |
|---|---|---|
image | Image | 容器镜像配置 |
gpu | str/list | GPU 类型:”T4”、”A100”、[”H100”、”A100”] |
cpu | float | CPU 核心数(0.125 至 64) |
memory | int | 内存,单位为 MB(128 至 262144) |
timeout | int | 最大执行秒数 |
retries | int | 失败时的重试次数 |
secrets | list | 要注入的密钥 |
volumes | dict | 卷挂载点 |
schedule | Cron/Period | 定时执行 |
concurrency_limit | int | 最大并发执行数 |
container_idle_timeout | int | 保持容器预热的秒数 |
include_source | bool | 自动同步源代码 |
GPU 参考
可用 GPU
| GPU | 内存 | 用途 | 约费用/小时 |
|---|---|---|---|
| T4 | 16 GB | 小规模推理 | $0.59 |
| L4 | 24 GB | 中等规模推理 | $0.80 |
| A10G | 24 GB | 推理/微调 | $1.10 |
| L40S | 48 GB | 高负载推理 | $1.50 |
| A100-40GB | 40 GB | 训练 | $2.00 |
| A100-80GB | 80 GB | 大型模型 | $3.00 |
| H100 | 80 GB | 前沿应用 | $5.00 |
| H200 | 141 GB | 最大型模型 | $5.00 |
| B200 | 180+ GB | 最新一代 | $6.25 |
GPU 配置
# Single GPU
@app.function(gpu="A100")
# Specific memory variant
@app.function(gpu="A100-80GB")
# Multi-GPU
@app.function(gpu="H100:4")
# Fallbacks (tries in order)
@app.function(gpu=["H100", "A100", "any"])
# "any" = L4, A10G, or T4
@app.function(gpu="any")
镜像构建
基础镜像
# Debian slim (recommended)
modal.Image.debian_slim(python_version="3.11")
# From Dockerfile
modal.Image.from_dockerfile("./Dockerfile")
# From Docker registry
modal.Image.from_registry("nvidia/cuda:12.1.0-base-ubuntu22.04")
安装软件包
# pip (standard)
image.pip_install("torch", "transformers")
# uv (FASTER - 10-100x)
image.uv_pip_install("torch", "transformers")
# System packages
image.apt_install("ffmpeg", "libsm6")
# Shell commands
image.run_commands("apt-get update", "make install")
添加文件
# Single file
image.add_local_file("./config.json", "/app/config.json")
# Directory
image.add_local_dir("./models", "/app/models")
# Python source
image.add_local_python_source("my_module")
# Environment variables
image.env({"VAR": "value"})
构建时函数
def download_model():
from huggingface_hub import snapshot_download
snapshot_download("model-name")
image.run_function(download_model, secrets=[...])
存储
卷
# Create/reference volume
vol = modal.Volume.from_name("my-vol", create_if_missing=True)
# Mount in function
@app.function(volumes={"/data": vol})
def func():
# Read/write to /data
vol.commit() # Persist changes
密钥
# From dashboard (recommended)
modal.Secret.from_name("secret-name")
# From dictionary
modal.Secret.from_dict({"KEY": "value"})
# From local env
modal.Secret.from_local_environ(["KEY1", "KEY2"])
# From .env file
modal.Secret.from_dotenv()
# Usage
@app.function(secrets=[modal.Secret.from_name("api-keys")])
def func():
import os
key = os.environ["API_KEY"]
字典和队列
# Distributed dict
d = modal.Dict.from_name("cache", create_if_missing=True)
d["key"] = "value"
d.put("key", "value", ttl=3600)
# Distributed queue
q = modal.Queue.from_name("jobs", create_if_missing=True)
q.put("task")
item = q.get()
Web 端点
FastAPI 端点(简单)
@app.function()
@modal.fastapi_endpoint()
def hello(name: str = "World"):
return {"message": f"Hello, {name}!"}
ASGI 应用(完整 FastAPI)
from fastapi import FastAPI
web_app = FastAPI()
@web_app.post("/predict")
def predict(text: str):
return {"result": process(text)}
@app.function()
@modal.asgi_app()
def fastapi_app():
return web_app
WSGI 应用(Flask)
from flask import Flask
flask_app = Flask(__name__)
@app.function()
@modal.wsgi_app()
def flask_endpoint():
return flask_app
自定义 Web 服务器
@app.function()
@modal.web_server(port=8000)
def custom_server():
subprocess.run(["python", "-m", "http.server", "8000"])
自定义域名
@modal.asgi_app(custom_domains=["api.example.com"])
定时任务
Cron
# Daily at 8 AM UTC
@app.function(schedule=modal.Cron("0 8 * * *"))
# With timezone
@app.function(schedule=modal.Cron("0 6 * * *", timezone="America/New_York"))
Period
@app.function(schedule=modal.Period(hours=5))
@app.function(schedule=modal.Period(days=1))
**注意:**定时函数仅在使用 modal deploy 时运行,不会在使用 modal run 时运行。
并行处理
Map
# Parallel execution (up to 1000 concurrent)
results = list(func.map(items))
# Unordered (faster)
results = list(func.map(items, order_outputs=False))
Starmap
# Spread args
pairs = [(1, 2), (3, 4)]
results = list(add.starmap(pairs))
Spawn
# Async job (returns immediately)
call = func.spawn(data)
result = call.get() # Get result later
# Spawn many
calls = [func.spawn(item) for item in items]
results = [call.get() for call in calls]
容器生命周期(类)
@app.cls(gpu="A100", container_idle_timeout=300)
class Server:
@modal.enter()
def load(self):
self.model = load_model()
@modal.method()
def predict(self, text):
return self.model(text)
@modal.exit()
def cleanup(self):
del self.model
并发
@modal.concurrent(max_inputs=100, target_inputs=80)
@modal.method()
def batched(self, item):
pass
CLI 命令
开发
modal run app.py # Run function
modal serve app.py # Hot-reload dev server
modal shell app.py # Interactive shell
modal shell app.py --gpu A100 # Shell with GPU
部署
modal deploy app.py # Deploy
modal app list # List apps
modal app logs app-name # View logs
modal app stop app-name # Stop app
资源
# Volumes
modal volume create name
modal volume list
modal volume put name local remote
modal volume get name remote local
# Secrets
modal secret create name KEY=value
modal secret list
# Environments
modal environment create staging
定价(2025 年)
套餐
| 套餐 | 价格 | 容器数 | GPU 并发数 |
|---|---|---|---|
| Starter | 免费($30 额度) | 100 | 10 |
| Team | $250/月 | 1000 | 50 |
| Enterprise | 定制 | 无限制 | 定制 |
计算
- CPU:$0.0000131/核心/秒
- 内存:$0.00000222/GiB/秒
- GPU:请参阅上方的 GPU 表格
特别计划
- 初创企业:最高可获 $25k 额度
- 研究人员:最高可获 $10k 额度
最佳实践
- 使用
@modal.enter()加载模型 - 使用
uv_pip_install加快构建速度 - 使用 GPU 回退方案 确保可用性
- 设置合适的超时时间和重试次数
- 使用环境(开发/预发布/生产)
- 在构建期间下载模型,而非运行时
- 当顺序不重要时使用
order_outputs=False - 设置
container_idle_timeout,平衡成本与延迟 - 在 Modal 控制面板中监控成本
- 在执行
modal deploy前,先使用modal run进行测试
常见模式
LLM 推理
@app.cls(gpu="A100", container_idle_timeout=300)
class LLM:
@modal.enter()
def load(self):
from vllm import LLM
self.llm = LLM(model="...")
@modal.method()
def generate(self, prompt):
return self.llm.generate([prompt])
批处理
@app.function(volumes={"/data": vol})
def process(file):
# Process file
vol.commit()
# Parallel
results = list(process.map(files))
定时 ETL
@app.function(
schedule=modal.Cron("0 6 * * *"),
secrets=[modal.Secret.from_name("db")]
)
def daily_etl():
extract()
transform()
load()
快速参考
| 任务 | 代码 |
|---|---|
| 创建应用 | app = modal.App("name") |
| 基本函数 | @app.function() |
| 使用 GPU | @app.function(gpu="A100") |
| 使用镜像 | @app.function(image=img) |
| Web 端点 | @modal.asgi_app() |
| 定时执行 | schedule=modal.Cron("...") |
| 挂载卷 | volumes={"/path": vol} |
| 使用密钥 | secrets=[modal.Secret.from_name("x")] |
| 并行映射 | func.map(items) |
| 异步启动 | func.spawn(arg) |
| 类模式 | 使用 @app.cls() 和 @modal.enter() |
评论
支持 Markdown