Skip to main content
많은 시나리오에서는 작업의 최종 출력을 평가하는 것으로 충분하지만, 경우에 따라서는 파이프라인의 중간 단계를 평가하고 싶을 수 있습니다. 예를 들어, 검색 증강 생성(RAG)의 경우 다음을 평가할 수 있습니다:
  1. 입력 쿼리에 대해 올바른 문서가 검색되는지 확인하기 위한 검색 단계 평가.
  2. 검색된 문서에 대해 올바른 답변이 생성되는지 확인하기 위한 생성 단계 평가.
이 가이드에서는 두 시나리오를 모두 강조하기 위해 기준 1을 평가하는 간단한 완전 사용자 정의 평가자와 기준 2를 평가하는 LLM 기반 평가자를 사용합니다. 파이프라인의 중간 단계를 평가하려면 평가자 함수가 run/rootRun 인수를 탐색하고 처리해야 합니다. 이는 파이프라인의 중간 단계를 포함하는 Run 객체입니다.

1. LLM 파이프라인 정의

아래의 RAG 파이프라인은 1) 입력 질문으로부터 Wikipedia 쿼리 생성, 2) Wikipedia에서 관련 문서 검색, 3) 검색된 문서를 기반으로 답변 생성으로 구성됩니다.
pip install -U langsmith langchain[openai] wikipedia
langsmith>=0.3.13이 필요합니다.
import wikipedia as wp
from openai import OpenAI
from langsmith import traceable, wrappers

oai_client = wrappers.wrap_openai(OpenAI())

@traceable
def generate_wiki_search(question: str) -> str:
    """Generate the query to search in wikipedia."""
    instructions = (
        "Generate a search query to pass into wikipedia to answer the user's question. "
        "Return only the search query and nothing more. "
        "This will passed in directly to the wikipedia search engine."
    )
    messages = [
        {"role": "system", "content": instructions},
        {"role": "user", "content": question}
    ]
    result = oai_client.chat.completions.create(
        messages=messages,
        model="gpt-4o-mini",
        temperature=0,
    )
    return result.choices[0].message.content

@traceable(run_type="retriever")
def retrieve(query: str) -> list:
    """Get up to two search wikipedia results."""
    results = []
    for term in wp.search(query, results = 10):
        try:
            page = wp.page(term, auto_suggest=False)
            results.append({
                "page_content": page.summary,
                "type": "Document",
                "metadata": {"url": page.url}
            })
        except wp.DisambiguationError:
            pass
        if len(results) >= 2:
            return results

@traceable
def generate_answer(question: str, context: str) -> str:
    """Answer the question based on the retrieved information."""
    instructions = f"Answer the user's question based ONLY on the content below:\n\n{context}"
    messages = [
        {"role": "system", "content": instructions},
        {"role": "user", "content": question}
    ]
    result = oai_client.chat.completions.create(
        messages=messages,
        model="gpt-4o-mini",
        temperature=0
    )
    return result.choices[0].message.content

@traceable
def qa_pipeline(question: str) -> str:
    """The full pipeline."""
    query = generate_wiki_search(question)
    context = "\n\n".join([doc["page_content"] for doc in retrieve(query)])
    return generate_answer(question, context)
이 파이프라인은 다음과 같은 트레이스를 생성합니다: evaluation_intermediate_trace.png

2. 파이프라인을 평가할 데이터셋 및 예제 생성

파이프라인을 평가하기 위해 몇 가지 예제가 포함된 매우 간단한 데이터셋을 구축합니다. langsmith>=0.3.13이 필요합니다.
from langsmith import Client

ls_client = Client()
dataset_name = "Wikipedia RAG"

if not ls_client.has_dataset(dataset_name=dataset_name):
    dataset = ls_client.create_dataset(dataset_name=dataset_name)
    examples = [
      {"inputs": {"question": "What is LangChain?"}},
      {"inputs": {"question": "What is LangSmith?"}},
    ]
    ls_client.create_examples(
      dataset_id=dataset.id,
      examples=examples,
    )

3. 사용자 정의 평가자 정의

위에서 언급한 것처럼 두 가지 평가자를 정의합니다: 입력 쿼리에 대한 검색된 문서의 관련성을 평가하는 평가자와 검색된 문서에 대한 생성된 답변의 환각을 평가하는 평가자입니다. 환각 평가자를 정의하기 위해 with_structured_output과 함께 LangChain LLM 래퍼를 사용합니다. 여기서 핵심은 평가자 함수가 파이프라인의 중간 단계에 접근하기 위해 run / rootRun 인수를 탐색해야 한다는 것입니다. 그런 다음 평가자는 원하는 기준에 따라 평가하기 위해 중간 단계의 입력과 출력을 처리할 수 있습니다. 예제에서는 편의를 위해 langchain을 사용하지만, 이는 필수가 아닙니다.
from langchain.chat_models import init_chat_model
from langsmith.schemas import Run
from pydantic import BaseModel, Field

def document_relevance(run: Run) -> bool:
    """Checks if retriever input exists in the retrieved docs."""
    qa_pipeline_run = next(
        r for run in run.child_runs if r.name == "qa_pipeline"
    )
    retrieve_run = next(
        r for run in qa_pipeline_run.child_runs if r.name == "retrieve"
    )
    page_contents = "\n\n".join(
        doc["page_content"] for doc in retrieve_run.outputs["output"]
    )
    return retrieve_run.inputs["query"] in page_contents

# Data model
class GradeHallucinations(BaseModel):
    """Binary score for hallucination present in generation answer."""
    is_grounded: bool = Field(..., description="True if the answer is grounded in the facts, False otherwise.")

# LLM with structured outputs for grading hallucinations
# For more see: https://python.langchain.com/docs/how_to/structured_output/
grader_llm= init_chat_model("gpt-4o-mini", temperature=0).with_structured_output(
    GradeHallucinations,
    method="json_schema",
    strict=True,
)

def no_hallucination(run: Run) -> bool:
    """Check if the answer is grounded in the documents.
    Return True if there is no hallucination, False otherwise.
    """
    # Get documents and answer
    qa_pipeline_run = next(
        r for r in run.child_runs if r.name == "qa_pipeline"
    )
    retrieve_run = next(
        r for r in qa_pipeline_run.child_runs if r.name == "retrieve"
    )
    retrieved_content = "\n\n".join(
        doc["page_content"] for doc in retrieve_run.outputs["output"]
    )

    # Construct prompt
    instructions = (
        "You are a grader assessing whether an LLM generation is grounded in / "
        "supported by a set of retrieved facts. Give a binary score 1 or 0, "
        "where 1 means that the answer is grounded in / supported by the set of facts."
    )
    messages = [
        {"role": "system", "content": instructions},
        {"role": "user", "content": f"Set of facts:\n{retrieved_content}\n\nLLM generation: {run.outputs['answer']}"},
    ]
    grade = grader_llm.invoke(messages)
    return grade.is_grounded

4. 파이프라인 평가

마지막으로 위에서 정의한 사용자 정의 평가자와 함께 evaluate를 실행합니다.
def qa_wrapper(inputs: dict) -> dict:
  """Wrap the qa_pipeline so it can accept the Example.inputs dict as input."""
  return {"answer": qa_pipeline(inputs["question"])}

experiment_results = ls_client.evaluate(
    qa_wrapper,
    data=dataset_name,
    evaluators=[document_relevance, no_hallucination],
    experiment_prefix="rag-wiki-oai"
)
실험에는 평가자의 점수와 코멘트를 포함한 평가 결과가 포함됩니다: evaluation_intermediate_experiment.png

관련 문서


Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.
I