Confianza
Cómo informa TypeSafe la certeza, en qué se diferencia de la probabilidad y cómo usarla para controlar el comportamiento del sistema.
Todas las respuestas de Score y Choice de TypeSafe incluyen una propiedad probabilities que representa la distribución de probabilidad entre las opciones (en Choice) o los niveles (en Score). La forma de esa distribución es lo que te dice cuán seguro está el modelo: concentrada en un solo resultado significa una respuesta con confianza, y repartida significa una respuesta incierta.
La propiedad confidence de la respuesta condensa esa forma en un único número de 0 a 1, para que puedas aplicar un umbral sobre él sin hacer tú los cálculos. Es 1 cuando toda la probabilidad está en un solo resultado y 0 cuando la probabilidad está repartida por igual. (Las respuestas de Noul no la incluyen; consulta más abajo Noul.)
La confianza se deriva de las probabilidades
confidence es un estadístico calculado a partir de la distribución de probabilidad que la respuesta ya te proporciona. TypeSafe lo calcula por ti y lo devuelve en cada respuesta de Choice y Score, así que el caso habitual no requiere trabajo adicional por tu parte.
Ejemplo: pregunta choice con tres opciones
Mira cómo la distribución de probabilidad cambia la confianza
Confianza
Probabilidad
Arrastra el control para cambiar la probabilidad de una opción. Las demás se ajustan solas para que la suma siga siendo 100%.
Seleccionado: Opciones A
Cómo se calcula aquí la confianza
TypeSafe calcula la confianza a partir de cómo se reparte la probabilidad entre las opciones. Si todo se concentra en una, es 1.0; cuanto más repartida esté, más baja. Esta demo usa (3 × probabilidad máxima − 1) / 2 para aproximar la confianza con tres opciones.
Para un Choice, la distribución es probabilities entre tus opciones. Para un Score, es la distribución entre tus niveles. En ambos casos, una distribución más plana significa menor confianza: una confianza baja en un Choice suele indicar que ninguna opción gana con claridad a las demás, y una confianza baja en un Score suele indicar que los niveles son ambiguos, multidimensionales, o que el estado no contiene suficiente información.
La fórmula exacta de cada tipo de pregunta está en Cómo se calcula la confianza, para que veas cómo cualquier valor de confidence se deriva de las probabilities propias de la respuesta.
«No lo sé» es una señal útil
Si un sistema inteligente, sea humano o máquina, no puede expresar incertidumbre con honestidad, no se puede confiar en él.
La confianza le da al modelo un mecanismo incorporado para decir «no estoy seguro de esto». Esto permite que tu código implemente un comportamiento distinto según el nivel de certeza, que es la base para construir sistemas en los que de verdad puedas confiar.
Tres caminos para usar la confianza en tu código
Un patrón inicial útil es dividir la confianza en tres rangos, cada uno con un comportamiento del sistema distinto:
Confianza alta: Actúa automáticamente. El modelo tiene una lectura clara y puedes proceder sin intervención humana.
Confianza media: Procede con cautela. El modelo tiene una respuesta razonable, pero no está seguro. Según el contexto, puedes pedir confirmación al usuario, marcar el caso para revisión o reunir más información antes de actuar.
Confianza baja: No actúes. Deriva a una persona, pide aclaración o recurre a otro sistema. El modelo te está diciendo que no tiene suficiente información o que la pregunta no encaja bien.
Dónde trazas esos límites depende de lo que esté en juego.
Los umbrales escalan con el riesgo
Un umbral de confianza no es un único número. Las distintas acciones dentro de un mismo sistema deberían condicionarse a niveles distintos según las consecuencias de equivocarse.
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)
El piso de confianza de 0.5 atrapa todo lo que el modelo reporta como genuinamente incierto. Por encima de eso, el umbral para actuar sin confirmación es más alto para una operación destructiva que para una de solo lectura. Tu código codifica la tolerancia al riesgo.
Cómo se calcula la confianza
Cada tipo de pregunta resume su distribución de forma un poco distinta. Un Noul tiene dos resultados, un Choice tiene cualquier número de opciones en un orden cualquiera, y los niveles de un Score están ordenados, así que cada fórmula de abajo se apoya en la anterior.
La confidence de TypeSafe es una forma razonable de resumir una distribución, no la única. Devolvemos una medida fija para que cada respuesta venga con un valor predeterminado sensato: puedes condicionar por confidence desde tu primera llamada, en la misma escala de 0 a 1 para toda pregunta, sin elegir y validar antes una estadística propia. Como las fórmulas de abajo son exactas y cada respuesta incluye sus probabilities completas, puedes calcular en su lugar la medida que más importe para tu aplicación.
Noul
Una respuesta de Noul es una única probabilidad $p$ de que la respuesta sea sí, y TypeSafe no devuelve un confidence aparte para ella. La probabilidad ya conlleva la incertidumbre: un valor cercano a 0.5 es el modelo diciendo que no está seguro, y la página Noul explica cómo aplicar un umbral directamente sobre ella.
Si de todos modos quieres un número al estilo de la confianza, por ejemplo para condicionar Nouls y Choices con el mismo código, usa la distancia a 0.5:
$$ \text{confidence} = |2p - 1| $$
Esto da 0 en $p = 0.5$ y 1 en $p = 0$ o $p = 1$. También es la fórmula de Choice de abajo aplicada a un Choice de sí/no, así que queda en la misma escala que la confianza de Choice.
Choice
Un Choice extiende la misma idea a cualquier número de opciones. Para un Choice con $n$ opciones, donde $p_{\max}$ es la probabilidad de la opción seleccionada:
$$ \text{confidence} = \frac{p_{\max} - \frac{1}{n}}{1 - \frac{1}{n}} $$
Esto mide cuánto se sitúa la probabilidad más alta por encima de un reparto equitativo de $\frac{1}{n}$ por opción, en una escala donde el reparto equitativo es 0 y la certeza es 1. Solo cuenta la probabilidad más alta, así que $(0.6, 0.3, 0.1)$ y $(0.6, 0.2, 0.2)$ tienen ambas confianza 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()))
El explorador de la parte superior de esta página usa esta fórmula con tres opciones.
Otras dos medidas más simples, calculadas a partir de las mismas probabilities, suelen ser muy eficaces en la práctica y vale la pena probarlas junto a confidence:
- Probabilidad más alta, $p_{\max}$. Se lee directamente como «qué probable es la opción seleccionada», lo que hace fáciles de razonar los umbrales. Su significado depende del número de opciones, ya que 0.5 es una respuesta débil entre dos opciones y una fuerte entre diez, así que fija su umbral por pregunta.
- Relación entre la más alta y la segunda, $p_{\max} / p_{\text{second}}$. Mide con qué claridad la opción seleccionada supera a la segunda y pasa por alto cómo se reparte el resto. Muchas decisiones reales se reducen a los dos candidatos principales, y esta relación apunta justo a eso.
Score
Los niveles de un Score están ordenados, así que su fórmula también cuenta cuánto se aleja la probabilidad del nivel más probable. Para un Score con $n$ niveles numerados de $0$ a $n - 1$, donde $p_i$ es la probabilidad del nivel $i$ y $m$ es el nivel más probable:
$$ \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| $$
La suma del numerador es la distancia media ponderada por probabilidad, en niveles, entre la respuesta y el nivel más probable. $\text{MAD}_{\text{unif}}$ es el mismo tipo de distancia media para un reparto equitativo entre todos los niveles, medida desde el nivel central. La confianza compara las dos, y se limita a 0 cuando la respuesta está al menos tan repartida como un reparto equitativo.
La probabilidad en un nivel vecino reduce la confianza menos que la misma probabilidad en un nivel más lejano. Con tres niveles, $(0, 0.5, 0.5)$ tiene confianza 0.25, porque el modelo está dividido entre dos niveles adyacentes. $(0.5, 0, 0.5)$ tiene confianza 0, porque está dividido entre extremos opuestos. La fórmula de Choice daría a ambas distribuciones 0.25.
Pregunta de puntuación con cinco niveles
Mira cómo la distancia entre niveles cambia la confianza
Confianza
Probabilidad
Mueve un control para cambiar la probabilidad de un nivel. Las demás se ajustan para mantener el total en 100 %.
- Puntuación
- 2.00
- Fórmula de Choice con las mismas probabilidades
- 0.88
Cómo calcula la confianza esta demostración
Esta demostración usa la fórmula de Score: toma la distancia media, en niveles, entre la respuesta y el pico, ponderada por la probabilidad. La divide entre 1.2, la misma media para un reparto uniforme en cinco niveles medida desde el nivel central, y resta el resultado de 1, sin bajar de 0. La probabilidad en un nivel contiguo al pico reduce menos la confianza que la probabilidad alejada de él, algo que la fórmula de Choice no tiene en cuenta.
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])
La respuesta de bug_severity en el ejemplo de respuesta de Score tiene probabilidades $(0, 0.57, 0.43)$. El nivel más probable es 1, la distancia es $0.43$, y $\text{MAD}_{\text{unif}}$ para tres niveles es $\frac{2}{3}$, así que la confianza es $1 - 0.43 / \frac{2}{3} \approx 0.35$.