Строительство · ИИ
Prokta
Разбор тендерной документации для коммерческого отдела генподрядчика: на входе архив файлов, на выходе отчёт по условиям со ссылкой на страницу для каждого пункта.
- Роль
- Бэкенд, обработка документов, ИИ-ассистент
- Срок
- 9 недель
- Стек
- Python · Qdrant · OpenAI API
Что изменилось
- 2,3 часа → 14 минут
- в среднем на первичный анализ тендера: от загрузки архива до отчёта по условиям. Разброс был от полутора до четырёх часов.
- +37%
- к тому, сколько тендеров успевает разобрать тот же коммерческий отдел. Людей в нём не прибавилось.
- 22% → 8%
- доля тендеров, отклонённых уже после подробного изучения, — после потраченных на них часов.
- 91%
- критичных условий из контрольной выборки система нашла сама. Оставшиеся 9% ищет человек.
Что не изменилось — документооборот и CRM: обе системы остались на местах, ничего из них не вытеснено. И решения система не принимает: она собирает условия со ссылками, а «идём или не идём» говорит коммерческий директор.
Что было до
В коммерческий отдел приходило от 180 до 250 тендеров в месяц, а в одном тендере — от сорока до шестисот страниц документации. Первичный анализ занимал от полутора до четырёх часов: специалист открывал файл за файлом и искал условия, из-за которых участвовать не стоит, а лежать они могли на любой из этих страниц. Пока он читал один тендер, приходили следующие.
- От 180 до 250 тендеров в месяц проходило через отдел, и каждый нужно было хотя бы открыть: пока тендер не прочитан, неизвестно, стоит ли он участия.
- От сорока до шестисот страниц в одном тендере. Что именно пришло, видно только изнутри документов, поэтому день нельзя было планировать по числу тендеров.
- Первичный анализ занимал от полутора до четырёх часов — и это только чтобы понять, о чём тендер, до всей работы по подаче.
- Около 22% тендеров отклонялись уже после подробного изучения, причём из-за условий, которые можно было найти в самом начале. Это часы, потраченные на тендеры, в которых компания в итоге не участвовала.
Что сделали
Один вход для пяти форматов: PDF, DOCX, XLSX, сканы и ZIP-архивы распаковываются, конвертируются и распознаются в страницы одного вида, у каждой из которых есть адрес.
Модуль на раздел вместо вопросов: требования, сроки, штрафы, оплата, обеспечение, лицензии и объёмы извлекаются по отдельности, каждый своим запросом.
Ссылка обязательна: за каждым утверждением стоит документ и номер страницы, а там, где два файла расходятся, показаны оба места.
Результат
Тендер, на который уходило от полутора до четырёх часов, разбирается за четырнадцать минут: система распаковывает архив, приводит файлы к одному виду и собирает отчёт по разделам — требования к участнику, сроки, штрафы, оплата, обеспечение, лицензии, технические объёмы, необычные условия договора и противоречия между документами. Каждое утверждение подписано документом и страницей, поэтому проверить его — значит открыть эту страницу, а не перечитать тендер. Доля тендеров, отклонённых уже после подробного изучения, упала с 22% до 8%, а решение об участии по-прежнему принимает коммерческий директор.
Кто заказчик
Генеральный подрядчик; система сделана для его коммерческого отдела — того, что решает, в каких тендерах компания участвует. Через отдел проходит от 180 до 250 тендеров в месяц, и по каждому нужно сказать «идём» или «не идём».
Тендеры приходят разного размера: в одном сорок страниц, в другом шестьсот, и заранее неизвестно, в каком из них лежит условие, из-за которого участвовать нельзя. Примерно каждый пятый отдел отклонял уже после подробного изучения — то есть после потраченных на него часов.
Задача
- Как ставил заказчик
- «Поиск по PDF через нейросеть»: загрузить документы и спрашивать их словами, вместо того чтобы листать файл за файлом.
- Как задача выглядела после разбора
- Поиск отвечает на вопрос, а вопроса у коммерческого директора нет: что именно спрятано в шестистах страницах, заранее не знает никто. Нужен был разбор — требования к участнику, сроки, штрафы, оплата, обеспечение, лицензии, необычные условия договора, объёмы, противоречия между документами и оценка привлекательности, всё сразу и через несколько минут после загрузки архива. И каждое утверждение со ссылкой на документ и страницу.
Почему нельзя было в лоб
Мешал не объём. Мешало то, чем оказались эти документы: пять форматов на входе, одно условие сразу в нескольких файлах и вопросы, которых никто не задаёт вслух.
- Пять форматов на входе
- PDF, DOCX, XLSX, сканы и ZIP-архивы, причём архив мог содержать любое из перечисленного. Прежде чем к документу можно применить хоть что-нибудь, его нужно распаковать, конвертировать и распознать — это отдельный конвейер, а не шаг предобработки.
- Сорок страниц или шестьсот
- Сорок страниц ещё можно отдать модели целиком, шестьсот — уже нет. Один и тот же путь обязан работать и на том, и на другом, поэтому в основе поиск по фрагментам, а не чтение документа за один заход.
- Одно условие в нескольких файлах
- Срок, штраф или требование к участнику встречались сразу в нескольких документах и разными словами. Значит, ни один файл нельзя объявить источником правды, а найденное в одном месте — считать ответом, пока оно не сверено с остальными.
- «Найди всё важное» — не запрос
- Спросить, какой в тендере срок гарантии, можно. Спросить, что здесь опасного, нельзя: у этого вопроса нет формы, по которой ищут. Поэтому список того, что нужно достать, задан заранее и извлекается по пунктам, а не спрашивается.
- Номер страницы должен пережить конвейер
- Ссылка обязана уцелеть после распаковки, конвертации и распознавания. Значит, адрес — файл и страница — присваивается на входе и едет вместе с каждым фрагментом до самого отчёта: назначить его позже уже не из чего.
- Десятый пункт — не факт из документа
- Девять пунктов отчёта извлекаются со страниц. Десятый, привлекательность тендера, извлечь нельзя: это вывод. На нём система и останавливается — собирает основания, а участвовать или нет, решает человек.
Как шла работа
- 01
Конвейер приёма
Недели 1–2Распаковка архивов, конвертация DOCX и XLSX через LibreOffice в безголовом режиме, OCR для сканов, оригиналы в объектном хранилище. Здесь же каждая страница получает адрес — файл и номер, — который дальше не меняется.
- 02
Структура и поиск
Недели 3–4Документы разбираются на разделы и фрагменты, фрагменты ложатся в векторный индекс. Поиск по смыслу нужен ровно затем, что одно условие в двух файлах записано разными словами: по словам находится одна формулировка из двух.
- 03
Извлечение по разделам
Неделя 5У требований к участнику, сроков, штрафов, оплаты, обеспечения, лицензий и технических объёмов появился свой модуль, свой запрос и своя форма ответа. Модуль возвращает не текст, а поля со ссылками на страницы.
- 04
Сравнение и противоречия
Неделя 6Извлечённое из разных файлов сводится по смыслу и сравнивается: один срок против другого, одна сумма против другой. Расхождение система не разрешает сама — показывает оба места и обе ссылки, потому что выбрать одно из них значит решить за коммерческого директора.
- 05
Ассистент и отчёт
Неделя 7Агент собирает результаты модулей в один отчёт: разделы, найденные условия, противоречия и оценку привлекательности. Там же вопросы к загруженному тендеру словами — то, с чего заказчик начинал просьбу.
- 06
Проверка на архиве
Недели 8–91 200 старых тендеров — архив, который отдел уже разобрал руками, — прошли через систему. Две недели ушли на сверку с контрольной выборкой: 91% критичных условий система нашла в ней сама, остальное осталось за человеком.
Технические решения
Конвейер собран из трёх частей, и порядок между ними важнее каждой: Python держит конвейер документов, Qdrant отвечает за поиск по смыслу, модели за OpenAI API превращают найденное в поля отчёта.
Приём отдельно от разбора
Распаковка, конвертация и распознавание — этап со своим результатом: страницы одного вида, у каждой файл-источник и номер. Дальше по пути уже неизвестно, пришла страница из DOCX, скана или таблицы, а сорвавшийся OCR на одном файле не уносит с собой весь тендер.
Адрес страницы — обязательное поле
Документ и страница присваиваются на входе, едут с фрагментом через индекс и модель и попадают в отчёт. Утверждение без источника в отчёт не идёт: непроверяемая строка в разборе тендера хуже, чем её отсутствие, — на неё сошлются.
Поиск по смыслу, а не по словам
Фрагменты лежат в Qdrant потому, что одно условие в двух документах сформулировано по-разному, а нужны оба вхождения. Поиск возвращает не лучший ответ, а все места, где условие встречается: сравнить их — следующий шаг.
Модуль на раздел вместо одного запроса
У каждого раздела отчёта свой модуль, свой запрос и своя форма ответа. Один общий запрос на всё выдаёт связный текст и молча теряет пункты; модуль, который ищет только штрафы, либо находит их, либо нет, и это видно.
Противоречия показываем, а не разрешаем
Если два документа одного тендера называют разные сроки, система не выбирает правильный: она ставит их рядом и даёт две ссылки. Разрешить расхождение значит решить, какому документу верить, а это уже не извлечение, а часть решения об участии.
Агент поверх модулей, а не вместо них
Итоговый отчёт собирает агент, который не читает тендер заново: он работает с тем, что вернули модули, поэтому оценка опирается на найденные условия, а не на впечатление от текста. Обращения к моделям вынесены в один слой — поставщиков в стеке два, и модуль не должен знать, к какому из них идёт.
Что осталось за рамками
Часть работы система не забирала, и граница проведена на разборе задачи, а не после запуска.
Документооборот. Файлы приходят туда же, куда приходили: система берёт архив на вход и отдаёт отчёт, а хранение и маршрут документов остались там, где были.
CRM. Её не трогали и не замещали — что происходит с тендером после решения об участии, живёт на прежнем месте.
Решение об участии. Система доводит дело до оценки привлекательности с основаниями и останавливается. Кнопки «участвовать» в ней нет.
Оставшиеся 9% критичных условий. На контрольной выборке система нашла 91%, а значит, отчёт не отменяет чтения договора — он говорит, с каких страниц начинать.
Система стоит на текущем потоке: тендер проходит через неё раньше, чем его открывает человек, и разбор по разделам со ссылками к этому моменту уже готов.
Другие проекты
Рестораны
Ostera
Сеть из 64 ресторанов: показатели пяти систем сведены в один слой, а вопрос о вчерашней прибыли задают словами и получают ответ вместе с исходными данными.
64 ресторана
считают показатели по одним определениям
NestJS · ClickHouse · OpenAI API
Страхование
Klarim
Разбирает пакет сканов по страховому обращению: находит поля в справках, фотографиях и выписках и переносит их в учётную систему.
40 → 6 минут
на разбор одного обращения
Python · FastAPI · Anthropic API
Контакты
Пришлите описание задачи
Ответ с объёмом работ, сроками и оценкой бюджета придёт в течение 24 часов.
Первый звонок — 30 минут, без обязательств с вашей стороны.