Documentação

Score

Um Score é um tipo de pergunta do System One para avaliar conteúdo segundo níveis ordenados e descritivos. A resposta inclui uma pontuação, uma probabilidade para cada nível e a confiança.

Use um Score quando a resposta é uma posição num espectro que você consegue descrever em passos. Por exemplo, quão grave é um bug, quão satisfeito está um cliente ou quanta experiência um candidato tem com Python. Se a resposta é uma de um conjunto fixo de opções sem ordem entre elas, use um Choice. Se for sim ou não, use um Noul. Escolha um tipo de pergunta compara os três.

Uma resposta de Score é uma posição ao longo dos seus níveis em score, que pode cair entre dois níveis. O modelo também retorna uma probabilidade para cada nível em probabilities, e um valor de confidence para a resposta.

Exemplo: pergunta score

How severe is the reported issue?

0 Cosmetic; no impact to functionality
1 Broken or degraded feature, but workaround exists
2 Blocking issue; no workaround exists

Estado (conteúdo a avaliar)

The export button crashes the settings page in Safari. It works in Chrome, but a few of our customers only use Safari.

Resposta

Probabilidade de cada nível

Confiança

0.35

Score: 1.43

Como o score e a confiança são calculados

Score:

Multiplique o número de cada nível pela sua probabilidade e some os resultados:

0 × 0 + 1 × 0.57 + 2 × 0.43 ≈ 1.43

Confiança

O TypeSafe a calcula a partir de como a probabilidade se espalha entre os níveis. Tudo em um só nível dá 1.0; quanto mais uniforme, menor a confiança.

How formal is this outfit based on the description?

0 gym clothes
1 casual
2 business casual
3 formal
4 black tie

Estado (conteúdo a avaliar)

A navy blazer over a plain white T-shirt, dark jeans, and clean leather loafers. No tie.

Resposta

Probabilidade de cada nível

Confiança

0.89

Score: 1.86

Como o score e a confiança são calculados

Score:

Multiplique o número de cada nível pela sua probabilidade e some os resultados:

0 × 0 + 1 × 0.14 + 2 × 0.86 + 3 × 0 + 4 × 0 ≈ 1.86

Confiança

O TypeSafe a calcula a partir de como a probabilidade se espalha entre os níveis. Tudo em um só nível dá 1.0; quanto mais uniforme, menor a confiança.

How relevant is this candidate's experience to the job posting?

0 completely unrelated
1 adjacent field
2 some direct experience
3 deep, direct experience

Estado (conteúdo a avaliar)

Job posting: Senior backend engineer building Python APIs and PostgreSQL services. Candidate: Three years building Django REST APIs with PostgreSQL, preceded by two years in frontend JavaScript. Has owned small services but has not led a backend team.

Resposta

Probabilidade de cada nível

Confiança

0.52

Score: 2.52

Como o score e a confiança são calculados

Score:

Multiplique o número de cada nível pela sua probabilidade e some os resultados:

0 × 0 + 1 × 0 + 2 × 0.48 + 3 × 0.52 ≈ 2.52

Confiança

O TypeSafe a calcula a partir de como a probabilidade se espalha entre os níveis. Tudo em um só nível dá 1.0; quanto mais uniforme, menor a confiança.

How frustrated is the customer?

0 Calm, just stating facts
1 Frustrated but civil
2 Very angry, strong language or threatening to leave

Estado (conteúdo a avaliar)

Export to PDF fails with a spinner that never finishes. Some of our team say CSV export still works for them, others say it fails too. This is the third time I'm writing in and honestly I'm done. Steps: open any report, click Export, choose PDF. Chrome 128 on macOS.

Resposta

Probabilidade de cada nível

Confiança

0.61

Score: 1.26

Como o score e a confiança são calculados

Score:

Multiplique o número de cada nível pela sua probabilidade e some os resultados:

0 × 0 + 1 × 0.74 + 2 × 0.26 ≈ 1.26

Confiança

O TypeSafe a calcula a partir de como a probabilidade se espalha entre os níveis. Tudo em um só nível dá 1.0; quanto mais uniforme, menor a confiança.

How much does the report give an engineer to work with?

