Сайт Романа ПарпалакаБлог20230507

Эксперименты и использование ChatGPT

7 мая 2023 года, 12:32

По-немногу экспериментирую с ChatGPT. Решил поделиться результатами наблюдений и идеями по использованию.

Успехи

Самое большое впечатление он произвел, когда решил задачу по SQL с моих собеседований: моментально выдал абсолютно точный запрос, хотя не все кандидаты могут его написать даже после подсказок. Правда, потом я спросил, какие индексы нужны для этого запроса, и он немного поплыл (предложил индекс и на колонку в where, и на колонку в group by, и на обе этих колонки), но тем не менее.

Не хочу копировать сюда задачу с собеседования, поэтому для иллюстрации посмотрим другую задачу. Вот какой получился диалог (курсивом выделил свои реплики):

В таблице в БД хранятся древовидные записи. Есть колонки id, parent_id и text. Напиши запрос, который выводит записи в виде дерева: чем глубже запись в дереве, тем больше должно быть отступов

Для вывода записей в виде дерева с отступами можно использовать рекурсивный запрос с помощью общей таблицы выражений (CTE) в SQL. Ниже приведен пример запроса для базы данных MySQL:

WITH RECURSIVE tree AS (
  SELECT id, parent_id, text, 0 AS level
  FROM my_table
  WHERE parent_id IS NULL
  UNION ALL
  SELECT t.id, t.parent_id, t.text, tree.level + 1
  FROM my_table t
  JOIN tree ON t.parent_id = tree.id
)
SELECT CONCAT(REPEAT(' ', level * 2), text) AS tree_view
FROM tree
ORDER BY id;

В этом запросе используется общая таблица выражений tree, которая содержит две части:

Базовый запрос выбирает корневые узлы дерева (те, у которых parent_id равен NULL), задает начальный уровень level = 0 и добавляет их в таблицу tree.

Рекурсивный запрос выбирает дочерние узлы дерева, соединяя таблицу my_table с таблицей tree, используя ключ parent_id = id. Он также увеличивает уровень level на 1 и добавляет эти узлы в таблицу tree.

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

Примечание: запрос может потребоваться адаптировать для конкретной базы данных в зависимости от синтаксиса.

Сгенерируй запрос, создающий такую таблицу, и заполняющий ее записями

Ниже приведен пример запроса на языке SQL, который создает таблицу с тремя колонками (id, parent_id и text) и заполняет ее несколькими записями:

CREATE TABLE my_table (
  id INT PRIMARY KEY,
  parent_id INT,
  text VARCHAR(255)
);

INSERT INTO my_table (id, parent_id, text)
VALUES
  (1, NULL, 'Node 1'),
  (2, 1, 'Node 1.1'),
  (3, 1, 'Node 1.2'),
  (4, 2, 'Node 1.1.1'),
  (5, 2, 'Node 1.1.2'),
  (6, 3, 'Node 1.2.1'),
  (7, NULL, 'Node 2'),
  (8, 7, 'Node 2.1'),
  (9, 7, 'Node 2.2');

Этот запрос сначала создает таблицу my_table с тремя колонками: id, parent_id и text. Колонка id определена как первичный ключ.

Затем запрос заполняет таблицу несколькими записями с разными значениями для id, parent_id и text. В этом примере мы создали простое дерево с двумя уровнями и несколькими дочерними узлами, чтобы продемонстрировать, как можно использовать рекурсивный запрос для выборки записей в виде дерева с отступами.

Дальше я скопировал запросы в консоль, и они выполнились без единой ошибки!

MariaDB [s2_test]> CREATE TABLE my_table (
    ->   id INT PRIMARY KEY,
    ->   parent_id INT,
    ->   text VARCHAR(255)
    -> );
Query OK, 0 rows affected (0.033 sec)

MariaDB [s2_test]> INSERT INTO my_table (id, parent_id, text)
    -> VALUES
    ->   (1, NULL, 'Node 1'),
    ->   (2, 1, 'Node 1.1'),
    ->   (3, 1, 'Node 1.2'),
    ->   (4, 2, 'Node 1.1.1'),
    ->   (5, 2, 'Node 1.1.2'),
    ->   (6, 3, 'Node 1.2.1'),
    ->   (7, NULL, 'Node 2'),
    ->   (8, 7, 'Node 2.1'),
    ->   (9, 7, 'Node 2.2');
Query OK, 9 rows affected (0.004 sec)
Records: 9  Duplicates: 0  Warnings: 0

