← Sandbox SDK / sandbox / tutorials
Анализ данных с помощью ИИ
Создание системы анализа данных на базе ИИ, которая принимает файлы CSV, использует Claude для генерации кода анализа на Python, выполняет его в песочницах и возвращает визуализации.
Время выполнения: 25 минут
Предварительные требования
- Зарегистрируйтесь для получения Аккаунт Cloudflare ↗.
- Установка
Node.js↗.
менеджер версий Node.js
Используйте менеджер версий Node, например Volta ↗ или nvm ↗ чтобы избежать проблем с правами доступа и переключать версии Node.js. Wrangler, о котором пойдёт речь далее в этом руководстве, требует версию Node 16.17.0 или более поздней версии.
Также потребуется:
- Одна Ключ API Anthropic ↗ для Claude
- Docker ↗ локальный запуск
1. Создайте проект
Создайте новый проект Sandbox SDK:
npm create cloudflare@latest -- analyze-data --template=cloudflare/sandbox-sdk/examples/minimalcd analyze-data2. Установите зависимости
npm i @anthropic-ai/sdk3. Постройте обработчик анализа
Замените src/index.ts:
import { getSandbox, proxyToSandbox, type Sandbox } from "@cloudflare/sandbox";
import Anthropic from "@anthropic-ai/sdk";
export { Sandbox } from "@cloudflare/sandbox";
interface Env {
Sandbox: DurableObjectNamespace<Sandbox>;
ANTHROPIC_API_KEY: string;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const proxyResponse = await proxyToSandbox(request, env);
if (proxyResponse) return proxyResponse;
if (request.method !== "POST") {
return Response.json(
{ error: "POST CSV file and question" },
{ status: 405 },
);
}
try {
const formData = await request.formData();
const csvFile = formData.get("file") as File;
const question = formData.get("question") as string;
if (!csvFile || !question) {
return Response.json(
{ error: "Missing file or question" },
{ status: 400 },
);
}
// Upload CSV to sandbox
const sandbox = getSandbox(env.Sandbox, `analysis-${Date.now()}`);
const csvPath = "/workspace/data.csv";
await sandbox.writeFile(csvPath, await csvFile.text());
// Analyze CSV structure
const structure = await sandbox.exec(
`python3 -c "import pandas as pd; df = pd.read_csv('${csvPath}'); print(f'Rows: {len(df)}'); print(f'Columns: {list(df.columns)[:5]}')"`,
);
if (!structure.success) {
return Response.json(
{ error: "Failed to read CSV", details: structure.stderr },
{ status: 400 },
);
}
// Generate analysis code with Claude
const code = await generateAnalysisCode(
env.ANTHROPIC_API_KEY,
csvPath,
question,
structure.stdout,
);
// Write and execute the analysis code
await sandbox.writeFile("/workspace/analyze.py", code);
const result = await sandbox.exec("python /workspace/analyze.py");
if (!result.success) {
return Response.json(
{ error: "Analysis failed", details: result.stderr },
{ status: 500 },
);
}
async function streamToBase64(stream) {
const blob = await new Response(stream).blob();
const buffer = await blob.arrayBuffer();
const bytes = new Uint8Array(buffer);
// Convert to base64
let binary = '';
for (let i = 0; i < bytes.length; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
// Check for generated chart
let chart = null;
try {
const { content, mimeType } = await sandbox.readFile("/workspace/chart.png", {
encoding: "none"
});
chart = `data:${mimeType};base64,${await streamToBase64(content)}`;
} catch {
// No chart generated
}
await sandbox.destroy();
return Response.json({
success: true,
output: result.stdout,
chart,
code,
});
} catch (error: any) {
return Response.json({ error: error.message }, { status: 500 });
}
},
};
async function generateAnalysisCode(
apiKey: string,
csvPath: string,
question: string,
csvStructure: string,
): Promise<string> {
const anthropic = new Anthropic({ apiKey });
const response = await anthropic.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 2048,
messages: [
{
role: "user",
content: `CSV at ${csvPath}:
${csvStructure}
Question: "${question}"
Generate Python code that:
- Reads CSV with pandas
- Answers the question
- Saves charts to /workspace/chart.png if helpful
- Prints findings to stdout
Use pandas, numpy, matplotlib.`,
},
],
tools: [
{
name: "generate_python_code",
description: "Generate Python code for data analysis",
input_schema: {
type: "object",
properties: {
code: { type: "string", description: "Complete Python code" },
},
required: ["code"],
},
},
],
});
for (const block of response.content) {
if (block.type === "tool_use" && block.name === "generate_python_code") {
return (block.input as { code: string }).code;
}
}
throw new Error("Failed to generate code");
}4. Настройте локальные переменные окружения
Создайте .dev.vars файл в корне вашего проекта для локальной разработки:
echo "ANTHROPIC_API_KEY=your_api_key_here\nSANDBOX_TRANSPORT=rpc" > .dev.varsЗамените your_api_key_here на ваш действующий API-ключ из Anthropic Console ↗.
SANDBOX_TRANSPORT требуется для использования новых API потоковой передачи файлов.
5. Протестируйте локально
Скачайте пример CSV:
# Create a test CSV
echo "year,rating,title
2020,8.5,Movie A
2021,7.2,Movie B
2022,9.1,Movie C" > test.csvЗапустите dev-сервер:
npm run devТестирование с помощью curl:
curl -X POST http://localhost:8787 \
-F "[email protected]" \
-F "question=What is the average rating by year?"Ответ:
{
"success": true,
"output": "Average ratings by year:\n2020: 8.5\n2021: 7.2\n2022: 9.1",
"chart": "data:image/png;base64,...",
"code": "import pandas as pd\nimport matplotlib.pyplot as plt\n..."
}6. Разверните
Разверните ваш Worker:
npx wrangler deployЗатем задайте ключ API Anthropic в качестве секрета для продакшена:
npx wrangler secret put ANTHROPIC_API_KEYВставьте свой API-ключ из Anthropic Console ↗ при появлении запроса.
Что вы создали
Система анализа данных на основе ИИ, которая:
- Загружает файлы CSV в песочницы
- Использует вызов инструментов Claude для генерации кода анализа
- Выполняет код на Python с pandas и matplotlib
- Возвращает текстовый вывод и визуализации
Следующие шаги
- Code Interpreter API - Используйте встроенный интерпретатор кода
- Файловые операции - Расширенная работа с файлами
- Потоковый вывод - Обновления прогресса в реальном времени