0 No detail; just says something is broken
1 Names the feature but no steps or environment
2 Steps to reproduce or environment, but not both
3 Steps to reproduce and environment

Estado (conteúdo a avaliar)

Export to PDF fails with a spinner that never finishes. Some of our team say CSV export still works for them, others say it fails too. This is the third time I'm writing in and honestly I'm done. Steps: open any report, click Export, choose PDF. Chrome 128 on macOS.

Resposta

Probabilidade de cada nível

Confiança

1.00

Score: 3.00

Como o score e a confiança são calculados

Score:

Multiplique o número de cada nível pela sua probabilidade e some os resultados:

0 × 0 + 1 × 0 + 2 × 0 + 3 × 1 ≈ 3.00

Confiança

O TypeSafe a calcula a partir de como a probabilidade se espalha entre os níveis. Tudo em um só nível dá 1.0; quanto mais uniforme, menor a confiança.

Os números à frente de cada passo são posições, explicadas em Níveis.

Estrutura da requisição

O corpo da requisição POST para a API da TypeSafe tem os mesmos três campos de nível superior que qualquer outro tipo de pergunta: state, que é o conteúdo a avaliar; model; e questions. Cada pergunta Score tem os seguintes campos:

  • type: Sempre "score".
  • instructions: A pergunta que o modelo responde. O que está sendo avaliado.
  • criteria: Um array ordenado de descrições de nível, do extremo baixo da escala ao alto. Deve ter pelo menos dois níveis; a API aceita até 10.

Abaixo está uma requisição em que o estado é um relatório de bug e a pergunta é quão grave o bug é:

request
{
  "state": "The export button crashes the settings page in Safari. It works in Chrome, but a few of our customers only use Safari.",
  "questions": {
    "bug_severity": {
      "type": "score",
      "instructions": "How severe is the reported issue?",
      "criteria": [
        "Cosmetic; no impact to functionality",
        "Broken or degraded feature, but workaround exists",
        "Blocking issue; no workaround exists"
      ]
    }
  }
}

Você escolhe o id da pergunta, bug_severity neste caso. Este id não é enviado ao modelo. A resposta é retornada sob o mesmo id.

Níveis

Cada entrada em criteria é um nível: um ponto no espectro de respostas possíveis, descrito em palavras. O número de um nível é a sua posição no array criteria, começando em 0, então as três entradas acima são os níveis 0, 1 e 2. A ordem do array é a numeração.

O modelo recebe as descrições e nada mais, e cada nível é julgado por si só em relação ao estado.

O score na resposta é uma posição no espectro de níveis. Para uma escala de três níveis, vai de 0 a 2, e pode cair entre dois níveis.

Nossos SDKs de cliente fornecem perguntas tipadas. Em Python, a mesma pergunta é um Score:

from typesafe_sdk import Score, TypeSafeClient

with TypeSafeClient() as client:
    response = client.system_one(
        state="The export button crashes the settings page in Safari. It works in Chrome, but a few of our customers only use Safari.",
        questions={
            "bug_severity": Score(
                instructions="How severe is the reported issue?",
                criteria=[
                    "Cosmetic; no impact to functionality",
                    "Broken or degraded feature, but workaround exists",
                    "Blocking issue; no workaround exists",
                ],
            ),
        },
    )

    print(response.answers["bug_severity"].score)

Use o método system_one ou o endpoint https://api.typesafe.ai/v1/systemone para chamar um modelo System One. O campo model seleciona qual modelo cuida da requisição. Como construir com TypeSafe cobre onde chamá-lo no seu código.

Use um dos nossos SDKs de cliente ou chame a API da TypeSafe diretamente. Se um agente de código estiver escrevendo a integração para você, instale antes a skill de agente da TypeSafe para que ele conheça os formatos de requisição e resposta.

Estrutura da resposta

A resposta tem uma entrada em answers por pergunta, sob os ids da requisição. Esta é a resposta para a requisição de exemplo acima:

{
  "model": "jev-1.13.0",
  "answers": {
    "bug_severity": {
      "type": "score",
      "score": 1.43,
      "confidence": 0.35,
      "legend": {
        "0": "Cosmetic; no impact to functionality",
        "1": "Broken or degraded feature, but workaround exists",
        "2": "Blocking issue; no workaround exists"
      },
      "probabilities": {
        "0": 0.0,
        "1": 0.57,
        "2": 0.43
      }
    }
  },
  "usage": {
    "input_tokens": 332,
    "output_tokens": 18
  }
}

