Appel de fonction

Présentation

Vous pouvez utiliser les appels de fonction pour définir des fonctions personnalisées et les fournir à un modèle d'IA générative. Lors du traitement d'une requête, le modèle peut choisir de déléguer certaines tâches de traitement de données à ces fonctions. Il n'appelle pas les fonctions. Il fournit une sortie de données structurées incluant le nom d'une fonction sélectionnée et les arguments avec lesquels le modèle propose d'appeler cette fonction. Vous pouvez utiliser cette sortie pour appeler des API externes. Vous pouvez ensuite renvoyer le résultat de l'API au modèle, lui permettant ainsi d'apporter une réponse complète à la requête. Lorsqu'il est utilisé de cette manière, l'appel de fonction permet aux LLM d'accéder à des informations en temps réel et d'interagir avec différents services, tels que les bases de données SQL, les systèmes de gestion de la relation client et les dépôts de documents.

Le schéma suivant illustre le fonctionnement des appels de fonction : Interaction d'appel de fonction 

Pour en savoir plus sur les cas d'utilisation des appels de fonction, consultez la section Cas d'utilisation des appels de fonction. Pour apprendre à créer une application d'appel de fonction, consultez la page Créer une application d'appel de fonction. Pour connaître les bonnes pratiques, consultez la section Bonnes pratiques.

L'appel de fonction est une fonctionnalité du modèle gemini-1.0-pro-001 et une fonctionnalité Bêta du modèle gemini-1.0-pro-002.

L'appel de fonction est une fonctionnalité du modèle Gemini 1.5 Pro (bêta).

Cas d'utilisation des appels de fonction

Vous pouvez utiliser les appels de fonction pour les tâches suivantes:

Créer une application d'appel de fonction

Pour permettre à un utilisateur de communiquer avec le modèle et d'utiliser des appels de fonction, vous devez créer du code qui effectue les tâches suivantes :

Vous pouvez créer une application qui gère toutes ces tâches. Il peut s'agir d'un chatbot textuel, d'un agent vocal, d'un workflow automatisé ou d'un autre programme.

Définir et décrire un ensemble de fonctions disponibles

L'application doit déclarer un ensemble de fonctions que le modèle peut utiliser pour traiter la requête. Chaque déclaration de fonction doit inclure un nom de fonction et des paramètres de fonction. Nous vous recommandons vivement d'inclure une description de fonction dans chaque déclaration de fonction.

Nom de la fonction

L'application et le modèle utilisent le nom de la fonction pour identifier celle-ci.

Pour connaître les bonnes pratiques concernant le nom de la fonction, consultez la section Bonnes pratiques – Nom de la fonction.

Paramètres de fonction

Les paramètres de fonction doivent être fournis dans un format compatible avec le schéma OpenAPI.

Vertex AI offre une compatibilité limitée avec le schéma OpenAPI. Les attributs suivants sont acceptés : type, nullable, required, format, description, properties, items, enum. Les attributs suivants ne sont pas acceptés : default, optional, maximum, oneOf.

Lorsque vous utilisez curl, spécifiez le schéma à l'aide de JSON. Lorsque vous utilisez le SDK Vertex AI pour Python, spécifiez le schéma à l'aide d'un dictionnaire Python.

Pour connaître les bonnes pratiques liées aux paramètres de fonction, consultez la section Bonnes pratiques : paramètres de fonction.

Description de la fonction

Le modèle utilise des descriptions de fonctions pour comprendre leur objectif et déterminer si celles-ci sont utiles dans le traitement des requêtes utilisateur.

Pour connaître les bonnes pratiques liées à la description de la fonction, consultez la section Bonnes pratiques – Description de la fonction.

Exemple de déclaration de fonction

Voici un exemple de déclaration de fonction simple en Python:

get_current_weather_func = FunctionDeclaration(
    name="get_current_weather",
    description="Get the current weather in a given location",
    parameters={
        "type": "object",
        "properties": {"location": {"type": "string", "description": "The city name of the location for which to get the weather."}},
    },
)

Voici un exemple de déclaration de fonction avec un tableau d'éléments:

extract_sale_records_func = FunctionDeclaration(
   name="extract_sale_records",
   description="Extract sale records from a document.",
   parameters={
       "type": "object",
       "properties": {
           "records": {
               "type": "array",
               "description": "A list of sale records",
               "items": {
                   "description": "Data for a sale record",
                   "type": "object",
                   "properties": {
                "id": {"type": "integer", "description": "The unique id of the sale."},
                       "date": {"type": "string", "description": "Date of the sale, in the format of MMDDYY, e.g., 031023"},
                       "total_amount": {"type": "number", "description": "The total amount of the sale."},
                       "customer_name": {"type": "string", "description": "The name of the customer, including first name and last name."},
                       "customer_contact": {"type": "string", "description": "The phone number of the customer, e.g., 650-123-4567."},
                   },
                   "required": ["id", "date", "total_amount"],
               },
           },
       },
       "required": ["records"],
   },
)

Envoyer la requête et les déclarations de fonction au modèle

Lorsque l'utilisateur fournit une requête, l'application doit fournir au modèle la requête utilisateur et les déclarations de fonctions. Pour configurer la manière dont le modèle génère des résultats, l'application peut fournir au modèle une configuration de génération. Pour configurer la manière dont le modèle utilise les déclarations de fonction, l'application peut fournir au modèle une configuration d'outil.

