Desenvolver apps de LLM com o SDK da Vertex AI

1. Introdução

Visão geral

Você é um desenvolvedor em uma empresa de marketing de viagens. Seu departamento de vendas decidiu que precisa de um novo aplicativo de chat para acompanhar as maiores empresas de reservas e pesquisas. Eles também já ouviram falar sobre a IA generativa, mas não sabem muito sobre ela. Outros departamentos ouviram falar dessa iniciativa e estão curiosos para saber como ela também pode ajudar na experiência do cliente.

Atividades deste laboratório

Neste laboratório, você vai criar um chatbot assistente de viagens usando o modelo Gemini 2.5 Flash na Vertex AI.

O aplicativo precisa:

  • Ajuda os usuários a fazer perguntas sobre viagens, reservar viagens e saber mais sobre os lugares que eles planejam visitar.
  • Oferece aos usuários maneiras de receber ajuda sobre planos de viagem específicos
  • Ser capaz de buscar dados em tempo real, como clima, usando ferramentas

Você vai trabalhar em um ambiente pré-configurado do Google Cloud, especificamente no editor do Cloud Shell. Um front-end de aplicativo Web básico já está configurado para você, junto com as permissões necessárias para acessar a Vertex AI. Este app foi criado usando o Streamlit.

O que você vai aprender

Neste laboratório, você aprenderá a fazer o seguinte:

2. Configurar o projeto

Conta do Google

Se você ainda não tiver uma Conta do Google pessoal, crie uma.

Use uma conta pessoal em vez de uma conta escolar ou de trabalho.

Faça login no console do Google Cloud.

Faça login no console do Google Cloud usando uma Conta do Google pessoal.

Ativar faturamento

Resgatar US $5 em créditos do Google Cloud (opcional)

Para fazer este workshop, você precisa de uma conta de faturamento com algum crédito. Se você planeja usar seu próprio faturamento, pule esta etapa.

  1. Clique neste link e faça login com uma Conta do Google pessoal.Você vai ver algo assim:Clique para autorizar o Cloud Shell
  2. Clique no botão CLIQUE AQUI PARA ACESSAR SEUS CRÉDITOS. Isso vai abrir uma página para configurar seu perfil de faturamentoClique para autorizar o Cloud Shell.
  3. Clique em Confirmar.

Agora você está conectado a uma conta de faturamento de avaliação do Google Cloud Platform.

Captura de tela da visão geral do faturamento

Configurar uma conta de faturamento pessoal

Se você configurou o faturamento usando créditos do Google Cloud, pule esta etapa.

Para configurar uma conta de faturamento pessoal, acesse este link para ativar o faturamento no console do Cloud.

Algumas observações:

  • A conclusão deste laboratório custa menos de US $1 em recursos do Cloud.
  • Siga as etapas no final deste laboratório para excluir recursos e evitar mais cobranças.
  • Novos usuários podem aproveitar a avaliação sem custos financeiros de US$300.

Criar um projeto (opcional)

Se você não tiver um projeto atual que gostaria de usar para este laboratório, crie um novo aqui.

3. Abrir editor do Cloud Shell

  1. Clique neste link para navegar diretamente até o editor do Cloud Shell.
  2. Se for preciso autorizar em algum momento, clique em Autorizar para continuar.Clique para autorizar o Cloud Shell
  3. Se o terminal não aparecer na parte de baixo da tela, abra-o:
    • Clique em Visualizar.
    • Clique em TerminalAbrir um novo terminal no editor do Cloud Shell.
  4. No terminal, defina o projeto com este comando:
    gcloud config set project [PROJECT_ID]
    
    • Exemplo:
      gcloud config set project lab-project-id-example
      
    • Se você não se lembrar do ID do projeto, liste todos os IDs com:
      gcloud projects list | awk '/PROJECT_ID/{print $2}'
      
      Definir o ID do projeto no terminal do Editor do Cloud Shell
  5. Você vai receber esta mensagem:
    Updated property [core/project].
    
    >aside negative Se você vir um "AVISO" e a pergunta "Quer continuar (S/N)?", provavelmente inseriu o ID do projeto incorretamente. Pressione "n", pressione "Enter" e tente executar o comando "gcloud config set project" novamente. >

4. Ativar APIs

Para usar o SDK da Vertex AI e interagir com o modelo Gemini, ative a API Vertex AI no seu projeto do Google Cloud.

  1. No terminal, ative as APIs:
    gcloud services enable \
      aiplatform.googleapis.com
    

Introdução ao SDK da Vertex AI para Python

Para interagir com modelos hospedados na Vertex AI do seu aplicativo Python, use o SDK da Vertex AI para Python. Esse SDK simplifica o processo de envio de comandos, especificação de parâmetros do modelo e recebimento de respostas sem precisar lidar diretamente com as complexidades das chamadas de API subjacentes.

Encontre a documentação completa do SDK da Vertex AI para Python aqui: Introdução ao SDK da Vertex AI para Python | Google Cloud.

