Провел эксперимент по вайбкодингу с 7 нейронками: 6 писали код, а последняя оценила их работу и предложила свой вариант

-

Хочу поделиться результатом небольшого эксперимента по вайбкодингу. Поставил перед несколькими нейронками одну и ту же задачу – написать код для решения одной и той же задачи. Всего воспользовался несколькими нейронками:

  1. Llama 3.1 на 8b – работает оффлайн на моем компьютере через Ollama
  2. qwen3 vl на 8b – также работает на моем компьютере через LM Studio
  3. Claude Sonnet 4.5
  4. ChatGPT 5.2
  5. Grok
  6. Mistral

Да, я понимаю, что сравнение между ними не совсем корректное с научной точки зрения, потому что у них разные возможности, мощности, параметры и прочие характеристики. Но это оправдано с точки зрения доступа к ним со стороны обычного пользователя. Именно как обычный пользователь я веду себя в этом эксперименте, чтобы понять, чего можно достичь и как, используя нейронки с разным уровнем “прокаченности” и доступа.

Задача

Задача же для всех нейронок звучала так:

Напиши код на Python 3, который будет искат в предоставленном файле CSV вот такие текста:  [интернете] (https://www.itu.int/itu-d/reports/statistics/2023/10/10/ff23-youth-internet-use/?utm_source=chatgpt.com)  Код должен превращать такие выражения в такой HTML:  <a href=’https://www.itu.int/itu-d/reports/statistics/2023/10/10/ff23-youth-internet-use/?utm_source=chatgpt.com’>интернете</a>

Чтобы оценка работы нейронок была также более объективной, сделать это попросил Gemini. В последнее время я всё чаще замечаю, что с кодингом у него получается довольно хорошо. И, чтобы он не понял, что оценивает код других нейронок, ему я сказал, что их написали люди и каждой нейронке дал такие имена:

  1. Llama – Матинбек
  2. qwen3 – Курбон
  3. Claude – Клавдия
  4. ChatGPT – Фарход
  5. Grok – Илон
  6. Mistral – Мишель

Полный промпт

Мой полный промпт был таким – он содержит как роль и задачу самому Gemini, так и весь код, написанный другими нейронками:

Представь, что ты - профессиональный сеньор Python разработчик.

Твоя задача - сделать ревью кодов, которые прислали тебе твои подчиненные.

Перед каждым из них была поставлена одна и та же задача, которая звучала так:
```
Напиши код на Python 3, который будет искат в предоставленном файле CSV вот такие текста:  [интернете] (https://www.itu.int/itu-d/reports/statistics/2023/10/10/ff23-youth-internet-use/?utm_source=chatgpt.com)  Код должен превращать такие выражения в такой HTML:  <a href='https://www.itu.int/itu-d/reports/statistics/2023/10/10/ff23-youth-internet-use/?utm_source=chatgpt.com'>интернете</a>
```

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

Код от Матинбека:
```
import pandas as pd

# Обработчик CSV-файла
def process_csv(file_path):
    # Загружаем файл в Dataframe (объект для работы с данными)
    df = pd.read_csv(file_path)

    # Регулярное выражение, которое мы будем использовать для поиска и замены текста
    pattern = r'\[(интернете]\(https://www\.itu\.int/itu-d/reports/statistics/\d{4}/\d{2}/\d{2}/ff23-youth-internet-use/\?utm_source=chatgpt\.com\)\?'

    # Функция замены текста
    def replace_text(text):
        import re
        return re.sub(pattern, lambda x: f'<a href="{x.group(0)[1:-1]}">интернете</a>', text)

    # Применяем замену всем строкам в Dataframe
    df['column_name'] = df.apply(replace_text, axis=1)  # Replace 'column_name' with the actual column name

    # Сохраняем измененный файл CSV
    output_file_path = file_path.replace('.csv', '_processed.csv')
    df.to_csv(output_file_path, index=False)

# Используем функцию для обработки файла CSV
process_csv('input.csv')  # Replace 'input.csv' with the actual path to your input file

```

Код от Курбона:
```
import csv
import re

def replace_links_in_cell(cell):
    """
    Заменяет в ячейке строки вида: [текст] (URL) на <a href='URL'>текст</a>
    """
    if not isinstance(cell, str):
        return cell

    # Регулярное выражение для поиска шаблона: [текст] (URL)
    # Группируем текст и URL
    pattern = r'$([^$]+)$\s*$([^)]+)$'
    def replace_func(match):
        text = match.group(1)
        url = match.group(2)
        return f"<a href='{url}'>{text}</a>"

    result = re.sub(pattern, replace_func, cell)
    return result

def process_csv(input_file, output_file):
    with open(input_file, newline='', encoding='utf-8') as infile, \
         open(output_file, 'w', newline='', encoding='utf-8') as outfile:

        reader = csv.reader(infile)
        writer = csv.writer(outfile)

        # Чтение заголовков
        headers = next(reader)
        writer.writerow(headers)

        # Обработка каждой строки
        for row in reader:
            new_row = [replace_links_in_cell(cell) for cell in row]
            writer.writerow(new_row)

if __name__ == "__main__":
    input_csv = "input.csv"   # Замените на путь к вашему файлу
    output_csv = "output.csv"  # Выходной файл

    process_csv(input_csv, output_csv)
    print(f"Обработка завершена. Результат сохранён в {output_csv}")

```

И код, написанный Клавдией:
```
import csv
import re

def convert_markdown_links_to_html(text):
    """
    Преобразует ссылки формата [текст] (url) в HTML формат <a href='url'>текст</a>
    """
    # Паттерн для поиска ссылок в формате [текст] (url)
    # Обратите внимание на пробел между ] и (
    pattern = r'\[([^\]]+)\]\s*\(([^\)]+)\)'
    
    # Заменяем найденные совпадения на HTML-ссылки
    html_text = re.sub(pattern, r"<a href='\2'>\1</a>", text)
    
    return html_text

def process_csv_file(input_file, output_file):
    """
    Обрабатывает CSV файл, преобразуя markdown-ссылки в HTML
    """
    with open(input_file, 'r', encoding='utf-8') as infile, \
         open(output_file, 'w', encoding='utf-8', newline='') as outfile:
        
        reader = csv.reader(infile)
        writer = csv.writer(outfile)
        
        for row in reader:
            # Обрабатываем каждую ячейку в строке
            processed_row = [convert_markdown_links_to_html(cell) for cell in row]
            writer.writerow(processed_row)
    
    print(f"Обработка завершена. Результат сохранён в {output_file}")

# Пример использования
if __name__ == "__main__":
    input_filename = "input.csv"  # Укажите имя вашего входного файла
    output_filename = "output.csv"  # Укажите имя выходного файла
    
    process_csv_file(input_filename, output_filename)
    
    # Пример тестирования функции преобразования
    test_text = "[интернете] (https://www.itu.int/itu-d/reports/statistics/2023/10/10/ff23-youth-internet-use/?utm_source=chatgpt.com)"
    print("\nПример преобразования:")
    print(f"До: {test_text}")
    print(f"После: {convert_markdown_links_to_html(test_text)}")

```

Код, написанный Фарходом:
```
#!/usr/bin/env python3
import csv
import re
import html
import argparse

# Ищем: [текст] (url)
# Пробел между ] и ( допускаем; url берём до закрывающей скобки.
PATTERN = re.compile(r"\[([^\]]+)\]\s*\(([^)]+)\)")

def replace_md_links_with_html(value: str) -> str:
if not isinstance(value, str) or not value:
return value

def _repl(m: re.Match) -> str:
text = m.group(1)
url = m.group(2).strip()

# Экранируем текст и URL для HTML
safe_text = html.escape(text, quote=False)
safe_url = html.escape(url, quote=True)

return f"<a href='{safe_url}'>{safe_text}</a>"

return PATTERN.sub(_repl, value)

def process_csv(input_path: str, output_path: str, delimiter: str = ",") -> None:
with open(input_path, "r", encoding="utf-8", newline="") as f_in:
reader = csv.reader(f_in, delimiter=delimiter)
rows = list(reader)

out_rows = []
for row in rows:
out_rows.append([replace_md_links_with_html(cell) for cell in row])

with open(output_path, "w", encoding="utf-8", newline="") as f_out:
writer = csv.writer(f_out, delimiter=delimiter, quoting=csv.QUOTE_MINIMAL)
writer.writerows(out_rows)

def main():
ap = argparse.ArgumentParser(description="Convert markdown-like links [text] (url) in CSV to HTML <a> tags.")
ap.add_argument("input_csv", help="Path to input CSV")
ap.add_argument("output_csv", help="Path to output CSV")
ap.add_argument("--delimiter", default=",", help="CSV delimiter (default: ,). For ; use --delimiter ';'")
args = ap.parse_args()

process_csv(args.input_csv, args.output_csv, delimiter=args.delimiter)

if __name__ == "__main__":
main()

```

Код, который написал Илон:
```
import re
import csv
import sys
from pathlib import Path

# Регулярное выражение для поиска markdown-ссылок
# Группа 1 → текст, Группа 2 → url
LINK_PATTERN = r'\[([^\]]+)\]\((https?://[^\s\)]+)\)'

def convert_markdown_links_to_html(text: str) -> str:
def replace_link(match):
text_part = match.group(1)
url_part = match.group(2)
return f'<a href="{url_part}">{text_part}</a>'

return re.sub(LINK_PATTERN, replace_link, text)


def process_csv_file(input_path: str, output_path: str = None, encoding='utf-8'):
input_path = Path(input_path)

if not input_path.is_file():
print(f"Файл не найден: {input_path}", file=sys.stderr)
return

if output_path is None:
output_path = input_path.with_name(input_path.stem + "_converted" + input_path.suffix)

converted_rows = []
links_found = 0

with open(input_path, encoding=encoding, newline='') as f_in:
reader = csv.reader(f_in)
header = next(reader, None) # читаем заголовок, если есть

if header:
converted_rows.append(header)

for row in reader:
new_row = []
for cell in row:
if not cell:
new_row.append(cell)
continue

new_cell = convert_markdown_links_to_html(cell)
if new_cell != cell:
links_found += len(re.findall(LINK_PATTERN, cell))
new_row.append(new_cell)
converted_rows.append(new_row)

# Записываем результат
with open(output_path, 'w', encoding=encoding, newline='') as f_out:
writer = csv.writer(f_out)
writer.writerows(converted_rows)

print(f"Обработано строк: {len(converted_rows)}")
print(f"Найдено и заменено ссылок: {links_found}")
print(f"Результат сохранён в: {output_path}")


# ────────────────────────────────────────────────
# Пример использования

if __name__ == "__main__":
# Измените на свой путь к файлу
FILE_PATH = "your_file.csv"

process_csv_file(
FILE_PATH,
# output_path="result.html.csv", # можно указать, если хотите другое имя
encoding="utf-8" # или "utf-8-sig", "windows-1251" и т.д.
)
```

И последний код, который написал Мишель:
```
import csv
import re

def replace_markdown_links_with_html(input_file, output_file):
# Регулярное выражение для поиска Markdown-ссылок
pattern = re.compile(r'\[([^\]]+)\]\(([^)]+)\)')

with open(input_file, mode='r', encoding='utf-8') as csv_input, \
open(output_file, mode='w', encoding='utf-8', newline='') as csv_output:

reader = csv.reader(csv_input)
writer = csv.writer(csv_output)

for row in reader:
# Обрабатываем каждую ячейку в строке
processed_row = []
for cell in row:
# Заменяем все найденные Markdown-ссылки на HTML-теги
processed_cell = pattern.sub(r"<a href='\2'>\1</a>", cell)
processed_row.append(processed_cell)
writer.writerow(processed_row)

# Пример использования:
input_csv = 'input.csv' # Замените на имя вашего входного файла
output_csv = 'output.csv' # Замените на имя выходного файла
replace_markdown_links_with_html(input_csv, output_csv)
```

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

Лучший по мнению Gemini результат показал Фарход (ChatGPT), хотя и в его работе Gemini нашел определенные недостатки.

Полный ответ Gemini:

Приветствую. Как Senior Python Developer, я провел ревью кода твоих подопечных. Задача кажется простой на первый взгляд, но она требует внимания к деталям: обработке больших файлов, безопасности (XSS), гибкости регулярных выражений и корректной работе с форматом CSV.

Ниже представлен детальный разбор полетов по каждому сотруднику и мой вариант эталонного решения.


Ревью кода сотрудников

1. Матинбек: “Худший результат”

  • Ошибки:

    • Регулярное выражение: Это катастрофа. Паттерн захардкожен под одну конкретную ссылку. Если завтра ссылка изменится, код бесполезен. К тому же, в паттерне синтаксические ошибки (несбалансированные скобки).

    • Производительность: Использование df.apply на всем DataFrame в Pandas для такой задачи — это “стрельба из пушки по воробьям” с огромным потреблением памяти.

    • Импорт внутри функции: import re внутри replace_text — это плохой тон (PEP 8).

    • Логика: x.group(0)[1:-1] просто обрежет первый и последний символ всей найденной строки, что не создаст корректный URL.

2. Курбон: “Ошибся в базе”

  • Ошибки:

    • Регулярное выражение: Паттерн r'$([^$]+)$\s*$([^)]+)$' абсолютно неверен. Символ $ в regex означает конец строки. Он пытался экранировать скобки, но перепутал символы.

    • Память: Код читает и пишет построчно (через csv.reader), что хорошо для памяти.

  • Плюсы: Разделил логику на функции.

3. Клавдия: “Хороший середнячок”

  • Ошибки:

    • Безопасность: Не учитывает, что в тексте могут быть спецсимволы HTML, которые могут “сломать” верстку или привести к XSS-уязвимости.

    • Регулярное выражение: Достаточно точное, учитывает возможный пробел между скобками.

  • Плюсы: Чистый код, наличие примера для тестирования.

4. Фарход: “Почти профессионал”

  • Плюсы: Лучший из представленных.

    • Использует html.escape — это критически важно для безопасности.

    • Использует argparse для запуска из консоли.

    • Предварительно компилирует регулярное выражение (re.compile).

  • Ошибки: Зачем-то делает list(reader), загружая весь файл в память. На огромных CSV это вызовет MemoryError.

5. Илон: “Перемудрил”

  • Плюсы: Использует pathlib, проверяет существование файла.

  • Ошибки:

    • Паттерн https?://... слишком строгий. Markdown-ссылка может быть относительной (на внутренние страницы сайта).

    • Опять же, загружает всё в список converted_rows.

    • Счетчик ссылок — лишняя работа, замедляющая процесс.

6. Мишель: “Просто и работает (но опасно)”

  • Плюсы: Самый лаконичный и понятный код. Правильно использует генератор для обработки строк.

  • Ошибки: Нет обработки исключений и экранирования HTML.


Итоговый профессиональный код

Как твой Senior, я подготовил версию, которая:

  1. Потоковая: Читает файл построчно (не ест память).

  2. Безопасная: Экранирует данные для HTML.

  3. Гибкая: Обрабатывает любые Markdown-ссылки, а не только одну конкретную.

Python

import csv
import re
import html
import logging
from pathlib import Path

# Настраиваем логирование
logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')

# Регулярное выражение: [текст](ссылка) или [текст] (ссылка)
# Ищем нежадно [^\]]+ чтобы корректно обрабатывать несколько ссылок в строке
LINK_PATTERN = re.compile(r'\[([^\]]+)\]\s*\(([^)]+)\)')

def md_to_html_link(match: re.Match) -> str:
    """Callback-функция для безопасной замены MD на HTML."""
    text = match.group(1)
    url = match.group(2).strip()
    
    # Экранируем спецсимволы (напр. & в URL или < в тексте), чтобы не "развалить" HTML
    safe_text = html.escape(text)
    safe_url = html.escape(url, quote=True)
    
    return f"<a href='{safe_url}'>{safe_text}</a>"

def process_csv(input_file: str, output_file: str):
    """
    Обрабатывает CSV файл потоково, заменяя Markdown ссылки на HTML теги.
    """
    input_path = Path(input_file)
    if not input_path.exists():
        logging.error(f"Файл {input_file} не найден.")
        return

    try:
        with open(input_path, 'r', encoding='utf-8', newline='') as f_in, \
             open(output_file, 'w', encoding='utf-8', newline='') as f_out:
            
            reader = csv.reader(f_in)
            writer = csv.writer(f_out)

            for row_idx, row in enumerate(reader, 1):
                # Обработка каждой ячейки через регулярное выражение
                processed_row = [LINK_PATTERN.sub(md_to_html_link, cell) for cell in row]
                writer.writerow(processed_row)
                
                if row_idx % 1000 == 0:
                    logging.info(f"Обработано {row_idx} строк...")

        logging.info(f"Успешно! Результат сохранен в: {output_file}")

    except Exception as e:
        logging.error(f"Произошла ошибка при обработке: {e}")

if __name__ == "__main__":
    # В реальном проекте здесь был бы argparse, но для текущей задачи достаточно так:
    INPUT = 'input.csv'
    OUTPUT = 'output_processed.csv'
    process_csv(INPUT, OUTPUT)

Почему этот код лучше:

  1. Память: Мы не используем list(reader) или df.apply. Даже если в CSV будет 10 миллионов строк, программа потребит всего пару мегабайт ОЗУ.

  2. Безопасность: Если в ссылке из твоего примера есть ?utm_source=...&other=..., символ & будет корректно превращен в &amp;, как того требуют стандарты HTML.

  3. Читаемость: Использование pathlib и logging — это стандарт современной разработки на Python.

  4. Надежность: Мы используем newline='', как рекомендует документация модуля csv, чтобы избежать проблем с переносами строк на разных ОС.

Вместо выводов

Конкретные выводы делать я не буду, призываю сделать это профессиональных Python-разработчиков. Поделитесь своим мнением, как вам работа этих нейронок? Смогли ли они сделать всё правильно? И как отработал Gemini – смогли ли он сделать нормальный анализ?

В свою очередь скажу, что его код сработал с первого раза без каких-либо ошибок.

Rustam Gulov
Rustam Gulovhttps://alifbo.media
Независимый медиа-тренер и консультант, блоггер, сооснователь первой фактчек-платформы Таджикистана Factcheck.tj и блогплатфоры Blogiston.tj. Веду данный авторский проект Alifbo.Media - образовательный ресурс о новых медийных технологиях, трендах, онлайн-сервисах для подготовки мультимедийных материалов. В свободное время читаю, веду канал на Телеграм, создаю сайты, программирую.

Поделиться постом

Свежее

TOP рубрик

ОСТАВЬТЕ ОТВЕТ

Пожалуйста, введите ваш комментарий!
пожалуйста, введите ваше имя здесь