Llamada a función

Descripción general

Puedes usar las llamadas a función para definir funciones personalizadas y proporcionarlas a un modelo de IA generativa. Mientras se procesa una consulta, el modelo puede elegir delegar ciertas tareas de procesamiento de datos a estas funciones. No llama a las funciones. En su lugar, proporciona un resultado de datos estructurados que incluye el nombre de una función seleccionada y los argumentos con los que el modelo propone que se llame a la función. Puedes usar este resultado para invocar APIs externas. Luego, puedes proporcionar el resultado de la API al modelo, lo que le permite completar su respuesta a la consulta. Cuando se usa de esta manera, la llamada a función permite que los LLM accedan a información en tiempo real y, además, interactúen con varios servicios, como bases de datos de SQL, sistemas de administración de relaciones con clientes y repositorios de documentos.

En el siguiente diagrama, se muestra cómo funciona la llamada a función: Interacción de llamada a función 

Para obtener información sobre los casos de uso de la llamada a función, consulta Casos de uso de la llamada a función. Para aprender a crear una aplicación que llama a función, consulta Crea una aplicación que llama a función. Para conocer las prácticas recomendadas, consulta las Prácticas recomendadas.

La llamada a función es una característica del modelo gemini-1.0-pro-001 y una función de vista previa del modelo gemini-1.0-pro-002.

Las llamadas a función son una característica del modelo Gemini 1.5 Pro (vista previa).

Casos de uso de llamada a función

Puedes usar la llamada a función para las siguientes tareas:

Crea una aplicación que llama a función

Para permitir que un usuario interactúe con el modelo y use la llamada a función, debes crear un código que realice las siguientes tareas:

Puedes crear una aplicación que administre todas estas tareas. Esta aplicación puede ser un chatbot de texto, un agente de voz, un flujo de trabajo automatizado o cualquier otro programa.

Define y describe un conjunto de funciones disponibles

La aplicación debe declarar un conjunto de funciones que el modelo pueda usar para procesar la consulta. Cada declaración de función debe incluir un nombre de función y parámetros de función. Te recomendamos que también incluyas una descripción de función en cada declaración de función.

Nombre de la función

La aplicación y el modelo usan el nombre de la función para identificarla.

Para obtener prácticas recomendadas relacionadas con el nombre de la función, consulta Prácticas recomendadas: Nombre de función.

Parámetros de las funciones

Los parámetros de la función deben proporcionarse en un formato que sea compatible con el esquema de OpenAPI.

Vertex AI ofrece asistencia limitada del esquema de OpenAPI. Los siguientes atributos son compatibles: type, nullable, required, format, description, properties, items, enum. Los siguientes atributos no son compatibles: default, optional, maximum, oneOf.

Cuando uses curl, especifica el esquema mediante JSON. Cuando uses el SDK de Vertex AI para Python, especifica el esquema con un diccionario de Python.

Para conocer las prácticas recomendadas relacionadas con los parámetros de funciones, consulta Prácticas recomendadas: Parámetros de funciones.

Descripción de función

El modelo usa descripciones de funciones para comprender el propósito de las funciones y determinar si estas son útiles en el procesamiento de consultas de los usuarios.

Para obtener prácticas recomendadas relacionadas con la descripción de la función, consulta Prácticas recomendadas: Descripción de funciones.

Ejemplo de una declaración de función

A continuación, se muestra un ejemplo de una declaración de función 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."}},
    },
)

El siguiente es un ejemplo de una declaración de función con un array de elementos:

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"],
   },
)

Envía la consulta y las declaraciones de la función al modelo

Cuando el usuario proporciona un mensaje, la aplicación debe proporcionar al modelo la instrucción del usuario y las declaraciones de la función. Para configurar cómo el modelo genera resultados, la aplicación puede proporcionarle una configuración de generación. Para configurar cómo el modelo usa las declaraciones de funciones, la aplicación puede proporcionarle al modelo una configuración de herramienta.

Instrucción del usuario

El siguiente es un ejemplo de una instrucción de usuario: "¿Cómo está el clima en Boston?".

