ДокументацияКонцепции TypeSafeКалиброванная уверенность (Confidence)

Калиброванная уверенность (Confidence)

How TypeSafe reports certainty, how it differs from probability, and how to use it to control system behavior.

Как TypeSafe сообщает о степени определенности, чем она отличается от вероятности и как использовать ее для управления поведением системы.

export function ConfidenceExplorer() {
const [probabilities, setProbabilities] = useState([90, 6, 4]);
const options = ["A", "B", "C"];
function changeProbability(index, value) {
setProbabilities(current => {
const others = [0, 1, 2].filter(i => i !== index);
const remaining = 100 - value;
const previousRemaining = current[others[0]] + current[others[1]];
const next = [...current];
next[index] = value;
next[others[0]] = previousRemaining > 0 ? remaining * current[others[0]] / previousRemaining : remaining / 2;
next[others[1]] = remaining - next[others[0]];
return next;
});
}
function formatProbability(value) {
if (Math.abs(value - 100 / 3) < 0.000001) return "33⅓%";
return ${Number(value.toFixed(1))}%;
}
function choiceConfidence(values) {
const count = values.length;
const peak = Math.max(...values) / 100;
return Math.max(0, Math.min(1, (count * peak - 1) / (count - 1)));
}
const confidence = choiceConfidence(probabilities);
const maximum = Math.max(...probabilities);
const winners = options.filter((option, i) => Math.abs(probabilities[i] - maximum) < 0.000001);
const selected = winners.length === 1 ? Вариант ${winners[0]} : Ничья: ${winners.join(", ")};
const buttonClass = "border px-3 py-2 text-sm hover:bg-zinc-100 dark:hover:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-pink-500";
const buttonStyle = {
borderColor: "#71717a"
};
const eyebrow = {
fontSize: "0.6875rem",
fontWeight: 700,
letterSpacing: "0.08em",
textTransform: "uppercase"
};
return




Вопрос Choice с тремя вариантами

Посмотрите, как распределение вероятностей меняет уверенность



Уверенность

<output className="block text-3xl font-semibold tabular-nums" style={{
color: "#E551BA"
}}>
{confidence.toFixed(2)}


PLAINTEXT api.wedstack.ru/v1
<div role="img" aria-label={`Probability distribution: ${options.map((option, i) => `${option} ${formatProbability(probabilities[i])}`).join(", ")}. ${selected}.`} className="my-6">
    <div className="text-xs text-zinc-600 dark:text-zinc-400">Вероятность</div>
    <div aria-hidden="true" style={{
position: "relative",
height: "180px",
margin: "34px 0 36px 44px"

}}>
{[0, 50, 100].map(tick => <div key={tick} style={{
position: "absolute",
bottom: ${tick}%,
width: "100%",
borderBottom: "1px solid",
borderColor: "color-mix(in srgb, currentColor 18%, transparent)"
}}>
<span className="text-xs" style={{
position: "absolute",
right: "calc(100% + 8px)",
transform: "translateY(-50%)"
}}>{tick}%

)}
<div style={{
position: "absolute",
inset: 0,
display: "flex",
justifyContent: "space-around",
alignItems: "flex-end"
}}>
{options.map((option, index) => <div key={option} style={{
position: "relative",
width: "21%",
height: ${probabilities[index]}%
}}>
<span className="text-sm font-semibold tabular-nums" style={{
position: "absolute",
bottom: "calc(100% + 6px)",
left: "50%",
transform: "translateX(-50%)",
whiteSpace: "nowrap"
}}>{formatProbability(probabilities[index])}
<div style={{
height: "100%",
background: winners.length === 1 && winners[0] === option ? "#E551BA" : "currentColor",
opacity: winners.length === 1 && winners[0] === option ? 1 : 0.45
}} />
<span className="text-sm" style={{
position: "absolute",
top: "calc(100% + 8px)",
left: "50%",
transform: "translateX(-50%)"
}}>{option}
)}


PLAINTEXT api.wedstack.ru/v1
<div className="space-y-3">
    {options.map((option, index) => <label key={option} className="flex items-center gap-3 text-sm">
        <span className="w-5 font-semibold">{option}</span>
        <input type="range" min="0" max="100" step="1" value={probabilities[index]} onChange={event => changeProbability(index, Number(event.target.value))} aria-label={`Probability of ${option}`} aria-valuetext={formatProbability(probabilities[index])} className="min-w-0 flex-1 cursor-pointer" style={{
accentColor: "#E551BA",
minHeight: "44px"

}} />
{formatProbability(probabilities[index])}
)}

Передвигайте ползунок, чтобы изменить вероятность варианта. Остальные вероятности автоматически подстроятся, сохраняя сумму 100%.

PLAINTEXT api.wedstack.ru/v1
<div className="mt-4 flex flex-wrap gap-2" aria-label="Example distributions">
    <button type="button" className={buttonClass} style={buttonStyle} onClick={() => setProbabilities([90, 6, 4])}>Явный победитель</button>
    <button type="button" className={buttonClass} style={buttonStyle} onClick={() => setProbabilities([40, 33, 27])}>Размытое распределение</button>
    <button type="button" className={buttonClass} style={buttonStyle} onClick={() => setProbabilities([100 / 3, 100 / 3, 100 / 3])}>Равное разделение</button>
  </div>
  <div className="mt-4 text-sm" aria-live="polite">{winners.length === 1 ? `Выбрано: ${selected}` : selected}</div>
  <details className="mt-4 text-sm text-zinc-600 dark:text-zinc-400">
    <summary className="cursor-pointer">Как это демо рассчитывает уверенность</summary>
    <p className="mt-3">TypeSafe вычисляет уверенность на основе распределения вероятностей по вариантам. Если вся вероятность приходится на один вариант, значение равно 1.0; чем равномернее распределена вероятность, тем ниже уверенность. В этом демо формула <code>(3 × наибольшая вероятность − 1) / 2</code> аппроксимирует уверенность для трех вариантов.</p>
  </details>
</section>;

}

