Documentação

Score

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

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

Uma resposta de Score é uma posição ao longo dos teus níveis em score, que pode cair entre dois níveis. O modelo também devolve 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 calcula isto a partir de como a probabilidade se distribui entre os níveis. Tudo num 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 calcula isto a partir de como a probabilidade se distribui entre os níveis. Tudo num 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 calcula isto a partir de como a probabilidade se distribui entre os níveis. Tudo num 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 calcula isto a partir de como a probabilidade se distribui entre os níveis. Tudo num 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 calcula isto a partir de como a probabilidade se distribui entre os níveis. Tudo num 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 do pedido

O corpo do pedido POST para a API da TypeSafe tem os mesmos três campos de topo 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 a que o modelo responde. O que está a avaliar.
  • criteria: Um array ordenado de descrições de níveis, do extremo inferior da escala ao extremo superior. Deve ter pelo menos dois níveis; a API aceita até 10.

Abaixo está um pedido 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"
      ]
    }
  }
}

Escolhes tu o id da pergunta, bug_severity neste caso. Este id não é enviado ao modelo. A resposta é devolvida com o mesmo id.

Níveis

Cada entrada de criteria é um nível: um ponto no espetro de respostas possíveis, descrito por palavras. O número de um nível é a sua posição no array criteria, a começar em 0, por isso 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ó face ao estado.

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

Os nossos SDK 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)

Usa 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 o modelo que trata do pedido. Como construir com a TypeSafe explica em que parte do teu código o chamar.

Usa um dos nossos SDK de cliente ou chama diretamente a API da TypeSafe. Se um agente de programação estiver a escrever a integração por ti, instala primeiro a habilidade de agente da TypeSafe para que ele conheça as formas do pedido e da resposta.

Estrutura da resposta

A resposta tem uma entrada em answers por pergunta, com os ids do pedido. Esta é a resposta ao pedido de exemplo de cima:

