Gemini kontra ChatGPT: Kto pisze lepszy kod?

Ari Mahpour
|  Utworzono: marzec 1, 2024  |  Zaktualizowano: kwiecień 2, 2024
Gemini vs. ChatGPT

 

Minęły czasy, kiedy inżynierowie elektrycy mogli obyć się bez pisania choćby jednej linijki kodu. Umiejętność programowania stała się wymaganą umiejętnością, niezbędną dla inżynierów wszystkich specjalności. Chociaż inżynierowie nie muszą rozumieć, jak napisać pełną aplikację internetową, ważne jest, aby posiadali podstawowe umiejętności skryptowe. Wykonywanie analiz na dużych zbiorach danych, na przykład, wymaga pewnej wiedzy z zakresu programowania. W przypadku bardziej złożonych zadań, inżynierowie mogą znaleźć się w trudnej sytuacji, czasami spędzając godziny na szukaniu w internecie konkretnej funkcji lub rozwiązania. Z wydaniem ChatGPT świat, bez wątpienia, się zmienił, podobnie jak krajobraz automatycznego generowania kodu. Inżynierowie bez mocnego zaplecza mogą teraz pisać wysokiej jakości kod przy pomocy generatywnej sztucznej inteligencji.

W poprzednich artykułach, takich jak Używanie ChatGPT do skryptowania w Altium oraz Używanie ChatGPT do automatycznego testowania, przyjrzeliśmy się, jak wykorzystać generatywną sztuczną inteligencję, a konkretnie ChatGPT, do pisania kodu za nas. Do tej pory konkurent ChatGPT, Google Bard, pozostawał w tyle, ale nowy model, Gemini, reklamowany jest jako przewyższający swojego konkurenta na skali zrozumienia języka w wielozadaniowych zadaniach masowych (MMLU):

Figure 1: Gemini’s MMLU  performance metric

Rysunek 1: Metryka wydajności MMLU firmy Gemini. Źródło: https://deepmind.google/technologies/gemini/#capabilities

W tym artykule porównamy najbardziej zaawansowany silnik ChatGPT, GPT4, z Gemini Advanced (poprzednio znany jako Ultra), najbardziej zaawansowanym silnikiem AI Google, aby zobaczyć, który lepiej generuje kod.

Kod szablonowy

Przeprowadzenie w pełni wyczerpującego porównania między tymi dwoma silnikami byłoby niezwykle trudne. W tym artykule przyjrzymy się, jak dobrze te dwa silniki generują kod szablonowy napisany w Pythonie (jako że jest to jeden z najbardziej wspieranych języków dla pisania kodu przez LLM). To nie jest dokładna nauka, ponieważ dobre kontra złe może być bardzo subiektywne. Zamiast tego, ocenimy każdy silnik bazując po prostu na tym, czy kod działa i jak dobrze zrozumiał nasze instrukcje.

Zadanie 1: Rekursywne wyświetlanie właściwości pliku

Aby zacząć, przyjrzyjmy się bardzo prostemu zadaniu skryptowemu:

Stwórz skrypt automatyzacji Pythona, który, mając absolutną ścieżkę do folderu, pobiera metadane każdego pliku rekursywnie jako obiekt słownika. Wydrukuj każdy obiekt słownika linia po linii, uwzględniając absolutną ścieżkę.

Przeanalizujmy najpierw kod, który otrzymaliśmy od GPT4:

import os

def get_file_metadata(directory):

    dla foldername, subfolders, filenames w os.walk(directory):

        dla filename w 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__)))

Jest zwięźle, działa i spełnia swoje zadanie. Dałbym temu zielone światło. To również wyjątkowo trywialne zadanie, ale to w porządku.

Teraz spójrzmy na kod, który otrzymaliśmy od Gemini Advanced:

import os

 

def get_file_metadata(file_path):

    metadata = {}

    spróbuj:

        stat = os.stat(file_path)

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

        metadata['size'] = stat.st_size  # Rozmiar w bajtach

        metadata['modified_time'] = stat.st_mtime  # Ostatni czas modyfikacji

        metadata['accessed_time'] = stat.st_atime  # Ostatni czas dostępu

    except OSError:

        print(f"Błąd dostępu do pliku: {file_path}")

    return metadata

 

def retrieve_metadata_recursively(folder_path):

    dla root, _, files w os.walk(folder_path):

        dla file w files:

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

            metadata = get_file_metadata(file_path)

            jeśli metadata:

                print(f"Pełna ścieżka: {file_path}")  # Wyświetl pełną ścieżkę

                print(metadata)

 

if __name__ == '__main__':

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

Gemini jest nieco bardziej rozwlekły, aczkolwiek dodał pewne obsługi błędów, co, jak przypuszczam, jest miłe. Jest dość długi, ale działa, więc damy mu fory.

