메인 콘텐츠로 건너뛰기
EvaluationLogger는 Python 또는 TypeScript 코드에서 평가 데이터를 직접 로깅할 수 있는 유연하고 단계적인 방법을 제공합니다. Weave의 내부 데이터 타입에 대해 깊이 알 필요는 없습니다. 단순히 logger 인스턴스를 생성한 뒤, 그 메서드들(log_prediction, log_score, log_summary)을 사용해 평가 단계를 기록하면 됩니다. 이 방식은 전체 데이터셋이나 모든 스코어러를 사전에 정의하기 어려운 복잡한 워크플로에서 특히 유용합니다. 미리 정의된 DatasetScorer 객체 목록이 필요한 표준 Evaluation 객체와 달리, EvaluationLogger를 사용하면 개별 예측과 해당 점수를 생성되는 대로 점진적으로 로깅할 수 있습니다.
더 구조화된 평가를 원하나요?미리 정의된 데이터셋과 스코어러를 사용하는, 구성이 미리 정해진 평가 프레임워크를 원한다면 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("평가 로깅이 완료되었습니다. Weave UI에서 결과를 확인하세요.")

고급 사용법

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

컨텍스트 매니저 사용

EvaluationLogger는 예측과 점수 모두에 대해 컨텍스트 매니저(with 문)를 지원합니다. 이를 사용하면 코드가 더 깔끔해지고, 리소스가 자동으로 정리되며, LLM 판정 호출과 같은 중첩 작업을 더 효과적으로 추적할 수 있습니다. 이 경우 with 문을 사용하면 다음과 같은 이점이 있습니다:
  • 컨텍스트를 벗어날 때 finish()가 자동으로 호출됨
  • 중첩된 LLM 호출에 대한 토큰/비용 추적 향상
  • 예측 컨텍스트 내에서 모델 실행 후 출력 설정
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"

# 예측에 컨텍스트 매니저 사용 - 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}],
    )

    # 모델 호출 후 출력 설정
    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})
이 패턴은 모든 중첩 작업이 상위 예측에 의해 추적되고 귀속되도록 보장하므로, Weave UI에서 정확한 토큰 사용량과 비용 데이터를 확인할 수 있습니다.

로깅 전에 출력 가져오기

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

# 토큰 추적을 위해 로거 초기화 이후에 모델 출력(예: OpenAI 호출)을 생성해야 합니다
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-bit max amplitude

    buffer = io.BytesIO()

    # Write wave data to the buffer
    with wave.open(buffer, 'wb') as wf:
        wf.setnchannels(1)
        wf.setsampwidth(2)  # 16-bit
        wf.setframerate(sample_rate)

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

    # Rewind the buffer to the beginning so we can read from it
    buffer.seek(0)

    # Return a Wave_read object
    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 뷰에서 다음 작업을 수행할 수 있습니다.
    • 추가하거나 제거할 eval 선택
    • 표시하거나 숨길 지표 선택
    • 특정 예제를 넘겨 보면서, 동일한 입력과 주어진 데이터셋에 대해 서로 다른 모델이 어떻게 동작했는지 확인
    비교 기능에 대한 자세한 내용은 Comparisons을 참고하세요.
import weave

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

for model in models:
    # EvalLogger must be initialized before model calls to capture tokens
    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 탭
비교(Comparison) 뷰

사용 팁

  • 각 예측 후 가능한 한 빨리 finish()를 호출하세요.
  • 단일 예측에 묶여 있지 않은 메트릭(예: 전체 지연 시간)을 기록하려면 log_summary를 사용하세요.
  • 리치 미디어 로깅은 정성적 분석에 매우 유용합니다.