Gemini vs. ChatGPT: どちらがより良いコードを書くのか?

Ari Mahpour
|  投稿日 2024/03/1, 金曜日  |  更新日 2024/04/2, 火曜日
Gemini vs. ChatGPT

 

もはや電気工学者が一行のコードも書かずに済む時代は終わりました。コーディングを知ることは、あらゆるタイプのエンジニアにとって必須のスキルとなっています。エンジニアがフルスタックのWebアプリケーションを書く方法を理解する必要はありませんが、基本的なスクリプティングスキルを持っていることが重要です。たとえば、大規模なデータセットの分析を行う場合、プログラミングに関するある程度の知識が必要です。より複雑なタスクの場合、エンジニアはしばしば特定の機能や解決策をオンラインで何時間も検索することになります。ChatGPTのリリースにより、世界は間違いなく変わり、自動コード生成の風景も変わりました。強力なバックグラウンドを持たないエンジニアでも、Generative AIの助けを借りて高品質のコードを書くことができるようになりました。

以前の記事であるAltiumスクリプティングのためのChatGPTの使用自動テストのためのChatGPTの使用では、Generative AI、特にChatGPTを活用してコードを書く方法について見てきました。これまでのところ、Google Bard(ChatGPTの競合)は後れを取っていましたが、新しいモデルであるGeminiが、Massive Multitask Language Understanding (MMLU)スケールで競合を上回ると宣伝しています:

Figure 1: Gemini’s MMLU  performance metric

図1:ジェミニのMMLUパフォーマンス指標。出典:https://deepmind.google/technologies/gemini/#capabilities

この記事では、ChatGPTの最も洗練されたエンジンであるGPT4と、Googleの最先端AIエンジンであるGemini Advanced(以前はUltraとして知られていた)を比較して、コード生成においてどちらが優れているかを見ていきます。

ボイラープレートコード

二つのエンジン間で完全に徹底的な比較を行うことは非常に難しいでしょう。この記事では、これら二つのエンジンがPythonで書かれたボイラープレートコードをどの程度うまく生成できるかを見ていきます(コード作成LLMにとって最もサポートされている言語の一つです)。これは正確な科学ではありません。良いか悪いかは非常に主観的です。代わりに、コードが実行されるか、および私たちの指示をどの程度理解したかに基づいて、各エンジンを評価します。

タスク1:再帰的ファイルプロパティ出力

始めるために、非常にシンプルなスクリプティングタスクを見てみましょう:

フォルダへの絶対パスが与えられた場合に、各ファイルのメタデータを辞書オブジェクトとして再帰的に取得し、辞書オブジェクトを行ごとに印刷し、絶対パスを含めるPython自動化スクリプトを開発します。

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

このコードは簡潔で、機能し、仕事をこなします。これは合格です。また、これは極めて簡単なタスクですが、それで問題ありません。

