Реализовать prompt diff

ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Реализовать prompt diff

1. Цель задачи

Научиться инженерно подходить к версионированию промптов и автоматизировать процесс код-ревью изменений в них. Вы разработаете утилиту для сравнения двух версий промпта с подсветкой изменений, интегрируете её в Git-рабочий процесс и обеспечите удобный просмотр диффа в пул-реквестах.

Ключевой результат Рабочая команда prompt-diff, которая принимает два файла промптов (или ссылки на коммиты) и выводит цветной diff в консоль/HTML, а также GitHub Action, автоматически публикующий diff в комментарии к PR.


2. Исходные данные

Что нужноОткуда взять
Репозиторий с промптами (версионированные .prompt или .yaml / .md файлы)Создать локально или использовать существующий проект
Python 3.9+Установлен в системе
GitУстановлен и настроен
Доступ к GitHub / GitLab (опционально)Личный аккаунт

Если нет реального репозитория с промптами — симулируем:

  1. Создайте пустой Git-репозиторий: mkdir prompt-demo && cd prompt-demo && git init
  2. Создайте пару файлов промптов в разных версиях:
    • v1.yaml — базовая версия промпта для суммаризации
    • v2.yaml — изменённая версия с другим тоном и примерами
  3. Закоммитьте оба файла в разные ветки или в виде последовательных коммитов в master
  4. Убедитесь, что можно выполнить git diff v1.yaml v2.yaml

3. Технологический стек

КомпонентИнструментыНазначение
ЯзыкPython 3.9+Реализация утилиты diff
Библиотека diffdifflib (stdlib), termcolor, diff2html-cliАлгоритмы сравнения и подсветка
Формат выводаТерминал (цветной) / HTML / MarkdownВизуализация для code review
АвтоматизацияGitHub Actions или GitLab CIПубликация diff в PR
ТестированиеpytestПроверка корректности диффа
Линтингflake8, blackКачество кода

4. Этапы выполнения

Этап 1: Проектирование интерфейса и выбор алгоритма (30 минут)

Действия

  1. Определите команду и аргументы

    • prompt-diff <file1> <file2> — сравнение двух файлов
    • prompt-diff --commit <hash1> <hash2> — сравнение файлов промптов между коммитами (опционально)
    • prompt-diff --html — вывод в HTML вместо терминала
  2. Сравните алгоритмы diff

  3. Напишите спецификацию в SPEC.md в репозитории:

    • Формат входных данных (файлы, текст)
    • Правила отображения: строки с удалением красным, добавлением зелёным, контекст серым
    • Поведение при пустых или несуществующих файлах

Ожидаемый результат этапа Документ SPEC.md с чётким описанием интерфейса и поведения утилиты.

Этап 2: Реализация базовой утилиты (1.5–2 часа)

Действия

  1. Создайте структуру проекта

    prompt-diff/
    ├── prompt_diff/
    │   ├── __init__.py
    │   ├── cli.py
    │   ├── differ.py
    │   ├── formatters.py
    ├── tests/
    │   ├── test_differ.py
    ├── sample_prompts/
    │   ├── v1.yaml
    │   └── v2.yaml
    ├── setup.py / pyproject.toml
    └── SPEC.md
    
  2. Реализуйте differ.py — основной класс PromptDiffer:

    import difflib
    from pathlib import Path
    from typing import List, Tuple
    
    class PromptDiffer:
        def __init__(self, context_lines: int = 3):
            self.context_lines = context_lines
    
        def load(self, path: Path) -> str:
            return path.read_text(encoding='utf-8')
    
        def compute_diff(self, text1: str, text2: str) -> str:
            lines1 = text1.splitlines(keepends=True)
            lines2 = text2.splitlines(keepends=True)
            diff = difflib.unified_diff(
                lines1, lines2,
                fromfile='version1', tofile='version2',
                n=self.context_lines
            )
            return ''.join(diff)
    
  3. Реализуйте formatters.py — цветной вывод в терминал:

    from termcolor import colored
    
    def format_terminal(diff_text: str) -> str:
        output = []
        for line in diff_text.splitlines(keepends=True):
            if line.startswith('+'):
                output.append(colored(line, 'green'))
            elif line.startswith('-'):
                output.append(colored(line, 'red'))
            elif line.startswith('@@'):
                output.append(colored(line, 'cyan'))
            else:
                output.append(line)
        return ''.join(output)
    
  4. Реализуйте cli.py:

    import argparse
    from pathlib import Path
    from .differ import PromptDiffer
    from .formatters import format_terminal, format_html
    
    def main():
        parser = argparse.ArgumentParser(description='Prompt Diff Tool')
        parser.add_argument('file1', type=Path)
        parser.add_argument('file2', type=Path)
        parser.add_argument('--html', action='store_true', help='Output as HTML')
        args = parser.parse_args()
    
        differ = PromptDiffer()
        text1 = differ.load(args.file1)
        text2 = differ.load(args.file2)
        diff = differ.compute_diff(text1, text2)
    
        if args.html:
            with open('diff.html', 'w') as f:
                f.write(format_html(diff))
        else:
            print(format_terminal(diff))
    
  5. Настройте pyproject.toml с точкой входа.

