BESTINDEX

Доверяем фактам, не маркетингу

Манифест и методология · v2

Score, в который мы готовы поверить сами.

Мы не ставим оценки технике на глаз. Каждое число в BestIndex — взвешенная агрегация независимых тестов с прозрачной формулой и публичными весами.

01

Не пишем сами

BestIndex не публикует собственных обзоров. Мы — мета-сервис, который агрегирует чужие тесты и измерения.

02

Не берём денег

Не размещаем брендовые материалы и партнёрки на странице оценки. Никакой замаскированной рекламы.

03

Открытая формула

Веса источников, формула score, журнал изменений — публичны. Любую оценку можно перепроверить.

Формула BestIndex Score

// взвешенное среднее с учётом источника и роли обзора
score(model) = round( Σ (w_src × role × rating) / Σ (w_src × role) ) × 10

confidence = 0.30 × coverage     // доля claims с ≥2 evidence
            + 0.25 × trusted_share  // доля Tier A источников
            + 0.25 × completeness   // avg(confidence) evidence
            + 0.20 × freshness      // средний freshness factor

controversy = (disagree + 0.5 × mixed) / total × 100

Формула детерминированная: те же источники на входе → тот же score на выходе. Можно повторить вручную.

9–18
Параметров (claims)
на категорию: камера, батарея, шум, навигация и т.п.
0–1
Вес источника
зависит от Tier (A/B), типа источника, истории успеха
≥2
Минимум источников
иначе модель помечена 'low_data'
100%
Воспроизводимость
никаких LLM-чёрных ящиков в финальном балле

Роли обзоров

Тип обзора влияет на вклад источника в итоговый балл. Полноценный лабораторный тест значит больше, чем подборка.

×1.0

Primary

Полноценный обзор с тестами, измерениями, развёрнутыми оценками. Работают с моделью неделями.

×0.7

Secondary

Подборки, обзоры по презентации, сжатые заметки от знакомых редакторов.

×0.4

Supplemental

Новости, упоминания в контексте сравнений, форумные ветки. Учитываем, но скромно.

Авториски

Вместе со score формула выдаёт список рисков. Это сигналы — чему доверять с оглядкой.

low_data Меньше 3 одобренных источников
old_reviews Все обзоры старше 2 лет
conflicting_claims ≥ 2 тезиса в статусе disagree
weak_reliability Тезис «Надёжность» в disagree/mixed
single_source_type Все обзоры одного типа источника

Главная: «Модель дня» и «Недавние проверки»

Hero-карточка и блок свежих пересчётов на главной — не редакторский выбор и не рандом, а две детерминированные выборки из каталога с открытыми правилами.

Модель дня

Hero-карточка на главной — не «самая популярная» и не «с самым высоким score». Это лучшая среди тех, кого реально качественно разобрали. Логика идёт в три шага: барьер допуска → ранжирование по showcase score → детерминированная ротация по дню внутри топ-10.

Шаг 1. Барьер допуска — карточка обязана соответствовать всем условиям одновременно:

  • status = published — карточка опубликована
  • score ≥ 75 — финальная оценка не ниже 75
  • confidence ≥ 65 — аналитическая уверенность не ниже 65
  • source_reviews ≥ 3 — минимум три реальных рецензии (считаем по таблице source_reviews, а не по JSONB source_consensus, который часто пуст до прогона RecomputeService)

Шаг 2. Showcase score — непрерывный ранг среди допущенных:

showcase = 0.25 × score/100
         + 0.20 × confidence/100
         + 0.15 × breadth
         + 0.15 × consensus
         + 0.15 × freshness
         + 0.10 × depth

         × risk_penalty
         × editorial_boost

// компоненты:
breadth         = min(1, ln(N+1) / ln(8))   // N = source_reviews. 3→0.67, 5→0.86, 7+→1.0
consensus       = max(0, (agree − disagree − 0.5·mixed) / total_claims)
freshness       = max(0, 1 − days_since_update / 365)
depth           = avg(evidence_quality, info_density, competence) / 100
risk_penalty    = max(0.75, 10.03 × risk_count)
editorial_boost = 1.05 if is_curated OR reviewed_by_editor else 1.00