Requête de l'utilisateur

Voici un exemple de requête utilisateur: "Quel temps fait-il à Boston ?".

Pour connaître les bonnes pratiques concernant la requête utilisateur, consultez la page Bonnes pratiques – Requête utilisateur.

Configuration de génération

Le modèle peut générer différents résultats pour différentes valeurs de paramètre. Le paramètre de température contrôle le degré de hasard dans cette génération. Les températures inférieures sont idéales pour les fonctions qui nécessitent des valeurs de paramètres déterministes, tandis que les températures plus élevées sont idéales pour les fonctions avec des paramètres qui acceptent des valeurs de paramètres plus diversifiées ou créatives. Une température de 0 est déterministe, ce qui signifie que la réponse dont la probabilité est la plus élevée est toujours sélectionnée. Pour en savoir plus, consultez la page API Gemini.

Pour définir ce paramètre, envoyez une configuration de génération (generation_config) avec la requête et les déclarations de fonction.

Pour connaître les bonnes pratiques liées à la configuration de génération, consultez la section Bonnes pratiques - Configuration de génération.

Configuration de l'outil

Vous pouvez appliquer certaines contraintes sur la manière dont le modèle doit utiliser les déclarations de fonction que vous lui fournissez. Par exemple, au lieu de permettre au modèle de choisir entre une réponse en langage naturel et un appel de fonction, vous pouvez l'obliger à ne prédire que les appels de fonction. Vous pouvez également choisir de fournir au modèle un ensemble complet de déclarations de fonctions, mais limiter ses réponses à un sous-ensemble de ces fonctions.

Pour placer ces contraintes, envoyez une configuration d'outil (tool_config) avec la requête et les déclarations de fonction. Dans la configuration, vous pouvez spécifier l'un des modes suivants:

Mode Description
AUTO Comportement par défaut du modèle. Le modèle décide s'il faut prédire un appel de fonction ou une réponse en langage naturel.
TOUTES Le modèle ne doit prédire que les appels de fonction. Pour limiter le modèle à un sous-ensemble de fonctions, définissez les noms de fonction autorisés dans allowed_function_names.
NONE Le modèle ne doit pas prédire les appels de fonction. Ce comportement est équivalent à une requête de modèle sans aucune déclaration de fonction associée.

Le mode ANY de la configuration de l'outil est une fonctionnalité en version Bêta. Elle n'est compatible qu'avec les modèles Gemini 1.5 Pro.

Pour en savoir plus, consultez la page API d'appel de fonction.

Envoyer la requête et les déclarations de fonction

Vous trouverez ci-dessous un exemple montrant comment envoyer la requête et les déclarations de fonction au modèle, et comment contraindre le modèle à ne prédire que les appels de fonction get_current_weather.

# Initialize Vertex AI
vertexai.init(project=project_id, location=location)

# Initialize Gemini model
model = GenerativeModel("Gemini 1.5 Pro")

# Define a tool that includes the function declaration get_current_weather_func
weather_tool = Tool(
    function_declarations=[get_current_weather_func],
)

# Define the user's prompt in a Content object that we can reuse in model calls
user_prompt_content = Content(
    role="user",
    parts=[
        Part.from_text(prompt),
    ],
)

# Send the prompt and instruct the model to generate content using the Tool object that you just created
response = model.generate_content(
    user_prompt_content,
    generation_config={"temperature": 0},
    tools=[weather_tool],
    tool_config=ToolConfig(
        function_calling_config=ToolConfig.FunctionCallingConfig(
            # ANY mode forces the model to predict a function call
            mode=ToolConfig.FunctionCallingConfig.Mode.ANY,
            # Allowed functions to call when the mode is ANY. If empty, any one of
            # the provided functions are called.
            allowed_function_names=["get_current_weather"],
    ))
)
response_function_call_content = response.candidates[0].content

Si le modèle détermine qu'il a besoin du résultat d'une fonction particulière, la réponse que l'application reçoit du modèle contient le nom de la fonction et les valeurs des paramètres avec lesquels la fonction doit être appelée.

Voici un exemple de réponse du modèle. Le modèle propose d'appeler la fonction get_current_weather avec le paramètre Boston, MA.

candidates {
    content {
      role: "model"
      parts {
        function_call {
          name: "get_current_weather"
          args {
            fields {
              key: "location"
              value {
                string_value: "Boston, MA"
              }
            }
          }
        }
      }
    }
    ...
}

Appeler une API externe

Si l'application reçoit un nom de fonction et des valeurs de paramètre du modèle, elle doit se connecter à une API externe et appeler la fonction.

L'exemple suivant utilise des données synthétiques pour simuler une charge utile de réponse provenant d'une API externe:

# Check the function name that the model responded with, and make an API call to an external system
if (
    response.candidates[0].content.parts[0].function_call.name
    == "get_current_weather"
):
    # Extract the arguments to use in your API call
    location = (
        response.candidates[0].content.parts[0].function_call.args["location"]
    )

    # Here you can use your preferred method to make an API request to fetch the current weather, for example:
    # api_response = requests.post(weather_api_url, data={"location": location})

    # In this example, we'll use synthetic data to simulate a response payload from an external API
    api_response = """{ "location": "Boston, MA", "temperature": 38, "description": "Partly Cloudy",
                    "icon": "partly-cloudy", "humidity": 65, "wind": { "speed": 10, "direction": "NW" } }"""

