1. Разделите программу, её параметры и коммерческое сопровождение
Код описывает поведение программы. Конфигурация определяет нагрузку: модель, данные, batch, точность и назначение. Секреты дают доступ к необходимым ресурсам. Держите эти элементы раздельно, чтобы менять попытку без переписывания кода и без копирования токена в общий файл.
Ссылка на команду Kernodeck позволяет найти контекст аренды в вашем аккаунте. Идентификатор попытки отличает запуски вашей программы в течение этого периода. Связывайте их в своих заметках, если это помогает, но не заставляйте скрипт выводить состояние вычисления из статуса оплаты.
Возьмём проект классификации документов, который нужно запускать несколько раз на одной и той же выборке. Контракт программы описывает входной файл, допустимые параметры, папку вывода и способ представления ошибок. Руководство по данным описывает проверку содержимого; здесь мы организуем интерфейс, связывающий эти этапы.
2. Напишите явный и версионированный контракт входных данных
Документируйте обязательные поля и допустимые значения. Избегайте молчаливых значений по умолчанию для решения, которое меняет результат, например модели или устройства. Номер схемы отличает форму конфигурации от версии кода; он её не заменяет.
В этом учебном примере JSON-файл содержит схему, путь к входным данным, batch и запрошенное устройство. Относительные пути читаются от папки конфигурации. Это правило, выбранное для примера, избавляет от зависимости от каталога, из которого коллега запускает команду.
Чтение корректного JSON проверяет только его синтаксис. Затем ваша программа должна проверить типы, поля и ограничения проекта. При ошибке она должна остановиться до загрузки дорогостоящего ресурса, с сообщением, называющим параметр, который нужно исправить.
{
"schema_version": 1,
"input": "../data/pilote.jsonl",
"batch_size": 4,
"device": "cuda"
}3. Подготовьте точку входа, которая отклоняет простые ошибки
argparse позволяет объявлять опции и формировать справку для вашей команды. Следующий пример представляет собой лишь предварительную проверку: он читает конфигурацию, проверяет её поля и обнаруживает уже используемую папку вывода. Он не загружает ни модель, ни данные в память и не проверяет доступность GPU.
Сохраните этот учебный код в prepare_run.py, если хотите его адаптировать. Он предлагается без подтверждённого запуска. Затем добавьте свои бизнес-проверки в приложение, вместо того чтобы считать итоговое сообщение результатом вычисления. Устройство cuda остаётся запросом; PyTorch использует это же имя и с ROCm.
Отказ при существующей папке вывода — это здесь соглашение о защите от смешивания попыток. Настоящая команда возобновления должна получать отдельную опцию и отдельные проверки. Не превращайте новый запуск в неявное возобновление только потому, что файлы уже присутствуют.
import argparse
import json
from pathlib import Path
parser = argparse.ArgumentParser(description="Проверка запуска проекта")
parser.add_argument("--config", type=Path, required=True)
parser.add_argument("--run-dir", type=Path, required=True)
args = parser.parse_args()
try:
config_path = args.config.resolve()
config = json.loads(config_path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
parser.error(f"Не удалось прочитать конфигурацию: {exc}")
expected = {"schema_version", "input", "batch_size", "device"}
if not isinstance(config, dict) or set(config) != expected:
parser.error("Ожидаемые поля: schema_version, input, batch_size, device")
if type(config["schema_version"]) is not int or config["schema_version"] != 1:
parser.error("schema_version должно быть равно 1")
if type(config["batch_size"]) is not int or config["batch_size"] < 1:
parser.error("batch_size должно быть положительным целым числом")
if config["device"] not in ("cpu", "cuda"):
parser.error("device должно быть равно cpu или cuda")
if not isinstance(config["input"], str) or not config["input"]:
parser.error("input должно быть непустым путём")
input_path = (config_path.parent / config["input"]).resolve()
run_dir = args.run_dir.resolve()
if not input_path.is_file():
parser.error("Входной файл отсутствует")
if run_dir.exists():
parser.error("Выберите новую папку для результатов")
print(json.dumps({
"status": "configuration_validated",
"input": str(input_path),
"run_dir": str(run_dir),
"device_requested": config["device"],
"batch_size": config["batch_size"]
}, ensure_ascii=False))python prepare_run.py --config config/pilote.json --run-dir runs/pilote-0014. Дайте идентичность запускам и их результатам
Свяжите каждый запуск с коротким идентификатором, уникальным в пределах вашей кампании. Зафиксируйте ревизию кода, схему и фактически использованные параметры, а затем ссылку на данные и модель. Сохраняйте эти значения вместе с результатами, чтобы результат не зависел от файла конфигурации, изменённого позже.
Чтобы сравнить два размера батча, создайте два запуска и две папки. Сохраните одну и ту же выборку и обозначьте намеренное различие. Имена pilote-001 и pilote-002 сами по себе не объясняют, что изменилось: манифест связывает имя с параметрами.
Выберите формат итогового отчёта, читаемый вашими инструментами. Он может различать полученные, успешно обработанные, отклонённые и оставшиеся элементы. Выберите правило полного успеха и не отмечайте запуск завершённым сразу после записи первого результата. Код возврата программы должен оставаться согласованным с этим выводом.
Прокрутите таблицу, чтобы увидеть все столбцы.| Файл или состояние | Роль | Ожидаемая проверка |
|---|---|---|
| manifest.json | Идентичность кода, данных и параметров | Фактически использованные значения, без секретов. |
| results.jsonl | Один результат на каждый принятый элемент | Известные идентификаторы и соответствующий формат. |
| errors.jsonl | Отклонённые элементы и полезная причина | Никаких незаметных пропаж и лишнего конфиденциального содержимого. |
| summary.json | Вывод запуска и счётчики | Согласованная сумма, файлы перечитаны перед финальным статусом. |
5. Публикуйте события, полезные вашим инструментам
Сделайте видимыми несколько переходов: конфигурация принята, данные доступны, модель загружена, первый результат записан и обработка завершена. Трассировка должна позволять ответить на вопрос «где сейчас этот запуск?», не переписывая документы или промпты. Связывайте этап и идентификатор запуска с сообщением.
Модуль logging в Python позволяет упорядочивать сообщения по уровню и назначению. Затем выберите собственную конвенцию событий и задокументируйте её. Приложение, которое записывает ошибку, а затем завершается успешно, делает автоматизацию обманчивой; и наоборот, не каждое предупреждение означает, что результат непригоден.
Не путайте отправленное событие и сохраняемый результат: сообщение «сохранение начато» не доказывает, что файл был перечитан. Для длительного выполнения специальное руководство объясняет связь между процессом и сессией. Ваш интерфейс должен прежде всего сохранять доступный вывод после завершения интерактивного соединения.
6. Определите сбой, возобновление и финальную проверку
Классифицируйте полезные сбои: неверная конфигурация, отсутствующий ресурс, ошибка вычислений и несоответствующий результат. Для каждого укажите следующее действие. Не устанавливайте автоматический перезапуск, не решив, какие эффекты можно повторять: перезапись уже принятого вывода и возобновление с контрольной точки требуют разных правил.
Ваша итоговая процедура объясняет, как запускать, наблюдать, останавливать, возобновлять и экспортировать. Для обработки документов сохраняйте список завершённых идентификаторов и тех, что нужно обработать повторно. Для обучения используйте протокол, который проверяет сохранённые состояния в новом процессе. Непустая папка не является доказательством корректного возобновления.
В завершение проверьте проект из нового вызова, с известной конфигурацией и отдельным местом назначения. Проверьте ожидаемые отказы, затем небольшой полный проход. Предварительная проверка на этой странице не охватывает ни конкурентный доступ, ни публичное раскрытие сервиса, ни права доступа к хранилищу: эти темы требуют собственного проектирования.