Cada resposta de Score tem cinco valores:

  • type: O tipo de pergunta da TypeSafe.
  • probabilities: A probabilidade de cada nível, com o número do nível como chave em forma de string. A soma de todos os valores é 1.
  • score: A posição na reta numérica dos níveis, de 0 até o número do nível mais alto, que aqui é 2. É cada número de nível multiplicado pela sua probabilidade, somado: 0 x 0.0 + 1 x 0.57 + 2 x 0.43 = 1.43.
  • legend: Cada número de nível mapeado de volta para a sua descrição.
  • confidence: Um número de 0 a 1 calculado a partir de como probabilities está distribuída. Um único pico num nível significa confiança alta. Probabilidade espalhada por vários níveis significa confiança baixa.

Uma pontuação de 1.43 significa que o modelo está dividido entre os níveis 1 e 2, pendendo para o nível 1. Isso combina com o relatório: a exportação está quebrada, e mudar para o Chrome é uma solução alternativa para a maioria dos clientes, mas não para os que só usam Safari. O modelo coloca 0.57 em “existe solução alternativa” e 0.43 em “não há solução alternativa”, e a confiança é 0.35 porque está dividida.

Com o SDK de Python, ScoreAnswer tem score, confidence, probabilities e legend como campos tipados. O SDK indexa probabilities e legend pelo nível inteiro, em vez de pela string.

Ler um Score

Vejamos como a pontuação muda com entradas diferentes. Por exemplo, usando a pergunta e seus níveis da requisição acima:

"How severe is the reported issue?"
  → 0: Cosmetic; no impact to functionality
  → 1: Broken or degraded feature, but workaround exists
  → 2: Blocking issue; no workaround exists

Podemos ver como relatórios de bug diferentes mudam a pontuação:

probabilities
EstadoscoreconfidenceNível 0Nível 1Nível 2
O botão de exportar está desalinhado por alguns pixels na página de configurações.0.01.01.00.00.0
O botão de exportar para PDF não faz nada quando clicado. Ainda consigo exportar para CSV e converter eu mesmo, mas isso demora uma eternidade.1.01.00.01.00.0
A exportação para PDF falha com um indicador de carregamento que nunca termina. Alguns da nossa equipe dizem que a exportação para CSV ainda funciona para eles, outros dizem que também falha.1.110.840.00.890.11
O botão de exportar trava a página de configurações no Safari. Funciona no Chrome, mas alguns dos nossos clientes só usam Safari.1.430.350.00.570.43
Ninguém da nossa equipe consegue entrar desde hoje de manhã. Recebemos um erro 500 em cada tentativa.2.01.00.00.01.0

Nestes exemplos, confiança 1.0 significa que a distribuição retornada coloca toda a sua probabilidade num nível. Isso descreve a resposta do modelo, não uma garantia de que a resposta está correta.

A pontuação é uma média ponderada pela probabilidade dos números de nível. No terceiro e no quarto exemplo, a probabilidade está dividida entre os níveis 1 e 2. Mais peso no nível 2 eleva a pontuação. Ela não mede a fração de clientes sem solução alternativa.

Distribuições diferentes podem produzir a mesma pontuação. Uma pontuação de 1.0 pode significar que toda a probabilidade está no nível 1, ou que metade está em cada um dos níveis 0 e 2. Leia probabilities e confidence junto com a pontuação para distinguir esses casos.

Uma pontuação fracionária é uma posição. Você pode usá-la para ordenar relatórios por gravidade, ou arredondá-la para o nível mais próximo quando o código precisar de um único resultado. Nosso cookbook de alinhamento de entidades mostra um exemplo de arredondamento para o nível mais próximo para tomar uma decisão.

Confiança baixa num Score geralmente significa uma de três coisas. Os níveis se sobrepõem para este estado, a pergunta mede mais de uma coisa, ou o estado não diz o suficiente para situá-lo. Nossa documentação de Confiança cobre como usá-la no seu código.

