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

1. Visão geral

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

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

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 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 com declarações de função, que ajudam o modelo generativo a entender a finalidade e os parâmetros de uma função. Depois de transmitir as declarações de função em uma consulta para um modelo generativo, o modelo 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. Em vez disso, é possível usar 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 o Python. Ao usar o 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 com a resposta.

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 da 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 começar a usar a chamada de função no Gemini, você precisa ativar a API Vertex AI e instalar a versão mais recente da biblioteca de cliente da Vertex AI para Python.

Ativar a API Vertex AI

Para ativar a API Vertex AI, siga estas etapas:

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

Instalar a biblioteca de cliente do Python para a Vertex AI

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

  1. Abra um terminal no ambiente de desenvolvimento.
  2. Verifique se você tem um ambiente de desenvolvimento em Python válido e consulte estas diretrizes, se necessário.
  3. Execute o comando a seguir para instalar a biblioteca de cliente Python para Vertex AI:
    pip install --upgrade google-cloud-aiplatform
    
  4. Se você estiver executando em um ambiente de notebook, talvez seja necessário reiniciar seu tempo 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 um modelo de IA generativa e perguntou sobre informações atuais ou em tempo real para receber uma resposta com informações desatualizadas ou imprecisas?

Vamos testar agora! Primeiro, vamos importar os pacotes Python relevantes 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 instalar 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 para você uma resposta limitada ou desatualizada semelhante a:

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 recebesse esse tipo de resposta, ele precisaria mudar os contextos para procurar as moedas nas quais tem interesse, buscar a taxa de câmbio mais recente e realizar 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 tentar algumas soluções comuns para receber respostas estruturadas de modelos generativos para chamar sistemas externos.

4. Testar soluções alternativas comuns

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

Antes de chamar um sistema externo, você precisa determinar a função certa a ser usada, extrair os parâmetros relevantes do usuário e colocá-los 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 rever a pergunta que fizemos na seção anterior e adicionar mais algumas instruções para o modelo. Tente enviar 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)

Este resultado é a seguinte resposta de texto, que não é um JSON válido e será difícil de trabalhar com ela:

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

Em particular, a primeira e a última linhas da resposta de texto incluem acentos graves 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 moeda de três letras que uma API de câmbio de moeda esperaria como parâmetros de entrada.

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

Mas existe uma forma mais determinista! 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çarmos com a extração de parâmetros e a chamada de função, vamos ver 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 e, nessa chamada, ao modelo do Gemini, o desenvolvedor definiu uma ou mais declarações de função em uma ferramenta para que o modelo do Gemini 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 e do comando do usuário, 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.

Fazer uma solicitação de API

Em seguida, você vai usar o nome e os parâmetros da função para fazer uma solicitação de API e recuperar informações de um sistema externo ou uma API. Essa solicitação e resposta de API são implementadas pelo desenvolvedor no código do aplicativo e acontecem fora do escopo da API Gemini e do SDK. Por exemplo, é possível 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 ao Gemini

Por fim, você vai transmitir a resposta da API de volta ao modelo 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 Gemini determinar que precisa de mais informações.

6. Escolha 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 usar como fonte de informações.

Para nosso app de câmbio de moeda, usaremos a API REST em https://www.frankfurter.app/ para buscar as informações mais recentes sobre taxas de câmbio globais.

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

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:

{
  "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 por você, não há restrições quanto ao tipo de API usado. É possível 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 para 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/, vemos que ela aceita os seguintes parâmetros de entrada:

Parâmetro

Tipo

Descrição

from

String

Moeda da qual converter

to

String

Moeda a ser convertida

date

String

Data para buscar a taxa de câmbio em

Usando esses parâmetros, uma especificação OpenAPI parcial para essa API REST em formato YAML será semelhante a:

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ção e parâmetro, já que o modelo generativo vai usar essas informações para determinar qual função selecionar e como preencher os parâmetros na chamada da função.

Por fim, você vai definir um Tool que inclui 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 observe que é possível registrar uma ou mais declarações de função em uma ferramenta e o modelo selecionará a função apropriada para usar no tempo de execução. Consulte a documentação sobre chamadas de função na API Gemini para saber mais sobre FunctionDeclaration, Tool e classes relacionadas no SDK do Gemini para Python.

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

8. Gerar uma chamada de função

Agora você pode enviar um comando para o modelo generativo e incluir o tool definido:

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 dar uma olhada no 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 para a função get_exchange_rate com os parâmetros. E os parâmetros estão no formato correto que queríamos. Parabéns por receber respostas estruturadas dos modelos generativos!

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

9. Fazer uma solicitação de API

Vale lembrar que a chamada de função no Gemini não faz a chamada de API externa para você. Em vez disso, você pode usar a linguagem, a biblioteca ou o 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

O que resulta em uma resposta semelhante a:

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

E nós temos nossa resposta da API REST, com as informações de taxa de câmbio mais recentes de hoje. Na próxima seção, vamos retornar essas informações 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 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 de transmitir a resposta da função de volta ao modelo, ele responderá 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. Confira o exemplo de código completo

Agora é possível 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 para o modelo generativo: uma para gerar uma chamada de função e outra para retornar a resposta da função. Esse é apenas um método para processar chamadas e respostas de função com o Gemini. Você também pode fazer chamadas de função adicionais para obter mais informações para sua consulta ou usar a chamada de função com chat e métodos assíncronos.

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

12. Parabéns

Ao usar 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 buscará os dados mais recentes de uma API externa e responderá com uma resposta.

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

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

Interface de API

Limpeza

Faça a limpeza abaixo para evitar cobranças dos recursos usados neste codelab na conta do Google Cloud:

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.