5. Criar um ambiente virtual e instalar dependências

Antes de iniciar qualquer projeto em Python, é recomendável criar um ambiente virtual. Isso isola as dependências do projeto, evitando conflitos com outros projetos ou com os pacotes globais do Python do sistema.

  1. Crie uma pasta chamada wanderbot para armazenar o código do app assistente de viagem. Execute o seguinte código no terminal:
    mkdir wanderbot && cd wanderbot
    
  2. Crie e ative um ambiente virtual:
    uv venv --python 3.12
    source .venv/bin/activate
    
    Você vai ver o prefixo (wanderbot) no comando do terminal, indicando que o ambiente virtual está ativo. Ele ficaria assim:

    uma captura de tela do terminal com um ambiente virtual ativo

6. Criar arquivos iniciais para wanderbot

  1. Crie e abra um novo arquivo app.py para o aplicativo. Execute o seguinte código no terminal:
    cloudshell edit app.py
    
    O comando cloudshell edit vai abrir o arquivo app.py no editor acima do terminal.
  2. Cole o seguinte código inicial do app em app.py:
    import streamlit as st
    from google import genai
    from google.genai import types
    import requests
    import logging
    
    # --- Defining variables and parameters  ---
    REGION = "global"
    PROJECT_ID = None # TO DO: Insert Project ID
    GEMINI_MODEL_NAME = "gemini-2.5-flash"
    
    temperature = .2
    top_p = 0.95
    
    system_instructions = None
    
    # --- Tooling ---
    # TODO: Define the weather tool function declaration
    
    # TODO: Define the get_current_temperature function
    
    
    # --- Initialize the Vertex AI Client ---
    try:
        # TODO: Initialize the Vertex AI client
    
        print(f"VertexAI Client initialized successfully with model {GEMINI_MODEL_NAME}")
    except Exception as e:
        st.error(f"Error initializing VertexAI client: {e}")
        st.stop()
    
    
    # TODO: Add the get_chat function here in Task 15.
    
    
    # --- Call the Model ---
    def call_model(prompt: str, model_name: str) -> str:
        """
        This function interacts with a large language model (LLM) to generate text based on a given prompt and system instructions. 
        It will be replaced in a later step with a more advanced version that handles tooling.
        """
        try:
    
            # TODO: Prepare the content for the model
    
            # TODO: Define generate_content configuration (needed for system instructions and parameters)
    
            # TODO: Define response
    
            logging.info(f"[call_model_response] LLM Response: \"{response.text}\"")
            # TODO: Uncomment the below "return response.text" line
            # return response.text
    
        except Exception as e:
            return f"Error: {e}"
    
    
    # --- Presentation Tier (Streamlit) ---
    # Set the title of the Streamlit application
    st.title("Travel Chat Bot")
    
    # Initialize session state variables if they don't exist
    if "messages" not in st.session_state:
        # Initialize the chat history with a welcome message
        st.session_state["messages"] = [
            {"role": "assistant", "content": "How can I help you today?"}
        ]
    
    # Display the chat history
    for msg in st.session_state.messages:
        st.chat_message(msg["role"]).write(msg["content"])
    
    # Get user input
    if prompt := st.chat_input():
        # Add the user's message to the chat history
        st.session_state.messages.append({"role": "user", "content": prompt})
        # Display the user's message
        st.chat_message("user").write(prompt)
    
        # Show a spinner while waiting for the model's response
        with st.spinner("Thinking..."):
            # Get the model's response using the call_model function
            model_response = call_model(prompt, GEMINI_MODEL_NAME)
            # Add the model's response to the chat history
            st.session_state.messages.append(
                {"role": "assistant", "content": model_response}
            )
            # Display the model's response
            st.chat_message("assistant").write(model_response)
    
  3. Crie e abra um novo arquivo requirements.txt para o código do aplicativo. Execute o seguinte código no terminal:
    cloudshell edit requirements.txt
    
    O comando cloudshell edit vai abrir o arquivo requirements.txt no editor acima do terminal.
  4. Cole o seguinte código inicial do app em requirements.txt.
    google-genai
    streamlit
    requests
    
  5. Instale as dependências obrigatórias do Python para este projeto. Execute o seguinte código no terminal:
    uv pip install -r requirements.txt
    

7. Explorar o código

Os arquivos criados incluem um front-end de aplicativo de chat básico. Veja alguns exemplos:

  • app.py: este é o arquivo em que vamos trabalhar. No momento, ele contém o seguinte:
    • importações necessárias
    • variáveis de ambiente e parâmetros (alguns deles são marcadores)
    • uma função call_model vazia, que vamos preencher
    • Código do Streamlit para o app de chat front-end
  • requirements.txt:
    • inclui os requisitos de instalação para executar app.py

Agora, vamos analisar o código.

Abrir o chat do Gemini Code Assist