Ожидаемый результат этапа Работающая команда prompt-diff (после pip install -e .) выводит цветной diff в терминал.

Этап 3: Интеграция с Git и code review (1–1.5 часа)

Действия

  1. Создайте Git-хук (pre-push) для автоматической проверки — опционально
  2. Напишите GitHub Action для публикации diff в комментарии PR:
    • Триггер: pull_request с изменением .prompt/.yaml/.md
    • Шаги:
      • Checkout веток PR и base
      • Установка утилиты prompt-diff
      • Для каждого изменённого промпта: prompt-diff --html <base> <head> → генерирует diff.html
      • Загрузка HTML как артефакт (опционально)
      • Отправка diff как комментарий в PR с помощью actions/github-script
    • Пример .github/workflows/prompt-diff.yml:
      name: Prompt Diff
      on: [pull_request]
      jobs:
        diff:
          runs-on: ubuntu-latest
          steps:
            - uses: actions/checkout@v4
              with:
                fetch-depth: 2
            - name: Set up Python
              uses: actions/setup-python@v5
              with:
                python-version: '3.10'
            - name: Install prompt-diff
              run: pip install .
            - name: Generate HTML diff
              run: |
                git diff HEAD^ --name-only -- '*.prompt' '*.yaml' '*.md' | while read f; do
                  if git diff HEAD^ -- "$f" | grep -q .; then
                    prompt-diff --html <(git show HEAD^:"$f") "$f" > "${f}.diff.html"
                  fi
                done
            - name: Upload artifacts
              uses: actions/upload-artifact@v4
              with:
                path: '*.diff.html'
            - name: Comment PR
              uses: actions/github-script@v7
              with:
                script: |
                  const fs = require('fs');
                  const files = fs.readdirSync('.').filter(f => f.endsWith('.diff.html'));
                  for (const f of files) {
                    const content = fs.readFileSync(f, 'utf-8');
                    await github.rest.issues.createComment({
                      ...context.repo,
                      issue_number: context.issue.number,
                      body: `## Prompt diff: ${f}\n\n<details><summary>Show diff</summary>\n\n${content}\n\n</details>`
                    });
                  }
      
  3. Проверьте работу Action на тестовом PR в вашем репозитории.

Ожидаемый результат этапа При создании PR с изменением промпта в комментариях появляется свёрнутый блок с цветным diff (HTML).

Этап 4: Тестирование и обработка граничных случаев (1 час)

Действия

  1. Напишите тесты в tests/test_differ.py:
    • Тест на пустые файлы
    • Тест на идентичные файлы (пустой diff)
    • Тест на полное изменение
    • Тест на изменение в середине большого промпта
    • Тест на Unicode (например, кириллица, эмодзи)
  2. Добавьте тесты для CLI с использованием subprocess или CliRunner из Click (если используете Click)
  3. Покройте тестами форматтеры — проверьте, что цвета содержат ANSI-коды (для терминала) или корректный HTML
  4. Запустите pytest, добейтесь 100% прохождения

Ожидаемый результат этапа pytest проходит минимум 8 тестов, coverage > 85%.

Этап 5: Документация и финальная упаковка (30 минут)

Действия

  1. Напишите README.md:
    • Установка: pip install prompt-diff (или pip install -e .)
    • Примеры использования
    • Скриншот/описание цветного вывода
    • Интеграция с Git (хук)
    • Ссылка на GitHub Action
  2. Добавьте CONTRIBUTING.md с правилами форматирования (black, flake8)
  3. Обновите pyproject.toml — укажите автора, лицензию, ссылки

Ожидаемый результат этапа Готовый репозиторий с документацией, который можно использовать и передать коллегам.


