В прошлых статьях я раскладывал различные знания и сущности по листам и показывал, как сравнить две редакции регламента с помощью карты. Теперь расскажу, что происходит, когда карту дорабатывает LLM. В предыдущих версиях PlyLoom я как-то упустил момент с тем как реализовать взаимодействие без перезагрузки новой версии всего проекта целиком, равно как и отсутствие возможности сравнить различия 2-х файлов.
Пример за минуту
Я попросил модель добавить в карту проекта новую проверку — “повторная доставка сообщения не должна создавать второй файл”. Ответ модели пришёл в виде списка из четырёх пунктов.
Два из них это то, что я просил — новая проверка и её связь с очередью. Ещё два в виде галлюцинаций. В одной срок хранения файла тихо вырос с 24 до 72 часов. В другой из описания очереди пропала оговорка о том, что провайдер пока не выбран.
Нужное я отметил, а лишнее нет, после чего нажал «Применить отмеченное». На карте появился новый узел, а срок и оговорка остались прежними. Этот пример можно открыть в браузере: ответ модели там уже ждёт проверки.
Откуда взялась задача
Прототип я затевал под простой сценарий: модель извлекает, человек проверяет. Я даю модели материалы, она раскладывает их в карту, а я хожу по листам и ищу ошибки. С первой версией карты так работать удобно. Сложности начинаются со второй.
Чтобы доработать карту, я прикладывал к промту весь проект и просил изменения. Модель возвращала его целиком, и я заменял им карту. На большом JSON модели иногда теряют узлы, сокращают цитаты и правят то, о чём их не просили. Найти это можно, только сравнив два файла от начала до конца. Что почти невозможно, к тому же если делать это регулярно.
Полный файл — это снимок. Мне же нужна разница: что добавили, изменили или убрали.
Какой же подход в работе с изменениями — выбрать? Confluence или git?
Confluence хранит историю страницы на сервере. Любые две версии можно сравнить и откатиться. Пользоваться просто, но правки попадают на страницу сразу и без проверки. К тому же сервера у PlyLoom — нет.
Git хранит историю от каждого участника и умеет принимать предложения правок через pull request. Предложение не попадёт в основную ветку, пока его не примут. Для правок от модели это то, что нужно. Но построчное сравнение для графа не годится: передвинул карточку и в JSON меняются десятки строк.
Я взял у Confluence простые термины, а у git логику. Пользователь видит кнопки «Сравнить», «Применить», «Принять» и «Отклонить». Внутри работают предложения правок и отпечатки версий.
Пакет и приращение
Проект — это файл .plyloom целиком. Его хранят, пересылают коллегам, кладут в репозиторий. Новую карту с нуля модель присылает проектом.
Приращение — это список правок к известной версии. Так приходят доработки. Правка выглядит так:
{"plyloom":"changes","version":1,"base":"a3f9c2…","title":"Уточнить роли","ops":[ {"op":"add_node","node":{"id":"loc","name":"Локализация отчёта","kind":"entity","sheets":["context"]}}, {"op":"set","node":"goal.export","field":"body","to":"новый текст","was":"старый текст"}, {"op":"add_edge","edge":{"from":"loc","to":"goal.export","kind":"ref"}}]}
Самое полезное поле здесь — was, прежнее значение. Если в проекте уже стоит другое, пункт помечается как конфликт. Поэтому ответ модели можно применить, даже если я успел поправить карту, пока она думала. Всё нетронутое встанет само, а спорные места будут на виду.
Одна страница для обмена
Чтобы как-то проще было в этом всем разбираться я добавил схему сценариев взаимодействия с несколькими переключателями. Выбрать нужно всего три:
-
делаем новую карту или дорабатываем открытую;
-
работаем с моделью или с коллегой;
-
отдаём всю карту или один лист с соседями.
Промт собирается из двух частей. Первая описывает формат обмена, вторая — задачу. Для задачи есть заготовки вроде «Ответить на открытые вопросы» или «Найти противоречия». Текст заготовки виден целиком, и его можно поправить перед копированием.
Проверка в два захода
Ответ модели вставляется как есть, текст вокруг JSON не мешает. Правки показываются списком по листам. Изменённый текст виден по словам: удалённое зачёркнуто, новое выделено.
Конфликты по умолчанию не отмечены. Заменить значение можно, но только сознательно. Если один пункт зависит от другого, например связь ведёт к новому узлу, без второго он не применится.
Проверка идёт в два захода. Сначала я решаю по списку, что стоит взять в режиме брифа, и нажимаю «Применить отмеченное». Неотмеченное отклоняется. Применённые правки появляются на карте и остаются отмеченными, как исправления в Word: новые узлы обведены зелёным, изменённые — жёлтым.
Второй заход проходит на карте, среди соседних узлов. Здесь видно то, чего не видно в списке: подходит ли новый узел по смыслу и не пропала ли связь. По каждому узлу можно нажать «Принять» или «Отклонить». Для всех сразу внизу есть полоса с кнопками «Принять все» и «Отклонить все». Отклонение возвращает и удалённое, а правки сделанные после — не трогает. Также всегда можно просто «Принять все», но надеюсь это не будет происходить часто — “доверяй но проверяй”
Разобрать всё за один раз не обязательно. Список можно отложить, а непринятые правки сохранятся в проекте и в скачанном файле.
Сравнение по смыслу
У каждого узла постоянный ID, поэтому сравнивать карты можно по содержанию. PlyLoom замечает:
-
новые, удалённые и переименованные узлы;
-
новое значение атрибута;
-
смену типа связи;
-
появление узла на листе или уход с него.
Передвинутые карточки по умолчанию не показываются, для них есть отдельная галочка.
Модели иногда перенумеровывают ID. Без защиты такая правка выглядела бы как «удалить всё и добавить заново». Поэтому узел с новым ID, но с тем же типом и названием считается прежним, если такая пара одна. Связь устанавливается по связям и типу.
Что хранится в файле
Сначала я хотел хранить в файле журнал правок со старыми значениями. Он дал бы историю и откат. Но у журнала есть неприятное свойство: удалённый текст остаётся в файле, пока историю не очистить. Если файл уходит наружу, это может стать сюрпризом. От журнала я решил отказаться.
В файле остаются отпечатки версий. Отпечаток — это первые 12 знаков SHA-256 от содержимого. Файл помнит отпечаток своей версии и до двадцати прежних. По ним PlyLoom понимает, что пришло: продолжение прежней версии, более старая копия или копия, которую меняли параллельно с прежней.
Пока правки не проверены до конца, файл хранит их вместе с прежними значениями затронутых мест. Иначе отклонить их позже было бы нечем. После «Принять все» или «Отклонить все» эти данные из файла уходят.
Как я проверял сравнение
Обычных тестов для такой функции мало: ошибки прячутся в сочетаниях правок. Поэтому я проверял сравнение на случайных правках учебных карт. Генератор вносит в карту от одной до пятнадцати правок, тех же, что делает человек или модель. Затем проверяются два свойства.
-
Список правок превращает карту A в карту B и обратно без остатка.
-
Если две копии менялись независимо, конфликты появляются только там, где обе стороны трогали одно и то же.
На генерации 500 вариантов для каждой карты эти проверки нашли несколько ошибок, которые руками я бы не поймал. Например, у узла терялся основной лист, а при сравнении не переносился порядок вкладок. Всё это исправлено до релиза.
Что дальше
Собирать и проверять карту теперь удобно, а вот показать её человеку без PlyLoom пока трудно. Следующий шагами мне видится необходимость реализации конкретных вариантов экспорта результатов внутри каких-то конкретных сценариев использования. Хочется придерживаться некоей универсальности.
Попробовать можно на сайте без установки — пример с правками уже ждёт проверки. Подробнее о функции — в статье на сайте. Если сравнение где-то ведёт себя странно, или нашли баги — просьба о них сообщать!
ссылка на оригинал статьи https://habr.com/ru/articles/1091266/