mcpField
M
modal

modal

github.com/kalarislabs其他7343 次安装4 天前更新
代码仓库

关于 modal

Modal 是以 Python 定义云端无服务器任务的平台,主要面向 AI 和机器学习工作负载。它提供按需 GPU、自动扩缩函数、持久存储、Web 端点和定时任务。

主要功能

  1. 01按需 GPU 计算
  2. 02自动扩缩无服务器函数
  3. 03用 Python 定义容器镜像
  4. 04持久化 Volumes
  5. 05Web 端点与定时任务
  6. 06隔离代码执行的 Sandboxes

适用场景

  1. 01部署模型推理 API
  2. 02运行 GPU 训练或微调
  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 是一个用于无服务器运行 Python 代码的云平台,专注于 AI/ML 工作负载。主要功能:

  • 按需 GPU 计算(T4、L4、A10、L40S、A100、H100、H200、B200)
  • 无服务器函数,可自动扩缩容,从零扩展到数千个容器
  • 自定义容器镜像,完全通过 Python 代码构建
  • 通过 Volumes 实现持久化存储,用于存放模型权重和数据集
  • 用于提供模型和 API 的Web 端点
  • 通过 cron 或固定间隔运行计划任务
  • 亚秒级冷启动,实现低延迟推理

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 专用变量是唯一相关的变量——不要读取、加载或泄露任何其他环境变量或 .env 文件内容:

  1. 检查当前环境中是否已设置 MODAL_TOKEN_ID 和 MODAL_TOKEN_SECRET。
  2. 如果没有,只在本地 .env 文件中查找这两个键(忽略所有其他条目),并在适合当前工作流的情况下加载它们。
  3. 只有当这两个值都无法从上述来源获取时,才回退到交互式 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。

核心概念

应用和函数

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() — 在构建期间运行 shell 命令
  • .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 推荐用于推理(成本与性能均衡,48 GB VRAM)
  • 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.with_options() / Function.with_concurrency() / Function.with_batching()(以及 Cls.with_options()),无需重新部署即可重新配置已部署的 Function 或 Cls:

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():
    ...

默认值:0.125 个 CPU 核心、128 MiB 内存。按 max(请求量、使用量)计费。

参考:有关限制和计费详情,请参阅 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 Agent 输出或代码解释器),请使用 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() 对文件系统进行快照,以便将其用作基础镜像
  • 非常适合代码解释器、Agent 工具执行和按用户隔离

常见工作流模式

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 或执行 shell 命令。请确保参数列表固定且硬编码。切勿使用未经净化的用户输入构造子进程或 shell 参数——应将不可信值作为数据传递(文件、环境变量、标准输入),而不是作为命令参数。
  • 不可信代码: 请在 modal.Sandbox 中运行用户或模型生成的代码(见上文),而不是在常规 Function 中运行,并使用 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 类和方法

如需了解本概览之外的详细信息,请阅读这些文件。

Agent 操作流程

  1. 检查环境。 确认 Python 环境和库版本(python -c "import pkg; print(pkg.__version__)"),并检查数据的形状、类型和缺失值。
  2. 明确输入。 根据数据或用户提供的信息确认格式、标识符和参数。凡是会改变结果的值,不要猜测,应先询问。
  3. 先运行小规模版本。 先在样本或单个折上运行,并检查运行时间和内存占用。
  4. 根据上述说明和参考资料执行完整任务。
  5. 验证结果。 使用留出数据、固定随机种子和适当的指标;检查是否存在数据泄漏;报告不确定性(置信区间、不同随机种子下的标准差)。
  6. 报告结果。 说明运行了什么(版本、命令、参数)、检查了什么,以及还有哪些不确定之处。
如果出现以下情况应执行的操作
内存不足或执行速度过慢对数据进行子采样、使用分块或惰性计算,或者缩小模型规模,并告知用户具体改动。
当前安装版本中缺少这些说明里提到的函数、标志或端点查看已安装版本自己的文档(help()、--help、官方文档),调整用法,并告知用户。切勿编造 API。
必需的输入、标识符或参数不明确询问用户,或在运行前明确说明所作的假设。

诚信规则

  • 切勿捏造结果、参数、标识符、引用或统计数据。如果某项内容无法运行或验证,请如实说明。
  • 切勿报告本次会话中未计算的指标;为每个数字展示生成它的代码路径。
  • 此处与版本相关的细节可能已过时:请根据已安装版本的官方文档进行确认。
  • 对于需要花费资金、占用共享 GPU 或云配额、涉及个人或患者数据,或无法撤销的操作,请先征求同意。

相关技能

  • modal-serverless-gpu:用于运行机器学习工作负载的无服务器 GPU 云平台。
  • tensorrt-llm:使用 NVIDIA TensorRT 优化大模型推理,以实现最高吞吐量和最低延迟。
  • serving-llms-vllm:使用 vLLM 的 PagedAttention 和连续批处理,以高吞吐量提供大模型服务。

评论

支持 Markdown