Chamadas de função

Visão geral

É possível usar a chamada de função para definir funções personalizadas e fornecê-las a um modelo de IA generativa. Ao processar uma consulta, o modelo pode delegar determinadas tarefas de processamento de dados a essas funções. Ele não chama as funções. Em vez disso, ele fornece uma saída de dados estruturados que inclui o nome de uma função selecionada e os argumentos com os quais o modelo propõe a chamada a ser usada. É possível usar essa saída para invocar APIs externas. É possível então fornecer a saída da API de volta ao modelo, permitindo que ele conclua a resposta à consulta. Quando usada dessa maneira, a chamada de função permite que os LLMs acessem informações em tempo real e interajam com vários serviços, como bancos de dados SQL, sistemas de gestão de relacionamento com o cliente e repositórios de documentos.

O diagrama a seguir ilustra como funciona a chamada de função: Interação de chamada de função 

Para saber mais sobre os casos de uso de chamada de função, consulte Casos de uso de chamada de função. Para saber como criar um aplicativo de chamada de função, consulte este link. Para conferir as práticas recomendadas, consulte Práticas recomendadas.

A chamada de função é um recurso do modelo gemini-1.0-pro-001 e um recurso de prévia do modelo gemini-1.0-pro-002.

Chamar funções é um recurso do modelo Gemini 1.5 Pro (pré-lançamento).

Casos de uso de chamada de funções

É possível usar a chamada de função para as seguintes tarefas:

Criar um aplicativo de chamada de função

Para permitir que um usuário interaja com o modelo e use a chamada de função, crie um código que execute as seguintes tarefas:

Crie um aplicativo que gerencie todas essas tarefas. Pode ser um chatbot de texto, um agente de voz, um fluxo de trabalho automatizado ou qualquer outro programa.

Definir e descrever um conjunto de funções disponíveis

O aplicativo precisa declarar um conjunto de funções que o modelo pode usar para processar a consulta. Cada declaração de função precisa incluir o nome da função e os parâmetros da função. É altamente recomendável incluir também a descrição da função em cada declaração de função.

Nome da função

O aplicativo e o modelo usam o nome da função para identificá-la.

Para conferir as práticas recomendadas relacionadas ao nome da função, consulte Práticas recomendadas: nome da função.

Parâmetros de função

Os parâmetros de função precisam ser fornecidos em um formato compatível com o esquema da OpenAPI.

A Vertex AI oferece suporte limitado ao esquema da OpenAPI. São aceitos os seguintes atributos: type, nullable, required, format, description, properties, items, enum. Não são aceitos os seguintes atributos: default, optional, maximum, oneOf.

Ao usar o curl, especifique o esquema usando JSON. Ao usar o SDK da Vertex AI para Python, especifique o esquema usando um dicionário Python.

Para práticas recomendadas relacionadas a parâmetros de função, consulte Práticas recomendadas: parâmetros de função.

Descrição da função

O modelo usa descrições de funções para entender a finalidade das funções e determinar se elas são úteis no processamento de consultas do usuário.

Para as práticas recomendadas relacionadas à descrição da função, consulte Práticas recomendadas: descrição da função.

Exemplo de uma declaração de função

Veja a seguir um exemplo de declaração de função simples em 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."}},
    },
)

Este é um exemplo de declaração de função com uma matriz de itens:

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

Enviar a consulta e as declarações de função ao modelo

Quando o usuário fornece um comando, o aplicativo precisa fornecer ao modelo o prompt do usuário e as declarações da função. Para configurar como o modelo gera resultados, o aplicativo pode fornecer ao modelo uma configuração de geração. Para configurar como o modelo usa as declarações de função, o aplicativo pode fornecer ao modelo uma configuração de ferramenta.

Comando do usuário

Este é um exemplo de comando do usuário: "Como está o clima em Boston?"

Para conferir as práticas recomendadas relacionadas à solicitação do usuário, consulte Práticas recomendadas: prompt do usuário.

Configuração de geração

O modelo pode gerar diferentes resultados para diferentes valores de parâmetros. O parâmetro de temperatura controla o grau de aleatoriedade nesta geração. Temperaturas mais baixas são boas para funções que exigem valores de parâmetro determinísticos, enquanto temperaturas mais altas são boas para funções com parâmetros que aceitam valores de parâmetros mais diversos ou criativos. Uma temperatura 0 é determinista, o que significa que a resposta de maior probabilidade é sempre selecionada. Para saber mais, consulte API Genmini.

Para definir esse parâmetro, envie uma configuração de geração (generation_config) com o prompt e as declarações da função.

Para as práticas recomendadas relacionadas à configuração de geração, consulte Práticas recomendadas: configuração de geração.

Configuração da ferramenta

