Alura > Cursos de Inteligência Artificial > Cursos de IA para Programação > Conteúdos de IA para Programação > Primeiras aulas do curso Python e GPT: crie seu chatbot com IA

Python e GPT: crie seu chatbot com IA

Integrando a API com o front-end - Apresentação

Olá! Meu nome é André Santana e serei seu instrutor neste curso de OpenAI.

Audiodescrição: André se descreve como um homem branco, de cabelos castanhos. Possui bigode e uma barba comprida também na cor castanho. Usa um óculos de armação redonda na cor prata, veste uma camiseta azul marinho com a logo da Alura na cor branco e está sentado em uma cadeira gamer na cor preta. À direita, uma estante com livros e itens de decoração sob uma iluminação de tons roxos e azulados.

No nosso curso de construção de um chatbot com Python e OpenAI, vamos aprender a utilizar as APIs da OpenAI para conectar com o front-end em Flask, usando Python. Vamos abordar também como utilizar um contexto dinâmico para selecionar personas e documentos de forma adequada, com base nas respostas das pessoas usuárias.

Aprenderemos a gerenciar o histórico, utilizando threads (linhas de execução) e assistentes, com os novos recursos que a OpenAI tem apresentado. Além disso, veremos como utilizar functions calling para trazer para dentro da nossa aplicação desvios de processos que, naturalmente, o modelo da OpenAI seria incapaz de realizar.

Por fim, teremos um exercício prático que vai envolver a parte de visão computacional, para garantir que o nosso chatbot seja capaz de interpretar imagens enviadas pelas pessoas usuárias.

Este curso é voltado para quem tem interesse em Python e em modelagem generativa, especialmente com a OpenAI, e já tem alguma experiência em criar projetos com a OpenAI e com lógica de programação. Recomendamos que conclua o curso anterior para aproveitar melhor este conteúdo.

Vamos aplicar todos esses assuntos em um projeto de um chatbot para um e-commerce sustentável, o EcoMart, onde vamos aprender a integrar prompts, tanto de texto quanto de imagem, para garantir que o nosso chatbot responda às pessoas usuárias de forma cada vez mais adequada e contextual.

Lembramos que, além das nossas aulas em vídeo, contamos com um conjunto de atividades e com os canais da nossa comunidade no Discord e do fórum, para que você possa aproveitar ao máximo a experiência do nosso curso. Vamos nessa?

Integrando a API com o front-end - Conectando o chatbot com o front-end

Vamos começar nosso projeto de implementação de um chatbot. Para isso, utilizaremos alguns recursos da biblioteca Flask para desenhar o front-end. Todas as partes que envolvem a dinâmica de orquestrar o que será desenhado na tela da pessoa usuária e as requisições internas do JavaScript, já estão prontas no projeto básico disponível no tópico "Preparando o ambiente".

Agora, vamos conhecer um pouco do nosso chatbot. As mensagens serão sempre apresentadas através de balões, que serão orquestrados através do uso do JavaScript junto com o Python e a API do Flask. Além disso, teremos algumas interações possíveis com a pessoa usuária.

Inicialmente, o botão de mais "+" não terá nenhuma atribuição, mas até o final deste curso adicionaremos algumas funcionalidades para poder utilizar arquivos externos dentro de um chatbot.

Nosso objetivo será implementar o envio de uma mensagem da pessoa usuária até o processo da interpretação da OpenAI, enriquecendo a capacidade de interagir com nossa pessoa usuária através de recursos distintos.

Para isso, temos um conjunto de bibliotecas necessárias para fazer essas interações junto com a OpenAI e também com o Flask. Tendo isso em vista, no arquivo app.py, importamos o Flask, a OpenAI, Dotenv e o sistema operacional, para garantir que toda essa parte inicial que envolve a construção da comunicação com a API do GPT, da OpenAI, possa ser utilizada dentro do nosso app.

Também inicializamos o próprio app do Flask, gerando uma chave para ele e definindo nossa primeira rota, que é a rota principal. Toda vez que acessarmos a URL principal, renderizaremos a página index.html.

Agora, vamos começar a implementar as mudanças necessárias para ter essa troca de comunicação entre o que a pessoa usuária envia e a própria OpenAI.

Na linha 13, após app.secret_key, vamos criar uma rota nova para o nosso app. Essa rota será gerada sempre que tivermos um caminho, que será o caminho do nosso chat.

app.secret_key = 'alura'

@app.route("/chat")

Definiremos também quais métodos serão utilizados para essa troca de mensagens. Como estaremos interagindo entre o Python, pelo Flask, junto com o JavaScript, teremos que definir qual é o tipo de método que será invocado em cada uma das interações com outra linguagem de programação.

