Как вы версионируете агента целиком (prompts, tools, memory schema, orchestration graph)?
Краткий тезис
Версионирование агента — это задача управления конфигурацией и артефактами, выходящая за рамки обычного Git. Агент состоит из кода, промптов, инструментов (tools), схем памяти (memory schema) и графа оркестрации (orchestration graph). Для каждого компонента нужен свой подход: Git для кода и текстовых промптов, DVC (control|versioning|control|control|versioning|Data control|Version Control) для бинарных/больших схем памяти, JSON/YAML для графа. Интегральный хеш (hash(код + промпты + схема + граф)) позволяет однозначно идентифицировать версию агента, а теги в CI обеспечивают воспроизводимость и откат.
1. Зачем версионировать агента целиком?
Агент — это не просто код. Его поведение определяется совокупностью:
- Prompts — текстовые инструкции для LLM (системные, user, few-shot).
- Tools — функции или API, которые агент может вызывать (их сигнатуры, реализации, версии).
- Memory schema — структура долговременной памяти (например, граф знаний, векторный индекс, SQL-схема).
- Orchestration graph — логика переходов между состояниями (DAG, конечный автомат, граф вызовов).
Без версионирования невозможно:
- воспроизвести поведение агента в проде;
- откатиться к стабильной версии после неудачного обновления;
- проводить A/B-тесты разных конфигураций;
- отслеживать, какая версия привела к ошибке.
2. Компоненты и их природа
| Компонент | Формат | Размер | Частота изменений | Инструмент |
|---|---|---|---|---|
| Код (логика агента) | .py, .js | малый | высокая | Git |
| Prompts | .txt, .yaml, .json | малый | средняя | Git |
| Tools (реализация) | .py, .js | малый | высокая | Git |
| Tools (конфигурация) | .yaml, .json | малый | средняя | Git |
| Memory schema | .sql, .json, .pkl | от малого до большого | низкая | DVC / Git LFS |
| Orchestration graph | .json, .yaml, .dot | малый | средняя | Git |
Важно Prompts и граф часто хранят в том же репозитории, что и код, но выделяют в отдельные директории для удобства диффа.
3. Подходы к версионированию каждого компонента
3.1 Код и промпты — Git
Код агента и текстовые промпты — это обычные файлы. Git отлично справляется с их версионированием. Рекомендуется:
- Хранить промпты в папке
prompts/с именами, отражающими назначение (например,system_prompt_v2.txt). - Использовать semantic versioning для тегов (например,
v1.2.3). - Для промптов можно вести changelog в комментариях или отдельном файле.
3.2 Tools — Git + контракты
Инструменты — это функции с чёткой сигнатурой. Версионирование их интерфейсов критично, так как изменение сигнатуры ломает граф. Подход:
- Определять контракты инструментов в отдельном файле (например, tools_schema.yaml).
- Версионировать этот файл вместе с кодом.
- При изменении контракта — мажорная версия агента.
3.3 Memory schema — DVC или Git LFS
Схема памяти может быть большой (векторный индекс, граф знаний). Git неэффективен для бинарных файлов. Используем DVC (Data Version Control):
- Храним схему в
memory/и отслеживаем через dvc add. - DVC создаёт метафайл .dvc, который коммитится в Git.
- Сами данные хранятся в удалённом хранилище (S3, GCS).
- При переключении ветки Git + dvc checkout восстанавливают нужную версию схемы.
Альтернатива — Git LFS (Large File Storage), но DVC даёт больше контроля над версиями и интеграцию с ML-пайплайнами.
3.4 Orchestration graph — JSON/YAML в Git
Граф оркестрации — это описание переходов между состояниями агента. Обычно это небольшой JSON или YAML. Храним в Git, но важно:
- Валидировать граф на соответствие схеме (например, JSON Schema).
- При изменении графа увеличивать минорную версию агента.
- Можно генерировать граф из кода (например, с помощью декораторов) и коммитить сгенерированный файл.
4. Интегральный хеш агента
Чтобы однозначно идентифицировать версию агента, вычисляем хеш от всех компонентов:
import hashlib
import json
import os
def compute_agent_hash(code_dir, prompts_dir, memory_schema_path, graph_path):
hasher = hashlib.sha256()
# Код
for root, _, files in os.walk(code_dir):
for f in sorted(files):
if f.endswith('.py'):
with open(os.path.join(root, f), 'rb') as fh:
hasher.update(fh.read())
# Промпты
for f in sorted(os.listdir(prompts_dir)):
with open(os.path.join(prompts_dir, f), 'rb') as fh:
hasher.update(fh.read())
# Memory schema (если текстовый — читаем, если бинарный — хеш от DVC-метафайла)
with open(memory_schema_path, 'rb') as fh:
hasher.update(fh.read())
# Граф
with open(graph_path, 'rb') as fh:
hasher.update(fh.read())
return hasher.hexdigest()
Этот хеш можно:
- Использовать как тег Docker-образа агента.
- Записывать в метаданные каждого запуска (MLflow, Weights & Biases).
- Сравнивать при деплое: если хеш не изменился — не перезапускать.
5. CI/CD и тегирование
В пайплайне CI (например, GitHub Actions) после сборки:
- Вычислить интегральный хеш.
- Создать Git-тег вида
agent-v1.2.3-<хеш>. - Запушить тег в репозиторий.
- Собрать Docker-образ с тегом
agent:<хеш>. - Задеплоить образ в staging/production.
Пример шага в CI:
- name: Compute agent hash
run: |
HASH=$(python compute_hash.py)
echo "HASH=$HASH" >> $GITHUB_ENV
- name: Create git tag
run: |
git tag "agent-v1.2.3-${{ env.HASH }}"
git push origin "agent-v1.2.3-${{ env.HASH }}"
6. Практические рекомендации
- Храните всё в одном репозитории (monorepo) для простоты связывания версий.
- Используйте .gitignore для исключения сгенерированных файлов (кроме графа, если он генерируется).
- Для memory schema используйте DVC с удалённым хранилищем, а в репозитории храните только
.dvc-файлы. - Версионируйте промпты отдельно от кода, чтобы можно было быстро менять поведение без пересборки.
- Документируйте изменения в CHANGELOG.md с указанием, какие компоненты затронуты.
7. Сравнение инструментов
| Инструмент | Для чего | Плюсы | Минусы |
|---|---|---|---|
| Git | Код, промпты, граф | Простота, дифф, ветки | Не подходит для больших файлов |
| DVC | Memory schema, большие артефакты | Версионирование данных, интеграция с Git | Дополнительный инструмент, требует настройки хранилища |
| Git LFS | Большие бинарные файлы | Прозрачная интеграция с Git | Ограничения по трафику на GitHub |
| MLflow | Метаданные, параметры, хеши | Хранение артефактов, эксперименты | Не заменяет Git для кода |
| Docker | Образ агента | Воспроизводимость, изоляция | Не версионирует отдельные компоненты |
8. Пример структуры репозитория
agent-repo/
├── agent/ # Код агента
│ ├── core.py
│ ├── tools/
│ ├── memory/
│ └── graph.py
├── prompts/ # Промпты
│ ├── system_v2.txt
│ └── user_template.txt
├── memory_schema/ # DVC-отслеживаемая папка
│ ├── vector_index.dvc
│ └── knowledge_graph.dvc
├── graph/ # Граф оркестрации
│ └── orchestration.json
├── compute_hash.py # Скрипт для интегрального хеша
├── .dvc/config
└── README.md
Пет-проект для закрепления
Задача Создать простого агента-помощника с двумя инструментами (поиск в википедии и калькулятор), версионировать его с помощью Git + DVC.
Инструменты Python, LangGraph (или простой конечный автомат), DVC, Git.
Шаги:
- Создать репозиторий, написать код агента (класс с методами
run,step). - Определить промпты в
prompts/(системный промпт, промпт для выбора инструмента). - Реализовать два инструмента как функции с декоратором
@tool. - Описать граф оркестрации в
graph/orchestration.json(состояния:start,tool_call,respond). - Создать схему памяти (простой JSON-файл с историей диалогов) и отследить через
dvc add. - Написать скрипт
compute_hash.py, который считает интегральный хеш. - Настроить GitHub Actions: при пуше в main вычислять хеш, создавать тег, собирать Docker-образ.
- Проверить, что при изменении промпта хеш меняется, а при изменении только комментария в коде — тоже.
Ожидаемый результат Репозиторий с полной историей версий агента, возможностью откатиться к любой версии через git checkout <tag> + dvc checkout, и Docker-образ с тегом-хешем.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 395 | Как спроектировать архитектуру агента? |
| 396 | Как управлять инструментами агента? |
| 397 | Как тестировать агента? |
| 399 | Как деплоить агента в production? |
| 400 | Как мониторить поведение агента? |
| 394 | Что такое Agentic RAG и чем отличается от обычного RAG? |
Навигация
- Предыдущий: 397
- Следующий: 399
- Индекс: 00. Индекс разборов