Para obtener prácticas recomendadas relacionadas con el mensaje del usuario, consulta Prácticas recomendadas: Instrucción del usuario.

Configuración de generación

El modelo puede generar resultados diferentes para los valores de parámetros diferentes. El parámetro de temperatura controla el grado de aleatorización en esta generación. Las temperaturas más bajas son buenas para las funciones que requieren valores de parámetros determinística, mientras que las temperaturas más altas son buenas para las funciones con parámetros que aceptan valores de parámetros más diversos o creativos. Una temperatura de 0 es determinística, lo que significa que siempre se elige la respuesta de mayor probabilidad. Para obtener más información, consulta API de Gemini.

Para establecer este parámetro, envía una configuración de generación (generation_config) junto con la instrucción y las declaraciones de la función.

Para obtener prácticas recomendadas relacionadas con la configuración de la generación, consulta Prácticas recomendadas: Configuración de la generación.

Configuración de herramientas

Puedes colocar algunas restricciones sobre cómo el modelo debe usar las declaraciones de funciones que le proporcionas. Por ejemplo, en lugar de permitir que el modelo elija entre una respuesta de lenguaje natural y una llamada a función, puedes forzarlo para que prediga solo las llamadas a función. También puedes optar por proporcionar al modelo un conjunto completo de declaraciones de funciones, pero restringir sus respuestas a un subconjunto de ellas.

Para colocar estas restricciones, envía una configuración de herramienta (tool_config) junto con la instrucción y las declaraciones de funciones. En la configuración, puedes especificar uno de los siguientes modos:

Moda Descripción
AUTOMÁTICO El comportamiento predeterminado del modelo. El modelo decide si predecir una llamada a función o una respuesta de lenguaje natural.
CUALQUIERA El modelo solo debe predecir las llamadas a funciones. Para limitar el modelo a un subconjunto de funciones, define los nombres de las funciones permitidas en allowed_function_names.
NINGUNO El modelo no debe predecir llamadas a funciones. Este comportamiento es equivalente a una solicitud de modelo sin ninguna declaración de función asociada.

El modo ANY de la configuración de la herramienta es una función de vista previa. Solo es compatible con los modelos Gemini 1.5 Pro.

Para obtener más información, consulta API de llamada a funciones.

Cómo enviar la instrucción y las declaraciones de funciones

El siguiente es un ejemplo de cómo puedes enviar la consulta y las declaraciones de función al modelo, y restringir el modelo para que prediga solo las llamadas a función 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 el modelo determina que necesita el resultado de una función en particular, la respuesta que recibe la aplicación del modelo contiene el nombre de la función y los valores de los parámetros con los que se debe llamar a la función.

El siguiente es un ejemplo de una respuesta del modelo. El modelo propone llamar a la función get_current_weather con el parámetro Boston, MA.

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

Invoca una API externa

Si la aplicación recibe un nombre de función y valores de parámetros del modelo, la aplicación debe conectarse a una API externa y llamar a la función.

En el siguiente ejemplo, se usan datos sintéticos para simular una carga útil de respuesta desde una API externa:

# 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" } }"""

Para conocer las prácticas recomendadas relacionadas con la invocación de APIs, consulta Prácticas recomendadas: Invocación de APIs.

Proporcionar la salida de la API al modelo

Después de que una aplicación recibe una respuesta de una API externa, debe proporcionar esta respuesta al modelo. A continuación, se muestra un ejemplo de cómo puedes hacerlo con 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 el modelo determina que la respuesta de la API es suficiente para responder la consulta del usuario, crea una respuesta de lenguaje natural y la muestra a la aplicación. En este caso, la aplicación debe pasar la respuesta al usuario. A continuación, se muestra un ejemplo de una respuesta de consulta: 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 el modelo determina que el resultado de otra función es necesario para responder la consulta, la respuesta que la aplicación recibe del modelo contendrá otro nombre de función y otro conjunto de valores del parámetro.

prácticas recomendadas

Nombre de la función

No uses caracteres de punto (.), guiones (-) ni espacios en el nombre de la función. En su lugar, usa caracteres de guion bajo (_) o cualquier otro carácter.