Pour connaître les bonnes pratiques relatives aux appels d'API, consultez la page Bonnes pratiques pour les appels d'API.

Fournir la sortie de la fonction au modèle

Après qu'une application a reçu une réponse d'une API externe, elle doit fournir cette réponse au modèle. Vous trouverez ci-dessous un exemple de cette procédure avec Python:

response = model.generate_content(
    [
        user_prompt_content,  # User prompt
        response_function_call_content,  # Function call response
        Content(
            parts=[
                Part.from_function_response(
                    name="get_current_weather",
                    response={
                        "content": api_response,  # Return the API response to Gemini
                    },
                )
            ],
        ),
    ],
    tools=[weather_tool],
)
# Get the model summary response
summary = response.candidates[0].content.parts[0].text

Si le modèle détermine que la réponse de l'API est suffisante pour répondre à la requête de l'utilisateur, il crée une réponse en langage naturel et la renvoie à l'application. Dans ce cas, l'application doit renvoyer la réponse à l'utilisateur. Voici un exemple de réponse à une requête : It is currently 38 degrees Fahrenheit in Boston, MA with partly cloudy skies. The humidity is 65% and the wind is blowing at 10 mph from the northwest.

Si le modèle détermine que le résultat d'une autre fonction est nécessaire pour répondre à la requête, la réponse que l'application reçoit du modèle contient un autre nom de fonction et un autre ensemble de valeurs de paramètres.

Bonnes pratiques

Nom de la fonction

N'utilisez pas de point (.), de tiret (-) ni d'espace dans le nom de la fonction. Utilisez plutôt des traits de soulignement (_) ou d'autres caractères.

Paramètres de fonction

Rédigez des descriptions de paramètres claires et détaillées, comprenant des détails tels que le format ou les valeurs que vous préférez. Par exemple, pour une fonction book_flight_ticket:

  • Voici un bon exemple de description de paramètre departure : Use the 3 char airport code to represent the airport. For example, SJC or SFO. Don't use the city name.
  • Voici un mauvais exemple de description du paramètre departure : the departure airport

Si possible, utilisez des paramètres fortement typés pour réduire les hallucinations du modèle. Par exemple, si les valeurs des paramètres proviennent d'un ensemble fini, ajoutez un champ enum au lieu de placer l'ensemble de valeurs dans la description. Si la valeur du paramètre est toujours un entier, définissez le type sur integer plutôt que number.

Description de la fonction

Rédigez des descriptions de fonction claires et détaillées. Par exemple, pour une fonction book_flight_ticket:

  • Voici un exemple de description de fonction appropriée :book flight tickets after confirming users' specific requirements, such as time, departure, destination, party size and preferred airline
  • Voici un exemple de description de fonction incorrecte : book flight ticket

Requête de l'utilisateur

