2
respostas

Agent React

# 1 - Instale os pacotes necessários e importe módulos essenciais (OS, RE, Google, Langgraph, Typing).
%pip install -U google-generativeai
%pip install google-ai-generativelanguage==0.6.15
%pip install -U langchain-google-genai
%pip install -U langchain-community
%pip install -U langgraph


# 2 - Configure as API Keys utilizando arquivo .env (ou Secrets no Colab) e teste o acesso com um exemplo "Hello World".
# arquivo .env
GOOGLE_API_KEY = "meu código"
GEMINI_API_KEY = "meu código"

import os
from dotenv import load_dotenv
import google.generativeai as genai 

load_dotenv()

os.environ['GOOGLE_API_KEY'] = os.getenv('GEMINI_API_KEY')
genai.configure(api_key=os.getenv('GOOGLE_API_KEY'))

model = genai.GenerativeModel('gemini-2.5-flash')
response = model.generate_content("Hello world")

# 3 - Desenvolva a classe do agente, definindo atributos de sistema, histórico e as funções call e executar.

client = genai.GenerativeModel('gemini-2.5-flash')

class Agent:
    def __init__(self, system=""):
        self.system = system
        self.messages = []
        if self.system:
            self.messages.append({"role": "system", "content": system})

    def __call__(self, message):
        self.messages.append({"role": "user", "content": message})
        result = self.execute()
        self.messages.append({"role": "assistant", "content": result})
        return result

    def execute(self):
        # Constrói o prompt com todo o histórico de mensagens
        prompt = ""
        for msg in self.messages:
            prompt += f"{msg['role']}: {msg['content']}\n"
        
        # Envia para o Gemini
        response = client.generate_content(prompt)
        return response.text
    

if __name__ == "__main__":
    agent = Agent(system="Você é um assistente útil e objetivo.")
    print(agent("Qual é a capital da Alemanha?"))



# 4 - Elabore um prompt baseado no ciclo: pensamento, ação, pausa e observação.

PROMPT_REACT = """
Você funciona em um ciclo de Pensamento, Ação, Pausa e Observação.
Ao final do ciclo, você fornece uma Resposta.
Use "Pensamento" para descrever seu raciocínio.
Use "Ação" para executar ferramentas - e então retorne "PAUSA".
A "Observação" será o resultado da ação executada.
Ações disponíveis:
  - consultar_estoque: retorna a quantidade disponível de um item no inventário (ex: "consultar_estoque: parafuso")
  - consultar_preco_produto: retorna o preço unitário de um produto (ex: "consultar_preco_produto: martelo")

Exemplo:
Pergunta: Quantos parafuso temos em estoque?
Pensamento: Devo consultar a ação consultar_estoque para saber a quantidade de parafuso.
Ação: consultar_estoque: parafuso
PAUSA

Observação: Temos 75 parafusos em estoque.
Resposta: Há 75 parafusos em estoque.
""".strip()




# 5 - Implemente as ferramentas para consulta de estoque e preço, com tratamento para itens inexistentes.

def consultar_estoque(item: str) -> str:
    """
    Simula a consulta de estoque de um item no inventário.
    """
    item = item.lower()
    estoque = {
        "parafuso": 1000,
        "prego": 3000,
        "martelo": 80,
        "alicate": 40,
        "serrote": 60,
        "cano": 200
    }

    if item in estoque:
        return f"Temos {estoque[item]} {item}s em estoque."
    else:
        return f"Item '{item}' não encontrado no inventário."

def consultar_preco_produto(produto: str) -> str:
    """
    Simula a consulta do preço unitário de um produto.
    """
    produto = produto.lower()
    precos = {
        "parafuso": 1.00,
        "prego": 0.50,
        "martelo": 150.00,
        "alicate": 120.00,
        "serrote": 180.00,
        "cano": 25.00
    }

    if produto in precos:
        return f"O preço de um(a) {produto} é R$ {precos[produto]:.2f}."
    else:
        return f"Produto '{produto}' não encontrado na lista de preços."


2 respostas
# 6 - Acrescente funções adicionais para identificar o produto mais caro e calcular o valor total de uma lista.

def ferramenta_encontrar_produto_mais_caro() -> str: 
    """
    Retorna o nome e o preço do produto mais caro no inventário.
    """
    
    precos_do_inventario = {
        "parafuso": 1.00,
        "prego": 0.50,
        "martelo": 150.00,
        "alicate": 120.00,
        "serrote": 180.00,
        "cano": 25.00
    }

    if not precos_do_inventario: 
        return "Nenhum produto encontrado na lista de preços para comparação."

    
    nome_produto_mais_caro = max(precos_do_inventario, key=precos_do_inventario.get)
    valor_produto_mais_caro = precos_do_inventario[nome_produto_mais_caro]

    return f"O produto mais caro é o(a) {nome_produto_mais_caro} com preço de R$ {valor_produto_mais_caro:.2f}." 

def ferramenta_calcular_valor_total_lista(lista_itens: str) -> str:
    """
    Calcula o valor total de uma lista de itens de compra.
    Recebe uma string com itens separados por vírgula (ex: "teclado, mouse gamer, monitor").
    """
    precos_do_inventario = {
        "parafuso": 1.00,
        "prego": 0.50,
        "martelo": 150.00,
        "alicate": 120.00,
        "serrote": 180.00,
        "cano": 25.00
    }

    itens_processados = [item.strip().lower() for item in lista_itens.split(',')]

    valor_total = 0.0
    itens_nao_encontrados = []


    for item in itens_processados: 
        if item in precos_do_inventario:
            valor_total += precos_do_inventario[item]
        else:
            itens_nao_encontrados.append(item)

    resposta = f"O valor total dos itens encontrados é R$ {valor_total:.2f}."
    if itens_nao_encontrados:
        resposta += f" Os seguintes itens não foram encontrados e não foram incluídos no cálculo: {', '.join(itens_nao_encontrados)}."

    return resposta


# 7 - Integre todas as funcionalidades na função RunReactAgent e crie um loop interativo para simular conversações.

def run_react_agent(pergunta: str, max_iterations: int = 5) -> str:
    model = genai.GenerativeModel('gemini-2.5-flash')

    chat = model.start_chat(history=[])
    chat.send_message(PROMPT_REACT)

    current_prompt = pergunta

    for i in range(max_iterations):
        response = chat.send_message(current_prompt)
        response_text = response.text.strip()

        print(f"\n--- Iteração {i+1} ---")
        print(f"Modelo pensou/respondeu:\n{response_text}\n")

        response_match_final = re.search(r"Resposta:\s*(.*)", response_text, re.DOTALL)
        if response_match_final:
            return response_match_final.group(1).strip()


        match = re.search(r"Ação:\s*(\w+)(?::\s*([^\n]*))?", response_text)

        if match:
            action_name = match.group(1).strip()
            action_arg = match.group(2).strip() if match.group(2) is not None else ""

            observacao_da_acao = ""

            if action_name == "consultar_estoque":
                observacao_da_acao = consultar_estoque(action_arg)
            elif action_name == "consultar_preco_produto":
                observacao_da_acao = consultar_preco_produto(action_arg)
            elif action_name == "encontrar_produto_mais_caro":
                observacao_da_acao = ferramenta_encontrar_produto_mais_caro()
            elif action_name == "calcular_valor_total_lista":
                observacao_da_acao = ferramenta_calcular_valor_total_lista(action_arg)
            else:
                observacao_da_acao = f"Erro: Ação '{action_name}' desconhecida. Verifique o prompt ou a implementação da ferramenta."

            current_prompt = f"Observação: {observacao_da_acao}"

            print(f"Executou ação: {action_name} com argumento '{action_arg}'")
            print(f"Observação: {observacao_da_acao}\n")

        else:
            return f"Erro: O agente não conseguiu extrair uma Ação ou Resposta final após {i+1} iterações. Última resposta do modelo: {response_text}"

    return "Erro: Limite máximo de iterações atingido sem uma resposta final do agente."

Oi, Ricardo! Como vai?

Agradeço por compartilhar seu código com a comunidade Alura.

Achei interessante como você estruturou o agente com histórico de mensagens, além de organizar bem as funções de estoque e preço. Dá para notar seu bom entendimento de como simular um agente estilo ReAct mesmo sem usar ferramentas nativas integradas.

Continue assim!

Qualquer dúvida que surgir, compartilhe no fórum. Abraços e bons estudos!

Alura Conte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!