Géminis vs. ChatGPT: ¿Quién escribe mejor código?

Ari Mahpour
|  Creado: Marzo 1, 2024  |  Actualizado: Abril 2, 2024
Gemini vs. ChatGPT

 

Los días en los que los ingenieros eléctricos podían pasar sin escribir ni una sola línea de código han quedado atrás. Saber programar se ha convertido en una habilidad requerida, necesaria para ingenieros de todo tipo. Aunque los ingenieros no necesitan entender cómo escribir una aplicación web completa, es importante que tengan habilidades básicas de scripting. Realizar análisis en grandes conjuntos de datos, por ejemplo, requiere cierto conocimiento en programación. Para tareas más complejas, los ingenieros pueden encontrarse en apuros, a veces pasando horas buscando en línea una función o solución particular. Con el lanzamiento de ChatGPT, el mundo, sin duda, ha cambiado y también lo ha hecho el panorama para la generación de código automatizado. Ahora, los ingenieros sin un fuerte background pueden escribir código de alta calidad con la ayuda de la IA Generativa.

En artículos anteriores como Usando ChatGPT para Scripting en Altium y Usando ChatGPT para Pruebas Automatizadas, vimos cómo aprovechar la IA Generativa, específicamente ChatGPT, para escribir código por nosotros. Hasta ahora, Google Bard (el competidor de ChatGPT) ha quedado atrás, pero un nuevo modelo, Gemini, ha anunciado que supera a su competidor en la escala de Entendimiento del Lenguaje Multitarea Masivo (MMLU):

Figure 1: Gemini’s MMLU  performance metric

Figura 1: Métrica de rendimiento de MMLU de Gemini. Fuente: https://deepmind.google/technologies/gemini/#capabilities

En este artículo vamos a comparar el motor más sofisticado de ChatGPT, GPT4, contra Gemini Advanced (anteriormente conocido como Ultra), el motor de IA más avanzado de Google, para ver cuál es mejor generando código.

Código Predeterminado

Realizar una comparación totalmente exhaustiva entre los dos motores sería extremadamente desafiante. En este artículo vamos a observar cómo estos dos motores generan código predeterminado escrito en Python (ya que es uno de los lenguajes más soportados para la escritura de código por LLMs). Esto no es una ciencia exacta ya que lo bueno versus lo malo puede ser muy subjetivo. En su lugar, calificaremos a cada motor basándonos simplemente en si el código funciona y cuán bien entendió nuestras instrucciones.

Tarea 1: Impresión Recursiva de Propiedades de Archivos

Para comenzar, veamos una tarea de scripting muy simple:

Desarrollar un script de automatización en Python que, dado un camino absoluto a una carpeta, recupere los metadatos de cada archivo de manera recursiva como un objeto de diccionario. Imprimir cada objeto de diccionario línea por línea e incluir el camino absoluto.

Analicemos primero el código que proviene de 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__)))

Es conciso, funciona y cumple su función. Yo le daría un aprobado. También es una tarea excepcionalmente trivial, pero está bien.

