메인 콘텐츠로 건너뛰기
이것은 인터랙티브 노트북입니다. 로컬에서 실행하거나 아래 링크를 사용할 수 있습니다:

Not Diamond를 사용한 LLM 프롬프트용 커스텀 라우팅

이 노트북은 평가 결과를 기반으로 LLM 프롬프트를 가장 적절한 모델로 라우팅하기 위해 Weave와 Not Diamond의 커스텀 라우팅을 사용하는 방법을 보여줍니다.

프롬프트 라우팅

복잡한 LLM 워크플로우를 구축할 때 Users는 정확도, 비용 또는 호출 지연 시간에 따라 서로 다른 모델에 프롬프트를 전달해야 할 수 있습니다. Users는 Not Diamond를 사용하여 이러한 워크플로우의 프롬프트를 요구 사항에 맞는 적절한 모델로 라우팅함으로써, 모델 비용을 절감하면서 정확도를 극대화할 수 있습니다. 어떤 데이터 분포에서도 단일 모델이 모든 쿼리에 대해 다른 모든 모델보다 뛰어난 성능을 보이는 경우는 드뭅니다. 각 LLM을 호출할 시점을 학습하는 “메타 모델”로 여러 모델을 결합하면, 개별 모델의 성능을 능가할 수 있으며 그 과정에서 비용과 지연 시간까지 줄일 수 있습니다.

커스텀 라우팅

프롬프트용 커스텀 라우터를 트레이닝하려면 세 가지가 필요합니다:
  1. LLM 프롬프트 세트: 프롬프트는 문자열이어야 하며 애플리케이션에서 사용되는 프롬프트를 대표할 수 있어야 합니다.
  2. LLM 응답: 각 입력에 대한 후보 LLM의 응답입니다. 후보 LLM에는 지원되는 LLM과 자체 커스텀 모델이 모두 포함될 수 있습니다.
  3. 후보 LLM의 입력 응답에 대한 평가 점수: 점수는 숫자이며, 요구 사항에 맞는 어떤 메트릭도 될 수 있습니다.
이러한 데이터를 Not Diamond API에 제출하면 각 워크플로우에 튜닝된 커스텀 라우터를 트레이닝할 수 있습니다.

트레이닝 데이터 설정

실제로는 자체 평가(Evaluations)를 사용하여 커스텀 라우터를 트레이닝하게 됩니다. 하지만 이 예제 노트북에서는 코딩 작업을 위한 커스텀 라우터를 트레이닝하기 위해 HumanEval 데이터셋에 대한 LLM 응답을 사용합니다. 먼저 이 예제를 위해 준비한 데이터셋을 다운로드한 다음, LLM 응답을 각 모델에 대한 EvaluationResults로 파싱하는 것부터 시작합니다.
!curl -L "https://drive.google.com/uc?export=download&id=1q1zNZHioy9B7M-WRjsJPkfvFosfaHX38" -o humaneval.csv
python
import random

import weave
from weave.flow.dataset import Dataset
from weave.flow.eval import EvaluationResults
from weave.integrations.notdiamond.util import get_model_evals

pct_train = 0.8
pct_test = 1 - pct_train

# 실제로는 데이터셋에서 Evaluation을 빌드하고
# `evaluation.get_eval_results(model)`을 호출합니다.
model_evals = get_model_evals("./humaneval.csv")
model_train = {}
model_test = {}
for model, evaluation_results in model_evals.items():
    n_results = len(evaluation_results.rows)
    all_idxs = list(range(n_results))
    train_idxs = random.sample(all_idxs, k=int(n_results * pct_train))
    test_idxs = [idx for idx in all_idxs if idx not in train_idxs]

    model_train[model] = EvaluationResults(
        rows=weave.Table([evaluation_results.rows[idx] for idx in train_idxs])
    )
    model_test[model] = Dataset(
        rows=weave.Table([evaluation_results.rows[idx] for idx in test_idxs])
    )
    print(
        f"Found {len(train_idxs)} train rows and {len(test_idxs)} test rows for {model}."
    )

커스텀 라우터 트레이닝

이제 EvaluationResults가 준비되었으므로 커스텀 라우터를 트레이닝할 수 있습니다. 계정을 생성하고 API 키를 생성했는지 확인한 다음, 아래에 API 키를 입력하세요.
API 키 생성
import os

from weave.integrations.notdiamond.custom_router import train_router