É possível impor algumas restrições sobre como o modelo precisa usar as declarações de função que você fornece. Por exemplo, em vez de permitir que o modelo escolha entre uma resposta de linguagem natural e uma chamada de função, é possível forçá-lo a prever apenas chamadas de função. Também é possível fornecer ao modelo um conjunto completo de declarações de função, mas restringir as respostas a um subconjunto dessas funções.

Para colocar essas restrições, envie uma configuração de ferramenta (tool_config) com o comando e as declarações da função. Na configuração, é possível especificar um dos seguintes modos:

Modo Descrição
AUTOMÁTICO O comportamento padrão do modelo. O modelo decide se quer prever uma chamada de função ou uma resposta de linguagem natural.
QUALQUER UMA O modelo precisa prever apenas chamadas de função. Para limitar o modelo a um subconjunto de funções, defina os nomes das funções permitidas em allowed_function_names.
NENHUM O modelo não deve prever chamadas de função. Esse comportamento é equivalente a uma solicitação de modelo sem declarações de função associadas.

O modo ANY da configuração da ferramenta é um recurso de Prévia. Ela é compatível apenas com modelos de Gemini 1.5 Pro.

Para saber mais, consulte API de chamada de função.

Como enviar o comando e as declarações de função

Veja a seguir um exemplo de como enviar a consulta e as declarações de função ao modelo e restringir o modelo para prever apenas chamadas de função get_current_weather.

# Initialize Vertex AI
from vertexai.preview.generative_models import ToolConfig

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

Se o modelo determinar que precisa da saída de uma função específica, a resposta que o aplicativo recebe do modelo conterá o nome da função e os valores de parâmetro com os quais a função precisa ser chamada.

Confira a seguir um exemplo de resposta de modelo. O modelo propõe chamar a função get_current_weather com o parâmetro Boston, MA.

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

Invocar uma API externa

Se o aplicativo receber o nome da função e os valores de parâmetro do modelo, ele precisará se conectar a uma API externa e chamar a função.

O exemplo a seguir usa dados sintéticos para simular um payload de resposta de uma 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 conferir as práticas recomendadas relacionadas à invocação de API, consulte Práticas recomendadas: invocação de API.

Fornecer a saída da função ao modelo

Depois que um aplicativo recebe uma resposta de uma API externa, ele precisa fornecer essa resposta ao modelo. Veja a seguir um exemplo de como fazer isso usando 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

Se o modelo determinar que a resposta da API é suficiente para responder à consulta do usuário, ele criará uma resposta com linguagem natural e a retornará para o aplicativo. Nesse caso, o aplicativo precisa transmitir a resposta de volta ao usuário. Veja a seguir um exemplo de resposta 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.

Se o modelo determinar que a saída de outra função é necessária para responder à consulta, a resposta recebida do aplicativo pelo modelo conterá outro nome da função e outro conjunto de valores de parâmetro.

Práticas recomendadas

Nome da função

Não use caracteres de ponto (.), traço (-) ou espaço no nome da função. Em vez disso, use o caractere de sublinhado (_) ou qualquer outro caractere.

Parâmetros de função

Escreva descrições claras e detalhadas dos parâmetros, incluindo detalhes como formato ou valores preferidos. Por exemplo, para uma função book_flight_ticket:

  • Veja a seguir um exemplo bom de uma descrição de parâmetro departure: Use the 3 char airport code to represent the airport. For example, SJC or SFO. Don't use the city name.
  • Veja a seguir um exemplo ruim de uma descrição de parâmetro departure: the departure airport

Se possível, use parâmetros fortemente tipados para reduzir as alucinações do modelo. Por exemplo, se os valores de parâmetro forem de um conjunto finito, adicione um campo enum em vez de colocar o conjunto de valores na descrição. Se o valor do parâmetro for sempre um número inteiro, defina o tipo como integer em vez de number.

Descrição da função

Escreva as descrições das funções de maneira clara e detalhada. Por exemplo, para uma função book_flight_ticket:

  • Veja a seguir um exemplo de uma descrição boa da função: book flight tickets after confirming users' specific requirements, such as time, departure, destination, party size and preferred airline
  • Veja a seguir um exemplo de uma descrição ruim da função: book flight ticket

Comando do usuário

Para melhores resultados, inclua os seguintes detalhes antes da consulta do usuário:

  • Contexto adicional para o modelo, por exemplo, You are a flight API assistant to help with searching flights based on user preferences..
  • Detalhes ou instruções sobre como e quando usar as funções, por exemplo, Don't make assumptions on the departure or destination airports. Always use a future date for the departure or destination time.
  • Instruções para fazer perguntas esclarecedoras se as consultas do usuário forem ambíguas, por exemplo, Ask clarifying questions if not enough information is available.

Configuração de geração

