메인 콘텐츠로 건너뛰기
Try in Colab 이 노트북은 W&B Weave를 W&B Models와 함께 사용하는 방법을 보여줍니다. 구체적으로, 이 예제는 두 개의 서로 다른 팀이 협업하는 시나리오를 고려합니다.
  • 모델 팀(Model Team): 모델 구축 팀이 새로운 Chat Model(Llama 3.2)을 파인튜닝하고 W&B Models를 사용하여 레지스트리에 저장합니다.
  • 앱 팀(App Team): 앱 개발 팀이 해당 Chat Model을 가져와 W&B Weave를 사용하여 새로운 RAG 챗봇을 생성하고 평가합니다.
W&B Models와 W&B Weave가 모두 포함된 공개 Workspace는 여기에서 확인할 수 있습니다.
W&B
워크플로우는 다음 단계로 구성됩니다:
  1. W&B Weave로 RAG 앱 코드를 계측(Instrument)합니다.
  2. LLM(Llama 3.2 등, 다른 LLM으로 교체 가능)을 파인튜닝하고 W&B Models로 추적합니다.
  3. 파인튜닝된 모델을 W&B Registry에 로그합니다.
  4. 새로운 파인튜닝 모델로 RAG 앱을 구현하고 W&B Weave로 앱을 평가합니다.
  5. 결과가 만족스러우면 업데이트된 Rag 앱의 레퍼런스를 W&B Registry에 저장합니다.
참고: 아래에서 언급되는 RagModel은 전체 RAG 앱으로 간주할 수 있는 최상위 weave.Model입니다. 여기에는 ChatModel, 벡터 데이터베이스 및 프롬프트가 포함됩니다. ChatModel 또한 W&B Registry에서 아티팩트를 다운로드하는 코드가 포함된 또 다른 weave.Model이며, RagModel의 일부로서 다른 채팅 모델을 지원하도록 변경할 수 있습니다. 자세한 내용은 Weave의 전체 모델에서 확인하세요.

1. 설정

먼저 weavewandb를 설치한 다음 API 키로 로그인합니다. API 키는 User Settings에서 생성하고 확인할 수 있습니다.
pip install weave wandb
import wandb
import weave
import pandas as pd

PROJECT = "weave-cookboook-demo"
ENTITY = "wandb-smle"

# wandb 로그인
wandb.login()
# weave 초기화
weave.init(ENTITY + "/" + PROJECT)

2. Artifact 기반의 ChatModel 만들기

레지스트리에서 파인튜닝된 채팅 모델을 가져와 weave.Model을 생성합니다. 이는 다음 단계의 RagModel에 직접 연결할 수 있습니다. 기존 ChatModel과 동일한 파라미터를 사용하며, initpredict만 변경됩니다.
pip install unsloth
pip uninstall unsloth -y && pip install --upgrade --no-cache-dir "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"
모델 팀은 더 빠른 속도를 위해 unsloth 라이브러리를 사용하여 다양한 Llama-3.2 모델을 파인튜닝했습니다. 따라서 레지스트리에서 다운로드한 모델을 로드할 때 어댑터가 포함된 특수 unsloth.FastLanguageModel 또는 peft.AutoPeftModelForCausalLM 모델을 사용하세요. 레지스트리의 “Use” 탭에서 로딩 코드를 복사하여 model_post_init에 붙여넣습니다.
import weave
from pydantic import PrivateAttr
from typing import Any, List, Dict, Optional
from unsloth import FastLanguageModel
import torch


class UnslothLoRAChatModel(weave.Model):
    """
    모델 이름 이상의 파라미터를 저장하고 버전 관리하기 위해 추가 ChatModel 클래스를 정의합니다.
    이를 통해 특정 파라미터에 대한 파인튜닝이 가능해집니다.
    """

    chat_model: str
    cm_temperature: float
    cm_max_new_tokens: int
    cm_quantize: bool
    inference_batch_size: int
    dtype: Any
    device: str
    _model: Any = PrivateAttr()
    _tokenizer: Any = PrivateAttr()

    def model_post_init(self, __context):
        # wandb run 시작 및 아티팩트 다운로드
        run = wandb.init(project=PROJECT, job_type="model_download")
        artifact_ref = self.chat_model.replace("wandb-artifact://", "")
        artifact = run.use_artifact(artifact_ref)
        model_path = artifact.download()

        # unsloth 버전 (기본적으로 2배 빠른 추론 활성화)
        self._model, self._tokenizer = FastLanguageModel.from_pretrained(
            model_name=model_path,
            max_seq_length=self.cm_max_new_tokens,
            dtype=self.dtype,
            load_in_4bit=self.cm_quantize,
        )
        FastLanguageModel.for_inference(self._model)

    @weave.op()
    async def predict(self, query: List[str]) -> dict:
        # add_generation_prompt = true - 생성을 위해 반드시 추가해야 함
        input_ids = self._tokenizer.apply_chat_template(
            query,
            tokenize=True,
            add_generation_prompt=True,
            return_tensors="pt",
        ).to("cuda")

        output_ids = self._model.generate(
            input_ids=input_ids,
            max_new_tokens=64,
            use_cache=True,
            temperature=1.5,
            min_p=0.1,
        )

        decoded_outputs = self._tokenizer.batch_decode(
            output_ids[0][input_ids.shape[1] :], skip_special_tokens=True
        )

        return "".join(decoded_outputs).strip()
