메인 콘텐츠로 건너뛰기
Weave에서 Scorer는 AI 출력값을 평가하고 평가 메트릭을 반환하는 데 사용됩니다. Scorer는 AI의 출력값을 받아 분석한 뒤, 결과를 담은 사전을 반환합니다. 필요하다면 입력 데이터를 참조로 사용할 수 있으며, 평가에 대한 설명이나 추론 과정과 같은 추가 정보도 함께 반환할 수 있습니다.
Scorer는 평가 시 weave.Evaluation 객체에 전달됩니다. Weave에는 두 가지 종류의 Scorer가 있습니다.
  1. 함수 기반 Scorer: @weave.op으로 데코레이트된 간단한 Python 함수입니다.
  2. 클래스 기반 Scorer: 더 복잡한 평가를 위해 weave.Scorer를 상속하는 Python 클래스입니다.
Scorer는 반드시 사전을 반환해야 하며, 여러 메트릭, 중첩된 메트릭, 그리고 LLM 평가자가 자신의 추론에 대해 반환한 텍스트와 같은 비수치형 값도 함께 반환할 수 있습니다.

나만의 Scorer 만들기

바로 사용할 수 있는 Scorer 이 가이드는 커스텀 Scorer를 만드는 방법을 설명하지만, Weave에는 이미 바로 사용할 수 있는 다양한 사전 정의된 Scorer로컬 SLM Scorer가 포함되어 있습니다. 예를 들면 다음과 같습니다.

함수 기반 Scorer

@weave.op 데코레이터가 적용되어 사전을 반환하는 함수입니다. 다음과 같은 간단한 평가에 적합합니다:
import weave

@weave.op
def evaluate_uppercase(text: str) -> dict:
    return {"text_is_uppercase": text.isupper()}

my_eval = weave.Evaluation(
    dataset=[{"text": "HELLO WORLD"}],
    scorers=[evaluate_uppercase]
)
평가를 실행하면, evaluate_uppercase는 텍스트가 모두 대문자인지 확인합니다.

클래스 기반 Scorer

더 고급 평가가 필요할 때, 특히 추가 Scorer 메타데이터를 추적하거나 LLM 평가자에 대해 다른 프롬프트를 시도하거나 여러 번 함수를 호출해야 하는 경우에는 Scorer 클래스를 사용할 수 있습니다.요구 사항:
  1. weave.Scorer를 상속합니다.
  2. @weave.op 데코레이터가 적용된 score 메서드를 정의합니다.
  3. score 메서드는 반드시 사전을 반환해야 합니다.
예시:
import weave
from openai import OpenAI
from weave import Scorer

llm_client = OpenAI()

class SummarizationScorer(Scorer):
    model_id: str = "gpt-4o"
    system_prompt: str = "Evaluate whether the summary is good."

    @weave.op
    def some_complicated_preprocessing(self, text: str) -> str:
        processed_text = "Original text: \n" + text + "\n"
        return processed_text

    @weave.op
    def call_llm(self, summary: str, processed_text: str) -> dict:
        res = llm_client.chat.completions.create(
            messages=[
                {"role": "system", "content": self.system_prompt},
                {"role": "user", "content": (
                    f"Analyze how good the summary is compared to the original text."
                    f"Summary: {summary}\n{processed_text}"
                )}])
        return {"summary_quality": res}

    @weave.op
    def score(self, output: str, text: str) -> dict:
        """Score the summary quality.

        Args:
            output: The summary generated by an AI system
            text: The original text being summarized
        """
        processed_text = self.some_complicated_preprocessing(text)
        eval_result = self.call_llm(summary=output, processed_text=processed_text)
        return {"summary_quality": eval_result}

evaluation = weave.Evaluation(
    dataset=[{"text": "The quick brown fox jumps over the lazy dog."}],
    scorers=[summarization_scorer])
이 클래스는 원문과 비교하여 요약의 품질을 평가합니다.

Scorer가 동작하는 방식

Scorer 키워드 인자

Scorer는 AI 시스템의 출력과 데이터셋 행의 입력 데이터를 모두 사용할 수 있습니다.
  • Input: Scorer에서 “label” 또는 “target” 컬럼 같은 데이터셋 행의 데이터를 사용하려면, scorer 정의에 label 또는 target 키워드 인자를 추가해 해당 데이터를 scorer에서 사용할 수 있게 하면 됩니다.
예를 들어 데이터셋에서 “label”이라는 컬럼을 사용하려면, scorer 함수(또는 score 클래스 메서드)는 다음과 같은 형태의 파라미터 목록을 갖습니다:
@weave.op
def my_custom_scorer(output: str, label: int) -> dict:
    ...
