В данной статье хотел бы поделиться опытом участия в хакатоне Agentic Legal RAG Challenge 2026. Наша команда называется "Sparks of intelligence".
Перевод на английский
1. О соревновании
Соревнование проводилось компанией EORA AI APPLICATIONS AND SERVICES.
Задача: разработать приложение, способное с высокой точностью отвечать на вопросы по документам судов Международного финансового центра Дубая (DIFC).
Призовой фонд — 32 000 долларов. Количество участников - более 300.
Соревнование проходило в два этапа:
Этап | Время проведения | Количество документов | Количество вопросов |
|---|---|---|---|
Предварительный | 11–19 марта | 30 | 100 |
Финальный | 20–22 марта | 300 | 900 |
Организаторы серьезно подошли к выбору вопросов. Вопросы разнообразны, для каждого указан тип ответа:
boolean (да/нет)
name (имена, названия)
date
number (float)
free text (текстовый ответ)
Была разработана комплексная система оценки, включающая:
точность
скорость
расход токенов
Все метрики подробно расписаны в документации с примерами кода. Free text оценивался с помощью LLM (вероятно, нестрого — достаточно было сообщить правильные факты).
Подробнее — на официальном сайте соревнования.
2. В чем вообще сложность задачи?
Истина где-то рядом…
Скорее всего, все, кто читает эту статью, так или иначе знают о векторном поиске. Многие сталкивались со сложностями поиска в большом количестве документов.
Пример:
Допустим, нас попросили найти книгу с рецептом яблочного пирога. Обычную бумажную книгу, на полке — слышали о таких?
Если у вас на полке несколько десятков книг — вы легко найдете нужную. Будете искать что-то вроде “кулинарной книги”, “книги рецептов”. Грубо говоря, это и есть векторы.Поиск займет секунды. Если нужная книга есть — вы найдете ее, посмотрите оглавление и обнаружите рецепт. Либо убедитесь, что такого там нет.
Если у вас солидная домашняя библиотека — потратите гораздо больше времени. Но миссия выполнима.
В центральной библиотеке у вас бы не было шансов найти нужную книгу просто перебором. Потому люди придумали индексацию: по авторам, темам, году издания и т.п.
На момент начала соревнования у нас не было опыта разработки серьезных RAG-систем. Настало время разобраться.
3. Современные векторные базы и подходы к RAG
А я милого узнаю по … вектору
В процессе исследования мы познакомились с различными методами поиска в документах. Даже краткого их описания хватит на отдельную статью: от семантического чанкинга до обучения моделей с LoRA под каждый конкретный документ.
Если коротко, современные векторные базы устроены примерно так:
А) Поиск: гибридный метод, векторы + best match
Вектор содержит смысл. “Прекращение договора” и “расторжение контракта” будут иметь близкие вектора.
Однако найти, например, “в каком городе/суде рассматривали дело Джейсона против Крюгера” векторным поиском скорее всего не получится.
Б) Чанкинг: нарезка текстов на смысловые фрагменты
В некоторых источниках пишут, что хороший чанкинг — это больше половины успеха.
Если в одном фрагменте “смешались в кучу кони, люди” — вектор не будет иметь выраженной направленности. Подобрать схожие вектора (а значит и найти источник информации) будет крайне сложно.
“Наивный” подход к чанкингу — разделение текста на фрагменты по каким-то паттернам: статья 1, параграф 2, пункт 4.
Если документ имеет четкую иерархию — такой подход может сработать. Но крайне важен размер чанка. У слишком маленького чанка будет выраженный вектор, однако контекст будет потерян.
Пример:
На заседании присутствовали:
Участник 1
Участник 2
Участник 3
Если разделить по маркеру списка — каждый пункт лишится смысла.
Возможные решения (от простого к сложному):
Подход | Описание | Плюсы | Минусы |
|---|---|---|---|
Б1. Фикс. размер + перекрытие | Чанки по N токенов с перекрытием | Простота реализации | Риск разрыва контекста |
Б2. Иерархический | Большие чанки → малые; поиск по малым, контекст из больших | Сохраняет контекст + точность | Сложнее в реализации |
Б3. Семантический | Группировка по смыслу с помощью ML | Максимальная релевантность | Сложность, требование к ресурсам |
У каждого решения свои плюсы и минусы. Универсального нет.
С семантическим чанкингом разбираться не стали — времени не хватило. Варианты А, Б мы использовали.
В) Реранкер
Оценка подобия векторов по косинусному расстоянию довольно поверхностна. Нужный контекст далеко не всегда содержится в тех чанках, у которых подобие выше.
Современные подходы подразумевают использование реранкеров — специальных моделей, обученных на огромном количестве пар вопросов и ответов. Они лучше оценивают сходство.
Вместо top-k ближайших чанков, мы находим top-k*10, потом переранжируем и выбираем уже top-k.
4. Обзор двух вариантов наших архитектур
По итогам обзора разных решений, команда реализовала два варианта: более простой и более сложный.
Для обоих вариантов выбрана векторная база Qdrant + LlamaIndex, с удобными методами работы с векторной базой и абстракциями LLM. Такая связка часто встречается в проанализированных решениях.
Параметр | Решение 1 (Простое) | Решение 2 (Агентное) |
|---|---|---|
Чанкинг | По страницам + перекрытие | Иерархический + LLM-анализ |
Поиск | Гибрид + метаданные + regex | Агент-роутер → 4 инструмента |
Реранкер | ✅ | ✅ |
Сложность | 🟡 Средняя | 🔴 Высокая |
Скорость | 🟡 Средняя | 🔴 Низкая (2× вызов LLM) |
4.1 Гибридный поиск + метаданные, чанкинг по страницам
Простой как ground truth

