메인 콘텐츠로 건너뛰기
_평가 기반 LLM 애플리케이션 개발_은 일관되고 선별된 예제를 사용해 LLM 애플리케이션의 동작을 체계적으로 측정함으로써 애플리케이션을 체계적으로 개선할 수 있게 해줍니다.
Weave에서 워크플로의 핵심은 _Evaluation 객체_이며, 다음을 정의합니다:Evaluation을 정의한 후에는 Model 객체나 LLM 애플리케이션 로직을 포함하는 임의의 사용자 정의 함수에 대해 이를 실행할 수 있습니다. .evaluate()를 호출할 때마다 _evaluation run_이 트리거됩니다. Evaluation 객체를 설계도로, 각 run을 해당 설정에서 애플리케이션 성능을 측정하는 과정으로 생각하면 됩니다.
평가를 시작하려면 다음 단계를 수행합니다:
  1. Evaluation 객체 만들기
  2. 테스트 예제 데이터셋 정의
  3. scoring function 정의
  4. 평가할 모델 또는 함수 정의
  5. 평가 실행
완전한 Evaluation 코드 예시는 여기에서 확인할 수 있습니다. 또한 Saved views명령형 평가 (EvaluationLogger 사용)와 같은 고급 평가 기능에 대해서도 더 자세히 알아볼 수 있습니다.

1. Evaluation 객체 생성

Evaluation 객체를 생성하는 것은 평가 설정을 구성하는 첫 번째 단계입니다. 하나의 Evaluation은 예제 데이터, 스코어링 로직, 그리고 선택적인 전처리로 구성됩니다. 이후 이 객체를 사용해 하나 이상의 평가를 실행합니다. Weave는 각 예제를 애플리케이션을 통해 처리한 후, 여러 개의 커스텀 스코어링 함수로 출력값을 평가합니다. 이를 통해 애플리케이션의 성능을 한눈에 파악할 수 있고, 개별 출력과 점수를 자세히 탐색할 수 있는 풍부한 UI를 활용할 수 있습니다.

(선택 사항) 사용자 지정 이름

평가 플로우에서는 사용자 지정 가능한 이름 유형이 두 가지 있습니다.

Evaluation 객체 이름 지정

Evaluation 객체 자체에 이름을 지정하려면 Evaluation 클래스에 evaluation_name 파라미터를 전달합니다. 이 이름은 코드와 UI 목록에서 Evaluation을 식별하는 데 도움이 됩니다.
evaluation = Evaluation(
    dataset=examples, scorers=[match_score1], evaluation_name="My Evaluation"
)

개별 evaluation run 이름 지정

특정 evaluation run(evaluate() 호출)에 이름을 지정하려면 display_name을 포함한 __weave 사전을 사용합니다. 이는 해당 run이 UI에 어떻게 표시되는지에 영향을 줍니다.
evaluation = Evaluation(
    dataset=examples, scorers=[match_score1]
)
evaluation.evaluate(model, __weave={"display_name": "My Evaluation Run"})

2. 테스트 예제용 데이터셋 정의하기

먼저 평가할 예제 모음으로 구성된 Dataset 객체 또는 예제 목록을 정의합니다. 이러한 예제들은 대개 테스트 대상이 되는 실패 사례로, 테스트 주도 개발(TDD)의 단위 테스트와 비슷한 역할을 합니다.
다음 예제는 딕셔너리 목록으로 정의된 데이터셋을 보여줍니다.
examples = [
    {"question": "What is the capital of France?", "expected": "Paris"},
    {"question": "Who wrote 'To Kill a Mockingbird'?", "expected": "Harper Lee"},
    {"question": "What is the square root of 64?", "expected": "8"},
]

3. 점수 함수 정의

그런 다음 하나 이상의 scoring functions을 생성합니다. 이 함수들은 Dataset의 각 예시를 점수화하는 데 사용됩니다.
각 점수 함수는 output 매개변수를 포함해야 하며, 점수가 담긴 사전을 반환해야 합니다. 선택적으로, 예시에 포함된 다른 입력들도 인자로 받을 수 있습니다.점수 함수는 output 키워드 인자를 가져야 하지만, 나머지 인자들은 사용자 정의이며 데이터셋 예시에서 가져옵니다. 함수는 인자 이름과 동일한 사전 키만 사용하여 필요한 값만 가져옵니다.
스코어러에서 output 인자를 기대하는데 전달되지 않는다면, 예전 방식의 model_output 키를 사용하고 있는지 확인하세요. 이를 수정하려면, 스코어러 함수가 키워드 인자로 output을 받도록 업데이트하세요.
다음 예제 스코어러 함수 match_score1은 점수 계산을 위해 examples 사전에서 expected 값을 사용합니다.
import weave