次に、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  # バイト単位のサイズ

        metadata['modified_time'] = stat.st_mtime  # 最終変更タイムスタンプ

        metadata['accessed_time'] = stat.st_atime  # 最終アクセスタイムスタンプ

    except OSError:

        print(f"ファイルへのアクセスエラー: {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"絶対パス: {file_path}")  # 絶対パスを表示

                print(metadata)

 

if __name__ == '__main__':

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

Geminiは少し冗長ですが、エラーハンドリングを追加したのは良い点だと思います。やや長いですが、機能するので許容しましょう。

タスク2: ウェブスクレイパー

次のタスクでは、両エンジンが与えられた言語をどの程度理解し、その言語に基づいたパーサーを作成できるかを見たいと思います。この場合、以下のプロンプトを使用してウェブスクレイパーを構築します:
BeautifulSoupまたはScrapyを使用してPythonスクリプトを書き、'https://news.ycombinator.com'からトップニュースの見出しをスクレイピングして、それを辞書オブジェクトに出力します。

これは'https://news.ycombinator.com'のページソースのスニペットです。これを使用して、タグをどのように解析するかを決定します。

BeautifulSoupまたはScrapyを使用してPythonスクリプトを書き、'https://news.ycombinator.com'からトップニュースの見出しをスクレイピングして、それを辞書オブジェクトに出力します。

これは'https://news.ycombinator.com'のページソースのスニペットです。これを使用して、タグをどのように解析するかを決定します。

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

お気づきの通り、私のプロンプトにはHTMLを含めています。実際のプロンプトにはもっとHTMLがありますが、この記事のために省略しました。ここでGPT4が生成したものです:

import requests
from bs4 import BeautifulSoup

# スクレイプするサイトのURL
url = 'https://news.ycombinator.com'

# URLにGETリクエストを送信
response = requests.get(url)

# BeautifulSoupを使用してページのHTMLコンテンツを解析
soup = BeautifulSoup(response.text, 'html.parser')

# すべてのニュース見出しを見つける
headlines = soup.find_all('tr', class_='athing')

# 見出しを格納するための辞書、キーはランク、値は見出しテキスト
news_headlines = {}

# 各見出しをループし、辞書に抽出して格納する
for headline in headlines:
    rank = headline.find('span', class_='rank').text.strip('.')
    title = headline.find('span', class_='titleline').text
    news_headlines[rank] = title

# 辞書を出力する
print(news_headlines)

このコードは問題なく動作し、意図した通りの機能を果たします。記事へのリンクも intuitively 知りたかったのですが、明示的にはしていなかったので、それをGPT4の評価に使うことはできません。

Geminiが生成したものはこちらです:

import requests
from bs4 import BeautifulSoup

# Hacker NewsのウェブサイトにHTTP GETリクエストを送信する
response = requests.get("https://news.ycombinator.com/")

# BeautifulSoupを使用してHTMLコンテンツを解析する
soup = BeautifulSoup(response.content, "html.parser")

# ニュース記事を含む'athing'クラスの要素を全て見つける
articles = soup.find_all("tr", class_="athing")

# 見出しを格納するための空の辞書を作成する
headlines = {}

# 各記事をループし、見出しとURLを抽出する
for article in articles:
    # 見出し要素を見つける
    headline_element = article.find("span", class_="titleline")
    headline = headline_element.find("a").text.strip()

    # URL要素を見つける
    url_element = headline_element.find("a")
    url = url_element["href"]

    # 見出しとURLを辞書に追加する
    headlines[headline] = url

# 見出しの辞書を印刷する
print(headlines)

これも機能し、GPT4の出力とかなり似ていますが、このコードは実際にURLを抽出します。それは素晴らしいことですが、再び、期待されるわけではありません。このチャレンジでは、彼らはほぼ同じだと言えます。おそらく、Geminiは心を読むことができる点で追加点を得るでしょう。

タスク3: 株式ウェブアプリケーション

このタスクでは、いくつかの異なるティッカーの株価チャートを描き出すウェブアプリケーションを作成したいと思います:

以下の株式のチャートを表示するPythonでウェブアプリケーションを作成してください: RIVN, TSLA, NKLA, FSR

これは間違いなく難しいものでした。フロントエンド(つまり、グラフ/画像)とバックエンドコンポーネント(つまり、株式データベースからデータを取得する)が必要です。私はGPT4で無数のアプリケーションを生成しましたが、Geminiがそれにどう対抗するかを見たかったです。これが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()

    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

図2: GPT4が生成したウェブアプリケーションのスクリーンショット

シンプルでクリーン、そして要点を得ています。余計な装飾はありませんが、必要な機能を果たしています。これがGeminiが私のために生成したものです:

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

app = flask.Flask(__name__)

# 株式シンボル
tickers = ['RIVN', 'TSLA', 'NKLA', 'FSR']

# yfinanceを使用して株価データを取得
def get_stock_data(ticker):
    start_date = '2023-02-10'  # 開始日を必要に応じて調整
    end_date = '2024-02-10'  # 今日の日付
    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)