Escrever bons níveis

Descreva situações, não graus. “Funcionalidade quebrada ou degradada, mas existe solução alternativa” dá ao modelo algo com que comparar o estado. “Moderadamente grave” não dá. Descrições concretas podem ajudar o modelo a distinguir os níveis. Verifique as respostas em relação a exemplos conhecidos; confiança mais alta por si só não mostra que uma descrição é melhor.

Cada nível é avaliado separadamente. O modelo não vê o número de um nível nem os seus vizinhos, então “pior que o nível anterior” não significa nada para ele, e números nas descrições ou nas instruções não ajudam. Veja o que acontece quando os níveis são só números, no relatório do botão desalinhado da tabela acima:

instructions: "Rate severity from 0 to 2, where 2 is worst"
criteria: ["0", "1", "2"]
→ score 0.55, confidence 0.33, probabilities 0: 0.45, 1: 0.55, 2: 0.0

O mesmo relatório com os três níveis descritivos pontua 0.0 com confiança 1.0. Com apenas números, o modelo não tem nada com que comparar e divide a probabilidade entre 0 e 1.

Use tantos níveis quantos você conseguir descrever de forma distinta, até 10. Três está bom. Não adicione níveis que você não consegue descrever de forma distinta.

Mantenha cada pergunta Score numa única dimensão. Se uma descrição diz “pontual e inteligente e experiente”, a pergunta está medindo três coisas, e uma entrada que é alta numa e baixa em outra não pode ser situada. A confiança cai e a pontuação significa menos. Divida-a numa pergunta Score por coisa e combine-as no código, como mostra a próxima seção.

Se o topo da sua escala tem um caso extremo raro sobre o qual você precisa agir de forma diferente, dê a ele o seu próprio nível. Uma escala de sentimento que termina em “muito irritado” pode acrescentar “abusivo ou ameaçador”. Sem esse nível, as duas mensagens podem receber uma pontuação perto do topo. A pontuação sozinha pode não distingui-las.

Se não houver nada intermediário, e a resposta for uma de algumas categorias discretas, use um Choice em vez disso, ou divida a pergunta em várias perguntas Noul. É importante testar seus níveis com os seus próprios dados. Duas redações da mesma escala podem se comportar de forma diferente nos seus dados.

Dividir um julgamento complexo em várias perguntas Score

Um julgamento complexo, que depende de várias coisas, é melhor dividido em uma pergunta Score por coisa. Você pode então combinar no código os Scores retornados pela TypeSafe para fazer o julgamento. Algumas perguntas Score podem importar mais que outras, então dê a cada pergunta Score um peso para a sua importância relativa. Os pesos são seus. Quando o resultado combinado não corresponder ao que sua equipe decidiria, mude-os no código e execute de novo. Envie as perguntas Score numa única requisição. Elas são avaliadas em paralelo. Adicionar perguntas quase não muda o tempo de resposta e custa alguns tokens de pergunta a mais; veja Faça várias perguntas juntas.

A requisição abaixo é o ticket do indicador de carregamento da tabela acima com um pouco mais de contexto. Ela faz três perguntas Score: quão grave é o bug, quão frustrado está o cliente e quanta informação o relatório dá a um engenheiro.

request
{
  "state": "Export to PDF fails with a spinner that never finishes. Some of our team say CSV export still works for them, others say it fails too. This is the third time I'm writing in and honestly I'm done. Steps: open any report, click Export, choose PDF. Chrome 128 on macOS.",
  "questions": {
    "severity": {
      "type": "score",
      "instructions": "How severe is the reported issue?",
      "criteria": [
        "Cosmetic; no impact to functionality",
        "Broken or degraded feature, but workaround exists",
        "Blocking issue; no workaround exists"
      ]
    },
    "frustration": {
      "type": "score",
      "instructions": "How frustrated is the customer?",
      "criteria": [
        "Calm, just stating facts",
        "Frustrated but civil",
        "Very angry, strong language or threatening to leave"
      ]
    },
    "report_quality": {
      "type": "score",
      "instructions": "How much does the report give an engineer to work with?",
      "criteria": [
        "No detail; just says something is broken",
        "Names the feature but no steps or environment",
        "Steps to reproduce or environment, but not both",
        "Steps to reproduce and environment"
      ]
    }
  }
}