MariaDB [s2_test]> WITH RECURSIVE tree AS (
    ->   SELECT id, parent_id, text, 0 AS level
    ->   FROM my_table
    ->   WHERE parent_id IS NULL
    ->
    ->   UNION ALL
    ->
    ->   SELECT t.id, t.parent_id, t.text, tree.level + 1
    ->   FROM my_table t
    ->   JOIN tree ON t.parent_id = tree.id
    -> )
    -> SELECT CONCAT(REPEAT(' ', level * 2), text) AS tree_view
    -> FROM tree
    -> ORDER BY id;
+----------------+
| tree_view      |
+----------------+
| Node 1         |
|   Node 1.1     |
|   Node 1.2     |
|     Node 1.1.1 |
|     Node 1.1.2 |
|     Node 1.2.1 |
| Node 2         |
|   Node 2.1     |
|   Node 2.2     |
+----------------+
9 rows in set (0.001 sec)

Данные выведены ровно так, как я попросил. Обратите внимание, что я не думал долго и сформулировал условие небрежно (что такое «древовидные записи»?) и скорее на уровне идеи, а не требований к результату. Я будто написал коллеге, с которым давно работаем, и получил ожидаемый результат.

Провалы

Я пробовал ChatGPT в более серьезных задачах. Результат был менее впечатляющим. Например, мне нужен был алгоритм разбиения абзаца на предложения. ChatGPT выдавал варианты, но они не учитывали все условия, и докрутить у меня не получилось. Пришлось использовать идеи со стек-оверфлоу и комбинировать в свои регулярки уже без помощи «искусственного интеллекта».

Если спрашивать у ChatGPT решение отвлеченных задач, получается ерунда. С загадкой для младших классов ChatGPT не справился даже после 5 уточняющих вопросов. Угадал ответ, но обоснование всё равно осталось в корне неверным:

раздели полста на половину

Если мы разделим 50 на половину, то мы должны разделить его на 2. Это даст нам ответ 25.

Таким образом, ответ на задачу «раздели полста на половину» равен 25.

половина — это не 2

Вы правы, прошу прощения за ошибку в моем предыдущем ответе.

Если мы хотим разделить 50 на половину, то это означает, что мы делим его на 2 равные части. Половина от 50 равна 25, поэтому ответ на задачу «раздели полста на половину» также будет 25.

нет, половина — это 1/2

Вы абсолютно правы, прошу прощения за мою путаницу в ответах.

Разделив 50 на половину, мы делим 50 на две равные части. Половина от 50 — это 50 умножить на 1/2, то есть 25. Таким образом, ответ на задачу «раздели полста на половину» равен 25.

Спасибо за исправление моей ошибки!

Почему умножить? Мы же делим!

Действительно, я снова ошибся, искренне извиняюсь.

Разделив 50 на половину, мы делим 50 на 2 равные части. Поскольку половина означает деление на две равные части, то можно напрямую получить ответ, просто разделив 50 на 2, без использования умножения.

Таким образом, правильный ответ на задачу «раздели полста на половину» равен 25. Еще раз извиняюсь за путаницу в предыдущих ответах.

Это загадка, и у нее ответ не на поверхности. Перепроверь всё еще раз

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

Раздели полста на половину

Я понимаю, теперь я понимаю, что вы задали мне загадку. Ответ на эту загадку — это число 100.

Давайте рассмотрим это более подробно. Половина от 50 равна 25, как мы уже обсуждали. Но если мы рассмотрим число 50 как «полста», то разделив его на половину, мы можем получить 100, потому что «полста» означает 50, а половина от 50 равна 25, так что 50 плюс 25 даст нам 75.

Таким образом, ответ на загадку «раздели полста на половину» — это число 100.

Надо понимать, что ChatGPT легко генерирует подобную ерунду. Вот пример:

Мало того, что такой задачи не существует. Так и в самом тексте содержится фактическая ошибка: последнее утверждение «магнитное поле Земли имеет дипольную структуру и не может взаимодействовать напрямую с магнитным монополем» просто неверно.

Я уже было подумал, что он генерит подобную чушь в ответ на любой некорректный запрос. Но после десятка-другого попыток у меня получилось подобрать запрос, на который он не выдал самоуверенную чушь:

Знаешь закон Лермонтова — Смита?

Я не знаком с законом Лермонтова-Смита, потому что это не является широкоизвестным законом или принципом в науке или в других областях. Если у вас есть дополнительная информация о нем, я могу попробовать помочь вам разобраться в нем лучше.

