PODBOR
Streamlit-приложение, которое подбирает до трёх event-подрядчиков.
О проекте
Команда: ConstTeam
Кейс HackAlem.ai: Креативные индустрии — Firebird
Стадия: Прототип
Задача кейса: «#79-lite»: подобрать до 3 подрядчиков для мероприятия и объяснить выбор
Суть
Streamlit-приложение, которое подбирает до трёх event-подрядчиков. AI-агент с инструментами ищет проверенные альтернативы по дате, бюджету, языку или длительности.
Как устроено
CSV → проверка запроса → строгий фильтр → эвристическое ранжирование (баллы за упоминание типа мероприятия, лексические совпадения с пожеланием, запас бюджета и часов) → до 3 карточек. LLM (gpt-4o-mini или Anthropic) через function calling (find_options / try_variant / compare_dates) возвращает только evidence_id и variant_id; код проверяет ссылки и собирает текст из полей и цитат, дедлайн AI 9 с, при сбое локальный режим.
Ключевые решения
- function calling
- hard filtering
- heuristic scoring
- evidence_id/variant_id verification
- counterfactual variants search
- in-memory cache
Особенности
Защита от галлюцинаций: модель не пишет свободный текст, только ссылки на факты и проверенные варианты. Альтернатива «изменить дату» предлагается, только если на новой дате кто-то действительно проходит по всем условиям. Однако в дереве файлов есть лишь app.py и bat-скрипты: описанные в README matcher/, tests/ и docs/ в репозитории отсутствуют.
Стек
Python · Streamlit · pytest · OpenAI SDK · Anthropic SDK
Модели
gpt-4o-mini · Anthropic Claude
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-5855b967-constteam.
README
README.mdPODBOR — ваше событие, ваши условия
До трёх event-подрядчиков с объяснением различий. Если никто не подходит — проверенные изменения даты, бюджета, языка или длительности с кнопкой применения.
Кейс HackAlem AI #79-lite. Рекомендация, не бронирование. 66 профилей, 17 категорий. Данные организаторов включены в data/contractors.csv без изменений.

