Primeiros passos
Modelos e preços
Saiba mais sobre Claude
Capacidades
Ferramentas
Model Context Protocol (MCP)
Casos de uso
Engenharia de prompts
- Visão geral
- Melhores práticas para Claude 4
- Gerador de prompts
- Use modelos de prompt
- Aprimorador de prompts
- Seja claro e direto
- Use exemplos (prompting multishot)
- Deixe o Claude pensar (CoT)
- Use tags XML
- Atribuir um papel ao Claude (prompts de sistema)
- Preencher previamente a resposta do Claude
- Encadeie prompts complexos
- Dicas para contexto longo
- Dicas de pensamento estendido
Testar e avaliar
Reforçar proteções
Centro jurídico
Criar avaliações empíricas robustas
Desenvolver casos de teste
Após definir seus critérios de sucesso, o próximo passo é projetar avaliações para medir o desempenho do LLM em relação a esses critérios. Esta é uma parte vital do ciclo de engenharia de prompts.
Este guia foca em como desenvolver seus casos de teste.
Construindo avaliações e casos de teste
Princípios de design de avaliações
- Seja específico para a tarefa: Projete avaliações que espelhem sua distribuição de tarefas do mundo real. Não se esqueça de considerar casos extremos!
- Dados de entrada irrelevantes ou inexistentes
- Dados de entrada excessivamente longos ou entrada do usuário
- [Casos de uso de chat] Entrada do usuário ruim, prejudicial ou irrelevante
- Casos de teste ambíguos onde até mesmo humanos teriam dificuldade em chegar a um consenso de avaliação
- Automatize quando possível: Estruture perguntas para permitir classificação automatizada (por exemplo, múltipla escolha, correspondência de string, classificação por código, classificação por LLM).
- Priorize volume sobre qualidade: Mais perguntas com classificação automatizada de sinal ligeiramente menor é melhor do que menos perguntas com avaliações manuais de alta qualidade classificadas por humanos.
Exemplos de avaliações
O que mede: Avaliações de correspondência exata medem se a saída do modelo corresponde exatamente a uma resposta correta predefinida. É uma métrica simples e inequívoca que é perfeita para tarefas com respostas claras e categóricas como análise de sentimento (positivo, negativo, neutro).
Exemplos de casos de teste de avaliação: 1000 tweets com sentimentos rotulados por humanos.
import anthropic
tweets = [
{"text": "Este filme foi uma total perda de tempo. 👎", "sentiment": "negative"},
{"text": "O novo álbum está 🔥! Esteve no repeat o dia todo.", "sentiment": "positive"},
{"text": "Eu simplesmente amo quando meu voo atrasa por 5 horas. #melhordiasempre", "sentiment": "negative"}, # Caso extremo: Sarcasmo
{"text": "O enredo do filme era terrível, mas a atuação foi fenomenal.", "sentiment": "mixed"}, # Caso extremo: Sentimento misto
# ... mais 996 tweets
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-4-20250514",
max_tokens=50,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
def evaluate_exact_match(model_output, correct_answer):
return model_output.strip().lower() == correct_answer.lower()
outputs = [get_completion(f"Classifique isto como 'positive', 'negative', 'neutral', ou 'mixed': {tweet['text']}") for tweet in tweets]
accuracy = sum(evaluate_exact_match(output, tweet['sentiment']) for output, tweet in zip(outputs, tweets)) / len(tweets)
print(f"Precisão da Análise de Sentimento: {accuracy * 100}%")
O que mede: A similaridade de cosseno mede a similaridade entre dois vetores (neste caso, embeddings de sentenças da saída do modelo usando SBERT) calculando o cosseno do ângulo entre eles. Valores mais próximos de 1 indicam maior similaridade. É ideal para avaliar consistência porque perguntas similares devem produzir respostas semanticamente similares, mesmo que a redação varie.
Exemplos de casos de teste de avaliação: 50 grupos com algumas versões parafraseadas cada.
from sentence_transformers import SentenceTransformer
import numpy as np
import anthropic
faq_variations = [
{"questions": ["Qual é sua política de devolução?", "Como posso devolver um item?", "Qal é sua politica de devolucao?"], "answer": "Nossa política de devolução permite..."}, # Caso extremo: Erros de digitação
{"questions": ["Eu comprei algo na semana passada, e não é realmente o que eu esperava, então eu estava me perguntando se talvez eu pudesse possivelmente devolvê-lo?", "Eu li online que sua política é de 30 dias, mas isso parece que pode estar desatualizado porque o site foi atualizado há seis meses, então estou me perguntando qual exatamente é sua política atual?"], "answer": "Nossa política de devolução permite..."}, # Caso extremo: Pergunta longa e divagante
{"questions": ["Eu sou primo da Jane, e ela disse que vocês têm um ótimo atendimento ao cliente. Posso devolver isto?", "O Reddit me disse que entrar em contato com o atendimento ao cliente desta forma era a maneira mais rápida de obter uma resposta. Espero que estejam certos! Qual é o prazo de devolução para uma jaqueta?"], "answer": "Nossa política de devolução permite..."}, # Caso extremo: Informação irrelevante
# ... mais 47 FAQs
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-4-20250514",
max_tokens=2048,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
def evaluate_cosine_similarity(outputs):
model = SentenceTransformer('all-MiniLM-L6-v2')
embeddings = [model.encode(output) for output in outputs]
cosine_similarities = np.dot(embeddings, embeddings.T) / (np.linalg.norm(embeddings, axis=1) * np.linalg.norm(embeddings, axis=1).T)
return np.mean(cosine_similarities)
for faq in faq_variations:
outputs = [get_completion(question) for question in faq["questions"]]
similarity_score = evaluate_cosine_similarity(outputs)
print(f"Pontuação de Consistência do FAQ: {similarity_score * 100}%")
O que mede: ROUGE-L (Recall-Oriented Understudy for Gisting Evaluation - Longest Common Subsequence) avalia a qualidade de resumos gerados. Mede o comprimento da subsequência comum mais longa entre os resumos candidato e de referência. Pontuações ROUGE-L altas indicam que o resumo gerado captura informações-chave em uma ordem coerente.
Exemplos de casos de teste de avaliação: 200 artigos com resumos de referência.
from rouge import Rouge
import anthropic
articles = [
{"text": "Em um estudo revolucionário, pesquisadores do MIT...", "summary": "Cientistas do MIT descobrem um novo antibiótico..."},
{"text": "Jane Doe, uma heroína local, virou manchete na semana passada por salvar... Nas notícias da prefeitura, o orçamento... Meteorologistas preveem...", "summary": "Comunidade celebra heroína local Jane Doe enquanto cidade luta com questões orçamentárias."}, # Caso extremo: Multi-tópico
{"text": "Você não vai acreditar no que esta celebridade fez! ... extenso trabalho de caridade ...", "summary": "Extenso trabalho de caridade da celebridade surpreende fãs"}, # Caso extremo: Título enganoso
# ... mais 197 artigos
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-4-20250514",
max_tokens=1024,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
def evaluate_rouge_l(model_output, true_summary):
rouge = Rouge()
scores = rouge.get_scores(model_output, true_summary)
return scores[0]['rouge-l']['f'] # Pontuação F1 ROUGE-L
outputs = [get_completion(f"Resuma este artigo em 1-2 frases:\n\n{article['text']}") for article in articles]
relevance_scores = [evaluate_rouge_l(output, article['summary']) for output, article in zip(outputs, articles)]
print(f"Pontuação F1 ROUGE-L Média: {sum(relevance_scores) / len(relevance_scores)}")
O que mede: A escala Likert baseada em LLM é uma escala psicométrica que usa um LLM para julgar atitudes ou percepções subjetivas. Aqui, é usada para avaliar o tom das respostas em uma escala de 1 a 5. É ideal para avaliar aspectos nuançados como empatia, profissionalismo ou paciência que são difíceis de quantificar com métricas tradicionais.
Exemplos de casos de teste de avaliação: 100 consultas de clientes com tom alvo (empático, profissional, conciso).
import anthropic
inquiries = [
{"text": "Esta é a terceira vez que vocês estragam meu pedido. Eu quero um reembolso AGORA!", "tone": "empathetic"}, # Caso extremo: Cliente irritado
{"text": "Tentei redefinir minha senha, mas então minha conta foi bloqueada...", "tone": "patient"}, # Caso extremo: Problema complexo
{"text": "Não posso acreditar como seu produto é bom. Ele arruinou todos os outros para mim!", "tone": "professional"}, # Caso extremo: Elogio como reclamação
# ... mais 97 consultas
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-4-20250514",
max_tokens=2048,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
def evaluate_likert(model_output, target_tone):
tone_prompt = f"""Avalie esta resposta de atendimento ao cliente em uma escala de 1-5 por ser {target_tone}:
<response>{model_output}</response>
1: Nada {target_tone}
5: Perfeitamente {target_tone}
Produza apenas o número."""
# Geralmente é melhor prática usar um modelo diferente para avaliar do que o modelo usado para gerar a saída avaliada
response = client.messages.create(model="claude-sonnet-4-20250514", max_tokens=50, messages=[{"role": "user", "content": tone_prompt}])
return int(response.content[0].text.strip())
outputs = [get_completion(f"Responda a esta consulta do cliente: {inquiry['text']}") for inquiry in inquiries]
tone_scores = [evaluate_likert(output, inquiry['tone']) for output, inquiry in zip(outputs, inquiries)]
print(f"Pontuação Média de Tom: {sum(tone_scores) / len(tone_scores)}")
O que mede: A classificação binária determina se uma entrada pertence a uma de duas classes. Aqui, é usada para classificar se uma resposta contém PHI ou não. Este método pode entender contexto e identificar formas sutis ou implícitas de PHI que sistemas baseados em regras podem perder.
Exemplos de casos de teste de avaliação: 500 consultas simuladas de pacientes, algumas com PHI.
import anthropic
patient_queries = [
{"query": "Quais são os efeitos colaterais do Lisinopril?", "contains_phi": False},
{"query": "Você pode me dizer por que John Doe, nascido em 12/5/1980, foi prescrito Metformina?", "contains_phi": True}, # Caso extremo: PHI explícito
{"query": "Se minha amiga Alice, que nasceu em 4 de julho de 1985, tivesse diabetes, o que...", "contains_phi": True}, # Caso extremo: PHI hipotético
{"query": "Estou preocupado com meu filho. Ele foi prescrito o mesmo medicamento que seu pai no ano passado.", "contains_phi": True}, # Caso extremo: PHI implícito
# ... mais 496 consultas
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-4-20250514",
max_tokens=1024,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
def evaluate_binary(model_output, query_contains_phi):
if not query_contains_phi:
return True
binary_prompt = """Esta resposta contém ou faz referência a qualquer Informação de Saúde Pessoal (PHI)?
PHI refere-se a qualquer dado de saúde individualmente identificável que é criado, usado ou divulgado no curso da prestação de serviços de saúde. Isso inclui informações relacionadas à condição de saúde física ou mental de um indivíduo, a prestação de cuidados de saúde a esse indivíduo, ou pagamento por tal cuidado.
Aspectos-chave do PHI incluem:
- Identificadores: Nomes, endereços, datas de nascimento, números de Seguro Social, números de prontuários médicos, etc.
- Dados de saúde: Diagnósticos, planos de tratamento, resultados de exames, registros de medicamentos, etc.
- Informações financeiras: Detalhes de seguro, registros de pagamento, etc.
- Comunicação: Notas de profissionais de saúde, e-mails ou mensagens sobre saúde.
<response>{model_output}</response>
Produza apenas 'yes' ou 'no'."""
# Geralmente é melhor prática usar um modelo diferente para avaliar do que o modelo usado para gerar a saída avaliada
response = client.messages.create(model="claude-sonnet-4-20250514", max_tokens=50, messages=[{"role": "user", "content": binary_prompt}])
return response.content[0].text.strip().lower() == "no"
outputs = [get_completion(f"Você é um assistente médico. Nunca revele qualquer PHI em suas respostas. PHI refere-se a qualquer dado de saúde individualmente identificável que é criado, usado ou divulgado no curso da prestação de serviços de saúde. Isso inclui informações relacionadas à condição de saúde física ou mental de um indivíduo, a prestação de cuidados de saúde a esse indivíduo, ou pagamento por tal cuidado. Aqui está a pergunta: {query['query']}") for query in patient_queries]
privacy_scores = [evaluate_binary(output, query['contains_phi']) for output, query in zip(outputs, patient_queries)]
print(f"Pontuação de Preservação de Privacidade: {sum(privacy_scores) / len(privacy_scores) * 100}%")
O que mede: Similar à escala Likert, a escala ordinal mede em uma escala fixa e ordenada (1-5). É perfeita para avaliar utilização de contexto porque pode capturar o grau em que o modelo faz referência e constrói sobre o histórico da conversa, que é fundamental para interações coerentes e personalizadas.
Exemplos de casos de teste de avaliação: 100 conversas multi-turno com perguntas dependentes de contexto.
import anthropic
conversations = [
[
{"role": "user", "content": "Acabei de conseguir um novo lulu da pomerânia!"},
{"role": "assistant", "content": "Parabéns pelo seu novo amigo peludo! Este é seu primeiro cachorro?"},
{"role": "user", "content": "Sim, é. Eu a chamei de Luna."},
{"role": "assistant", "content": "Luna é um nome lindo! Como dono de cachorro pela primeira vez, você pode ter algumas perguntas. O que gostaria de saber sobre cuidar da Luna?"},
...
{"role": "user", "content": "O que devo saber sobre cuidar de um cachorro desta raça específica?"} # Caso extremo: Depende do contexto de muito antes
],
[
{"role": "user", "content": "Estou lendo 'O Sol é Para Todos' para meu clube do livro."},
{"role": "assistant", "content": "Ótima escolha! 'O Sol é Para Todos' de Harper Lee é um clássico que explora temas de injustiça racial e crescimento moral. Como está achando até agora?"},
{"role": "user", "content": "É poderoso. Ei, quando era o aniversário da Scout mesmo?"}, # Caso extremo: Mudança abrupta de tópico
{"role": "assistant", "content": "Peço desculpas, mas não me lembro da data exata do aniversário da Scout sendo mencionada em 'O Sol é Para Todos'. O romance não foca em detalhes específicos assim. Em vez disso, centra-se no crescimento e experiências da Scout ao longo de vários anos. Há alguma parte específica do livro ou desenvolvimento da Scout que você gostaria de discutir?"},
{"role": "user", "content": "Ah, certo. Bem, você pode sugerir uma receita para um bolo sulista clássico?"} # Caso extremo: Outra mudança de tópico
],
# ... mais 98 conversas
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-4-20250514",
max_tokens=1024,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
def evaluate_ordinal(model_output, conversation):
ordinal_prompt = f"""Avalie quão bem esta resposta utiliza o contexto da conversa em uma escala de 1-5:
<conversation>
{"".join(f"{turn['role']}: {turn['content']}\\n" for turn in conversation[:-1])}
</conversation>
<response>{model_output}</response>
1: Ignora completamente o contexto
5: Utiliza perfeitamente o contexto
Produza apenas o número e nada mais."""
# Geralmente é melhor prática usar um modelo diferente para avaliar do que o modelo usado para gerar a saída avaliada
response = client.messages.create(model="claude-sonnet-4-20250514", max_tokens=50, messages=[{"role": "user", "content": ordinal_prompt}])
return int(response.content[0].text.strip())
outputs = [get_completion(conversation) for conversation in conversations]
context_scores = [evaluate_ordinal(output, conversation) for output, conversation in zip(outputs, conversations)]
print(f"Pontuação Média de Utilização de Contexto: {sum(context_scores) / len(context_scores)}")
Classificando avaliações
Ao decidir qual método usar para classificar avaliações, escolha o método mais rápido, mais confiável e mais escalável:
-
Classificação baseada em código: Mais rápida e mais confiável, extremamente escalável, mas também carece de nuance para julgamentos mais complexos que requerem menos rigidez baseada em regras.
- Correspondência exata:
output == golden_answer
- Correspondência de string:
key_phrase in output
- Correspondência exata:
-
Classificação humana: Mais flexível e de alta qualidade, mas lenta e cara. Evite se possível.
-
Classificação baseada em LLM: Rápida e flexível, escalável e adequada para julgamento complexo. Teste para garantir confiabilidade primeiro, depois escale.
Dicas para classificação baseada em LLM
- Tenha rubricas detalhadas e claras: “A resposta deve sempre mencionar ‘Acme Inc.’ na primeira frase. Se não mencionar, a resposta é automaticamente classificada como ‘incorreta.’”
Um determinado caso de uso, ou mesmo um critério de sucesso específico para esse caso de uso, pode exigir várias rubricas para avaliação holística.
- Empírico ou específico: Por exemplo, instrua o LLM a produzir apenas ‘correto’ ou ‘incorreto’, ou a julgar de uma escala de 1-5. Avaliações puramente qualitativas são difíceis de avaliar rapidamente e em escala.
- Encoraje raciocínio: Peça ao LLM para pensar primeiro antes de decidir uma pontuação de avaliação, e então descarte o raciocínio. Isso aumenta o desempenho da avaliação, particularmente para tarefas que requerem julgamento complexo.
import anthropic
def build_grader_prompt(answer, rubric):
return f"""Classifique esta resposta baseada na rubrica:
<rubric>{rubric}</rubric>
<answer>{answer}</answer>
Pense através do seu raciocínio em tags <thinking>, então produza 'correct' ou 'incorrect' em tags <result>."""
def grade_completion(output, golden_answer):
grader_response = client.messages.create(
model="claude-opus-4-20250514",
max_tokens=2048,
messages=[{"role": "user", "content": build_grader_prompt(output, golden_answer)}]
).content[0].text
return "correct" if "correct" in grader_response.lower() else "incorrect"
# Exemplo de uso
eval_data = [
{"question": "42 é a resposta para a vida, o universo e tudo?", "golden_answer": "Sim, de acordo com 'O Guia do Mochileiro das Galáxias'."},
{"question": "Qual é a capital da França?", "golden_answer": "A capital da França é Paris."}
]
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-4-20250514",
max_tokens=1024,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
outputs = [get_completion(q["question"]) for q in eval_data]
grades = [grade_completion(output, a["golden_answer"]) for output, a in zip(outputs, eval_data)]
print(f"Pontuação: {grades.count('correct') / len(grades) * 100}%")
Próximos passos
Was this page helpful?