Desenvolvendo soluções com IA Generativa na Google Cloud

Luciano Martins
google-cloud-brasil
14 min readMay 16, 2023

--

* TLDR: No Google I/O 2023, as API de Generative AI de Google Cloud foram disponibilizadas (em preview) para os desenvolvedores. Vamos fazer uma “primeira jornada” no potencial desses serviços utilizando o Generative AI Studio da Vertex AI.

Como chegamos até aqui?

No Google I/O 2023, dentre diversos outros lançamentos relacionados a inteligência artificial, tivemos o lançamento das funcionalidades de Generative AI (IA Generativa em português), ou simplesmente GenAI, dentro do universo de produtos e tecnologias do Google — Cloud, Workspace, Pixel e etc.

Mas antes de ir para o serviço em si, meio que para traçar uma linha de base conceitual, para quem já conhece a área de GenAI revisar os conceitos e quem está começando agora, conhecê-los.

E tudo começou com Transformers

Estes transformers são importantes também, mas não estamos falando deles

A arquitetura Transformers é um tema que merece uma postagem dedicada (tá no backlog aqui). Mas tentando falar da forma mais sucinta possível: Transformers é uma arquitetura de modelos de aprendizado de máquina desenvolvida pelo Google e publicada em 2017. Ela trabalha usando mecanismos de atenção para aprender as relações entre diferentes partes de uma sequência de entrada, permitindo aprender padrões mais complexos do que os modelos tradicionais. A arquitetura Transformers serve como base para a maioria dos modelos atualmente considerados “estado da arte” (State Of The Art, ou SOTA, em inglês) — incluindo processamento de linguagem natural, tradução automática e reconhecimento de imagem (mas também usados em outras áreas).

um exemplo de arquitetura transformer e de como funciona seu mecanismo de "encoder" e "decoder"

Uma maneira de pensar em transformers é imaginar que você está tentando traduzir uma frase do português para o francês. Um modelo tradicional de aprendizado de máquina primeiro aprenderia um vocabulário de palavras e depois tentaria encontrar as palavras no idioma francês que correspondem às palavras na frase em inglês. No entanto, isso não seria muito preciso, porque não levaria em conta o contexto das palavras. Por exemplo, a palavra “banco” pode significar uma instituição financeira ou o equipamento que sentamos. Um transformer, por outro lado, seria capaz de aprender o significado da palavra “banco” com base no contexto em que é usada. Por exemplo, se a palavra “banco” for seguida pela palavra “conta”, é mais provável que se refira a uma instituição financeira.

Modelos Fundamentais ou Foundation Models

Modelos Fundamentais, ou foundation models em inglês, são modelos gigantes que podem ser adaptados para uma variadade de cenários (ou tasks como se fala no mundo de IAs Generativas) que são treinados em volumes muito grandes de dados — Exemplos de modelos fundamentais podem ser o BERT (Bidirectional Encoder Representations from Transformers) e o PaLM ( Pathways Language Model), ambos desenvolvidos pelo Google Research.

Uma abstração da idéia de modelos fundamentais e suas várias utilidades

Large Language Models

Modelos de linguagem gigantes, numa tradução livre, ou Large Language Models do inglês (ou ainda LLM) são modelos treinados em grandes quantidades de dados de texto. Isso permite que eles gerem texto, façam traduções de alta qualidade entre idiomas, escrevam diferentes tipos de conteúdo criativo e respondam às suas perguntas de maneira informativa. Há muitos esforços — acadêmicos, de comunidades e de empresas — que estão acelerando a evolução desta área de pesquisa de inteligência artificial. Aqui deixo, como referência, o histórico recente do Google nesta área de pesquisa:

linha do tempo de pesquisas Google relacionadas a modelos de processamento de linguagem

Prompts — o que são, para que servem, porque se importar com eles?

Dos conceitos principais, se este não for o mais importante deles, talvez seja o que tenhamos que refinar melhor em nossas mentes — pois é o que mais utilizaremos no dia a dia, como desenvolvedores ou pessoas interagindo com modelos generativos.

Prompts (acho que essa é uma daquelas palavras que não foram traduzidas, foi adotada pelo processo que chamamos de anglicismo) são a forma que provemos contexto, ou direcionamentos, para os LLM. Os prompts são utilizados em todos os contextos que utilizamos LLM — geração de texto, tradução de idiomas, criação de conteúdos, cenários de perguntas e respostas, etc.

