Tutoriel sur l'appel de fonction

L'appel de fonction vous permet d'obtenir plus facilement des données structurées en sortie les modèles génératifs. Vous pouvez ensuite utiliser ces sorties pour appeler d'autres API et renvoyer les données de réponse pertinentes au modèle. En d'autres termes, les appels de fonction vous aident à connecter des modèles génératifs à des systèmes externes afin que le contenu généré inclue les informations les plus récentes et les plus précises.

Vous pouvez fournir des descriptions de fonctions aux modèles Gemini. Il s'agit des fonctions que vous écrivez dans le langage de votre application (c'est-à-dire qu'elles ne sont pas Google Cloud Functions). Le modèle peut vous demander d'appeler une fonction et de renvoyer du résultat pour aider le modèle à traiter votre requête.

Si vous ne l'avez pas déjà fait, consultez le Introduction à l'appel de fonction pour en savoir plus autres. Vous pouvez aussi essayez cette fonctionnalité dans Google Colab ou consultez l'exemple de code dans le dépôt du livre de recettes de l'API Gemini.

Exemple d'API pour le contrôle de l'éclairage

Imaginez que vous disposez d'un système de contrôle de l'éclairage basique avec une application (API) et que vous voulez permettre aux utilisateurs de contrôler les éclairages via des requêtes textuelles. Vous pouvez utiliser la fonctionnalité d'appel de fonction pour interpréter l'éclairage les demandes de modification des utilisateurs et les traduire en appels d'API pour définir l'éclairage valeurs. Ce système de contrôle d'éclairage hypothétique vous permet de contrôler la luminosité de la lumière et sa température de couleur, définies comme deux paramètres distincts :

Paramètre Type Obligatoire Description
brightness Nombre oui Niveau d'éclairage compris entre 0 et 100. La valeur 0 correspond à l'arrêt et la valeur 100 à la luminosité maximale.
colorTemperature chaîne oui Température des couleurs du luminaire, qui peut être daylight, cool ou warm.

Par souci de simplicité, ce système d'éclairage imaginaire n'a qu'une seule lumière. L'utilisateur n'a pas besoin de spécifier une pièce ou un lieu. Voici un exemple de requête JSON vous pouvez envoyer à l'API de contrôle de l'éclairage pour faire passer le niveau de luminosité à 50% en utilisant la température des couleurs en plein jour:

{
  "brightness": "50",
  "colorTemperature": "daylight"
}

Ce tutoriel explique comment configurer un appel de fonction pour que l'API Gemini interpréter les requêtes d'éclairage des utilisateurs et les mapper avec les paramètres d'API pour contrôler la luminosité et la température des couleurs de la lumière.

Avant de commencer : configurez votre projet et votre clé API

Avant d'appeler l'API Gemini, vous devez configurer votre projet et votre clé API.

Définir une fonction d'API

Créez une fonction qui envoie une requête API. Cette fonction doit être définie dans le code de l'application, mais elle peut appeler des services ou des API en dehors votre application. L'API Gemini n'appelle pas cette fonction directement. Vous devez donc peut contrôler quand et comment cette fonction est exécutée via votre application du code source. À des fins de démonstration, ce tutoriel définit une fonction d'API fictive qui ne renvoie que les valeurs d'éclairage demandées :

def set_light_values(brightness, color_temp):
    """Set the brightness and color temperature of a room light. (mock API).

    Args:
        brightness: Light level from 0 to 100. Zero is off and 100 is full brightness
        color_temp: Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.

    Returns:
        A dictionary containing the set brightness and color temperature.
    """
    return {
        "brightness": brightness,
        "colorTemperature": color_temp
    }

Lorsque vous créez une fonction qui sera utilisée par le modèle dans un appel de fonction, vous doit inclure autant de détails que possible dans la fonction et le paramètre des descriptions détaillées. Le modèle génératif utilise ces informations pour déterminer sélectionner et comment fournir des valeurs pour les paramètres de la fonction .

Déclarer des fonctions lors de l'initialisation du modèle