O método que utilizaremos será o método do tipo POST. Dessa forma, toda vez que acessarmos essa rota, invocaremos um método em Python, que chamaremos de chat(). Esse método será responsável por garantir a comunicação que teremos tanto com a interação da pessoa usuária, quanto com o nosso back-end, encarregador de renderizar todas as mensagens e o comportamento visual que vimos quando estávamos no navegador, a respeito do nosso chatbot.

app.secret_key = 'alura'

@app.route("/chat", methods=["POST"])
def chat():

O primeiro passo será pegar o prompt que a pessoa usuária vai digitar. Este prompt será utilizado para encaminhar para a API e virá de uma requisição. Como são linguagens de programação diferentes, precisamos garantir que elas se comuniquem através de um intermediador comum, que será o JSON. Então, acessaremos o JSON e buscaremos a camada de mensagem, do JavaScript, para poder utilizar esse prompt.

app.secret_key = 'alura'

@app.route("/chat", methods=["POST"])
def chat():
    prompt = request.json["msg"]

Feito isso, enviaremos essa resposta para que nosso chatbot possa desenhar na tela também através do JavaScript junto com o HTML. Essa resposta virá de um método que também teremos que implementar, que será o método de bot(), onde passaremos o prompt da pessoa usuária para poder ser enviado, de fato, para o OpenAI.

app.secret_key = 'alura'

@app.route("/chat", methods=["POST"])
def chat():
    prompt = request.json["msg"]
    resposta = bot(prompt)

Então, o que acontecerá na definição de rota que temos junto com o Flask? Toda vez que tivermos uma interação de envio de uma mensagem, acionaremos essa rota de chat e ela buscará essa informação de forma assíncrona. Ou seja, tentará identificar se houve realmente um envio de mensagem pelo JavaScript, acessará essa resposta através do campo de mensagem do nosso JSON e ativará nosso bot através desse prompt, para que ele tenha uma devolutiva da resposta e possamos desenhar via JavaScript.

Para entendermos como buscamos essa informação, vamos acessar nosso explorador de arquivo, especificamente a parte de camada estática, na pasta static. Em seguida, na pasta js, acessaremos o script index.js. Nele, temos uma função assíncrona, que é a função enviarMensagem().

async function enviarMensagem() {
    if(input.value == "" || input.value == null) return;
    let mensagem = input.value;
    input.value = "";

    let novaBolha = criaBolhaUsuario();
    novaBolha.innerHTML = mensagem;
    chat.appendChild(novaBolha);

    let novaBolhaBot = criaBolhaBot();
    chat.appendChild(novaBolhaBot);
    vaiParaFinalDoChat();
    novaBolhaBot.innerHTML = "Analisando ..."
    
    // Envia requisição com a mensagem para a API do ChatBot
    const resposta = await fetch("http://127.0.0.1:5000/chat", {
        method: "POST",
        headers: {
        "Content-Type": "application/json",
        },
        body: JSON.stringify({'msg':mensagem}),
    });
    const textoDaResposta = await resposta.text();
    console.log(textoDaResposta);
    novaBolhaBot.innerHTML = textoDaResposta.replace(/\n/g, '<br>');
    vaiParaFinalDoChat();
}

Essa função criará uma bolha nova, onde toda a parte textual do chat será adicionada. Depois, o conteúdo dela é alterado para "Analisando...", enquanto o chatbot ainda não tiver respondido. Isso porque, de alguma forma, ele terá que consultar a OpenAI e até esse processo ser concluído há um certo tempo de espera.

Feito isso, buscamos uma resposta, através de uma chamada assíncrona para a rota http://127.0.0.1:5000, que é a rota do nosso servidor local, e o caminho do chat. Utilizaremos o método POST para buscar essa informação e teremos no conteúdo do texto um JSON. Todo o conteúdo que será gerado através do envio da mensagem será adicionado ao JSON no atributo msg que buscamos no Python.

Feito isso, extraímos essa informação do JSON, geramos um conteúdo novo através da variável textoDaResposta e a adicionamos no nosso innerHTML, garantindo que todas as quebras de linha que estão selecionadas sejam alteradas para br, que é a forma como o HTML utiliza para poder ter uma quebra de linha dentro de um texto sequencial.

Agora, precisamos implementar o nosso bot, que será o que faremos no próximo vídeo.

Integrando a API com o front-end - Criação do bot

Agora que já temos essa rota conectada, vamos implementar nosso método responsável por toda a orquestração de troca de mensagens entre a pessoa usuária e nosso bot.

Ainda no arquivo app.py, após app.secret_key, definiremos um novo método, que chamaremos de bot(). Esse método receberá por parâmetro o prompt do usuário.

app.secret_key = 'alura'

def bot(prompt):