Weave Evaluation이 실행되면, AI 시스템의 출력은 output 파라미터로 전달됩니다. Evaluation은 또한 추가 scorer 인자의 이름을 데이터셋 컬럼 이름과 자동으로 매칭하려고 시도합니다. Scorer 인자나 데이터셋 컬럼을 커스터마이즈하기 어렵다면, 컬럼 매핑을 사용할 수 있습니다. 자세한 내용은 아래를 참조하세요.
  • Output: AI 시스템의 출력을 사용하려면 scorer 함수의 시그니처에 output 파라미터를 포함하세요.

column_map으로 컬럼 이름 매핑하기

때로는 score 메서드의 인자 이름이 데이터셋의 컬럼 이름과 일치하지 않을 수 있습니다. 이때는 column_map을 사용해 해결할 수 있습니다.클래스 기반 scorer를 사용하는 경우, scorer 클래스를 초기화할 때 Scorercolumn_map 속성에 사전을 전달하세요. 이 사전은 {scorer_keyword_argument: dataset_column_name} 형식으로 score 메서드의 인자 이름을 데이터셋 컬럼 이름에 매핑합니다.예시:
import weave
from weave import Scorer

# 요약할 뉴스 기사 데이터셋
dataset = [
    {"news_article": "The news today was great...", "date": "2030-04-20", "source": "Bright Sky Network"},
    ...
]

# Scorer 클래스
class SummarizationScorer(Scorer):

    @weave.op
    def score(self, output, text) -> dict:
        """
            output: LLM 요약 시스템이 생성한 요약 결과
            text: 요약 대상이 되는 텍스트
        """
        ...  # 요약의 품질을 평가

# `text` 인자를 `news_article` 데이터 컬럼에 매핑하는 column_map으로 scorer 생성
scorer = SummarizationScorer(column_map={"text" : "news_article"})
이제 score 메서드의 text 인자는 news_article 데이터셋 컬럼의 값을 받게 됩니다.참고:
  • 컬럼을 매핑하는 또 다른 동등한 방법은 Scorer를 상속(subclass)한 뒤, 컬럼을 명시적으로 매핑하도록 score 메서드를 오버로드하는 것입니다.
import weave
from weave import Scorer

class MySummarizationScorer(SummarizationScorer):

    @weave.op
    def score(self, output: str, news_article: str) -> dict:  # 타입 힌트 추가
        # score 메서드를 오버로드하고 컬럼을 수동으로 매핑
        return super().score(output=output, text=news_article)

스코어링 프롬프트에서 op의 변수에 접근하기

LLM-as-a-judge 스코어러용 스코어링 프롬프트에서는 op에서 정의한 변수를 참조할 수 있습니다. 이 값들은 스코어러 run이 실행될 때 자동으로 추출됩니다. 예를 들어, 다음과 같은 함수가 있다고 할 때:
@weave.op
def summarize_article(article: str, max_length: int) -> str:
    # 요약 로직을 여기에 작성하세요
    return summary
다음 변수를 사용할 수 있습니다:
VariableDescription
{article}입력 인수 article의 값
{max_length}입력 인수 max_length의 값
{inputs}모든 입력 인수를 포함한 JSON 사전
{output}op이 반환한 결과
예시 스코어링 프롬프트:
이 요약의 품질을 평가하세요.

원본 기사: {article}
요약: {output}
요청된 최대 길이: {max_length}

다음 기준에 따라 1-10점 척도로 요약을 평가하세요:
- 정확성: 기사를 정확하게 나타내고 있는가?
- 완전성: 핵심 내용을 다루고 있는가?
- 간결성: 적절히 간결한가?

평가 점수와 근거를 담은 JSON 객체를 반환하세요.

스코어러의 최종 요약

평가 시 스코어러는 데이터셋의 각 행에 대해 계산됩니다. 평가에 대한 최종 점수를 제공하기 위해, 출력 타입에 따라 동작하는 auto_summarize를 제공합니다.
  • 수치형 컬럼에는 평균이 계산됩니다.
  • 불리언 컬럼에는 개수와 비율이 계산됩니다.
  • 그 외 컬럼 타입은 무시됩니다.
Scorer 클래스의 summarize 메서드를 오버라이드하여 최종 점수를 계산하는 방식을 직접 정의할 수 있습니다. summarize 함수는 다음을 기대합니다.
  • 단일 파라미터 score_rows: 사전들의 리스트로, 각 사전에는 데이터셋의 단일 행에 대해 score 메서드가 반환한 점수가 들어 있습니다.
  • 요약된 점수가 들어 있는 사전을 반환해야 합니다.
이 기능이 유용한 이유는 무엇인가요?데이터셋에 대한 최종 점수 값을 결정하기 전에, 먼저 모든 행에 대해 스코어링해야 할 때 유용합니다.
class MyBinaryScorer(Scorer):
    """
    전체 출력이 target과 일치하면 True, 그렇지 않으면 False를 반환합니다.
    """

    @weave.op
    def score(self, output, target):
        return {"match": output == target}

    def summarize(self, score_rows: list) -> dict:
        full_match = all(row["match"] for row in score_rows)
        return {"full_match": full_match}