Ahora veamos el código que proviene de 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  # Tamaño en bytes

        metadata['modified_time'] = stat.st_mtime  # Última marca de tiempo de modificación

        metadata['accessed_time'] = stat.st_atime  # Última marca de tiempo de acceso

    except OSError:

        print(f"Error al acceder al archivo: {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"Ruta absoluta: {file_path}")  # Imprime la ruta absoluta

                print(metadata)

 

if __name__ == '__main__':

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

Gemini es un poco más verboso, aunque, añadió algo de manejo de errores lo cual, supongo, es bueno. Es algo largo pero funciona así que le daremos un pase.

Tarea 2: Raspador Web

Para la siguiente tarea quería ver qué tan bien ambos motores pueden entender un lenguaje dado y crear un analizador basado en ese lenguaje. En este caso vamos a construir un raspador web usando la siguiente indicación:
Escribe un script de Python usando BeautifulSoup o Scrapy que raspe los titulares principales de noticias de 'https://news.ycombinator.com' y los exporte a un objeto de diccionario.

Aquí hay un fragmento de la fuente de la página de 'https://news.ycombinator.com'. Usa esto para determinar cómo analizar las etiquetas.

Escribe un script de Python usando BeautifulSoup o Scrapy que raspe los titulares principales de noticias de 'https://news.ycombinator.com' y los exporte a un objeto de diccionario.

Aquí hay un fragmento de la fuente de la página de 'https://news.ycombinator.com'. Usa esto para determinar cómo analizar las etiquetas.

<html lang="es" 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 notarás, incluí algo de HTML en mi indicación. Mi indicación real consiste en más HTML pero lo truncé para este artículo. Aquí está lo que generó GPT4:

import requests
from bs4 import BeautifulSoup

# URL del sitio a raspar
url = 'https://news.ycombinator.com'

# Envía una solicitud GET a la URL
response = requests.get(url)

# Analiza el contenido HTML de la página usando BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')

# Encuentra todos los titulares de noticias
headlines = soup.find_all('tr', class_='athing')

# Diccionario para almacenar los titulares donde la clave es el rango y el valor es el texto del titular
news_headlines = {}

# Itera a través de cada titular, extráelo y almacénalo en el diccionario
for headline in headlines:
    rank = headline.find('span', class_='rank').text.strip('.')
    title = headline.find('span', class_='titleline').text
    news_headlines[rank] = title

# Muestra el diccionario
print(news_headlines)

Este código funciona bien y hace lo que se supone que debe hacer. Esperaba que supiera, intuitivamente, que quería el enlace a los artículos pero no fui explícito, así que no puedo usar eso como una marca en contra de la calificación de GPT4.

Aquí está lo que Gemini generó:

import requests
from bs4 import BeautifulSoup

# Envía una solicitud HTTP GET al sitio web de Hacker News
response = requests.get("https://news.ycombinator.com/")

# Analizar el contenido HTML usando BeautifulSoup
soup = BeautifulSoup(response.content, "html.parser")

# Encontrar todos los elementos de clase 'athing', que contienen los artículos de noticias
articles = soup.find_all("tr", class_="athing")

# Crear un diccionario vacío para almacenar los titulares
headlines = {}

# Recorrer cada artículo y extraer el titular y la URL
for article in articles:
    # Encontrar el elemento del titular
    headline_element = article.find("span", class_="titleline")
    headline = headline_element.find("a").text.strip()

    # Encontrar el elemento de la URL
    url_element = headline_element.find("a")
    url = url_element["href"]

    # Añadir el titular y la URL al diccionario
    headlines[headline] = url

# Imprimir el diccionario de titulares
print(headlines)

Esto también funciona y es bastante similar a la salida de GPT4, pero este código realmente extrae la URL. Eso está bien, pero, de nuevo, no es una expectativa. En este desafío diría que son, prácticamente, lo mismo. Quizás Gemini gana un punto extra por ser un lector de mentes.

Tarea 3: Aplicación Web de Acciones

Para esta tarea quiero crear una aplicación web que muestre gráficos de acciones de algunos tickers diferentes:

Crea una aplicación web en Python que muestre gráficos de las siguientes acciones: RIVN, TSLA, NKLA, FSR

Esta definitivamente fue más complicada. Requiere un componente de frontend (es decir, gráficos/imagenes) y un componente de backend (es decir, recuperar los datos de una base de datos de acciones). He generado innumerables aplicaciones con GPT4 y quería ver cómo se comparaba Gemini con él. Esto es lo que GPT4 generó para mí:

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 pantalla de la aplicación web generada por GPT4

Es simple, limpia y al grano. Sin adornos pero cumple su función. Esto es lo que Gemini generó para mí:

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

app = flask.Flask(__name__)

# Símbolos de acciones
tickers = ['RIVN', 'TSLA', 'NKLA', 'FSR']

# Obtener datos de acciones usando yfinance
def obtener_datos_accion(ticker):
    fecha_inicio = '2023-02-10'  # Ajustar fecha de inicio según sea necesario
    fecha_fin = '2024-02-10'  # Fecha de hoy
    return yf.download(ticker, start=fecha_inicio, end=fecha_fin)

@app.route('/')
def index():
    datos_acciones = {}
    for ticker in tickers:
        datos_acciones[ticker] = obtener_datos_accion(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)

También me requirió crear un nuevo archivo, index.html, en un nuevo directorio llamado templates:

<!DOCTYPE html>
<html>
<head>
    <title>Gráficos de Acciones</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 pantalla de la aplicación web generada por Gemini Advanced

Definitivamente era más sofisticado, ya que incluía un histograma y abstraía el contenido HTML en un nuevo archivo. De nuevo, ambos eran funcionales, por lo tanto, ambos reciben una calificación aprobatoria.

Fallos y Alucinaciones

Cuando GPT4 se lanzó por primera vez, tomó tiempo entender cómo "solicitarlo" adecuadamente. Al usar IA Generativa para escribir código, los detalles importan. Como resultado, muchos de nosotros nos hemos vuelto más competentes como "Ingenieros de Solicitudes" durante este último año. Desafortunadamente, esto puede introducir cierto sesgo al comparar GPT4 con otros motores y estoy dispuesto a admitirlo. Sé cómo "funciona" GPT4 más que cómo funciona Gemini. La manera en que formulo solicitudes para GPT4 podría ser diferente a lo que Gemini espera. Sin embargo, aún me encontré con algunos problemas muy fundamentales con Gemini.

Un problema común que encontré con Gemini al interpretar instrucciones fue al generar pruebas unitarias. Mi objetivo inicial era cubrir las pruebas unitarias en el artículo pero, por frustración, renuncié por completo a Gemini porque nunca seguía las instrucciones. Por ejemplo, le pediría a Gemini que escribiera una prueba unitaria usando Pytest y la encapsulara en una clase. Generaría la prueba usando UnitTest en su lugar, ignorando descaradamente mi solicitud, pero encapsularía el código dentro de una clase. Lo corregiría y reconocería que accidentalmente usó UnitTest en lugar de Pytest. Luego reescribiría el código usando Pytest pero se olvidaría de ponerlo en una clase. Cuando solicito que use una construcción Mock, recurre por defecto al mock de UnitTest versus el Mock de Pytest. Estos son matices pero importantes al interactuar con la IA Generativa.

Figure 4: Gemini Advanced not following directions

Figura 4: Gemini Avanzado no siguiendo instrucciones

La solución de fallos fue otro punto doloroso. El motor de razonamiento de GPT4 ha demostrado ser bastante poderoso al depurar errores en Python. Gemini… no tanto. Cuando le pedía que solucionara ciertos problemas, simplemente intentaba reescribir el código con sangrías adicionales o intercambiando variables… una respuesta completamente inútil.

A veces, Gemini simplemente no funcionaba. Decía que no podía procesar mi solicitud. En otros casos, comenzó a comentar sobre las... ¿próximas elecciones?

Gemini Advanced confused about the upcoming elections?

Figura 5: Gemini Advanced confundido acerca de las próximas elecciones?

Conclusión

En general, la calidad del código base generado por Gemini fue bastante competitiva en comparación con GPT4. Sin embargo, la experiencia y su motor de razonamiento dejaban mucho que desear. Afortunadamente para Google, esos elementos son parte de la implementación del LLM y no del LLM en sí. En otras palabras, el LLM de Gemini parece ser, fundamentalmente, bastante bueno y a la par con GPT4, pero el código escrito alrededor de él que se utiliza en la experiencia de chat necesita ayuda. Con el tiempo, probablemente veremos a Google iterar en su código y mejorar esa experiencia y motor de razonamiento.

Sobre el autor / Sobre la autora

Sobre el autor / Sobre la autora

Ari es un ingeniero con una amplia experiencia en diseño, fabricación, pruebas e integración de sistemas eléctricos, mecánicos y de software. Le apasiona integrar a los ingenieros de diseño, de verificación y de pruebas para que trabajen juntos como una unidad cohesiva.

Recursos Relacionados

Documentación técnica relacionada

Volver a la Pàgina de Inicio
Thank you, you are now subscribed to updates.