Структура онтологии против размера модели: сколько стоит проектирование графа для ИИ-агента.
Как три безубыточные структуры одной графовой структуры данных страхования изменили точность, количество вызовов инструментов, количество токенов и затраты для небольших и крупных моделей в Azure Cosmos DB.
Источники: Your Agent Is Not Confused, Your Ontology Is
Когда агент показывает низкую эффективность, большинство команд прибегают к использованию более крупной модели. Этот метод действительно работает, но стоит примерно в четырнадцать раз дороже, чем решение проблемы путем корректировки структуры графа. Эта цифра получена в результате эксперимента, в котором одни и те же данные моделировались тремя разными способами, а агент в Microsoft Foundry имел в своем распоряжении четыре инструмента для поиска путей и никаких других способов найти ответ. Измерялась стоимость структуры знаний за каждый вопрос.
Выше показаны три варианта представления одной базы фактов, в общей сложности 2 435 фактов. Каждая панель представляет собой настоящий субграф, взятый из данных эксперимента, и демонстрирует, как каждая онтология организует информацию о трех одинаковых страховых требованиях. В плоском формате структура расположена внутри свойств, поэтому почти нет связей между элементами. В нормализованном формате каждый факт становится отдельным вершиной: ничего не пропущено, но у ничего нет названия. В формате с формами каждая сущность имеет свой тип, а каждая связь — свое название. Агент, модель и база данных остаются одинаковыми во всех трех вариантах, причем только форма меняется.
Сначала несколько слов о данных. Всё в них вымышлено: люди, компании, места и страховщик взяты из составленных списков слов с фиксированным исходным материалом, поэтому ничто из этого не относится к реальным объектам. Значения показателей получены в результате реальных запусков в Sweden Central. Мышление осуществлялось с использованием специальной инфраструктуры Microsoft Foundry, данные хранились в учётной записи Azure Cosmos DB для Apache Gremlin, а каждый вызов инструмента представлял собой запрос Gremlin к динамической графовой структуре. В итоге было получено 480 эпизодов с участием агентов, 4,3 миллиона токенов и сумма в $8,09. Первый прогон по той же сетке, при котором инструменты читали файлы-генераторы вместо базы данных, обошёлся в $7,74; его называют проверочным прогоном. Все приведённые цифры взяты из кампаний Cosmos, а проверочный прогон проводится только тогда, когда два прогона вместе показывают что-то, чего не смог показать один прогон.
Слой, который никто не обновляет
Команды, разрабатывающие агентов, как правило, совершают один и тот же цикл действий. Агент терпит неудачу при решении вопросов, с которыми должен справиться. Кто-то предлагает использовать более сложную модель. Сумма счета удваивается, проблемы переходят на другие вопросы, и в итоге делается вывод, что агенты еще не готовы.
Почти никто не рассматривает сам материал, на основе которого формируется знание агента. На мгновение забудем факты. Спросим себя: является ли корректирующий элемент узлом или строкой внутри JSON-объекта, содержит ли ребро значение assessed_by или просто related, и требуется ли для перехода от заявки к страхователю один шаг или пять.
Предыдущие исследования охватывали систему принятия решений и инструмент их фиксации. В других работах трехчастная публичная серия создала постоянный слой знаний, запустила на нем агентов с использованием собственных синтетических данных страхования и обосновала необходимость рассматривать знания как специально созданный продукт, а не просто источник информации. Однако в этих обоснованиях отсутствовали показатели оценки, которые предоставляет данное экспериментальное исследование. Оно добавляет слой к основе, над которой работают агенты, и ставит вопрос, на который редко получаются числовые ответы: при неизменности модели, инструментов, подсказок и фактов, а также при изменении лишь структуры онтологии, как меняются точность, усилия и затраты?
Этот первый ответ вызывает возражения, поэтому весь анализ был перепроизведен на гораздо более мощной модели, чтобы выяснить, может ли деньги просто обогнать граф с плохой структурой. Это возможно. Интересна цена, а также то, что она говорит о том, какая структура стоит создавать. Как и раньше, каждое утверждение требует подтверждения.
Три формы одной истины
Область тестирования — это сфера страхования, включающая страхователей, полисы, страховые покрытия, заявки на возмещение ущерба, страховых брокеров, поставщиков ремонтных услуг, платежи и регионы. С помощью специального скрипта всё это было сгенерировано один раз, в результате чего получилось 2 435 канонических фактов, относящихся к 507 сущностям, причем все они вымышленные.
Из этой одной базы фактов проистекают три онтологии. Называть их тремя наборами данных было бы неверно; это три формы одних и тех же данных, регулируемые единым правилом: каждая версия должна переформулировать факты без добавлений и без убыли. Для обеспечения соблюдения этого правила скрипт просматривает каждую построенную графовую структуру, воссоздает факты и проверяет, что результат полностью совпадает с исходным данным. Если какая-либо версия содержит на один факт больше или меньше, чем другая, это превращает процесс в тест на полноту охвата данных. Система CI хранилища выполняет эту проверку при каждом добавлении кода в основную ветку и при каждом запросе на слияние, а также проверяет, что сохранённые данные байт за байтом совпадают с теми, что генерируются из исходных данных; эксперимент считается недействительным, если хотя бы одна из проверок не пройдена. Существует оговорка относительно справедливости: конструкции типа «Flat» и «Shaped» были разработаны без учета набора фактов, из-за чего их проверки носят субстантивный характер, тогда как нормализованный граф кодируется непосредственно на основе фактов, поэтому по своей структуре он более близок к исходным данным, чем при доказательственном подходе.
Конструкция типа «Flat» обычно первой попадает в готовую версию продукта, и в ней используются всего два типа узлов с большим объемом данных. Каждый узел страхователя хранит свои полисы и условия страхования в виде JSON-объекта в одном свойстве. Каждый узел требования таким же образом содержит информацию об агенте по урегулированию, поставщике услуг и произведенных платежах. Единственный универсальный тип ребра — related — связывает страхователей с требованиями, и это составляет всю схему. Вся информация присутствует, но находится в скрытом виде.
Нормализация, действующая в противоположном направлении, не является упрощённой моделью, поскольку учебники одобряют её. Она превращает всё в конкретные объекты: сущности становятся простыми узлами Resource, содержащими лишь их тип, каждое атрибут превращается в узел Attribute, к которому можно обратиться через универсальную связь has, а каждая связь между сущностями превращается в узел Relation с связями subject и object. На бумаге это выглядит безупречно, но для изучения любой информации требуется четыре шага.
Shaped разработан с учётом потребностей тех, кто будет им фактически пользоваться. Типы узлов имеют чётко определённую степень детализации, а каждая рёбра имеет направление, тип и название, несущее определённый смысл, такой как filed_against, assessed_by или settles. Политики указывают на застрахованных лиц с помощью поля held_by, причём то же название используется ещё и по одной особой причине: девяносто рёбер типа held_by, возникающих непосредственно из заявки и ведущих к соответствующему застрахованному лицу, позволяют сократить путь от заявки к застрахованному лицу до одного шага. Повторное использование этого названия сделано намеренно, поскольку отношение одинаково понимается с обеих сторон, и агенту не требуется дополнительный словарь. Эти девяносто рёбер имеют флаг derived, не добавляют никакой новой информации и исключаются из доказательства отсутствия потерь, поскольку представляют собой арифметические операции над уже существующими фактами.
На рисунке 1 показана одна взаимосвязь — заявка и оценивающий её агент — во всех трёх форматах. В формате «Flat» агент включается в свойство JSON заявки, и между элементами почти нет связей. В формате «Normalized» для этой взаимосвязи создаётся отдельный узел, две рёбра, а также отдельный узел атрибутов для каждого факта. В формате «Shaped» просто указывается название рёбра, и на вкладке также объясняется причина существования этого упрощённого варианта. Скрипт реконструкции подтверждает, что все три формата содержат ровно одинаковое количество фактов — 2 435.
Количество узлов позволяет оценить масштаб структуры. Одна совокупность фактов занимает 130 узлов в формате «Flat», 507 узлов в формате «Shaped» и 2 942 узла в формате «Normalized»; каждый дополнительный узел представляет собой возможный путь для дальнейшего анализа.
Конкретный пример лучше, чем описание, показывает разницу. Возьмём страховой полис, из-за которого получены эти результаты; каждый вариант хранит его по-своему:
На рисунке 2 стратегия P-7009 берется непосредственно из сохранённых файлов онтологии с помощью скрипта отрисовки рисунков — тех же файлов, которые были загружены в Cosmos, поэтому на нём точно показано, по какому пути двигался агент. В режиме Flat стратегия хранится в виде строки внутри свойства страхователя: она существует, но не является вершиной и не может быть обращена к ней напрямую. В режиме Normalized она сохраняется в виде простой вершины Resource, причём все её атрибуты находятся в отдельных вершинах, расположенных на два шага дальше. В режиме Shaped хранится типизированная вершина с привязанными к ней свойствами и имеющимися у неё рёбрами с именами. Страховая премия одинакова во всех трёх случаях, однако в каждом из них она находится на разном расстоянии от исходного вопроса.
Каждая форма находится в своем собственном контейнере графа внутри Azure Cosmos DB для Apache Gremlin, и именно его исследует агент; каждый вызов инструмента превращается в операции исследования графа с использованием Gremlin в реальном времени. Генератор выдает базу фактов, загрузчик записывает её в Cosmos, а механизм загрузки сам проверяет данные: количество вершин и рёбер должно совпадать с исходными значениями, в противном случае фиксируется несоответствие, вместо того чтобы позже обнаружить неполностью сформированный граф.
Одна база данных, один слой инструментов и идентичные параметры индексации делают конструкции сопоставимыми, а также позволяют их видеть. Граф свойств ничего не скрывает. Спросите его о том, что он знает, и ответом будет сама конструкция.
В таблице 1 перечислены те же 2 435 фактов по каждой схеме, взятых из файлов графа. В формате «Flat» количество вершин превышает количество рёбер, причём пять вершин не связаны ни с чем. Формат «Normalized» однороден и не содержит текста. Формат «Shaped» обладает наилучшей связностью, а его метки используют словарный запас данной области.
Вернёмся к формату «Flat». Количество рёбер меньше, чем количество вершин, и пять узлов не связаны ни с чем; это страхователи без заявлений, и при такой структуре ничто другое в системе к ним не приводит. Это база данных графов, хранящая что-то, что едва можно считать графом. Структура всё ещё существует, но она была преобразована в 8,2 свойства на каждую вершину, поэтому она ведёт себя как текст, а не как топология. Результаты зависят от этого выбора конструкции, и база данных графов представляет это как факт, а не как мнение.
Нормализованный столбец отражает эту структуру. Это самый однородный из трех графов: примерно по одной рёбру на вершину, ничего изолированного, 1,6 свойства на узел, поскольку процедура реификации преобразует каждый факт в три одинаковых составляющих элемента, которые повторяются 2 942 раза. Структура здесь в изобилии, а лексика отсутствует — три метки вершин и три метки рёбер охватывают всю сферу страхования.
При 1,36 рёбрах на вершину граф с определённой формой обладает наилучшей связностью: восемь меток вершин и девять типов рёбер. Разница становится сразу заметной, когда от каждого графа запрашивают, какие типы объектов он содержит:
g.V().groupCount().by(label)
- В формате Flat хранятся только информация о претензии (90) и страхователе (40).
- В нормализованных отчетах указываются ресурс (507), атрибут (1834) и связь (601).
- В структурированных списках присутствуют восемь категорий: 216 — охват, 90 — претензии, 75 — полисы, 59 — платежи, 40 — страхователи, 12 — поставщики услуг, 10 — регулировщики и 5 — регионы.
Второй запрос подсчитывает количество полисов по категориям:
g.V().hasLabel('policy').count()
В таблице 2 один запрос расположен рядом с тремя ответами. Оба нуля обозначают неудачи разного типа. В плоской графике просто нет политики, которую можно было бы найти. В нормализованной графике политика существует, но не выявляется сама по себе. В плоской версии был потерян элемент; в нормализованной версии элемент сохранён, но был потерян словарь, поэтому к политике можно добраться только путём поиска, а не путём её названия. Всё это не зависит от того, как именно хранились данные: три схемы, одна база данных, один запрос.
Та же диспропорция наблюдается при оценке стоимости реалистичного вопроса. В каком городе проживает страхователь по полису, связанному с заявлением C-31020? Каждый график отвечает Larkfield, поскольку во всех графиках содержатся одни и те же факты. Различается лишь путь, ведущий к этому ответу. В графике с определённой структурой производные рёбра сокращают этот путь:
# shaped - the derived shortcut collapses the path
g.V().has('number','C-31020').out('held_by').values('city')
Для плоских и нормализованных графиков требуется вот это:
# flat - one hop, but only because claims and holders are the only two things
g.V().has('number','C-31020').in('related').values('city')# normalized - the same answer, five steps and two unwrappings later
g.V().has('value','C-31020').in('has')
.in('subject').has('kind','filed_against').out('object')
.in('subject').has('kind','held_by').out('object')
.out('has').has('attr','city').values('value')
Flat справляется с этим за один шаг, поскольку в данной схеме существуют лишь два типа элементов — требования и владельцы. Для нормализованного подхода требуется пять шагов и два этапа разбора структуры. Агент никогда не формирует эти запросы самостоятельно; он находит путь, выполняя по одному вызову инструмента за раз, и именно в этом заключается смысл эксперимента. Тем не менее запросы позволяют узнать, что именно обнаруживается и сколько этого материала имеется.
На рисунке 3 показано, что одинаковый запрос выполняется на всех трех графах в Cosmos DB Data Explorer. Независимо от того, предоставляет ли граф два метки, три метаметки или описание домена собственными словами, схемы не хранят разные данные; они хранят одну набор данных в разных формах.
На рисунке 4 в каждой графике выбирается заявка C-31020, после чего инструмент Data Explorer определяет её соседей. В плоской графике доступен только один вершин — страхователь, соединённый ребром с меткой related. Специалист AJ-09 и страховка PL-043 видны в панели свойств, но в виде текста, поэтому агент не может перейти к ним. В нормализованной графике присутствуют восемь вершин, шесть атрибутов и два отношения; ни одно из них не имеет названий на языке домена. В графике с формой имеются названия для трёх элементов: filed_against, assessed_by и held_by. Одна заявка, одна база данных, три расстояния.
Инструмент: четыре средства и квитанция
Агент используется в минимальном объеме намеренно, поскольку он не является объектом тестирования. Это простой цикл вызовов функций, работающий с развертыванием модели Microsoft Foundry в соответствии с описанием использования инструментов через API Chat Completions, приведенным в документации Foundry. Для работы используется фиксированный системный промпт, лимит в шестнадцать обработок модели на вопрос (после чего сессия прерывается), а также четыре инструмента; их подписи одинаковы во всех трех онтологиях.
На рисунке 5 показана полная структура вычислений: один ресурс Microsoft Foundry, содержащий два развертывания моделей — agent-small, работающий с gpt-5.4-nano, и agent-large, работающий с gpt-5.5, обе модели относятся к категории Global Standard. Названия и версии взяты из шаблона инфраструктуры в репозитории, поэтому за данными данными не скрывается никакая дополнительная инфраструктура.
Четыре инструмента следующие:
find_nodesищет свойства и идентификаторы узлов по подстроке, ограничивая количество результатов двадцатьюget_nodeсчитывает тип и свойства одного узлаtraverseвозвращает до тридцати соседей узла, которые можно отфильтровать по типу ребра и направлениюdescribe_edgesподводит итоги относительно того, какие ребра выходят из узла или входят в него, и сколько их каждого типа
По сути, каждый инструмент преобразуется в Gremlin в Cosmos. Функции get_node и find_nodes требуют по одному проходу — по одному чтению узла и по одному сканированию, тогда как функции traverse и describe_edges нуждаются в трех проходах, поскольку сначала они проверяют наличие узла, а затем поочередно прослеживают исходящие и входящие рёбра. Агент не записывает ничего из этого; он запрашивает узел или соседний узел и получает компактный JSON-ответ, который является стандартным форматом интерфейса производственных инструментов для работы с хранилищем графов, а также позволяет изолировать язык запросов от самой модели.
Прохождение графа — единственный способ найти ответ. Агент никогда не просматривает схему и не пишет код на Gremlin; у него есть инструкция отвечать текстом NOT_MODELED, когда в графе отсутствует необходимая информация для ответа на вопрос. Регистр имеет значение: граф с неправильной структурой требует дополнительных вызовов инструментов для обработки данных, а не одного огромного ответа, что соответствует реальному поведению бюджетов на использование инструментов. Лимит в шестнадцать ходов учитывает количество ходов в диалоге, а не вызовов инструментов; один ход может включать несколько запросов к инструментам, поэтому в самом загруженном эпизоде за шестнадцать ходов было совершено шестьдесят вызовов.
Три практических урока, полученных при работе с настоящей базой данных графов, требовавшей полной перестройки структуры. Cosmos не поддерживает скрипты с несколькими операциями, поэтому загрузка данных означает один проход по структуре на каждый запрос, а пропускная способность достигается за счёт одновременной обработки множества запросов, а не их группировки. Жёсткий таймаут в 60 секунд не позволяет команде g.V().drop() полностью удалить несколько тысяч вершин: она останавливается на полпути, оставляя частично удалённую структуру графа, поэтому очистка происходит поэтапно. У уровня без сервера также существует предел пропускной способности, из-за которого всплеск в 40 одновременных записей приводит к таймаутам, и именно поэтому как загрузчик, так и инструменты агента повторяют попытки с задержками. Всё это не является чем-то необычным, но именно это отличает базу данных графов в состоянии покоя от той, что находится под нагрузкой.
Оценивание без судьи
Оценка агентов как правило снижается на этапе классификации, поэтому именно этот этап привлекает наибольшее внимание, причем нигде не фигурируют судьи в виде больших языков моделей. Сорок вопросов делятся на четыре группы по десять вопросов каждая: запросы на получение информации по одному факту, краткие поиски с двумя или тремя шагами, вопросы, требующие длинного пути или агрегации данных из подграфа, и вопросы, на которые невозможно ответить. Скрипт генерирует их на основе базы фактов и выводит каждый правильный ответ из первоначальных данных. Оценивание происходит автоматически: число должно совпадать с вычисленным значением, строка должна его содержать, а вопрос, на который невозможно ответить, считается правильным только в том случае, если агент прямо заявляет, что не может на него ответить. Никакая онтология не оценивает себя сама, никакая модель не судит другую модель, и правильность определяется путем сравнения, а не мнением.
Поскольку агент может действовать только с помощью своих четырех инструментов, к каждому ответу прилагается полный список вызовов, которые его сгенерировали. В предыдущих измерениях маршрутизатора в качестве подтверждения использовалось поле model; здесь же в качестве такового выступает путь. Правильный ответ можно отследить шаг за шагом, а сбой показывает точку, в которой структура потеряла связь с агентом.
На рисунке 6 показана схема работы. Одна база фактов питает три структуры без потерь данных, которые превращаются в три контейнера графов в Azure Cosmos DB для Apache Gremlin; отдельная ветвь обеспечивает доступ к оракулу, который формирует каждый правильный ответ на основе тех же фактов. Агент достигает графов исключительно с помощью четырех инструментов, выполняя по одному запросу Gremlin на каждый вызов. Инструменты, циклы и вопросы остаются неизменными, в то время как структуры меняются; каждая запуск производит отчеты: информацию о вызовах инструментов, токенах, задержках и вердикт оракула.
Эта нерешаемая группа вопросов заслуживает отдельного рассмотрения. Её десять вопросов касаются информации, которую база фактов никогда не моделирует: номеров телефонов, адресов электронной почты, погоды, идентификационных номеров транспортных средств. Правильным ответом будет утверждение, что граф не может дать ответа. Агент, который выдумывает ребро вместо того, чтобы признать, что в графе его нет, демонстрирует самую опасную ошибку в этой семье систем, и почти никто её не измеряет.
Стоимость пройдения
Основная кампания была проведена на реальных графах Cosmos DB с использованием специальной инфраструктуры Microsoft Foundry, расположенной в Центральной Швеции. В ходе кампании использовались три онтологии, сорок вопросов и три полных прохождения с одной небольшой моделью, которая оставалась неизменной; в итоге было получено 360 эпизодов, 3,1 миллиона токенов и семьдесят центов. Каждый вызов инструмента соответствовал запросу в Gremlin. Вторая кампания, описанная позже, включала повторное выполнение задач с более крупной моделью в течение ещё 120 эпизодов при затратах в 7,39 доллара. Скрипт хранилища вычисляет все приведённые ниже цифры на основе зафиксированных отчётов; ни одна из них не была введена вручную.
В таблице 3 обобщены результаты кампании: использовалась небольшая модель, три прохождения, 360 эпизодов, при этом за каждым вызовом инструмента следовал запрос в Gremlin. Зелёный цвет обозначает лучший результат в каждой строке. Строки, относящиеся к ресурсам, намеренно оставлены без цвета, поскольку показатели эффективности во всех четырёх критериях минимальны, и, как покажут последующие разделы, частично именно благодаря этой экономии финансировались ответы, которые так и не были предоставлены.
Начните с учета первого ряда — числа, содержащего наименьше информации в таблице. Метод «Shaped» дал правильные ответы на 84,2% вопросов, метод «Flat» — на 78,3%, а метод «Normalized» — на 59,2%. Однако при трех идентичных испытаниях точность этих методов изменялась на 0,075, 0,150 и 0,075 соответственно, так что шестипроцентный разрыв между методами «Shaped» и «Flat» находится в пределах собственного шума; при трех испытаниях ничто не позволяет отличить эти два метода по общей точности. Преимущество метода «Normalized» в двадцать пять процентов легко преодолевает этот шум.
Это звучит хуже, чем есть на самом деле. Общий показатель кажется нечетким, потому что он представляет собой среднее значения категорий, сильно различающихся между собой, а именно это различие и является ключевым выводом:
В таблице 4 объясняется проблема с общим итогом. Формы графиков не отличаются незначительно везде; они резко различаются в каждой отдельной категории, причем каждая категория предъявляет к графику свои особые требования.
Сначала рассмотрим поиски с использованием одного факта. Значения для «формированных» данных составляют 0,967, а для «плоских» — 0,533, что даёт разницу в сорок три пункта; при этом уровень шума составляет 0,100 для первого варианта и 0,200 для второго, что свидетельствует о реальном сигнале. При двух- и трёхэтапных поисках оба варианта также достигают значения 0,967. В самом сложном случае уровень шума составляет 0,300 и 0,400, что не позволяет определить победителя.
Следовательно, эти два подхода не являются ни лучше, ни хуже. Они слабеют в разных моментах, и их сведение в одно число скрывает полезную информацию. Когда необходимо найти что-то конкретное, метод «плоских» данных терпит неудачу и продолжает её терпеть. Когда агент уже имеет точку опоры и ему нужно лишь продолжить движение, метод «плоских» данных работает так же хорошо, как и предусмотренная схема.
Метод нормализации отражает ситуацию аналогичным образом, как видно из его показателей: при поиске значение составляет 0,867, что выше, чем у метода «плоских» данных, поскольку каждый элемент является реальным вершиной; затем при увеличении длины пути значения снижаются до 0,467 и 0,133. Этот метод способен найти что угодно, но не может завершить поиск.
Как каждый метод терпит неудачу
Эти модели отличаются способом и местом возникновения сбоев. Каждая из них решала по тридцать вопросов три раза, в общей сложности девяносто эпизодов; группировка ошибок по типам сбоев позволяет выявить механизм их возникновения.
В таблице 5 представлена классификация ошибок, допущенных в ходе этих девяноста эпизодов. Агент «Normalized» исчерпывает свой лимит попыток; агент «Flat» останавливается рано и с уверенностью по вопросам, на которые база данных могла бы дать ответ.
Двадцать два из девяноста эпизодов, в которых участвовал «Normalized», то есть примерно четверть, заканчивались тем, что лимит попыток исчерпывался, а агент все еще продолжал работу. «Flat» редко так поступал: он останавливался рано и уверенно, отклоняя восемнадцать вопросов, на которые ответы уже имелись в базе данных. Одна модель истощает свои ресурсы, а другая просто прекращает работу.
Полный сбой происходит более резко, и следы указывают на механизм, которого никто не ожидал. Вот два реальных примера. В обоих случаях требуется доплата по полису P-7009, и они отличаются лишь тем, какая схема стоит за используемыми инструментами:
flat shaped
find_nodes "P-7009" -> 1 hit: find_nodes "P-7009" type=policy
policyholder:PH-05 "Ivo Renner" -> 1 hit: policy:PL-009 "P-7009"
find_nodes "7009" -> 1 hit get_node policy:PL-009
find_nodes "P-7009" type=policy -> 0 -> premium 750
find_nodes "P-7009" type=policyholder -> 1 hit
ANSWER: NOT_MODELED ANSWER: 750
В структурированной графике достаточно двух запросов. Запрашивается полис по номеру, получается соответствующий вершине, с неё считается стоимость страховки — и всё готово.
В плоском графике ситуация иная. Первый поиск вернул вершину, так же как и второй. Третий запрос с параметром type=policy ничего не нашёл, поскольку такой метки нет в этой схеме. Четвёртый запрос с параметром type=policyholder принёс результат. Таким образом, агент по типу нашёл именно ту вершину, которая содержала ответ, но всё равно заявил о отсутствии данных.
Данные о страховке находились внутри этого вершины, в одном из свойств, в одном вызове функции get_node оттуда. За десять неудачных случаев поиска данные о страховке были найдены в соответствующей вершине пятнадцать раз, но функция get_node над ней не выполнялась ни разу. На вершине была помечена информация «Иво Реннер» — имя человека. В остальных неудачных случаях метка относилась к одному из двух других страхователей, никогда не к самой страховке, и имя человека не давало никаких подсказок о том, что запрашиваемая страховка находится внутри.
В этом и заключается особая опасность скрытия объекта в структуре графа — база данных графов позволяет его обнаружить, но данные остаются неразличимыми. Они индексируются, возвращаются в результате запроса и присутствуют в контексте агента, однако не соответствуют никакому из использованных для поиска имён.
Процесс нормализации происходит публично и стоит дорого. Чтение одного атрибута подразумевает обработку узла Attribute, а следование одной связи — обход через узел Relation. В столбце «Токены» показана стоимость: 13 701 за каждый вопрос против 7 176 для форматированного варианта, а также 12,15 вызовов инструментов против 7,24. В 25 из 120 эпизодов был превышен лимит в 16 шагов, тогда как у форматированного варианта — 3 эпизода, а у плоского — 2; самый сложный вариант показал показатель 0,133. В графе не было ничего, чего бы не хватало. Агент просто не успевал дышать до конца предложения.
Самый дешевый вариант действительно стоит меньше всего, хотя это и не комплимент. Вариант «Flat» обходится в 0,109 доллара за сто вопросов против 0,165 доллара у варианта «Shaped», причем при учете точности он все равно выигрывает: 0,14 доллара за сто правильных ответов против 0,20 доллара. По этим показателям вариант «Flat» действительно дешевле в использовании. Однако цена не покрывает те восемнадцать ответов, которые он отклонил. Быстрое прекращение работы обходится недорого, но небольшая сумма при низком лимите не является экономией, чего никогда не покажет столбец с затратами.
Парадокс отказа
При рассмотрении вопросов, на которые можно ответить, лучший и худший варианты меняются местами среди тех, на которые ответить невозможно. Вариант «Flat» правильно отклонил все тридцать неразрешимых вопросов, что является единственным идеальным результатом в таблице. Вариант «Shaped» показал результат 0,933, а нормализованный результат — 0,900; его ошибки были связаны с истечением времени на ответ, а не с выдумками.
Если рассматривать этот ряд по отдельности, он показывает равномерность. Однако при учёте количества ложных отказов порядок меняется: группа с наилучшим показателем отказов пропустила восемнадцать вопросов, на которые могла ответить, тогда как группа с худшим показателем отказов — тринадцать. Равномерность не способствует лучшему выявлению отсутствия ответов; она склоняется к их объявлению, и эта тенденция, которая работает при невозможных к ответу вопросах, терпит неудачу при возможных к ответу. Показатель отказов без сопутствующего показателя возможности ответа приводит к созданию самой нечёткой диаграммы, которая только возможна.
Результат, противоречащий концепции дизайна
Один из результатов противоречит формату дизайна, предпочтительному в эксперименте, а вторая кампания усугубила эту ситуацию. В формате «shaped» существует лишь один вспомогательный механизм: held_by, который напрямую связывает заявку с её страхователем. По показателю «заявка — город страхователя» этот формат показал значение 0,83, тогда как нормализованный вариант — 0,33; при этом вариант «flat» достиг 0,92 без использования каких-либо вспомогательных механизмов, поскольку в данной схеме имеются только заявка и страхователь. Результат, полученный при использовании формата без дополнительных элементов, нельзя приписать самим этим элементам.
Хуже того, отсутствие удобных сокращений сказалось именно там, где это было ожидаемо. При подсчёте различных видов покрытия в рамках полисов владельца на предположительно хорошо спроектированной графике результат составил 0,17, а на плоской графике — 0,67, что позволяет объединить их в одно читаемое свойство. Общая сумма выплат по претензиям владельца составила 0,33. При агрегации данных в подграфике предлагаемый дизайн проигрывает дизайну, называемому «сломанным». Денормализация — это не компромисс перед лицом хорошего дизайна, а его часть; к тому же формированный график применял свои принципы слишком осторожно именно там, где это было необходимо из-за объёма работы.
Выход через использование более сложной модели
Затем полная сеть была запущена во второй раз на гораздо более крупной модели, и ответ на основной вопрос появился благодаря её неожиданному поведению. Изначально предполагалось, что небольшая модель на хорошо структурированной графике превзойдёт крупную модель на плохо структурированной. Этого не произошло. В этое сравнение входят только те вопросы, на которые можно ответить, поэтому отказы по неразрешимым вопросам не могут улучшить рейтинг ни одной структуры. Каждая строка, относящаяся к небольшой модели, содержит девяносто эпизодов, полученных в ходе трёх проходов, а каждая строка, относящаяся к крупной модели, содержит тридцать эпизодов, полученных за один проход.
Таблица 6 ограничивается только теми вопросами, на которые можно ответить, поэтому правильные отказы не могут сделать структуру, склонную к отказам, более привлекательной.
Большая модель без проблем считывает скрытые свойства. Она ответила на все тридцать вопросов, предназначенных для оценки, включая те, которые касались элементов, преобразованных схемой в текст, а восемнадцать ложных отказов, мешавших работе маленькой модели, исчезли. Честный результат оказался не тем, которого ожидали все.
Недостаточно хорошо структурированная онтология может компенсировать свои недостатки. Стоимость составляет примерно четырнадцать раз больше затрат на один вопрос: большая модель при использовании плоской схемы стоит 1,90 доллара за сто вопросов, а маленькая модель — тринадцать центов. Если сохранить плоскую схему и обновить только модель, работающую на ней, сумма расходов будет в двадцать раз выше, чем при использовании той же маленькой модели на структурированной схеме.
Такой результат более полезен, чем прогнозируемый, с учетом того, к чему он приводит. С использованием модели границ и задач, требующих ответа, вопрос формы перестал быть проблемой корректности и превратился в проблему затрат: как вариант «плоский», так и вариант «сформированный» давали ответы на все тридцать вопросов, и только стоимость разделяла их. При использовании небольшой модели форма сама по себе определяла корректность. Следовательно, хорошо спроектированная онтология обеспечивает меньшее качество, чем возможность использования дешевой модели. Плоская структура связывает слой знаний с бюджетом модели и функционирует только до тех пор, пока продолжается оплата достаточно большой модели, способной обрабатывать ее для каждого вопроса бесконечно.
Во всех четырех категориях порядок результатов более четкий, чем это позволяет предположить подход, основанный исключительно на наличии ответов. При использовании крупной модели вариант «сформированный» показал идеальный результат 1,000 во всех категориях, включая ту, где ответы были невозможны. Вариант «плоский» достиг 0,950, а нормализованный результат составил 0,825. Деньги лишь частично обеспечивают корректность, а стоимость остается неизменной.
Чему нас научил процесс перепроверки в вопросах осторожности
Результаты перепроверки (тот же массив данных, те же вопросы, инструменты, читающие файлы вместо Cosmos) принесли самые тревожные выводы проекта, и они связаны с полученной графикой. Когда агента спросили о погоде в день происшествия, которую онтология намеренно не моделирует, он ответил «ущерб от града». Агент нашел свойство cause заявки и представил его как погодные условия. В то время это было зарегистрировано как наиболее опасный вариант дизайна, приводящий к сбою, при этом отмечалось, что речь идет лишь об одном случае из одной серии проверок, о наблюдении, а не о измерении, и что это не является основанием для формулировки закона.
Повторная обработка на реальной инфраструктуре оказалась правильным решением. В ходе проведенного тестирования структурированный граф корректно отклонил все десять вопросов, на которые большие модели не могли ответить, тогда как на плоском графе появилась вымышленная ответная информация, на которую на тот же вопрос был дан ответ «град». Модель, вопрос и «ловушка» были идентичны; отличалась лишь форма, в которую попадал граф.
Следовательно, вывод заключается не в том, что сложные графы способствуют вымышлению ответов. Атрибут причина с значением «ущерб от града» будет соблазнять любую модель, задаваемой вопросы о погоде, независимо от места её хранения, причем форма, в которую попадает граф, меняется при каждой обработке. Это более скромное утверждение, чем то, которое почти было сделано, и именно его подтверждают имеющиеся доказательства. Это также означает, что риск не зависит от формы графа: если граф содержит поле, которое выглядит как ответ на какой-то вопрос, на который он на самом деле не отвечает, какая-нибудь модель где-то всё равно предоставит этот ответ.
Нормализованная форма у обоих моделей
Показатель нормализации в целом снизился у обоих моделей. У меньшей модели он оказался самым низким, а у большей модели он всё ещё составлял 0,867 при ответах на вопросы, причём стоимость её работы составляла 9,31 доллара за сто запросов — почти в пять раз больше, чем у модели с плоской кривой на том же уровне, к тому же она семь раз заканчивала работу до истечения времени. У модели с более крупными ресурсами ситуация не улучшилась, поскольку её проблемой никогда не было понимание текста — проблемой была дистанция: пятнадцать вызовов инструментов на вопрос против 8,3 у модели с нормализованной формой, причём последняя никогда не ошибалась в интерпретации данных.
Формат с нормализацией не потерпел поражений во всех случаях, и именно эти исключения дают наибольший урок. При поиске по одному факту формат с нормализацией показал результат 0,867 против 0,533 у формата «плоский»; при двух вопросах, где формат «плоский» не справился, формат с нормализацией явно оказался лучше: 0,83 против 0,17 для показателя страховой премии и 0,83 против 0,33 для показателя специализации поставщика. Метод реификации крайне дорог, но ничего не скрывает. Каждая сущность является вершиной, поэтому каждую сущность можно найти.
Вот краткое резюме аргумента: каждый неэффективный формат сохранял лишь половину проблемы и отбрасывал другую половину. Формат «плоский» сохранял расстояния, но терял возможность точного определения адреса; формат с нормализацией сохранял возможность точного определения адреса, но терял расстояния. Каждый из форматов конкурирует в той области, которую он сохраняет, и бесполезен в остальной.
Shaped не является компромиссом между этими двумя подходами. Он показывает значение 0,967 в диапазоне, превосходящем значение flat, и также 0,967 в диапазоне, превосходящем значение normalized, тем самым отвергая необходимость такого компромисса. Именно в этом и заключается его преимущество, но один единственный показатель точности полностью скрывает его.
Задержка при работе с реальной базой данных
Задержка — это показатель, который невозможно было оценить с помощью кросс-проверки. При работе с файлами время выполнения каждого запроса сильно варьировалось даже при одинаковых проходах: одна и та же операция могла занимать 1,17 секунды при одном проходе и 4,21 секунды при другом, поэтому никаких данных не было зафиксировано, поскольку различия в работе сервиса превосходили различия в структуре данных. При работе с Cosmos ситуация более упорядоченная, причем по довольно очевидной причине.
В таблице 7 показано время выполнения каждого вопроса: оно четко различается между разными форматами данных и остается стабильным внутри каждого из них; при этом время выполнения каждого запроса к инструменту одинаково для всех трех форматов, что позволяет рассматривать эту таблицу как отражение количества запросов к инструменту в секундах.
В рамках любого одного варианта максимальная разница составляет семь секунд, тогда как разница между уровнем «равный» и уровнем «нормализованный» достигает почти пятидесяти секунд. На обработку нормализованного вопроса уходит в два с половиной раза больше времени, чем на обработку вопроса с уровнем «равный». Последняя колонка снижает значимость этих данных: при каждом вызове все три варианта занимают примерно одинаковое время — от 6,2 до 7,4 секунд, независимо от схемы. Следовательно, это не является независимым выводом. База данных способствует единообразию, поскольку время выполнения операций в Cosmos предсказуемо, в отличие от ситуации с локальными словарями, и именно это позволяет вообще предоставлять статистические данные.
Из этого следует один практический вывод. Поскольку задержка при каждом вызове остается примерно постоянной, наборы форм в онтологии определяют время ответа так же прямо, как и стоимость токенов, причем этот показатель можно оценить ещё до создания системы, подсчитав количество шагов в процессе обработки.
Принципы, каждый из которых сопровождается доказательством
При описании проектирования онтологий обычно приводятся принципы, которые считаются вопросом вкуса. Большинство из приведённых ниже принципов сопровождаются номером, указывающим на их порядок, а те, у которых такого номера нет, об этом упоминают.
Любой элемент, о котором можно задать вопрос, должен считаться вершиной. Если нужно выгравировать один принцип над дверью, пусть это будет именно он. В плоской модели каждая стоимость страховки и специализация поставщика хранятся с индексацией в той же базе данных, что и все остальное, но небольшая модель с трудом их находила: стоимости страховки находились с вероятностью 17%, а специализации — 33%, тогда как в модели с формированием профилей эта вероятность составляла 100% и 83% соответственно. Полный диапазон значений находится в пределах от 0,533 до 0,967. Скрытие объекта внутри свойства другого объекта не делает его труднодоступным; это приводит к тому, что законный вопрос о нем возвращается под другим названием, что агент воспринимает как доказательство отсутствия данного объекта. Метод пересечения добавляет дополнительное условие, поскольку модель границы находит их все. Скрытие не является абсолютным барьером — это лишь «налог», который необходимо уплатить на определенном уровне модели.
Степень детализации представляет собой своего рода бюджет, который быстро исчерпывается из-за процессов реификации. Каждый добавленный узел ради чистоты схемы влечёт за собой дополнительные затраты при каждом запросе. По сравнению с форматированными данными, нормализованные данные требовали в 3,7 раза больше вызовов инструментов для поиска одного факта, в 2,3 раза больше — для кратких просмотров, и в четыре раза больше токенов при обработке длинных путей; к тому же в 25 из 120 случаев был достигнут лимит количества операций, тогда как при использовании других методов таких случаев было всего три. Модель, стоимость одного токена вводных данных которой была в 25 раз выше, позволила улучшить качество ответов с 0,489 до 0,867. Это действительно значительное улучшение, но оно стоило 9,31 доллара за сотню запросов, что почти в пять раз больше, чем стоимость той же модели при использовании обычного формата. Расстояние между данными никогда не бывает дешёвым, независимо от бюджета.
Точки входа — это архитектура, и они в значительной степени зависят от модели. Каждый вопрос начинается с какого-либо имени или числа, и результат первого вызова инструмента определяет, будет ли агент выполнять действия или начнёт догадываться. Для небольшой модели этот вызов возвращал пустой результат в 10% случаев с формированными сценариями, 26% — с плоскими сценариями и 53% — с нормализованными сценариями; в этих случаях поиск завершался на вершине Attribute, а не на сущности. Для передовой модели результат никогда не был пустым, независимо от формы сценария. Следовательно, потерянный первый ход — это не только свойство графа; это то, что происходит, когда более слабая модель сталкивается с точкой входа, которой она не ожидала. Создавайте структуры для модели, которая будет использоваться в производстве, а не для той, что применяется в тестировании.
Целенаправленно используйте денормализацию и признавайте это, когда результаты расходятся. Один из используемых упрощений — held_by — был применён в надежде на эффективность на пути от заявки к владельцу. На этом пути он показал результат 0,83 против 0,33 у нормализованного варианта, однако без упрощений он дал результат 0,92 по тому же вопросу, поэтому кредит предоставлен не был, а чистое тестирование (с учётом граничных случаев и без них) не проводилось. Отсутствие этого упрощения даёт больше информации. При подсчёте уровня покрытия различных типов политик для владельцев результат на хорошо спроектированной структуре составил 0,17, а на простой структуре — 0,67, что позволяет объединить их в одну понятную характеристику. При агрегации данных по подграфу предложенный дизайн уступил дизайну, обозначенному как «сломанный». Выбор упрощений — это часть дизайна, объём работы показывает, какие из них необходимы, и здесь было выбрано неверное упрощение, о чём свидетельствуют данные.
Ограничено распространение запросов. Поиск ограничивался двадцатью результатами, а просмотр — тридцатью, из-за чего чрезмерно связанный узел приводил к заметному увеличению количества вызовов и не к одному большому ответу. Никаких неограниченных вариантов обработки не использовалось, поэтому экономия остается неизвестной. Известно лишь то, что без ограничений затраты скрываются в размере ответа, где отсутствует показатель количества вызовов.
Сделайте отсутствие ответа заметным и оценивайте его честно. Рассматривайте категорию вопросов, на которые невозможно ответить, как требование дизайна, а не как уловку в тесте, но размещайте её рядом с категорией вопросов, на которые можно ответить. Модель Flat получила идеальную оценку 1,000 за отказы, отклонив восемнадцать вопросов, на которые могла ответить. Модель Shaped отказалась от ответов наименее часто, и два случая отсутствия ответа привели к сдаче задания, а не к выдумке какого-либо ответа. Хорошая онтология позволяет утверждению «мы не моделируем это» быть одновременно достижимым и истинным, а оценка требует наличия обеих составляющих, чтобы отличить граф, осознающий свои ограничения, от того, который не может найти собственный контент.
Названия — это API. Агент воспринимает названия элементов так же, как разработчик воспринимает сигнатуру функции, и в рамках этого эксперимента названия и структура намеренно объединяются в одну переменную под названием «дизайн». Ни одно число само по себе не подтверждает этот принцип. Очевидным следующим шагом является разделение этих двух аспектов, и говорить об этом лучше, чем утверждать то, что не было измерено.
Чем это не является
Это не тестирование производительности графовых баз данных. Все три варианта используют один аккаунт Cosmos DB, один слой инструментов и одинаковые настройки индексации, поэтому хранилище является константой, а не переменной, и ничто не сравнивает Cosmos с другими графовыми базами данных или не настраивает его. Также не утверждается, что исключительно просмотр структуры должен использоваться агентами в производственных средах для получения всех данных, поскольку нечеткие запросы без четкой точки входа требуют поиска; результаты показывают, где простой просмотр структуры имеет смысл, а где — нет. В тексте нет возражений против нормализации в транзакционных системах, поскольку нормализованная структура здесь неподходит для данного пользователя — агента, оплачивающего услуги за каждый шаг, но это не означает, что нормализация в целом неверна. Кроме того, это не сравнение поставщиков: Microsoft Foundry является константой, а не переменной, и данный метод можно применять на любой платформе с возможностью вызова функций.
Изменит ли наличие базы данных в цикле результаты? На этот вопрос требуется ответ, а не утверждение. Перед проведением тестированных кампаний те же четыре инструмента были использованы дважды — через Cosmos и через файлы, генерируемые программным модулем, причем записанные вызовы инструментов были повторно обработаны для обоих способов: всего 3 056 различных вызовов, каждый из которых представлял собой уникальную комбинацию инструмента и аргументов, сгенерированную кампаниями. Во всех случаях оба варианта реализации давали одинаковые результаты. База данных всё ещё играет определённую роль: она увеличивает задержку и количество запросов, а Cosmos требует примерно на 4% больше шагов агента по сравнению с вариантом на основе файлов, причём почти вся дополнительная нагрузка приходится на нормализованную структуру данных. Однако ответы, полученные агентом, формировались на основе структуры онтологии, а не движка, расположенного ниже, и этого достаточно для сравнения. Результаты повторных тестов хранятся в репозитории в виде скрипта.
Ограничения инструмента
Несколько ограничений перенесены из исследований роутеров. Сорок синтетических вопросов в одной синтетической области составляют небольшой инструмент для анализа. Контрасты выражены четко, поскольку формы являются архетипами, а промежуточная позиция занимает онтология производства, и именно конечные точки и были измерены. В рамках кампании с небольшой моделью было проведено три полных тестирования, и уровень шума в ней приводится во всех отчетах. Для сетки с большой моделью было проведено лишь одно тестирование, поэтому только ее насыщенные результаты — тридцать правильных ответов из тридцати по двум формам — могут считаться достоверными. Разница в два вопроса внутри этой сетки считается единичным случаем, и ничего не выводится на ее основе. Также были сравнены только одна небольшая и одна большая модели, поэтому кривая их сравнения остается неизмеренной.
Проверка кода перед выпуском выявила два недостатка в этом инструменте. Во-первых, когда запрашиваемый тип ребра отсутствует в графе, функция traverse возвращает пустой список соседей, что невозможно отличить от узла, у которого действительно нет соседей. Агент совершил 112 таких вызовов в ходе кампаний, и девять из двадцати двух ложных отказов в нормализованном графе связаны с этим явлением; скрипт анализа учитывает оба случая. Разница в результатах сохраняется, поскольку инструмент shaped совершил наибольшее количество таких вызовов, но отклонил наименьшее количество запросов. Тем не менее, когда инструмент отвечает «здесь ничего нет» вместо указания «такого типа ребра не существует», это создаёт путаницу; честным решением будет указание имеющихся типов с указанием ошибки. Во-вторых, доказательство без потерь сравнивает восстановленные факты, поэтому оно не может учитывать ребра, не содержащие собственных фактов, то есть связующие ребра в инструменте flat и полученные через упрощения ребра в shaped. Сейчас происходит вторая проверка, которая подтверждает соответствие этих рёбер изложенным фактам и выявляет случаи удаления или неверного указания для каждого из них. Кампании проводились до появления этой проверки, поэтому гарантии во время их выполнения не существовало.
Форма представляет собой системный промпт
Много усилий вкладывается в слова, помещаемые перед моделью, но почти никаких — в структуру знаний, лежащих в её основе. Для агента, использующего инструменты, онтология является промптом: она определяет возможные действия в мире, описанные типами узлов и названиями рёбер, и обрабатывается по одному вызову инструмента за раз. Её необходимо проектировать с учётом реального пользователя.
Вспомогательные материалы хранятся в репозитории кода экспериментов: база фактов, три онтологии, доказательство отсутствия потерь данных, вопросы, оракул, описание агента и все квитанции о кампаниях. Любой, кто сможет сформулировать ту же истину по-четвёртому способу и превзойти эти структуры в решении тех вопросов, которые стали причиной их неудачи, внесёт что-то значимое в сравнение.
Чтобы ознакомиться с информацией о используемых компонентах, соответствующая справочная документация охватывает Azure Cosmos DB для Apache Gremlin, вызов функций с использованием моделей Microsoft Foundry, а также REST API Azure Retail Prices, который предоставляет цены за токен, лежащие в основе показателей затрат.