{
  "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 string. A soma de todos os valores é 1.
  • score: A posição na linha dos números de nível, de 0 ao número do nível superior, 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ído. Um único pico num nível significa confiança alta. Probabilidade repartida 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. Isto corresponde ao relatório: a exportação está avariada, 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.

Usando o SDK de Python, ScoreAnswer tem score, confidence, probabilities e legend como campos tipados. O SDK usa o nível inteiro, e não a string, como chave de probabilities e legend.

Ler um Score

Vejamos como a pontuação muda com diferentes entradas. Por exemplo, usando a pergunta e os seus níveis do pedido de cima:

"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 diferentes relatórios de bug alteram a pontuação:

probabilities
EstadoscoreconfidenceNível 0Nível 1Nível 2
O botão de exportar está desalinhado por alguns píxeis na página de definiçõ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 convertê-lo eu, mas isso demora imenso.1.01.00.01.00.0
A exportação para PDF falha com um indicador de carregamento que nunca termina. Alguns da nossa equipa dizem que exportar para CSV ainda lhes funciona, outros dizem que também falha.1.110.840.00.890.11
O botão de exportar bloqueia a página de definições no Safari. Funciona no Chrome, mas alguns dos nossos clientes só usam Safari.1.430.350.00.570.43
Ninguém da nossa equipa consegue iniciar sessão desde esta manhã. Recebemos um erro 500 em cada tentativa.2.01.00.00.01.0

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

A pontuação é uma média dos números de nível ponderada pelas probabilidades. No terceiro e no quarto exemplos, a probabilidade reparte-se entre os níveis 1 e 2. Mais peso no nível 2 faz subir a pontuação. 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. Lê probabilities e confidence a par da pontuação para distinguires estes casos.

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

Uma confiança baixa num Score costuma significar uma de três coisas. Os níveis sobrepõem-se para este estado, a pergunta está a medir mais do que uma coisa, ou o estado não diz o suficiente para o situar. A nossa documentação de Confiança explica como a usar no teu código.

Escrever bons níveis

Descreve situações, não graus. “Funcionalidade avariada 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 níveis. Verifica as respostas contra exemplos conhecidos; uma confiança mais alta, por si só, não mostra que uma descrição é melhor.

Cada nível é avaliado em separado. O modelo não vê o número de um nível nem os seus vizinhos, por isso “pior do que o nível anterior” não lhe diz nada, e números nas descrições ou nas instruções não ajudam. Eis o que acontece quando os níveis são apenas números, no relatório do botão desalinhado da tabela de cima:

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 obtém 0.0 com uma confiança de 1.0. Apenas com números, o modelo não tem nada com que comparar e reparte a probabilidade entre 0 e 1.

Usa tantos níveis quantos conseguires descrever de forma distinta, até 10. Três é suficiente. Não acrescentes níveis que não consigas descrever de forma distinta.

Mantém cada pergunta Score numa única dimensão. Se uma descrição diz “pontual e inteligente e experiente”, a pergunta está a medir três coisas, e uma entrada que é alta numa e baixa noutra não pode ser situada. A confiança cai e a pontuação significa menos. Divide-a em uma pergunta Score por coisa e combina-as em código, como mostra a secção seguinte.

Se o topo da tua escala tiver um caso extremo raro sobre o qual precisas de agir de forma diferente, dá-lhe o seu próprio nível. Uma escala de sentimento que termina em “muito zangado” pode acrescentar “abusivo ou ameaçador”. Sem esse nível, ambas as mensagens podem receber uma pontuação perto do topo. Só a pontuação pode não as distinguir.

Se não houver mesmo meio-termo, e a resposta for uma de algumas categorias discretas, usa antes um Choice, ou divide a pergunta em várias perguntas Noul. É importante testar os teus níveis contra os teus próprios dados. Duas redações da mesma escala podem comportar-se de forma diferente nos teus dados.

Dividir um julgamento complexo em várias perguntas Score

Um julgamento complexo, que depende de várias coisas, é melhor dividi-lo em uma pergunta Score por coisa. Podes depois combinar em código os Scores devolvidos pela TypeSafe para fazer o julgamento. Algumas perguntas Score podem importar mais do que outras, por isso dá a cada pergunta Score um peso para a sua importância relativa. Os pesos são teus. Quando o resultado combinado não corresponder ao que a tua equipa decidiria, altera-os no código e volta a executar. Envia as perguntas Score num único pedido. São avaliadas em paralelo. Acrescentar perguntas quase não altera o tempo de resposta e custa alguns tokens de pergunta extra; vê Faz várias perguntas ao mesmo tempo.

O pedido abaixo é o ticket do spinner da tabela de cima com mais algum contexto. Faz três perguntas Score: quão grave é o bug, quão frustrado está o cliente e quanto o relatório dá a um engenheiro para trabalhar.

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 si só face ao ticket e recebe uma pontuação:

  • severity é 1.24 com confiança 0.64. Mesma leitura que o exemplo de abertura: a exportação está avariada e alguns têm uma solução alternativa.
  • frustration é 1.28 com confiança 0.58. O tom é cordial, mas “terceira vez” e “já não aguento” deslocam parte da pontuação para o nível superior, por isso o modelo reparte 0.72 e 0.28 entre “frustrado mas cordial” e “muito zangado”. Para este ticket, os dois níveis sobrepõem-se, e é por isso que a confiança é moderada.
  • report_quality é 3.0 com confiança 1.0. Tanto os passos como a versão do navegador são indicados.

As três escalas têm comprimentos diferentes, por isso, antes de as combinares, normaliza cada pontuação. Uma escala de quatro níveis devolve de 0 a 3 e uma de três níveis devolve de 0 a 2, por isso a pontuação máxima numa é maior do que na outra. Divide cada pontuação pelo número do seu nível superior, len(criteria) - 1, para pôr todas as pontuações entre 0 e 1. Aí os pesos significam o que dizem: 0.6 em severity e 0.3 em frustration fazem com que severity conte o dobro.

O código do SDK de Python da TypeSafe abaixo faz as três perguntas, normaliza cada pontuação e combina-as 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 de cima, 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 vivem no teu código, por isso podes ver exatamente como o número é formado e alterá-lo quando a ordenação não corresponder ao que a tua equipa faria. Se mais tarde precisares de mais perguntas Score, acrescenta-as a TRIAGE_QUESTIONS. O número de pedidos continua a ser um. Esta técnica de dividir um julgamento complexo em Scores separados e depois combiná-los com pesos no teu código chama-se padrão de Pontuação composta.

Descrições de nível estruturadas

Começa com uma descrição de texto básica para cada nível. Quando o modelo continua a pontuar entre dois níveis vizinhos em entradas que consideras claras, dá a cada nível um objeto em vez de uma string, com um campo para o que o nível abrange e um campo com alguns exemplos de situações. Usa os mesmos nomes de campo em todos os níveis para que o modelo possa comparar o que é comparável.

O pedido abaixo é o ticket do spinner que usámos 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 uma confiança de 0.84. Com exemplos, pontua 1.09 com uma confiança de 0.87, uma pequena mudança porque as strings simples já o situavam bem. O efeito é maior quando as strings simples deixam o modelo dividido, como mostra a tabela seguinte.

Os exemplos orientam o modelo, e só ajudam quando se parecem com as tuas entradas reais. A tabela abaixo é o relatório de Safari de abertura 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 examples adicionado com um exemplo útil: “a exportação falha num navegador mas funciona noutro” 1.03 0.96
array examples adicionado com um exemplo não relacionado com navegadores: “a pesquisa falha, mas navegar pelas categorias continua a funcionar” 1.43 0.35

Nesta comparação, o exemplo correspondente concentra quase toda a probabilidade num nível. O exemplo não relacionado devolve o mesmo resultado que as strings simples. Uma confiança mais alta não estabelece qual resposta está correta. Escolhe exemplos com níveis esperados conhecidos e depois testa as descrições revistas em entradas separadas antes de as manteres.