Como interagir com APIs usando chamadas de função no Gemini

1. Visão geral

O que é a chamada de função no Gemini?

A API Vertex AI Gemini é uma família de modelos de IA generativa desenvolvida pelo Google DeepMind, criada para casos de uso multimodais. A chamada de função é um recurso dos modelos do Gemini que facilita a obtenção de saídas de dados estruturados de modelos generativos para desenvolvedores.

Os desenvolvedores podem usar essas saídas para chamar outras APIs e retornar os dados de resposta relevantes ao modelo. Em outras palavras, a chamada de função ajuda você a conectar seus modelos generativos a sistemas externos para que o conteúdo gerado inclua as informações mais atualizadas e precisas.

Como a chamada de funções funciona

As funções são descritas usando declarações de função, o que ajuda o modelo generativo a entender a finalidade e os parâmetros de uma função. Depois que você transmite declarações de função em uma consulta para um modelo generativo, ele retorna um objeto estruturado que inclui os nomes das funções relevantes e os argumentos delas com base na consulta do usuário. Com a chamada de função, o modelo não chama a função de verdade. Em vez disso, use a função e os parâmetros retornados para chamar a função em qualquer linguagem, biblioteca ou framework que você quiser.

Interface de API

O que você vai criar

Neste codelab, você vai criar um pipeline de IA generativa com a API Gemini da Vertex AI e Python. Usando seu app, os usuários podem perguntar sobre taxas de câmbio, e o sistema vai buscar os dados mais recentes de uma API externa e responder ao usuário.

O que você vai aprender

  • Como interagir com o modelo do Gemini usando a biblioteca de cliente do Python
  • Como definir uma declaração de função e registrá-la como uma ferramenta
  • Como chamar o Gemini e receber uma resposta de chamada de função
  • Como retornar a resposta da função ao Gemini e responder ao usuário

O que é necessário

2. Configuração e requisitos

Antes de usar a chamada de função no Gemini, é necessário ativar a API Vertex AI e instalar a versão mais recente da biblioteca de cliente Python da Vertex AI.

Ativar a API Vertex AI

Para ativar a API Vertex AI, siga estas etapas:

  1. No navegador, acesse a página de detalhes do serviço da API Vertex AI.
  2. Clique no botão Ativar para ativar a API Vertex AI no seu projeto na nuvem do Google Cloud.

Instalar a biblioteca de cliente Python para a Vertex AI

Para instalar as bibliotecas de cliente Python da Vertex AI, siga estas etapas:

  1. Abra um terminal no ambiente de desenvolvimento.
  2. Verifique se você tem um ambiente de desenvolvimento Python válido e consulte estas diretrizes, se necessário.
  3. Execute o seguinte comando para instalar a biblioteca de cliente Python da Vertex AI:
    pip install --upgrade google-cloud-aiplatform
    
  4. Se você estiver executando em um ambiente de notebook, talvez seja necessário reiniciar o ambiente de execução/kernel para usar os pacotes recém-instalados.

Agora você já pode usar a API Vertex AI.

3. Entenda o problema

Você já interagiu com um modelo de linguagem grande ou de IA generativa e perguntou sobre informações atuais ou em tempo real, mas recebeu uma resposta com informações desatualizadas ou imprecisas?

Vamos tentar! Primeiro, vamos importar os pacotes relevantes do Python e inicializar o modelo do Gemini. É possível executar o código a seguir em um ambiente de desenvolvimento Python, como o Colab ou o Colab Enterprise, e instalando a versão mais recente do SDK da Vertex AI para Python:

import vertexai
from vertexai.generative_models import GenerativeModel
model = GenerativeModel("gemini-1.5-pro-001")

Agora, vamos fazer uma pergunta sobre a taxa de câmbio de diferentes moedas hoje:

response = model.generate_content(
    "What's the exchange rate for euros to dollars today?"
)
print(response.text)

O modelo vai gerar uma resposta limitada ou desatualizada semelhante a esta:

As an AI language model, I don't have access to real-time currency exchange
rates. However, as of my last update in September 2021, the approximate exchange
rate between euros (EUR) and US dollars (USD) was:

1 EUR ≈ 1.18 USD

Please note that currency exchange rates constantly fluctuate and can vary
depending on various factors such as economic conditions, supply and demand,
political events, and more. To obtain the most up-to-date and accurate exchange
rate, I recommend using a reliable currency converter or financial website that
provides live rates.

[...]

Se um usuário final receber esse tipo de resposta, ele precisará mudar de contexto para pesquisar as moedas de interesse, buscar a taxa de câmbio mais recente e fazer as conversões por conta própria.

O ideal é que um pipeline de modelo generativo possa lidar com algumas ou todas essas tarefas para o usuário. Na próxima seção, você vai testar algumas soluções alternativas comuns para receber respostas estruturadas de modelos generativos e chamar sistemas externos.

4. Tentar soluções alternativas comuns

Ao trabalhar com modelos generativos em cenários em que você precisa de informações atualizadas ou dados de fontes externas, é possível chamar uma API externa e enviar os resultados de volta ao modelo generativo para que ele use na resposta.

Antes de chamar um sistema externo, é necessário determinar a função certa a ser usada, extrair os parâmetros relevantes do usuário e colocar os parâmetros em um objeto de dados estruturados. Isso geralmente envolve uma engenharia de comando exaustiva para forçar o modelo generativo a gerar dados estruturados válidos.

Vamos retomar a pergunta que fizemos na seção anterior e adicionar mais instruções para o modelo. Envie a seguinte solicitação ao modelo do Gemini:

user_prompt = "What's the exchange rate from euros to US dollars today?"

response = model.generate_content("""
Your task is to extract parameters from the user's input and return it as a
structured JSON payload. The user will ask about the exchange rate and which
currency they are converting from and converting to.

User input: {user_prompt}

Please extract the currencies as parameters and put them in a JSON object.
""".format(user_prompt=user_prompt))
print(response.text)

Isso resulta na seguinte resposta de texto, que não é um JSON válido e será difícil de trabalhar:

```json
{
  "currency_from": "euros",
  "currency_to": "US dollars"
}
```

Em particular, a primeira e a última linha da resposta de texto incluem crases para delimitar o bloco de código, a primeira linha inclui um especificador de linguagem, e os valores no objeto JSON não são as abreviações padrão de três letras que uma API de câmbio esperaria como parâmetros de entrada.

Podemos tentar usar o Python para pós-processar esse texto em um JSON e um dicionário válidos, adicionar mais instruções ao comando, fornecer um ou mais exemplos da saída desejada, ajustar o modelo ou fazer outra chamada ao modelo generativo pedindo que ele limpe o JSON.

Mas há uma maneira mais determinística. Vamos aprender a usar a chamada de função no Gemini para consultar informações em serviços externos e retornar respostas relevantes aos usuários finais.

5. Como a chamada de funções funciona

Antes de começar a extração de parâmetros e a chamada de função, vamos analisar as etapas da chamada de função e quais componentes são usados no ambiente de execução.

Visão geral da chamada de função no Gemini

Entrada do usuário para a API Gemini

O comando do usuário é enviado à API Gemini. Nessa chamada de API para o modelo do Gemini, o desenvolvedor definiu uma ou mais declarações de função em uma ferramenta para que o modelo saiba quais funções ele pode chamar e como fazer isso.

A API Gemini retorna uma chamada de função

Com base no conteúdo da entrada do usuário e do comando, o Gemini vai retornar uma resposta de chamada de função com dados estruturados que incluem o nome da função a ser chamada e os parâmetros correspondentes a serem usados.

Fazer uma solicitação de API

Em seguida, use o nome da função e os parâmetros para fazer uma solicitação de API e recuperar informações de um sistema ou API externa. Essa solicitação e resposta de API é implementada pelo desenvolvedor no código do aplicativo e acontece fora do escopo da API Gemini e do SDK. Por exemplo, você pode usar a biblioteca requests em Python para chamar uma API REST e receber uma resposta JSON. Ou você pode chamar a função usando sua abordagem e biblioteca de cliente preferidas.

Retornar a resposta da API para o Gemini

