Transformers documentation

Utilisation d'outils

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.2).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Utilisation d'outils

Les modèles de chat sont couramment entraînés avec un support pour le « function-calling » ou le « tool-use ». Les outils sont des fonctions fournies par l'utilisateur, que le modèle peut choisir d'appeler dans le cadre de sa réponse. Par exemple, un modèle pourrait avoir accès à un outil de calculatrice pour effectuer des opérations arithmétiques sans avoir à effectuer le calcul en interne.

Ce guide montre comment définir des outils, comment les passer à un modèle de chat et comment traiter la sortie du modèle lorsqu’il appelle un outil.

Passage d'outils

Lorsqu’un modèle prend en charge l’utilisation d’outils, passez les fonctions à l’argument tools de apply_chat_template(). Les outils sont passés sous forme de schéma JSON ou de fonctions Python. Si vous passez des fonctions Python, les arguments, les types d’arguments et la docstring de la fonction sont analysés afin de générer automatiquement le schéma JSON.

Bien que le passage de fonctions Python soit très pratique, l’analyseur ne peut traiter que des docstrings au format Google. Reportez-vous aux exemples ci-dessous pour savoir comment formater une fonction prête à l’emploi.

def get_current_temperature(location: str, unit: str):
    """
    Get the current temperature at a location.

    Args:
        location: The location to get the temperature for, in the format "City, Country"
        unit: The unit to return the temperature in. (choices: ["celsius", "fahrenheit"])
    """
    return 22.  # A real function should probably actually get the temperature!

def get_current_wind_speed(location: str):
    """
    Get the current wind speed in km/h at a given location.

    Args:
        location: The location to get the wind speed for, in the format "City, Country"
    """
    return 6.  # A real function should probably actually get the wind speed!

tools = [get_current_temperature, get_current_wind_speed]

Vous pouvez éventuellement ajouter un bloc Returns: à la docstring et un type de retour à l’en-tête de la fonction, mais la plupart des modèles n’utiliseront pas ces informations. L’analyseur ignorera également le code réel à l’intérieur de la fonction !

Ce qui compte vraiment, c’est le nom de la fonction, les noms des arguments, les types des arguments et la docstring décrivant le but de la fonction ainsi que le but de ses arguments. Ces éléments constituent la « signature » que le modèle utilisera pour décider s’il doit appeler l’outil.

Exemple d'appel d'outil

Chargez un modèle et un tokenizer prenant en charge l'utilisation d'outils, comme NousResearch/Hermes-2-Pro-Llama-3-8B, mais vous pouvez également envisager un modèle plus grand comme Command-R et Mixtral-8x22B si votre matériel le permet.

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

checkpoint = "NousResearch/Hermes-2-Pro-Llama-3-8B"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForCausalLM.from_pretrained(checkpoint, dtype="auto", device_map="auto")

Créer un historique de chat.

messages = [
  {"role": "system", "content": "You are a bot that responds to weather queries. You should reply with the unit used in the queried location."},
  {"role": "user", "content": "Hey, what's the temperature in Paris right now?"}
]

Ensuite, passez messages et une liste d'outils à apply_chat_template(). Tokenisez la conversation et générez une réponse.

inputs = tokenizer.apply_chat_template(messages, tools=tools, add_generation_prompt=True, return_dict=True, return_tensors="pt")
outputs = model.generate(**inputs.to(model.device), max_new_tokens=128)
print(tokenizer.decode(outputs[0][len(inputs["input_ids"][0]):]))
<tool_call>
{"arguments": {"location": "Paris, France", "unit": "celsius"}, "name": "get_current_temperature"}
</tool_call><|im_end|>

Le modèle de chat a appelé l'outil get_current_temperature avec les paramètres corrects issus de la docstring. Il a déduit que la localisation était la France à partir de Paris, et qu'il devait utiliser les Celsius comme unité de température.

Un modèle ne peut pas réellement appeler l’outil lui-même. Il demande un appel d’outil, et il vous incombe de gérer cet appel, puis d’ajouter celui-ci et son résultat à l’historique de la conversation. Pour les modèles qui prennent en charge l’analyse de la réponse, cette analyse est gérée automatiquement, et vous pouvez simplement utiliser parse_response() pour extraire l’appel d’outil. Pour les autres modèles, vous devrez traduire manuellement la chaîne de sortie en dictionnaire d’appel d’outil.

Quelle que soit l’approche utilisée, l’appel d’outil doit être placé dans la clé tool_calls d’un message assistant. Il s’agit de l’API recommandée, qui devrait être prise en charge par le modèle de dialogue de la plupart des modèles utilisant des outils.

Bien que tool_calls soit similaire à l’API OpenAI, cette dernière utilise une chaîne JSON comme format pour tool_calls. Cela peut provoquer des erreurs ou un comportement inattendu du modèle si utilisé dans Transformers, qui s’attend à un dictionnaire.

tool_call = {"name": "get_current_temperature", "arguments": {"location": "Paris, France", "unit": "celsius"}}
messages.append({"role": "assistant", "tool_calls": [{"type": "function", "function": tool_call}]})

Ajoutez la réponse de l'outil à l'historique de la conversation avec le rôle tool.

messages.append({"role": "tool", "content": "22"})  # Note that the returned content is always a string!

Enfin, autorisez le modèle à lire la réponse de l'outil et à répondre à l'utilisateur.

inputs = tokenizer.apply_chat_template(messages, tools=tools, add_generation_prompt=True, return_dict=True, return_tensors="pt")
out = model.generate(**inputs.to(model.device), max_new_tokens=128)
print(tokenizer.decode(out[0][len(inputs["input_ids"][0]):]))
The temperature in Paris, France right now is 22°C.<|im_end|>

Bien que la clé du message de l'assistant s'appelle tool_calls, dans la plupart des cas, les modèles n'émettent qu'un seul appel d'outil à la fois. Certains modèles plus anciens émettent plusieurs appels d'outils simultanément, mais il s'agit d'un processus nettement plus complexe, car vous devez gérer plusieurs réponses d'outils à la fois et les désambiguïser, souvent à l'aide d'identifiants d'appel d'outil. Veuillez consulter la fiche du modèle pour connaître exactement le format que le modèle attend pour les appels d'outils.

Schémas JSON

Une autre façon de définir des outils consiste à passer un schéma JSON.

Vous pouvez également appeler manuellement les fonctions de bas niveau qui convertissent les fonctions Python en schémas JSON, puis vérifier ou modifier les schémas générés. Ce n'est généralement pas nécessaire, mais cela est utile pour comprendre les mécanismes sous-jacents. C'est particulièrement important pour les auteurs de modèles de discussion qui ont besoin d'accéder au schéma JSON pour afficher les définitions d'outils.

La méthode apply_chat_template() utilise la fonction get_json_schema pour convertir les fonctions Python appelables en schéma JSON. Cela inclut les méthodes : self et cls sont traitées comme des arguments de récepteur implicites et sont ignorées.

from transformers.utils import get_json_schema

def multiply(a: float, b: float):
    """
    A function that multiplies two numbers

    Args:
        a: The first number to multiply
        b: The second number to multiply
    """
    return a * b

schema = get_json_schema(multiply)
print(schema)
{
  "type": "function",
  "function": {
    "name": "multiply",
    "description": "A function that multiplies two numbers",
    "parameters": {
      "type": "object",
      "properties": {
        "a": {
          "type": "number",
          "description": "The first number to multiply"
        },
        "b": {
          "type": "number",
          "description": "The second number to multiply"
        }
      },
      "required": ["a", "b"]
    }
  }
}

Nous n’entrerons pas dans les détails du schéma JSON lui-même ici, car il est déjà très bien documenté ailleurs. Nous mentionnerons toutefois que vous pouvez passer des dictionnaires de schéma JSON à l’argument tools de apply_chat_template() au lieu de fonctions Python :

# A simple function that takes no arguments
current_time = {
  "type": "function",
  "function": {
    "name": "current_time",
    "description": "Get the current local time as a string.",
    "parameters": {
      'type': 'object',
      'properties': {}
    }
  }
}

# A more complete function that takes two numerical arguments
multiply = {
  'type': 'function',
  'function': {
    'name': 'multiply',
    'description': 'A function that multiplies two numbers',
    'parameters': {
      'type': 'object',
      'properties': {
        'a': {
          'type': 'number',
          'description': 'The first number to multiply'
        },
        'b': {
          'type': 'number', 'description': 'The second number to multiply'
        }
      },
      'required': ['a', 'b']
    }
  }
}

model_input = tokenizer.apply_chat_template(
    messages,
    tools = [current_time, multiply]
)
Update on GitHub