메인 콘텐츠로 건너뛰기
평가는 애플리케이션에 변경을 가한 뒤 일련의 예제를 대상으로 테스트하여 애플리케이션을 반복적으로 개선할 수 있도록 도와줍니다. Weave는 ModelEvaluation 클래스를 통해 평가를 추적하기 위한 일급 지원을 제공합니다. 이 API는 전제를 최소화하도록 설계되어, 매우 다양한 사용 사례에 유연하게 대응할 수 있습니다. Evals hero

이 가이드에서 배우게 될 내용:

이 가이드는 다음 방법을 보여줍니다:
  • Model을 설정하는 방법
  • LLM의 응답을 검증할 데이터셋을 생성하는 방법
  • 모델 출력과 기대 출력값을 비교하기 위한 스코어링 함수를 정의하는 방법
  • 스코어링 함수와 추가 기본 제공 스코어러를 사용해 데이터셋에 대해 모델을 테스트하는 평가를 실행하는 방법
  • Weave UI에서 평가 결과를 확인하는 방법

사전 준비 사항

  • W&B 계정
  • Python 3.8+ 또는 Node.js 18+
  • 다음 패키지가 설치되어 있어야 합니다:
    • Python: pip install weave openai
    • TypeScript: npm install weave openai
  • 환경 변수로 설정된 OpenAI API 키

필요한 라이브러리와 함수 임포트하기

다음 라이브러리를 스크립트에 임포트합니다.
import json
import openai
import asyncio
import weave
from weave.scorers import MultiTaskBinaryClassificationF1

Model 빌드하기

Weave에서 Models는 객체로, 모델/에이전트의 동작(로직, 프롬프트, 파라미터)과 버전 관리되는 메타데이터(파라미터, 코드, 마이크로 설정)를 함께 캡처하여, 신뢰성 있게 추적·비교·평가·반복할 수 있도록 해 줍니다. Model을 인스턴스화하면 Weave가 해당 Model의 설정과 동작을 자동으로 캡처하고, 변경 사항이 있을 때마다 버전을 업데이트합니다. 이를 통해 반복적으로 개선해 나가면서 시간에 따른 성능을 추적할 수 있습니다. ModelModel을 서브클래싱(subclassing)하고, 하나의 예제를 입력으로 받아 응답을 반환하는 predict 함수 정의를 구현하여 선언합니다. 다음 예시 모델은 OpenAI를 사용해, 전달된 문장에서 외계 과일의 이름, 색깔, 풍미를 추출합니다.
class ExtractFruitsModel(weave.Model):
    model_name: str
    prompt_template: str

    @weave.op()
    async def predict(self, sentence: str) -> dict:
        client = openai.AsyncClient()

        response = await client.chat.completions.create(
            model=self.model_name,
            messages=[
                {"role": "user", "content": self.prompt_template.format(sentence=sentence)}
            ],
        )
        result = response.choices[0].message.content
        if result is None:
            raise ValueError("No response from model")
        parsed = json.loads(result)
        return parsed
ExtractFruitsModel 클래스는 Weave가 인스턴스화된 객체를 추적할 수 있도록 weave.Model을 상속(서브클래싱)합니다. @weave.op은 predict 함수를 데코레이터로 감싸 입력과 출력을 추적합니다. Model 객체는 다음과 같이 인스턴스화할 수 있습니다:
# 팀과 프로젝트 이름을 설정합니다.
weave.init('<team-name>/eval_pipeline_quickstart')

model = ExtractFruitsModel(
    model_name='gpt-3.5-turbo-1106',
    prompt_template='Extract fields ("fruit": <str>, "color": <str>, "flavor": <str>) from the following text, as json: {sentence}'
)

sentence = "There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy."

print(asyncio.run(model.predict(sentence)))
# Jupyter Notebook 환경이라면 다음을 실행하세요:
# await model.predict(sentence)

데이터셋 생성하기

다음으로, 모델을 평가할 때 사용할 데이터셋이 필요합니다. Dataset은 Weave 객체로 저장된 예시들의 모음입니다. 아래 예시 데이터셋은 세 개의 입력 문장과 그에 해당하는 정답(labels)을 정의한 뒤, 스코어링 함수가 읽을 수 있도록 JSON 테이블 형식으로 포맷합니다. 이 예제에서는 코드에서 예시 목록을 만드는 방식이지만, 실행 중인 애플리케이션에서 예시를 하나씩 로그하는 것도 가능합니다.
sentences = ["There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy.",
"Pounits are a bright green color and are more savory than sweet.",
"Finally, there are fruits called glowls, which have a very sour and bitter taste which is acidic and caustic, and a pale orange tinge to them."]
labels = [
    {'fruit': 'neoskizzles', 'color': 'purple', 'flavor': 'candy'},
    {'fruit': 'pounits', 'color': 'bright green', 'flavor': 'savory'},
    {'fruit': 'glowls', 'color': 'pale orange', 'flavor': 'sour and bitter'}
]
examples = [
    {'id': '0', 'sentence': sentences[0], 'target': labels[0]},
    {'id': '1', 'sentence': sentences[1], 'target': labels[1]},
    {'id': '2', 'sentence': sentences[2], 'target': labels[2]}
]
그런 다음 weave.Dataset() 클래스를 사용해 데이터셋을 생성하고 공개합니다:
weave.init('eval_pipeline_quickstart')
dataset = weave.Dataset(name='fruits', rows=examples)
weave.publish(dataset)

