3️⃣Evaluation

평가와 벤치마킹은 LLM 개발에서 매우 중요한 개념입니다. LLM 앱(RAG, Agents))의 성능을 개선하려면 이를 측정할 수 있는 방법이 있어야 합니다.

LlamaIndex는 생성된 결과의 품질을 측정할 수 있는 주요 모듈을 제공합니다. 또한 검색 품질을 측정하기 위한 주요 모듈도 제공합니다.

  • 응답 평가(Response Evaluation): 응답이 검색된 컨텍스트와 일치하나요? 쿼리와도 일치하는가? 참조 답변 또는 가이드라인과 일치하는가?

  • 검색 평가(Retrieval Evaluation): 검색된 소스가 쿼리와 관련이 있는가?이 섹션에서는 LlamaIndex 내의 평가 구성요소가 어떻게 작동하는지 설명합니다.

자세한 LLM의 Evaluation 지표는 LLM Evaluation with RAGAS에서 참고하세요.

1. Response Evaluation

LlamaIndex는 결과의 품질을 측정하기 위해 LLM 기반 평가 모듈을 제공합니다. 이는 LLM(예: GPT-4)을 사용하여 다양한 방식으로 예측된 정답의 정답 여부를 결정합니다.

이러한 최신 평가 모듈 중 상당수는 실측값 레이블이 필요하지 않습니다. 평가는 쿼리, 컨텍스트, 응답을 조합하여 수행할 수 있으며, 이를 LLM 호출과 결합할 수도 있습니다.

이러한 평가 모듈은 다음과 같은 형태입니다:

  • Correctness: 생성된 답변이 쿼리에 주어진 참조 답변의 답변과 일치하는지 여부(레이블 필요).

  • Semantic Similarity: 예측된 답변이 참조 답변과 의미적으로 유사한지 여부(레이블 필요).

  • Faithfulness: 충실도: 답변이 검색된 문맥에 충실한지(즉, 환각이 있는지 여부) 평가합니다.

  • Context Relevancy: 검색된 문맥이 쿼리와 관련이 있는지 여부입니다.

  • Answer Relevancy: 생성된 답변이 쿼리와 관련이 있는지 여부입니다.

  • Guideline Adherence: 예측된 답변이 특정 가이드라인을 준수하는지 여부입니다.

Question Generation 기능 제공

LlamaIndex는 쿼리를 평가하는 것 외에도 데이터를 사용하여 평가할 질문을 생성할 수도 있습니다. 즉, 자동으로 질문을 생성한 다음 평가 파이프라인을 실행하여 LLM이 데이터를 사용하여 실제로 질문에 정확하게 답변할 수 있는지 테스트할 수 있습니다.

EvaluationResult 예시

FaithfulnessEvaluator 답변이 검색된 문맥에 충실한지(즉, 환각이 있는지 여부)를 평가합니다.

from llama_index.core import VectorStoreIndex
from llama_index.llms.openai import OpenAI
from llama_index.core.evaluation import FaithfulnessEvaluator

# create llm
llm = OpenAI(model="gpt-4", temperature=0.0)

# build index
...

# define evaluator
evaluator = FaithfulnessEvaluator(llm=llm)

# query index
query_engine = vector_index.as_query_engine()
response = query_engine.query(
    "What battles took place in New York City in the American Revolution?"
)
eval_result = 
evaluator.evaluate_response(response=response)
print(str(eval_result.passing))

각 소스 컨텍스트를 개별적으로 평가하도록 선택할 수도 있습니다:

from llama_index.core import VectorStoreIndex
from llama_index.llms.openai import OpenAI
from llama_index.core.evaluation import FaithfulnessEvaluator

# create llm
llm = OpenAI(model="gpt-4", temperature=0.0)

# build index
...

# define evaluator
evaluator = FaithfulnessEvaluator(llm=llm)

# query index
query_engine = vector_index.as_query_engine()
response = query_engine.query(
    "What battles took place in New York City in the American Revolution?"
)
response_str = response.response
for source_node in response.source_nodes:
    eval_result = evaluator.evaluate(
        response=response_str, contexts=[source_node.get_content()]
    )
    print(str(eval_result.passing))

Evaluating Query + Response Relevancy

RelevancyEvaluator는 검색된 컨텍스트와 답변이 주어진 쿼리에 대해 관련성이 있고 일관성이 있는지 평가합니다.

이 평가자는 응답 객체 외에 query를 전달해야 한다는 점에 유의하세요.

from llama_index.core import VectorStoreIndex
from llama_index.llms.openai import OpenAI
from llama_index.core.evaluation import RelevancyEvaluator

# create llm
llm = OpenAI(model="gpt-4", temperature=0.0)

# build index
...

# define evaluator
evaluator = RelevancyEvaluator(llm=llm)

# query index
query_engine = vector_index.as_query_engine()
query = "What battles took place in New York City in the American Revolution?"
response = query_engine.query(query)
eval_result = evaluator.evaluate_response(query=query, response=response)
print(str(eval_result))

마찬가지로 특정 소스 노드에서 평가할 수도 있습니다.

from llama_index.core import VectorStoreIndex
from llama_index.llms.openai import OpenAI
from llama_index.core.evaluation import RelevancyEvaluator

# create llm
llm = OpenAI(model="gpt-4", temperature=0.0)

# build index
...

# define evaluator
evaluator = RelevancyEvaluator(llm=llm)