O chat do Gemini Code Assist já deve estar aberto em um painel à direita no editor do Cloud Shell. Se o chat do Gemini Code Assist ainda não estiver aberto, siga estas etapas:

  1. Clicando no botão do Gemini Code Assist (Clique aqui para ativar o Gemini Code Assist) perto da parte de cima da tela.
  2. Selecione Abrir o chat do Gemini Code Assist.Menu do Gemini Code Assist

Usar o Gemini Code Assist para entender o código

Use a conversa do Gemini Code Assist para entender melhor o código.

  1. Destaque ou selecione a seção de código desejada.
  2. Digite "Explique este código" no chat do Gemini.
  3. Clique em "Enter" para enviar

Um vídeo que mostra como destacar uma parte do código, passar "Explique isso" para o Gemini Code Assist e receber uma resposta.

8. Iniciar o webapp

Antes de conectar esse app a um LLM, inicie-o para ver como ele se comporta inicialmente.

  1. No diretório wanderbot, execute o seguinte comando no terminal para iniciar o aplicativo Streamlit e torná-lo acessível localmente no ambiente do Cloud Shell:
    streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080
    
    Mantenha essa janela do terminal aberta, porque o aplicativo Streamlit vai continuar sendo executado. Você pode abrir uma nova janela de terminal no Cloud Shell para executar outros comandos.
  2. Depois de executar o comando, clique no botão Visualização da Web na parte de cima do editor do Cloud Shell e selecione Visualizar na porta 8080.
    o menu de visualização aberto, com

    Uma interface de chat simples vai aparecer para seu app de viagens.
  3. Digite qualquer mensagem (por exemplo, Hi!) e pressione ENTER.

    A mensagem vai aparecer no histórico de chat, mas você vai receber uma mensagem de erro em vez de uma resposta do assistente. Isso ocorre porque o aplicativo ainda não está conectado a um modelo de linguagem grande. Observe esse comportamento para entender o ponto de partida do laboratório.

9. Inicializar o cliente da Vertex AI

Conhecer os modelos disponíveis na Vertex AI

A plataforma Vertex AI do Google Cloud oferece acesso a vários modelos de IA generativa. Antes de integrar uma, confira as opções disponíveis no console do Google Cloud.

  1. No console do Google Cloud, navegue até o Model Garden. Para isso, pesquise "Model Garden" na barra de pesquisa na parte de cima da tela e selecione Vertex AI.(programas )
  2. Navegue pelos modelos disponíveis. É possível filtrar por modalidades, tipos de tarefas e recursos, entre outros.

Para este laboratório, você vai usar o modelo Gemini 2.5 Flash, que é uma boa opção para criar aplicativos de chat responsivos devido à velocidade.

Inicializar o cliente da Vertex AI

Agora, modifique a seção --- Initialize the Vertex AI Client --- em app.py para inicializar o cliente da Vertex AI. Esse objeto cliente será usado para enviar comandos ao modelo.

  1. Abra app.py no editor do Cloud Shell.
  2. Em app.py, encontre a linha PROJECT_ID = None.
  3. Substitua None pelo ID do projeto do Google Cloud entre aspas. (por exemplo, PROJECT_ID = "google-cloud-labs")
    Se você não se lembrar do ID do projeto, liste todos os IDs com:
    gcloud projects list | awk '/PROJECT_ID/{print $2}'
    
  4. Defina o cliente: dentro do bloco try, inicialize o cliente da Vertex AI.
        client = genai.Client(
            vertexai=True,
            project=PROJECT_ID,
            location=REGION,
        )
    

Inicialização atualizada do cliente da Vertex AI

Neste ponto, a seção "Inicializar o cliente da Vertex AI" ficaria assim:

# --- Initialize the Vertex AI Client ---
try:
    client = genai.Client(
        vertexai=True,
        project=PROJECT_ID,
        location=REGION,
    )
    print(f"VertexAI Client initialized successfully with model {GEMINI_MODEL_NAME}")
except Exception as e:
    st.error(f"Error initializing VertexAI client: {e}")
    st.stop()

10. Preparar dados e chamar o modelo

Agora você vai preparar o conteúdo para enviar ao modelo e fazer uma chamada para o modelo do Gemini.

  1. Encontre a seção --- Call the Model --- em que a função call_model está definida.
  2. Definir conteúdo: em # TODO: Prepare the content for the model , defina o conteúdo de entrada que será enviado ao modelo. Para uma solicitação básica, essa será a mensagem de entrada do usuário.
            contents = [prompt]
    
  3. Defina a resposta: cole este código abaixo de # TODO: Define response.
            response = client.models.generate_content(
                model=model_name,
                contents=contents,
            )
    
  4. Retorne a resposta: remova os comentários da seguinte linha:
            return response.text
    
  5. Examine a linha em que a função call_model está sendo chamada, na parte de baixo do arquivo no bloco with. Se você não entender o que está acontecendo, destaque a linha e peça para o Gemini Code Assist explicar.

Uma maneira mais explícita de definir contents

A maneira acima de definir contents funciona porque o SDK é inteligente o suficiente para entender que uma lista que contém strings representa a entrada de texto do usuário. Ele formata automaticamente de maneira correta para a API do modelo.

