메인 콘텐츠로 건너뛰기
EvaluationLogger는 Python 또는 TypeScript 코드에서 직접 평가 데이터를 기록할 수 있는 유연하고 점진적인 방법을 제공합니다. Weave의 내부 데이터 유형을 자세히 알 필요 없이, 로거를 인스턴스화한 뒤 해당 메서드(log_prediction, log_score, log_summary)를 사용해 평가 step을 기록하면 됩니다. 이 접근 방식은 전체 데이터셋이나 모든 scorer가 처음부터 정의되어 있지 않을 수 있는 복잡한 워크플로에서 특히 유용합니다. 미리 정의된 DatasetScorer 객체 목록이 필요한 표준 Evaluation 객체와 달리, EvaluationLogger를 사용하면 개별 예측과 그에 해당하는 점수를 사용할 수 있게 되는 대로 점진적으로 기록할 수 있습니다.
더 체계적인 평가를 선호하시나요?미리 정의된 데이터셋과 scorer를 갖춘, 더 구조화된 평가 프레임워크를 원한다면 Weave의 표준 Evaluation 프레임워크를 참조하세요.EvaluationLogger는 유연성을 제공하고, 표준 프레임워크는 구조와 가이드를 제공합니다.

기본 워크플로

  1. 로거 초기화: EvaluationLogger 인스턴스를 생성하고, 필요에 따라 modeldataset에 대한 메타데이터를 전달합니다. 생략하면 기본값이 사용됩니다.
    LLM 호출(예: OpenAI)의 토큰 사용량과 비용을 수집하려면 LLM을 호출하기 **전에 EvaluationLogger를 초기화하세요. 먼저 LLM을 호출하고 나중에 예측을 로깅하면 토큰 및 비용 데이터는 수집되지 않습니다.
  2. 예측 로깅: 시스템의 각 입력/출력 쌍에 대해 log_prediction()을 호출합니다.
  3. 점수 로깅: 반환된 ScoreLogger를 사용해 해당 예측에 대한 log_score()를 호출합니다. 예측마다 여러 점수를 기록할 수 있습니다.
  4. 예측 완료: 예측을 최종 확정하려면 점수를 로깅한 뒤 항상 finish()를 호출합니다.
  5. 요약 로깅: 모든 예측 처리가 끝나면 log_summary()를 호출해 점수를 집계하고 선택 커스텀 메트릭을 추가합니다.
예측에 대해 finish()를 호출한 후에는 더 이상 점수를 로깅할 수 없습니다.
설명한 워크플로를 보여주는 Python 코드는 기본 예제를 참조하세요.

기본 예제

다음 예제에서는 EvaluationLogger를 사용해 기존 코드에 인라인으로 예측과 점수를 로깅하는 방법을 보여줍니다.
user_model 모델 함수는 입력 목록에 대해 정의되며 적용됩니다. 각 예제마다:
  • 입력과 출력은 log_prediction을 사용해 로깅됩니다.
  • 단순한 정확성 점수(correctness_score)는 log_score를 통해 로깅됩니다.
  • finish()는 해당 예측에 대한 로깅을 마무리합니다. 마지막으로 log_summary는 집계 메트릭을 기록하고 Weave에서 점수 자동 요약을 트리거합니다.
import weave
from openai import OpenAI
from weave import EvaluationLogger

weave.init('your-team/your-project')

# 토큰 추적을 위해 모델 호출 전에 EvaluationLogger를 초기화하세요
eval_logger = EvaluationLogger(
    model="my_model",
    dataset="my_dataset"
)

# 예제 입력 데이터 (원하는 데이터 구조를 사용할 수 있습니다)
eval_samples = [
    {'inputs': {'a': 1, 'b': 2}, 'expected': 3},
    {'inputs': {'a': 2, 'b': 3}, 'expected': 5},
    {'inputs': {'a': 3, 'b': 4}, 'expected': 7},
]

# OpenAI를 사용한 예제 모델 로직
@weave.op
def user_model(a: int, b: int) -> int:
    oai = OpenAI()
    response = oai.chat.completions.create(
        messages=[{"role": "user", "content": f"What is {a}+{b}?"}],
        model="gpt-4o-mini"
    )
    # 응답을 어떤 방식으로든 활용합니다 (여기서는 단순하게 a + b를 반환합니다)
    return a + b

# 예제를 순회하며 예측하고 로깅합니다
for sample in eval_samples:
    inputs = sample["inputs"]
    model_output = user_model(**inputs) # 입력을 kwargs로 전달합니다

    # 예측 입력과 출력을 로깅합니다
    pred_logger = eval_logger.log_prediction(
        inputs=inputs,
        output=model_output
    )

    # 이 예측에 대한 점수를 계산하고 로깅합니다
    expected = sample["expected"]
    correctness_score = model_output == expected
    pred_logger.log_score(
        scorer="correctness", # 스코어러의 단순 문자열 이름
        score=correctness_score
    )

    # 이 특정 예측에 대한 로깅을 완료합니다
    pred_logger.finish()

