feat: уточнение адреса — место происшествия не равно адресу заявителя (lct-35)
Главный предмет проверки в билетах заказчика — адрес: названный заявителем часто неверен, а настоящий добывается переспросом («ул. Станционная, 28» оказывается Королёвом). Памятка АРМ-112 называет это обычным делом. До этой правки оценка работала наоборот: ground_truth.address сравнивался с единственным значением факта, поэтому курсант, правильно переспросивший и записавший настоящий адрес, получал расхождение с эталоном, а записавший ориентир — зачёт. - Схема: у факта появились refined и refine_on, задаются только вместе. - Слот-автомат различает уточнение и повтор: повтор раздражает звонящего, уточнение — нет, оператор спросил о другом и получил другое. - Звонящий поправляется отдельной репликой, а не повторяет прежнее значение; офлайн-таблица получила секцию refine. - Оценка: метрика address_refined (E1, опрос). Сделана отдельной, а не правкой метрики address: «записал не тот адрес» и «не спросил» — разные навыки и разные компетенции в радаре. - Общие пункты чек-листа подключаются по требованию сценария: формулировки в checklists/common.yaml, сценарий объявляет пункт с тем же id без текста. Добавлять «уточните адрес» во все сценарии нельзя — неотработанный пункт штрафует за вопрос, которого сценарий не требовал. - scenarios/fire-private-house-l3.yaml — первый сценарий из библиотеки заказчика (билет 3, вызов 1). Риск механики проверен на живой модели: «Назовите адрес» и «Это точно Москва?» эмбеддинги не путают, тест это фиксирует. 125 тестов зелёных (12 новых), make typecheck чистый.
This commit is contained in:
parent
7212251112
commit
842a333d16
11 changed files with 381 additions and 8 deletions
|
|
@ -111,6 +111,7 @@ def evaluate(
|
|||
kio: KIO,
|
||||
timers: SessionTimers,
|
||||
revealed_facts: list[str] | None,
|
||||
refined_facts: list[str] | None = None,
|
||||
end_reason: CallEndReason | None = None,
|
||||
bounced_fields: list[str] | None = None,
|
||||
) -> GostResult:
|
||||
|
|
@ -222,6 +223,23 @@ def evaluate(
|
|||
finding=f"Карточка ушла в ДДС {actual}, верная — {truth.dds.value}",
|
||||
)
|
||||
|
||||
# ── подтверждение места происшествия, E1 ──
|
||||
#
|
||||
# Адрес заявителя не всегда адрес происшествия: он называет тот, где стоит
|
||||
# сам, или ориентир вместо дома. В билетах заказчика это основной приём
|
||||
# усложнения (docs/spec/TICKETS.md), и оператор обязан переспросить.
|
||||
refinable = [fact.id for fact in scenario.facts if fact.refine_on]
|
||||
if refinable and refined_facts is not None:
|
||||
confirmed = [fact_id for fact_id in refinable if fact_id in refined_facts]
|
||||
build.add(
|
||||
"address_refined", "Место происшествия подтверждено",
|
||||
f"уточнено {len(confirmed)} из {len(refinable)}", "уточнены все",
|
||||
passed=len(confirmed) == len(refinable),
|
||||
ref="памятка АРМ-112: адрес заявителя не всегда адрес происшествия",
|
||||
finding="Оператор не переспросил про место происшествия — записан адрес,"
|
||||
" который назвал заявитель",
|
||||
)
|
||||
|
||||
# ── карточка, E5 ──
|
||||
if truth.address:
|
||||
written = kio.address or " ".join(filter(None, [kio.street, kio.building]))
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ METRIC_MAP: dict[str, tuple[ErrorCode, Competency]] = {
|
|||
"dds_chain": (ErrorCode.E6, Competency.CARD),
|
||||
"callback": (ErrorCode.E3, Competency.INTAKE),
|
||||
"checklist_completeness": (ErrorCode.E1, Competency.INTERVIEW),
|
||||
"address_refined": (ErrorCode.E1, Competency.INTERVIEW),
|
||||
"interview_time": (ErrorCode.E3, Competency.NORMS),
|
||||
"incident_signs": (ErrorCode.E2, Competency.ROUTING),
|
||||
"incident_type": (ErrorCode.E2, Competency.ROUTING),
|
||||
|
|
@ -30,6 +31,7 @@ METRIC_MAP: dict[str, tuple[ErrorCode, Competency]] = {
|
|||
#: тренажёр, поэтому он весит больше всего.
|
||||
METRIC_WEIGHTS: dict[str, float] = {
|
||||
"checklist_completeness": 4.0,
|
||||
"address_refined": 2.0,
|
||||
"incident_signs": 2.0,
|
||||
"incident_type": 2.0,
|
||||
"dds_choice": 2.0,
|
||||
|
|
|
|||
Loading…
Reference in a new issue