No entanto, a maneira mais explícita e fundamental de estruturar a entrada envolve o uso de objetos types.Part e types.Content, assim:

user_message_parts = [types.Part.from_text(text=prompt)]
contents = [
    types.Content(
        role="user", # Indicates the content is from the user
        parts=user_message_parts, # A list, allowing multiple types of content
    ),
]

Função call_model atualizada

Neste ponto, a função call_model vai ficar assim:

def call_model(prompt: str, model_name: str) -> str:
    """
    This function interacts with a large language model (LLM) to generate text based on a given prompt and system instructions. 
    It will be replaced in a later step with a more advanced version that handles tooling.
    """
    try:

        contents = [prompt]

        # TODO: Define generate_content configuration (needed later for system instructions and parameters)

        response = client.models.generate_content(
            model=model_name,
            contents=contents,
        )
        logging.info(f"[call_model_response] LLM Response: \"{response.text}\"")

        return response.text
    except Exception as e:
        return f"Error: {e}"

11. Testar o app conectado

  1. No terminal, encerre o processo em execução (CTRL+C).
  2. Execute o comando novamente para iniciar o aplicativo Streamlit.
    streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080
    
  3. Atualize o aplicativo Streamlit. Se o aplicativo Streamlit ainda estiver em execução, basta atualizar a página de visualização da Web no navegador.
  4. Agora, digite uma pergunta na entrada de chat, como:
    What is the best time of year to go to Iceland?
    
  5. Pressione ENTER.

    O aplicativo vai mostrar sua mensagem, um spinner "Pensando..." e uma resposta gerada pelo modelo do Gemini. Se sim, você conectou seu aplicativo da Web a um LLM na Vertex AI. 🙌 🥳

12. Definir instruções do sistema

Embora a conexão básica funcione, a qualidade e o estilo das respostas do LLM são muito influenciados pela entrada que ele recebe. A engenharia de comando é o processo de criar e refinar essas entradas (comandos) para orientar o modelo a gerar o resultado desejado.

Para isso, comece criando algumas instruções do sistema e transmitindo-as ao modelo.