이제 레지스트리의 특정 링크를 사용하여 새로운 모델을 생성합니다:
ORG_ENTITY = "wandb32"  # 조직 이름으로 변경하세요
artifact_name = "Finetuned Llama-3.2" # 아티팩트 이름으로 변경하세요
MODEL_REG_URL = f"wandb-artifact://{ORG_ENTITY}/wandb-registry-RAG Chat Models/{artifact_name}:v3"

max_seq_length = 2048
dtype = None
load_in_4bit = True

new_chat_model = UnslothLoRAChatModel(
    name="UnslothLoRAChatModelRag",
    chat_model=MODEL_REG_URL,
    cm_temperature=1.0,
    cm_max_new_tokens=max_seq_length,
    cm_quantize=load_in_4bit,
    inference_batch_size=max_seq_length,
    dtype=dtype,
    device="auto",
)
마지막으로 비동기 방식으로 예측을 실행합니다:
await new_chat_model.predict(
    [{"role": "user", "content": "독일의 수도는 어디인가요?"}]
)

3. 새로운 ChatModel 버전을 RagModel에 통합

파인튜닝된 채팅 모델로 RAG 앱을 구축하면 대화형 AI 시스템의 성능과 범용성을 향상시키는 데 여러 가지 이점이 있습니다. 이제 기존 Weave 프로젝트에서 RagModel을 가져와서(아래 이미지처럼 use 탭에서 현재 RagModel의 weave ref를 가져올 수 있습니다) ChatModel을 새 모델로 교체합니다. 다른 컴포넌트(VDB, 프롬프트 등)를 변경하거나 다시 만들 필요가 없습니다!
레퍼런스 코드가 포함된 Weave UI 'User' 탭
pip install litellm faiss-gpu
RagModel = weave.ref(
    "weave://wandb-smle/weave-cookboook-demo/object/RagModel:cqRaGKcxutBWXyM0fCGTR1Yk2mISLsNari4wlGTwERo"
).get()
# MAGIC: chat_model을 교체하고 새 버전을 게시 (다른 RAG 컴포넌트는 걱정할 필요 없음)
RagModel.chat_model = new_chat_model
# 예측 중에 참조될 수 있도록 먼저 새 버전을 게시합니다
PUB_REFERENCE = weave.publish(RagModel, "RagModel")
await RagModel.predict("첫 번째 기후 변화 회의는 언제 열렸나요?")

4. 기존 모델 Run에 연결된 새로운 weave.Evaluation 실행

마지막으로, 기존의 weave.Evaluation에서 새로운 RagModel을 평가합니다. 통합을 최대한 쉽게 하기 위해 다음 변경 사항을 포함합니다. Models 관점:
  • 레지스트리에서 모델을 가져오면 채팅 모델의 E2E 계보(Lineage)의 일부인 새로운 run 오브젝트가 생성됩니다.
  • 모델 팀이 링크를 클릭하여 해당 Weave 페이지로 이동할 수 있도록 Run 설정에 Trace ID(현재 평가 ID 포함)를 추가합니다.
Weave 관점:
  • 아티팩트 / 레지스트리 링크를 ChatModel(RagModel 내의)의 입력으로 저장합니다.
  • weave.attributes를 사용하여 run.id를 trace의 추가 컬럼으로 저장합니다.
# MAGIC: 평가 데이터셋과 scorer가 있는 평가를 가져와서 사용합니다
WEAVE_EVAL = "weave://wandb-smle/weave-cookboook-demo/object/climate_rag_eval:ntRX6qn3Tx6w3UEVZXdhIh1BWGh7uXcQpOQnIuvnSgo"
climate_rag_eval = weave.ref(WEAVE_EVAL).get()

run = wandb.init()

with weave.attributes({"wandb-run-id": run.id}):
    # .call 속성을 사용하여 결과와 call을 모두 가져와 평가 trace를 Models에 저장합니다
    summary, call = await climate_rag_eval.evaluate.call(climate_rag_eval, RagModel)

5. 레지스트리에 새로운 RAG 모델 저장

새로운 RAG 모델을 효율적으로 공유하기 위해, Weave 버전을 에일리어스로 추가하여 레퍼런스 아티팩트로 레지스트리에 푸시합니다.
MODELS_OBJECT_VERSION = PUB_REFERENCE.digest  # weave 오브젝트 버전
MODELS_OBJECT_NAME = PUB_REFERENCE.name  # weave 오브젝트 이름

models_url = f"https://wandb.ai/{ENTITY}/{PROJECT}/weave/objects/{MODELS_OBJECT_NAME}/versions/{MODELS_OBJECT_VERSION}"
models_link = (
    f"weave://{ENTITY}/{PROJECT}/object/{MODELS_OBJECT_NAME}:{MODELS_OBJECT_VERSION}"
)

with wandb.init(project=PROJECT, entity=ENTITY) as run:
    # 새로운 Artifact 생성
    artifact_model = wandb.Artifact(
        name="RagModel",
        type="model",
        description="Weave의 RagModel에서 연결된 모델 링크",
        metadata={"url": models_url},
    )
    artifact_model.add_reference(models_link, name="model", checksum=False)

    # 새로운 아티팩트 로그
    run.log_artifact(artifact_model, aliases=[MODELS_OBJECT_VERSION])

    # 레지스트리에 연결
    run.link_artifact(
        artifact_model, target_path="wandb32/wandb-registry-RAG Models/RAG Model"
    )