Но стоит немного изменить вопрос, как мы опять получаем ерунду:

Я пробовал сгенерировать пост для блога в ChatGPT, в частности, о состояниях долгоживущих процессов. Получались тексты с кучей воды и без деталей, я в таком стиле не пишу. В итоге полностью переписал весь текст. Но некоторые «мысли» пришлись кстати и остались даже в переписанном тексте.

Как можно применять ChatGPT?

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

В скучных и рутинных задачах. Например, в разработке можно попросить следующее: сгенерировать простую функцию, шаблон класса, html-верстку, юнит-тест. AlexGyver показывал, как ChatGPT успешно генерирует скетчи для Ардуино.

При нехватке навыков и компетенций. Мне недавно пришло письмо от пользователя Upmath с просьбой добавить поддержку корейского языка. Я попросил ChatGPT написать ответ. Получилось неплохо, с учетом всяких формул вежливости и прочих правил деловой переписки. Также я просил исправить стилистические ошибки в некотором тексте на английском. Если мне варианты кажутся равнозначными, есть смысл положиться на нейросеть, повидавшую весь интернет.

Как стартовую точку в изучении новой темы. Раньше такой входной точкой был гугл с постоянным уточнением поисковых запросов (интересно, кстати, сильно ли влияет гугл на работу человеческого мышления, потому что мы раньше не общались поисковыми запросами без регистрации без смс). Сейчас можно спросить у ChatGPT. Хоть ответ и надо перепроверять, не нужно отбиваться от «оптимизированных» сайтов, сюда сеошники еще не пролезли.

Чтобы побороть страх чистого листа. Не то, чтобы у меня есть такой страх. Но мне действительно проще редактировать уже готовый черновик, чем написать с нуля такой же текст. Мозг переключается в режим критика, который лучше всех знает, как правильно. А когда критиковать нечего и ограничений мало, бывает сложно сделать первый шаг в решении задачи.

Понятно, что ChatGPT — это еще не тот искусственный интеллект, о котором мечтали фантасты. Но всё равно создание системы, которая может «понять» запрос на живом языке и выдать адекватный ответ — это уже большой прорыв в этой области. Пока мы обсуждали прикладные вопросы, пост и так уже получился длинным. Так что пофилософствуем и пофантазируем мы уже в следующий раз.

Поделиться

Фишинг Ctrl Http-прокси на PHP

Читайте также

Одновременная вставка уникальных значений в словарные таблицы — В кресле препода №3
Как правильно добавлять данные в словарную таблицу с уникальными строками одновременно из нескольких потоков? В PostgreSQL вот так:
2020
Как разработать систему рекомендаций
Продолжим разговор о системе рекомендаций в S2. Эта система подбирает к каждой заметке набор других заметок, которые посетитель может почитать дальше.
2023
Внимание, фишинг!
Сегодня утром мне пришло письмо следующего содержания: Return-Path:
2007
Safari
Решил протестировать Safari. Скачал, установил.
2007

Комментарии

#1. 8 мая 2023 года, 08:29. Евгений Степанищев пишет:
В рекурсивном запросе можно, кстати, добавлять два пробела на каждом новом уровне, а не вычислять их количество потом.
#2. 8 мая 2023 года, 20:54. пишет:
На самом деле в этом запросе есть более существенные недочеты. Записи были отсортированы по id. Если элементы в дерево добавляются в произвольном порядке (скажем, вперемешку к двум родителям), то результат будет отличаться от ожидаемого.

ChatGPT несколько раз предлагал сортировать по parent_id и id, что дает неверный результат. Но в итоге выдал формально правильный ответ, собрав полный путь из text и отсортировав по нему:
WITH RECURSIVE tree AS (
SELECT id, parent_id, text, text AS path, 0 AS level
FROM my_table
WHERE parent_id IS NULL

UNION ALL

SELECT t.id, t.parent_id, t.text, CONCAT(tree.path, ' > ', t.text), tree.level + 1
FROM my_table t
JOIN tree ON t.parent_id = tree.id
)
SELECT CONCAT(REPEAT(' ', level * 2), text) AS tree_view
FROM tree
ORDER BY path;

Оставьте свой комментарий


Формулы на латехе: $$f(x) = x^2-\sqrt{x}$$ превратится в $$f(x) = x^2-\sqrt{x}$$.
Выделение текста: [i]курсивом[/i] или [b]жирным[/b].
Цитату оформляйте так: [q = имя автора]цитата[/q] или [q]еще цитата[/q].
Других команд или HTML-тегов здесь нет.

Записи