Por fim, você vai transmitir a resposta da API de volta ao modelo do Gemini para que ele possa gerar uma resposta ao comando inicial do usuário final ou invocar outra resposta de chamada de função se o modelo do Gemini determinar que precisa de mais informações.

6. Escolher sua API

Agora que você entende o fluxo geral e as etapas específicas da chamada de função, vai criar um pipeline de IA generativa para buscar as taxas de câmbio mais recentes. Primeiro, precisamos selecionar qual API queremos usar como fonte de informações.

Para nosso app de câmbio, vamos usar a API REST em https://www.frankfurter.app/ (em inglês) para buscar as informações mais recentes sobre as taxas de câmbio globais.

Para interagir com essa API REST, podemos fazer uma chamada de API REST com requests em Python da seguinte maneira:

import requests
url = "https://api.frankfurter.app/latest"
response = requests.get(url)
response.text

ou uma solicitação cURL, como:

curl https://api.frankfurter.app/latest

que retorna uma resposta semelhante a esta:

{
  "amount": 1,
  "base": "EUR",
  "date": "2023-12-20",
  "rates": {
    "AUD": 1.6186, "BGN": 1.9558, "BRL": 5.3287,
    "CAD": 1.4609, "CHF": 0.946, "CNY": 7.8121,
    "CZK": 24.538, "DKK": 7.4565, "GBP": 0.86555,
    "HKD": 8.5439, "HUF": 385.23, "IDR": 16994,
    "ILS": 3.9983, "INR": 91.06, "ISK": 150.3,
    "JPY": 157.12, "KRW": 1425.62, "MXN": 18.6867,
    "MYR": 5.0977, "NOK": 11.2895, "NZD": 1.7421,
    "PHP": 60.991, "PLN": 4.3413, "RON": 4.9699,
    "SEK": 11.129, "SGD": 1.4562, "THB": 38.252,
    "TRY": 31.883, "USD": 1.0944, "ZAR": 20.111
  }
}

Como a chamada de função no Gemini não faz a chamada de API externa para você, não há restrições sobre o tipo de API que você usa. Você pode usar um serviço do Cloud Run, uma função do Cloud, uma solicitação de API para um serviço do Google Cloud ou qualquer API REST externa.

7. Definir uma função e uma ferramenta

Agora que você selecionou uma API REST para usar, podemos definir uma especificação de API e registrar a função em uma ferramenta.

Verifique se você instalou a versão mais recente do SDK da Vertex AI para Python.

Em seguida, importe os módulos necessários do SDK do Python e inicialize o modelo do Gemini:

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

model = GenerativeModel("gemini-1.5-pro-001")

Voltando à API REST em https://api.frankfurter.app/, podemos ver que ela aceita os seguintes parâmetros de entrada:

Parâmetro

Tipo

Descrição

from

String

Moeda de conversão

to

String

Moeda para conversão

date

String

Data para buscar a taxa de câmbio

Usando esses parâmetros, uma especificação OpenAPI parcial para essa API REST no formato YAML fica assim:

openapi: 3.0.0
info:
  title: Frankfurter Exchange Rate API
  description: This API provides current and historical exchange rates
  version: 1.0.0
servers:
  - url: https://api.frankfurter.app
paths:
  /{date}:
    get:
      summary: Get the latest currency exchange rates.
      parameters:
        - name: date
          in: path
          description: Get currency rates for a specific date or 'latest' if a date is not specified
          required: true
          schema:
            type: string
        - name: from
          in: query
          description: The currency to convert from.
          required: true
          schema:
            type: string
        - name: to
          in: query
          description: The currency to convert to.
          schema:
            type: string

Agora, vamos registrar isso como um FunctionDeclaration usando o SDK do Python para Gemini:

get_exchange_rate_func = FunctionDeclaration(
    name="get_exchange_rate",
    description="Get the exchange rate for currencies between countries",
    parameters={
    "type": "object",
    "properties": {
        "currency_date": {
            "type": "string",
            "description": "A date that must always be in YYYY-MM-DD format or the value 'latest' if a time period is not specified"
        },
        "currency_from": {
            "type": "string",
            "description": "The currency to convert from in ISO 4217 format"
        },
        "currency_to": {
            "type": "string",
            "description": "The currency to convert to in ISO 4217 format"
        }
    },
         "required": [
            "currency_from",
            "currency_date",
      ]
  },
)