Para o parâmetro de temperatura, use 0 ou outro valor baixo. Isso instrui o modelo a gerar resultados mais confiáveis e reduz alucinações.

Invocação da API

Se o modelo propor a invocação de uma função que envia uma ordem, atualiza um banco de dados ou tem consequências significativas, valide a chamada de função com o usuário antes de executá-la.

Preços

Os preços da chamada de funções são baseados no número de caracteres nas entradas e saídas de texto. Para saber mais, consulte os preços da Vertex AI.

Aqui, a entrada de texto (comando) se refere à consulta do usuário sobre o turno da conversa atual, as declarações de função para o turno da conversa atual e o histórico da conversa. O histórico da conversa inclui as consultas, as chamadas de função e as respostas de função das interações anteriores. A Vertex AI trunca o histórico da conversa em 32.000 caracteres.

Saída de texto (resposta) refere-se às chamadas de função e às respostas de texto da rodada de conversa atual.

Amostras de chamada de função

É possível usar a chamada de função para gerar uma única resposta de texto ou para permitir uma sessão de chat. As respostas de texto ad hoc são úteis para tarefas específicas de negócio, incluindo a geração de código. As sessões de chat são úteis em cenários de conversa com formato livre, em que um usuário provavelmente fará perguntas complementares.

Se você usar a chamada de função para gerar uma única resposta, forneça ao modelo o contexto completo da interação. Por outro lado, se você usar a chamada da função no contexto de uma sessão de chat, ela armazenará o contexto por você e o incluirá em todas as solicitações do modelo. Em ambos os casos, a Vertex AI armazenará o histórico da interação no lado do cliente.

Para aprender a usar chamadas de função para gerar uma única resposta de texto, consulte exemplos de texto. Para saber como usar a chamada de função para permitir uma sessão de chat, consulte exemplos de chat.

Exemplos de texto

Python

Este exemplo demonstra um cenário de texto com uma só função e um só comando. Ele usa a classe GenerativeModel e os respectivos métodos. Para mais informações sobre como usar o SDK da Vertex AI para Python com os modelos multimodais do Gemini, consulte Introdução às classes multimodais no SDK da Vertex AI para Python.

Python

Para saber como instalar o SDK da Vertex AI para Python, consulte Instalar o SDK da Vertex AI para Python. Para mais informações, consulte a documentação de referência da 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(model_name="gemini-1.0-pro-001")

    # 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

Este exemplo demonstra um cenário de texto com uma só função e um só comando.

Node.js

Antes de testar essa amostra, siga as instruções de configuração para Node.js Guia de início rápido da Vertex AI: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Vertex AI para Node.js.

Para autenticar na Vertex AI, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento 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: 'user', 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

Este exemplo demonstra um cenário de texto com três funções e um só comando.

Neste exemplo, você chama o modelo de IA generativa duas vezes.

Primeira solicitação de modelo

A solicitação precisa definir uma consulta no parâmetro text. Esse exemplo define a seguinte consulta: "Quais cinemas em Mountain View exibem o filme da Barbie?".

A solicitação também precisa definir uma ferramenta (tools) com um conjunto de declarações de função (functionDeclarations). Essas declarações de função precisam ser especificadas em um formato compatível com o esquema da OpenAPI. Este exemplo define as seguintes funções:

  • find_movies encontra títulos de filmes em exibição nos cinemas.
  • find_theatres encontra cinemas com base na localização.
  • get_showtimes encontra os horários de início dos filmes em exibição em um cinema específico.

Para saber mais sobre os parâmetros da solicitação de modelo, consulte a API Gemini.

Substitua my-project pelo nome do projeto do Google Cloud.

Primeira solicitação 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-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 o comando "Quais cinemas em Mountain View exibem o filme da Barbie?", o modelo pode retornar a função find_theatres com os parâmetros Barbie e Mountain View, CA.

Resposta à primeira solicitação 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 solicitação de modelo

Esse exemplo usa dados sintéticos em vez de chamar a API externa. Há dois resultados, cada um com dois parâmetros (name e 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

Substitua my-project pelo nome do projeto do Google Cloud.

Segunda solicitação 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"]
    }
  }]
}]
}'
  

A resposta do modelo pode ser semelhante a esta:

Resposta à segunda solicitação 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
}
}
  

Exemplos de chat

Python

Neste exemplo, demonstramos um cenário de chat com duas funções e dois comandos sequenciais. Ele usa a classe GenerativeModel e os respectivos métodos. Para mais informações sobre como usar o SDK da Vertex AI para Python com os modelos multimodais, consulte Introdução às classes multimodais no SDK da Vertex AI para Python.

Para saber como instalar ou atualizar o Python, consulte Instalar o SDK da Vertex AI para Python. Para mais informações, consulte a documentação de referência da API Python.

