Beyonder
Сервис подбора до трёх event-подрядчиков с воронкой отбора, объяснениями, «Планом Б» по ближайшим датам и разбором запроса из одной фразы.
О проекте
Команда: Beyonder
Кейс HackAlem.ai: Креативные индустрии — Firebird
Стадия: Доведённый продукт
Задача кейса: «#79-lite»: подобрать до 3 подрядчиков для мероприятия и объяснить выбор
Суть
Сервис подбора до трёх event-подрядчиков с воронкой отбора, объяснениями, «Планом Б» по ближайшим датам и разбором запроса из одной фразы. Всё работает без API-ключа.
Как устроено
Запрос приходит из формы или свободным текстом: правила nl_parse извлекают город, дату, формат, категорию, бюджет, часы и язык, для каждого поля показывается фрагмент, из которого оно взято. Дальше идут пул по категории и городу и последовательные фильтры (дата → бюджет → формат → язык → длительность) с подсчётом воронки и причин отказа, затем взвешенный рейтинг, где смысловое соответствие формату считается по заранее посчитанным эмбеддингам локально. Объяснения собираются по данным каталога. С ключом OpenAI или NVIDIA LLM дополнительно редактирует текст (таймаут 6 с, кэш). Эндпоинт /api/alternatives ищет даты, где подборка больше.
Ключевые решения
- rule-based NL parsing
- воронка фильтров
- взвешенный рейтинг
- предвычисленные эмбеддинги (косинусная близость)
- аудит объяснений
- LLM-редактура с таймаутом и кэшем
Метрики
Аудит объяснений: 7290 запросов (сетка город × категория × формат × дата × бюджет), 0 нарушений; demo.py: 8/8 PASS
Особенности
Смысловая оценка без ключа за счёт эмбеддингов, сохранённых в репозитории. Скрипт аудита проверяет по всей сетке запросов, что объяснения в одной выдаче не совпадают даже без имени подрядчика. В README таблица «требование DoD → где увидеть → какой тест проверяет».
Стек
Python 3.10+ · FastAPI · Uvicorn · pytest · Docker Compose · HTML/JS
Модели
OpenAI · NVIDIA API
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-774a9321-beyonder.
README
README.mdBeyonder
Подбор event-подрядчиков, который объясняет свой выбор
До трёх вариантов под город, дату, формат и бюджет — и у каждого своя причина.
Если никто не подходит, сервис говорит, что помешало и что изменить.
Быстрый старт · Как проверить · Архитектура · API · Сценарии и ответы
Кнопка «Фотографы в Алматы»: воронка отбора и три карточки с объяснениями. Запуск без ключа API.
[!NOTE] Ключ API не нужен. Без ключа работают подбор, «План Б», разбор фразы и смысловая оценка описаний: эмбеддинги для каталога и шести форматов уже сохранены в
data/embeddings.jsonи сравниваются локально. Объяснения собираются по данным каталога (метка «Объяснение по данным»); результаты ниже проверены без ключа. С ключом OpenAI или NVIDIA модель дополнительно редактирует текст объяснений — это необязательно.
Описание решения и назначение
Трек 06 «Креативные индустрии», задача «Умный подбор подрядчиков» (#79-lite). Заказчик уже выбрал тип мероприятия и видит каталог своего города; ему нужно выбрать, а не листать длинный список. Он задаёт город, дату, формат, категорию и бюджет в тенге (по желанию — длительность и язык) — формой или одной фразой.
| Что делает сервис | Как это выглядит |
|---|---|
| Три карточки, а не список | До трёх подрядчиков; у каждого «Чем выделяется» и «Почему этот подрядчик» — карточки не перепутать даже без имён |
| Честное «нет» | Воронка «8 в категории → 4 свободны → 3 в бюджете» и причины отказа по каждому кандидату |
| Подсказки с действием | «ближайший свободный день — 13 декабря», «при бюджете от 300 000 ₸» → кнопка «Применить» |
| План Б | Ближайшие даты, где подборка больше, — или прямое «смена даты не поможет» |
| Запрос одной фразой | «Нужен тамада на той 20 ноября в Астане…» → форма, у каждого поля — фрагмент текста, из которого оно взято |
| Смысловая оценка без ключа | Заранее рассчитанные векторы предложений сравниваются с одним из шести форматов мероприятия локально; порядок остаётся воспроизводимым |
| Прозрачный рейтинг | «Как посчитан рейтинг»: оценки бюджета, описания, часов, языка и качества данных и их веса |
Каталог организаторов — data/hackathon-dataset-anonymized.csv: 66 анонимизированных профилей, 13 из них синтетические
(помечены в выдаче), у части профилей оценочная цена или восстановленный город (тоже помечены). Календарь занятости —
23 сентября — 31 декабря 2026. Это подбор, а не бронирование: цены «от», доступность — по календарю каталога.
Быстрый старт
Нужны Git и Python 3.10 или новее. Ключ API не нужен.
✅ Проверено запуском с нуля 23.09.2026 (Windows 11): чистый
git clone→venv→ установка зависимостей за 56 с →scripts/demo.py—PASS: 8 ответов, 0 ошибок,pytest— все тесты проходят, аудит — «Нарушений не найдено». Docker: контейнерhealthy,demo.py8/8, тесты внутри контейнера (Linux, Python 3.12) проходят.
Инструкции по установке
Windows PowerShell
git clone https://github.com/BAITC-Hacks/hack-774a9321-beyonder.git
cd hack-774a9321-beyonder
py -3 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
macOS / Linux
git clone https://github.com/BAITC-Hacks/hack-774a9321-beyonder.git
cd hack-774a9321-beyonder
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
Если в Windows нет команды py, используйте python -m venv .venv. На macOS проверьте python3 --version.
Активировать окружение не нужно, все команды выполняются из корня репозитория.
Инструкции по запуску
.\.venv\Scripts\python.exe -m uvicorn app.main:app --host 127.0.0.1 --port 8000
.venv/bin/python -m uvicorn app.main:app --host 127.0.0.1 --port 8000
Откройте http://localhost:8000. Там же — Swagger и метаданные каталога.
Остановка — Ctrl+C. Если порт занят, используйте --port 8001. HTML через file:// не откроется: странице нужен API.
Альтернатива: Docker
Если установлен Docker с Compose, из корня репозитория запустите одну команду (одинакова в PowerShell, macOS и Linux):
docker compose up --build
Откройте http://localhost:8000. Ключ API не нужен. Для первой сборки нужна сеть, чтобы загрузить базовый образ и Python-зависимости; каталог и эмбеддинги уже входят в собранный образ. Остановка — Ctrl+C, затем docker compose down.
Порядок проверки основного сценария
В браузере — всё проверяется кнопками-сценариями над формой:
| # | Что сделать | Что вы увидите |
|---|---|---|
| 1 | Нажать «Фотографы в Алматы» | Исход «Нашли три подходящих варианта». Три карточки с одинаковой структурой фактов (цена и % бюджета, свободен, часы, языки), своей строкой «Чем выделяется» и своим объяснением. «Как посчитан рейтинг» показывает оценки факторов и веса; рядом — фактическое время ответа. Метка «Объяснение по данным» |
| 2 | Нажать «Редкая категория», затем «Нет в городе» | Флористы: один вариант и объяснение, почему меньше трёх. Лайв-бэнд в Астане: «В этом городе нет такой категории» |
| 3 | Нажать «Сравнить даты» | Подборки на 10 октября и 12 декабря рядом. Октябрьская тройка отмечена «занят 12 декабря»; под декабрьской — «Другие даты»: 13 декабря (вс) и 7 декабря (пн), по 3 варианта |
| 4 | Вставить фразу ниже в поле «Опишите мероприятие своими словами» → «Разобрать» → «Подобрать подрядчиков» | Форма заполнена, у каждого поля — фрагмент текста; совет выбрать язык «казахский» или формат «той». Подбор сам не запускается. После нажатия — один вариант: Мицури Канроджи |
| 5 | Под результатом нажать «Применить» у подсказки | Дата или бюджет подставлены, подбор повторён |
Фраза для шага 4:
Нужен ведущий на казахскую свадьбу 14 ноября в Алматы, бюджет до 800 тысяч, часов на 6
Скриншот: сравнение дат и «План Б»
В терминале — во втором окне, пока сервер работает:
.\.venv\Scripts\python.exe scripts/demo.py
.\.venv\Scripts\python.exe -m pytest -q
.\.venv\Scripts\python.exe scripts/audit_explanations.py --strict
.venv/bin/python scripts/demo.py
.venv/bin/python -m pytest -q
.venv/bin/python scripts/audit_explanations.py --strict
| Команда | Ожидается |
|---|---|
scripts/demo.py | PASS: 8 ответов, 0 ошибок, код 0. Восемь сценариев через настоящий HTTP; один сценарий — --case dense (также rare, no-category, none, december, invalid, nl, plan-b). Входы и ответы — в docs/DEMO.md |
pytest -q | Все тесты проходят. Без сети; LLM-тесты подменяют SDK |
audit_explanations.py --strict | Запросов: 7290 … Нарушений не найдено. — вся сетка «город × категория × формат × дата × бюджет»: карточки одного запроса не совпадают ни целиком, ни первым предложением, ни без имени и номера профиля; нет общих фраз; не больше двух предложений |
Если сервер запущен на другом порту: scripts/demo.py --base-url http://127.0.0.1:8001.
Соответствие Definition of Done
| Требование задачи | Где увидеть | Автоматическая проверка |
|---|---|---|
| До 3 карточек: имя, категория, город, цена, 1–2 предложения объяснения | Шаг 1 | demo.py dense, tests/test_dod.py |
| Объяснения не взаимозаменяемы: без имён не перепутать | Шаг 1 | test_explanations_remain_distinct_without_names, аудит: 7290 запросов, 0 нарушений |
| Занятый на дату подрядчик не попадает в выдачу | «Не попали — почему» | test_busy_contractors_never_shown |
| Тот же запрос — тот же порядок | Повторить шаг 1 | test_determinism_and_card_contract |
| Две даты — разная выдача, видно, что дело в занятости | Шаг 3 | test_two_dates_change_results_with_busy_reason, demo.py december |
| Меньше трёх — показать, сколько есть и почему | Шаг 2 | test_rare_category_explains_partial_result, demo.py rare |
| Три исхода различимы | Шаги 1–2, бюджет 1 ₸ | test_outcomes, demo.py no-category, none |
| Пустой результат объяснён словами | Бюджет 1 ₸: причины и «при бюджете от…» | demo.py none |
| Время ответа и ограничение ожидания LLM | Фактическое время над подборкой; для LLM установлен лимит 6 с | tests/test_explain_llm.py |
| Команда может объяснить пайплайн | Архитектура, «Как посчитан рейтинг» | test_funnel_is_sequential_and_preserves_rejection_reasons |
Архитектура
flowchart TD
T[Фраза: POST /api/parse или /api/ask] --> P[Разбор правилами: город, дата, формат, категория, бюджет, часы, язык]
P -->|все обязательные поля найдены| B
P -->|чего-то нет| MS[missing: интерфейс просит уточнить]
A[Форма или POST /api/match] --> B[Валидация запроса и календаря]
B --> C[Пул по категории и городу]
C --> D[Фильтры: дата → бюджет → формат → язык → длительность]
D --> FN[funnel: сколько осталось после каждого фильтра]
D --> E[Прошедшие: взвешенный рейтинг, затем id]
S[Локальные эмбеддинги каталога и 6 форматов] --> E
D --> F[Не прошедшие: все причины в excluded]
E --> G[До 3 карточек: сравнительные объяснения по фактам]
G --> L{Задан ключ OpenAI или NVIDIA?}
L -- да --> LLM[LLM редактирует тексты → проверка → кэш]
L -- нет / ошибка / таймаут --> N[Объяснения по данным]
F --> H[Исход и подсказки]
FN --> H
LLM --> H
N --> H
H --> I[Ответ API → интерфейс]
| Модуль | Что делает |
|---|---|
app/matcher.py | Жёсткие фильтры, рейтинг, сравнительные объяснения, воронка, подсказки. Хранит все причины отказа по каждому кандидату |
app/semantic.py, data/embeddings.json | При старте загружают заранее рассчитанные векторы и локально строят таблицу близости описаний к шести форматам, без ключа и сети |
app/alternatives.py | «План Б»: для дат ±14 дней прогоняет те же фильтры и рейтинг и предлагает ближайшие даты с большей подборкой |
app/nl_parse.py | Разбор фразы по правилам, без сети: у каждого поля — исходный фрагмент; отрицания, диапазоны, синонимы |
app/explain_llm.py | Необязательная редактура объяснений моделью с проверкой фактов, кэшем и откатом на объяснения по данным |
app/data.py | Загрузка CSV; необязательный data/synthetic-extra.csv для профилей команды (synthetic=true) |
app/main.py, static/index.html | API на FastAPI и интерфейс на чистых HTML, CSS и JavaScript — без сборщика и Node.js |
Как считается рейтинг и какие бывают исходы
Рейтинг кандидатов, прошедших фильтры, рассчитывается как взвешенная сумма внутренних оценок факторов
и округляется до 6 знаков. При равенстве порядок определяется по id. Рейтинг не является вероятностью.
В score_parts для показа возвращаются те же исходные оценки до применения весов, округлённые до 3 знаков;
поэтому пересчёт по JSON может немного отличаться от score. Для профилей, у которых есть вектор,
поле semantic дополнительно показывает близость, используемую как relevance, и отдельно
в итоговую сумму не прибавляется. Если подходящего вектора нет, relevance считается по маркерам описания,
а semantic равен нулю.
| Фактор | Вес | Что означает |
|---|---|---|
budget | 0.40 | Запас бюджета относительно цены «от» |
relevance | 0.30 | Косинусная близость предложений описания к заранее заданному формату; без подходящего вектора — маркеры формата и узкая специализация |
hours | 0.15 | Запас по длительности на площадке |
language | 0.10 | Совпадение языка или разнообразие языков |
data_quality | 0.05 | Ниже, если цена или город восстановлены |
| Исход | Когда |
|---|---|
found | Подходят три и больше — показаны три лучших |
partial | Подходят один-два — в message объяснено, почему меньше трёх |
no_category_in_city | В городе нет такой категории |
none_match | Категория есть, но никто не прошёл условия |
invalid_request | Дата вне календаря |
Некорректные поля, неположительный бюджет и неизвестные формат или язык — HTTP 422 с detail.
API
| Метод | Вход | Выход |
|---|---|---|
GET /api/meta | — | Города, категории, форматы, языки, границы календаря |
POST /api/match | город, дата, формат, категория, бюджет; по желанию часы и язык | outcome, message, cards (с highlights, score_parts — исходные оценки до весов, explanation_source), excluded, hints, funnel |
POST /api/alternatives | те же поля | base, options (ближайшие даты: день недели, сколько проходит, топ), message |
POST /api/parse | {"text": "..."} | params, found (поле, значение, фрагмент текста), missing, notes, source |
POST /api/ask | {"text": "..."} | parsed и result — ответ /api/match или null, если не хватает полей |
Интерактивная документация — http://localhost:8000/docs. Ответы отдаются как application/json; charset=utf-8.
«План Б» и разбор свободного текста — подробнее
«План Б». /api/alternatives проверяет даты в пределах ±14 дней теми же фильтрами и рейтингом, что /api/match,
и показывает первыми ближайшие даты с полной подборкой. Для фотографов в Алматы на 12 декабря (подходит один):
«13 декабря (вс) — 3 варианта; 7 декабря (пн) — 3 варианта…». Если мешает не дата, а бюджет, формат, язык или часы,
ответ прямо говорит, что смена даты не поможет. Тест сверяет, что предложенная дата даёт в /api/match ту же тройку.
Разбор текста. /api/parse распознаёт город, дату («14 ноября», «14.11», «2026-11-14»), формат, категорию
(с синонимами: «тамада», «фотобудка», «живая музыка»), бюджет («800 тысяч», «1,5 млн», «600к», «400 000 ₸», диапазон),
длительность и язык. Отрицания («не на английском») не превращаются в фильтр, а объясняются в notes.
Нераспознанные обязательные поля — в missing. Разбор детерминирован и работает без сети.
Почему так устроено
- Решение принимает детерминированный алгоритм — фильтры и рейтинг: задание требует «тот же запрос — тот же порядок». LLM используется там, где он безопасен: переписывает объяснения из уже проверенных фактов; валидатор отклоняет выдуманные числа, цитаты и общие фразы, при отказе остаются объяснения по данным.
- Вес бюджета 0.40: цена в каталоге указана «от», поэтому запас бюджета снижает риск выйти за него. Все веса видны в карточке — «Как посчитан рейтинг».
- Смысл описания доступен без ключа. Для каждого предложения в 66 профилях и каждого из шести форматов векторы рассчитаны заранее и сохранены в репозитории. При старте код строит локальную таблицу косинусной близости; она влияет только на порядок кандидатов, прошедших жёсткие фильтры. Свободная фраза сначала разбирается правилами до полей формы: дополнительные слова не превращаются в отдельный семантический запрос.
Агентный подход
Модель не принимает решение сама — она работает в цикле с проверяемыми инструментами:
- Генерация → проверка → исправление → fallback. LLM пишет объяснения по фактам; код проверяет каждое
(выдуманные числа и цитаты, общие фразы, одинаковые тексты); при ошибках модель получает их список и исправляет
ответ; если и вторая попытка не прошла — показываются объяснения по данным (
app/explain_llm.py). - «План Б» сам ищет решение. Если на дату подходит меньше трёх, сервис перебирает соседние даты теми же
фильтрами и рейтингом и предлагает лучшие; если мешает не дата — прямо говорит, что изменить (
app/alternatives.py). - Фраза → задача. Свободный текст превращается в параметры запроса с указанием источника каждого поля;
неясное и противоречивое возвращается человеку, а не угадывается (
app/nl_parse.py). - API как набор инструментов.
/api/parse,/api/match,/api/alternativesдетерминированы и покрыты тестами — их может вызывать внешний LLM-агент (function calling), не получая возможности выдумать подрядчика или цену.
Что сделано иначе
Только то, что есть в коде и проверяется тестами или демо-сценарием.
| Решение | Проверка |
|---|---|
| Объяснения сравнительные: карточка говорит, чем подрядчик отличается от двух других в этой же подборке | test_explanations_remain_distinct_without_names |
| Причина исчезновения при смене даты доказана: «занят 12 декабря» берётся из причин отказа, а не из разницы списков | test_two_dates_change_results_with_busy_reason |
| Все причины отказа по каждому кандидату и последовательная воронка | test_funnel_is_sequential_and_preserves_rejection_reasons |
| «План Б» и подсказки с кнопкой «Применить» — следующий шаг в один клик | test_offered_date_really_gives_that_selection_in_main_match |
| Офлайн-ранжирование по смысловой близости описаний к шести форматам; готовый индекс работает без ключа и сети | tests/test_semantic.py, data/embeddings.json |
| Фраза → форма: у каждого поля фрагмент текста; подбор запускает пользователь, а не догадка парсера | test_every_found_field_has_source_fragment |
| LLM не влияет на отбор: только редактирует текст, ответ проверяется на выдуманные факты, есть кэш и откат | test_match_marks_llm_source_without_changing_order |
| Аудит на всей сетке запросов, а не на трёх примерах: 7290 запросов, 0 нарушений | scripts/audit_explanations.py --strict |
Используемые технологии
| Слой | Технологии |
|---|---|
| Backend | Python 3.10+, FastAPI, Pydantic, Uvicorn |
| Интерфейс | HTML, CSS и JavaScript без фреймворков и сборщика |
| Смысловая оценка (офлайн) | Предрассчитанные эмбеддинги text-embedding-3-small, локальное косинусное сравнение |
| AI-редактура объяснений (необязательно) | OpenAI Python SDK — OpenAI или NVIDIA API Catalog через OpenAI-совместимый endpoint |
| Данные | CSV каталога организаторов, data/embeddings.json, ответы API в JSON |
| Проверки | pytest, httpx, HTTP-сценарии scripts/demo.py, аудит scripts/audit_explanations.py |
Зависимости
Все зависимости — в requirements.txt (с верхними границами версий): fastapi, uvicorn — сервис; openai —
необязательный LLM-слой, импортируется только при обращении к модели; python-dotenv — чтение .env через
--env-file; pytest, httpx — тесты. Готовый индекс эмбеддингов работает без сети и ключа. Интернет
нужен для установки зависимостей, необязательной LLM-редактуры и только если заново создавать индекс.
Переменные окружения
Все переменные необязательны: без них сервис полностью работает на объяснениях по данным.
| Переменная | По умолчанию | Назначение |
|---|---|---|
LLM_PROVIDER | openai | openai или nvidia; другое значение — только объяснения по данным |
OPENAI_API_KEY | пусто | Ключ OpenAI (platform.openai.com → API keys) |
OPENAI_MODEL | gpt-4o-mini | Модель с temperature=0 и Structured Outputs |
NVIDIA_API_KEY | пусто | Ключ NVIDIA API Catalog (build.nvidia.com), при LLM_PROVIDER=nvidia |
NVIDIA_MODEL | пусто (в .env.example — meta/llama-3.3-70b-instruct) | Модель через https://integrate.api.nvidia.com/v1 |
EXPLANATIONS_LLM_ENABLED | true | false полностью выключает обращения к модели |
LLM_DEBUG | 0 | 1 печатает в консоль сервера, почему ответ модели отклонён (ключ не выводится) |
Ключ хранится только в окружении или в локальном .env, который исключён из Git.
Как устроен LLM-слой объяснений
Один вызов обрабатывает все карточки запроса. Модель получает только условия запроса, проверяемые факты, релевантные
цитаты и уже рассчитанные кодом сравнения; возвращает JSON с объяснениями и не влияет на отбор и порядок.
Ответ проверяется: 1–2 предложения, стоп-лист общих фраз, наличие числового или цитатного основания, отсутствие чисел
и цитат, которых нет во входе, различимость карточек без имён. При нарушении — одна попытка исправления с перечнем
ошибок; на обе попытки вместе 6 секунд. Нет ключа, ошибка, таймаут или повторный невалидный ответ — объяснения по данным.
В каждой карточке explanation_source: llm или template.
Кэш — .cache/explanations.json, ключ — SHA-256 от запроса, упорядоченных ID и версии промпта; запись учитывает
модель и факты. Одинаковый запрос возвращает тот же текст. Чтобы заново запросить модель после временной ошибки,
удалите файл и перезапустите сервер.
Необязательно: AI-объяснения с ключом
Для проверки решения ключ не нужен. С ключом модель редактирует текст объяснений по проверенным фактам; отбор, порядок карточек и все исходы остаются теми же.
Как включить и прогреть кэш
- Создать
.envиз примера и вписать ключ (OPENAI_API_KEY=…; для NVIDIA —LLM_PROVIDER=nvidia,NVIDIA_API_KEY,NVIDIA_MODEL):
Copy-Item .env.example .env
cp .env.example .env
- Запустить сервер с этим файлом:
.\.venv\Scripts\python.exe -m uvicorn app.main:app --host 127.0.0.1 --port 8000 --env-file .env
.venv/bin/python -m uvicorn app.main:app --host 127.0.0.1 --port 8000 --env-file .env
- Прогреть кэш — во втором терминале:
.\.venv\Scripts\python.exe scripts/demo.py
.venv/bin/python scripts/demo.py
Ожидается PASS: 8 ответов, 0 ошибок; при успешном ответе модели у карточек Источник объяснения: llm, при таймауте
или отклонении ответа — template. Успешные ответы сохраняются в .cache/explanations.json и переживают перезапуск:
точно такие же запросы кнопок-сценариев, сравнения дат и примера с фразой затем отвечают из кэша. Запросы, которых не было
при прогреве («Применить», «Другие даты»), обращаются к модели на лету — до 6 с. В интерфейсе у карточек появится метка
«AI-объяснение»; если модель недоступна или ответ не прошёл проверку фактов — остаётся «Объяснение по данным».
Причины отклонения видны в консоли сервера при LLM_DEBUG=1 в .env.
Ограничения
- Календарь известен только с 23.09 по 31.12.2026; цена «от» — не окончательная смета; бронирования и уведомлений нет.
- Разбор текста работает по правилам и поддерживает один язык; редкие формулировки попадают в
missing, и поле заполняется в форме. - У полностью одинаковых по данным профилей отличия не выдумываются. Качество перефразирования моделью зависит от модели; проверка фактов не заменяет полную семантическую проверку.
Масштабирование и развитие
Планы, а не реализованные функции:
- Живые календари — синхронизация занятости с подрядчиками вместо CSV; фильтры, рейтинг и «План Б» уже работают с датами.
- Больше городов и категорий — города и категории берутся из данных (
/api/meta); при росте каталога — база данных с индексом по городу, категории и дате. - Семантика свободной фразы — сейчас локальный индекс сравнивает описания с шестью фиксированными форматами; будущий шаг — использовать дополнительные пожелания заказчика из фразы при ранжировании и обновлять индекс с каталогом.
- Обратная связь — отметки «подошло / не подошло» для настройки весов рейтинга на реальных выборах.
- Встраивание — API без состояния: подбор можно встроить виджетом на сайт агрегатора или площадки.
- Казахский интерфейс — разбор текста уже понимает казахские формулировки («той»).
Команда
| Участник | Роль |
|---|---|
| @Nurzhan-Zhumabekov | Backend: подбор, объяснения и LLM-слой, разбор текста, «План Б», тесты; координация |
| @Dossm04 | Интерфейс, демо-сценарии, документация и проверка воспроизводимости |
Авторы коммитов
История коммитов
- 2026-09-23 17:43Интерфейс: плашка «Был в подборке на другую дату» больше не наезжает на причину отказаNurzhan-Zhumabekov
- 2026-09-23 17:40README: раздел «Агентный подход» — цикл генерация→проверка→исправление, «План Б», фраза→задача, API как инструменты агентаNurzhan-Zhumabekov
- 2026-09-23 17:25Скриншоты под дизайн «Той»Nurzhan-Zhumabekov
- 2026-09-23 17:17Дизайн «Той»: бирюза и золото, орнамент «қошқар мүйіз», иконка и логотипNurzhan-Zhumabekov
- 2026-09-23 17:12README: проверено запуском с нуля (Windows + Docker); «План Б»: двоеточие в объясненииNurzhan-Zhumabekov
- 2026-09-23 16:20Обновить снимки интерфейса по актуальному рейтингуDossm04
- 2026-09-23 16:15Включить проверенные настройки Docker для локального показаDossm04
- 2026-09-23 16:15Добавить проверяемый запуск Docker в READMEDossm04
Все коммиты (99)
- 2026-09-23 16:15Ограничить Docker локальным портом и передать настройки NVIDIADossm04
- 2026-09-23 16:14Собрать проверенные исправления поверх Docker-версииDossm04
- 2026-09-23 16:14README: Docker, эмбеддинги в блоке «ключ не нужен», округление score_parts; DEMO и demo-results под итоговую версиюDossm04
- 2026-09-23 16:14Merge remote-tracking branch 'origin/main' into feature/readme-expertsDossm04
- 2026-09-23 16:11Docker: запуск одной командой — docker compose up --buildNurzhan-Zhumabekov
- 2026-09-23 16:10Merge remote-tracking branch 'origin/codex/semantic-docs-v2' into codex/verified-final-v2Dossm04
- 2026-09-23 16:09Уточнить версию проверенного демоDossm04
- 2026-09-23 16:09Merge remote-tracking branch 'origin/codex/final-ui-audit' into codex/verified-final-v2Dossm04
- 2026-09-23 16:09Merge remote-tracking branch 'origin/codex/semantic-fallback-v2' into codex/verified-final-v2Dossm04
- 2026-09-23 16:08Обновить демо после переиндексации описанийDossm04
- 2026-09-23 16:07Сохранить резервную релевантность для профилей вне индексаDossm04
- 2026-09-23 16:06Проверять границы слов в LLM-цитатахNurzhan-Zhumabekov
- 2026-09-23 16:04Уточнить округление оценок рейтингаDossm04
- 2026-09-23 16:03Исправить границы фраз и обрезку цитатNurzhan-Zhumabekov
- 2026-09-23 16:01Merge remote-tracking branch 'origin/codex/semantic-docs' into codex/verified-finalDossm04
- 2026-09-23 16:01Merge remote-tracking branch 'origin/codex/final-ui-audit' into codex/verified-finalDossm04
- 2026-09-23 16:01Merge remote-tracking branch 'origin/codex/semantic-qa' into codex/verified-finalDossm04
- 2026-09-23 15:58Уточнить описание формулы рейтингаDossm04
- 2026-09-23 15:58Синхронизировать документацию с офлайн-ранжированиемDossm04
- 2026-09-23 15:56Показать веса при резервной оценке профиляDossm04
- 2026-09-23 15:56Документация под эмбеддинги: смысловая релевантность в README, новый порядок фотографов, DEMO, demo-results и скриншотыDossm04
- 2026-09-23 15:55Пояснить округление оценок рейтингаDossm04
- 2026-09-23 15:55Исправить цитаты и резервную оценку профилей без эмбеддинговDossm04
- 2026-09-23 15:53Уточнить семантический рейтинг и ошибки полейDossm04
- 2026-09-23 15:52Merge remote-tracking branch 'origin/feature/readme-experts' into integrationNurzhan-Zhumabekov
- 2026-09-23 15:49Merge remote-tracking branch 'origin/feature/primary-track06' into integrationNurzhan-Zhumabekov
- 2026-09-23 15:49Merge remote-tracking branch 'origin/main' into feature/readme-expertsDossm04
- 2026-09-23 15:48README: значки в одну строку, фраза для проверки — отдельным блоком с копированиемDossm04
- 2026-09-23 15:47Предрассчитать эмбеддинги и ранжировать по смысловой близостиNurzhan-Zhumabekov
- 2026-09-23 15:46README: новое оформление — шапка со скриншотом, таблица проверки, раскрывающиеся подробностиDossm04
- 2026-09-23 15:46Merge remote-tracking branch 'origin/codex/ui-polish' into integrationNurzhan-Zhumabekov
- 2026-09-23 15:42Уточнить быстрый старт и честные ожидания от AIDossm04
- 2026-09-23 15:40README: скриншот интерфейса (сценарий «Фотографы в Алматы», без ключа)Dossm04
- 2026-09-23 15:39Подписать смысловую оценку и не показывать устаревшие весаDossm04
- 2026-09-23 15:36README для самостоятельной проверки: ключ не нужен (вверху), команды для Windows и macOS/Linux, AI — отдельным необязательным разделом, «Почему так устроено»Dossm04
- 2026-09-23 15:33DEMO: время проверкиDossm04
- 2026-09-23 15:32README: «Демо с AI-объяснениями» (env-file, прогрев кэша); demo.py по умолчанию 127.0.0.1 — без задержки 2 с на запрос в WindowsDossm04
- 2026-09-23 15:30Сверить README и демо с актуальными ответами APIDossm04
- 2026-09-23 15:29Уточнить обещание интерфейса и переход к результатамDossm04
- 2026-09-23 15:24LLM-объяснения: цены с разделителем разрядов («350 000 ₸»), цитаты не трогаютсяNurzhan-Zhumabekov
- 2026-09-23 15:21Merge remote-tracking branch 'origin/feature/ui-planb' into integrationNurzhan-Zhumabekov
- 2026-09-23 15:21Merge remote-tracking branch 'origin/feature/readme-v2' into integrationNurzhan-Zhumabekov
- 2026-09-23 15:21Сделать метки карточек короткими отличиямиNurzhan-Zhumabekov
- 2026-09-23 15:20README: «План Б» в интерфейсе — блок «Другие даты»Dossm04
- 2026-09-23 15:18README и DEMO под текущий main: кнопки-сценарии, highlights, «Как посчитан рейтинг», LLM_DEBUG, аудит объяснений 7290/0Dossm04
- 2026-09-23 15:17Merge remote-tracking branch 'origin/main' into feature/primary-track06Nurzhan-Zhumabekov
- 2026-09-23 15:16Показать альтернативные даты и убрать пустую воронкуDossm04
- 2026-09-23 15:14Сделать сравнение в объяснении однозначнымNurzhan-Zhumabekov
- 2026-09-23 15:11Merge remote-tracking branch 'origin/feature/primary-track06' into integrationNurzhan-Zhumabekov
- 2026-09-23 15:11Merge remote-tracking branch 'origin/feature/ui-cards' into integrationNurzhan-Zhumabekov
- 2026-09-23 15:09Усилить проверку объяснений и диагностику LLMNurzhan-Zhumabekov
- 2026-09-23 15:09Уточнить причины подбора и факты в карточкахNurzhan-Zhumabekov
- 2026-09-23 14:59Улучшить карточки и добавить готовые сценарииDossm04
- 2026-09-23 14:58Аудит: проверка «без имени и номера профиля» и запрет HK-номера вместо отличияNurzhan-Zhumabekov
- 2026-09-23 14:52API отдаёт charset=utf-8; аудит не считает разные цитаты одинаковымиNurzhan-Zhumabekov
- 2026-09-23 14:51Merge remote-tracking branch 'origin/feature/primary-track06' into integrationNurzhan-Zhumabekov
- 2026-09-23 14:51Merge remote-tracking branch 'origin/feature/ui-nl' into integrationNurzhan-Zhumabekov
- 2026-09-23 14:51Merge remote-tracking branch 'origin/feature/readme-final' into integrationNurzhan-Zhumabekov
- 2026-09-23 14:50Различать площадки по деталям их описанийNurzhan-Zhumabekov
- 2026-09-23 14:46README: проверяемый пример, Definition of Done, «План Б», что сделано иначе, масштабирование и команда; демо «План Б»Dossm04
- 2026-09-23 14:42Аудит объяснений: scripts/audit_explanations.pyNurzhan-Zhumabekov
- 2026-09-23 14:41Проверить совместимость запроса NVIDIA через SDKNurzhan-Zhumabekov
- 2026-09-23 14:40«План Б»: /api/alternatives — ближайшие даты с большей подборкойNurzhan-Zhumabekov
- 2026-09-23 14:38Подбор запускается после проверки распознанных условийDossm04
- 2026-09-23 14:37requirements: верхние границы fastapi <0.142 и uvicorn <0.54 (проверено на 0.141.1 / 0.53.0)Nurzhan-Zhumabekov
- 2026-09-23 14:35README: шаг проверки запроса свободным текстом через интерфейсNurzhan-Zhumabekov
- 2026-09-23 14:34Добавить проверку объяснений на пяти демонстрационных запросахNurzhan-Zhumabekov
- 2026-09-23 14:34Разбор текста: фрагменты показываются целыми словами («Астане», а не «Астан»)Nurzhan-Zhumabekov
- 2026-09-23 14:33Merge remote-tracking branch 'origin/feature/primary-track06' into integrationNurzhan-Zhumabekov
- 2026-09-23 14:33Merge remote-tracking branch 'origin/feature/ui-nl' into integrationNurzhan-Zhumabekov
- 2026-09-23 14:30Улучшить объяснения карточек и добавить выбор провайдера LLMNurzhan-Zhumabekov
- 2026-09-23 14:30Разбор текста: отрицания, отрицательный бюджет, диапазон бюджетаNurzhan-Zhumabekov
- 2026-09-23 14:30Уточнены состояния разбора заявки и защита от устаревшей выдачиDossm04
- 2026-09-23 14:28Merge remote-tracking branch 'origin/main' into feature/ui-nlDossm04
- 2026-09-23 14:26Добавлен разбор заявки и интерактивные подсказки, обновлены демо-ответыDossm04
- 2026-09-23 14:22Слита документация ноутбука 2 (6498c79); подсказка для «казахской свадьбы»Nurzhan-Zhumabekov
- 2026-09-23 14:17Merge remote-tracking branch 'origin/feature/ui' into integrationNurzhan-Zhumabekov
- 2026-09-23 14:16Merge remote-tracking branch 'origin/feature/readme-demo' into integrationNurzhan-Zhumabekov
- 2026-09-23 14:16Документация: воронка отбора, запрос свободным текстом, проверка за 2 минуты и автотестыDossm04
- 2026-09-23 14:15Merge remote-tracking branch 'origin/feature/nl-parse' into integrationNurzhan-Zhumabekov
- 2026-09-23 14:09Убрать предположение о роде из подсказок и объясненийNurzhan-Zhumabekov
- 2026-09-23 14:05Запрос свободным текстом: /api/parse и /api/askNurzhan-Zhumabekov
- 2026-09-23 14:04Добавлены сравнение дат, состояния выдачи и прозрачные объяснения в интерфейсеDossm04
- 2026-09-23 14:03Добавить проверяемые LLM-объяснения с кэшем и таймаутомNurzhan-Zhumabekov
- 2026-09-23 13:56Merge remote-tracking branch 'origin/main' into feature/primary-track06Nurzhan-Zhumabekov
- 2026-09-23 13:55Бюджет: разрешены любые целые суммы, дробные отсекаются формойDossm04
- 2026-09-23 13:54Добавлены инструкция запуска и шесть проверенных демо-сценариевDossm04
- 2026-09-23 13:49Добавить сравнительные объяснения и воронку отбораNurzhan-Zhumabekov
- 2026-09-23 13:47Исправлен шаг бюджета: разрешены произвольные положительные суммыDossm04
- 2026-09-23 13:43Исправлено поле бюджета: форма отправляется со значением по умолчаниюDossm04
- 2026-09-23 13:29WIP: каркас сервиса подбора подрядчиковNurzhan-Zhumabekov
Структура репозитория (31 файлов)
.dockerignore .env.example .gitignore Dockerfile README.md app/__init__.py app/alternatives.py app/data.py app/explain_llm.py app/main.py app/matcher.py app/nl_parse.py app/semantic.py data/embeddings.json data/hackathon-dataset-anonymized.csv docker-compose.yml docs/DEMO.md docs/demo-results.json docs/screenshot-compare.png docs/screenshot.png requirements.txt scripts/audit_explanations.py scripts/build_embeddings.py scripts/demo.py scripts/evaluate_explanations.py static/index.html tests/test_alternatives.py tests/test_dod.py tests/test_explain_llm.py tests/test_nl_parse.py tests/test_semantic.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.