Уверенность
Как TypeSafe сообщает об уверенности, чем она отличается от вероятности и как управлять поведением системы с её помощью.
Все ответы Score и Choice от TypeSafe содержат свойство probabilities, представляющее распределение вероятностей по вариантам (для Choice) или уровням (для Score). Именно форма этого распределения говорит о том, насколько модель уверена: сосредоточенность на одном исходе означает уверенный ответ, размытость — неуверенный.
Свойство confidence ответа сводит эту форму к одному числу от 0 до 1, так что вы можете задать по нему порог, не считая всё сами. Оно равно 1, когда вся вероятность сосредоточена на одном исходе, и 0, когда вероятность распределена равномерно. (В ответах Noul его нет; см. ниже Noul.)
Уверенность выводится из вероятностей
confidence — это статистика, вычисляемая по распределению вероятностей, которое ответ уже даёт вам. TypeSafe вычисляет её за вас и возвращает в каждом ответе Choice и Score, так что в обычном случае от вас не требуется дополнительной работы.
Пример: вопрос choice с тремя вариантами
Как распределение вероятностей меняет уверенность
Уверенность
Вероятность
Двигайте ползунок, чтобы изменить вероятность варианта. Остальные подстраиваются автоматически, чтобы сумма оставалась 100%.
Выбрано: Вариант A
Как эта демонстрация вычисляет уверенность
TypeSafe вычисляет уверенность по тому, насколько вероятность распределена между вариантами. Если всё сосредоточено на одном варианте, получается 1.0; чем равномернее распределение, тем ниже уверенность. Эта демонстрация использует (3 × максимальная вероятность − 1) / 2, чтобы приблизить уверенность для трёх вариантов.
Для Choice распределение — это probabilities по вашим вариантам. Для Score это распределение по вашим уровням. В обоих случаях более плоское распределение означает более низкую уверенность: низкая уверенность у Choice часто означает, что ни один из вариантов явно не превосходит остальные, а низкая уверенность у Score часто означает, что уровни неоднозначны, многомерны или что состояние содержит недостаточно данных.
Точная формула для каждого типа вопроса приведена в разделе Как вычисляется уверенность, так что вы видите, как любое значение confidence вытекает из собственных probabilities ответа.
«Не знаю» — полезный сигнал
Если интеллектуальная система, человек или машина, не может честно выразить неуверенность, ей нельзя доверять.
Уверенность даёт вам встроенный механизм, позволяющий модели сказать «я не уверена в этом». Это позволяет вашему коду реализовать разное поведение для разных уровней уверенности — основу для создания систем, на которые действительно можно положиться.
Три пути использования уверенности в коде
Полезный начальный паттерн — разделить уверенность на три диапазона, каждый из которых даёт разное поведение системы:
Высокая уверенность: действуйте автоматически. Модель видит ситуацию ясно, и вы можете продолжать без участия человека.
Средняя уверенность: действуйте осторожно. У модели есть разумный ответ, но она не уверена. В зависимости от контекста вы можете попросить пользователя подтвердить, пометить для проверки или собрать больше информации, прежде чем действовать.
Низкая уверенность: не действуйте. Передайте человеку, запросите уточнение или откатитесь к другой системе. Модель сообщает вам, что у неё недостаточно информации или вопрос ей не подходит.
Где провести эти границы, зависит от ставок.
Пороги масштабируются вместе с риском
Порог уверенности — это не одно число. Разные действия в одной системе следует ограничивать на разных уровнях в зависимости от последствий ошибки.
response = client.system_one(
state=user_message,
questions={
"action": Choice(
instructions="What is the user trying to do?",
criteria={
"check_balance": "View account balance",
"approve_transfer": "Approve the pending withdrawal request",
"support": "Get help with an issue",
},
),
},
)
action = response.answers["action"]
confidence = action.confidence
if confidence < 0.5:
# Model is genuinely unsure. Don't guess.
route_to_human(user_message)
elif action.choice == "check_balance":
# Low stakes. Showing the wrong screen is recoverable.
show_balance(account_id)
elif action.choice == "approve_transfer":
if confidence > 0.9:
# High stakes, high confidence. Proceed with confirmation.
confirm_then_execute(account_id)
else:
# High stakes, moderate confidence. Verify first.
ask_user_to_confirm(account_id)
Порог уверенности 0.5 отсекает всё, что модель сообщает как действительно неопределённое. Выше него порог для действия без подтверждения выше для разрушительной операции, чем для операции только для чтения. Ваш код кодирует допустимый уровень риска.
Как вычисляется уверенность
Каждый тип вопроса обобщает своё распределение немного по-своему. У Noul два исхода, у Choice — любое число вариантов в произвольном порядке, а уровни Score упорядочены, поэтому каждая формула ниже опирается на предыдущую.
confidence в TypeSafe — один разумный способ обобщить распределение, но не единственный. Мы возвращаем фиксированную меру, чтобы каждый ответ шёл с разумным значением по умолчанию: вы можете гейтить по confidence с первого вызова, в одной и той же шкале от 0 до 1 для любого вопроса, не выбирая и не проверяя сначала собственную статистику. Поскольку формулы ниже точны, а каждый ответ содержит полные probabilities, вы можете вместо этого вычислить ту меру, которая важнее всего для вашего приложения.
Noul
Ответ Noul — это единственная вероятность $p$ того, что ответ «да», и TypeSafe не возвращает для него отдельный confidence. Вероятность уже несёт неопределённость: значение около 0.5 — это модель говорит, что не уверена, а страница Noul рассказывает, как задать порог прямо по ней.
Если вам всё же нужно число в стиле уверенности, например чтобы гейтить Noul и Choice одним и тем же кодом, используйте расстояние от 0.5:
$$ \text{confidence} = |2p - 1| $$
Это даёт 0 при $p = 0.5$ и 1 при $p = 0$ или $p = 1$. Это также формула Choice ниже, применённая к Choice «да/нет», так что она находится в той же шкале, что и уверенность Choice.
Choice
Choice распространяет ту же идею на любое число вариантов. Для Choice с $n$ вариантами, где $p_{\max}$ — вероятность выбранного варианта:
$$ \text{confidence} = \frac{p_{\max} - \frac{1}{n}}{1 - \frac{1}{n}} $$
Это измеряет, насколько наибольшая вероятность поднимается выше равного дележа $\frac{1}{n}$ на вариант, в шкале, где равный дележ равен 0, а полная определённость — 1. Учитывается только наибольшая вероятность, поэтому $(0.6, 0.3, 0.1)$ и $(0.6, 0.2, 0.2)$ обе имеют уверенность 0.4.
def choice_confidence(probabilities: list[float]) -> float:
n = len(probabilities)
return (max(probabilities) - 1 / n) / (1 - 1 / n)
choice_confidence(list(answer.probabilities.values()))
Обозреватель в верхней части этой страницы использует эту формулу с тремя вариантами.
Две более простые меры, вычисляемые из тех же probabilities, часто очень эффективны на практике, и их стоит попробовать рядом с confidence:
- Наибольшая вероятность, $p_{\max}$. Она читается прямо как «насколько вероятен выбранный вариант», что делает пороги легко осмысляемыми. Её смысл зависит от числа вариантов: 0.5 — слабый ответ среди двух вариантов и сильный среди десяти, поэтому задавайте её порог для каждого вопроса отдельно.
- Отношение наибольшей ко второй, $p_{\max} / p_{\text{second}}$. Оно измеряет, насколько явно выбранный вариант обходит ближайшего конкурента, и игнорирует, как распределён остаток. Многие реальные решения сводятся к двум лучшим кандидатам, и это отношение нацелено именно на это.
Score
Уровни Score упорядочены, поэтому его формула также учитывает, насколько вероятность удалена от наиболее вероятного уровня. Для Score с $n$ уровнями, пронумерованными от $0$ до $n - 1$, где $p_i$ — вероятность уровня $i$, а $m$ — наиболее вероятный уровень:
$$ \text{confidence} = \max\left(0,\ 1 - \frac{\sum_i p_i , |i - m|}{\text{MAD}{\text{unif}}}\right) \qquad \text{MAD}{\text{unif}} = \frac{1}{n} \sum_i \left| i - \frac{n - 1}{2} \right| $$
Сумма в числителе — это средневзвешенное по вероятности расстояние, в уровнях, между ответом и наиболее вероятным уровнем. $\text{MAD}_{\text{unif}}$ — такое же среднее расстояние для равномерного распределения по всем уровням, измеренное от среднего уровня. Уверенность сравнивает оба, и ограничена снизу нулём, когда ответ разбросан не меньше равномерного распределения.
Вероятность на соседнем уровне снижает уверенность меньше, чем та же вероятность на более далёком уровне. При трёх уровнях $(0, 0.5, 0.5)$ имеет уверенность 0.25, потому что модель разрывается между двумя соседними уровнями. $(0.5, 0, 0.5)$ имеет уверенность 0, потому что разрывается между противоположными краями. Формула Choice дала бы обоим распределениям 0.25.
Вопрос со шкалой из пяти уровней
Как расстояние между уровнями меняет уверенность
Уверенность
Вероятность
Двигайте ползунок, чтобы изменить вероятность уровня. Остальные подстраиваются, чтобы сумма оставалась 100%.
- Оценка
- 2.00
- Формула Choice на тех же вероятностях
- 0.88
Как эта демонстрация считает уверенность
Демонстрация использует формулу Score: берётся среднее расстояние в уровнях между ответом и пиком, взвешенное вероятностью. Оно делится на 1.2 — то же среднее для равномерного распределения по пяти уровням, измеренное от среднего уровня, — и результат вычитается из 1 с остановкой на 0. Вероятность на уровне рядом с пиком снижает уверенность меньше, чем далёкая вероятность; формула Choice этого не учитывает.
def score_confidence(probabilities: list[float]) -> float:
n = len(probabilities)
m = probabilities.index(max(probabilities))
spread = sum(p * abs(i - m) for i, p in enumerate(probabilities))
even_spread = sum(abs(i - (n - 1) / 2) for i in range(n)) / n
return max(0.0, 1 - spread / even_spread)
levels = sorted(answer.probabilities)
score_confidence([answer.probabilities[level] for level in levels])
Ответ bug_severity в примере ответа Score имеет вероятности $(0, 0.57, 0.43)$. Наиболее вероятный уровень — 1, расстояние равно $0.43$, а $\text{MAD}_{\text{unif}}$ для трёх уровней равно $\frac{2}{3}$, поэтому уверенность равна $1 - 0.43 / \frac{2}{3} \approx 0.35$.