# 예시를 수집합니다
examples = [
    {"question": "What is the capital of France?", "expected": "Paris"},
    {"question": "Who wrote 'To Kill a Mockingbird'?", "expected": "Harper Lee"},
    {"question": "What is the square root of 64?", "expected": "8"},
]

# 사용자 정의 점수 함수를 정의합니다
@weave.op()
def match_score1(expected: str, output: dict) -> dict:
    # 여기에서 모델 출력에 점수를 매기는 로직을 정의합니다
    return {'match': expected == output['generated_text']}

(선택 사항) 사용자 정의 Scorer 클래스 정의하기

일부 애플리케이션에서는 사용자 정의 Scorer 클래스를 만들고자 할 수 있습니다. 예를 들어, 특정 파라미터(예: 채팅 모델, 프롬프트), 각 행에 대한 특정 점수 계산, 집계 점수 계산 방식으로 표준화된 LLMJudge 클래스를 생성해야 할 수 있습니다.자세한 내용은 RAG 애플리케이션의 모델 기반 평가 튜토리얼의 Scorer 클래스 정의 섹션을 참고하세요.

4. 평가할 모델 또는 함수 정의하기

Model을 평가하려면 Evaluation을 사용해 해당 모델 인스턴스에서 evaluate를 호출하세요. Models는 실험해 보고 Weave에 기록하고 싶은 파라미터가 있을 때 사용합니다.
from weave import Model, Evaluation
import asyncio

class MyModel(Model):
    prompt: str

    @weave.op()
    def predict(self, question: str):
        # 여기에서 LLM 호출을 추가하고 결과를 반환합니다
        return {'generated_text': 'Hello, ' + self.prompt}

model = MyModel(prompt='World')

evaluation = Evaluation(
    dataset=examples, scorers=[match_score1]
)
weave.init('intro-example') # weave로 결과 추적 시작
asyncio.run(evaluation.evaluate(model))
이렇게 하면 각 예제에 대해 predict를 실행하고, 각 스코어링 함수로 출력값을 점수화합니다.

(선택 사항) 평가할 함수 정의하기

또는 @weave.op()으로 추적되는 사용자 정의 함수를 평가할 수도 있습니다.
@weave.op
def function_to_evaluate(question: str):
    # 여기에서 LLM 호출을 추가하고 결과를 반환합니다
    return  {'generated_text': 'some response'}

asyncio.run(evaluation.evaluate(function_to_evaluate))

5. 평가 실행하기

평가를 실행하려면 Evaluation 객체에서 .evaluate()를 호출합니다.
evaluation이라는 Evaluation 객체와 평가할 model 객체가 있다고 가정하면, 아래 코드는 평가 run을 생성합니다.
asyncio.run(evaluation.evaluate(model))

(선택 사항) 여러 번의 trial 실행

각 예제를 여러 번 실행하려면 Evaluation 객체의 trials 파라미터를 설정하면 됩니다.
evaluation = Evaluation(
    dataset=examples,
    scorers=[match_score],
    trials=3
)
이 평가 run은 각 예제를 모델에 세 번씩 전달하며, 각 실행(run)은 Weave에서 개별적으로 점수화되고 표시됩니다.

전체 평가 코드 예시

다음 코드 예시는 평가를 처음부터 끝까지 한 번 완전히 실행하는 방법을 보여줍니다. examples 사전은 prompt 값이 주어졌을 때 MyModel을 평가하기 위해 match_score1match_score2 스코어링 함수에서 사용되며, 사용자 정의 함수 function_to_evaluate를 평가하는 데에도 사용됩니다. Model과 함수에 대한 평가는 모두 asyncio.run(evaluation.evaluate())로 호출됩니다.
from weave import Evaluation, Model
import weave
import asyncio
weave.init('intro-example')
examples = [
    {"question": "What is the capital of France?", "expected": "Paris"},
    {"question": "Who wrote 'To Kill a Mockingbird'?", "expected": "Harper Lee"},
    {"question": "What is the square root of 64?", "expected": "8"},
]

@weave.op()
def match_score1(expected: str, output: dict) -> dict:
    return {'match': expected == output['generated_text']}

@weave.op()
def match_score2(expected: dict, output: dict) -> dict:
    return {'match': expected == output['generated_text']}

class MyModel(Model):
    prompt: str

    @weave.op()
    def predict(self, question: str):
        # 여기에서 LLM 호출을 추가하고 출력을 반환합니다
        return {'generated_text': 'Hello, ' + question + self.prompt}