Pour de meilleurs résultats, ajoutez les informations suivantes en préfixe à la requête utilisateur:

  • Contexte supplémentaire pour le modèle (par exemple, You are a flight API assistant to help with searching flights based on user preferences.)
  • Détails ou instructions sur quand et comment utiliser des fonctions (par exemple, Don't make assumptions on the departure or destination airports. Always use a future date for the departure or destination time.)
  • Instructions pour poser des questions de clarification si les requêtes des utilisateurs sont ambiguës (par exemple, Ask clarifying questions if not enough information is available.)

Configuration de génération

Pour le paramètre de température, utilisez 0 ou une autre valeur faible. Cela indique au modèle de générer des résultats plus fiables et de réduire les hallucinations.

Appel d'API

Si le modèle propose d'appeler une fonction qui permet d'envoyer une commande, de mettre à jour une base de données ou de provoquer des conséquences importantes, validez l'appel de fonction auprès de l'utilisateur avant de l'exécuter.

Tarification

Les tarifs des appels de fonction sont basés sur le nombre de caractères dans les entrées et les sorties de texte. Pour en savoir plus, consultez les tarifs de Vertex AI.

Ici, la saisie de texte (requête) fait référence à la requête utilisateur pour le tour de conversation en cours, aux déclarations de fonction pour le tour de conversation en cours et à l'historique de la conversation. L'historique de la conversation inclut les requêtes, les appels de fonction et les réponses de fonction des tours de conversation précédents. Vertex AI tronque l'historique de la conversation à 32 000 caractères.

La sortie textuelle (réponse) fait référence aux appels de fonction et aux réponses textuelles pour le tour de conversation en cours.

Exemples d'appels de fonction

Vous pouvez utiliser les appels de fonction pour générer une réponse textuelle unique ou pour prendre en charge une session de chat. Les réponses textuelles ad hoc sont utiles pour des tâches métier spécifiques, y compris la génération de code. Les sessions de chat sont utiles dans des scénarios de conversation libres, où un utilisateur est susceptible de poser des questions de suivi.

Si vous utilisez les appels de fonction pour générer une seule réponse, vous devez fournir au modèle le contexte complet de l'interaction. En revanche, si vous utilisez l'appel de fonction dans le contexte d'une session de chat, celle-ci stocke le contexte à votre place et l'inclut dans chaque requête de modèle. Dans les deux cas, Vertex AI stocke l'historique de l'interaction côté client.

Pour apprendre à utiliser les appels de fonction pour générer une réponse textuelle unique, consultez la section Exemples textuels. Pour savoir comment utiliser les appels de fonction pour prendre en charge une session de chat, consultez des exemples de chat.

Exemples textuels

Python

Cet exemple illustre un scénario de texte avec une fonction et une requête. Il utilise la classe GenerativeModel et ses méthodes. Pour en savoir plus sur l'utilisation du SDK Vertex AI pour Python avec des modèles multimodaux Gemini, consultez la page Présentation des classes multimodales dans le SDK Vertex AI pour Python.

Python

Pour savoir comment installer ou mettre à jour le SDK pour Python, consultez la page Installer le SDK Vertex AI pour Python. Pour en savoir plus, consultez la documentation de référence de l'API Python.

import vertexai
from vertexai.generative_models import (
    Content,
    FunctionDeclaration,
    GenerationConfig,
    GenerativeModel,
    Part,
    Tool,
)

def generate_function_call(prompt: str, project_id: str, location: str) -> tuple:
    # Initialize Vertex AI
    vertexai.init(project=project_id, location=location)

    # Initialize Gemini model
    model = GenerativeModel("gemini-1.0-pro")

    # Specify a function declaration and parameters for an API request
    get_current_weather_func = FunctionDeclaration(
        name="get_current_weather",
        description="Get the current weather in a given location",
        # Function parameters are specified in OpenAPI JSON schema format
        parameters={
            "type": "object",
            "properties": {"location": {"type": "string", "description": "Location"}},
        },
    )

    # Define a tool that includes the above get_current_weather_func
    weather_tool = Tool(
        function_declarations=[get_current_weather_func],
    )

    # Define the user's prompt in a Content object that we can reuse in model calls
    user_prompt_content = Content(
        role="user",
        parts=[
            Part.from_text(prompt),
        ],
    )

    # Send the prompt and instruct the model to generate content using the Tool that you just created
    response = model.generate_content(
        user_prompt_content,
        generation_config=GenerationConfig(temperature=0),
        tools=[weather_tool],
    )
    response_function_call_content = response.candidates[0].content

    # Check the function name that the model responded with, and make an API call to an external system
    if (
        response.candidates[0].content.parts[0].function_call.name
        == "get_current_weather"
    ):
        # Extract the arguments to use in your API call
        location = (
            response.candidates[0].content.parts[0].function_call.args["location"]
        )

        # Here you can use your preferred method to make an API request to fetch the current weather, for example:
        # api_response = requests.post(weather_api_url, data={"location": location})

        # In this example, we'll use synthetic data to simulate a response payload from an external API
        api_response = """{ "location": "Boston, MA", "temperature": 38, "description": "Partly Cloudy",
                        "icon": "partly-cloudy", "humidity": 65, "wind": { "speed": 10, "direction": "NW" } }"""

    # Return the API response to Gemini so it can generate a model response or request another function call
    response = model.generate_content(
        [
            user_prompt_content,  # User prompt
            response_function_call_content,  # Function call response
            Content(
                parts=[
                    Part.from_function_response(
                        name="get_current_weather",
                        response={
                            "content": api_response,  # Return the API response to Gemini
                        },
                    )
                ],
            ),
        ],
        tools=[weather_tool],
    )
    # Get the model summary response
    summary = response.candidates[0].content.parts[0].text

    return summary, response

Node.js

Cet exemple illustre un scénario de texte avec une fonction et une requête.

Node.js

Avant d'essayer cet exemple, suivez les instructions de configuration pour Node.js décrites dans le guide de démarrage rapide de Vertex AI à l'aide des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API Vertex AI Node.js.

Pour vous authentifier auprès de Vertex AI, configurez le service Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.

const {
  VertexAI,
  FunctionDeclarationSchemaType,
} = require('@google-cloud/vertexai');

const functionDeclarations = [
  {
    function_declarations: [
      {
        name: 'get_current_weather',
        description: 'get weather in a given location',
        parameters: {
          type: FunctionDeclarationSchemaType.OBJECT,
          properties: {
            location: {type: FunctionDeclarationSchemaType.STRING},
            unit: {
              type: FunctionDeclarationSchemaType.STRING,
              enum: ['celsius', 'fahrenheit'],
            },
          },
          required: ['location'],
        },
      },
    ],
  },
];

const functionResponseParts = [
  {
    functionResponse: {
      name: 'get_current_weather',
      response: {name: 'get_current_weather', content: {weather: 'super nice'}},
    },
  },
];

/**
 * TODO(developer): Update these variables before running the sample.
 */
async function functionCallingStreamChat(
  projectId = 'PROJECT_ID',
  location = 'us-central1',
  model = 'gemini-1.0-pro'
) {
  // Initialize Vertex with your Cloud project and location
  const vertexAI = new VertexAI({project: projectId, location: location});

  // Instantiate the model
  const generativeModel = vertexAI.preview.getGenerativeModel({
    model: model,
  });

  const request = {
    contents: [
      {role: 'user', parts: [{text: 'What is the weather in Boston?'}]},
      {
        role: 'model',
        parts: [
          {
            functionCall: {
              name: 'get_current_weather',
              args: {location: 'Boston'},
            },
          },
        ],
      },
      {role: 'function', parts: functionResponseParts},
    ],
    tools: functionDeclarations,
  };
  const streamingResp = await generativeModel.generateContentStream(request);
  for await (const item of streamingResp.stream) {
    console.log(item.candidates[0].content.parts[0].text);
  }
}

REST

Cet exemple illustre un scénario textuel avec trois fonctions et une requête.

Dans cet exemple, vous appelez deux fois le modèle d'IA générative.

  • Dans le premier appel, vous fournissez au modèle la requête et les déclarations de la fonction.
  • Dans le deuxième appel, vous transmettez la réponse de l'API au modèle.

Première requête du modèle

La requête doit définir une requête dans le paramètre text. Cet exemple définit la requête suivante : "Quels cinémas à Mountain View diffusent le film Barbie ?".

La requête doit également définir un outil (tools) avec un ensemble de déclarations de fonction (functionDeclarations). Ces déclarations de fonction doivent être spécifiées dans un format compatible avec le schéma OpenAPI. Cet exemple définit les fonctions suivantes :

  • find_movies trouve les titres de films diffusés au cinéma.
  • find_theatres trouve des films en fonction de leur emplacement.
  • get_showtimes recherche les heures de début des films diffusés dans un cinéma spécifique.

Pour en savoir plus sur les paramètres de la requête de modèle, consultez la page API Gemini.

Remplacez my-project par le nom de votre projet Google Cloud.

Première requête du modèle

PROJECT_ID=my-project
MODEL_ID=gemini-1.0-pro
API=streamGenerateContent
curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "Content-Type: application/json"  https://us-central1-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/${MODEL_ID}:${API} -d '{
"contents": {
  "role": "user",
  "parts": {
    "text": "Which theaters in Mountain View show the Barbie movie?"
  }
},
"tools": [
  {
    "function_declarations": [
      {
        "name": "find_movies",
        "description": "find movie titles currently playing in theaters based on any description, genre, title words, etc.",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
            },
            "description": {
              "type": "string",
              "description": "Any kind of description including category or genre, title words, attributes, etc."
            }
          },
          "required": [
            "description"
          ]
        }
      },
      {
        "name": "find_theaters",
        "description": "find theaters based on location and optionally movie title which are is currently playing in theaters",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
            },
            "movie": {
              "type": "string",
              "description": "Any movie title"
            }
          },
          "required": [
            "location"
          ]
        }
      },
      {
        "name": "get_showtimes",
        "description": "Find the start times for movies playing in a specific theater",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
            },
            "movie": {
              "type": "string",
              "description": "Any movie title"
            },
            "theater": {
              "type": "string",
              "description": "Name of the theater"
            },
            "date": {
              "type": "string",
              "description": "Date for requested showtime"
            }
          },
          "required": [
            "location",
            "movie",
            "theater",
            "date"
          ]
        }
      }
    ]
  }
]
}'
  