# 전체 평가에 대한 최종 요약을 로깅합니다.
# Weave는 위에서 로깅된 'correctness' 점수를 자동으로 집계합니다.
summary_stats = {"subjective_overall_score": 0.8}
eval_logger.log_summary(summary_stats)

print("Evaluation logging complete. View results in the Weave UI.")

고급 활용

EvaluationLogger는 더 복잡한 평가 시나리오를 지원할 수 있도록 기본 워크플로를 넘어서는 유연한 사용 패턴을 제공합니다. 이 섹션에서는 자동 리소스 관리를 위한 컨텍스트 매니저 사용, 모델 실행과 로깅의 분리, 리치 미디어 데이터 처리, 그리고 여러 모델 평가를 나란히 비교하는 등 고급 기법을 다룹니다.

컨텍스트 관리자 사용

EvaluationLogger는 예측과 점수 모두에 대해 컨텍스트 관리자(with 문)를 지원합니다. 이를 사용하면 코드를 더 깔끔하게 작성할 수 있고, 리소스를 자동으로 정리할 수 있으며, LLM judge call과 같은 중첩된 오퍼레이션도 더 효과적으로 추적할 수 있습니다. 이 문맥에서 with 문을 사용하면 다음과 같은 이점이 있습니다.
  • 컨텍스트를 벗어날 때 finish()가 자동으로 호출됨
  • 중첩된 LLM call에 대한 토큰/비용 추적 개선
  • prediction 컨텍스트 내에서 모델 실행 후 output 설정 가능
import openai
import weave

weave.init("nested-evaluation-example")
oai = openai.OpenAI()

# 로거 초기화

ev = weave.EvaluationLogger(
model="gpt-4o-mini",
dataset="joke_dataset"
)

user_prompt = "Tell me a joke"

# prediction에 컨텍스트 관리자 사용 - finish()를 호출할 필요 없음

with ev.log_prediction(inputs={"user_prompt": user_prompt}) as pred: # 컨텍스트 내에서 모델 호출 수행
result = oai.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": user_prompt}],
)

    # 모델 호출 후 output 설정
    pred.output = result.choices[0].message.content

    # 단순한 점수 로깅
    pred.log_score("correctness", 1.0)
    pred.log_score("ambiguity", 0.3)

    # LLM 호출이 필요한 점수에는 중첩된 컨텍스트 관리자 사용
    with pred.log_score("llm_judge") as score:
        judge_result = oai.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": "Rate how funny the joke is from 1-5"},
                {"role": "user", "content": pred.output},
            ],
        )
        # 계산 후 점수 값 설정
        score.value = judge_result.choices[0].message.content

# 'with' 블록을 벗어나면 finish()가 자동으로 호출됨

ev.log_summary({"avg_score": 1.0})

이 패턴을 사용하면 모든 중첩된 오퍼레이션이 추적되고 상위 prediction에 귀속되므로, Weave UI에서 정확한 토큰 사용량과 비용 데이터를 확인할 수 있습니다.
원시 데이터셋을 log_predictioninputs로 전달하면, Weave는 평가 run이 실행될 때마다 데이터를 다시 수집합니다. 그 결과 중복 데이터가 저장되며, 데이터셋이 크거나 많은 평가에서 이를 재사용하는 경우 저장 공간이 낭비될 수 있습니다. 이 중복을 방지하려면 평가를 실행하기 전에 먼저 데이터셋을 Weave에 게시한 다음, 게시된 데이터셋의 행을 inputs로 전달하세요. 그러면 Weave는 데이터를 다시 수집하는 대신 내부 참조를 사용해 게시된 행 참조를 해석합니다. 이 방식을 사용하면 표준 Evaluation 프레임워크와 동일하게 연결된 환경을 사용할 수 있으며, 각 예측은 Weave UI의 특정 데이터셋 행에 다시 연결됩니다. 다음 예제에서는 데이터셋을 게시하고 이를 EvaluationLogger에 연결한 뒤, 다른 데이터셋과 마찬가지로 조회하고 순회합니다.
import weave
from weave import EvaluationLogger

weave.init("your-team-name/your-project-name")

# 데이터셋 게시(한 번만 수행하면 됨)

dataset = weave.Dataset(
name="my_eval_dataset",
rows=[
{"question": "What is the capitol of France?", "expected": "Paris"},
{"question": "What U.S. state is Seattle in?", "expected": "Washington"},
{"question": "In what country is Mount Fuji located in?", "expected": "Japan"},
],
)
weave.publish(dataset)

# 게시된 데이터셋 조회

dataset = weave.ref("my_eval_dataset").get()

로깅 전에 출력 먼저 계산하기