Você vai usar o Perguntar ao Gemini para criar instruções úteis para o sistema.

  1. Em app.py, localize a variável system_instructions, que está definida como None.
    system_instructions = None
    
    Você vai substituir None por uma string de várias linhas que fornece instruções para nosso bot assistente de viagens.
  2. Pergunte ao Gemini Code Assist: envie o seguinte comando para o Gemini Code Assist (ou crie o seu próprio!):
    I am a developer at a travel marketing company, and my sales department has decided that they need a new chat application to keep up with the bigger booking and search companies. I'm building a simple travel assistant chatbot using the Gemini 2.5 Flash model on Vertex AI.
    
    The application should:
    - Helps users ask questions about travel, book travel, and learn about places they are going to go
    - Provides users ways to get help about their specific travel plans
    - Provides all this in a production quality way (multiple environments, logging and monitoring, etc.)
    
    Please create system instructions appropriate for that chat app. Be thorough.
    
    Do not alter the code in any way beyond providing me with system instructions.
    
  3. Defina system_instructions: defina system_instructions como as instruções do sistema que você gerou usando o Gemini Code Assist. Você também pode usar estas instruções do sistema, que foram criadas pelo Gemini com um comando semelhante.
    system_instructions = """
    You are a sophisticated travel assistant chatbot designed to provide comprehensive support to users throughout their travel journey. Your capabilities include answering travel-related questions, assisting with booking travel arrangements, offering detailed information about destinations, and providing support for existing travel plans.
    
    **Core Functionalities:**
    
    1.  **Travel Information and Recommendations:**
        *   Answer user inquiries about travel destinations, including popular attractions, local customs, visa requirements, weather conditions, and safety advice.
        *   Provide personalized recommendations for destinations, activities, and accommodations based on user preferences, interests, and budget.
        *   Offer insights into the best times to visit specific locations, considering factors like weather, crowds, and pricing.
        *   Suggest alternative destinations or activities if the user's initial choices are unavailable or unsuitable.
    
    2.  **Booking Assistance:**
        *   Facilitate the booking of flights, hotels, rental cars, tours, and activities.
        *   Search for available options based on user-specified criteria such as dates, destinations, budget, and preferences.
        *   Present clear and concise information about available options, including pricing, amenities, and booking terms.
        *   Guide users through the booking process, ensuring accurate information and secure transactions.
        *   Provide booking confirmations and relevant details, such as booking references and contact information.
    
    3.  **Travel Planning and Itinerary Management:**
        *   Assist users in creating detailed travel itineraries, including flights, accommodations, activities, and transportation.
        *   Offer suggestions for optimizing travel plans, such as minimizing travel time or maximizing sightseeing opportunities.
        *   Provide tools for managing and modifying existing itineraries, including adding or removing activities, changing booking dates, or upgrading accommodations.
        *   Offer reminders and notifications for upcoming travel events, such as flight check-in or tour departure times.
    
    4.  **Customer Support and Troubleshooting:**
        *   Provide prompt and helpful support to users with questions or issues related to their travel plans.
        *   Assist with resolving booking discrepancies, cancellations, or modifications.
        *   Offer guidance on travel-related emergencies, such as lost luggage or travel delays.
        *   Provide access to relevant contact information for airlines, hotels, and other travel providers.
    
    **Interaction Guidelines:**
    
    *   **Professionalism:** Maintain a polite, respectful, and professional tone in all interactions.
    *   **Clarity and Conciseness:** Provide clear, concise, and easy-to-understand information. Avoid jargon or technical terms unless necessary and always explain them.
    *   **Accuracy:** Ensure all information provided is accurate and up-to-date. Double-check details before sharing them with users. If unsure about something, admit that you don't know and offer to find the information.
    *   **Personalization:** Tailor your responses and recommendations to the specific needs and preferences of each user.
    *   **Proactive Assistance:** Anticipate user needs and offer relevant information or suggestions proactively.
    *   **Error Handling:** Gracefully handle user errors or misunderstandings. Provide helpful guidance and alternative options when necessary.
    *   **Confidentiality:** Respect user privacy and handle personal information with the utmost confidentiality and in compliance with data protection regulations.
    
    **Example Interactions:**
    
    **User:** "I want to go on a beach vacation in the Caribbean. I have a budget of $2000 per person for a week."
    **Chatbot:** "Certainly! The Caribbean offers many beautiful beach destinations within your budget. Some popular options include Punta Cana in the Dominican Republic, Cancun in Mexico, and Montego Bay in Jamaica. These destinations offer stunning beaches, all-inclusive resorts, and various activities. Would you like me to search for flights and accommodations for these locations based on your travel dates?"
    
    **User:** "My flight is delayed. What should I do?"
    **Chatbot:** "I'm sorry to hear about the delay. Please check with the airline for the updated departure time and any assistance they can offer. You may be entitled to compensation or rebooking options depending on the length of the delay and the airline's policy. Do you have your flight number handy so I can look up the current status for you?"
    
    **User:** "Tell me about the best time to visit Japan."
    **Chatbot:** "Japan is a fantastic destination with distinct seasons offering unique experiences. Spring (March-May) is famous for the beautiful cherry blossoms, while autumn (September-November) boasts stunning fall foliage. Both seasons have pleasant temperatures, making them ideal for sightseeing. Summer (June-August) can be hot and humid, but it's a great time for festivals and outdoor activities in the mountains. Winter (December-February) offers opportunities for skiing and snowboarding in the Japanese Alps, though some areas may experience heavy snowfall. To recommend the best time for you, could you tell me what you'd like to experience in Japan?"
    
    By following these instructions, you will be able to provide exceptional travel assistance and create a positive experience for every user.
    """
    
  4. Defina a configuração generate_content:inicialize um objeto de configuração, ao qual você vai transmitir essas instruções do sistema. Como system_instructions é definido globalmente no nosso script, a função pode acessá-lo diretamente.
            generate_content_config = types.GenerateContentConfig(
                system_instruction=[
                    types.Part.from_text(text=system_instructions)
                ],
            )
            logging.info(f"[generate_config_details] System Instruction: {generate_content_config.system_instruction[0].text}")
    
  5. Para adicionar as instruções do sistema à resposta, adicione um parâmetro config ao método generate content e defina-o como igual ao objeto generate_content_config criado acima.
            response = client.models.generate_content(
                model=model_name,
                contents=contents,
                config=generate_content_config, # This is the new line
            )
    

Função call_model atualizada

A função call_model completa agora fica assim:

def call_model(prompt: str, model_name: str) -> str:
    """
    This function interacts with a large language model (LLM) to generate text based on a given prompt and system instructions. 
    It will be replaced in a later step with a more advanced version that handles tooling.
    """
    try:
        contents = [prompt]

        generate_content_config = types.GenerateContentConfig(
            system_instruction=[
                types.Part.from_text(text=system_instructions)
            ],
        )
        logging.info(f"[generate_config_details] System Instruction: {generate_content_config.system_instruction[0].text}")
        response = client.models.generate_content(
            model=model_name,
            contents=contents,
            config=generate_content_config,
        )

        logging.info(f"[call_model_response] LLM Response: \"{response.text}\"")
        
        return response.text
    except Exception as e:
        return f"Error: {e}"

13. Testar o app com instruções do sistema

  1. No terminal, encerre o processo em execução (CTRL+C).
  2. Execute o comando novamente para iniciar o aplicativo Streamlit.
    streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080
    
  3. Atualize o aplicativo Streamlit. Se o aplicativo Streamlit ainda estiver em execução, basta atualizar a página de visualização da Web no navegador.
  4. Faça a mesma pergunta de antes:
    What is the best time of year to go to Iceland?
    
  5. Pressione ENTER.
    Compare como ele responde desta vez em relação à última vez.

14. Definir uma ferramenta de clima