Pour l'invite "Quels films à Mountain View diffusent le film Barbie ?", le modèle peut renvoyer la fonction find_theatres avec les paramètres Barbie et Mountain View, CA.

Réponse à la première requête du modèle

[{
"candidates": [
  {
    "content": {
      "parts": [
        {
          "functionCall": {
            "name": "find_theaters",
            "args": {
              "movie": "Barbie",
              "location": "Mountain View, CA"
            }
          }
        }
      ]
    },
    "finishReason": "STOP",
    "safetyRatings": [
      {
        "category": "HARM_CATEGORY_HARASSMENT",
        "probability": "NEGLIGIBLE"
      },
      {
        "category": "HARM_CATEGORY_HATE_SPEECH",
        "probability": "NEGLIGIBLE"
      },
      {
        "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
        "probability": "NEGLIGIBLE"
      },
      {
        "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
        "probability": "NEGLIGIBLE"
      }
    ]
  }
],
"usageMetadata": {
  "promptTokenCount": 9,
  "totalTokenCount": 9
}
}]
  

Deuxième requête du modèle

Cet exemple utilise des données synthétiques au lieu d'appeler l'API externe. Deux résultats s'affichent, chacun avec deux paramètres (name et address) :

  1. name : AMC Mountain View 16, address : 2000 W El Camino Real, Mountain View, CA 94040
  2. name : Regal Edwards 14, address : 245 Castro St, Mountain View, CA 94040

Remplacez my-project par le nom de votre projet Google Cloud.

Deuxième requête du modèle

