Что такое «prompt as code» (промпты в Git, code review)?

Краткий тезис

Prompt as code — это практика управления промптами (текстовыми инструкциями для LLM) как программным кодом: хранение в системе контроля версий (Git), code review через Pull Request, автоматическое тестирование (CI) и деплой (CD) в Prompt Registry. Цель — обеспечить воспроизводимость, версионирование, коллаборацию и надёжность при работе с промптами, особенно в масштабируемых agentic RAG-системах. Без этой практики промпты часто редактируются «на лету» в ноутбуках или продакшн-конфигах, что ведёт к неконтролируемым изменениям и сложности отката.


1. Термин: «Prompt as code» — происхождение и аналогия

Практика заимствована из Infrastructure as Code (IaC) и Data as Code. Идея: промпт — это не статичный текст, а сущность, которая должна проходить формальный жизненный цикл:

  • Разработка → Ревью → Тестирование → Релиз → Мониторинг.

Термин «Prompt as code» ввёл в широкий обиход OpenAI в своих рекомендациях по безопасному развёртыванию LLM (2023). Ключевые принципы:

  • Хранение в Git — каждый промпт — файл (YAML, JSON, Markdown) с метаданными.
  • Версионирование — семантическое версионирование (semver) для промптов.
  • Code Review — изменения промпта проходят ревью, как и обычный код.
  • CI/CD — при изменении запускаются тесты на регрессию и метрики качества.
  • Регистрация — утверждённый промпт публикуется в централизованное хранилище (Prompt Registry).

2. Проблемы ad-hoc управления промптами (почему это важно)

До внедрения prompt as code команды часто сталкиваются с хаосом:

ПроблемаОписаниеПоследствие
Неявные измененияПромпт правят в интерфейсе LLM или в коде на летуНевозможно отследить, когда и кем изменён
Отсутствие версийНет истории измененийСложно откатить к рабочей версии
Ручное тестированиеПромпты проверяют вручнуюРиск регрессии после небольшого изменения
Конфликт при мержеДва разработчика меняют один промптПотеря изменений
Разные окруженияdev/staging/prod имеют разные версииОшибки из-за несоответствия

Prompt as code решает эти проблемы через стандартные DevOps-практики.


3. Жизненный цикл промпта как кода

3.1 Разработка и формат

Промпт хранится в файле с метаданными. Пример структуры:

# prompts/agentic_rag/v1.2.3.yaml
version: "1.2.3"
name: "agentic_rag_system_prompt"
model: "gpt-4-turbo"
template: |
  You are an AI assistant that helps answer questions using the provided context.
  Always cite sources in the format [1], [2], etc.
  If the context does not contain the answer, say "I don't know"  do not make up information.

  Context:
  {context}

  Question: {question}
variables:
  - name: context
    type: string
    description: "Retrieved documents concatenated"
  - name: question
    type: string
    description: "User query"
tests:
  - name: "test_grounded_answer"
    input:
      context: "Paris is the capital of France. [1]"
      question: "What is the capital of France?"
    expected_response_contains: "Paris"
    expected_citation: true
  - name: "test_no_context_refusal"
    input:
      context: ""
      question: "Who invented the telephone?"
    expected_response_contains: "I don't know"
metadata:
  author: "alice.ml-team"
  created: "2025-03-01"
  description: "System prompt for agentic RAG with citation requirement"

3.2 Code Review

  • Разработчик создаёт ветку feature/update-prompt-v1.3.0.
  • Открывает Pull Request с изменениями в prompts/agentic_rag/.
  • Ревьюеры проверяют:
    • Корректность семантики промпта.
    • Добавлены ли тесты для нового сценария.
    • Не нарушена ли обратная совместимость (например, не удалены обязательные переменные).

3.3 CI — Автоматическое тестирование

GitHub Actions (или аналоги) при создании PR запускают конвейер:

# .github/workflows/prompt-tests.yml
name: Prompt CI
on: [pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install dependencies
        run: pip install openai pytest pyyaml
      - name: Run prompt tests
        run: |
          for file in prompts/*.yaml; do
            python validate_and_test.py --prompt-file "$file" --test-suite
          done

validate_and_test.py загружает промпт, подставляет переменные из тестовых случаев, вызывает LLM и проверяет условия (expected_response_contains, наличие цитат и т.п.).

3.4 CD — Деплой в Prompt Registry

После мержа в main (или master) происходит деплой:

  • Промпт загружается в Prompt Registry (например, S3 + DynamoDB или LangSmith Hub).
  • Реестр хранит все версии, текущая отмечается как latest.
  • Система (агент или RAG-пайплайн) при запуске загружает промпт по имени и версии (или подписывается на обновления).

Пример загрузки в реестр (Python-скрипт):

import yaml
import boto3
from datetime import datetime

def deploy_prompt(prompt_file):
    with open(prompt_file) as f:
        prompt = yaml.safe_load(f)
    registry = boto3.client('s3')
    key = f"prompts/{prompt['name']}/{prompt['version']}.yaml"
    registry.put_object(Bucket='my-prompt-registry', Key=key, Body=yaml.dump(prompt))
    print(f"Deployed {prompt['name']} version {prompt['version']}")

4. Prompt Registry — централизованное хранилище

Prompt Registry — это сервис (или просто бакет), который позволяет:

  • Регистрировать новые версии.
  • Получать промпт по имени и версии (или latest).
  • Версионировать и отслеживать изменения.
  • Проводить A/B тестирование — два параллельных промпта (контроль и эксперимент).

Пример архитектуры:

┌─────────────┐   CI/CD   ┌──────────────────┐
│  Git (main)  │ ────────>│ Prompt Registry  │
│  prompts/*   │          │ (S3 + index)     │
└─────────────┘          └──────────────────┘
                                │
                                ▼
                      ┌──────────────────┐
                      │  Agent/RAG system │
                      │  загружает промпт │
                      │  при инициализации│
                      └──────────────────┘

Популярные готовые решения:

  • LangSmith Hub — встроенный реестр от LangChain.
  • PromptLayer — коммерческий сервис для управления промптами.
  • Agenta — open-source платформа для разработки и версионирования промптов.
  • Собственный реестр на FastAPI + PostgreSQL для полного контроля.

5. Связь с тестированием и метриками

Для prompt as code критически важно иметь регрессионные тесты. Они могут включать:

  • Семантические проверки (содержит ли ответ конкретную фразу).
  • Проверку фактов (faithfulness) — ответ не противоречит контексту.
  • Метрики качества (answer relevance, context recall) через фреймворки вроде RAGAS или DeepEval.

Пример теста с pytest:

import pytest
import openai
import yaml

def load_prompt(path):
    with open(path) as f:
        return yaml.safe_load(f)

prompt_data = load_prompt("prompts/rag_system/v1.yaml")

def test_citation_present():
    client = openai.OpenAI()
    response = client.chat.completions.create(
        model=prompt_data['model'],
        messages=[
            {"role": "system", "content": prompt_data['template'].format(
                context="Earth is round [1].", question="What shape is Earth?")},
        ]
    )
    assert "[1]" in response.choices[0].message.content

6. Интеграция с Agentic RAG

В agentic RAG промпты ещё сложнее: они содержат описание инструментов (tools), структуру планирования (planning) и правила принятия решений. Практика prompt as code особенно полезна здесь:

  • Системный промпт — задаёт поведение агента.
  • Промпты для инструментов — описание каждого tool (function calling).
  • Планировщик — промпт, который разбивает задачу на шаги.
  • Правила рефлексии — промпт для самооценки (Self-RAG).

Все эти промпты должны быть версионированы и тестироваться совместно. Изменение одного может повлиять на всё поведение агента.


7. Инструменты и лучшие практики

ИнструментОписаниеКогда выбрать
LangSmith HubВстроенный реестр, интеграция с LangChainИспользуете LangChain
PromptLayerПлатформа с мониторингом, A/B, версиямиНужна аналитика
AgentaOpen-source, веб-интерфейс для редактированияКоманда не разработчиков
Собственный реестрПолный контроль, низкая стоимостьСтартап/enterprise

Лучшие практики

  • Используйте семантическое версионирование major.minor.patch:
    • major — изменение поведения (breaking change).
    • minor — добавление нового теста или незначительное улучшение.
    • patch — исправление опечатки.
  • Всегда указывайте модель (model) и параметры (temperature, max_tokens).
  • Храните тесты в отдельной директории prompts/tests/ рядом с файлами.
  • Настройте автоматический откат при провале тестов.

Пет-проект для закрепления

Задача Создать репозиторий с тремя версиями промпта для RAG-системы, настроить CI/CD (GitHub Actions) для тестирования и деплоя в локальный Prompt Registry на FastAPI.

Инструменты

Шаги:

  1. Создайте структуру репозитория:
    prompts/
      rag_assistant/
        v1.0.0.yaml
        v1.1.0.yaml
        v2.0.0.yaml
    tests/
      test_prompts.py
    registry/ (FastAPI приложение)
    .github/workflows/
      prompt-ci.yml
      prompt-cd.yml
    
  2. Напишите минимальный реестр на FastAPI с эндпоинтами POST /prompts и GET /prompts/{name}/{version}.
  3. В GitHub Actions:
    • CI: при пул-реквесте запускать pytest tests/ для каждого изменённого промпта.
    • CD: при мерже в main деплоить промпты в реестр (выполнить POST-запрос).
  4. Добавьте тесты на:
    • Наличие ответа с фактами из контекста.
    • Корректное игнорирование нерелевантного контекста.

Ожидаемый результат

  • Репозиторий, в котором истории изменений промптов полностью прозрачна.
  • При каждом PR автоматически проверяются регрессионные тесты.
  • После мержа промпт сразу доступен через API реестра для использования в приложении.

Связь с другими вопросами

ВопросТема
801Что такое Agentic RAG?
803Как проектировать пайплайны промптов?
804Что такое динамический выбор промптов?
805Как оценивать агентов?
808Инструменты (tools) в агентах
809Память в агентах

Навигация