api_key = os.getenv("NOTDIAMOND_API_KEY", "<YOUR_API_KEY>")

preference_id = train_router(
    model_evals=model_train,
    prompt_column="prompt",
    response_column="actual",
    language="en",
    maximize=True,
    api_key=api_key,
    # 첫 번째 커스텀 라우터를 트레이닝하려면 이 부분을 주석 처리된 상태로 두세요.
    # 커스텀 라우터를 그 자리에서 다시 트레이닝하려면 이 주석을 해제하세요.
    # preference_id=preference_id,
)
그런 다음 Not Diamond 앱을 통해 커스텀 라우터의 트레이닝 프로세스를 확인할 수 있습니다.
라우터 트레이닝 진행 상황 확인
커스텀 라우터 트레이닝이 완료되면 이를 사용하여 프롬프트를 라우팅할 수 있습니다.
from notdiamond import NotDiamond

import weave

weave.init("notdiamond-quickstart")

llm_configs = [
    "anthropic/claude-3-5-sonnet-20240620",
    "openai/gpt-4o-2024-05-13",
    "google/gemini-1.5-pro-latest",
    "openai/gpt-4-turbo-2024-04-09",
    "anthropic/claude-3-opus-20240229",
]
client = NotDiamond(api_key=api_key, llm_configs=llm_configs)

new_prompt = (
    """
You are a helpful coding assistant. Using the provided function signature, write the implementation for the function
in Python. Write only the function. Do not include any other text.

from typing import List

def has_close_elements(numbers: List[float], threshold: float) -> bool:
    """
    """ Check if in given list of numbers, are any two numbers closer to each other than
    given threshold.
    >>> has_close_elements([1.0, 2.0, 3.0], 0.5)
    False
    >>> has_close_elements([1.0, 2.8, 3.0, 4.0, 5.0, 2.0], 0.3)
    True
    """
    """
"""
)
session_id, routing_target_model = client.model_select(
    messages=[{"role": "user", "content": new_prompt}],
    preference_id=preference_id,
)

print(f"Session ID: {session_id}")
print(f"Target Model: {routing_target_model}")
이 예제는 또한 Weave의 자동 추적(auto-tracing)과 Not Diamond의 호환성을 활용했습니다. Weave UI에서 결과를 확인할 수 있습니다. 커스텀 라우팅을 위한 Weave UI

커스텀 라우터 평가하기

커스텀 라우터 트레이닝을 마친 후에는 다음 중 하나를 평가할 수 있습니다.
  • 트레이닝 프롬프트를 제출하여 확인하는 인샘플(in-sample) 성능
  • 새로운 프롬프트 또는 별도로 떼어놓은 프롬프트를 제출하여 확인하는 아웃오브샘플(out-of-sample) 성능
아래에서는 성능 평가를 위해 테스트 세트를 커스텀 라우터에 제출합니다.
from weave.integrations.notdiamond.custom_router import evaluate_router

eval_prompt_column = "prompt"
eval_response_column = "actual"

best_provider_model, nd_model = evaluate_router(
    model_datasets=model_test,
    prompt_column=eval_prompt_column,
    response_column=eval_response_column,
    api_key=api_key,
    preference_id=preference_id,
)
python
@weave.op()
def is_correct(score: int, output: dict) -> dict:
    # 이미 모델 응답이 있으므로 score를 활용합니다
    return {"correct": score}

best_provider_eval = weave.Evaluation(
    dataset=best_provider_model.model_results.to_dict(orient="records"),
    scorers=[is_correct],
)
await best_provider_eval.evaluate(best_provider_model)

nd_eval = weave.Evaluation(
    dataset=nd_model.model_results.to_dict(orient="records"), scorers=[is_correct]
)
await nd_eval.evaluate(nd_model)
이 사례에서 Not Diamond “메타 모델”은 여러 다른 모델에 걸쳐 프롬프트를 라우팅합니다. Weave를 통해 커스텀 라우터를 트레이닝하면 평가가 실행되고 결과가 Weave UI에 업로드됩니다. 커스텀 라우터 프로세스가 완료되면 Weave UI에서 결과를 검토할 수 있습니다. UI를 통해 Not Diamond “메타 모델”이 프롬프트에 정확하게 응답할 가능성이 더 높은 다른 모델로 프롬프트를 라우팅함으로써, 가장 성능이 좋은 단일 모델의 성능을 능가하는 것을 볼 수 있습니다.
Not Diamond 평가하기