Smart Contractor Selection
Подбирает до трёх подрядчиков на мероприятие из анонимизированного каталога (66 профилей) по жёстким фильтрам и занятости на дату и объясняет выбор…
О проекте
Команда: Maisoncreo
Кейс HackAlem.ai: Креативные индустрии — Firebird
Стадия: Рабочий MVP
Задача кейса: «#79-lite»: подобрать до 3 подрядчиков для мероприятия и объяснить выбор
Суть
Подбирает до трёх подрядчиков на мероприятие из анонимизированного каталога (66 профилей) по жёстким фильтрам и занятости на дату и объясняет выбор, опираясь на данные профиля.
Как устроено
Streamlit-форма передаёт запрос в recommendation_core.py. Там детерминированно фильтруются город, дата (по busy_dates), формат, категория, бюджет, язык и длительность, кандидаты ранжируются по стартовой цене, затем по ID, и берутся top-3. Отдельно различаются статусы MATCHED, CATEGORY_NOT_FOUND и NO_ELIGIBLE_CANDIDATES. Слой explanation_layer.py по желанию просит OpenAI только выбрать доказательства; Python проверяет, что цитата точно есть в описании, и сам собирает текст. При сбое срабатывает circuit breaker и детерминированный fallback.
Ключевые решения
- deterministic hard-constraint filtering
- stable price/ID ranking
- exact-substring evidence validation
- circuit breaker
- deterministic fallback explanations
Особенности
Принцип «Python решает КОГО, AI объясняет ПОЧЕМУ»: модель не может добавить или переставить кандидатов, итоговый текст собирает код из проверенных полей. Три демо-пресета: DENSE, RARE и NO RESULT.
Стек
Python · Streamlit · unittest
Модели
OpenAI
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-3058b2bd-maisoncreo.
README
README.mdSmart Contractor Selection
HackAlem case #79-lite: a small, reproducible contractor-shortlisting demo built for the official anonymized catalog.
Problem
The customer already has a city contractor catalog. The useful outcome is not a longer list, but a shortlist of contractors who satisfy the request and are not busy on the event date.
Solution
The application follows one explicit pipeline:
request → deterministic eligibility → deterministic ranking → top 3 → grounded explanation → validated fallback
Python owns every hard fact: category, city, event format, budget, language, duration, availability, selection, and ordering. The optional language model can only select evidence for explaining contractors that Python has already chosen. It cannot add, remove, or reorder recommendations.
Features
- Filters by city, event date, event format, contractor category, and budget.
- Supports optional language and duration constraints.
- Excludes every contractor whose
busy_datescontains the requested date. - Returns at most three recommendations in deterministic order.
- Distinguishes
MATCHED,CATEGORY_NOT_FOUND, andNO_ELIGIBLE_CANDIDATESoutcomes. - Produces contractor-specific explanations grounded in verified fields and an exact description excerpt.
- Works offline with deterministic fallback explanations.
- Shows unobtrusive synthetic, city-imputed, and price-imputed provenance flags.
- Includes DENSE, RARE, and NO RESULT demo presets.
Architecture
app.pyloads the CSV, builds the Streamlit form and presets, calls the core, enriches selected cards, and renders Russian user-facing results.recommendation_core.pyvalidates the request, applies all hard constraints, ranks eligible records by starting price and then stable contractor ID, and returns at most three cards.explanation_layer.pyoptionally asks OpenAI to select exact description and structured evidence. Python validates that evidence and constructs the final Russian explanation. Any rejection or provider failure uses the deterministic fallback.data/contractors.csvis the local source of contractor profiles and availability data.
In short: Python decides WHO. AI helps explain WHY. Strict evidence validation and fallback prevent ungrounded model-written claims from reaching the UI.
Dataset
The repository contains the official anonymized dataset with 66 contractor profiles. Its availability horizon is 2026-09-23 through 2026-12-31; dates outside that interval are treated as unknown availability, never as free.
price_from_kzt is a starting price, not a final quote. The dataset also
contains synthetic, city_imputed, and price_imputed flags, which the UI
surfaces when applicable.
Requirements
- Python 3.10 or newer (verified with Python 3.12.1)
- Streamlit
>=1.40,<2, declared inrequirements.txt
The deterministic core and OpenAI HTTP integration otherwise use the Python standard library. No database, vector database, or OpenAI SDK is required.
Setup
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
Run
python -m streamlit run app.py
Optional OpenAI explanations
The application works without an API key. In that mode, every selected card uses the deterministic grounded fallback.
To enable optional OpenAI evidence selection in the current shell:
export OPENAI_API_KEY='your-api-key'
The default model can be overridden if needed:
export OPENAI_EXPLANATION_MODEL='your-model-name'
.env files are not loaded automatically. Never commit API keys or other
secrets. If an API request fails or its evidence is rejected, the application
automatically falls back; selection and ordering remain unchanged.
Demo scenarios
DENSE
Алматы / 2026-09-30 / корпоратив / Ведущий / 1,000,000 KZT / 6h / русский
Demonstrates a category with enough eligible candidates for deterministic ranking and the three-card limit.
RARE
Алматы / 2026-09-24 / свадьба / Ведущий церемонии / 300,000 KZT / 3h / русский
Demonstrates a rare category where only two contractors satisfy every hard constraint, so the application returns both and explains the shortage.
NO RESULT
Астана / 2026-09-28 / свадьба / Фотограф / 1,000,000 KZT / 8h / русский
Demonstrates NO_ELIGIBLE_CANDIDATES: the category exists, but no contractor
meets all requested constraints for that date.
All presets use the same application pipeline as manually entered requests; their results are not hard-coded.
Tests
python -m unittest discover -s tests -v
The current suite contains 28 passing behavioral tests covering hard filters, availability, deterministic ordering and limits, status distinctions, evidence validation, fallback behavior, and provider failure handling. Tests do not make live API requests.
Determinism and safety
- All hard constraints and availability checks run in Python.
- Ranking is stable: lower starting price first, then contractor ID as the final tie-breaker.
- The explanation layer cannot change selected IDs or their ordering.
- Model-selected structured fields are checked against the query and profile; description evidence must be an exact source substring.
- Final displayed wording is constructed in Python, not copied from arbitrary model-authored prose.
- Deterministic fallback keeps the application usable offline.
- After the first provider or validation failure in one enrichment run, a circuit breaker skips further provider calls and uses fallback for the remaining cards.
Known limitations
- Ranking intentionally uses only starting price and stable ID; semantic ranking is not implemented.
- Availability is known only within the dataset horizon.
- Data is loaded from the bundled CSV; there is no live marketplace integration or booking workflow.
- Strict evidence validation can reject otherwise useful model-selected evidence, in which case the deterministic fallback is shown.
Reproducibility
From a clean checkout:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python -m unittest discover -s tests -v
python -m streamlit run app.py
The application reads only repository data by default and does not require an OpenAI key to run or pass the test suite.
Future development
Possible extensions are semantic ranking, richer marketplace integration, booking as a separate future workflow, and support for larger catalogs.
Авторы коммитов
История коммитов
- 2026-09-23 17:35docs: add demo and architecture guidesTalAIdev
- 2026-09-23 17:10ui: localize demo labelsTalAIdev
- 2026-09-23 16:54docs: finalize submission and reproducibility guideTalAIdev
- 2026-09-23 16:36fix: harden explanation grounding and API fallbackTalAIdev
- 2026-09-23 16:01feat: add interactive contractor recommendation demoTalAIdev
- 2026-09-23 15:44feat: add grounded AI explanations with fallbackTalAIdev
- 2026-09-23 14:51feat: implement deterministic contractor matchingTalAIdev
- 2026-09-23 14:25data: add official contractor datasetTalAIdev
Структура репозитория (12 файлов)
.env.example .gitignore ARCHITECTURE.md DEMO.md README.md app.py data/contractors.csv explanation_layer.py recommendation_core.py requirements.txt tests/test_explanation_layer.py tests/test_recommendation_core.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.