SandboxesЗапуск Python

API интерпретатора кода для кода, который пишет LLM

Интерпретатор кода запускает код, который пишет языковая модель, и возвращает ей результат. В Lizard (lizard.build) это делает CodeSandbox из Lizard SDK внутри sandbox на базе microVM Firecracker. Поэтому код выполняется отдельно от вашего приложения и компьютера. CodeSandbox запускает шаблон interpreter с Python и основными библиотеками для работы с данными. Python работает в ядре Jupyter, которое сохраняет переменные между вызовами, а каждый результат содержит напечатанный вывод, значение последнего выражения, графики в формате image/png и ошибку с трассировкой, если она возникла.

Запуск кода с сохранением состояния

import { CodeSandbox } from '@lizard-build/sdk';
 
const sandbox = await CodeSandbox.create({ projectId: 'proj_123', timeoutMs: 300_000 });
try {
  await sandbox.runCode('import pandas as pd\ndf = pd.DataFrame({"x": [1, 2, 3]})');
  const run = await sandbox.runCode('df.x.sum()');
  console.log(run.results[0]?.data); // "6"
  const bad = await sandbox.runCode('1/0');
  console.log(bad.error?.name); // "ZeroDivisionError"
} finally {
  await sandbox.kill();
}
from lizard import CodeSandbox
 
with CodeSandbox.create(project_id="proj_123", timeout_ms=300_000) as sandbox:
    sandbox.run_code('import pandas as pd\ndf = pd.DataFrame({"x": [1, 2, 3]})')
    run = sandbox.run_code("df.x.sum()")
    print(run.results[0].data)  # "6"
    print(sandbox.run_code("1/0").error.name)  # "ZeroDivisionError"

Ошибка в коде возвращается в результате, а не вызывает исключение в SDK. Сбои запроса, например неверный API-ключ, выбрасывают исключение.

Что возвращает runCode?

runCode (в Python: run_code) возвращает Execution:

ПолеСодержимое
stdout, stderrВсё, что напечатал код
resultsРасширенный вывод: значение последнего выражения как text/plain, графики matplotlib и изображения как base64 image/png, HTML и другие типы, каждый с mime и data
errorname, message и traceback, если код выбросил исключение
executionCountСчётчик ячеек ядра (в Python: execution_count)

Передайте onStdout, onStderr, onResult или onError (в Python: on_stdout и т. д.), чтобы получать вывод, пока код выполняется.

Использование как инструмента LLM

Дайте модели один инструмент, например run_python с единственным строковым аргументом code. Когда модель вызывает его, выполните код в sandbox и отправьте текст обратно как результат инструмента. Держите один sandbox на весь диалог, чтобы переменные модели сохранялись между вызовами.

import { CodeSandbox } from '@lizard-build/sdk';
 
const sandbox = await CodeSandbox.create({ projectId: 'proj_123', timeoutMs: 600_000 });
 
// Call this when the model asks to run Python. Return the text to send back to it.
async function runPython(code: string): Promise<string> {
  const run = await sandbox.runCode(code, { timeoutMs: 30_000 });
  if (run.error) return `${run.error.name}: ${run.error.message}\n${run.error.traceback}`;
  const values = run.results.flatMap((r) =>
    r.type === 'result' && r.mime === 'text/plain' ? [r.data] : [],
  );
  return [run.stdout, ...values].filter(Boolean).join('\n');
}
 
// When the conversation ends:
await sandbox.kill();
from lizard import CodeSandbox
 
sandbox = CodeSandbox.create(project_id="proj_123", timeout_ms=600_000)
 
def run_python(code: str) -> str:
    """Call this when the model asks to run Python. Return the text to send back to it."""
    run = sandbox.run_code(code, timeout_ms=30_000)
    if run.error:
        return f"{run.error.name}: {run.error.message}\n{run.error.traceback}"
    values = [r.data for r in run.results if r.mime == "text/plain"]
    return "\n".join(filter(None, [run.stdout, *values]))
 
# When the conversation ends:
sandbox.kill()

В этом примере sandbox работает десять минут. Для более длинных диалогов увеличьте срок через setTimeout (в Python: set_timeout) или задайте timeoutMs: 0 и останавливайте sandbox сами.

Графики

Когда код рисует график matplotlib, в results появляется элемент с mime, равным image/png, и изображением в base64 в data:

import base64
from pathlib import Path
 
run = sandbox.run_code("import matplotlib.pyplot as plt\nplt.plot([1, 4, 9])\nplt.show()")
png = next(r.data for r in run.results if r.mime == "image/png")
Path("chart.png").write_bytes(base64.b64decode(png))

Контексты, таймауты и языки

  • Контексты. createContext() (в Python: create_context()) запускает отдельное ядро со своими переменными и рабочей папкой; передайте его как context в runCode. listContexts(), restartContext(ctx) и deleteContext(ctx) управляют контекстами. Без контекста каждый язык использует свой контекст по умолчанию.
  • Таймауты. timeoutMs (в Python: timeout_ms) ограничивает один вызов, по умолчанию 60 секунд. Ядро Python, которое работает дольше, прерывается и сохраняет состояние; error.name в результате равно TimeoutError.
  • Другие языки. JavaScript и bash выполняются как новый процесс при каждом вызове, поэтому состояние не сохраняется, а results остаётся пустым. Для JavaScript нужен node, которого нет в шаблоне interpreter.
  • Пауза и снимки. Ядра работают внутри sandbox, поэтому pause() и resume() сохраняют их переменные, а snapshot() и fork() их копируют.

Запуск команд

process.exec создаёт отдельный процесс для каждой команды, поэтому переменные Python между вызовами не сохраняются. Используйте его для команд оболочки, например pip install, а результаты, которые понадобятся позже, сохраняйте в файлы. См. запуск команды и справочник SDK.

Недоверенный код

Считайте недоверенным всё, что пишет модель. Не передавайте lizardToken, если коду не нужен Lizard CLI; этот ключ может прочитать всё, что работает в sandbox, поэтому в таком случае используйте ключ с доступом только к рабочему пространству. Не кладите другие секреты в envs. Sandbox с томом на базе pod использует ядро хоста; см. runtime и шаблоны.

Хранение и оплата

Переменные и файлы доступны, только пока работает sandbox. Правила оплаты и хранения смотрите в разделе хранение и оплата; размеры и цены смотрите в лимитах.

Обзор Sandboxes · Быстрый старт · Справочник SDK · Persistent Volumes · Страница продукта Sandboxes

Обновлено