PROJECT_ID=my-project
MODEL_ID=gemini-1.0-pro
API=streamGenerateContent
curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "Content-Type: application/json"  https://us-central1-autopush-aiplatform.sandbox.googleapis.com/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/${MODEL_ID}:${API} -d '{
"contents": [{
  "role": "user",
  "parts": [{
    "text": "Which theaters in Mountain View show the Barbie movie?"
  }]
}, {
  "role": "model",
  "parts": [{
    "functionCall": {
      "name": "find_theaters",
      "args": {
        "location": "Mountain View, CA",
        "movie": "Barbie"
      }
    }
  }]
}, {
  "parts": [{
    "functionResponse": {
      "name": "find_theaters",
      "response": {
        "name": "find_theaters",
        "content": {
          "movie": "Barbie",
          "theaters": [{
            "name": "AMC Mountain View 16",
            "address": "2000 W El Camino Real, Mountain View, CA 94040"
          }, {
            "name": "Regal Edwards 14",
            "address": "245 Castro St, Mountain View, CA 94040"
          }]
        }
      }
    }
  }]
}],
"tools": [{
  "functionDeclarations": [{
    "name": "find_movies",
    "description": "find movie titles currently playing in theaters based on any description, genre, title words, etc.",
    "parameters": {
      "type": "OBJECT",
      "properties": {
        "location": {
          "type": "STRING",
          "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
        },
        "description": {
          "type": "STRING",
          "description": "Any kind of description including category or genre, title words, attributes, etc."
        }
      },
      "required": ["description"]
    }
  }, {
    "name": "find_theaters",
    "description": "find theaters based on location and optionally movie title which are is currently playing in theaters",
    "parameters": {
      "type": "OBJECT",
      "properties": {
        "location": {
          "type": "STRING",
          "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
        },
        "movie": {
          "type": "STRING",
          "description": "Any movie title"
        }
      },
      "required": ["location"]
    }
  }, {
    "name": "get_showtimes",
    "description": "Find the start times for movies playing in a specific theater",
    "parameters": {
      "type": "OBJECT",
      "properties": {
        "location": {
          "type": "STRING",
          "description": "The city and state, e.g. San Francisco, CA or a zip code e.g. 95616"
        },
        "movie": {
          "type": "STRING",
          "description": "Any movie title"
        },
        "theater": {
          "type": "STRING",
          "description": "Name of the theater"
        },
        "date": {
          "type": "STRING",
          "description": "Date for requested showtime"
        }
      },
      "required": ["location", "movie", "theater", "date"]
    }
  }]
}]
}'
  

La réponse du modèle peut ressembler à ce qui suit :

Réponse à la deuxième requête du modèle

{
"candidates": [
  {
    "content": {
      "parts": [
        {
          "text": " OK. Barbie is showing in two theaters in Mountain View, CA: AMC Mountain View 16 and Regal Edwards 14."
        }
      ]
    }
  }
],
"usageMetadata": {
  "promptTokenCount": 9,
  "candidatesTokenCount": 27,
  "totalTokenCount": 36
}
}
  

Exemples de chat

Python

Cet exemple présente un scénario de chat avec deux fonctions et deux requêtes séquentielles. Il utilise la classe GenerativeModel et ses méthodes. Pour en savoir plus sur l'utilisation du SDK Vertex AI pour Python avec des modèles multimodaux, consultez la page Présentation des classes multimodales dans le SDK Vertex AI pour Python.

Pour savoir comment installer ou mettre à jour Python, consultez la page Installer le SDK Vertex AI pour Python. Pour en savoir plus, consultez la documentation de référence de l'API Python.

import vertexai
from vertexai.generative_models import (
    FunctionDeclaration,
    GenerativeModel,
    Part,
    Tool,
)

def generate_function_call_chat(project_id: str, location: str) -> tuple:
    prompts = []
    summaries = []

    # Initialize Vertex AI
    vertexai.init(project=project_id, location=location)

    # Specify a function declaration and parameters for an API request
    get_product_info_func = FunctionDeclaration(
        name="get_product_sku",
        description="Get the SKU for a product",
        # Function parameters are specified in OpenAPI JSON schema format
        parameters={
            "type": "object",
            "properties": {
                "product_name": {"type": "string", "description": "Product name"}
            },
        },
    )

    # Specify another function declaration and parameters for an API request
    get_store_location_func = FunctionDeclaration(
        name="get_store_location",
        description="Get the location of the closest store",
        # Function parameters are specified in OpenAPI JSON schema format
        parameters={
            "type": "object",
            "properties": {"location": {"type": "string", "description": "Location"}},
        },
    )

    # Define a tool that includes the above functions
    retail_tool = Tool(
        function_declarations=[
            get_product_info_func,
            get_store_location_func,
        ],
    )

    # Initialize Gemini model
    model = GenerativeModel(
        "gemini-1.0-pro", generation_config={"temperature": 0}, tools=[retail_tool]
    )

    # Start a chat session
    chat = model.start_chat()

    # Send a prompt for the first conversation turn that should invoke the get_product_sku function
    prompt = "Do you have the Pixel 8 Pro in stock?"
    response = chat.send_message(prompt)
    prompts.append(prompt)

    # Check the function name that the model responded with, and make an API call to an external system
    if response.candidates[0].content.parts[0].function_call.name == "get_product_sku":
        # Extract the arguments to use in your API call
        product_name = (
            response.candidates[0].content.parts[0].function_call.args["product_name"]
        )
        product_name

        # Here you can use your preferred method to make an API request to retrieve the product SKU, as in:
        # api_response = requests.post(product_api_url, data={"product_name": product_name})

        # In this example, we'll use synthetic data to simulate a response payload from an external API
        api_response = {"sku": "GA04834-US", "in_stock": "yes"}

    # Return the API response to Gemini so it can generate a model response or request another function call
    response = chat.send_message(
        Part.from_function_response(
            name="get_product_sku",
            response={
                "content": api_response,
            },
        ),
    )

    # Extract the text from the summary response
    summary = response.candidates[0].content.parts[0].text
    summaries.append(summary)

    # Send a prompt for the second conversation turn that should invoke the get_store_location function
    prompt = "Is there a store in Mountain View, CA that I can visit to try it out?"
    response = chat.send_message(prompt)
    prompts.append(prompt)

    # Check the function name that the model responded with, and make an API call to an external system
    if (
        response.candidates[0].content.parts[0].function_call.name
        == "get_store_location"
    ):
        # Extract the arguments to use in your API call
        location = (
            response.candidates[0].content.parts[0].function_call.args["location"]
        )
        location

        # Here you can use your preferred method to make an API request to retrieve store location closest to the user, as in:
        # api_response = requests.post(store_api_url, data={"location": location})

        # In this example, we'll use synthetic data to simulate a response payload from an external API
        api_response = {"store": "2000 N Shoreline Blvd, Mountain View, CA 94043, US"}

    # Return the API response to Gemini so it can generate a model response or request another function call
    response = chat.send_message(
        Part.from_function_response(
            name="get_store_location",
            response={
                "content": api_response,
            },
        ),
    )

    # Extract the text from the summary response
    summary = response.candidates[0].content.parts[0].text
    summaries.append(summary)

    return prompts, summaries

