Avaliação (Evals) para Agentes e RAG

Criar um agente ou um sistema RAG é apenas parte do trabalho. Para garantir que ele seja confiável, precisamos avaliar a qualidade das respostas.


Parametros de avaliação

  • Corretude factual -> A resposta está correta?
  • Cobertura -> A resposta aborda todos os pontos da pergunta?
  • Clareza -> A resposta é fácil de entender?
  • Consistência -> O estilo e formato são mantidos ao longo da conversa?
  • Uso correto de ferramentas -> O agente escolheu a ferramenta certa para a tarefa?

Tipos de avaliação

  1. Avaliação automática
    • Usa outra LLM ou métricas automáticas para comparar respostas com referências.
    • Ex.: Similaridade semântica, BLEU, ROUGE, METEOR, BERTScore.
  2. Avaliação humana
    • Usuários ou especialistas avaliam manualmente as respostas.
    • Mais precisa, mas mais cara e demorada.
  3. Avaliação híbrida
    • Combina métricas automáticas com revisão humana.

Ferramentas úteis

  • LangChain Evals -> Avaliação integrada no fluxo de LLMs.
  • DeepEval -> Framework para testes de LLMs.
  • Ragas -> Avaliação de sistemas RAG com métricas específicas.

A seguir, vamos fazer um exemplo simples usando o LangChain Evals para comparar respostas do nosso agente com respostas de referência.

from langchain_openai import ChatOpenAI
from langchain.evaluation import load_evaluator
import os

# Criar avaliador de similaridade semântica
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0, api_key=os.environ.get("OPENAI_API_KEY"))
evaluator = load_evaluator("pairwise_string", llm=llm)

predictions = [
    "LangChain é uma biblioteca Python para orquestrar LLMs e criar agentes inteligentes."
]
references = [
    "LangChain é uma biblioteca Python para orquestrar modelos de linguagem e criar aplicações com agentes."
]

original_input = "O que é LangChain?"

# Evaluation
result = evaluator.evaluate_string_pairs(
    prediction=predictions[0],
    prediction_b=references[0],
    input=original_input
)

print("Resultado da avaliação:", result)

Avaliação de Sistemas RAG com Ragas

O Ragas é uma biblioteca especializada em avaliar sistemas RAG (Retrieval-Augmented Generation), medindo a qualidade do contexto recuperado e da resposta gerada.

No exemplo abaixo, avaliamos um sistema RAG com base em quatro métricas principais: context_precision, context_recall, faithfulness e answer_relevance.


Estrutura do Dataset

O dataset usado pelo Ragas deve conter:

Campo Tipo Descrição
question Lista de strings Perguntas feitas ao sistema.
answer Lista de strings Respostas geradas pelo sistema.
contexts Lista de listas de strings Trechos de contexto recuperados para responder à pergunta.

Exemplo:

data = {
    "question": ["O que é LangChain?"],
    "answer": ["LangChain é uma biblioteca Python para orquestrar LLMs e criar agentes inteligentes."],
    "contexts": [["LangChain é uma biblioteca Python para orquestrar modelos de linguagem e criar aplicações com agentes."]],
}

Fluxo de Funcionamento

  1. Preparação dos dados
    • Definimos pergunta, resposta e contexto recuperado.
    • Criamos um Dataset com Dataset.from_dict().
  2. Avaliação
    • Chamamos evaluate() passando o dataset e as métricas desejadas.
    • O Ragas processa cada pergunta e calcula as métricas.
  3. Resultado
    • O print(score) exibe um relatório com os valores de cada métrica (entre 0 e 1).

from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import CharacterTextSplitter
from langchain.docstore.document import Document
from langchain.chains import RetrievalQA
from datasets import Dataset
from ragas import evaluate
from ragas.metrics import context_precision, context_recall, faithfulness, answer_relevancy
import os

docs = [
    Document(page_content="LangChain é uma biblioteca Python para orquestrar modelos de linguagem e criar aplicações com agentes."),
    Document(page_content="O RAG combina recuperação de informações e geração de texto para criar respostas mais precisas.")
]

splitter = CharacterTextSplitter(chunk_size=200, chunk_overlap=0)
split_docs = splitter.split_documents(docs)

embeddings = OpenAIEmbeddings(api_key=os.environ.get("OPENAI_API_KEY"))
vectorstore = Chroma.from_documents(split_docs, embeddings)

retriever = vectorstore.as_retriever(search_kwargs={"k": 2})

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0, api_key=os.environ.get("OPENAI_API_KEY"))

qa = RetrievalQA.from_chain_type(llm=llm, retriever=retriever)

question = "O que é LangChain?"
predicted_answer = qa.run(question)

retrieved_docs = retriever.get_relevant_documents(question)
retrieved_contexts = [doc.page_content for doc in retrieved_docs]

reference_answer = "LangChain é uma biblioteca Python para orquestrar modelos de linguagem e criar aplicações com agentes."

data = {
    "question": [question],
    "answer": [predicted_answer],
    "contexts": [retrieved_contexts],
    "reference": [reference_answer]
}
dataset = Dataset.from_dict(data)

score = evaluate(
    dataset,
    llm=llm,
    embeddings=embeddings,
    metrics=[context_precision, context_recall, faithfulness, answer_relevancy]
)

print("🔍 Predicted Answer:", predicted_answer)
print("\\n📊 Evaluation Score:")
print(score)

Forma de avaliação do Ragas

O método evaluate() recebe:

  • O dataset com perguntas, respostas e contextos.
  • Uma lista de métricas a serem calculadas.

No exemplo, usamos:

  1. context_precision (Precisão do Contexto) Mede a proporção de informações relevantes dentro do contexto recuperado.
    • Alta precisão → Pouco conteúdo irrelevante no contexto.
    • Fórmula simplificada: Precisão = (Informações relevantes no contexto) / (Total de informações no contexto)
  2. context_recall (Revocação do Contexto) Mede o quanto do conteúdo necessário para responder à pergunta está presente no contexto recuperado.
    • Alta revocação → O contexto cobre todas as informações necessárias.
    • Fórmula simplificada: Revocação = (Informações relevantes recuperadas) / (Total de informações necessárias)
  3. faithfulness (Fidelidade) Mede se a resposta está fiel ao contexto fornecido, sem inventar informações (alucinações).
    • Alta fidelidade → A resposta só contém informações que estão no contexto.
  4. answer_relevance (Relevância da Resposta) Mede se a resposta é relevante para a pergunta feita, independentemente do contexto.
    • Alta relevância -> A resposta aborda diretamente a questão.