Use o máximo de detalhes possível nas descrições de funções e parâmetros, já que o modelo generativo usa essas informações para determinar qual função selecionar e como preencher os parâmetros na chamada de função.

Por fim, defina um Tool que inclua a declaração da função:

exchange_rate_tool = Tool(
    function_declarations=[get_exchange_rate_func],
)

Aqui, você está usando uma declaração de função em uma ferramenta, mas é possível registrar uma ou mais declarações de função em uma ferramenta, e o modelo vai selecionar a função apropriada para usar durante a execução. Consulte a documentação sobre Chamada de função na API Gemini para mais detalhes sobre FunctionDeclaration, Tool e classes relacionadas no SDK Gemini para Python.

Você concluiu a configuração da função e das definições de ferramentas. Na próxima seção, vamos chamar o modelo generativo com essa ferramenta e receber uma chamada de função que pode ser usada para chamar a API REST.

8. Gerar uma chamada de função

Agora você pode enviar um comando ao modelo generativo e incluir a tool que você definiu:

prompt = """What is the exchange rate from Australian dollars to Swedish krona?
How much is 500 Australian dollars worth in Swedish krona?"""

response = model.generate_content(
    prompt,
    tools=[exchange_rate_tool],
)

Vamos analisar o objeto de resposta:

print(response.candidates[0].content)

role: "model"
parts {
  function_call {
    name: "get_exchange_rate"
    args {
      fields {
        key: "currency_to"
        value {
          string_value: "SEK"
        }
      }
      fields {
        key: "currency_from"
        value {
          string_value: "AUD"
        }
      }
      fields {
        key: "currency_date"
        value {
          string_value: "latest"
        }
      }
    }
  }
}

Parece que o modelo selecionou a única função disponível e retornou uma chamada de função para a função get_exchange_rate com os parâmetros. E os parâmetros estão no formato correto que queríamos. Viva por receber respostas estruturadas de modelos generativos!

Na próxima seção, você vai usar as informações da resposta para fazer uma solicitação de API.

9. Fazer uma solicitação de API

A chamada de função no Gemini não faz a chamada de API externa para você. Em vez disso, você pode usar qualquer linguagem, biblioteca ou framework que quiser.

Aqui, você vai usar a biblioteca requests em Python para chamar a API REST de taxa de câmbio.

Vamos descompactar a resposta em um dicionário Python:

params = {}
for key, value in response.candidates[0].content.parts[0].function_call.args.items():
    params[key[9:]] = value
params

Agora podemos chamar requests ou qualquer outro método:

import requests
url = f"https://api.frankfurter.app/{params['date']}"
api_response = requests.get(url, params=params)
api_response.text

que resulta em uma resposta semelhante a esta:

'{"amount":1.0,"base":"AUD","date":"2024-01-16","rates":{"SEK":6.8682}}'

E temos nossa resposta da API REST, com as informações mais recentes da taxa de câmbio de hoje. Na próxima seção, vamos transmitir essas informações de volta ao modelo para que ele possa gerar uma resposta relevante para o usuário.

10. Gerar uma resposta

Por fim, vamos gerar uma resposta para o usuário transmitindo a resposta da função ao modelo na próxima rodada de conversa:

response = model.generate_content(
    [
    Content(role="user", parts=[
        Part.from_text(prompt + """Give your answer in steps with lots of detail
            and context, including the exchange rate and date."""),
    ]),
    Content(role="function", parts=[
        Part.from_dict({
            "function_call": {
                "name": "get_exchange_rate",
            }
        })
    ]),
    Content(role="function", parts=[
        Part.from_function_response(
            name="get_exchange_rate",
            response={
                "content": api_response.text,
            }
        )
    ]),
    ],
    tools=[exchange_rate_tool],
)


response.candidates[0].content.parts[0].text