Node.js

Avant d'essayer cet exemple, suivez les instructions de configuration pour Node.js décrites dans le guide de démarrage rapide de Vertex AI à l'aide des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API Vertex AI Node.js.

Pour vous authentifier auprès de Vertex AI, configurez le service Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.

const {
  VertexAI,
  FunctionDeclarationSchemaType,
} = require('@google-cloud/vertexai');

const functionDeclarations = [
  {
    function_declarations: [
      {
        name: 'get_current_weather',
        description: 'get weather in a given location',
        parameters: {
          type: FunctionDeclarationSchemaType.OBJECT,
          properties: {
            location: {type: FunctionDeclarationSchemaType.STRING},
            unit: {
              type: FunctionDeclarationSchemaType.STRING,
              enum: ['celsius', 'fahrenheit'],
            },
          },
          required: ['location'],
        },
      },
    ],
  },
];

const functionResponseParts = [
  {
    functionResponse: {
      name: 'get_current_weather',
      response: {name: 'get_current_weather', content: {weather: 'super nice'}},
    },
  },
];

/**
 * TODO(developer): Update these variables before running the sample.
 */
async function functionCallingStreamChat(
  projectId = 'PROJECT_ID',
  location = 'us-central1',
  model = 'gemini-1.0-pro'
) {
  // Initialize Vertex with your Cloud project and location
  const vertexAI = new VertexAI({project: projectId, location: location});

  // Instantiate the model
  const generativeModel = vertexAI.preview.getGenerativeModel({
    model: model,
  });

  // Create a chat session and pass your function declarations
  const chat = generativeModel.startChat({
    tools: functionDeclarations,
  });

  const chatInput1 = 'What is the weather in Boston?';

  // This should include a functionCall response from the model
  const result1 = await chat.sendMessageStream(chatInput1);
  for await (const item of result1.stream) {
    console.log(item.candidates[0]);
  }
  await result1.response;

  // Send a follow up message with a FunctionResponse
  const result2 = await chat.sendMessageStream(functionResponseParts);
  for await (const item of result2.stream) {
    console.log(item.candidates[0]);
  }

  // This should include a text response from the model using the response content
  // provided above
  const response2 = await result2.response;
  console.log(response2.candidates[0].content.parts[0].text);
}

Java

Avant d'essayer cet exemple, suivez les instructions de configuration pour Java décrites dans le guide de démarrage rapide de Vertex AI à l'aide des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API Vertex AI Java.

Pour vous authentifier auprès de Vertex AI, configurez le service Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.

import com.google.cloud.vertexai.VertexAI;
import com.google.cloud.vertexai.api.Content;
import com.google.cloud.vertexai.api.FunctionDeclaration;
import com.google.cloud.vertexai.api.GenerateContentResponse;
import com.google.cloud.vertexai.api.Schema;
import com.google.cloud.vertexai.api.Tool;
import com.google.cloud.vertexai.api.Type;
import com.google.cloud.vertexai.generativeai.ChatSession;
import com.google.cloud.vertexai.generativeai.ContentMaker;
import com.google.cloud.vertexai.generativeai.GenerativeModel;
import com.google.cloud.vertexai.generativeai.PartMaker;
import com.google.cloud.vertexai.generativeai.ResponseHandler;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;

public class FunctionCalling {
  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-google-cloud-project-id";
    String location = "us-central1";
    String modelName = "gemini-1.0-pro";

    String promptText = "What's the weather like in Paris?";