Pour utiliser l'appel de fonction avec un modèle, vous devez déclarer votre lorsque vous initialisez l'objet du modèle. Vous déclarez des fonctions en définissant le paramètre tools du modèle:

model = genai.GenerativeModel(model_name='gemini-1.5-flash',
                              tools=[set_light_values])

Générer un appel de fonction

Une fois que vous avez initialisé le modèle avec vos déclarations de fonction, vous pouvez envoyer une requête avec la fonction définie. Vous devez utiliser l'appel de fonction à l'aide d'une requête de chat (sendMessage()), car l'appel de fonction bénéficie généralement du contexte des requêtes et réponses précédentes.

chat = model.start_chat()
response = chat.send_message('Dim the lights so the room feels cozy and warm.')
response.text

L'objet ChatSession du SDK Python simplifie la gestion des sessions de chat en gérant l'historique des conversations à votre place. Vous pouvez utiliser enable_automatic_function_calling pour obtenir le SDK appelle automatiquement la fonction.

# Create a chat session that automatically makes suggested function calls
chat = model.start_chat(enable_automatic_function_calling=True)

Appels de fonction en parallèle

En plus de l'appel de fonction de base décrit ci-dessus, vous pouvez également appeler plusieurs fonctions en un seul tour. Cette section présente un exemple d'utilisation de l'appel de fonction parallèle.

Définir les outils

def power_disco_ball(power: bool) -> bool:
    """Powers the spinning disco ball."""
    print(f"Disco ball is {'spinning!' if power else 'stopped.'}")
    return True


def start_music(energetic: bool, loud: bool, bpm: int) -> str:
    """Play some music matching the specified parameters.

    Args:
      energetic: Whether the music is energetic or not.
      loud: Whether the music is loud or not.
      bpm: The beats per minute of the music.

    Returns: The name of the song being played.
    """
    print(f"Starting music! {energetic=} {loud=}, {bpm=}")
    return "Never gonna give you up."


def dim_lights(brightness: float) -> bool:
    """Dim the lights.

    Args:
      brightness: The brightness of the lights, 0.0 is off, 1.0 is full.
    """
    print(f"Lights are now set to {brightness:.0%}")
    return True

Appelez maintenant le modèle avec une instruction qui pourrait utiliser tous les outils spécifiés.

# Set the model up with tools.
house_fns = [power_disco_ball, start_music, dim_lights]

model = genai.GenerativeModel(model_name="gemini-1.5-flash", tools=house_fns)

# Call the API.
chat = model.start_chat()
response = chat.send_message("Turn this place into a party!")

# Print out each of the function calls requested from this single call.
for part in response.parts:
    if fn := part.function_call:
        args = ", ".join(f"{key}={val}" for key, val in fn.args.items())
        print(f"{fn.name}({args})")
power_disco_ball(power=True)
start_music(energetic=True, loud=True, bpm=120.0)
dim_lights(brightness=0.3)

Chacun des résultats imprimés reflète un seul appel de fonction que le modèle a demandé. Pour renvoyer les résultats, incluez les réponses dans le même ordre que celui demandé.

# Simulate the responses from the specified tools.
responses = {
    "power_disco_ball": True,
    "start_music": "Never gonna give you up.",
    "dim_lights": True,
}

# Build the response parts.
response_parts = [
    genai.protos.Part(function_response=genai.protos.FunctionResponse(name=fn, response={"result": val}))
    for fn, val in responses.items()
]

response = chat.send_message(response_parts)
print(response.text)
Let's get this party started! I've turned on the disco ball, started playing some upbeat music, and dimmed the lights. 🎶✨  Get ready to dance! 🕺💃

Mappage des types de données d'un appel de fonction

L'extraction automatique de schémas à partir de fonctions Python ne fonctionne pas dans tous les cas. Par exemple, il ne gère pas les cas où vous décrivez les champs d'un objet de dictionnaire imbriqué, mais l'API le fait. L'API peut décrire l'un des types suivants :