Parámetros de las funciones

Escribe descripciones de parámetros claras y detalladas, incluidos detalles como tu formato o valores preferidos. Por ejemplo, para una función book_flight_ticket, usa lo siguiente:

  • El siguiente es un buen ejemplo de la descripción de un parámetro departure: Use the 3 char airport code to represent the airport. For example, SJC or SFO. Don't use the city name.
  • El siguiente es un mal ejemplo de la descripción de un parámetro departure: the departure airport

Si es posible, usa parámetros de tipado fuerte para reducir las alucinaciones del modelo. Por ejemplo, si los valores de los parámetros son de un conjunto finito, agrega un campo enum en lugar de colocar el conjunto de valores en la descripción. Si el valor del parámetro es siempre un número entero, establece el tipo en integer en lugar de number.

Descripción de función

Escribe descripciones de funciones de forma clara y detallada. Por ejemplo, para una función book_flight_ticket, usa lo siguiente:

  • A continuación, se muestra un ejemplo de una buena descripción de función: book flight tickets after confirming users' specific requirements, such as time, departure, destination, party size and preferred airline
  • A continuación, se muestra un ejemplo de la descripción de una función incorrecta: book flight ticket

Instrucción del usuario

Para obtener mejores resultados, antepone los siguientes detalles a la consulta del usuario:

  • Contexto adicional para el modelo, por ejemplo, You are a flight API assistant to help with searching flights based on user preferences.
  • Detalles o instrucciones sobre cómo y cuándo usar las funciones; por ejemplo, Don't make assumptions on the departure or destination airports. Always use a future date for the departure or destination time.
  • Instrucciones para hacer preguntas aclaratorias si las búsquedas de los usuarios son ambiguas, por ejemplo, Ask clarifying questions if not enough information is available.

Configuración de generación

Para el parámetro de temperatura, usa 0 o algún otro valor bajo. Esto le indica al modelo que genere resultados más seguros y reduzca las alucinaciones.

Invocación a la API

Si el modelo propone la invocación de una función que enviaría un pedido, actualizaría una base de datos o tendría consecuencias significativas, valida la llamada a función con el usuario antes de ejecutarla.

Precios

El precio de la llamada a función se basa en la cantidad de caracteres dentro de las entradas y salidas de texto. Para obtener más información, consulta Certificaciones de Vertex AI.

Aquí, la entrada de texto (instrucción) se refiere a la consulta del usuario para el turno de conversación actual, las declaraciones de función para el turno de conversación actual y el historial de la conversación. El historial de la conversación incluye las consultas, las llamadas a función y las respuestas de función de turnos de conversación anteriores. Vertex AI trunca el historial de la conversación en 32,000 caracteres.

El resultado de texto (respuesta) se refiere a las llamadas a función y las respuestas de texto para el turno de la conversación actual.

Muestras de llamadas a función

Puedes usar la llamada a función para generar una sola respuesta de texto o admitir una sesión de chat. Las respuestas de texto ad hoc son útiles para tareas empresariales específicas, como la generación de código. Las sesiones de chat son útiles en situaciones de conversación de formato libre, en las que es probable que el usuario haga preguntas de seguimiento.

Si usas la llamada a función para generar una sola respuesta, debes proporcionar al modelo el contexto completo de la interacción. Por otro lado, si usas la llamada a función en el contexto de una sesión de chat, la sesión almacenará el contexto por ti y lo incluirá en cada solicitud de modelo. En ambos casos, Vertex AI almacena el historial de la interacción en el lado del cliente.

Si quieres aprender a usar la llamada a función para generar una sola respuesta de texto, consulta los ejemplos de texto. Si quieres aprender a usar las llamadas a funciones para asistir en una sesión de chat, consulta los ejemplos de chat.

Ejemplos de texto

Python

En este ejemplo, se muestra una situación de texto con una función y una instrucción. Usa la clase GenerativeModel y sus métodos. Si deseas obtener más información sobre el uso del SDK de Vertex AI para Python con modelos multimodales de Gemini, consulta Introducción a las clases multimodales en el SDK de Vertex AI para Python.