    whatsTheWeatherLike(projectId, location, modelName, promptText);
  }

  public static String whatsTheWeatherLike(String projectId, String location,
                                           String modelName, String promptText)
      throws IOException {

    try (VertexAI vertexAI = new VertexAI(projectId, location)) {

      FunctionDeclaration functionDeclaration = FunctionDeclaration.newBuilder()
          .setName("getCurrentWeather")
          .setDescription("Get the current weather in a given location")
          .setParameters(
              Schema.newBuilder()
                  .setType(Type.OBJECT)
                  .putProperties("location", Schema.newBuilder()
                      .setType(Type.STRING)
                      .setDescription("location")
                      .build()
                  )
                  .addRequired("location")
                  .build()
          )
          .build();

      System.out.println("Function declaration:");
      System.out.println(functionDeclaration);

      // Add the function to a "tool"
      Tool tool = Tool.newBuilder()
          .addFunctionDeclarations(functionDeclaration)
          .build();

      // Start a chat session from a model, with the use of the declared function.
      GenerativeModel model =
          GenerativeModel.newBuilder()
              .setModelName(modelName)
              .setVertexAi(vertexAI)
              .setTools(Arrays.asList(tool))
              .build();
      ChatSession chat = model.startChat();

      System.out.println(String.format("Ask the question: %s", promptText));
      GenerateContentResponse response = chat.sendMessage(promptText);

      // The model will most likely return a function call to the declared
      // function `getCurrentWeather` with "Paris" as the value for the
      // argument `location`.
      System.out.println("\nPrint response: ");
      System.out.println(ResponseHandler.getContent(response));

      // Provide an answer to the model so that it knows what the result
      // of a "function call" is.
      Content content =
          ContentMaker.fromMultiModalData(
              PartMaker.fromFunctionResponse(
                  "getCurrentWeather",
                  Collections.singletonMap("currentWeather", "sunny")));
      System.out.println("Provide the function response: ");
      System.out.println(content);
      response = chat.sendMessage(content);

      // See what the model replies now
      System.out.println("Print response: ");
      String finalAnswer = ResponseHandler.getText(response);
      System.out.println(finalAnswer);

      return finalAnswer;
    }
  }
}

Go

Avant d'essayer cet exemple, suivez les instructions de configuration pour Go décrites dans le guide de démarrage rapide de Vertex AI à l'aide des bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API Vertex AI Go.

Pour vous authentifier auprès de Vertex AI, configurez le service Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"

	"cloud.google.com/go/vertexai/genai"
)

// functionCalls opens a chat session and sends 2 messages to the model:
// - first, to convert a text into a structured function call request
// - second, to convert a structured function call response into natural language
func functionCalls(w io.Writer, prompt, projectID, location, modelName string) error {
	// prompt := "What's the weather like in Paris?"
	// location := "us-central1"
	// modelName := "gemini-1.0-pro"
	ctx := context.Background()
	client, err := genai.NewClient(ctx, projectID, location)
	if err != nil {
		return fmt.Errorf("unable to create client: %v", err)
	}
	defer client.Close()

	model := client.GenerativeModel(modelName)

	// Build an OpenAPI schema, in memory
	params := &genai.Schema{
		Type: genai.TypeObject,
		Properties: map[string]*genai.Schema{
			"location": {
				Type:        genai.TypeString,
				Description: "location",
			},
		},
	}
	fundecl := &genai.FunctionDeclaration{
		Name:        "getCurrentWeather",
		Description: "Get the current weather in a given location",
		Parameters:  params,
	}
	model.Tools = []*genai.Tool{
		{FunctionDeclarations: []*genai.FunctionDeclaration{fundecl}},
	}

	chat := model.StartChat()

	fmt.Fprintf(w, "Question: %s\n", prompt)
	resp, err := chat.SendMessage(ctx, genai.Text(prompt))
	if err != nil {
		return err
	}
	if len(resp.Candidates) == 0 ||
		len(resp.Candidates[0].Content.Parts) == 0 {
		return errors.New("empty response from model")
	}

	// The model has returned a function call to the declared function `getCurrentWeather`
	// with a value for the argument `location`.
	jsondata, err := json.MarshalIndent(resp.Candidates[0].Content.Parts[0], "", "  ")
	if err != nil {
		return fmt.Errorf("json.Marshal: %w", err)
	}
	fmt.Fprintf(w, "function call generated by the model:\n%s\n\n", string(jsondata))

	// Create a function call response, to simulate the result of a call to a
	// real service
	funresp := &genai.FunctionResponse{
		Name: "getCurrentWeather",
		Response: map[string]any{
			"currentWeather": "sunny",
		},
	}
	jsondata, err = json.MarshalIndent(funresp, "", "  ")
	if err != nil {
		return fmt.Errorf("json.Marshal: %w", err)
	}
	fmt.Fprintf(w, "function call response sent to the model:\n%s\n\n", string(jsondata))

	// And provide the function call response to the model
	resp, err = chat.SendMessage(ctx, funresp)
	if err != nil {
		return err
	}
	if len(resp.Candidates) == 0 ||
		len(resp.Candidates[0].Content.Parts) == 0 {
		return errors.New("empty response from model")
	}

	// The model has taken the function call response as input, and has
	// reformulated the response to the user.
	jsondata, err = json.MarshalIndent(resp.Candidates[0].Content.Parts[0], "", "  ")
	if err != nil {
		return fmt.Errorf("json.Marshal: %w", err)
	}
	fmt.Fprintf(w, "Answer generated by the model:\n%s\n", string(jsondata))

	return nil
}