Чанкинг выполнялся по страницам с перекрытием. Это рабочее решение, которое сразу снимало вопрос с grounding. В другом решении пришлось ставить маркеры разрывов страниц, потом удалять их. Это вызывало проблемы с появлением мелких обрывочных чанков, приходилось усложнять алгоритм. Для поиска паттернов использовались регулярные выражения. Найденные значения использовались для фильтрации.
Что сработало:
Быстрая реализация
Предсказуемое поведение
Grounding «из коробки» (чанк = страница)
Проблемы:
Regex пропускает паттерны или даёт ложные срабатывания
Жёсткая привязка к структуре документа
Изначально не загружали grounding в метаданные (позже пофиксили)
4.2 Агентная RAG система, иерархический чанкинг
99 способов … запутаться

Алгоритм чанкинга:
Предварительный анализ структуры случайной выборки документов с помощью LLM
Фиксация паттернов для разделения
Рекурсивное объединение малых чанков в большие, пока не достигнут нужный размер По факту алгоритм работал не слишком хорошо. Для разных страниц документа один и тот же паттерн разбивки работал по-разному. В итоге оставалось множество мусорных маленьких чанков, которые просто приклеивались к ближайшим без системы. Возможно, есть легкие модели для чанкинга — мы таких не нашли. Либо уже нужен семантический поиск.
Алгоритм поиска:
Аргументы и метаданные выбирает LLM исходя из контекста вопроса.
Было сделано 4 поисковых инструмента: простой поиск по метаданным, поиск точного совпадения, сравнение документов и гибридный поиск. В каждом можно фильтровать по номеру дела или закона.
Архитектура:
Агент-роутер → поисковые инструменты → агент-генератор.
Роутер получает вопрос пользователя, список инструментов с описанием и инструкции, какой инструмент для чего использовать.
Инструменты используют различные методы поиска в векторной базе (векторы, ключи, метаданные), реранкер. Выдают один или несколько текстовых фрагментов в генератор ответов. Генератор обрабатывает эти данные и выдает ответ в нужном формате.
После фикса инструменты выбирались корректно. Однако полноценно протестировать и настроить систему не хватило времени.
Что сработало:
Роутер корректно выбирал инструменты по контексту вопроса
Фильтрация по номеру дела/закона функционировала
Проблемы:
Алгоритм чанкинга нестабилен: один паттерн → разное поведение на разных страницах
Оставался «мусор» из мелких чанков, приклеенных без системы
Не хватило времени на полноценное тестирование и отладку
5. Выводы и итоги
Наша команда не может похвастаться выдающимся результатом. Однако итоги экспериментов и описание процесса могут быть интересны.
Решение 1 (простое)
На предварительном этапе
Получило максимальный (из наших вариантов) балл по точности детерминированных ответов, где указывается точное значение.
Был довольно низкий grounding. Скорее всего, ответы тогда просто брались из метаданных. Когда это исправили, grounding подрос, однако точность снизилась.
На финальном этапе
Получили точность 0.79 при grounding 0.63
Решение 2 (сложное)
На предварительном этапе
Получило самую низкую оценку точности из всех наших попыток.
Скорость была существенно ниже, из-за 2х вызовов LLM.
Низкая точность скорее всего была связана с “детскими” ошибками (например, реализовали функции с поисковыми инструментами, но не передали схему tools в агента — даже в простых случаях выполнялся гибридный поиск).
На финальном этапе
Не успели сдать решение (в последний момент пошли ошибки API, потом сдача закрылась).
К тому моменту многие ошибки были исправлены. По личным ощущениям поиск стал работать гораздо лучше.
Решение | Этап | Точность Det | Grounding | Скорость | Комментарий |
|---|---|---|---|---|---|
Решение 1 | Предварительный | 0.9 → 0.81* | 0.5 → 0.58* | 🟡 Средняя | *После фикса grounding'а точность немного упала |
Решение 1 | Финальный | 0.79 | 0.63 | 🟡 Средняя | Стабильно, но не идеально |
Решение 2 | Предварительный | 0.74 | 0.6 | 🔴 Низкая | «Детские» ошибки: не передали tools в агента |
Решение 2 | Финальный | — | — | — | — Не успели сдать (ошибки API + дедлайн) |
Надеюсь, благодаря данному соревнованию мы смогли повысить свои компетенции в части векторного поиска. На будущее постараемся учесть все ошибки.
Буду рад обсудить эти и другие подходы RAG в комментариях.
P.S. По условиям соревнования, датасет и код участников являются закрытыми. Предоставить ссылки не могу.
P.P.S. Понятно, что в такие сжатые сроки построить подобную систему практически невозможно без кодовых агентов. Однако использовать их надо осторожно. Можно доверить агенту сделать обвязку для базы, какой то API где четко задан формат входных и выходных данных. При построении каких то сложных алгоритмов, пайплайнов, даже четкая постановка задачи далеко не всегда приводит к результату. Для достижения поставленной цели агенты готовы на любые ухищрения: замена реальных методов заглушками, подстановка "магических чисел" вместо реальных данных, и даже "оптимизация" самой задачи - например использование регулярок подобранных под определенные паттерны вместо ллм. При этом все тесты проходятся идеально, и вычислить такое читерство может быть крайне сложно.
