Gêmeos vs. ChatGPT: Quem Escreve Melhor Código?

Ari Mahpour
|  Criada: Marco 1, 2024  |  Atualizada: Abril 2, 2024
Gemini vs. ChatGPT

 

Os dias em que Engenheiros Eletricistas podiam se dar ao luxo de não escrever uma única linha de código acabaram. Saber programar tornou-se uma habilidade necessária, essencial para engenheiros de todos os tipos. Embora os engenheiros não precisem entender como escrever uma aplicação web completa, é importante que eles tenham habilidades básicas de script. Realizar análises em grandes conjuntos de dados, por exemplo, requer algum conhecimento em programação. Para tarefas mais complexas, os engenheiros podem se encontrar em dificuldades, às vezes gastando horas pesquisando online por uma função ou solução específica. Com o lançamento do ChatGPT, o mundo, sem dúvida, mudou e também mudou o cenário para a geração automatizada de código. Engenheiros sem um forte background agora podem escrever código de alta qualidade com a ajuda da IA Generativa.

Em artigos anteriores como Usando ChatGPT para Scripting no Altium e Usando ChatGPT para Testes Automatizados, vimos como aproveitar a IA Generativa, especificamente o ChatGPT, para escrever código por nós. Até agora, o Google Bard (o concorrente do ChatGPT) ficou para trás, mas um novo modelo, Gemini, anunciou que supera seu concorrente na escala de Entendimento de Linguagem Multitarefa Massiva (MMLU):

Figure 1: Gemini’s MMLU  performance metric

Figura 1: Métrica de desempenho MMLU da Gemini. Fonte: https://deepmind.google/technologies/gemini/#capabilities

Neste artigo, vamos comparar o motor mais sofisticado do ChatGPT, o GPT4, com o Gemini Advanced (anteriormente conhecido como Ultra), o motor de IA mais avançado do Google, para ver quem é melhor na geração de código.

Código Padrão

Realizar uma comparação totalmente exaustiva entre os dois motores seria extremamente desafiador. Neste artigo, vamos analisar como esses dois motores geram código padrão escrito em Python (já que é uma das linguagens mais suportadas para a escrita de código por LLMs). Isso não é uma ciência exata, pois o bom versus o ruim pode ser muito subjetivo. Em vez disso, vamos avaliar cada motor simplesmente com base se o código funciona e o quanto ele entendeu nossas instruções.

Tarefa 1: Impressão Recursiva das Propriedades de Arquivos

Para começar, vamos olhar para uma tarefa de script muito simples:

Desenvolver um script de automação em Python que, dado um caminho absoluto para uma pasta, recupere os metadados de cada arquivo recursivamente como um objeto dicionário. Imprimir cada objeto dicionário linha por linha e incluir o caminho absoluto.

Vamos primeiro analisar o código que vem do GPT4:

import os

def get_file_metadata(directory):

    for foldername, subfolders, filenames in os.walk(directory):

        for filename in filenames:

            filepath = os.path.join(foldername, filename)

            metadata = {

                'filename': filename,

                'path': filepath,

                'size': os.path.getsize(filepath),

                'last_modified': os.path.getmtime(filepath)

            }

            print(metadata)

 

get_file_metadata(os.path.dirname(os.path.abspath(__file__)))

É conciso, funciona e faz o trabalho. Eu daria uma aprovação. Também é uma tarefa excepcionalmente trivial, mas tudo bem.

Agora vamos olhar para o código que veio do Gemini Advanced:

import os

 

def get_file_metadata(file_path):

    metadata = {}

    try:

        stat = os.stat(file_path)

        metadata['name'] = os.path.basename(file_path)

        metadata['size'] = stat.st_size  # Tamanho em bytes

        metadata['modified_time'] = stat.st_mtime  # Última modificação

        metadata['accessed_time'] = stat.st_atime  # Último acesso

    except OSError:

        print(f"Erro ao acessar arquivo: {file_path}")

    return metadata

 

def retrieve_metadata_recursively(folder_path):

    for root, _, files in os.walk(folder_path):

        for file in files:

            file_path = os.path.join(root, file)

            metadata = get_file_metadata(file_path)

            if metadata:

                print(f"Caminho Absoluto: {file_path}")  # Imprime o caminho absoluto

                print(metadata)

 

if __name__ == '__main__':

    retrieve_metadata_recursively(os.path.dirname(os.path.abspath(__file__)))

Gemini é um pouco mais verboso, embora tenha adicionado algum tratamento de erro, o que, suponho, é bom. É um tanto quanto extenso, mas funciona, então vamos aceitar.

Tarefa 2: Web Scraper

Para a próxima tarefa, eu queria ver como ambos os motores conseguem entender uma linguagem dada e criar um analisador com base nessa linguagem. Neste caso, vamos construir um raspador web usando o seguinte prompt:
Escreva um script Python usando BeautifulSoup ou Scrapy que raspe as principais manchetes de notícias de 'https://news.ycombinator.com' e as exporte para um objeto dicionário.