이 예시에서 기본 auto_summarize는 True의 개수와 비율을 반환했을 것입니다.
더 자세히 알고 싶다면 CorrectnessLLMJudge의 구현을 참고하십시오.

호출에 Scorer 적용하기

Weave op에 scorer를 적용하려면, 연산 결과와 추적 정보에 모두 접근할 수 있는 .call() 메서드를 사용해야 합니다. 이를 통해 Weave의 데이터베이스에서 특정 호출과 scorer 결과를 연결할 수 있습니다. .call() 메서드 사용 방법에 대한 자세한 내용은 Calling Ops 가이드를 참고하세요.
기본 예제는 다음과 같습니다:
# 결과와 Call 객체 모두 가져오기
result, call = generate_text.call("Say hello")

# scorer 적용
score = await call.apply_scorer(MyScorer())
동일한 호출에 여러 scorer를 적용할 수도 있습니다:
# 여러 scorer를 병렬로 적용
await asyncio.gather(
    call.apply_scorer(quality_scorer),
    call.apply_scorer(toxicity_scorer)
)
참고:
  • scorer 결과는 Weave의 데이터베이스에 자동으로 저장됩니다.
  • scorer는 메인 연산이 완료된 이후 비동기적으로 실행됩니다.
  • UI에서 scorer 결과를 확인하거나 API를 통해 조회할 수 있습니다.
scorer를 가드레일 또는 모니터로 사용하는 방법, 운영 환경 모범 사례, 전체 예제를 포함한 보다 자세한 정보는 Guardrails and Monitors 가이드를 참고하세요.

preprocess_model_input 사용하기

평가 중에 데이터셋 예제가 모델에 전달되기 전에 이를 수정하려면 preprocess_model_input 파라미터를 사용할 수 있습니다. 사용 방법과 예시는 평가 전에 데이터셋 행을 포맷하기 위해 preprocess_model_input 사용하기를 참고하세요.

점수 분석

이 섹션에서는 단일 호출, 여러 호출, 그리고 특정 스코어러가 채점한 모든 호출의 점수를 분석하는 방법을 설명합니다.

단일 호출 점수 분석

단일 Call API

단일 Call을 조회하려면 get_call 메서드를 사용합니다.
client = weave.init("my-project")

# 단일 call 가져오기
call = client.get_call("call-uuid-here")

# 점수가 포함된 call의 피드백 가져오기
feedback = list(call.feedback)

단일 Call UI

Call Scores 탭
단일 Call에 대한 점수는 Call 상세 패널의 “Scores” 탭에서 확인할 수 있습니다.

여러 호출의 점수 분석

Multiple Calls API

여러 Calls의 정보를 조회하려면 get_calls 메서드를 사용합니다.
client = weave.init("my-project")

# 여러 calls 가져오기 - 원하는 필터를 사용하고 피드백 포함
calls = client.get_calls(..., include_feedback=True)

# calls를 순회하며 점수가 포함된 피드백에 접근
for call in calls:
    feedback = list(call.feedback)

다중 호출 UI

Multiple Calls Tab
여러 호출에 대한 점수는 traces 테이블의 “Scores” 열에 표시됩니다.

특정 Scorer가 채점한 모든 Call 분석

Scorer별 모든 Call API

특정 Scorer가 채점한 모든 Call을 가져오려면 get_calls 메서드를 사용하세요.
client = weave.init("my-project")

# 스코어러의 모든 버전으로 채점된 호출을 가져오려면 스코어러 이름(일반적으로 클래스 이름)을 사용하세요
calls = client.get_calls(scored_by=["MyScorer"], include_feedback=True)

# 스코어러의 특정 버전으로 채점된 호출을 가져오려면 전체 ref를 사용하세요
# Ref는 스코어러 객체에서 또는 UI를 통해 얻을 수 있습니다.
calls = client.get_calls(scored_by=[myScorer.ref.uri()], include_feedback=True)

# 호출을 순회하며 점수가 포함된 피드백에 접근하세요
for call in calls:
    feedback = list(call.feedback)

Scorer별 전체 Call UI

마지막으로, 특정 Scorer가 채점한 모든 call을 보려면 UI에서 Scorers 탭으로 이동한 뒤 “Programmatic Scorer” 탭을 선택하세요. Scorer를 클릭해 Scorer 상세 페이지를 엽니다.
Scorer 상세 페이지
다음으로, Scores 아래에 있는 View Traces 버튼을 클릭해 Scorer가 채점한 모든 call을 확인합니다.
Scorer 버전으로 필터링된 Call
기본적으로 선택된 Scorer 버전으로 필터링됩니다. 버전 필터를 제거하면 해당 Scorer의 모든 버전에서 채점한 call 전체를 볼 수 있습니다.
Scorer 이름으로 필터링된 Call