Что значит каждый компонент:

  • score / confidence — почти половина веса формулы. Финальная оценка и аналитическая уверенность уже учитывают вес источников, долю Tier A, coverage по claims, свежесть источников.
  • breadth — широта покрытия источниками. Логарифм с насыщением, чтобы 12 источников не били 7 в три раза.
  • consensus — насколько источники согласны между собой. Если все спорят — компонент 0; если все за — 1. Дисcсент штрафуется сильнее, чем mixed.
  • freshness — свежесть самого разбора: линейный спад от 1.0 (сегодня) до 0.0 (год и старше). Это отдельный сигнал от freshness внутри confidence — там про возраст обзоров, тут про возраст нашей агрегации.
  • depth — глубина разбора по редакционным метрикам: качество доказательств, плотность информации, компетенция автора.
  • risk_penalty — мягкий штраф за каждый зафиксированный риск (любой степени), не ниже ×0.75.
  • editorial_boost — небольшая надбавка за курирование или ручную проверку редактором. Не обязательное условие, просто приоритет.

Шаг 3. Ротация. Берём топ-10 по showcase и крутим по дню: top10[date.today().toordinal() % 10]. Все посетители в один день видят одну модель, в полночь UTC она меняется на следующую из топа. Так чередуются именно «отличники», а не весь хвост каталога.

Эндпоинт: GET /api/cards/featured. Если ни одна карточка не прошла барьер допуска (true cold-start каталога), включается мягкий fallback по recommended-рангу без quality-фильтров — плюс предупреждение в логах, чтобы мы видели, что каталог пока ниже порога качества и не должен оставаться таким надолго.

Недавние проверки

Блок под hero показывает карточки, отсортированные по последнему событию scoring в журнале model_history: recomputed или score_changed, статус published. Это «что мы реально пересчитали недавно».

Эндпоинт: GET /api/cards/recently-scored. Под капотом — JOIN с model_history, GROUP BY карточке, MAX по дате события. Каждая модель появляется один раз с полем last_scored_at.

Косметические правки (переименование, загрузка картинки, изменение статуса) этот блок не двигают — только реальные прогоны через RecomputeService. Кнопка «История» в правом углу блока ведёт в каталог с более широкой сортировкой по updated_at, куда попадает любое изменение строки.

Подбор: как мы выбираем модели под ваши ответы

Подбор не строит новый рейтинг. Он использует уже посчитанные score и confidence карточек, а ваши ответы только сдвигают вес тех тезисов, которые важны именно вам.

// Базовый ранг: уже посчитанная "качественная сила" модели.
base(card) = card.score × card.confidence / 100

// Бонус за каждый "важный" тезис (claim) из ваших ответов.
claim_bonus = Σ over claims (
    w_claim ×  +1 if model_claim.status = agree
    w_claim ×  -1 if model_claim.status = disagree
    0 otherwise (mixed / low_data)
)

// Тематическое попадание / противопоказание.
fit_bonus     = +5 per keyword found in card.fit_for
not_fit_pen   = -5 per keyword found in card.not_fit_for

match_score(card) = base + claim_bonus + fit_bonus + not_fit_pen

// Фильтрация результата перед показом.
show(card) = card.confidence ≥ 60
        AND match_score ≥ 0.70 × leader.match_score
top-N = first 5 from sorted(show, by match_score desc)

Если ни одна карточка не прошла оба фильтра — мы покажем пустой результат. Лучше промолчать, чем рекомендовать «на отвали».

≥60
Минимальная уверенность
Карточка должна иметь подтверждённый консенсус, а не одну рецензию
≥70%
От лучшей в выборке
Чтобы 5-й результат не оказался слабее лидера в полтора раза
0–5
Сколько вернём
Только реально подходящие — никаких заглушек ради круглого числа
JSON
Веса в админке
weights_json у каждой опции вопроса — редакция настраивает без релиза

Как ответ влияет на формулу

  1. Hard-фильтры (категория обязательно, бюджет/бренд/минимальный score — опционально из filter_json опции): убирают модели, которые точно не подходят. Бюджет включится, когда у карточек появится цена.
  2. Веса тезисов (weights_json.claims): каждая ваша опция говорит «эти 1–3 тезиса для меня важны». Если у модели по этому тезису согласие источников (model_claim.status = agree) — модель получает плюс. Если расхождение — минус.
  3. Текстовые подсказки (fit_for_keywords / not_fit_for_keywords): ищем подстроку в редакторских полях fit_for / not_fit_for карточки. Простая, но эффективная эвристика, пока теги не структурированы.
  4. Сортировка и отсечка: сортируем по match_score, отрезаем по уверенности и относительному порогу — оставляем только то, в чём действительно уверены.