Aqui está um trecho da fonte da página de 'https://news.ycombinator.com'. Use isso para determinar como analisar as tags.

Escreva um script Python usando BeautifulSoup ou Scrapy que raspe as principais manchetes de notícias de 'https://news.ycombinator.com' e as exporte para um objeto dicionário.

Aqui está um trecho da fonte da página de 'https://news.ycombinator.com'. Use isso para determinar como analisar as tags.

<html lang="pt" op="news"><head><meta name="referrer" content="origin"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" type="text/css" href="news.css?J16btoAd8hqdkSoIdLSk">
        <link rel="icon" href="y18.svg">

</html>

Como você notará, incluí algum HTML na minha solicitação. Minha solicitação real consiste em mais HTML, mas eu o truncado para este artigo. Aqui está o que o GPT4 gerou:

import requests
from bs4 import BeautifulSoup

# URL do site para raspar
url = 'https://news.ycombinator.com'

# Envia uma solicitação GET para a URL
response = requests.get(url)

# Analisa o conteúdo HTML da página usando BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')

# Encontre todas as manchetes
headlines = soup.find_all('tr', class_='athing')

# Dicionário para armazenar as manchetes onde a chave é o ranking e o valor é o texto da manchete
news_headlines = {}

# Percorre cada manchete, extrai e armazena no dicionário
for headline in headlines:
    rank = headline.find('span', class_='rank').text.strip('.')
    title = headline.find('span', class_='titleline').text
    news_headlines[rank] = title

# Saída do dicionário
print(news_headlines)

Este código funciona bem e faz o que é suposto. Eu esperava que ele soubesse, intuitivamente, que eu queria o link para os artigos, mas eu não fui explícito, então não posso usar isso como uma marca contra a nota do GPT4.

Aqui está o que o Gemini gerou:

import requests
from bs4 import BeautifulSoup

# Envia uma solicitação HTTP GET para o site do Hacker News
response = requests.get("https://news.ycombinator.com/")

# Analise o conteúdo HTML usando BeautifulSoup
soup = BeautifulSoup(response.content, "html.parser")

# Encontre todos os elementos de classe 'athing', que contêm os artigos de notícias
articles = soup.find_all("tr", class_="athing")

# Crie um dicionário vazio para armazenar as manchetes
headlines = {}

# Percorra cada artigo e extraia a manchete e a URL
for article in articles:
    # Encontre o elemento da manchete
    headline_element = article.find("span", class_="titleline")
    headline = headline_element.find("a").text.strip()

    # Encontre o elemento da URL
    url_element = headline_element.find("a")
    url = url_element["href"]

    # Adicione a manchete e a URL ao dicionário
    headlines[headline] = url

# Imprima o dicionário de manchetes
print(headlines)

Isso também funciona e é bastante semelhante à saída do GPT4, mas este código realmente extrai a URL. Isso é bom, mas, novamente, não é uma expectativa. Neste desafio, eu diria que eles são, praticamente, iguais. Talvez o Gemini ganhe um ponto extra por ser um leitor de mentes.

Tarefa 3: Aplicação Web de Ações

Para esta tarefa, quero criar uma aplicação web que desenhe gráficos de ações de alguns tickers diferentes:

Crie uma aplicação web em Python que mostre gráficos das seguintes ações: RIVN, TSLA, NKLA, FSR

Esta foi definitivamente mais complicada. Requer um componente de frontend (ou seja, gráficos/imagens) e um componente de backend (ou seja, recuperar os dados de um banco de dados de ações). Eu gerei inúmeras aplicações com GPT4 e queria ver como o Gemini se comparava a ele. Aqui está o que o GPT4 gerou para mim:

from flask import Flask, render_template_string
import yfinance as yf
import plotly.graph_objects as go
from datetime import datetime

app = Flask(__name__)