5. Критерии приемки (Definition of Done)

  • Утилита prompt-diff установлена и работает через CLI
  • Цветной diff в терминале: зелёный для добавлений, красный для удалений, голубой для заголовков
  • HTML-вывод генерируется корректно и может быть вставлен в Markdown (с экранированием)
  • GitHub Action автоматически публикует diff в комментарии PR
  • Все тесты проходят, coverage > 85%
  • Документация содержит примеры для разных случаев (добавление, удаление, изменение)
  • Поддерживаются файлы с расширениями .prompt, .yaml, .md, .txt
  • Утилита корректно обрабатывает Unicode (эмодзи, кириллицу)
  • Скрипт не падает при отсутствии одного из файлов, выводит понятную ошибку
  • В README есть инструкция по быстрой установке и использованию

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

Основной артефакт Python-пакет prompt-diff (как локальный репозиторий) со следующей структурой:

prompt-diff/
├── prompt_diff/
│   ├── __init__.py
│   ├── cli.py
│   ├── differ.py
│   ├── formatters.py
├── tests/
│   ├── test_differ.py
│   ├── test_formatters.py
├── sample_prompts/
│   ├── v1.yaml
│   └── v2.yaml
├── .github/
│   └── workflows/
│       └── prompt-diff.yml
├── README.md
├── CONTRIBUTING.md
├── pyproject.toml
├── SPEC.md

Содержание ключевых файлов

  • differ.py — класс с методами load, compute_diff, compare_commits (опционально)
  • formatters.py — функции format_terminal, format_html
  • .github/workflows/prompt-diff.yml — рабочий Action
  • README.md — полное описание

Опционально pre-commit hook скрипт, Makefile


7. Возможные сложности и их решение

СложностьРешение
Цвета в терминале не отображаются (Windows)Использовать библиотеку colorama для инициализации ANSI-поддержки
HTML diff слишком большой и ломает комментарий PR (ограничение GitHub – 65536 символов)Обрезать diff до 60000 символов и добавить ссылку на артефакт; или выводить только сводку изменений с детальной ссылкой
Нужно сравнивать промпты из разных коммитов, а не только файлыДобавить опцию --commit и реализовать git show внутри Python (через subprocess)
diff показывает только строки, но не символьные изменения внутри строки (например, изменённое слово)Использовать difflib.ndiff для посимвольного сравнения; затем сгруппировать в строки с подсветкой слов
GitHub Action не может найти prompt-diff (не установлен)Установить пакет внутри шага: pip install git+https://github.com/your-org/prompt-diff.git или создать Docker-образ
При большом количестве изменённых промптов в одном PR генерируется много комментариевОбъединить все diff в один комментарий, используя <details> для каждого файла

8. Бюджет времени (оценка)

ЭтапВремя
Этап 1: Проектирование интерфейса30 мин
Этап 2: Реализация базовой утилиты1 ч 30 мин
Этап 3: Интеграция с Git и code review1 ч 30 мин
Этап 4: Тестирование1 ч
Этап 5: Документация30 мин
Итого (без учёта отладки)5 ч
С учётом типичных задержек (×1.5)~7.5 ч

Примечание: Для первого раза рекомендуется выделить 2 рабочих дня с возможностью доработок.


9. Связанные вопросы из базы знаний

ВопросТема
15Управление версиями промптов
42Форматы хранения промптов (yaml, md, txt)
73Инструменты сравнения текстов (diff)
104GitHub Actions для промптов
157Дифф промптов и его визуализация
208Подсветка изменений в code review
259Ревью промптов: критерии и процесс
310Версионирование промптов с помощью Git
401CI/CD для промптов: автоматизация проверок
503Лучшие практики хранения промптов в репозитории

10. Чек-лист самопроверки

  • Я создал SPEC.md до начала кодирования и утвердил его с командой
  • Утилита запускается без ошибок на пустых и несуществующих файлах с понятными сообщениями
  • Цвета работают и в терминале, и в HTML-версии
  • GitHub Action корректно обрабатывает изменения только в файлах промптов
  • Я написал минимум 8 unit-тестов, покрытие > 85%
  • README содержит команды установки, примеры и скриншоты
  • Я проверил, что diff не нарушает лимит длины комментария GitHub (если используется)
  • Я просмотрел пул-реквест с реальным изменением промпта и убедился, что ревьювер сразу видит изменения