> ## Documentation Index
> Fetch the complete documentation index at: https://wb-21fd5541-serverless-sft-revamp.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Weave 및 Models 인테그레이션 데모

export const ColabLink = ({url}) => <a href={url} target="_blank" rel="noopener noreferrer" className="colab-link">
    <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
      <path d="M14.25.18l.9.2.73.26.59.3.45.32.34.34.25.34.16.33.1.3.04.26.02.2-.01.13V8.5l-.05.63-.13.55-.21.46-.26.38-.3.31-.33.25-.35.19-.35.14-.33.1-.3.07-.26.04-.21.02H8.77l-.69.05-.59.14-.5.22-.41.27-.33.32-.27.35-.2.36-.15.37-.1.35-.07.32-.04.27-.02.21v3.06H3.17l-.21-.03-.28-.07-.32-.12-.35-.18-.36-.26-.36-.36-.35-.46-.32-.59-.28-.73-.21-.88-.14-1.05-.05-1.23.06-1.22.16-1.04.24-.87.32-.71.36-.57.4-.44.42-.33.42-.24.4-.16.36-.1.32-.05.24-.01h.16l.06.01h8.16v-.83H6.18l-.01-2.75-.02-.37.05-.34.11-.31.17-.28.25-.26.31-.23.38-.2.44-.18.51-.15.58-.12.64-.1.71-.06.77-.04.84-.02 1.27.05zm-6.3 1.98l-.23.33-.08.41.08.41.23.34.33.22.41.09.41-.09.33-.22.23-.34.08-.41-.08-.41-.23-.33-.33-.22-.41-.09-.41.09zm13.09 3.95l.28.06.32.12.35.18.36.27.36.35.35.47.32.59.28.73.21.88.14 1.04.05 1.23-.06 1.23-.16 1.04-.24.86-.32.71-.36.57-.4.45-.42.33-.42.24-.4.16-.36.09-.32.05-.24.02-.16-.01h-8.22v.82h5.84l.01 2.76.02.36-.05.34-.11.31-.17.29-.25.25-.31.24-.38.2-.44.17-.51.15-.58.13-.64.09-.71.07-.77.04-.84.01-1.27-.04-1.07-.14-.9-.2-.73-.25-.59-.3-.45-.33-.34-.34-.25-.34-.16-.33-.1-.3-.04-.25-.02-.2.01-.13v-5.34l.05-.64.13-.54.21-.46.26-.38.3-.32.33-.24.35-.2.35-.14.33-.1.3-.06.26-.04.21-.02.13-.01h5.84l.69-.05.59-.14.5-.21.41-.28.33-.32.27-.35.2-.36.15-.36.1-.35.07-.32.04-.28.02-.21V6.07h2.09l.14.01.21.03zm-6.47 14.25l-.23.33-.08.41.08.41.23.33.33.23.41.08.41-.08.33-.23.23-.33.08-.41-.08-.41-.23-.33-.33-.23-.41-.08-.41.08z" />
    </svg>
    Try in Colab
  </a>;

<ColabLink url="https://colab.research.google.com/drive/1Uqgel6cNcGdP7AmBXe2pR9u6Dejggsh8?usp=sharing" />

