Passer au contenu principal
Il s’agit d’un notebook interactif. Vous pouvez l’exécuter en local ou utiliser les liens ci-dessous :

Prérequis

Commencez par installer les bibliothèques nécessaires, configurer vos clés API, vous connecter à W&B et créer un projet W&B.
  1. Installez weave, pandas, unsloth, wandb, litellm, pydantic, torch et faiss-gpu à l’aide de pip.
%%capture
!pip install weave wandb pandas pydantic litellm faiss-gpu
python
%%capture
!pip install unsloth
# Obtenez également la dernière version nightly d'Unsloth !
!pip uninstall unsloth -y && pip install --upgrade --no-cache-dir "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"
  1. Ajoutez les clés API nécessaires à partir de votre environnement.
import os

from google.colab import userdata

os.environ["WANDB_API_KEY"] = userdata.get("WANDB_API_KEY")  # W&B Models and Weave
os.environ["OPENAI_API_KEY"] = userdata.get(
    "OPENAI_API_KEY"
)  # OpenAI - pour les embeddings de récupération
os.environ["GEMINI_API_KEY"] = userdata.get(
    "GEMINI_API_KEY"
)  # Gemini - pour le modèle de chat de base
  1. Connectez-vous à W&B, puis créez un nouveau projet.
import pandas as pd
import wandb

import weave

wandb.login()

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

weave.init(ENTITY + "/" + PROJECT)

Télécharger ChatModel depuis Models registre et implémenter UnslothLoRAChatModel

Dans notre scénario, le modèle Llama-3.2 a déjà été affiné par la Model Team à l’aide de la bibliothèque unsloth pour optimiser les performances, et est disponible dans le W&B Models registre. Dans cette étape, nous allons récupérer le ChatModel affiné depuis le registre et le convertir en weave.Model pour le rendre compatible avec le RagModel.
Le RagModel mentionné ci-dessous est un weave.Model de premier niveau qui peut être considéré comme une application RAG complète. Il contient un ChatModel, une base de données vectorielle et un prompt. Le ChatModel est lui aussi un weave.Model, qui contient le code nécessaire pour télécharger un artifact depuis le W&B registre. ChatModel peut être remplacé de manière modulaire pour prendre en charge n’importe quel autre type de modèle de chat LLM au sein du RagModel. Pour plus d’informations, voir le modèle dans Weave.
Pour charger le ChatModel, unsloth.FastLanguageModel ou peft.AutoPeftModelForCausalLM avec adaptateurs sont utilisés, ce qui permet une intégration efficace dans l’application. Après avoir téléchargé le modèle depuis le registre, vous pouvez configurer la logique d’initialisation et de prédiction à l’aide de la méthode model_post_init. Le code requis pour cette étape est disponible dans l’onglet Use du registre et peut être copié directement dans votre implémentation Le code ci-dessous définit la classe UnslothLoRAChatModel pour gérer, initialiser et utiliser le modèle Llama-3.2 affiné récupéré depuis le W&B Models registre. UnslothLoRAChatModel utilise unsloth.FastLanguageModel pour une inférence optimisée. La méthode model_post_init gère le téléchargement et la configuration du modèle, tandis que la méthode predict traite les requêtes des utilisateurs et génère des réponses. Pour adapter le code à votre cas d’usage, mettez à jour MODEL_REG_URL avec le bon chemin du registre pour votre modèle affiné et ajustez des paramètres comme max_seq_length ou dtype en fonction de votre matériel ou de vos requirements.
from typing import Any

from pydantic import PrivateAttr
from unsloth import FastLanguageModel

import weave

class UnslothLoRAChatModel(weave.Model):
    """
    Nous définissons une classe ChatModel supplémentaire pour pouvoir stocker et versionner davantage de paramètres que le simple nom du modèle.
    Particulièrement pertinent si l'on envisage le fine-tuning (en local ou en aaS) en raison de paramètres spécifiques.
    """

    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):
        # nous pouvons simplement coller ceci depuis l'onglet "Use" du registre
        run = wandb.init(project=PROJECT, job_type="model_download")
        artifact = run.use_artifact(f"{self.chat_model}")
        model_path = artifact.download()

        # version unsloth (active l'inférence native 2x plus rapide)
        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 - Obligatoire pour la génération
        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
MODEL_REG_URL = "wandb32/wandb-registry-RAG Chat Models/Finetuned Llama-3.2:v3"

max_seq_length = 2048  # Au choix ! Le RoPE Scaling est pris en charge automatiquement en interne !
dtype = (
    None  # None pour la détection automatique. Float16 pour Tesla T4, V100, Bfloat16 pour Ampere+
)
load_in_4bit = True  # Utiliser la quantification 4 bits pour réduire l'utilisation de la mémoire. Peut être False.

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
await new_chat_model.predict(
    [{"role": "user", "content": "What is the capital of Germany?"}]
)

Intégrer la nouvelle version de ChatModel dans RagModel

