Коротко: TENDER — система, которая каждый день обходит 29 международных площадок, собирает все опубликованные тендеры ООН и банков развития и показывает эксперту только те, где ему действительно стоит подавать заявку. Решение выносит языковая модель, развёрнутая на машине клиента: резюме и техзадания не уходят ни в один внешний сервис.
Клиент: независимый эксперт-консультант · Категория: парсинг · локальная LLM · Telegram-бот
Что главное в проекте?
- 300+ новых тендеров в день на площадках ООН, до эксперта доходят единицы.
- Результативность отбора 100%: в выдаче нет лишнего, разбирать нерелевантное не приходится.
- ИИ работает локально. Резюме это персональные данные, а часть техзаданий закрыта условиями заказчика, поэтому модель стоит у клиента, а не в облаке.
- Нулевая стоимость токенов: расход не растёт с числом обработанных тендеров.
- 29 источников под одним интерфейсом: агентства ООН, банки развития, порталы ЕС и ОБСЕ.
- Управление из Telegram: заявки приходят в чат, там же отклоняются, оттуда же вход в админку без пароля.
На чём собран проект?
- Парсинг:
- Python 3.12, httpx, BeautifulSoup, lxml. Для сайтов на JavaScript (Азиатский и Африканский банки) Playwright через Bright Data Scraping Browser: реальный Chrome с удалённым рендерингом, без локального браузера.
- Антибот:
- Bright Data Web Unlocker для Cloudflare и JS, Scraping Browser для полного рендеринга.
- ИИ:
- локальная модель Ollama плюс Qwen 2.5 с OpenAI-совместимым API, развёрнута на мощностях заказчика. Промпты на русском, редактируются из админки.
- Бэкенд и админка:
- Flask 3 с gunicorn, шаблоны Jinja2, авторский CSS с двумя темами и мобильной версией.
- Бот:
- aiogram 3 на long-polling, без открытых портов.
- База:
- SQLite, изолированная, без общего MySQL.
- Выгрузка:
- openpyxl для Excel, reportlab для PDF с кириллицей.
- Инфраструктура:
- nginx с собственным блоком и basic auth, systemd на четыре сервиса и таймеры, отдельный пользователь на сервере.
- Интеграции:
- API баланса Bright Data, курс Национального банка Казахстана.
Внешние ИИ-сервисы не используются вообще. Модель можно заменить без переписывания конвейера: интерфейс OpenAI-совместимый.
С чего всё началось?
Тендеры ООН это конкурсные закупки агентств ООН и банков развития: консультации, экспертиза, исследования. Объявления разбросаны по десяткам сайтов, среди них UNGM, UNICEF, ПРООН, Всемирный банк. Каждый день выходит больше трёхсот новых, и ручной обход занимает часы ежедневно.
Проблема не только в объёме. Заголовок тендера почти никогда не описывает суть: проект может называться «Управление государственными финансами», а внутри требуется эколог или местный консультант с обязательным знанием языка страны. Отсеять такое по названию невозможно, читать надо описание целиком.
Отдать эту работу облачному ИИ было нельзя. В контекст модели уходит полное резюме эксперта, а это персональные данные; часть техзаданий закрыта условиями заказчика. Поэтому модель развернули на его собственной машине.
Что реализовано?
🧠 Почему LLM работает на железе заказчика?
- Ollama и Qwen 2.5 на машине клиента: решение о соответствии тендера профилю выносится локально
- Резюме и тексты техзаданий не уходят во внешние API: ни в облако, ни в чужие логи
- Два варианта развёртывания: собственные мощности заказчика или арендованный сервер, контур приватности одинаковый
- Нулевая стоимость токенов: расход не растёт с числом обработанных тендеров
- OpenAI-совместимый интерфейс: модель меняется без переписывания конвейера
- Промпты редактируются из админки, по каждой возможности сохраняется полный лог диалога модели
🤖 Как устроены парсеры и сбор?
- 29 источников с единым интерфейсом Connector → Vacancy: агентства ООН (UNICEF, ООН-Женщины, ЮНФПА, МОМ, UNGM, ПРООН), банки (Всемирный, Азиатский, Исламский, Африканский, ЕБРР, ЕАБР, ЕФСР), ЕС и ОБСЕ (TED, ОБСЕ, МОТ)
- Пять типов протоколов под одной абстракцией: серверный HTML, REST JSON-API, Oracle Recruiting Cloud (один движок на три агентства), POST с HTML-фрагментом, sitemap-XML
- Рендеринг JS-сайтов реальным браузером там, где список собирает клиентский скрипт
- ИИ-контролёр восстановления: если вёрстка источника изменилась и парсер сбоит, модель восстанавливает поля карточки с заземлением на HTML и лимитом против лавины
- Падение одного источника не роняет прогон, работает антитроттл с паузами и дедупликация внутри источника
⚙️ Как работает конвейер обработки?
- Нормализация: даты из шести несовместимых форматов приводятся к ISO, страны из NUTS-кодов и произвольных форм к названию и региону по справочнику 249 стран ISO 3166-1
- Доопределение страны: строгая текстовая эвристика с ИИ-фолбэком при нераспознавании
- Кросс-источниковый дедуп: один тендер висит на нескольких порталах, система склеивает дубли и оставляет самую полную запись, обогащая её остальными
- Двухуровневый предфильтр: STOP-слова, CORE-слова, территориальный фильтр, язык, национальный консультант, дедлайн. Все правила редактируются в админке, журнал показывает сработавшие метками
- Отсев просроченных в двух точках: на предфильтре и повторно после загрузки деталей, потому что у банков дедлайн виден только внутри
🌍 Как работает территориальный фильтр?
- Справочник 249 стран: ISO 3166-1, русские и английские названия, коды, нормализация
- Редактируемый список разрешённых стран с поиском по всем 249
- Двойное применение: в предфильтре и повторно после решения модели
🧠 Как ИИ подбирает тендеры?
- В модель уходит полное резюме эксперта: 69 проектов, публикации, образование, языки, около 34 000 знаков, а не выжимка
- Суждение по сути роли, а не по названию: модель читает полное описание и отклоняет несоответствие
- Структурированный вердикт: да или нет, короткая причина по правилу, длинная причина описанием, резюме на русском и английском, страна, флаг наличия техзадания
- Калибровка доказана на эталонах, по каждой возможности сохраняется полный лог
- Промпты и профиль редактируются из админки с защитой от поломки
🖥 Что умеет веб-админка на 13 страниц?
- Дашборд: здоровье сервера в реальном времени, графическая воронка всех фаз, статус каждого парсера
- Финансы: расход по прогонам, прогноз на месяц по медиане, стоимость прогона и одной найденной заявки, баланс прокси с кнопкой пополнения
- Отобранные заявки с карточкой: полное описание, вложения, лог доставки, ручное отклонение с причиной и STOP-словом
- Принятые, отклонённые и журнал всех заявок с поиском и фильтром по меткам
- Карточка на каждый из 29 источников: что собирает, метод, антибот, расписание
- Редакторы STOP и SIGNAL, вкладка территории, логи, алгоритм с реальными промптами, редактор промптов, получатели, настройки
- Выгрузка списков в CSV, Excel, JSON и PDF с учётом активного фильтра
- Управление пользователями админки и вход по ссылке из Telegram
- Две темы, адаптив, мобильная версия карточками
🤖 Как Telegram-бот служит пультом управления?
- Меню с постоянными кнопками: все заявки, источники, статистика, помощь
- Автодоставка каждой новой подходящей заявки активным получателям
- Кнопка «Не подходит» отклоняет заявку прямо в чате, синхронно с админкой
- Вложения и техзадания приходят документами
- Расширенная статистика: воронка, база, балансы, эффективность
- Вход в админку без пароля по личной ссылке
🚀 Как устроены автоматизация и продакшн?
- Ежедневный конвейер по таймеру systemd: сбор, ИИ, доставка, с догоном пропущенных запусков
- Планировщик отчётов: ежечасный таймер проверяет, кому пора, промежуточные отчёты в выбранный час и еженедельный по понедельникам, по часовому поясу каждого получателя
- Ручной запуск кнопкой «Прогнать сейчас»
- Четыре сервиса в продакшне, изолированные от других проектов сервера
💳 Как ведётся финансовый учёт?
- Расход по прогонам: трафик прокси и браузера, за токены платить не нужно
- Эффективность: стоимость прогона и одной найденной заявки, прогноз на месяц
- Баланс прокси онлайн через API с кнопкой пополнения
Какой результат?
| Показатель | Значение |
|---|---|
| Новых тендеров в день на площадках | 300+ |
| Источников под мониторингом | 29 |
| Результативность отбора | 100% |
| Стран в справочнике фильтра | 249 |
| Проектов в резюме, уходящем в модель | 69 |
| Объём контекста на решение | ~34 000 знаков |
| Страниц в админке | 13 |
| Сервисов в продакшне | 4 |
| Плата за токены ИИ | нет, модель своя |
Где узнать подробнее об этом кейсе?
Полная история о том, почему заголовки тендеров врут и как мы научили ИИ читать тендеры ООН по-настоящему: читайте статью на LinkedIn.