Zadanie 2: Web Scraper

W następnym zadaniu chciałem zobaczyć, jak dobrze oba silniki rozumieją dany język i potrafią stworzyć na jego podstawie parser. W tym przypadku będziemy budować web scraper, używając następującej wskazówki:
Napisz skrypt Pythona używając BeautifulSoup lub Scrapy, który scrapuje najważniejsze nagłówki wiadomości z 'https://news.ycombinator.com' i wypisuje je do obiektu słownika.

Oto fragment źródła strony z 'https://news.ycombinator.com'. Użyj tego, aby określić, jak parsować tagi.

Napisz skrypt Pythona używając BeautifulSoup lub Scrapy, który scrapuje najważniejsze nagłówki wiadomości z 'https://news.ycombinator.com' i wypisuje je do obiektu słownika.

Oto fragment źródła strony z 'https://news.ycombinator.com'. Użyj tego, aby określić, jak parsować tagi.

<html lang="pl" 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>

Jak zauważysz, dołączyłem trochę HTML-a do mojej wypowiedzi. Moje rzeczywiste polecenie zawiera więcej HTML-a, ale skróciłem je dla tego artykułu. Oto co wygenerował GPT4:

import requests
from bs4 import BeautifulSoup

# URL strony do scrapowania
url = 'https://news.ycombinator.com'

# Wyślij żądanie GET do URL
response = requests.get(url)

# Parsuj zawartość HTML strony używając BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')

# Znajdź wszystkie nagłówki wiadomości
headlines = soup.find_all('tr', class_='athing')

# Słownik do przechowywania nagłówków, gdzie klucz to ranga, a wartość to tekst nagłówka
news_headlines = {}

# Przejście przez każdy nagłówek, ekstrakcja i zapisanie go w słowniku
for headline in headlines:
    rank = headline.find('span', class_='rank').text.strip('.')
    title = headline.find('span', class_='titleline').text
    news_headlines[rank] = title

# Wyświetlenie słownika
print(news_headlines)

Ten kod działa dobrze i robi to, co powinien. Miałem nadzieję, że intuicyjnie będzie wiedział, że chcę link do artykułów, ale nie byłem w tym wyraźny, więc nie mogę tego uznać za minus oceny GPT4.

Oto co wygenerowało Gemini:

import requests
from bs4 import BeautifulSoup

# Wysłanie żądania HTTP GET do strony Hacker News
response = requests.get("https://news.ycombinator.com/")

# Przetwarzanie zawartości HTML za pomocą BeautifulSoup
soup = BeautifulSoup(response.content, "html.parser")

# Znajdź wszystkie elementy klasy 'athing', które zawierają artykuły
articles = soup.find_all("tr", class_="athing")

# Utwórz pusty słownik do przechowywania nagłówków
headlines = {}

# Przejdź przez każdy artykuł i wyodrębnij nagłówek oraz URL
for article in articles:
    # Znajdź element nagłówka
    headline_element = article.find("span", class_="titleline")
    nagłówek = headline_element.find("a").text.strip()

    # Znajdź element URL
    url_element = headline_element.find("a")
    url = url_element["href"]

    # Dodaj nagłówek i URL do słownika
    headlines[nagłówek] = url

# Wydrukuj słownik nagłówków
print(headlines)

To również działa i jest dość podobne do wyników GPT4, ale ten kod faktycznie ekstrahuje URL. To miłe, ale znowu, nie jest to oczekiwane. W tym wyzwaniu powiedziałbym, że są praktycznie takie same. Może Gemini zdobywa dodatkowy punkt za bycie czytelnikiem myśli.

Zadanie 3: Aplikacja internetowa do śledzenia akcji

W tym zadaniu chcę stworzyć aplikację internetową, która będzie wyświetlać wykresy akcji kilku różnych spółek:

Stwórz aplikację internetową w Pythonie, która pokaże wykresy następujących akcji: RIVN, TSLA, NKLA, FSR

To zadanie było zdecydowanie trudniejsze. Wymaga komponentu frontendowego (tj. wykresy/obrazy) oraz backendowego (tj. pobieranie danych z bazy danych akcji). Wygenerowałem niezliczone aplikacje z GPT4 i chciałem zobaczyć, jak wypada Gemini w porównaniu z nim. Oto co wygenerowało dla mnie GPT4:

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()

    dla akcji w stocks:
        df = yf.download(akcja, start=start, end=end)
        fig.add_trace(go.Scatter(x=df.index, y=df.Close, mode='lines', name=akcja))

    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

Rysunek 2: Zrzut ekranu wygenerowanej przez GPT4 aplikacji webowej

To proste, czyste i na temat. Bez zbędnych dodatków, ale robi swoje. Oto co Gemini wygenerowało dla mnie:

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

app = flask.Flask(__name__)