Até agora, nosso chatbot tem conhecimento, mas ele é limitado aos dados com que foi treinado. Ele não pode acessar informações em tempo real. Para um bot de viagens, poder buscar dados em tempo real, como previsões do tempo, é uma grande vantagem.

É aí que entra o conjunto de ferramentas, também conhecido como chamada de função. É possível definir um conjunto de ferramentas (funções Python) que o LLM pode chamar para receber informações externas.

Como as ferramentas funcionam

  1. Descrevemos nossas ferramentas para o modelo, incluindo o que elas fazem e quais parâmetros usam.
  2. O usuário envia um comando (por exemplo, Qual é a previsão do tempo em Londres?").
  3. O modelo recebe o comando e percebe que o usuário está perguntando sobre algo que ele pode descobrir usando uma das ferramentas.
  4. Em vez de responder com texto, o modelo responde com um objeto function_call especial, indicando qual ferramenta ele quer chamar e com quais argumentos.
  5. Nosso código Python recebe esse function_call, executa a função get_current_temperature real com os argumentos fornecidos e recebe o resultado (por exemplo, 15°C).
  6. Enviamos esse resultado de volta ao modelo.
  7. O modelo recebe o resultado e gera uma resposta em linguagem natural para o usuário (por exemplo, A temperatura atual em Londres é de 15 °C.

Esse processo permite que o modelo responda a perguntas muito além dos dados de treinamento, tornando-o um assistente muito mais eficiente e útil.

Definir uma ferramenta de clima

Se um viajante estiver procurando conselhos sobre o que fazer e escolhendo entre atividades afetadas pelo clima, uma ferramenta de previsão do tempo pode ser útil. Vamos criar uma ferramenta para que nosso modelo receba a previsão do tempo atual. Precisamos de duas partes: uma declaração de função que descreve a ferramenta para o modelo e a função Python real que a implementa.

  1. Em app.py, encontre o comentário # TODO: Define the weather tool function declaration.
  2. Abaixo desse comentário, adicione a variável weather_function. É um dicionário que informa ao modelo tudo o que ele precisa saber sobre a finalidade, os parâmetros e os argumentos obrigatórios da função.
    weather_function = {
        "name": "get_current_temperature",
        "description": "Gets the current temperature for a given location.",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "The city name, e.g. San Francisco",
                },
            },
            "required": ["location"],
        },
    }
    
  3. Em seguida, encontre o comentário # TODO: Define the get_current_temperature function. Abaixo dele, adicione o seguinte código Python. Essa função vai:
    • Chame uma API Geocoding para receber as coordenadas do local.
    • Use essas coordenadas para chamar uma API de clima.
    • Retorne uma string simples com a temperatura e a unidade.
    def get_current_temperature(location: str) -> str:
        """Gets the current temperature for a given location."""
    
        try:
            # --- Get Latitude and Longitude for the location ---
            geocode_url = f"https://geocoding-api.open-meteo.com/v1/search?name={location}&count=1&language=en&format=json"
            geocode_response = requests.get(geocode_url)
            geocode_data = geocode_response.json()
    
            if not geocode_data.get("results"):
                return f"Could not find coordinates for {location}."
    
            lat = geocode_data["results"][0]["latitude"]
            lon = geocode_data["results"][0]["longitude"]
    
            # --- Get Weather for the coordinates ---
            weather_url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}&current_weather=true"
            weather_response = requests.get(weather_url)
            weather_data = weather_response.json()
    
            temperature = weather_data["current_weather"]["temperature"]
            unit = "°C"
    
            return f"{temperature}{unit}"
    
        except Exception as e:
            return f"Error fetching weather: {e}"
    

15. Refatoração para chat e ferramentas

Nossa função call_model atual usa uma chamada generate_content simples e única. Isso é ótimo para perguntas únicas, mas não é ideal para uma conversa dividida em vários turnos, principalmente uma que envolve troca de informações para ferramentas.