Все ответы Score и Choice от TypeSafe включают свойство probabilities, представляющее собой распределение вероятностей по вариантам (для Choice) или уровням (для Score). Именно форма этого распределения показывает, насколько модель уверена: концентрация на одном исходе означает уверенный ответ, а размытое распределение — неуверенный.

Свойство confidence в ответе сводит эту форму распределения к единому числу от 0 до 1, позволяя использовать пороговые условия без необходимости производить математические расчеты самостоятельно. (Ответы Noul не содержат отдельного поля confidence.)

Уверенность вычисляется из вероятностей

confidence — это статистическая метрика, вычисляемая из распределения вероятностей, уже присутствующего в ответе. TypeSafe рассчитывает ее за вас и возвращает для каждого ответа Choice и Score, поэтому в стандартных сценариях вам не требуется дополнительная работа.

**Надежное значение по умолчанию:** Мы предоставляем `confidence` как удобную метрику, подходящую для большинства сценариев, однако вы не привязаны исключительно к нашему определению. В зависимости от специфики задачи вам может подойти другая метрика, именно поэтому мы возвращаем полное распределение `probabilities` в ответе. Плюсы и минусы различных способов вычисления — специализированная тема, которую мы вынесем в отдельный кукбук.

Для Choice распределением является probabilities по вашим вариантам. Для Score — распределение по вашим уровням. В обоих случаях более пологое распределение означает меньшую уверенность: низкая уверенность для Choice часто говорит о том, что ни один из вариантов не имеет явного преимущества перед другими, а для Score — что уровни неоднозначны, многомерны, либо состояние содержит недостаточно контекста.

«Я не знаю» — ценный сигнал

Если интеллектуальная система (будь то человек или машина) не способна честно признать свою неуверенность, такой системе нельзя доверять.

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

Три пути использования уверенности в вашем коде

Полезный базовый паттерн — разделить уверенность на три диапазона, каждый из которых запускает свое системное поведение:

Высокая уверенность: Действовать автоматически. Модель имеет однозначную трактовку, и процесс может продолжаться без участия человека.

Средняя уверенность: Действовать с осторожностью. Модель сформировала разумный ответ, но не уверена до конца. В зависимости от контекста вы можете запросить подтверждение у пользователя, отправить кейс на ревью или собрать дополнительную информацию перед выполнением действия.

Низкая уверенность: Не выполнять автоматических действий. Направьте задачу человеку, запросите уточнение или переключитесь на резервную систему. Модель сообщает, что у нее недостаточно данных либо вопрос не подходит для данного случая.

То, где именно вы проведете эти границы, зависит от цены ошибки.

Пороги масштабируются в зависимости от риска

Порог уверенности — это не одно универсальное число. Различные действия внутри одной и той же системы должны контролироваться на разных уровнях в зависимости от последствий возможной ошибки.

PYTHON THEME={NULL} api.wedstack.ru/v1
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:
    # Модель искренне не уверена. Не угадываем.
    route_to_human(user_message)

elif action.choice == "check_balance":
    # Низкие ставки. Ошибочный экран можно исправить.
    show_balance(account_id)

elif action.choice == "approve_transfer":
    if confidence > 0.9:
        # Высокие ставки, высокая уверенность. Выполняем с подтверждением.
        confirm_then_execute(account_id)
    else:
        # Высокие ставки, умеренная уверенность. Сначала верифицируем.
        ask_user_to_confirm(account_id)

Нижний порог уверенности 0.5 отсекает всё, в чем модель искренне сомневается. Выше этой планки порог для действий без подтверждения для разрушительных операций значительно выше, чем для операций чтения. Ваш код выражает допустимый уровень риска.

Корректные пороговые значения зависят от вашей предметной области и точности работы модели в вашей конкретной задаче. Начните с консервативных порогов, протестируйте их на собственных данных и корректируйте по мере накопления результатов.