Por exemplo, se queremos que o nosso modelo escreva um poema sobre a cidade de Belém do Pará, enviamos o seguinte prompt para o modelo:

“Escreva um poema sobre a cidade de Belém do Pará”

Ou para solicitar ao modelo uma tradução de inglês para português:

“Traduza a sentença ‘I love you’ para português”

Tarefas mais complexas e com detalhamentos mais específicos também podem ser realizadas utilizando prompts — por exemplo:

"escreva um texto, com dois parágrafos, sobre computação quântica”.

Mas prompts podem ter diferente formatos — alguns possíveis são:

Zero-shot: Em uma solicitação de tarefa, o modelo pode usar seu conhecimento aprendido durante o seu treinamento para gerar uma solução. Nenhuma informação adicional (como contexto, textos ou exemplos) é dada ao modelo durante a solicitação.

One-shot: Em uma nova solicitação de tarefa, o modelo recebe um único exemplo de “pergunta e resposta”, ou de “texto e classificação” ou de qualquer que seja a tarefa a ser executada.

Few-shot: Em uma nova solicitação de tarefa, o modelo recebe alguns exemplos da nova tarefa e é capaz de gerar uma solução. Os poucos exemplos funcionam como um “refinamento” do treinamento em tempo de inferência, dando direcionamentos mais detalhados ao modelo de como responder (em determinado formato, ou usando determinadas palavras).

Uma das principais diferenças entre as três abordagens é a quantidade de dados de treinamento necessários, uma vez que entregamos ao modelo exemplos validados e confiáveis do que o modelo deve fazer. Enquanto na abordagem one-shot não precisamos de dados adicionais, na abordagem few-shot precisamos de mais exemplos (além dos usados para treinar o modelo inicialmente).

Por outro lado, da perspectiva de eficiência do modelo, para tarefas mais específicas e mais complexas, a abordagem few-shot pode apresentar melhores resultados (esse cenário é válido também para aqueles cenários onde é trabalhoso ou muito caro gerar um dataset grande e dedicado para a tarefa em questão).

Bom, acho que com esse preâmbulo, podemos ir para a parte mais divertida — desenvolvendo com a Vertex AI.

Generative AI na Vertex AI

Dentro da Google Cloud, há para todos os usuários e desenvolvedores a Vertex AI — uma plataforma de desenvolvimento de soluções com machine learning na Google Cloud.

No Google I/O 2023 foram lançados dois grandes serviços, em public preview, como parte como ecossistema da Vertex AI — O Vertex AI Model Garden e o Vertex AI Generative AI Studio. Para uma visão inicial, podemos imaginar a estrutura abaixo:

visão geral das funcionalidades da Vertex AI na Google Cloud

Navegando em sua console da Vertex AI, você verá alguns menus adicionais como abaixo:

Novos serviços disponíveis na console da Vertex AI

Ou seja, Generative AI Studio, com opções de linguagem e sintetização/reconhecimento de fala e o Model Garden.

Iniciando com a Vertex AI Model Garden

A Vertex AI Model Garden é a funcionalidade da Vertex AI que aceleram o seu processo de desenvolvimento fornecendo foundation models, modelos desenvolvidos pela Google Research e modelos open source:

visão geral do Model Garden na console da Vertex AI

O Model Garden serve como um local central para encontrar os modelos disponíveis dentro da Google Cloud — nele você encontrará os modelos e as tarefas (ou tasks) possíveis de serem realizadas com as API gerenciadas (como Vision API, Natural Language API e as API de Speech [Speech-to-Text e Text-to-Speech]).

Para alguns passo-a-passo de como navegar no Model Garden, visite a seção Explorando Modelos da documentação do Model Garden.

Iniciando com a Vertex AI Generative AI Studio

Agora a parte que, para mim, é a mais interessante e divertida 🙂

Também durante o Google I/O 2023, foi anunciada a mais nova versão do modelo PaLM — o PaLM 2. E na Vertex AI você tem disponível o que chamamos de PaLM APIs via o Generative AI Studio.

O Generative AI Studio, em private preview, é um ambiente gerenciado (ou seja, onde você não se preocupa com a gestão de infraestrutura) que simplifica o seu processo de desenvolvimento na interação, refinamento e implantação de modelos generativos. O mais legal é que você consegue fazer isso tudo usando o SDK da Vertex AI (no que focaremos aqui).

Na console da Vertex AI você consegue acessar diretamente o Generative AI Studio, onde você encontra uma interface simples — como abaixo:

visão geral do Generative AI Studio na console da Vertex AI

Especialmente na parte de linguagem, há um mundo de coisas que podem ser feitas — vamos navegar em alguns exemplos:

Algumas das tarefas que podem ser realizadas na Vertex AI Generative AI Studio

Vale ressaltar que, como um produto em public preview, há algumas características para serem consideradas:

  1. No momento há três modelos disponíveis publicamente: text-bison-001 (para geração de texto), chat-bison-001 (para cenários conversacionais) e textembeddings-gecko-001 (para a geração de text embeddings a partir de entradas de texto). Na documentação você encontrará uma lista sempre atualizada de modelos disponíveis.
  2. Neste momento de public preview, o único idioma oficialmente suportado é o Inglês. Mas mais adiante neste blog podemos ter uma idéia de como realizar alguns testes utilizando o português também, adicionando uma etapa intermediária de tradução.
  3. Alguns parâmetros estão disponíveis para customizar (ou direcionar o modelo) para uma saída da forma que você espera. Um detalhamento maior desses parâmetros podem ser encontrados na documentação do Generative AI Studio, mas um resumo seria:

maxOutputTokens: que define o tamanho máximo da saída do modelo em número de tokens (que podemos imaginar como sendo palavras e caracteres de pontuação)

temperature: que é a “permissão” que damos ao modelo para ser criativo em suas gerações — ou seja, na hora de escolher o próximo token na formação de uma frase. Valores maiores de temperature irão utilizar uma maior aleatoriedade na escolha do próximo token.

topK: que define a quantidade de quantos “próximos tokens possíveis” serão considerados para decidir o próximo token da formação de uma frase. Por exemplo, topK=1 vai considerar somente o top-1 token e topK=20 vai selecionar o próximo token considerando os top-20 possíveis tokens

topP: Na hora de selecionar o próximo token da formação de uma frase, considerando o universo de possíveis tokens definidos pelo parâmetro topK, o topP considerará a probabilidade que queremos considerar. Por exemplo, um topP=0.5, significa que serão selecionados quantos tokens forem possíveis até que a soma de suas probabilidades seja o mais próximo possível (sem ultrapassar) de 0.5.

Gerando informações usando a SDK da Vertex AI Generative AI Studio

Legal, agora que vamos utilizar a SDK da Vertex AI, a primeira coisa que temos que fazer é instalar (ou atualizar) o pacote do SDK. Para isso, no seu ambiente com Python instalado, rode o comando abaixo:

$ pip install google-cloud-aiplatform --upgrade

Com o pacote devidamente instalado, o próximo passo é importar os métodos do módulo (aqui eu estou importando vários, apenas para dar uma idéia das possibilidades):

from vertexai.preview.language_models import TextGenerationModel,\
ChatModel,\
InputOutputTextPair,\
TextEmbeddingModel

Pelos métodos importados já conseguimos ver os grandes grupos de atividades que podem ser feitas:

TextGenerationModel() vai ajudar com a geração de conteúdo (sejam perguntas e respostas, escrita de parágrafos, idéias de campanhas ou descrições de produtos, etc)

ChatModel() vai ajudar a criar sessões de conversas com o modelo, enriquecendo chatbots e fornecendo experiências mais fluidas a clientes

InputOutputTextPair() para criarmos cenários few-shot (para rever o conceito, basta ir na sessão “Prompts, o que são, para que servem, porque se importar com eles” mais ali acima) onde oferecemos exemplos de tarefas e suas respostas, para orientar as respostas do modelo

TextEmbeddingModel() para cenários onde, ao invés de realizar tarefas diretas com o modelo, queremos criar text embeddings de nossas informações para acelerar a criação de cenários mais avançados — como busca semântica, análise de similaridade de sentenças, etc. De forma ultra resumida, um embeddings é você pegar uma informação, como um texto ou uma imagem, e transformá-la numa representação numérica, ou em um vetor de números reais, para facilitar a manipulação matemática (aplicando conceitos como distância de vetores) Vou fazer um blog só sobre esse tema que acho que vale a pena 🙂

Com os módulos devidamente carregados, a próxima etapa é instanciar um objeto que utilizará algum dos modelos disponíveis. Para isso, usamos algum dos método importados da SDK e apontamos para um dos modelos disponíveis — como abaixo, que estou utilizando o método TextGenerationModel() e o modelo text-bison-001:

generation_model = TextGenerationModel.from_pretrained("text-bison@001")

Após isso, o próximo passo já é interagir com o modelo:

# prompt é a informação que você quer que o modelo gere
prompt = "What is a large language model?"

# generation_model.predict() é a chamada ao modelo
response = generation_model.predict(
prompt=prompt
)

# aqui mostramos o resultado da chamada
print(response.text)

E a resposta será similar ao texto abaixo:

A large language model (LLM) is a type of artificial intelligence (AI) model 
that can understand and generate human language. LLMs are trained on massive
datasets of text and code, and they can learn to perform a wide variety of
tasks, such as translating languages, writing different kinds of creative
content, and answering your questions in an informative way.

LLMs are still under development, but they have the potential to revolutionize
many industries. For example, LLMs could be used to create more accurate and
personalized customer service experiences, to help doctors diagnose and treat
diseases, and to even write entire books and movies.

Mas temos vários parâmetros que podemos trabalhar, certo? Então abaixo iremos utilizá-los:

prompt_top_k_example = "Write a 2-day itinerary for France."
temperature = 0.9
top_k_val = 5
top_p_val = 0.7
response = generation_model.predict(
prompt=prompt_top_k_example,
max_output_tokens=300,
temperature=temperature,
top_k=top_k_val,
top_p=top_p_val
)
print(response.text)

Aqui estamos utilizando algumas definições específicas de temperature, top-k e top-p. O resultado será semelhante ao abaixo:

Day 1:
* Morning: Start your day in Paris with a visit to the Eiffel Tower. Take the
elevator to the top for stunning views of the city.
* Afternoon: After lunch, visit the Louvre Museum, one of the largest and most
famous art museums in the world. See works by Leonardo da Vinci, Michelangelo,
and Rembrandt.
* Evening: Enjoy a romantic dinner at a traditional French restaurant.

Day 2:
* Morning: Visit the Palace of Versailles, a UNESCO World Heritage Site.
Explore the opulent palace and gardens, once home to French royalty.
* Afternoon: Take a walk through the Tuileries Gardens, a beautiful park in
the heart of Paris.
* Evening: See a show at the Moulin Rouge, a world-famous cabaret.
This is just a suggested itinerary, of course, and you can customize it to
fit your interests and budget. There are many other things to see and do in
France, so be sure to do some research before you go to make the most of your
trip.

Se modificarmos um pouco estes parâmetros podemos ver a diferença que isso gera no resultado:

prompt_top_k_example = "Write a 2-day itinerary for France."
temperature = 0.2
top_k_val = 20
top_p_val = 0.5
response = generation_model.predict(
prompt=prompt_top_k_example,
max_output_tokens=300,
temperature=temperature,
top_k=top_k_val,
top_p=top_p_val
)
print(response.text)

E podemos ver que houve mudanças no resultado da geração de texto por conta da mudança dos parâmetros:

Day 1:
* Morning: Start your day in Paris with a visit to the Eiffel Tower. Take the
elevator to the top for stunning views of the city.
* Afternoon: After lunch, visit the Louvre Museum, one of the largest and most
famous museums in the world. See works of art by Leonardo da Vinci,
Michelangelo, and Rembrandt.
* Evening: Enjoy a romantic dinner at a cozy bistro in Montmartre.

Day 2:
* Morning: Take a day trip to Versailles, the former home of French royalty.
Tour the opulent palace and gardens.
* Afternoon: Visit the Palace of Fontainebleau, another former royal residence.
Explore the palace's many rooms and admire its beautiful architecture.
* Evening: Enjoy a delicious meal at a traditional French restaurant in Paris.

Mas para tarefas conversacionais, como funcionaria? Bom primeiros temos que instanciar um client da SDK utilizando o método para chat e o modelo adequado para isso:

chat_model = ChatModel.from_pretrained("chat-bison@001")

E depois iniciamos nossas interações:

chat_model = ChatModel.from_pretrained("chat-bison@001")
chat = chat_model.start_chat()
print(chat.send_message("""
What is the average weight of a mobile phone?
"""))

A resposta desta primeira interação seria similar a abaixo:

The average weight of a mobile phone is 200 grams. However, the weight of 
mobile phones can vary depending on the size, type, and features of the phone.
For example, a large smartphone with a lot of features may weigh more than a
small, basic phone.

Mas o mais legal dessa interação conversacional é o histórico da conversa. Se eu seguir fazendo mais perguntas usando o contexto que acabou de ser falado (sem você precisar, manualmente, armazenar as respostas passadas e reenviar ao modelo), o modelo consegue responder:

print(chat.send_message("""
Is it lighter or heavier than a regular pencil?
"""))

E como podemos verificar, o modelo entendeu que o contexto ainda era relacionado a pergunta inicial (peso de um aparelho celular) e respondeu baseado nesse contexto:

The average weight of a regular pencil is 2.5 grams. The average weight of a 
mobile phone is 200 grams. Therefore, a mobile phone is heavier than a regular
pencil.

Mas como a gente pode interagir em português?

Legal, vimos alguns exemplos de como é simples e rápido interagir com as API do Generative AI Studio, mas como foi dito antes, durante esse período de public preview, somente o idioma inglês é suportado. O que podemos fazer enquanto o suporte oficial a português brasileiro não está disponível é utilizarmos uma função wrapper que realize a tradução do português para o inglês antes de enviar as informações para a API, e de inglês para português para vermos os resultados.

Um exemplo de função wrapper de tradução seria como abaixo (utilizando a Cloud Translation API). Primeiro você precisa instalar a SDK do Translate:

$ pip install google-cloud-translate

Após, utilizaramos a SDK do Translate para criar a função wrapper como abaixo:

# definição do client da SDK da Cloud Translation API
from google.cloud import translate_v3 as translate
client = translate.TranslationServiceClient()


# funçãp que interage com Cloud Translation API
def doTranslate(text, target_language):
project_id = !gcloud config list | grep 'project ='
parent = f'projects/' + project_id[2].split('= ')[1]
translation = client.translate_text(
request={
"parent": parent,
"contents": [text],
"mime_type": "text/plain",
"target_language_code": target_language
}).translations[0]
return(translation.translated_text)

Com isso, podemos repetir o último teste que fizemos, da tarefa conversacional e perguntando sobre o peso de celulares e de lápis, mas desta vez com conteúdo em português:

chat_model = ChatModel.from_pretrained("chat-bison@001")
chat = chat_model.start_chat()

# utilizando o prompt do modelo com a tradução de ptbr -> en
prompt = doTranslate("""
Qual é o peso médio de um aparelho celular?
""", 'en')

# avaliando o resultado com a tradução de en -> ptbr
print(doTranslate(chat.send_message(prompt).text, 'pt'))

O resultado será como abaixo:

O peso médio de um telefone celular é de 200 gramas. No entanto, o peso dos 
telefones celulares pode variar dependendo do tamanho, tipo e recursos do
telefone. Por exemplo, um smartphone grande com muitos recursos pode pesar
mais do que um telefone pequeno e básico.

E ainda conseguimos manter o contexto da conversa como fizemos com a interação puramente em inglês:

prompt = doTranslate("""
Isso é mais leve ou mais pesado que um lápis comum?
""", 'en')
print(doTranslate(chat.send_message(prompt).text, 'pt'))

E a resposta:

O peso médio de um lápis comum é de 2,5 gramas. O peso médio de um telefone 
celular é de 200 gramas. Portanto, um telefone celular é mais pesado que um
lápis comum.

Pronto!! Chegando até aqui você:

  • Conheceu os serviços de Generative AI disponibilizados na Google Cloud no Google I/O 2023
  • Revisou os conceitos básicos ao redor da área de Generative AI
  • Visualizou as diferences API do Generative AI Studio
  • Incluiu mecanismos de tradução para utilizar o português brasileiro durante o public preview

Legal, como começo a experimentar?

Todas as API que utilizamos aqui já estão disponíveis em todos os projetos de Google Cloud e, durante o período de public preview, sem custos para utilização (como pode ser verificado na página de preços da Vertex AI).

Para facilitar os experimentos, nós do time de Developer Relations criamos um repositório no GitHub chamado “/generative-ai”, onde há exemplos de vários cenários de linguagem natural (conversacionais, extração de informações de textos, sumarização de conteúdos, etc).

Não possui ainda uma conta em Google Cloud? Crie sua conta gratuitamente e tenha acesso ao crédito de “novo usuário”.

Participa de comunidades? Melhor ainda!! Entre em contato com o Google Developer Group mais próximo de você e quem sabe não conseguimos criar um workshop gratuito para as pessoas da sua região?

Obrigado por chegarem até aqui e um grande abraço! Qualquer dúvida, estou a uma mensagem de distância no Twitter ou no LinkedIn 🙂

--

--