Uma prática melhor é usar uma sessão de chat, que mantém o contexto da conversa. Agora vamos refatorar nosso código para usar uma sessão de chat, que é necessária para implementar corretamente as ferramentas.

  1. Exclua a função call_model atual. Vamos substituí-lo por uma versão mais avançada.
  2. Em vez disso, adicione a nova função call_model do bloco de código abaixo. Essa nova função contém a lógica para processar o loop de chamada de ferramenta que discutimos anteriormente. Ele tem vários comentários TODO que vamos concluir nas próximas etapas.
    # --- Call the Model ---
    def call_model(prompt: str, model_name: str) -> str:
        """
        This function interacts with a large language model (LLM) to generate text based on a given prompt.
        It maintains a chat session and handles function calls from the model to external tools.
        """
        try:
            # TODO: Get the existing chat session or create a new one.
    
            message_content = prompt
    
            # Start the tool-calling loop
            while True:
                # TODO: Send the message to the model.
    
                # Check if the model wants to call a tool
                has_tool_calls = False
                for part in response.candidates[0].content.parts:
                    if part.function_call:
                        has_tool_calls = True
                        function_call = part.function_call
                        logging.info(f"Function to call: {function_call.name}")
                        logging.info(f"Arguments: {function_call.args}")
    
                        # TODO: Call the appropriate function if the model requests it.
    
                # If no tool call was made, break the loop
                if not has_tool_calls:
                    break
    
            # TODO: Return the model's final text response.
    
        except Exception as e:
            return f"Error: {e}"
    
  3. Agora, vamos adicionar uma função auxiliar para gerenciar a sessão de chat. Acima da nova função call_model, adicione a função get_chat. Essa função vai criar uma nova sessão de chat com nossas instruções do sistema e definições de ferramentas ou recuperar uma sessão existente. Essa é uma boa prática para organizar o código.
    def get_chat(model_name: str):
        if f"chat-{model_name}" not in st.session_state:
    
            # TODO: Define the tools configuration for the model
    
            # TODO: Define the generate_content configuration, including tools
    
            # TODO: Create a new chat session
    
            st.session_state[f"chat-{model_name}"] = chat
        return st.session_state[f"chat-{model_name}"]
    

Agora você configurou o scaffolding para nossa lógica de chat avançada e habilitada para ferramentas.

16. Implementar a lógica de chamada de função

Agora, vamos preencher o TODOs para que a lógica de chamada de função fique totalmente funcional.

Implemente o get_chat.

  1. Na função get_chat, abaixo do comentário # TODO: Define the tools configuration..., defina o objeto tools criando uma instância types.Tool da nossa declaração weather_function.
            tools = types.Tool(function_declarations=[weather_function])
    
  2. Em # TODO: Define the generate_content configuration..., defina generate_content_config e transmita o objeto tools ao modelo. É assim que o modelo aprende sobre as ferramentas que pode usar.
            generate_content_config = types.GenerateContentConfig(
                system_instruction=[types.Part.from_text(text=system_instructions)],
                tools=[tools] # Pass the tool definition here
            )
    
  3. Em # TODO: Create a new chat session, crie o objeto de chat usando client.chats.create(), transmitindo o nome e a configuração do modelo.
            chat = client.chats.create(
                model=model_name,
                config=generate_content_config,
            )
    

Implemente o call_model.

  1. Em # TODO: Get the existing chat session... na função call_model, chame a nova função auxiliar get_chat.
            chat = get_chat(model_name)
    
  2. Em seguida, encontre # TODO: Send the message to the model. Envie a mensagem do usuário usando o método chat.send_message().
                response = chat.send_message(message_content)
    
  3. Localize a # TODO: Call the appropriate function.... É aqui que verificamos qual função o modelo quer e a executamos.
                    if function_call.name == "get_current_temperature":
                      result = get_current_temperature(**function_call.args)
                    function_response_part = types.Part.from_function_response(
                        name=function_call.name,
                        response={"result": result},
                    )
                    message_content = [function_response_part]
  1. Por fim, encontre # TODO: Return the model's final text response e adicione a instrução de retorno.
            return response.text
    

Função get_chat atualizada

A função get_chat atualizada vai ficar assim:

def get_chat(model_name: str):
    if f"chat-{model_name}" not in st.session_state:
        #Tools
        tools = types.Tool(function_declarations=[weather_function])

        # Initialize a confiburation object
        generate_content_config = types.GenerateContentConfig(
            system_instruction=[types.Part.from_text(text=system_instructions)],
            tools=[tools]
        )
        chat = client.chats.create(
            model=model_name,
            config=generate_content_config,
        )
        st.session_state[f"chat-{model_name}"] = chat
    return st.session_state[f"chat-{model_name}"]

Função call_model atualizada

A função call_model atualizada vai ficar assim:

def call_model(prompt: str, model_name: str) -> str:
    try:
        chat = get_chat(model_name)
        message_content = prompt
        
        while True:
            response = chat.send_message(message_content)
            has_tool_calls = False
            for part in response.candidates[0].content.parts:
                if part.function_call:
                    has_tool_calls = True
                    function_call = part.function_call
                    logging.info(f"Function to call: {function_call.name}")
                    logging.info(f"Arguments: {function_call.args}")
                    if function_call.name == "get_current_temperature":
                        result = get_current_temperature(**function_call.args)
                        function_response_part = types.Part.from_function_response(
                            name=function_call.name,
                            response={"result": result},
                        )
                        message_content = [function_response_part]
                elif part.text:
                    logging.info("No function call found in the response.")
                    logging.info(response.text)

            if not has_tool_calls:
                break

        return response.text

    except Exception as e:
        return f"Error: {e}"

17. Testar o app com a ferramenta ativada

