中文翻译暂不可用,显示俄语原文。
Как управлять dependency между промптами (один промпт вызывает другой)?
Краткий тезис
Управление зависимостями промптов — это ключевой элемент архитектуры Agentic RAG, где один промпт может вызывать другой как под-агент или использовать его содержимое на этапе компиляции. Систематический подход включает явное описание зависимостей (типа include и call), версионирование промптов, построение DAG зависимостей с проверкой на циклы и использование Prompt Registry с автоматическим отслеживанием изменений. Без этого каскадные изменения в одном промпте могут незаметно сломать поведение всей системы агентов.
1. Термин: dependency (зависимость) между промптами
Dependency (зависимость) возникает, когда выход одного промпта (шаблона или инструкции для LLM) используется как вход для другого, или когда один промпт динамически вызывает другой в процессе выполнения. В RAG|Agentic RAG агенты часто состоят из нескольких шагов, каждый из которых управляется отдельным промптом.
Почему это важно
- Одиночный промпт редко решает сложную задачу — нужна композиция.
- Изменение в родительском промпте может повлиять на все дочерние.
- Необходимо обеспечить целостность и повторяемость поведения системы.
Термин «Промпт» — это шаблон инструкции для LLM, который может содержать переменные, примеры (few-shot) и ссылки на другие промпты.
2. Типы зависимостей: include vs call
Черновик выделяет два основных типа:
2.1 include: — статическая вставка (compile time)
include: — механизм, при котором содержимое одного промпта подставляется в другой на этапе компиляции шаблона. Это похоже на импорт модулей в коде.
Пример синтаксиса (Prompt Template):
# main_prompt.j2
Ты — аналитик документов.
Ответь на вопрос на основе следующего контекста:
{% include 'context_prompt.j2' %}
Характеристики
- Зависимость разрешается до запуска (статическая).
- Изменение вложенного промпта автоматически меняет результат главного.
- Нет дополнительных вызовов LLM — всё уже в одном контексте.
- Удобно для общих частей (стили, системные инструкции, списки правил).
2.2 call: — динамический вызов (runtime)
call: — механизм, при котором один промпт (агент) во время исполнения решает вызвать другой промпт как под-агента и передаёт ему управление. Это уже агентный паттерн.
Пример (псевдокод агента):
if need_more_info:
response = call_prompt("search_agent_prompt", query=user_query)
# используем response в текущем промпте
Характеристики
- Зависимость разрешается динамически, в зависимости от промежуточного выхода LLM.
- Вызов может быть последовательным или условным.
- Требует фреймворка для агентов (LangChain, Semantic Kernel, AutoGen).
- Изменение вызываемого промпта может изменить логику ветвления вызывающего.
| Характеристика | include: (compile time) | call: (runtime) |
|---|---|---|
| Момент разрешения | До запуска | Во время выполнения |
| Вызов LLM | Нет (подстановка текста) | Да (отдельный вызов) |
| Влияние изменений | Прямое (всегда подставляется новая версия) | Косвенное (зависит от логики вызова) |
| Контроль версий | Проще (достаточно тестировать итоговый промпт) | Сложнее (нужно тестировать цепочки) |
Термин «Compile time» — этап сборки шаблона промпта, когда все include раскрываются. «Runtime» — момент фактического выполнения промпта LLM.
3. Версионирование промптов и каскадные изменения
Если промпт B изменился, нужно протестировать промпт A, который его вызывает или включает. Это каскадное тестирование.
Пример проблемы
- Промпт
summarizer(версия 1.2) содержал инструкцию: «Суммируй не более 50 слов». - Промпт
report_generatorиспользует include: summarizer и ожидает краткие саммари. - После обновления
summarizer(версия 1.3) инструкция стала «Дай полный пересказ». report_generatorсломается — ответ станет слишком длинным.
Решение
- Использовать семантическое версионирование (semver) промптов:
X.Y.Z— мажорное изменение (ломает совместимость) → обязательно тестировать всех потребителей. - Хранить манифест зависимостей для каждого промпта (какие промпты он включает/вызывает с диапазонами версий).
- Автоматизировать regression-тестирование при изменении любого промпта в графе.
Термин «Семантическое версионирование» — система нумерации, где изменение мажорной версии (X) означает обратно несовместимые изменения, минорной (Y) — добавление функциональности с обратной совместимостью, патч (Z) — исправления багов.
4. DAG зависимостей и проверка на циклы
DAG (Directed Acyclic Graph) — направленный ациклический граф, в котором вершины — промпты, а рёбра — зависимости (include или call).
Почему ацикличность
- Циклическая зависимость (
A -> B -> A) приведёт к бесконечной рекурсии (для call) или конфликту включений (для include).
Пример проверки на циклы (топологическая сортировка):
# Упрощённый код проверки DAG на циклы с помощью DFS
def has_cycle(graph, node, visited, rec_stack):
visited.add(node)
rec_stack.add(node)
for neighbor in graph.get(node, []):
if neighbor not in visited:
if has_cycle(graph, neighbor, visited, rec_stack):
return True
elif neighbor in rec_stack:
return True
rec_stack.discard(node)
return False
graph = {
'A': ['B'],
'B': ['C'],
'C': ['A'] # цикл!
}
visited = set()
print(has_cycle(graph, 'A', visited, set())) # True
Рекомендации
- При добавлении или изменении зависимости проверять, не образуется ли цикл.
- Использовать готовые библиотеки (NetworkX) для построения и валидации DAG.
- Для call допускается цикл с условием остановки (например, max_depth), но это усложняет отладку.
Термин «Топологическая сортировка» — упорядочивание вершин DAG так, чтобы все рёбра шли от более ранних к более поздним. Если сортировка невозможна → есть цикл.
5. Инструменты: Prompt Registry с dependency tracking
Prompt Registry (реестр промптов) — централизованный сервис (или модуль), который хранит версии промптов, их зависимости и метаданные.
Ключевые функции
- Хранение шаблонов и их версий (в базе данных или Git-репозитории).
- Отслеживание зависимостей: для каждого промпта список include и call с указанием диапазона версий.
- Автоматическое оповещение при изменении зависимого промпта (например, через CI/CD пайплайн).
- Предотвращение несовместимых обновлений (blocker при попытке обновить промпт, если какая-то зависимость нарушена).
Пример структуры записи в реестре
{
"prompt_id": "summarizer",
"version": "1.2.0",
"content": "Суммируй документ не более 50 слов.",
"dependencies": {
"include": [],
"call": []
}
}
{
"prompt_id": "report_generator",
"version": "2.0.0",
"dependencies": {
"include": ["summarizer@^1.0.0"],
"call": ["search_agent@>=1.0 <2.0"]
}
}
Термин «^1.0.0» — диапазон версий (семантическое версионирование): ^ означает «мажорная версия 1, любой минор и патч».
Популярные реализации: Prompt Flow (Microsoft), W&B Prompt Registry, LangChain Hub, Dify Prompt Management.
6. Тестирование зависимостей: тесты на интеграцию и регрессию
Для управления dependency недостаточно просто хранить граф — нужно автоматически проверять, что изменения не сломали систему.
Типы тестов
| Тип теста | Что проверяет | Когда запускать |
|---|---|---|
| Unit-тест промпта | Формат вывода, наличие переменных, отсутствие синтаксических ошибок | При каждом изменении промпта |
| Интеграционный тест | Цепочка A -> B -> C: конечный ответ корректен | При изменении любого промпта в цепочке |
| Тест на регрессию | Старые сценарии (golden датасет) не сломались | Периодически / перед релизом |
| Тест на циклы | DAG остаётся ацикличным | При изменении зависимостей (CI/CD) |
Пример интеграционного теста (Python + pytest):
def test_report_generation():
# Arrange: загружаем промпты из реестра
registry = PromptRegistry()
report_prompt = registry.get("report_generator", version="2.0.0")
# Act: генерируем ответ с помощью агента
agent = Agent(prompt=report_prompt)
result = agent.run(input="Какой курс доллара?")
# Assert: проверяем ключевые аспекты
assert len(result) > 0
assert "доллар" in result.lower()
Термин «Golden датасет» — набор входных данных и эталонных ответов, используемый для регрессионного тестирования промптов.
7. Управление зависимостями в lifecycle агента
Рассмотрим жизненный цикл промпта-агента в конвейере:
- Разработка — создание нового промпта с явными зависимостями (include/call).
- Версионирование — фиксация версии и зависимостей в реестре.
- Тестирование — прогон unit-тестов и интеграционных тестов для всей группы зависимых промптов.
- Развёртывание — деплой новой версии промпта только если все зависимости удовлетворены и тесты пройдены.
- Мониторинг — отслеживание метрик (доля отказов, время ответа) для обнаружения регрессий.
Рекомендация хранить зависимости в коде (YAML/JSON рядом с промптами) и автоматически проверять их через CI.
8. Расширенный пример: Agentic RAG с dependency management
Представим систему вопросно-ответного агента, где:
- Router prompt решает, какой под-агент вызвать (search или summarise).
- Search prompt вызывает Rewrite prompt для переформулировки запроса.
- Summarise prompt включает Format prompt для единого стиля.
# router_prompt v1.0
Ты — маршрутизатор. Если вопрос фактографический — вызови search_agent_prompt,
иначе — summarise_agent_prompt.
Вызываемые промпты: {call: [search_agent_prompt^1.0, summarise_agent_prompt^1.0]}
# search_agent_prompt v1.0
Сначала перепиши запрос, вызвав rewrite_prompt.
Затем выполни поиск по документам.
Зависимости: {call: [rewrite_prompt^1.0]}
# rewrite_prompt v1.0
Перепиши запрос в формате для поиска.
Зависимости: {}
DAG зависимостей
router_prompt → search_agent_prompt → rewrite_prompt
router_prompt → summarise_agent_prompt → format_prompt
Ацикличен, можно выполнять топологическую сортировку.
Пет-проект для закрепления
Задача Разработать небольшой реестр промптов с отслеживанием зависимостей и автоматической проверкой на циклы.
Инструменты Python, NetworkX (для DAG), JSON/YAML для хранения, pytest для тестов.
Шаги:
- Определить структуру данных
Promptс полями:id,version,content,dependencies(список объектов с типомinclude/callи версией). - Реализовать класс
PromptRegistry, который умеет:- добавлять/обновлять промпты;
- проверять, не нарушена ли совместимость версий при добавлении;
- строить граф зависимостей и проверять его на ацикличность (с помощью NetworkX).
- Написать CLI-утилиту, которая загружает все промпты из папки и выдаёт отчёт: наличие циклов, неудовлетворённые зависимости.
- Добавить интеграционный тест: при изменении промпта B тестируется промпт A (который его включает/вызывает).
Ожидаемый результат Инструмент, который предотвращает каскадные поломки и автоматически подсвечивает проблемы при изменении промптов в многокомпонентной системе агентов.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 800 | Основы архитектуры Agentic RAG |
| 803 | Цепочки вызовов агентов |
| 805 | Управление состоянием в агентных системах |
| 808 | Версионирование промптов |
| 810 | Дебаггинг и трассировка агентов |
| 730 | Общие принципы композиции LLM-вызовов |
Навигация
- Предыдущий: 805
- Следующий: 807
- Индекс: 00. Индекс разборов