@app.route('/')
def home():
    stocks = ['RIVN', 'TSLA', 'NKLA', 'FSR']
    start = datetime(2021, 1, 1)
    end = datetime.now()

    fig = go.Figure()

    for stock in stocks:
        df = yf.download(stock, start=start, end=end)
        fig.add_trace(go.Scatter(x=df.index, y=df.Close, mode='lines', name=stock))

    graph_html = fig.to_html(full_html=False)

    return render_template_string("""
        <html>
            <body>
                {{ graph_html | safe }}
            </body>
        </html>

Figure 2: Screenshot of GPT4 generated web application

Figura 2: Captura de tela da aplicação web gerada pelo GPT4

É simples, limpo e direto ao ponto. Sem extravagâncias, mas cumpre o que promete. Aqui está o que o Gemini gerou para mim:

import flask
from flask import render_template
import yfinance as yf
import plotly.graph_objects as go

app = flask.Flask(__name__)

# Símbolos de ações
tickers = ['RIVN', 'TSLA', 'NKLA', 'FSR']

# Buscar dados de ações usando yfinance
def get_stock_data(ticker):
    start_date = '2023-02-10'  # Ajustar data de início conforme necessário
    end_date = '2024-02-10'  # Data de hoje
    return yf.download(ticker, start=start_date, end=end_date)

@app.route('/')
def index():
    stock_data = {}
    for ticker in tickers:
        stock_data[ticker] = get_stock_data(ticker)

    charts = []
    for ticker, data in stock_data.items():
        fig = go.Figure(data=[go.Candlestick(x=data.index,
                                             open=data['Open'],
                                             high=data['High'],
                                             low=data['Low'],
                                             close=data['Close'])])
        fig.update_layout(title=ticker)
        charts.append(fig.to_html(full_html=False, include_plotlyjs='cdn'))

    return render_template('index.html', charts=charts)

if __name__ == '__main__':
    app.run(debug=True)

Também foi necessário criar um novo arquivo, index.html, em um novo diretório chamado templates:

<!DOCTYPE html>
<html>
<head>
    <title>Gráficos de Ações</title>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
    {% for chart in charts %}
        <div id="{{ loop.index0 }}"></div> 
        <script>
            Plotly.newPlot('{{ loop.index0 }}', {{ chart | safe }});
        </script>
    {% endfor %}
</body>
</html>

Figure 3: Screenshot of Gemini Advanced generated web application

Figura 3: Captura de tela da aplicação web gerada pelo Gemini Advanced

Isso foi definitivamente mais sofisticado, pois incluiu um histograma e abstraiu o conteúdo HTML para um novo arquivo. Novamente, ambos foram funcionais, assim, ambos recebem uma nota de aprovação.

Falhas e Alucinações

Quando o GPT4 foi lançado pela primeira vez, levou um tempo para entender como "solicitar" adequadamente. Ao usar IA Generativa para escrever código, os detalhes importam. Como resultado, muitos de nós nos tornamos "Engenheiros de Solicitações" mais competentes ao longo deste último ano. Infelizmente, isso pode introduzir algum viés ao comparar o GPT4 com outros motores, e estou admitindo isso voluntariamente. Eu sei como o GPT4 "funciona" mais do que como o Gemini funciona. A maneira como eu elaboro solicitações para o GPT4 pode ser diferente do que o Gemini espera. Independentemente disso, ainda me deparei com alguns problemas muito fundamentais com o Gemini.

Um problema comum que encontrei com o Gemini ao interpretar instruções foi na geração de testes unitários. Meu objetivo inicial era cobrir testes unitários no artigo, mas, por frustração, desisti completamente do Gemini porque ele nunca seguia as instruções. Por exemplo, eu pedia ao Gemini para escrever um teste unitário usando Pytest e encapsulá-lo em uma classe. Ele gerava o teste usando UnitTest em vez disso, ignorando descaradamente meu pedido, mas encapsulava o código dentro de uma classe. Eu corrigia e ele reconhecia que acidentalmente usou UnitTest em vez de Pytest. Então, ele reescrevia o código usando Pytest, mas esquecia de colocá-lo em uma classe. Quando eu pedia para usar uma construção Mock, ele recorria ao mock do UnitTest em vez do Mock do Pytest. São nuances, mas importantes ao interagir com a IA Generativa.

Figure 4: Gemini Advanced not following directions

Figura 4: Gemini Avançado não seguindo instruções

Resolver falhas foi outro ponto problemático. O motor de raciocínio do GPT4 provou ser bastante poderoso ao depurar erros em Python. Gemini... nem tanto. Quando eu pedia para corrigir certos problemas, ele simplesmente tentava reescrever o código com mais indentação ou trocando variáveis... uma resposta completamente inútil.

Às vezes, o Gemini simplesmente não funcionava. Dizia que não conseguia processar minha solicitação. Em outros casos, começava a comentar sobre a... próxima eleição?

Gemini Advanced confused about the upcoming elections?

Figura 5: Gemini Advanced confuso sobre as próximas eleições?

Conclusão

No geral, a qualidade do código boilerplate gerado pelo Gemini era bastante competitiva em relação ao GPT4. No entanto, a experiência e seu motor de raciocínio deixavam muito a desejar. Felizmente para o Google, essas partes fazem parte da implementação do LLM e não do próprio LLM. Em outras palavras, o LLM Gemini parece ser, fundamentalmente, bastante bom e equiparável ao GPT4, mas o código escrito ao redor dele, que é usado na experiência de chat, precisa de ajuda. Com o tempo, provavelmente veremos o Google iterar em seu código e aprimorar essa experiência e motor de raciocínio.

Sobre o autor

Sobre o autor

Ari is an engineer with broad experience in designing, manufacturing, testing, and integrating electrical, mechanical, and software systems. He is passionate about bringing design, verification, and test engineers together to work as a cohesive unit.

Recursos relacionados

Documentação técnica relacionada

Retornar a página inicial
Thank you, you are now subscribed to updates.