Vamos conferir seu novo recurso em ação!

  1. No terminal, encerre o processo em execução (CTRL+C).
  2. Execute o comando novamente para iniciar o aplicativo Streamlit.
    streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080
    
  3. Atualize o aplicativo Streamlit. Se o aplicativo Streamlit ainda estiver em execução, basta atualizar a página de visualização da Web no navegador.
  4. Agora, faça uma pergunta que acione a nova ferramenta, como:
    I'm looking for something to do in New York today. What do you recommend? Would it be a good day to go to Ellis Island?
    
  5. Pressione ENTER
    Compare essa resposta com as anteriores. O que há de diferente?
    Você vai receber uma resposta que incorpora a temperatura da sua função. Verifique também o terminal do Cloud Shell. Você vai encontrar instruções de impressão confirmando que a função Python foi executada.

18. Refinar a saída do modelo com parâmetros

Bom trabalho! Seu assistente de viagem agora pode usar ferramentas para buscar dados externos em tempo real, o que o torna muito mais eficiente.

Agora que melhoramos o que nosso modelo pode fazer, vamos ajustar a forma como ele responde. Com os parâmetros do modelo, você controla o estilo e a aleatoriedade do texto gerado pelo LLM. Ao ajustar essas configurações, você pode tornar a saída do bot mais focada e determinista ou mais criativa e variada.

Neste laboratório, vamos nos concentrar em temperature e top_p. Consulte GenerateContentConfig na referência da API para ver uma lista completa de parâmetros configuráveis e as descrições deles.

  • temperature: controla a aleatoriedade da saída. Um valor menor (mais próximo de 0) torna a saída mais determinista e focada, enquanto um valor maior (mais próximo de 2) aumenta a aleatoriedade e a criatividade. Para um bot de perguntas e respostas ou assistente, geralmente é preferível uma temperatura mais baixa para respostas mais consistentes e factuais.
  • top_p: a probabilidade cumulativa máxima de tokens a serem considerados na amostragem. Os tokens são classificados com base nas probabilidades atribuídas para que apenas os mais prováveis sejam considerados. O modelo considera os tokens mais prováveis, com probabilidades que somam o valor top_p. Um valor menor restringe as opções de token, resultando em uma saída menos variada.

Parâmetros de chamada

  1. Encontre as variáveis temperature e top_p, definidas na parte de cima de app.py. Observe que eles ainda não foram chamados em nenhum lugar.
  2. Adicione temperature e top_p aos parâmetros definidos em GenerateContentConfig na função call_model.
            generate_content_config = types.GenerateContentConfig(
                temperature=temperature,
                top_p=top_p,
                system_instruction=[types.Part.from_text(text=system_instructions)],
                tools=[tools] # Pass the tool definition here
            )
    
    

Função get_chat atualizada

O app get_chat agora vai ficar assim:

def get_chat(model_name: str):
    if f"chat-{model_name}" not in st.session_state:
        #Tools
        tools = types.Tool(function_declarations=[weather_function])

        # Initialize a confiburation object
        generate_content_config = types.GenerateContentConfig(
            temperature=temperature,
            top_p=top_p,
            system_instruction=[types.Part.from_text(text=system_instructions)],
            tools=[tools] 
        )
        chat = client.chats.create(
            model=model_name,
            config=generate_content_config,
        )
        st.session_state[f"chat-{model_name}"] = chat
    return st.session_state[f"chat-{model_name}"]

19. Testar com parâmetros do modelo

  1. No terminal, encerre o processo em execução (CTRL+C).
  2. Execute o comando novamente para iniciar o aplicativo Streamlit.
    streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080
    
  3. Atualize o aplicativo Streamlit. Se o aplicativo Streamlit ainda estiver em execução, basta atualizar a página de visualização da Web no navegador.
  4. Tente fazer a mesma pergunta de antes.
    I'm looking for something to do in New York today. What do you recommend? Would it be a good day to go to Ellis Island?
    
  5. Pressione ENTER
    Compare essa resposta com as anteriores.

20. Parabéns!

Você atualizou seu aplicativo de perguntas e respostas com ferramentas, um recurso avançado que permite que seu app com tecnologia do Gemini interaja com sistemas externos e acesse informações em tempo real.

Continuação do experimento

Há muitas opções para continuar otimizando seu comando. Confira algumas opções:

  • Ajuste temperature e top_p e veja como isso muda a resposta do LLM.
  • Consulte GenerateContentConfig na referência da API para ver uma lista completa de parâmetros configuráveis e as descrições deles. Tente definir mais parâmetros e ajuste-os para ver o que acontece.

Recapitulação

Neste laboratório, você:

  • Usou o Editor do Cloud Shell e o terminal para desenvolvimento.
  • Usou o SDK da Vertex AI para Python para conectar seu aplicativo a um modelo do Gemini.
  • Aplicamos instruções do sistema e parâmetros de modelo para orientar as respostas do LLM.
  • Aprendi o conceito de ferramentas (chamada de função) e os benefícios delas.
  • Refatorou seu código para usar uma sessão de chat com estado, uma prática recomendada para IA de conversação.
  • Definir uma ferramenta para o modelo usando uma declaração de função.
  • Implementou a função Python para fornecer a lógica da ferramenta.
  • Escreveu o código para processar as solicitações de chamada de função do modelo e retornar os resultados.