Эталонный диалог собирается кодом из фактов и чек-листа: написанный руками, он разошёлся бы с фактами при первой же правке сценария, и курсанта оштрафовали бы за правильный ответ. Отчёт: метрики фактом против норматива со ссылкой, отметка E1 на каждый недобытый факт с эталонным вопросом, расхождение самооценки — что курсант заметил сам, чего не заметил, что отметил зря. Не заметил — самое ценное для разбора. Внешний монитор — не отдельное приложение, а другой режим отрисовки тех же событий: крупный таймер опроса, ход разговора, карточка, после оценки разбор на весь экран. Коррекция преподавателем сохраняет автооценку рядом: видно, что скорректировано и кем. Найдено: все метрики весили одинаково, и курсант, не задавший ни одного вопроса, но заполнивший карточку руками, получал 87 из 100. Предварительные веса (полнота опроса — 4) дают 74; окончательные утверждает методист, вопрос записан в DEBRIEF.md.
44 lines
2.3 KiB
Python
44 lines
2.3 KiB
Python
"""Какая метрика каким кодом ошибки и какой компетенцией размечается.
|
||
|
||
Это методика, а не вычисление: таблица читается глазами и сверяется
|
||
с docs/product/METHODOLOGY.md. Считает метрики gost.py, сюда он только смотрит.
|
||
"""
|
||
|
||
from app.domain.taxonomy import Competency, ErrorCode
|
||
|
||
#: Метрика → (код ошибки при провале, компетенция радара).
|
||
METRIC_MAP: dict[str, tuple[ErrorCode, Competency]] = {
|
||
"answer_time": (ErrorCode.E3, Competency.INTAKE),
|
||
"callback": (ErrorCode.E3, Competency.INTAKE),
|
||
"checklist_completeness": (ErrorCode.E1, Competency.INTERVIEW),
|
||
"interview_time": (ErrorCode.E3, Competency.NORMS),
|
||
"incident_type": (ErrorCode.E2, Competency.ROUTING),
|
||
"dds_choice": (ErrorCode.E2, Competency.ROUTING),
|
||
"address": (ErrorCode.E5, Competency.CARD),
|
||
"victims_count": (ErrorCode.E5, Competency.CARD),
|
||
"required_fields": (ErrorCode.E5, Competency.CARD),
|
||
}
|
||
|
||
#: Вес метрики в детерминированной оценке.
|
||
#:
|
||
#: **Предварительные значения, требуют утверждения методистом.** Без весов все
|
||
#: метрики равны, и курсант, не задавший ни одного вопроса, но заполнивший
|
||
#: карточку руками, получает 87 из 100: «ответ за секунду» стоит столько же,
|
||
#: сколько «добыл все обязательные факты». Опрос — то, ради чего существует
|
||
#: тренажёр, поэтому он весит больше всего.
|
||
METRIC_WEIGHTS: dict[str, float] = {
|
||
"checklist_completeness": 4.0,
|
||
"incident_type": 2.0,
|
||
"dds_choice": 2.0,
|
||
"address": 2.0,
|
||
"required_fields": 2.0,
|
||
"interview_time": 1.5,
|
||
"victims_count": 1.0,
|
||
"answer_time": 1.0,
|
||
"callback": 1.0,
|
||
}
|
||
|
||
#: Вес детерминированного слоя в итоговой оценке. Остальное — LLM-судья
|
||
#: на мягкие критерии (E4), и не больше (docs/arch/BACKEND.md).
|
||
DETERMINISTIC_WEIGHT = 0.6
|
||
JUDGE_WEIGHT = 0.4
|