Двойники против ChatGPT: Кто пишет лучший код?

Ari Mahpour
|  Создано: 1 Марта, 2024  |  Обновлено: 2 Апреля, 2024
Двойник против ChatGPT

 

Те времена, когда электротехники могли обходиться без написания хотя бы одной строки кода, ушли в прошлое. Умение программировать стало необходимым навыком для инженеров всех специализаций. Хотя инженерам и не требуется понимать, как написать полноценное веб-приложение, важно, чтобы у них были базовые навыки скриптинга. Анализ больших данных, например, требует некоторых знаний в программировании. Для более сложных задач инженеры могут оказаться в тупике, иногда проводя часы в поисках в интернете определенной функции или решения. С выпуском ChatGPT мир, безусловно, изменился, как и ландшафт автоматизированной генерации кода. Теперь инженеры без глубоких знаний могут писать код высокого качества с помощью генеративного ИИ.

В предыдущих статьях, таких как Использование ChatGPT для скриптинга в Altium и Использование ChatGPT для автоматизированного тестирования, мы рассматривали, как использовать генеративный ИИ, в частности ChatGPT, для написания кода за нас. До сих пор Google Bard (конкурент ChatGPT) отставал, но новая модель, Gemini, заявляет, что превосходит своего конкурента по шкале понимания многофункционального языка (MMLU):

Figure 1: Gemini’s MMLU  performance metric

Рисунок 1: Метрика производительности MMLU Gemini. Источник: https://deepmind.google/technologies/gemini/#capabilities

В этой статье мы собираемся сравнить самый совершенный движок ChatGPT, GPT4, с Gemini Advanced (ранее известным как Ultra), самым продвинутым AI движком Google, чтобы увидеть, кто лучше генерирует код.

Шаблонный код

Провести полное исчерпывающее сравнение между двумя движками было бы чрезвычайно сложно. В этой статье мы собираемся посмотреть, насколько хорошо эти два движка генерируют шаблонный код на 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: Веб-скрейпер

Для следующей задачи я хотел проверить, насколько хорошо оба движка могут понимать данный язык и создавать на его основе парсер. В данном случае мы собираемся построить веб-скрейпер, используя следующее задание:
Напишите скрипт на Python с использованием BeautifulSoup или Scrapy, который собирает заголовки главных новостей с 'https://news.ycombinator.com' и выводит их в объект словаря.

Вот фрагмент исходного кода страницы с 'https://news.ycombinator.com'. Используйте это, чтобы определить, как анализировать теги.

Напишите скрипт на Python с использованием BeautifulSoup или Scrapy, который собирает заголовки главных новостей с 'https://news.ycombinator.com' и выводит их в объект словаря.

Вот фрагмент исходного кода страницы с 'https://news.ycombinator.com'. Используйте это, чтобы определить, как анализировать теги.

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

# Отправить GET запрос на URL
response = requests.get(url)

# Разобрать HTML содержимое страницы с помощью BeautifulSoup
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)

Этот код работает нормально и делает то, что от него требуется. Я надеялся, что он интуитивно поймет, что мне нужны ссылки на статьи, но я не был в этом ясен, поэтому не могу считать это минусом для оценки GPT4.

Вот что сгенерировал Gemini:

import requests
from bs4 import BeautifulSoup

# Отправляем HTTP GET запрос на веб-сайт Hacker News
response = requests.get("https://news.ycombinator.com/")

# Разбор HTML-контента с использованием BeautifulSoup
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()

    для акции в stocks:
        df = yf.download(акция, start=start, end=end)
        fig.add_trace(go.Scatter(x=df.index, y=df.Close, mode='lines', name=акция))

    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)

Также потребовалось создать новый файл, index.html, в новой папке под названием templates:

<!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 впервые появился, потребовалось время, чтобы понять, как правильно его "запускать". При использовании генеративного ИИ для написания кода, детали имеют значение. В результате многие из нас стали более компетентными "инженерами по запросам" за прошедший год. К сожалению, это может внести некоторую предвзятость при сравнении GPT4 с другими движками, и я готов признать это. Я знаю, как "работает" GPT4 лучше, чем Gemini. Способ, которым я формулирую запросы для GPT4, может отличаться от того, что ожидает Gemini. Тем не менее, я все равно столкнулся с некоторыми очень фундаментальными проблемами с Gemini.

Одна из общих проблем, с которой я столкнулся, используя Gemini для интерпретации инструкций, заключалась в генерации модульных тестов. Моей первоначальной целью было охватить тему модульного тестирования в статье, но, из-за разочарования, я полностью отказался от использования Gemini, так как оно никогда не следовало инструкциям. Например, я просил Gemini написать модульный тест с использованием Pytest и инкапсулировать его в класс. Вместо этого оно генерировало тест с использованием UnitTest, полностью игнорируя мою просьбу, но инкапсулировало код в класс. Я исправлял его, и оно признавало, что случайно использовало UnitTest вместо Pytest. Затем оно переписывало код с использованием Pytest, но забывало поместить его в класс. Когда я просил использовать конструкцию Mock, оно по умолчанию использовало mock из UnitTest вместо Mock из Pytest. Это нюансы, но они важны при работе с генеративным ИИ.

Figure 4: Gemini Advanced not following directions

Рисунок 4: Gemini не следует инструкциям

Устранение неудач было еще одной больной точкой. Разум машины GPT4 оказался довольно мощным при отладке ошибок в Python. Gemini… не так уж и много. Когда я просил его исправить определенные проблемы, оно просто пыталось переписать код, добавляя отступы или меняя переменные… совершенно бесполезный ответ.

Иногда Gemini просто не работал. Он сообщал, что не может обработать мой запрос. В других случаях он начинал комментировать... предстоящие выборы?

Gemini Advanced confused about the upcoming elections?

Рисунок 5: Gemini Advanced запутался в предстоящих выборах?

Заключение

В целом, качество генерируемого шаблонного кода от Gemini было довольно конкурентоспособным по сравнению с GPT4. Однако опыт использования и его логический механизм оставляли желать лучшего. К счастью для Google, эти элементы являются частью реализации LLM, а не самого LLM. Другими словами, LLM Gemini, по сути, довольно хорош и наравне с GPT4, но код, написанный вокруг него и используемый в чате, требует доработки. Со временем, вероятно, мы увидим, как Google будет дорабатывать свой код и улучшать этот опыт и логический механизм.

Об авторе

Об авторе

Ари — инженер с большим опытом работы в сфере проектирования, производства, тестирования и интеграции электрических, механических и программных систем. Он стремится к созданию дружного сообщества специалистов по разработке, верификации и тестированию решений.

Связанные ресурсы

Связанная техническая документация

Вернуться на главную
Thank you, you are now subscribed to updates.