Запуск на Windows
- Распакуйте архив в отдельную папку.
- Для реального AI скопируйте свой существующий
.envиз старого проекта в эту папку. Либо скопируйте.env.exampleв.envи впишите ключ локально. Ключи в архив не включены. - Дважды нажмите
run.bat. При первом запуске нужен интернет для установки зависимостей и Python 3.12+. - Откроется
http://localhost:8501. Стартовый пример посчитан локально; нажмите «Найти подрядчиков» для запуска AI.
Если Python не найден, установите Python 3.12+ с python.org и включите Add Python to PATH. Для проверки используется Python 3.12.14. Скрипт создаёт отдельное окружение .venv-podbor; старую .venv копировать не нужно.
Запуск командами / macOS / Linux
python -m venv .venv-podbor
# Windows:
.venv-podbor\Scripts\activate
# macOS / Linux:
# source .venv-podbor/bin/activate
pip install -r requirements.txt
streamlit run app.py --server.address=127.0.0.1
AI и резервный режим
В .env задаются LLM_PROVIDER=openai, OPENAI_API_KEY, LLM_MODEL=gpt-4o-mini, AGENT_DEADLINE=9. Также поддерживается Anthropic через LLM_PROVIDER=anthropic и ANTHROPIC_API_KEY.
Ключ API оплачивается отдельно от подписки на чат. Наличие строки ключа не доказывает его работоспособность: реальный результат отображается после запроса. При ошибке авторизации (401) проверьте ключ в .env и перезапустите приложение. Не отправляйте ключ в чат и не коммитьте его.
Без ключа, при тайм-ауте, некорректном ответе модели или LLM_ENABLED=0 остаются подбор, объяснения из данных и проверенные альтернативы. Интерфейс явно сообщает о локальном режиме. Это не имитация вызова AI.
Защита за 10 секунд
«PODBOR показывает, кто действительно подходит под ваши условия, чем отличаются кандидаты и что можно изменить, если совпадений нет. AI выбирает аргументы и проверяет варианты; условия, факты и итоговые рекомендации контролирует код».
Подробный сценарий: docs/DEMO.md.
Пайплайн
CSV → проверка запроса → фильтр → стабильное ранжирование → максимум 3 карточки
↓
AI с инструментами и ссылками
find_options / try_variant / compare_dates
↓
проверка evidence_id и variant_id
↓
объяснения и применимые альтернативы
AI выбирает аргументы, относящиеся к конкретному кандидату, и исследует альтернативы. Состав и порядок основной выдачи определяются кодом. Модель не выдаёт свободный текст пользователю: возвращает ссылки на факты и варианты. Python собирает текст из проверяемых полей и атрибутированных дословных фрагментов описания.
Каждый variant_id связан с ПОЛНЫМ запросом и результатом фильтра. Рекомендация допускается только при наличии подходящих кандидатов и добавлении новых кандидатов относительно исходной выдачи. Комбинация «дата + бюджет» выводится вместе и применяется вместе. Нулевые, неизвестные и неисполненные варианты не могут стать рекомендациями.
Это защита от переноса цифр между кандидатами и от совета «измените дату», когда на другой дате никто не проходит по бюджету. Она не удостоверяет правдивость рекламных описаний: такие сведения показаны как слова автора профиля.
Правила фильтрации
Город и категория должны совпасть. Кандидат исключается, если занят на дату, не берёт формат, начальная цена превышает бюджет, отсутствует нужный язык или максимум часов меньше заданной длительности. Язык и часы необязательны.
- Даты только 23.09–31.12.2026. Вне календаря доступность неизвестна.
- Пустой
max_hoursу 9 профилей означает неприменимость ограничения; это не 0 часов и не обещание круглосуточного присутствия. - Цена «от» не является окончательной сметой.
- Три состояния: совпадения найдены; категории нет в городе; категория есть, но никто не подходит.
synthetic,price_imputed,city_imputedвидны пользователю. Несинтетический профиль не называется «проверенным реальным подрядчиком».- При расхождении описания и структурированных полей ограничения берутся из полей; описание их не отменяет.
Ранжирование
Все баллы считаются только после строгого фильтра:
| Признак | Баллы |
|---|---|
| Тип мероприятия упомянут в описании (словарь корней в коде) | +3 |
| Лексические совпадения с пожеланием | +1 за корень, максимум +3 |
| Цена не проставлена при подготовке датасета | +1 |
| Город не проставлен при подготовке датасета | +1 |
| Разница между бюджетом и ценой «от» не менее 30% бюджета | +1 |
| Максимум часов превышает запрос минимум на 2 часа | +1 |
При равенстве — id по возрастанию. Это эвристика соответствия и полноты данных, а не объективный рейтинг качества. Синтетический флаг не даёт штрафов или бонусов. Пожелание — мягкое предпочтение, не гарантия соответствия. Отрицания «без/не/никаких…» не получают положительного лексического бонуса. AI может выбрать дословную деталь описания, но не подтверждает выполнение пожелания.
Проверки
python -m pytest -q
python scripts/run_demo.py --no-llm
# С ключом из .env — реальный прогон, расходует API:
python scripts/run_demo.py
Тесты используют исходный CSV, сценарных клиентов и настоящие SDK против локальных HTTP-серверов. Streamlit AppTest проверяет формы, примеры и применение альтернативы. Тестам не нужен API-ключ. Результаты последних проверок описаны в docs/VALIDATION.md.
Демо-примеры лишь заполняют форму. ID ответов не зашиты в алгоритм.
Ограничения
66 обезличенных профилей — не полный рынок. Ранжирование эвристическое, интерпретация пожеланий ограничена. Бюджет времени AI по умолчанию 9 секунд; доступность и скорость внешнего API не гарантируются. UI сразу показывает результат фильтра, при сбое сохраняет локальные объяснения. Повторный успешный ответ кэшируется в памяти с учётом полного каталога, запроса, модели и провайдера; максимум 128 записей.
Поиск альтернатив: минимальное увеличение бюджета на исходную дату; ближайшие даты раньше/позже в пределах календаря; снятие ограничения по языку или сокращение часов; для пустой выдачи сочетания даты и бюджета в пределах недели. Это ограниченный поиск, не доказательство отсутствия всех возможных решений.
Нет заявлений об измеренном росте конверсии или экономии времени пользователей: для них нужен отдельный пилот.
Файлы
app.py — интерфейс; assets/style.html — оформление; matcher/engine.py — фильтр и баллы; matcher/variants.py — проверяемые альтернативы; matcher/explain.py — факты и цитаты; matcher/agent.py — цикл AI и проверка ссылок; matcher/llm.py — API; tests/ — проверки; docs/ — защита и валидация.
API function calling: https://developers.openai.com/api/docs/guides/function-calling
Авторы коммитов
История коммитов
- 2026-09-23 17:51save.bat "Название проекта: Podbor"; изменение стиля и дизайна сайтаMarzhan Nurbakyt
- 2026-09-23 17:37Delete .envMarzhan Nurbakyt
- 2026-09-23 17:22save.bat "Финал: скриншот, автотесты в GitHub, ИИ-агент в заголовке"Marzhan Nurbakyt
- 2026-09-23 16:21save.bat "Интерфейс: карточки, вывод и ход работы агента; доработки по прогону на gpt-4o-mini"Marzhan Nurbakyt
- 2026-09-23 15:18save.bat "ИИ-агент: инструменты, tool use, проверка ответа, OpenAI и Anthropic, тесты", обновлены файлы под ИИ агентаMarzhan Nurbakyt
- 2026-09-23 14:34add: Основа подбора: загрузка данных, фильтрация, три исхода, ранжирование, тестыMarzhan Nurbakyt
Структура репозитория (10 файлов)
.env.example .gitignore README.md app.py check.bat demo_queries.json pytest.ini requirements.txt run.bat save.bat
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.