이 노트북은 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는 [여기](https://wandb.ai/wandb-smle/weave-cookboook-demo/weave/evaluations)에서 확인할 수 있습니다.

<Frame>
  <img src="https://mintcdn.com/wb-21fd5541-serverless-sft-revamp/nnIqJ01CGwOGYvb1/images/tutorials/weave_models_workflow.jpg?fit=max&auto=format&n=nnIqJ01CGwOGYvb1&q=85&s=5ec623bcc279e39e533029d2aabbadfb" alt="W&B" width="2450" height="1360" data-path="images/tutorials/weave_models_workflow.jpg" />
</Frame>

워크플로우는 다음 단계로 구성됩니다:

1. W\&B Weave로 RAG 앱 코드를 계측(Instrument)합니다.
2. LLM(Llama 3.2 등, 다른 LLM으로 교체 가능)을 파인튜닝하고 W\&B Models로 추적합니다.
3. 파인튜닝된 모델을 [W\&B Registry](https://docs.wandb.ai/guides/core/registry)에 로그합니다.
4. 새로운 파인튜닝 모델로 RAG 앱을 구현하고 W\&B Weave로 앱을 평가합니다.
5. 결과가 만족스러우면 업데이트된 Rag 앱의 레퍼런스를 W\&B Registry에 저장합니다.

**참고:**

아래에서 언급되는 `RagModel`은 전체 RAG 앱으로 간주할 수 있는 최상위 `weave.Model`입니다. 여기에는 `ChatModel`, 벡터 데이터베이스 및 프롬프트가 포함됩니다. `ChatModel` 또한 W\&B Registry에서 아티팩트를 다운로드하는 코드가 포함된 또 다른 `weave.Model`이며, `RagModel`의 일부로서 다른 채팅 모델을 지원하도록 변경할 수 있습니다. 자세한 내용은 [Weave의 전체 모델](https://wandb.ai/wandb-smle/weave-cookboook-demo/weave/evaluations?peekPath=%2Fwandb-smle%2Fweave-cookboook-demo%2Fobjects%2FRagModel%2Fversions%2Fx7MzcgHDrGXYHHDQ9BA8N89qDwcGkdSdpxH30ubm8ZM%3F%26)에서 확인하세요.

## 1. 설정

먼저 `weave`와 `wandb`를 설치한 다음 API 키로 로그인합니다. API 키는 [User Settings](https://wandb.ai/settings)에서 생성하고 확인할 수 있습니다.

```bash theme={null}
pip install weave wandb
```

```python theme={null}
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`](https://wandb.ai/wandb-smle/weave-cookboook-demo/weave/object-versions?filter=%7B%22objectName%22%3A%22RagModel%22%7D\&peekPath=%2Fwandb-smle%2Fweave-cookboook-demo%2Fobjects%2FRagModel%2Fversions%2FcqRaGKcxutBWXyM0fCGTR1Yk2mISLsNari4wlGTwERo%3F%26)에 직접 연결할 수 있습니다. 기존 [ChatModel](https://wandb.ai/wandb-smle/weave-cookboook-demo/weave/object-versions?filter=%7B%22objectName%22%3A%22RagModel%22%7D\&peekPath=%2Fwandb-smle%2Fweave-rag-experiments%2Fobjects%2FChatModelRag%2Fversions%2F2mhdPb667uoFlXStXtZ0MuYoxPaiAXj3KyLS1kYRi84%3F%26)과 동일한 파라미터를 사용하며, `init`과 `predict`만 변경됩니다.

```bash theme={null}
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`에 붙여넣습니다.

```python theme={null}
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()
```

이제 레지스트리의 특정 링크를 사용하여 새로운 모델을 생성합니다:

```python theme={null}
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",
)
```

마지막으로 비동기 방식으로 예측을 실행합니다:

```python theme={null}
await new_chat_model.predict(
    [{"role": "user", "content": "독일의 수도는 어디인가요?"}]
)
```

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

파인튜닝된 채팅 모델로 RAG 앱을 구축하면 대화형 AI 시스템의 성능과 범용성을 향상시키는 데 여러 가지 이점이 있습니다.

이제 기존 Weave 프로젝트에서 [`RagModel`](https://wandb.ai/wandb-smle/weave-cookboook-demo/weave/object-versions?filter=%7B%22objectName%22%3A%22RagModel%22%7D\&peekPath=%2Fwandb-smle%2Fweave-cookboook-demo%2Fobjects%2FRagModel%2Fversions%2FcqRaGKcxutBWXyM0fCGTR1Yk2mISLsNari4wlGTwERo%3F%26)을 가져와서(아래 이미지처럼 use 탭에서 현재 `RagModel`의 weave ref를 가져올 수 있습니다) `ChatModel`을 새 모델로 교체합니다. 다른 컴포넌트(VDB, 프롬프트 등)를 변경하거나 다시 만들 필요가 없습니다!

<Frame>
  <img src="https://mintcdn.com/wb-21fd5541-serverless-sft-revamp/nnIqJ01CGwOGYvb1/images/tutorials/weave-ref-1.png?fit=max&auto=format&n=nnIqJ01CGwOGYvb1&q=85&s=5a6b1730a735454ce14b78a57010923f" alt="레퍼런스 코드가 포함된 Weave UI 'User' 탭" width="1572" height="1076" data-path="images/tutorials/weave-ref-1.png" />
</Frame>

```bash theme={null}
pip install litellm faiss-gpu
```

```python theme={null}
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의 추가 컬럼으로 저장합니다.

```python theme={null}
# 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 버전을 에일리어스로 추가하여 레퍼런스 아티팩트로 레지스트리에 푸시합니다.

```python theme={null}
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"
    )
```