A resposta da TypeSafe:

{
  "model": "jev-1.13.0",
  "answers": {
    "severity": {
      "type": "score",
      "score": 1.24,
      "confidence": 0.64,
      "legend": {
        "0": "Cosmetic; no impact to functionality",
        "1": "Broken or degraded feature, but workaround exists",
        "2": "Blocking issue; no workaround exists"
      },
      "probabilities": {
        "0": 0.0,
        "1": 0.76,
        "2": 0.24
      }
    },
    "frustration": {
      "type": "score",
      "score": 1.28,
      "confidence": 0.58,
      "legend": {
        "0": "Calm, just stating facts",
        "1": "Frustrated but civil",
        "2": "Very angry, strong language or threatening to leave"
      },
      "probabilities": {
        "0": 0.0,
        "1": 0.72,
        "2": 0.28
      }
    },
    "report_quality": {
      "type": "score",
      "score": 3.0,
      "confidence": 1.0,
      "legend": {
        "0": "No detail; just says something is broken",
        "1": "Names the feature but no steps or environment",
        "2": "Steps to reproduce or environment, but not both",
        "3": "Steps to reproduce and environment"
      },
      "probabilities": {
        "0": 0.0,
        "1": 0.0,
        "2": 0.0,
        "3": 1.0
      }
    }
  },
  "usage": {
    "input_tokens": 468,
    "output_tokens": 43
  }
}

Cada pergunta é respondida por conta própria em relação ao ticket e recebe uma pontuação:

  • severity é 1.24 com confiança 0.64. Mesma leitura do exemplo inicial: a exportação está quebrada e alguns têm uma solução alternativa.
  • frustration é 1.28 com confiança 0.58. As palavras são cordiais, mas “terceira vez” e “já era” deslocam parte da pontuação para o nível mais alto, então o modelo divide 0.72 e 0.28 entre “frustrado mas cordial” e “muito irritado”. Para este ticket os dois níveis se sobrepõem, e por isso a confiança é moderada.
  • report_quality é 3.0 com confiança 1.0. Tanto os passos quanto a versão do navegador são informados.

As três escalas têm comprimentos diferentes, então antes de combiná-las, normalize cada pontuação. Uma escala de quatro níveis retorna de 0 a 3 e uma de três níveis retorna de 0 a 2, então a pontuação máxima numa é maior que na outra. Divida cada pontuação pelo número do seu nível mais alto, len(criteria) - 1, para colocar todas as pontuações entre 0 e 1. Então os pesos significam o que dizem: 0.6 em severity e 0.3 em frustration fazem severity contar o dobro.

O código do SDK de Python da TypeSafe abaixo faz as três perguntas, normaliza cada pontuação e as combina usando um cálculo de prioridade de exemplo:

from typesafe_sdk import Score, TypeSafeClient

TRIAGE_QUESTIONS = {
    "severity": Score(
        instructions="How severe is the reported issue?",
        criteria=[
            "Cosmetic; no impact to functionality",
            "Broken or degraded feature, but workaround exists",
            "Blocking issue; no workaround exists",
        ],
    ),
    "frustration": Score(
        instructions="How frustrated is the customer?",
        criteria=[
            "Calm, just stating facts",
            "Frustrated but civil",
            "Very angry, strong language or threatening to leave",
        ],
    ),
    "report_quality": Score(
        instructions="How much does the report give an engineer to work with?",
        criteria=[
            "No detail; just says something is broken",
            "Names the feature but no steps or environment",
            "Steps to reproduce or environment, but not both",
            "Steps to reproduce and environment",
        ],
    ),
}

def normalized(answers, question_id: str) -> float:
    """Put a score on 0 to 1 by dividing by its top level number."""
    top_level = len(TRIAGE_QUESTIONS[question_id].criteria) - 1
    return answers[question_id].score / top_level

def priority(ticket: str) -> float:
    with TypeSafeClient() as client:
        response = client.system_one(
            state=ticket,
            questions=TRIAGE_QUESTIONS,
        )
    answers = response.answers

    severity = normalized(answers, "severity")
    frustration = normalized(answers, "frustration")
    report_quality = normalized(answers, "report_quality")

    # A detailed report helps an engineer investigate, so it raises priority a little.
    return 0.6 * severity + 0.3 * frustration + 0.1 * report_quality