Depois que passamos a resposta da função de volta para o modelo, ele responde ao comando do usuário com informações relevantes da resposta da API.

The exchange rate from Australian dollars to Swedish krona on January 16, 2024,
is 1 Australian dollar is equal to 6.8663 Swedish krona.

So, 500 Australian dollars would be worth 500 * 6.8663 = 3,433.15 Swedish krona.

11. Conferir o exemplo de código completo

Neste ponto, você pode colocar seu código Python em uma API de back-end usando um serviço do Cloud Run, uma função do Cloud ou outro serviço do Cloud e implantar um app de front-end que usa essa API de back-end para realizar consultas de modelo e chamadas de API.

Confira o exemplo de código completo da nossa solução final:

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

model = GenerativeModel("gemini-1.5-pro-001")

get_exchange_rate_func = FunctionDeclaration(
    name="get_exchange_rate",
    description="Get the exchange rate for currencies between countries",
    parameters={
    "type": "object",
    "properties": {
        "currency_date": {
            "type": "string",
            "description": "A date that must always be in YYYY-MM-DD format or the value 'latest' if a time period is not specified"
        },
        "currency_from": {
            "type": "string",
            "description": "The currency to convert from in ISO 4217 format"
        },
        "currency_to": {
            "type": "string",
            "description": "The currency to convert to in ISO 4217 format"
        }
    },
         "required": [
            "currency_from",
            "currency_date",
      ]
  },
)

exchange_rate_tool = Tool(
    function_declarations=[get_exchange_rate_func],
)

prompt = """What is the exchange rate from Australian dollars to Swedish krona?
How much is 500 Australian dollars worth in Swedish krona?"""

response = model.generate_content(
    prompt,
    tools=[exchange_rate_tool],
)

response.candidates[0].content

params = {}
for key, value in response.candidates[0].content.parts[0].function_call.args.items():
    params[key[9:]] = value
params

import requests
url = f"https://api.frankfurter.app/{params['date']}"
api_response = requests.get(url, params=params)
api_response.text

response = model.generate_content(
    [
    Content(role="user", parts=[
        Part.from_text(prompt + """Give your answer in steps with lots of detail
            and context, including the exchange rate and date."""),
    ]),
    Content(role="function", parts=[
        Part.from_dict({
            "function_call": {
                "name": "get_exchange_rate",
            }
        })
    ]),
    Content(role="function", parts=[
        Part.from_function_response(
            name="get_exchange_rate",
            response={
                "content": api_response.text,
            }
        )
    ]),
    ],
    tools=[exchange_rate_tool],
)


response.candidates[0].content.parts[0].text

Nesta implementação, usamos duas solicitações ao modelo generativo: uma para gerar uma chamada de função e outra para retornar a resposta da função. Essa é apenas uma das maneiras de processar chamadas e respostas de função com o Gemini. Você também pode fazer outras chamadas de função para receber mais informações sobre sua consulta ou usar a chamada de função com métodos assíncronos e de chat.

Para mais exemplos de código, consulte o notebook de exemplo para chamadas de função no Gemini.

12. Parabéns

Usando a chamada de função no Gemini, você criou um pipeline de IA generativa que usa a API Gemini da Vertex AI e o Python. Os usuários podem perguntar sobre taxas de câmbio, e o sistema vai buscar os dados mais recentes de uma API externa e responder.

Com um comando de um usuário final, a chamada de função no Gemini seleciona a função adequada, extrai parâmetros do comando e retorna um objeto de dados estruturados para que você faça uma chamada de API externa.

O design da chamada de função no Gemini foi criado para oferecer o melhor dos dois mundos na extração determinística de parâmetros, deixando o resumo e a criação de conteúdo para o modelo generativo. Teste outras APIs e comandos no seu pipeline e conheça as outras funcionalidades disponíveis relacionadas à API Vertex AI Gemini.

Interface de API

Limpeza

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados neste codelab, faça a limpeza a seguir:

Saiba mais

Continue aprendendo sobre IA de conversação e IA generativa com estes guias e recursos:

Licença

Este conteúdo está sob a licença Atribuição 2.0 Genérica da Creative Commons.