먼저 모델 출력을 계산한 다음, 예측과 점수를 별도로 로깅할 수 있습니다. 이렇게 하면 평가 로직과 로깅 로직을 더 명확하게 분리할 수 있습니다.
# 토큰 추적을 위해 모델을 호출하기 전에 EvaluationLogger를 초기화합니다
ev = EvaluationLogger(
    model="example_model",
    dataset="example_dataset"
)

# 토큰 추적을 위해 모델 출력(예: OpenAI Call)은 로거 초기화 후에 발생해야 합니다

outputs = [your_output_generator(**inputs) for inputs in your_dataset]
preds = [ev.log_prediction(inputs, output) for inputs, output in zip(your_dataset, outputs)]
for pred, output in zip(preds, outputs):
pred.log_score(scorer="greater_than_5_scorer", score=output > 5)
pred.log_score(scorer="greater_than_7_scorer", score=output > 7)
pred.finish()

ev.log_summary()

리치 미디어 로깅

입력, 출력, 점수에는 이미지, 비디오, 오디오, 구조화된 테이블 같은 리치 미디어를 포함할 수 있습니다. log_prediction 또는 log_score 메서드에 dict 또는 미디어 객체를 전달하면 됩니다.
import io
import wave
import struct
from PIL import Image
import random
from typing import Any
import weave

def generate_random_audio_wave_read(duration=2, sample_rate=44100):
n_samples = duration \* sample_rate
amplitude = 32767 # 16비트 최대 진폭

    buffer = io.BytesIO()

    # 버퍼에 wave 데이터를 씁니다
    with wave.open(buffer, 'wb') as wf:
        wf.setnchannels(1)
        wf.setsampwidth(2)  # 16비트
        wf.setframerate(sample_rate)

        for _ in range(n_samples):
            sample = random.randint(-amplitude, amplitude)
            wf.writeframes(struct.pack('<h', sample))

    # 읽을 수 있도록 버퍼를 처음 위치로 되돌립니다
    buffer.seek(0)

    # Wave_read 객체를 반환합니다
    return wave.open(buffer, 'rb')

rich*media_dataset = [
{
'image': Image.new(
"RGB",
(100, 100),
color=(
random.randint(0, 255),
random.randint(0, 255),
random.randint(0, 255),
),
),
"audio": generate_random_audio_wave_read(),
}
for * in range(5)
]

@weave.op
def your_output_generator(image: Image.Image, audio) -> dict[str, Any]:
return {
"result": random.randint(0, 10),
"image": image,
"audio": audio,
}

ev = EvaluationLogger(model="example_model", dataset="example_dataset")

for inputs in rich_media_dataset:
output = your_output_generator(\*\*inputs)
pred = ev.log_prediction(inputs, output)
pred.log_score(scorer="greater_than_5_scorer", score=output["result"] > 5)
pred.log_score(scorer="greater_than_7_scorer", score=output["result"] > 7)

ev.log_summary()

여러 평가 기록 및 비교

EvaluationLogger를 사용하면 여러 평가를 기록하고 비교할 수 있습니다.
  1. 아래 코드 샘플을 실행합니다.
  2. Weave UI에서 Evals 탭으로 이동합니다.
  3. 비교하려는 eval을 선택합니다.
  4. Compare 버튼을 클릭합니다. Compare 뷰에서 다음 작업을 할 수 있습니다.
    • 추가하거나 제거할 Evals 선택
    • 표시하거나 숨길 메트릭 선택
    • 특정 예제를 페이지별로 살펴보며, 주어진 데이터셋에서 동일한 입력에 대해 서로 다른 모델이 어떻게 수행되었는지 확인
    비교에 대한 자세한 내용은 Comparisons를 참조하세요.
import weave

models = [
"model1",
"model2",
{"name": "model3", "metadata": {"coolness": 9001}}
]

for model in models: # 토큰을 캡처하려면 모델 Call 전에 EvalLogger를 초기화해야 합니다
ev = EvaluationLogger(
name="comparison-eval",
model=model,
dataset="example_dataset",
scorers=["greater_than_3_scorer", "greater_than_5_scorer", "greater_than_7_scorer"],
eval_attributes={"experiment_id": "exp_123"}
)
for inputs in your_dataset:
output = your_output_generator(\*\*inputs)
pred = ev.log_prediction(inputs=inputs, output=output)
pred.log_score(scorer="greater_than_3_scorer", score=output > 3)
pred.log_score(scorer="greater_than_5_scorer", score=output > 5)
pred.log_score(scorer="greater_than_7_scorer", score=output > 7)
pred.finish()

    ev.log_summary()

Evals 탭
Compare 뷰

사용 팁

  • 각 예측 후에는 즉시 finish()를 호출하세요.
  • 개별 예측에 연결되지 않은 메트릭(예: 전체 지연 시간)을 기록하려면 log_summary를 사용하세요.
  • 리치 미디어 로깅은 정성적 분석에 매우 유용합니다.