Para a resposta de exemplo acima, as pontuações normalizadas são 0.62 para severity, 0.64 para frustration e 1.0 para report quality. A prioridade é 0.6 × 0.62 + 0.3 × 0.64 + 0.1 × 1.0 = 0.664, que arredonda para 0.66.

Os pesos ficam no seu código, então você vê exatamente como o número é formado e pode mudá-lo quando a ordenação não corresponder ao que sua equipe faria. Se mais tarde você precisar de mais perguntas Score, adicione-as a TRIAGE_QUESTIONS. A contagem de requisições continua em uma. Esta técnica de dividir um julgamento complexo em Scores separados e depois combiná-los com pesos no seu código é chamada de padrão Pontuação composta.

Descrições de nível estruturadas

Comece com uma descrição de texto básica para cada nível. Quando o modelo continuar pontuando entre dois níveis vizinhos em entradas que você considera claras, dê a cada nível um objeto em vez de uma string, com um campo para o que o nível cobre e um campo com alguns exemplos de situações. Use os mesmos nomes de campo em todos os níveis, para que o modelo possa comparar coisas equivalentes.

A requisição abaixo é o ticket do indicador de carregamento que usamos antes, mas com exemplos em cada nível:

request
{
  "state": "Export to PDF fails with a spinner that never finishes. Some of our team say CSV export still works for them, others say it fails too.",
  "questions": {
    "bug_severity": {
      "type": "score",
      "instructions": "How severe is the reported issue?",
      "criteria": [
        {
          "what": "Cosmetic; no impact to functionality",
          "examples": [
            "typo in a label",
            "misaligned icon"
          ]
        },
        {
          "what": "Broken or degraded feature, but workaround exists",
          "examples": [
            "export fails in one browser but works in another"
          ]
        },
        {
          "what": "Blocking issue; no workaround exists",
          "examples": [
            "cannot log in",
            "data loss"
          ]
        }
      ]
    }
  }
}

A resposta:

{
  "model": "jev-1.13.0",
  "answers": {
    "bug_severity": {
      "type": "score",
      "score": 1.09,
      "confidence": 0.87,
      "legend": {
        "0": {
          "what": "Cosmetic; no impact to functionality",
          "examples": [
            "typo in a label",
            "misaligned icon"
          ]
        },
        "1": {
          "what": "Broken or degraded feature, but workaround exists",
          "examples": [
            "export fails in one browser but works in another"
          ]
        },
        "2": {
          "what": "Blocking issue; no workaround exists",
          "examples": [
            "cannot log in",
            "data loss"
          ]
        }
      },
      "probabilities": {
        "0": 0.0,
        "1": 0.91,
        "2": 0.09
      }
    }
  },
  "usage": {
    "input_tokens": 379,
    "output_tokens": 18
  }
}

Com strings simples, este ticket pontuou 1.11 com confiança 0.84. Com exemplos, pontua 1.09 com confiança 0.87, uma mudança pequena porque as strings simples já o situavam bem. O efeito é maior quando as strings simples deixam o modelo dividido, como mostra a próxima tabela.

Os exemplos orientam o modelo, e só ajudam quando se parecem com as suas entradas reais. A tabela abaixo é o relatório do Safari inicial com três conjuntos diferentes de objetos de nível:

Descrição do nível score confidence
string simples: sem objeto com exemplos 1.43 0.35
array de examples acrescentado com um exemplo útil: “a exportação falha num navegador mas funciona em outro” 1.03 0.96
array de examples acrescentado com um exemplo não relacionado a navegadores: “a busca falha, mas navegar pelas categorias ainda funciona” 1.43 0.35

Nesta comparação, o exemplo que corresponde concentra quase toda a probabilidade num nível. O exemplo não relacionado retorna o mesmo resultado que as strings simples. Confiança mais alta não estabelece qual resposta está correta. Escolha exemplos com níveis esperados conhecidos e depois teste as descrições revisadas em entradas separadas antes de mantê-las.