# query index
query_engine = vector_index.as_query_engine()
query = "What battles took place in New York City in the American Revolution?"
response = query_engine.query(query)
response_str = response.response
for source_node in response.source_nodes:
    eval_result = evaluator.evaluate(
        query=query,
        response=response_str,
        contexts=[source_node.get_content()],
    )
    print(str(eval_result.passing))

Question Generation

LlamaIndex는 데이터를 사용하여 답변할 질문을 생성할 수도 있습니다. 위의 평가기와 함께 사용하면 데이터에 대한 완전 자동화된 평가 파이프라인을 만들 수 있습니다.

from llama_index.core import SimpleDirectoryReader
from llama_index.llms.openai import OpenAI
from llama_index.core.llama_dataset.generator import RagDatasetGenerator

# create llm
llm = OpenAI(model="gpt-4", temperature=0.0)

# build documents
documents = SimpleDirectoryReader("./data").load_data()

# define generator, generate questions
dataset_generator = RagDatasetGenerator.from_documents(
    documents=documents,
    llm=llm,
    num_questions_per_chunk=10,  # set the number of questions per nodes
)

rag_dataset = dataset_generator.generate_questions_from_nodes()
questions = [e.query for e in rag_dataset.examples]

Batch Evaluation

또한 여러 질문에 걸쳐 평가자 세트를 실행할 수 있는 일괄 평가 러너를 제공합니다.

from llama_index.core.evaluation import BatchEvalRunner

runner = BatchEvalRunner(
    {"faithfulness": faithfulness_evaluator, "relevancy": relevancy_evaluator},
    workers=8,
)

eval_results = await runner.aevaluate_queries(
    vector_index.as_query_engine(), queries=questions
)

DeepEval 연동하기

DeepEval은 독자적인 평가 메트릭으로 구동되는 6개의 평가기(리트리버 및 발전기 평가를 위한 3개의 RAG 평가기 포함)를 제공합니다.

pip install -U deepeval
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from deepeval.integrations.llama_index import DeepEvalAnswerRelevancyEvaluator

documents = SimpleDirectoryReader("YOUR_DATA_DIRECTORY").load_data()
index = VectorStoreIndex.from_documents(documents)
rag_application = index.as_query_engine()

# An example input to your RAG application
user_input = "What is LlamaIndex?"

# LlamaIndex returns a response object that contains
# both the output string and retrieved nodes
response_object = rag_application.query(user_input)

evaluator = DeepEvalAnswerRelevancyEvaluator()
evaluation_result = evaluator.evaluate_response(
    query=user_input, response=response_object
)
print(evaluation_result)

6개의 평가자를 모두 deepeval에서 가져오는 방법은 다음과 같습니다:

from deepeval.integrations.llama_index import (
    DeepEvalAnswerRelevancyEvaluator,
    DeepEvalFaithfulnessEvaluator,
    DeepEvalContextualRelevancyEvaluator,
    DeepEvalSummarizationEvaluator,
    DeepEvalBiasEvaluator,
    DeepEvalToxicityEvaluator,
)

2. Retrieval Evaluation

LlamaIndex는 검색을 독립적으로 평가하는 데 도움이 되는 모듈도 제공합니다.

Retrieval evaluation라는 개념은 새로운 것이 아니며, 질문의 데이터 세트와 실제 순위가 주어지면 평균 상호 순위(mean-reciprocal rank, MRR), 적중률(hit-rate), 정확도(precision) 등과 같은 순위 메트릭을 사용하여 검색기를 평가할 수 있습니다.

Retrieval evaluation 단계는 다음을 중심으로 이루어집니다:

  • Dataset generation: 비정형 텍스트 코퍼스가 주어지면 (질문, 문맥) 쌍을 합성적으로 생성합니다.

  • rieval Evaluation: 검색기와 질문 세트가 주어지면 순위 메트릭을 사용하여 검색된 결과를 평가합니다.

RetrieverEvaluator예시

검색기가 주어진 단일 쿼리 + 실측 데이터 문서 세트에 대한 평가를 실행합니다.표준 관행은 from_metrics로 유효한 메트릭 집합을 지정하는 것입니다.

from llama_index.core.evaluation import RetrieverEvaluator

# define retriever somewhere (e.g. from index)
# retriever = index.as_retriever(similarity_top_k=2)
retriever = ...

retriever_evaluator = RetrieverEvaluator.from_metric_names(
    ["mrr", "hit_rate"], retriever=retriever
)

retriever_evaluator.evaluate(
    query="query", expected_ids=["node_id1", "node_id2"]
)

Building an Evaluation Dataset

질문 + 노드 ID로 구성된 검색 평가 데이터 세트를 수동으로 큐레이션할 수 있습니다. 또한, generate_question_context_pairs를 통해 기존 텍스트 코퍼스를 통한 합성 데이터 세트 생성도 제공합니다:


from llama_index.core.evaluation import generate_question_context_pairs

qa_dataset = generate_question_context_pairs(
    nodes, llm=llm, num_questions_per_chunk=2
)

반환된 결과는 (queries, relevant_docs, and corpus를 포함하는) EmbeddingQAFinetuneDataset 객체입니다.

RetrieverEvaluator 플러그인 하기

일괄 모드에서 데이터 세트에 대해 RetrieverEvaluator를 실행할 수 있는 편리한 기능을 제공합니다.

eval_results = await retriever_evaluator.aevaluate_dataset(qa_dataset)

이렇게 하면 각 쿼리에서 .evaluate를 개별적으로 호출하는 것보다 훨씬 빠르게 실행됩니다.

Last updated