import vertexai
from vertexai.generative_models import (
    FunctionDeclaration,
    GenerationConfig,
    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(
        model_name="gemini-1.0-pro-001",
        generation_config=GenerationConfig(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 testar essa amostra, siga as instruções de configuração para Node.js Guia de início rápido da Vertex AI: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Vertex AI para Node.js.

Para autenticar na Vertex AI, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento 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 testar essa amostra, siga as instruções de configuração para Java Guia de início rápido da Vertex AI: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Vertex AI para Java.

Para autenticar na Vertex AI, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento 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 testar essa amostra, siga as instruções de configuração para Go Guia de início rápido da Vertex AI: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Vertex AI para Go.

Para autenticar na Vertex AI, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

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

// functionCallsChat opens a chat session and sends 4 messages to the model:
// - convert a first text question into a structured function call request
// - convert the first structured function call response into natural language
// - convert a second text question into a structured function call request
// - convert the second structured function call response into natural language
func functionCallsChat(w io.Writer, projectID, location, modelName string) error {
	// 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
	paramsProduct := &genai.Schema{
		Type: genai.TypeObject,
		Properties: map[string]*genai.Schema{
			"productName": {
				Type:        genai.TypeString,
				Description: "Product name",
			},
		},
	}
	fundeclProductInfo := &genai.FunctionDeclaration{
		Name:        "getProductSku",
		Description: "Get the SKU for a product",
		Parameters:  paramsProduct,
	}
	paramsStore := &genai.Schema{
		Type: genai.TypeObject,
		Properties: map[string]*genai.Schema{
			"location": {
				Type:        genai.TypeString,
				Description: "Location",
			},
		},
	}
	fundeclStoreLocation := &genai.FunctionDeclaration{
		Name:        "getStoreLocation",
		Description: "Get the location of the closest store",
		Parameters:  paramsStore,
	}
	model.Tools = []*genai.Tool{
		{FunctionDeclarations: []*genai.FunctionDeclaration{
			fundeclProductInfo,
			fundeclStoreLocation,
		}},
	}
	model.SetTemperature(0.0)

	chat := model.StartChat()

	// Send a prompt for the first conversation turn that should invoke the getProductSku function
	prompt := "Do you have the Pixel 8 Pro in stock?"
	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 `getProductSku`
	// with a value for the argument `productName`.
	jsondata, err := json.MarshalIndent(resp.Candidates[0].Content.Parts[0], "\t", "  ")
	if err != nil {
		return fmt.Errorf("json.Marshal: %w", err)
	}
	fmt.Fprintf(w, "function call generated by the model:\n\t%s\n", string(jsondata))

	// Create a function call response, to simulate the result of a call to a
	// real service
	funresp := &genai.FunctionResponse{
		Name: "getProductSku",
		Response: map[string]any{
			"sku":      "GA04834-US",
			"in_stock": "yes",
		},
	}
	jsondata, err = json.MarshalIndent(funresp, "\t", "  ")
	if err != nil {
		return fmt.Errorf("json.Marshal: %w", err)
	}
	fmt.Fprintf(w, "function call response sent to the model:\n\t%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], "\t", "  ")
	if err != nil {
		return fmt.Errorf("json.Marshal: %w", err)
	}
	fmt.Fprintf(w, "Answer generated by the model:\n\t%s\n\n", string(jsondata))

	// Send a prompt for the second conversation turn that should invoke the getStoreLocation function
	prompt2 := "Is there a store in Mountain View, CA that I can visit to try it out?"
	fmt.Fprintf(w, "Question: %s\n", prompt)

	resp, err = chat.SendMessage(ctx, genai.Text(prompt2))
	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 `getStoreLocation`
	// with a value for the argument `store`.
	jsondata, err = json.MarshalIndent(resp.Candidates[0].Content.Parts[0], "\t", "  ")
	if err != nil {
		return fmt.Errorf("json.Marshal: %w", err)
	}
	fmt.Fprintf(w, "function call generated by the model:\n\t%s\n", string(jsondata))

	// Create a function call response, to simulate the result of a call to a
	// real service
	funresp = &genai.FunctionResponse{
		Name: "getStoreLocation",
		Response: map[string]any{
			"store": "2000 N Shoreline Blvd, Mountain View, CA 94043, US",
		},
	}
	jsondata, err = json.MarshalIndent(funresp, "\t", "  ")
	if err != nil {
		return fmt.Errorf("json.Marshal: %w", err)
	}
	fmt.Fprintf(w, "function call response sent to the model:\n\t%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], "\t", "  ")
	if err != nil {
		return fmt.Errorf("json.Marshal: %w", err)
	}
	fmt.Fprintf(w, "Answer generated by the model:\n\t%s\n\n", string(jsondata))
	return nil
}