Python

Si deseas obtener información para instalar o actualizar el SDK de Python, consulta Instala el SDK de Vertex AI para Python. Si deseas obtener más información, consulta la documentación de referencia de la API de 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

En este ejemplo, se muestra una situación de texto con una función y una instrucción.

Node.js

Antes de probar este ejemplo, sigue las instrucciones de configuración para Node.js incluidas en la guía de inicio rápido de Vertex AI sobre cómo usar bibliotecas cliente. Para obtener más información, consulta la documentación de referencia de la API de Vertex AI Node.js.

Para autenticarte en Vertex AI, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo 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

En este ejemplo, se muestra una situación de texto con tres funciones y una instrucción.

En este ejemplo, debes llamar al modelo de IA generativa dos veces.

  • En la primera llamada, debes proporcionar al modelo el mensaje y las declaraciones de la función.
  • En la segunda llamada, debes proporcionar al modelo la respuesta de la API.

Primera solicitud del modelo

La solicitud debe definir una consulta en el parámetro text. En este ejemplo, se define la siguiente consulta: “¿Qué cines de Mountain View muestran la película Barbie?”.

La solicitud también debe definir una herramienta (tools) con un conjunto de declaraciones de función (functionDeclarations). Estas declaraciones de funciones deben especificarse en un formato que sea compatible con el esquema de OpenAPI. En este ejemplo, se definen las siguientes funciones:

  • find_movies encuentra títulos de películas que se proyectan en cines.
  • find_theatres encuentra cines en función de la ubicación.
  • get_showtimes busca las horas de inicio de las películas que se proyectan en un cine específico.

Para obtener más información sobre los parámetros de la solicitud de modelo, consulta la API de Gemini.

Reemplaza my-project por el nombre del proyecto de Google Cloud.

Primera solicitud del modelo

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"
          ]
        }
      }
    ]
  }
]
}'
  

Para el mensaje “¿Qué cines de Mountain View muestran la película de Barbie?”, el modelo podría mostrar la función find_theatres con los parámetros Barbie y Mountain View, CA.

Respuesta a la primera solicitud de modelo

[{
"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
}
}]
  

Segunda solicitud de modelo

En este ejemplo, se usan datos sintéticos en lugar de llamar a la API externa. Hay dos resultados, cada uno con dos parámetros (name y 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

Reemplaza my-project por el nombre del proyecto de Google Cloud.

Segunda solicitud de modelo

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 respuesta del modelo podría ser similar a la siguiente:

Respuesta a la segunda solicitud de modelo

{
"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
}
}
  

Ejemplos de chat

Python

En este ejemplo, se muestra una situación de chat con dos funciones y dos prompts secuenciales. Usa la clase GenerativeModel y sus métodos. Si deseas obtener más información sobre el uso del SDK de Vertex AI para Python con modelos multimodales, consulta Introducción a las clases multimodales en el SDK de Vertex AI para Python.

Si deseas obtener información para instalar o actualizar Python, consulta Instala el SDK de Vertex AI para Python. Si deseas obtener más información, consulta la documentación de referencia de la API de 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

Antes de probar este ejemplo, sigue las instrucciones de configuración para Node.js incluidas en la guía de inicio rápido de Vertex AI sobre cómo usar bibliotecas cliente. Para obtener más información, consulta la documentación de referencia de la API de Vertex AI Node.js.

Para autenticarte en Vertex AI, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo 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

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java incluidas en la guía de inicio rápido de Vertex AI sobre cómo usar bibliotecas cliente. Para obtener más información, consulta la documentación de referencia de la API de Vertex AI Java.

Para autenticarte en Vertex AI, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo 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

Antes de probar este ejemplo, sigue las instrucciones de configuración para Go incluidas en la guía de inicio rápido de Vertex AI sobre cómo usar bibliotecas cliente. Para obtener más información, consulta la documentación de referencia de la API de Vertex AI Go.

Para autenticarte en Vertex AI, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo 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
}