Construire une application RAG à partir d’un modèle de chat affiné améliore l’IA conversationnelle en s’appuyant sur des composants adaptés, sans avoir à reconstruire l’ensemble du pipeline. Dans cette étape, nous récupérons le RagModel existant dans notre projet Weave et mettons à jour son ChatModel pour utiliser le modèle nouvellement affiné. Ce remplacement transparent signifie que les autres composants, comme la base de données vectorielle (VDB) et les prompts, restent inchangés, ce qui préserve la structure globale de l’application tout en améliorant les performances. Le code ci-dessous récupère l’objet RagModel à l’aide d’une référence du projet Weave. L’attribut chat_model du RagModel est ensuite mis à jour pour utiliser la nouvelle instance UnslothLoRAChatModel créée à l’étape précédente. Ensuite, le RagModel mis à jour est publié afin de créer une nouvelle version. Enfin, le RagModel mis à jour sert à exécuter un exemple de requête de prédiction, afin de vérifier que le nouveau modèle de chat est bien utilisé.
RagModel = weave.ref(
    "weave://wandb-smle/weave-cookboook-demo/object/RagModel:cqRaGKcxutBWXyM0fCGTR1Yk2mISLsNari4wlGTwERo"
).get()
python
RagModel.chat_model.chat_model
python
await RagModel.predict("When was the first conference on climate change?")
python
# MAGIC : remplacement du chat_model et publication d'une nouvelle version (inutile de se soucier des autres composants RAG)
RagModel.chat_model = new_chat_model
python
RagModel.chat_model.chat_model
python
# publier d'abord la nouvelle version pour référencer la nouvelle version dans la prédiction
PUB_REFERENCE = weave.publish(RagModel, "RagModel")
python
await RagModel.predict("When was the first conference on climate change?")

Exécuter une weave.Evaluation

À l’étape suivante, nous évaluons les performances de notre RagModel mis à jour à l’aide d’une weave.Evaluation existante. Ce processus garantit que le nouveau modèle de chat affiné se comporte comme prévu dans l’application RAG. Pour simplifier l’intégration et permettre la collaboration entre les équipes Models et Apps, nous consignons les résultats de l’évaluation à la fois dans le run W&B du modèle et dans le workspace Weave. Dans Models :
  • Le résumé de l’évaluation est consigné dans le run W&B utilisé pour télécharger le modèle de chat affiné. Cela inclut des métriques de synthèse et des graphiques affichés dans une vue Workspace pour l’analyse.
  • L’ID de trace de l’évaluation est ajouté à la configuration du run, avec un lien direct vers la page Weave afin de faciliter la traçabilité pour la Model Team.
Dans Weave :
  • Le lien vers l’artifact ou le registre du ChatModel est stocké comme entrée du RagModel.
  • L’ID du run W&B est enregistré comme colonne supplémentaire dans les traces d’évaluation pour fournir davantage de contexte.
Le code ci-dessous montre comment récupérer un objet d’évaluation, exécuter l’évaluation avec le RagModel mis à jour, puis consigner les résultats à la fois dans W&B et dans Weave. Assurez-vous que la référence de l’évaluation (WEAVE_EVAL) correspond à la configuration de votre projet.
# MAGIC : nous pouvons simplement obtenir une évaluation avec un jeu de données et des évaluateurs et les utiliser
WEAVE_EVAL = "weave://wandb-smle/weave-cookboook-demo/object/climate_rag_eval:ntRX6qn3Tx6w3UEVZXdhIh1BWGh7uXcQpOQnIuvnSgo"
climate_rag_eval = weave.ref(WEAVE_EVAL).get()
python
with weave.attributes({"wandb-run-id": wandb.run.id}):
    # utiliser l'attribut .call pour récupérer à la fois le résultat et l'appel afin d'enregistrer la trace d'évaluation dans Models
    summary, call = await climate_rag_eval.evaluate.call(climate_rag_eval, RagModel)
python
# enregistrer dans models
wandb.run.log(pd.json_normalize(summary, sep="/").to_dict(orient="records")[0])
wandb.run.config.update(
    {"weave_url": f"https://wandb.ai/wandb-smle/weave-cookboook-demo/r/call/{call.id}"}
)
wandb.run.finish()

Enregistrer le nouveau modèle RAG dans le registre

Pour rendre le RagModel mis à jour disponible pour une utilisation ultérieure par les équipes Models et Apps, nous le publions dans le registre Models de W&B en tant qu’artifact de référence. Le code ci-dessous récupère la version et le nom de l’objet weave du RagModel mis à jour, puis les utilise pour créer des liens de référence. Un nouvel artifact est ensuite créé dans W&B avec des métadonnées contenant l’URL Weave du modèle. Cet artifact est enregistré dans le registre W&B et lié à un chemin de registre spécifié. Avant d’exécuter le code, assurez-vous que les variables ENTITY et PROJECT correspondent à votre configuration W&B et que le chemin de registre cible est correctement spécifié. Ce processus finalise le flux de travail en publiant le nouveau RagModel dans l’écosystème W&B afin de faciliter la collaboration et la réutilisation.
MODELS_OBJECT_VERSION = PUB_REFERENCE.digest  # version de l'objet weave
MODELS_OBJECT_NAME = PUB_REFERENCE.name  # nom de l'objet weave
python
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:
    # créer un nouvel artifact
    artifact_model = wandb.Artifact(
        name="RagModel",
        type="model",
        description="Lien Models depuis RagModel dans Weave",
        metadata={"url": models_url},
    )
    artifact_model.add_reference(models_link, name="model", checksum=False)

    # journaliser le nouvel artifact
    run.log_artifact(artifact_model, aliases=[MODELS_OBJECT_VERSION])

    # lier au registre
    run.link_artifact(
        artifact_model, target_path="wandb32/wandb-registry-RAG Models/RAG Model"
    )