사용자 정의 스코어링 함수 정의하기

Weave evaluation을 사용할 때 Weave는 output과 비교할 target이 필요합니다. 아래 스코어링 함수는 두 개의 사전(targetoutput)을 받아서, output이 target과 일치하는지를 나타내는 불리언 값의 사전을 반환합니다. @weave.op() 데코레이터는 Weave가 스코어링 함수의 실행을 추적할 수 있도록 해 줍니다.
@weave.op()
def fruit_name_score(target: dict, output: dict) -> dict:
    return {'correct': target['fruit'] == output['fruit']}
직접 스코어링 함수를 작성하려면 Scorers 가이드를 참고하세요. 일부 애플리케이션에서는 사용자 정의 Scorer 클래스를 만들고 싶을 수 있습니다. 예를 들어, 특정 파라미터(예: 채팅 모델 또는 프롬프트), 개별 행 스코어링 방식, 그리고 집계 점수 계산을 포함하는 표준화된 LLMJudge 클래스를 만들 수 있습니다. RAG 애플리케이션의 모델 기반 평가에 대한 다음 장의 튜토리얼에서 Scorer 클래스를 정의하는 방법을 확인하세요.

기본 제공 스코어러를 사용해 평가 실행하기

사용자 정의 스코어링 함수와 함께 Weave의 기본 제공 스코어러도 사용할 수 있습니다. 다음 예제에서 weave.Evaluation()은 이전 섹션에서 정의한 fruit_name_score 함수와 F1 점수를 계산하는 기본 제공 스코어러인 MultiTaskBinaryClassificationF1을 함께 사용합니다. 다음 예제에서는 fruits 데이터셋에 대해 ExtractFruitsModel을 두 가지 스코어링 함수를 사용해 평가하고, 그 결과를 Weave에 로깅합니다.
weave.init('eval_pipeline_quickstart')

evaluation = weave.Evaluation(
    name='fruit_eval',
    dataset=dataset, 
    scorers=[
        MultiTaskBinaryClassificationF1(class_names=["fruit", "color", "flavor"]), 
        fruit_name_score
    ],
)
print(asyncio.run(evaluation.evaluate(model)))
# Jupyter Notebook 환경이라면, 다음을 실행하세요:
# await evaluation.evaluate(model)
Python 스크립트에서 실행하는 경우에는 asyncio.run을 사용해야 합니다. 반면 Jupyter Notebook에서 실행하는 경우에는 await를 바로 사용할 수 있습니다.

완전한 예제

import json
import asyncio
import openai
import weave
from weave.scorers import MultiTaskBinaryClassificationF1

# Weave 초기화 (한 번만)
weave.init('eval_pipeline_quickstart')

# 1. 모델 정의
class ExtractFruitsModel(weave.Model):
    model_name: str
    prompt_template: str

    @weave.op()
    async def predict(self, sentence: str) -> dict:
        client = openai.AsyncClient()
        response = await client.chat.completions.create(
            model=self.model_name,
            messages=[{"role": "user", "content": self.prompt_template.format(sentence=sentence)}],
        )
        result = response.choices[0].message.content
        if result is None:
            raise ValueError("No response from model")
        return json.loads(result)

# 2. 모델 인스턴스화
model = ExtractFruitsModel(
    model_name='gpt-3.5-turbo-1106',
    prompt_template='Extract fields ("fruit": <str>, "color": <str>, "flavor": <str>) from the following text, as json: {sentence}'
)

# 3. 데이터셋 생성
sentences = ["There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy.",
"Pounits are a bright green color and are more savory than sweet.",
"Finally, there are fruits called glowls, which have a very sour and bitter taste which is acidic and caustic, and a pale orange tinge to them."]
labels = [
    {'fruit': 'neoskizzles', 'color': 'purple', 'flavor': 'candy'},
    {'fruit': 'pounits', 'color': 'bright green', 'flavor': 'savory'},
    {'fruit': 'glowls', 'color': 'pale orange', 'flavor': 'sour and bitter'}
]
examples = [
    {'id': '0', 'sentence': sentences[0], 'target': labels[0]},
    {'id': '1', 'sentence': sentences[1], 'target': labels[1]},
    {'id': '2', 'sentence': sentences[2], 'target': labels[2]}
]

dataset = weave.Dataset(name='fruits', rows=examples)
weave.publish(dataset)

# 4. 채점 함수 정의
@weave.op()
def fruit_name_score(target: dict, output: dict) -> dict:
    return {'correct': target['fruit'] == output['fruit']}

# 5. 평가 실행
evaluation = weave.Evaluation(
    name='fruit_eval',
    dataset=dataset,
    scorers=[
        MultiTaskBinaryClassificationF1(class_names=["fruit", "color", "flavor"]),
        fruit_name_score
    ],
)
print(asyncio.run(evaluation.evaluate(model)))

평가 결과 보기

Weave는 각 예측과 점수에 대한 트레이스를 자동으로 캡처합니다. 평가 시 출력되는 링크를 클릭해서 Weave UI에서 평가 결과를 확인하세요. 평가 결과

Weave 평가 더 알아보기

다음 단계

RAG 애플리케이션 구축하기를 통해 retrieval-augmented generation(RAG)을 평가하는 방법을 알아보세요.