model = MyModel(prompt='World')
evaluation = Evaluation(dataset=examples, scorers=[match_score1, match_score2])

asyncio.run(evaluation.evaluate(model))

@weave.op()
def function_to_evaluate(question: str):
    # 여기에서 LLM 호출을 추가하고 출력을 반환합니다
    return  {'generated_text': 'some response' + question}

asyncio.run(evaluation.evaluate(function_to_evaluate("What is the capitol of France?")))
Evals hero

고급 평가 활용

평가 전에 데이터셋 행 형식 지정하기

preprocess_model_input 함수는 모델의 예측 함수에 전달되기 전 입력에만 적용됩니다. Scorer 함수는 항상 어떤 전처리도 적용되지 않은 원본 데이터셋 예제를 받습니다.
preprocess_model_input 파라미터를 사용하면 평가 함수에 전달되기 전에 데이터셋 예제를 변환할 수 있습니다. 다음과 같은 경우에 유용합니다.
  • 필드 이름을 모델이 기대하는 입력 이름에 맞게 변경해야 할 때
  • 데이터를 올바른 형식으로 변환해야 할 때
  • 필드를 추가하거나 제거해야 할 때
  • 각 예제에 대해 추가 데이터를 로드해야 할 때
다음은 preprocess_model_input을 사용해 필드 이름을 변경하는 방법을 보여 주는 간단한 예제입니다.
import weave
from weave import Evaluation
import asyncio

# 데이터셋에는 "input_text"가 있지만, 모델은 "question"을 기대합니다
examples = [
    {"input_text": "What is the capital of France?", "expected": "Paris"},
    {"input_text": "Who wrote 'To Kill a Mockingbird'?", "expected": "Harper Lee"},
    {"input_text": "What is the square root of 64?", "expected": "8"},
]

@weave.op()
def preprocess_example(example):
    # input_text를 question으로 이름 변경
    return {
        "question": example["input_text"]
    }

@weave.op()
def match_score(expected: str, output: dict) -> dict:
    return {'match': expected == output['generated_text']}

@weave.op()
def function_to_evaluate(question: str):
    return {'generated_text': f'Answer to: {question}'}

# 전처리를 포함해 Evaluation 생성
evaluation = Evaluation(
    dataset=examples,
    scorers=[match_score],
    preprocess_model_input=preprocess_example
)

# 평가 실행
weave.init('preprocessing-example')
asyncio.run(evaluation.evaluate(function_to_evaluate))
이 예제에서 데이터셋에는 input_text 필드를 가진 예제들이 있지만, 평가 함수는 question 파라미터를 기대합니다. preprocess_example 함수는 필드 이름을 변경해 각 예제를 변환하고, 이를 통해 평가가 올바르게 동작하도록 합니다.전처리 함수는 다음을 수행합니다.
  1. 데이터셋에서 원본 예제를 입력으로 받습니다.
  2. 모델이 기대하는 필드를 가진 사전을 반환합니다.
  3. 예제가 평가 함수에 전달되기 전에 각 예제에 적용됩니다.
이는 외부 데이터셋을 사용할 때 특히 유용합니다. 외부 데이터셋은 모델이 기대하는 것과 다른 필드 이름이나 구조를 가질 수 있습니다.

HuggingFace 데이터셋을 평가에 활용하기

우리는 서드파티 서비스 및 라이브러리와의 인테그레이션을 지속적으로 개선하고 있습니다.더 원활한 인테그레이션을 제공하기 전까지는, 임시 방편으로 preprocess_model_input을 사용하여 Weave 평가에서 HuggingFace 데이터셋을 사용할 수 있습니다.자세한 내용은 평가에서 HuggingFace 데이터셋 사용하기 쿡북을 참고하세요.

저장된 뷰

Evals 테이블 설정, 필터, 정렬을 저장된 뷰 로 저장해 두면 선호하는 구성을 빠르게 다시 불러와 사용할 수 있습니다. UI와 Python SDK 모두에서 저장된 뷰를 설정하고 사용할 수 있습니다. 자세한 내용은 Saved Views를 참조하세요.

명령형 평가 (EvaluationLogger)

더 유연한 평가 프레임워크를 선호한다면 Weave의 EvaluationLogger를 살펴보세요. EvaluationLogger는 Python과 TypeScript에서 모두 사용할 수 있으며, 복잡한 워크플로에 더 높은 유연성을 제공하고, 표준 평가 프레임워크는 더 많은 구조와 안내를 제공합니다.