싱글턴 컴포넌트 레벨 평가
싱글턴 컴포넌트 레벨 평가 (Single-Turn, Component-Level Evals)
싱글턴 유스케이스에 대해 컴포넌트 레벨 테스트를 실행하는 방법을 배워볼게요. 컴포넌트 레벨 테스트는 최종 아웃풋만이 아니라 LLM 애플리케이션의 개별 부분 — 리트리버, 생성기, 툴, 플래너 — 을 평가하게 해줘요. 어떤 컴포넌트가 실패하는지 정확히 짚어야 하는 복잡한 파이프라인 디버깅에 필수적이에요.
출처: 문서
본문
개요
컴포넌트 레벨 테스트는 최종 아웃풋만이 아니라 LLM 애플리케이션의 개별 부분 — 리트리버, 생성기, 툴, 플래너 — 을 평가하게 해줘요. 이는 어떤 컴포넌트가 정확히 실패하는지 짚어야 하는 복잡한 파이프라인을 디버깅하는 데 필수적이에요.
요구 사항 (Requirements):
컴포넌트 레벨 테스트는 현재
deepevalPython을 사용하는 사용자만 지원하며, 로컬에서 반드시 실행해야 해요. 하지만 프로덕션 컴포넌트에 대한 임시(ad-hoc) 온라인 평가는 여전히 여기서 가능해요.
이 페이지의
@observe데코레이터는 DeepEval의 것이며, 로컬이나 CI에서 실행하는 코드 기반 평가를 위해 설계됐어요. 프로덕션에서 앱을 트레이싱하려면confident-trace를 대신 사용하세요 — LLM 트레이싱 퀵스타트를 참고하세요. 둘 다 같은 프로젝트로 데이터를 보내므로, 개발 시 트레이스와 프로덕션 트레이스가 나란히 존재해요.
동작 방식
@observe데코레이터로 LLM 트레이싱을 설정하고 각 컴포넌트에 대한metrics를 정의- Confident AI에서 데이터셋 가져오기
evals_iterator()로 골든스를 순회하며 LLM 앱 호출
sequenceDiagram
participant Your Code
participant Confident AI
participant LLM App
participant Components
Your Code->>Confident AI: Pull dataset
Confident AI-->>Your Code: List of goldens (count = N)
loop N times via evals_iterator()
Your Code->>LLM App: Invoke app
LLM App->>Components: @observe captures spans
Components->>Components: update_current_span() sets test case fields
Components-->>LLM App: Component metric(s) executes
end
LLM App-->>Confident AI: Upload traces & run component metrics
Note over Confident AI: Generate testing report
종단 간 테스트와 달리, LLM 앱을 호출하는 데
golden.input을 쓸 필요가 없어요.evals_iterator()는 단순히 앱이 몇 번 실행되는지(골든스당 한 번) 제어해요. 테스트 케이스 필드는 각 컴포넌트 안의update_current_span()으로 설정돼요 — 골든스는 반복 횟수만 결정해요.
컴포넌트 레벨 테스트 로컬에서 실행하기 (Run Component-Level Tests Locally)
이 섹션은 LLM 트레이싱으로 종단 간 평가를 실행한 이전 섹션의 해당 부분과 거의 동일해요. LLM 트레이싱이 워낙 편해서 뭐든 평가할 수 있기 때문이에요.
이 예시에서는 기본적으로
update_current_trace를update_current_span으로만 바꾸는 거예요.
LLM 트레이싱을 보여주기 위해 이전 섹션의 같은 mock LLM 앱을 사용할게요:
Mock LLM 앱 보기
from openai import OpenAI
def llm_app(query: str) -> str:
# Retriever for your vector db
def retriever(query: str) -> list[str]:
return ["List", "of", "text", "chunks"]
# Generator that combines retrieved context with user query
def generator(query: str, text_chunks: list[str]) -> str:
return OpenAI().chat.completions.create(
model="gpt-4o",
messages=[
{"role": "user", "content": query}
]
).choices[0].message.content
# Calls retriever then generator
return generator(query, retriever(query))
LLM 트레이싱 설정 및 메트릭 정의
애플리케이션을 @observe 데코레이터로 감싸고, 평가하고 싶은 컴포넌트에 metrics를 제공해요:
from openai import OpenAI
from deepeval.metrics import AnswerRelevancyMetric, ContextualRelevancyMetric
from deepeval.tracing import observe, update_current_span
@observe()
def llm_app(query: str) -> str:
@observe(metrics=[ContextualRelevancyMetric()], embedder="your-embedding-model-name")
def retriever(query: str) -> list[str]:
chunks = ["List", "of", "text", "chunks"]
update_current_span(input=query, retrieval_context=chunks)
return chunks
@observe(metrics=[AnswerRelevancyMetric()])
def generator(query: str, text_chunks: list[str]) -> str:
res = OpenAI().chat.completions.create(model="gpt-4o", messages=[{"role": "user", "content": query}]
).choices[0].message.content
update_current_span(input=query, output=res)
return res
return generator(query, retriever(query))
위 예시는 몇 개의 @observe 데코레이터만 추가해 LLM 앱을 트레이싱하는 방법을 보여줘요:
- 각
@observe데코레이터는 **스팬(span)**을 만들며, 이는 컴포넌트를 나타내요 - 반면 **트레이스(trace)**는 최상위
@observe데코레이터가 만들며, 많은 스팬/컴포넌트로 구성돼요 - 평가하려는 컴포넌트에는
@observe()에metrics목록을 포함하고, 해당 컴포넌트 안에서update_current_span함수를 호출해 평가용 테스트 케이스를 만들어요
update_current_span()을 호출해inputs,outputs,retrieval_contexts 등을 설정하면,deepeval이 이를 자동으로 매핑해LLMTestCases를 만들어요.
데이터셋 가져오기 및 골든스 순회
데이터셋을 가져오고 .evals_iterator()로 반복해요. 이 반복자는 LLM 앱이 몇 번 실행되는지 — 데이터셋의 골든스마다 한 번씩 — 제어해요.
from deepeval.dataset import EvaluationDataset
dataset = EvaluationDataset()
dataset.pull(alias="YOUR-DATASET-ALIAS")
for _ in dataset.evals_iterator():
llm_app("any input") # golden.input is optional for component-level testing
테스트 케이스 필드는 컴포넌트 안의 update_current_span()으로 채워지므로, LLM 앱에 어떤 인풋이든 전달할 수 있어요 — 테스트 시나리오가 특정 인풋을 요구한다면 golden.input을 써도 되고요.
완료 ✅. 새로 만들어진 공유 가능한 테스팅 리포트 링크가 보일 거예요.
컴포넌트 레벨 테스팅 리포트
for 루프를 비동기로 실행할 수도 있어요:
import asyncio from deepeval.dataset import EvaluationDataset dataset = EvaluationDataset() dataset.pull(alias="YOUR-DATASET-ALIAS") for golden in dataset.evals_iterator(): task = asyncio.create_task(a_llm_app(golden.input)) dataset.evaluate(task)
데이터셋의 evals_iterator() 안에서 LLM 앱을 호출하면, deepeval이 LLM 앱의 호출을 자동으로 캡처하고 @observe된 컴포넌트의 계층 구조에 기반해 테스트 케이스를 동적으로 만들어요. 컴포넌트 레벨 평가에 대한 추가 정보는:
@observe됐지만metrics가 붙지 않은 컴포넌트는 Confident AI가 테스트하지 않고 일반 스팬으로 표시해요- 컴포넌트 레벨 테스트에서는 일반적으로 참조 기반(reference-based) 메트릭을 쓰지 않아요. 골든스가 테스트 케이스에 1대1로 매핑되도록 설계되어
expected_output같은 인자가 중복되기 때문이에요.