# Symbole akcji
tickers = ['RIVN', 'TSLA', 'NKLA', 'FSR']

# Pobieranie danych o akcjach za pomocą yfinance
def get_stock_data(ticker):
    start_date = '2023-02-10'  # Dostosuj datę początkową w razie potrzeby
    end_date = '2024-02-10'  # Dzisiejsza data
    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)

Wymagało to również ode mnie stworzenia nowego pliku, index.html, w nowym katalogu o nazwie templates:

<!DOCTYPE html>
<html>
<head>
    <title>Wykresy Giełdowe</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

Rysunek 3: Zrzut ekranu z wygenerowanej aplikacji webowej Gemini Advanced

To było zdecydowanie bardziej wyszukane, ponieważ zawierało histogram i abstrahowało zawartość HTML do nowego pliku. Ponownie, oba były funkcjonalne, więc oba otrzymują pozytywną ocenę.

Niepowodzenia i Halucynacje

Gdy GPT4 został po raz pierwszy wprowadzony, potrzebowaliśmy czasu, aby zrozumieć, jak właściwie go „pobudzać”. Podczas używania AI generatywnej do pisania kodu, szczegóły mają znaczenie. W rezultacie wielu z nas stało się bardziej kompetentnymi „Inżynierami Pobudek” w ciągu minionego roku. Niestety, może to wprowadzić pewne uprzedzenia przy porównywaniu GPT4 z innymi silnikami, co chętnie przyznaję. Wiem, jak „działa” GPT4 bardziej niż Gemini. Sposób, w jaki formułuję pobudki dla GPT4, może różnić się od tego, czego oczekuje Gemini. Niezależnie od tego, nadal napotkałem kilka bardzo podstawowych problemów z Gemini.

Jednym z częstych problemów, które napotkałem podczas korzystania z Gemini przy interpretacji instrukcji, było generowanie testów jednostkowych. Moim początkowym celem było omówienie testów jednostkowych w artykule, ale z frustracji całkowicie zrezygnowałem z Gemini, ponieważ nigdy nie postępowało zgodnie z instrukcjami. Na przykład, prosiłem Gemini, aby napisało test jednostkowy przy użyciu Pytest i umieściło go w klasie. Zamiast tego generowało test przy użyciu UnitTest, całkowicie ignorując moją prośbę, ale umieszczało kod w klasie. Poprawiałem to, a ono przyznawało, że przypadkowo użyło UnitTest zamiast Pytest. Następnie przepisywało kod przy użyciu Pytest, ale zapominało o umieszczeniu go w klasie. Gdy prosiłem o użycie konstruktu Mock, domyślnie używało mocka z UnitTest zamiast Mocka z Pytest. To są niuanse, ale ważne przy pracy z generatywną sztuczną inteligencją.

Figure 4: Gemini Advanced not following directions

Rysunek 4: Gemini Advanced nie postępuje zgodnie z instrukcjami

Rozwiązywanie problemów było kolejnym punktem bólu. Silnik rozumowania GPT4 okazał się dość potężny przy debugowaniu błędów w Pythonie. Gemini... już niekoniecznie. Gdy prosiłem go o naprawienie pewnych problemów, po prostu próbowało przepisać kod, dodając wcięcia lub zamieniając zmienne... zupełnie bezużyteczna odpowiedź.

Czasami Gemini po prostu nie działało. Informowało, że nie może przetworzyć mojego żądania. W innych przypadkach zaczynało komentować... nadchodzące wybory?

Gemini Advanced confused about the upcoming elections?

Rysunek 5: Gemini Advanced zdezorientowane w kwestii nadchodzących wyborów?

Podsumowanie

Podsumowując, jakość generowanego kodu szablonowego przez Gemini była całkiem konkurencyjna w porównaniu do GPT4. Doświadczenie i silnik rozumowania pozostawiały jednak wiele do życzenia. Na szczęście dla Google, te elementy są częścią implementacji LLM, a nie samego LLM. Innymi słowy, LLM Gemini wydaje się być, zasadniczo, całkiem dobry i na równi z GPT4, ale kod napisany wokół niego, który jest używany w doświadczeniu czatu, potrzebuje pewnej pomocy. Z czasem prawdopodobnie zobaczymy, jak Google iteruje nad swoim kodem i ulepsza to doświadczenie oraz silnik rozumowania.

About Author

About Author

Ari jest inżynierem z rozległym doświadczeniem w projektowaniu, produkcji, testowaniu i integracji systemów elektrycznych, mechanicznych i oprogramowania. Jego pasją jest łączenie inżynierów zajmujących się projektowaniem, weryfikacją i testowaniem, aby pracowali jako jeden zespół.

Powiązane zasoby

Powiązana dokumentacja techniczna

Powrót do strony głównej
Thank you, you are now subscribed to updates.