Modal
Modal
deepagents와 함께 Modal 샌드박스 백엔드를 사용하면 GPU 지원으로 격리된 코드 실행이 가능해요.
Modal은 GPU 지원을 갖춘 서버리스 컨테이너 인프라를 제공해요. ML/AI 워크로드와 Python 개발에 가장 적합합니다.
출처: 문서
본문
설정
npm install @langchain/modal
yarn add @langchain/modal
pnpm add @langchain/modal
인증
modal.com/settings/tokens에서 토큰을 받으세요.
export MODAL_TOKEN_ID=your_token_id
export MODAL_TOKEN_SECRET=your_token_secret
또는 자격 증명을 직접 전달하세요:
const sandbox = await ModalSandbox.create({
auth: {
tokenId: "your-token-id",
tokenSecret: "your-token-secret",
},
});
deepagents와 함께 사용하기
import { createDeepAgent } from "deepagents";
import { ChatAnthropic } from "@langchain/anthropic";
import { ModalSandbox } from "@langchain/modal";
const sandbox = await ModalSandbox.create({
imageName: "python:3.12-slim",
timeoutMs: 600_000, // 10 minutes
});
try {
const agent = createDeepAgent({
model: new ChatAnthropic({ model: "claude-sonnet-4-20250514" }),
systemPrompt: "You are a coding assistant with sandbox access.",
backend: sandbox,
});
const result = await agent.invoke({
messages: [{ role: "user", content: "Install numpy and calculate pi" }],
});
} finally {
await sandbox.close();
}
단독 사용(Standalone usage)
import { ModalSandbox } from "@langchain/modal";
const sandbox = await ModalSandbox.create({
imageName: "python:3.12-slim",
timeoutMs: 600_000,
});
const result = await sandbox.execute("python --version");
console.log(result.output);
await sandbox.close();
구성(Configuration)
| 옵션(Option) | 타입(Type) | 기본값(Default) | 설명(Description) |
|---|---|---|---|
imageName |
string |
"alpine:3.21" |
사용할 Docker 이미지 |
timeoutMs |
number |
300000 |
최대 수명(밀리초) |
workdir |
string |
- | 작업 디렉터리 |
gpu |
string |
- | GPU 타입("T4", "A100", "H100" 등) |
cpu |
number |
- | CPU 코어 수(소수 허용) |
memoryMiB |
number |
- | 메모리 할당량(MiB) |
volumes |
Record<string, string> |
- | 볼륨 이름 매핑(마운트 경로 → 볼륨 이름) |
secrets |
string[] |
- | 주입할 Modal Secret 이름 |
initialFiles |
Record<string, string | Uint8Array> |
- | 시작 시 생성할 파일 |
env |
Record<string, string> |
- | 환경 변수 |
blockNetwork |
boolean |
- | 네트워크 접근 차단 |
name |
string |
- | 샌드박스 이름(앱 내에서 고유) |
GPU 지원
Modal은 ML 워크로드를 위한 NVIDIA GPU를 지원합니다:
const sandbox = await ModalSandbox.create({
imageName: "python:3.12-slim",
gpu: "T4", // or "L4", "A10G", "A100", "H100"
});
볼륨과 시크릿(Volumes and secrets)
영속적 저장을 위해 Modal Volumes를 마운트하고 시크릿을 환경 변수로 주입하세요:
// Volumes and secrets must be created in Modal first
const sandbox = await ModalSandbox.create({
imageName: "python:3.12-slim",
volumes: {
"/data": "my-data-volume",
"/models": "my-models-volume",
},
secrets: ["my-api-keys", "database-credentials"],
});
// Files in /data and /models persist across sandbox restarts
await sandbox.execute("echo 'Hello' > /data/test.txt");
// Secrets are available as environment variables
await sandbox.execute("echo $API_KEY");
초기 파일(Initial files)
생성 중 샌드박스를 파일로 미리 채우세요:
const sandbox = await ModalSandbox.create({
imageName: "python:3.12-slim",
initialFiles: {
"/app/main.py": 'print("Hello from Python!")',
"/app/config.json": JSON.stringify({ name: "my-app" }, null, 2),
},
});
const result = await sandbox.execute("python /app/main.py");
Modal SDK 접근하기
BaseSandbox가 노출하지 않는 고급 기능을 위해 기본 Modal SDK에 접근하세요:
const modalSandbox = await ModalSandbox.create();
const client = modalSandbox.client; // ModalClient
const instance = modalSandbox.instance; // Sandbox
// Direct SDK operations
const process = await instance.exec(["python", "-c", "print('Hello')"], {
stdout: "pipe",
stderr: "pipe",
});
기존 샌드박스에 재연결하기
// Reconnect by ID
const reconnected = await ModalSandbox.fromId(sandboxId);
// Reconnect by name
const reconnected2 = await ModalSandbox.fromName("my-app", "my-sandbox");
팩토리 함수(Factory functions)
import { createModalSandboxFactory, createModalSandboxFactoryFromSandbox } from "@langchain/modal";
// Create new sandbox per invocation
const factory = createModalSandboxFactory({ imageName: "python:3.12-slim" });
// Or reuse an existing sandbox across invocations
const sandbox = await ModalSandbox.create();
const reuseFactory = createModalSandboxFactoryFromSandbox(sandbox);
오류 처리(Error handling)
import { ModalSandboxError } from "@langchain/modal";
try {
await sandbox.execute("some command");
} catch (error) {
if (error instanceof ModalSandboxError) {
switch (error.code) {
case "NOT_INITIALIZED":
await sandbox.initialize();
break;
case "COMMAND_TIMEOUT":
console.error("Command took too long");
break;
case "AUTHENTICATION_FAILED":
console.error("Check your Modal token credentials");
break;
}
}
}
오류 코드(Error codes)
| 코드(Code) | 설명(Description) |
|---|---|
NOT_INITIALIZED |
샌드박스가 초기화되지 않음 - initialize() 호출 |
ALREADY_INITIALIZED |
두 번 초기화할 수 없음 |
AUTHENTICATION_FAILED |
유효하지 않거나 누락된 Modal 토큰 |
SANDBOX_CREATION_FAILED |
샌드박스 생성 실패 |
SANDBOX_NOT_FOUND |
샌드박스 ID/이름을 찾을 수 없거나 만료됨 |
COMMAND_TIMEOUT |
명령 실행 타임아웃 |
COMMAND_FAILED |
명령 실행 실패 |
FILE_OPERATION_FAILED |
파일 읽기/쓰기 실패 |
RESOURCE_LIMIT_EXCEEDED |
CPU, 메모리, 스토리지 제한 초과 |
VOLUME_ERROR |
볼륨 작업 실패 |
환경 변수(Environment variables)
| 변수(Variable) | 설명(Description) |
|---|---|
MODAL_TOKEN_ID |
Modal API 토큰 ID |
MODAL_TOKEN_SECRET |
Modal API 토큰 시크릿 |
더 알아보기 (Learn more)
- 이 문서를 MCP로 연결하면 Claude, VSCode 등에서 실시간 답변을 받을 수 있어요.
- GitHub에서 이 페이지 편집하기 또는 이슈 제출하기.