TL;DR
Это конвейер, который превращает длинный технический документ (даташит на микросхему) в структурированное дерево свойств. Документ режут на куски. Из каждого куска отдельным запросом достают параметры. Потом параметры раскладывают по дереву функциональных блоков. Модель при этом не переписывает данные, а выдаёт только команды («положи свойство в блок UART», «создай блок SPI»). Сами значения хранятся у вас и не проходят через модель.
Главная находка: если скормить документ целиком и попросить сразу готовый результат, модель молча теряет часть данных, даже когда документ влезает в контекст. Результат выглядит гладко и правдоподобно, но самого важного параметра в нём нет. Вес важности не совпадает с весом в тексте: критичное ограничение может быть одной строкой в таблице. Вторая беда: при пересборке данных модель незаметно меняет значения, единицы и условия.
Метод решает это в три хода. Нарезка сужает внимание модели до одного фрагмента, поэтому мелочи не теряются. Каждая стадия делает одно дело, и её результат можно проверить. Модель только командует, а исходные данные остаются нетронутыми.
Схема метода
ШАГ 0: Нарезать документ на куски по границам предложений;
таблицу — целиком, с заголовком и подписью → список кусков
ШАГ 1: Каждый кусок — отдельный запрос. Просим извлечь свойства
по общим описаниям с примерами (не по жёсткому списку)
→ {название, описание с условиями, значение, единица} + номер куска
ШАГ 2: Маршрутизация: даём модели свойства и текущее дерево блоков
(без уже разложенных свойств) → ТОЛЬКО команды:
«прикрепить к блоку X» или «создать блок Y в Z и прикрепить»
ШАГ 3: Проверка команд на структуру и согласованность; применение
к исходным данным без участия модели
ШАГ 4: Циклы уточнения внутри соседних блоков: удаление дублей,
конфликты имён, перенос свойств, попавших не туда
(до лимита итераций)
Каждый шаг — отдельный запрос. В оригинале шаги 3–4 выполняет программа на компьютере. В чате вы можете делать это вручную или таблицей.
Пример применения
Задача: Вы открываете кофейню в Казани, и вам прислали договор аренды помещения на 60 страниц. Внутри таблица ставок, штрафов и индексаций. Условия разбросаны: арендная ставка в приложении, штраф за досрочный выезд в пункте 9.4, «каникулы» в допсоглашении. Если спросить «перечисли все финансовые условия» целиком, модель выдаст аккуратный список и пропустит пункт про индексацию на 12% в год, спрятанный в сноске к таблице.
Промпт (шаг 1, один кусок; повторяется для каждого куска):
Ты извлекаешь условия из фрагмента договора аренды нежилого помещения.
Что искать (это ориентиры, а не закрытый список — извлекай всё
похожее, что встретишь):
- денежные условия (e.g. ставка аренды, обеспечительный платёж,
коммунальные платежи, индексация)
- штрафы и санкции (e.g. за просрочку, за досрочное расторжение)
- сроки и даты (e.g. срок аренды, арендные каникулы, уведомления)
- права и ограничения (e.g. субаренда, переоборудование, вывеска)
- условия расторжения и продления
Для каждого условия верни строку:
- название: короткое имя переменной
- описание: к чему относится и ПРИ КАКИХ УСЛОВИЯХ действует
(период, площадь, вариант помещения, исключения)
- значение: число, диапазон или формулировка как в тексте
- единица: ₽, %, дни, мес. или «—»
- источник: {номер_куска}
Правила:
1. Извлекай только то, что явно написано во фрагменте.
2. Не пересчитывай и не округляй значения.
3. Если одно условие действует по-разному в разных случаях —
это отдельные строки с разными описаниями.
4. Если во фрагменте нет ничего подходящего — напиши «пусто».
Фрагмент {номер_куска}:
{текст_куска}
Результат: Модель вернёт список строк в заданном формате с номером куска у каждой. Условия, которые различаются периодом или площадью, придут отдельными строками, а не склеенными в одну. Для кусков без нужных данных будет «пусто». Дальше вы собираете все строки в таблицу и запускаете шаг 2 (раскладка по блокам) по шаблону ниже.
Почему это работает
Слабость модели. На длинном тексте внимание размазывается. Мелкая деталь в одной ячейке таблицы получает столько же шансов быть замеченной, как один пункт из сотен. Вдобавок вы просите модель одновременно искать, группировать, убирать дубли, переименовывать и собирать результат. Задачи мешают друг другу. Ещё одна слабость: когда модель пересобирает данные, она их слегка переписывает. Меняются значения, условия, формулировки.
Сильная сторона. На коротком фрагменте с одной понятной задачей модель извлекает точно. Раскладывать свойства по смыслу («это про UART, а не про общую периферию») она умеет хорошо. Команды вида «прикрепить к блоку X» она тоже выдаёт надёжно.
Как метод это использует. Нарезка даёт модели маленький фрагмент, где ничего не теряется. Общие описания с примерами говорят что искать по смыслу и не закрывают список заранее. Команды вместо пересказа оставляют данные нетронутыми: модель решает только куда положить, а не что написано. Номер куска у каждого свойства позволяет проверить, что оно взято из текста и не выдумано.
Рычаги управления: - Размер куска → меньше кусок, меньше потерь, но больше запросов и риск оторвать условие от значения. - Таблицы целиком → не режь таблицу: значения зависят от заголовков, подписей и единиц. - Описания с примерами «e.g.» → шире список примеров, шире охват. Жёсткий список сузит извлечение до того, что вы предвидели. - Начальный каркас блоков → задай 5–8 верхнеуровневых блоков под свою область. Остальные модель создаст сама. - Число циклов уточнения → меньше для коротких документов, больше для запутанных. - Общее свойство → верхний блок → правило, что общее условие хранится один раз на верхнем уровне. Так не плодятся дубли.
Шаблон промпта
Шаг 2 — маршрутизация. Модель получает свойства и текущее дерево и возвращает только команды.
Ты раскладываешь извлечённые условия по иерархии блоков.
Ты НЕ переписываешь, НЕ пересказываешь и НЕ меняешь свойства.
Ты возвращаешь только команды.
{дерево_блоков}
{список_свойств_с_номерами}
Для каждого свойства выбери ОДНУ из двух команд:
1. ATTACH(property_id, block) — если подходящий блок уже есть.
Крепи к САМОМУ ОБЩЕМУ блоку, для которого свойство верно
без условий для всех его дочерних блоков.
Пример: общее требование ко всем выходам — к «{общий_блок}»,
а не отдельно к каждому дочернему.
Если свойство относится только к одному дочернему блоку —
крепи к нему.
2. CREATE_AND_ATTACH(property_id, new_block, parent_block) —
если свойство указывает на отдельную сущность, которой в
дереве нет. Новый блок создавай под подходящим существующим.
Пример: максимальная скорость UART при наличии блока
«Периферия» → создай «UART» внутри «Периферии».
Только список команд, по одной на строку. Без пояснений.
Не воспроизводи значения, описания и единицы свойств.
Используй только id из PropertiesToRoute и имена блоков из
CurrentHierarchy или новые, созданные в этом же ответе.
Что подставлять:
- {дерево_блоков} — стартовый каркас (например, «Деньги», «Сроки», «Штрафы», «Расторжение») и далее то, что выросло. Уже разложенные свойства в дерево не включай, это экономит контекст.
- {список_свойств_с_номерами} — строки из шага 1, каждой присвоен id.
- {общий_блок} — пример из вашей области, чтобы модель поняла правило «самый общий блок».
После ответа вы сами проверяете команды (все ли id существуют, не ссылается ли команда на несуществующий блок) и вносите их в таблицу. Значения при этом не трогаете.
🚀 Быстрый старт — вставь в чат:
Вот шаблон маршрутизации (раскладки извлечённых данных по иерархии
блоков командами). Адаптируй под мою задачу: {твоя_задача}.
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM спросит, какой у вас документ, какие верхнеуровневые блоки нужны на старте и какие примеры «общего» и «частного» свойства бывают в вашей области. Это нужно, чтобы она выстроила правило «крепить к самому общему блоку» под вашу тематику. Остальную структуру она возьмёт из шаблона.
Ограничения
⚠️ Нужен код для полной версии: Оригинал — программа: разбор PDF, нарезка, проверка команд, их исполнение на локальных данных. В чате получится урезанная версия: нарезка и склейка руками или таблицей. Автоматизация без кода (Make, n8n) подойдёт, но это уже настройка.
⚠️ Картинки не учтены: Схемы, графики и диаграммы авторы исключили. Если важное в документе показано графиком, метод его пропустит.
⚠️ Нарезка может оторвать контекст: Условие, описанное в одном месте, а применяемое в другом, при разрезании теряет связь. Поэтому таблицы нельзя резать. С длинными пояснениями в прозе риск остаётся.
⚠️ Причина выигрыша не разделена: Авторы сами пишут, что прирост нельзя целиком приписать разделению задач. Часть эффекта даёт то, что каждая стадия получает меньше контекста. Что именно дало сколько, они не разложили.
⚠️ Сравнение только с одним запросом: Базой был «скормить всё сразу». С другими разумными подходами (например, просто нарезка и без команд) полная версия не сравнивалась в доступной части текста.
⚠️ Нишевая проверка: Проверяли на технической документации по электронике. Для юридических и финансовых документов это перенос принципа, а не доказанный результат.
⚠️ Оценка полноты относительная: Метрика «покрытие одного графа другим» показывает, кто полнее, но не гарантирует, что нашли всё. Абсолютной полноты авторы не знают.
Как исследовали
Авторы взяли 20 даташитов на разные компоненты: датчики, процессоры, модули питания, связи. Документы были разной длины. Конвейер сравнивали с простым подходом: отдать документ целиком и попросить готовый граф знаний.
Проверяли две вещи. Первая — достоверность: каждое извлечённое свойство сверяли с исходным текстом, действительно ли оно там есть и с теми ли значениями. У конвейера вышло 98,8%, у запроса целиком 76,1%. То есть примерно четверть свойств в одном запросе была искажена или выдумана.
Вторая — полнота. Идеального списка «всего, что есть в даташите» не существует, и задать его вручную нельзя. Поэтому придумали относительную меру: берут два графа и смотрят, насколько информация из одного восстанавливается из другого. Свойства сначала приводят к одинаковой детализации. Одна модель может записать VIH, VIL, VOH, VOL одним пунктом, другая четырьмя, и считать пункты напрямую нельзя. Результат асимметричен: конвейер полностью покрывает 83,6% достоверных свойств базового подхода, а базовый подход покрывает лишь 10,5% того, что нашёл конвейер.
Неочевидное: даже когда документ целиком влезает в контекст, простой запрос теряет детали. Практический вывод: влезает в контекст ≠ модель увидит всё. Для документов, где важна каждая строка, нарезка и узкая задача на каждый запрос надёжнее одного большого запроса.
Адаптации и экстраполяции
🔧 Техника: добавить второй проход по тому же куску → ловим пропущенное
Это моя идея, в статье её нет. После шага 1 отдайте модели тот же кусок и свой список извлечённого:
Вот фрагмент и уже извлечённые из него условия. Найди условия, которых в списке нет. Верни только недостающие строки в том же формате. Если всё извлечено — напиши «ничего не пропущено».Дороже, зато лучше для критичных документов.
🔧 Техника: проверка достоверности → судья сверяет с источником
Идея в духе статьи: у каждого свойства есть номер куска. Отдельным запросом дайте модели свойство и его кусок и спросите: «Есть ли это в тексте с таким значением, единицей и условием? Ответ: ДА / НЕТ / ЧАСТИЧНО + цитата». Строки с «НЕТ» и «ЧАСТИЧНО» проверяйте руками.
Применение для агентов: в файл инструкций агента можно вписать правило «не пересказывай данные — возвращай только ссылки и команды изменений, значения берёшь из исходного файла». Это перенос принципа, а не результат статьи.
Ресурсы
- Статья: Faithful and Complete LLM-Assisted Automated Construction of Hierarchical Hardware Knowledge Graphs
- Авторы: Haotian Qiao, Robert P. Dick — Department of Electrical Engineering and Computer Science, University of Michigan, Ann Arbor, США
- Упомянутые инструменты и работы: MinerU (разбор PDF в Markdown), ElecGraph-RAG, ChipMind (ChipKG)
- Примечание: доступный текст обрывается на описании маршрутизации. Подробности циклов уточнения, полный набор промптов и экспериментальные таблицы не видны.