また、新しいディレクトリ「templates」に「index.html」という新しいファイルを作成する必要がありました:

<!DOCTYPE html>
<html>
<head>
    <title>株価チャート</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

図3: Gemini Advancedが生成したウェブアプリケーションのスクリーンショット

これは間違いなく洗練されており、ヒストグラムを含んでおり、HTMLコンテンツを新しいファイルに抽象化していました。再び、どちらも機能していたので、合格点を受けます。

失敗と幻覚

GPT4が初めて登場したとき、それを適切に「プロンプト」する方法を理解するのに時間がかかりました。コードを書くために生成AIを使用する場合、詳細が重要です。その結果、私たちの多くは、この過去1年間でより有能な「プロンプトエンジニア」になりました。残念ながら、これはGPT4を他のエンジンと比較する際にいくつかのバイアスを導入する可能性があり、私はそれを率直に認めています。GPT4の「動作」方法をGeminiのそれよりもよく知っています。GPT4に対して作成するプロンプトの方法は、Geminiが期待するものと異なるかもしれません。それにもかかわらず、Geminiに関していくつかの非常に基本的な問題に直面しました。

私がGeminiで指示を解釈する際に遭遇した一般的な問題は、ユニットテストの生成に関するものでした。当初の目標は記事でユニットテストを取り上げることでしたが、Geminiが指示に従わないため、いら立ちを感じて完全にGeminiの使用を諦めました。例えば、Pytestを使用してユニットテストを書き、それをクラスにカプセル化するようにGeminiに依頼しました。しかし、それはUnitTestを使用してテストを生成し、私の要求を完全に無視していましたが、コードをクラス内にカプセル化はしました。私がそれを訂正すると、誤ってUnitTestを使用したと認め、Pytestを使用してコードを書き直しましたが、それをクラスに入れることを忘れました。Mock構造を使用するように依頼すると、UnitTestのモックではなくPytestのMockをデフォルトで使用します。これらは細かい点ですが、生成AIを使用する際には重要です。

Figure 4: Gemini Advanced not following directions

図4: Geminiが指示に従わない

トラブルシューティングの失敗ももう一つの痛点でした。Pythonでのエラーをデバッグする際、GPT4の推論エンジンはかなり強力であることが証明されています。Geminiは…それほどではありません。特定の問題を修正するよう依頼したとき、それは単にインデントを追加したり変数を入れ替えたりしてコードを書き直すだけで…全く役に立たない反応でした。

時々Geminiはうまく機能しないことがありました。リクエストを処理できないと表示されました。他の場合では、...次の選挙についてコメントし始めましたか?

Gemini Advanced confused about the upcoming elections?

図5: 次の選挙について混乱しているGemini Advanced?

結論

全体として、Geminiから生成されたボイラープレートコードの品質は、GPT4に対してかなり競争力がありました。しかし、その経験と推論エンジンには、まだ望むべき点が多くありました。幸運なことにGoogleにとって、これらの部分はLLMの実装の一部であり、LLM自体ではありません。言い換えれば、Gemini LLMは、基本的にはかなり良好であり、GPT4と同等であるようですが、チャット体験で使用される周りのコードにはいくつかの改善が必要です。時間が経つにつれて、Googleはおそらく彼らのコードを反復し、その体験と推論エンジンを強化するでしょう。

筆者について

筆者について

Ariは、設計、デバイスパッケージ、テスト、および電気、機械、およびソフトウェアシステムの統合において幅広い経験を持つエンジニアです。彼は、設計/デザイン、検証、テストのエンジニアをまとめて団結したグループとして機能させることに情熱を注いでいます。

関連リソース

関連する技術文書

ホームに戻る
Thank you, you are now subscribed to updates.