Что меняется, если на вопрос можно выбрать несколько ответов

Некоторые вопросы намеренно multi-select: смартфон может быть нужен и «для фото», и «для игр»; в камере одинаково важны и «ночь», и «видео». В таких вопросах формула ведёт себя предсказуемо:

  • Веса тезисов суммируются. Если две ваши опции бустят один и тот же тезис — его вес удваивается. Семантика: «вы дважды подтвердили, что это важно».
  • Текстовые ключевые слова дедуплицируются. Одна и та же фраза в fit_for_keywords двух опций даёт +5 за модель, а не +10.
  • Жёсткий фильтр бренда расширяется. Выбор двух брендов → разрешены оба.
  • Жёсткие пороги (минимальный score, максимальная цена) берут самый строгий вариант. Это редкий случай — большинство «жёстких» опций сейчас в single-вопросах.

Из этого следует простое правило: не нужно отмечать «всё подряд». 5 галочек в одном вопросе либо ничего не изменят (если опции бустят разные тезисы), либо приведут к одному и тому же ранжированию, что и 1–2 точных ответа. Лучше выбирать 1–3 пункта, которые действительно важны.

Что показывает счётчик «Подходит сейчас» во время квиза

Каждый раз, когда вы меняете ответ, мы делаем тот же запрос match, который запустится в конце, и показываем число прошедших отсечку моделей. Это не оценка «возможно подходящих», а реальный результат поиска по текущим ответам:

  • До первого ответа счётчик показывает число моделей в категории, которые уже прошли минимальную уверенность консенсуса (≥ 60).
  • По мере ответов число сужается — но «0» не обязательно означает, что вы что-то сделали не так. Скорее каталог ещё не догнал ваш запрос. В этом случае квиз честно скажет «уверенных совпадений нет» вместо того чтобы подсунуть сомнительный вариант.

Что мы предлагаем, если ничего не подошло

Когда match возвращает 0, квиз вызывает второй эндпоинт — /api/picker/relax. Он берёт ваши ответы и для каждого вопроса по очереди пробует убрать только этот ответ, перезапускает match и смотрит, насколько вырастет число подходящих моделей.

  • Возвращается top-5 вариантов «снять X → +N моделей», отсортированных по приросту.
  • Кнопка «Снять» сразу удаляет соответствующий ответ и возвращает вас к этому шагу — можно ответить иначе.
  • Никакой магии: это тот же match-алгоритм, прогнанный ещё несколько раз. Цены те же отсечки, те же веса.

Что подбор учитывает, а что — пока нет

Прозрачность важнее красивой обещалки. Подбор сейчас работает как soft-ранжирование по консенсусу источников, а не как hard-фильтр по характеристикам устройства. Что это значит на практике:

  • Учитываем: ваши ответы повышают вес тех тезисов, по которым обзорщики в целом согласны (модель «хорошо моет», «тихая», «долго живёт от заряда»). Эти оценки берутся из агрегации model_claims.
  • Не учитываем: точные физические характеристики моделей — ёмкость батареи в мАч, объём пылесборника, диагональ экрана, тип установки, IP-рейтинг, наличие сушки. У нас в БД пока нет структурированных спек устройств.
  • Что это значит для вас: «150+ м²» в квизе означает «дай больший вес моделям, которым обзорщики ставят плюс за автономность» — а не «отсей тех, у кого батарея < 150 минут». В большинстве случаев это даёт разумные рекомендации, но финальный выбор лучше сверять с карточкой модели.
  • Что планируем: добавить Card.specs_json со схемой характеристик по категориям и расширить filter_json опций hard-фильтрами вида spec_min, spec_eq. Это превратит квиз из «soft-ранжирования» в «hard-фильтр + soft-ранжирование внутри отфильтрованного». План — в PLAN_V2.5.md.

Save & resume

Кнопка «Сохранить и выйти» в шапке квиза сохраняет ваши ответы в таблицу picker_sessions и возвращает короткий токен. URL дополняется параметром ?session=<токен> — добавьте страницу в закладки или скопируйте ссылку, и при открытии квиз восстановит шаг и ответы. Ничего не привязано к учётной записи и работает анонимно.

Не знаете, что выбрать?

Ответьте на 5 вопросов — подберём модели с высоким консенсусом источников.

Подобрать модель