Dentro deste método, vamos garantir que todo o processo de interação com o chatbot seja protegido nas ocasiões corretas, para podermos pegar essa informação durante algum tipo de erro e estabelecer comunicação com a OpenAI.

Para isso, vamos definir que teremos um número máximo de tentativas para cada interação com a pessoa usuária. Então, criaremos uma variável chamada maximo_tentativas, que começará com o valor de 1, pois nesse momento queremos apenas garantir que o chatbot tenha uma única resposta, uma única interação. Se necessário, caso seja uma operação de alto risco, podemos garantir 3 tentativas até encontrar uma resposta, por exemplo.

app.secret_key = 'alura'

def bot(prompt):
    maximo_tentativas = 1

Teremos também uma variável para controlar as repetições, chamada repeticao, que começa em 0. Ou seja, nesse momento não houve nenhuma interação extra necessária. Essa interação extra pode ocorrer por problemas de conexão de internet, falha de conexão devido a uma chave de API equivocada, ou até por lentidão do próprio uso da API.

app.secret_key = 'alura'

def bot(prompt):
    maximo_tentativas = 1
    repeticao = 0

Feito isso, começaremos a interação com nosso chatbot através de um while True, para garantir que toda essa informação permaneça aqui dentro, até que a composição da mensagem esteja concluída.

Como é uma operação que tem um acesso externo, envolve o uso de uma API que não faz parte apenas do conjunto de arquivos de programação que estão dentro do projeto, é importante circundar esse trecho de código através de uma proteção, que é um try catch, para evitar que, caso tenhamos uma exceção, a aplicação seja encerrada. Então, vamos marcar um try antes de começar a trabalhar com nosso bot.

def bot(prompt):
    maximo_tentativas = 1
    repeticao = 0
    
    while True:
        try:

Agora, começaremos a trazer os prompts necessários para essa troca de mensagem. Esse chatbot que estamos implementando tem um papel específico, que é assumir o papel de um chatbot de um e-commerce de produtos sustentáveis, para que as pessoas usuárias possam obter respostas assertivas. É importante evitar que esse chatbot forneça respostas que não necessariamente têm uma relação com outros tipos de conteúdo, então precisamos que o prompt de sistema deixe bem claro qual é o papel e a persona que esse chatbot deve assumir.

Pensando nisso, vamos colar um trecho de prompt de sistema, onde dizemos que nosso chatbot é um chatbot de atendimento a clientes de um e-commerce, e que ele não deve responder perguntas que não sejam dados do e-commerce informado. Ou seja, perguntas que não tenham a ver com esse conteúdo devem ser ignoradas.

def bot(prompt):
  maximo_tentativas = 1
  repeticao = 0
  
  while True:
    try:
            prompt_do_sistema = f"""
            Você é um chatbot de atendimento a clientes de um e-commerce.
            Você não deve responder perguntas que não sejam dados do ecommerce informado!
                """

Após a definição desse prompt, traremos nosso fluxo principal de troca de mensagens.

def bot(prompt):
  maximo_tentativas = 1
  repeticao = 0
  
  while True:
    try:
            prompt_do_sistema = f"""
            Você é um chatbot de atendimento a clientes de um e-commerce.
            Você não deve responder perguntas que não sejam dados do ecommerce informado!
                """
                
                response = cliente.chat.completions.create(
                    messages=[
                                {
                                    "role": "system,
                                    "content": prompt_do_sistema
                                },
                                {
                                    "role": "user",
                                    "content": prompt
                                }
                            ],
                            temperature=1,
                            max_tokens=256,
                            top_p=1,
                            frequency_penalty=0,
                            presence_penalty=0,
                            modal = modelo)

Estamos definindo que teremos uma completions, ou seja, a pessoa cliente vai acessar o chat e gerar uma completion nova através de dois prompts. O primeiro prompt, é o prompt_do_sistema, que envolve a personalidade do chatbot. O segundo prompt, chamado prompt, é a mensagem que a pessoa usuária enviou pela nossa interface desenhada em HTML.

Além disso, essa resposta será armazenada na variável response e contará com alguns parâmetros pré-definidos, como a temperatura (temperature), que será 1, e o número máximo de tokens admissível (max_tokens), que será de 256.

Ainda nesses parâmetros, definimos que ela acessará todo o espaço amostral e não gerará nenhuma penalidade para palavras repetitivas. No caso de algum conteúdo, ou algum tipo de interação que o chatbot terá na hora de compor essa mensagem, seja com contextos, assuntos ou temas, também não gerará nenhuma penalidade. Por fim, definimos nosso modelo, que será do GPT-4, e que será utilizado para gerar essa resposta para a pessoa usuária.

Em seguida, vamos retornar a resposta e usar o except para que a exceção seja capturada caso não consiga finalizar a tarefa.