AllowedType = (int | float | bool | str | list['AllowedType'] | dict[str, AllowedType])

La bibliothèque cliente google.ai.generativelanguage donne accès aux types de bas niveau, ce qui vous donne un contrôle total.

Examinez d'abord l'attribut _tools du modèle. Vous pouvez voir comment il décrit la ou les fonctions que vous avez transmises au modèle:

def multiply(a:float, b:float):
    """returns a * b."""
    return a*b

model = genai.GenerativeModel(model_name='gemini-1.5-flash',
                             tools=[multiply])

model._tools.to_proto()
[function_declarations {
   name: "multiply"
   description: "returns a * b."
   parameters {
     type_: OBJECT
     properties {
       key: "b"
       value {
         type_: NUMBER
       }
     }
     properties {
       key: "a"
       value {
         type_: NUMBER
       }
     }
     required: "a"
     required: "b"
   }
 }]

Cela renvoie la liste des objets genai.protos.Tool qui seraient envoyés à l'API. Si le format imprimé ne vous est pas familier, c'est parce qu'il s'agit protobuf. Chaque genai.protos.Tool (1 dans ce cas) contient une liste de genai.protos.FunctionDeclarations, qui décrivent une fonction et ses .

Voici une déclaration de la même fonction de multiplication écrite à l'aide des classes genai.protos. Notez que ces classes décrivent simplement la fonction l'API, ils n'incluent aucune implémentation de celle-ci. Par conséquent, cette méthode ne fonctionne pas avec l'appel automatique des fonctions, mais les fonctions n'ont pas toujours besoin d'une implémentation.

calculator = genai.protos.Tool(
    function_declarations=[
      genai.protos.FunctionDeclaration(
        name='multiply',
        description="Returns the product of two numbers.",
        parameters=genai.protos.Schema(
            type=genai.protos.Type.OBJECT,
            properties={
                'a':genai.protos.Schema(type=genai.protos.Type.NUMBER),
                'b':genai.protos.Schema(type=genai.protos.Type.NUMBER)
            },
            required=['a','b']
        )
      )
    ])

De manière équivalente, vous pouvez décrire cela comme un objet compatible JSON:

calculator = {'function_declarations': [
      {'name': 'multiply',
       'description': 'Returns the product of two numbers.',
       'parameters': {'type_': 'OBJECT',
       'properties': {
         'a': {'type_': 'NUMBER'},
         'b': {'type_': 'NUMBER'} },
       'required': ['a', 'b']} }]}
genai.protos.Tool(calculator)
function_declarations {
  name: "multiply"
  description: "Returns the product of two numbers."
  parameters {
    type_: OBJECT
    properties {
      key: "b"
      value {
        type_: NUMBER
      }
    }
    properties {
      key: "a"
      value {
        type_: NUMBER
      }
    }
    required: "a"
    required: "b"
  }
}

Dans tous les cas, vous transmettez une représentation d'un genai.protos.Tool ou d'une liste d'outils à

model = genai.GenerativeModel('gemini-1.5-flash', tools=calculator)
chat = model.start_chat()

response = chat.send_message(
    f"What's 234551 X 325552 ?",
)

Comme précédemment, le modèle renvoie un genai.protos.FunctionCall appelant la fonction multiply du calculateur:

response.candidates
[index: 0
content {
  parts {
    function_call {
      name: "multiply"
      args {
        fields {
          key: "b"
          value {
            number_value: 325552
          }
        }
        fields {
          key: "a"
          value {
            number_value: 234551
          }
        }
      }
    }
  }
  role: "model"
}
finish_reason: STOP
]

Exécutez la fonction vous-même :

fc = response.candidates[0].content.parts[0].function_call
assert fc.name == 'multiply'

result = fc.args['a'] * fc.args['b']
result
76358547152.0

Envoyez le résultat au modèle pour poursuivre la conversation:

response = chat.send_message(
    genai.protos.Content(
    parts=[genai.protos.Part(
        function_response = genai.protos.FunctionResponse(
          name='multiply',
          response={'result': result}))]))