def bot(prompt):
  maximo_tentativas = 1
  repeticao = 0
  
  while True:
    try:
            prompt_do_sistema = f"""
            Você é um chatbot de atendimento a clientes de um e-commerce.
            Você não deve responder perguntas que não sejam dados do ecommerce informado!
                """
                
                response = cliente.chat.completions.create(
                    messages=[
                                {
                                    "role": "system,
                                    "content": prompt_do_sistema
                                },
                                {
                                    "role": "user",
                                    "content": prompt
                                }
                            ],
                            temperature=1,
                            max_tokens=256,
                            top_p=1,
                            frequency_penalty=0,
                            presence_penalty=0,
                            modal = modelo)
                return response
                    except Exception as erro:
                        repeticao += 1
                        if repeticao >= maximo_tentativas:
                            return "Erro no GPT: %s" % erro
                        print('Erro de comunicação com OpenAI: ', erro)
                        sleep(1)

Ao final, temos um erro em sleep(), porque falta importar essa biblioteca. Então, no início do nosso código, podemos adicionar a importação com from time import sleep.

import os
from time import sleep

Feito isso, conseguimos fazer essa pausa para garantir que, se houve alguma tentativa frustrada na hora de interagir com a OpenAI, ela tenha o tempo necessário para que essa resposta possa ser recomputada. Assim, conseguimos alcançar, em uma segunda tentativa, a resposta esperada pela OpenAI.

Agora, nosso chatbot já devolve essa informação para quem fez a requisição. Essa requisição foi feita em nosso método de chat, na linha resposta = bot(prompt), mas precisamos devolver resposta para o Javascript, porque é ele que desenhará essa informação na tela, através do uso de HTML e CSS.

No nosso método de chat, teremos um trecho de código que capturará essa informação. Ou seja, vai capturar a resposta que foi gerada pelo chatbot, através da interação com a OpenAI. Em seguida, buscará a resposta que está na posição 0, dentro do choices, além da mensagem inserida e o conteúdo dela, e armazenar dentro de texto_resposta. Esse texto_resposta será retornado para o nosso Javascript.

@app.route("/chat", methods=["POST"])
def chat():
    prompt = request.json["msg"]
    resposta = bot(prompt)
    texto_resposta = resposta.choices[0].message.content
    return texto_resposta

No arquivo index.js, essa resposta ocorrerá na linha 27, onde encontramos essa informação, convertemos ela para um texto, e utilizamos esse texto para compor a resposta que irá, de fato, para o nosso chatbot no navegador.

const textoDaResposta = await resposta.text();

Vamos salvar e voltar ao nosso navegador para conferir que tipo de resposta conseguimos obter agora com o nosso chatbot.

Enviaremos uma mensagem para que a OpenAI possa processar e devolver essa resposta para nós no formato de uma conversa com o nosso chatbot. Então, vamos pedir para que ele indique produtos da EcoMart.

Você pode indicar produtos da EcoMart?

Ele analisará nosso texto, construirá essa resposta e, assim que concluir, desenhará a resposta no balão de baixo.

Como resposta, ele diz que a EcoMart oferece uma grande variedade de produtos e dá alguns exemplos. Então, ele construiu essa resposta através da interação com a OpenAI.

Claro! No EcoMart, oferecemos uma variedade de produtos ecológicos e sustentáveis. Aqui estão algumas de nossas recomendações populares:

  1. Kit de cosméticos orgânicos: Inclui shampoo, condicionador e sabonete líquido. Todos os três são feitos de ingredientes naturais e orgânicos.

  2. Canudos reutilizáveis de aço inoxidável: Uma alternativa ecológica aos canudos de plástico. Eles vêm em um conjunto com uma escova de limpeza.

  3. Sacolas reutilizáveis de algodão: Ótimas para supermercados, compras geral e viagens à praia.

  4. Copos de café reutilizáveis: Feitos de bambu, uma excelente alternativa aos copos de café descartáveis.

  5. Embalagem de Food Wrap de cera de abelha: Uma alternativa sustentável ao filme plástico.

Estes são apenas alguns dos muitos produtos ecológicos que temos disponíveis. Navegue pelo nosso site para descobrir mais!

No momento, ainda não temos um contexto muito bem definido, pois não sabemos de fato quais são os produtos que fazem parte da loja. Falaremos sobre isso no próximo vídeo!

Sobre o curso Python e GPT: crie seu chatbot com IA

O curso Python e GPT: crie seu chatbot com IA possui 149 minutos de vídeos, em um total de 47 atividades. Gostou? Conheça nossos outros cursos de IA para Programação em Inteligência Artificial, ou leia nossos artigos de Inteligência Artificial.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda IA para Programação acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas