Discourse AI + Data Explorer?

Сегодня я решил, что хочу получить особенно сложный запрос. Не желая слишком сильно отвлекать моих инженеров, я попросил ChatGPT написать для меня запрос к Data Explorer на основе того, что я знал и чего хотел добиться. Я был весьма впечатлён тем, что он всё сделал правильно (за исключением добавления лишней точки с запятой в конце).

Вот запрос, который он сгенерировал для меня, когда я указал некоторые параметры и попросил создать запрос, возвращающий накопительную сумму всех пользователей по месяцам:

SELECT 
    timeframe "Month, Year",
    user_count as "Users Joined This Month",
    SUM(user_count) OVER (ORDER BY TO_DATE(timeframe, 'Month, YYYY'))::integer as "Users (Running Total)"
FROM (
    SELECT 
        TO_CHAR(u.created_at, 'Month, YYYY') as "timeframe",
        count(u.id) as "user_count"
    FROM 
        users u
    GROUP BY 
        timeframe
    ORDER BY
        timeframe
) subquery
ORDER BY 
    TO_DATE(timeframe, 'Month, YYYY')

Было ли уже рассмотрено внедрение искусственного интеллекта в область Data Explorer? :slight_smile:

12 лайков

Пост был перенесён в новую тему: Можно ли снова открыть тему для обмена запросами Explorer?

Не могли бы вы поделиться промптом, версией ChatGPT и используемой моделью? :slightly_smiling_face:

Например:


Версия ChatGPT от 3 августа
Модель: GPT-3.5
Промпт

Что такое Discourse Data Explorer?

Ответ

По состоянию на последнее обновление в сентябре 2021 года мне не известно о существовании конкретного инструмента или продукта под названием «Discourse Data Explorer». Однако я могу дать общее объяснение на основе информации, доступной на тот момент.

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

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

Учитывая эти два компонента, «Discourse Data Explorer» мог бы быть гипотетическим инструментом или плагином, который предоставляет пользователям возможность исследовать и выполнять запросы к данным внутри форума Discourse. Это могло бы быть полезно для администраторов сообщества или аналитиков данных, желающих получить представление о поведении пользователей, тенденциях контента или других метриках, связанных с обсуждениями на форуме.

Важно отметить, что моя информация может быть устаревшей, и после последнего обновления могли произойти новые события. Если «Discourse Data Explorer» действительно является реальным продуктом или функцией, рекомендую поискать актуальную информацию для получения точных сведений о его возможностях и использовании.


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

Примечание: Я являюсь модератором категории на форуме OpenAI в Discourse, поэтому имею большой опыт работы с теми, кто ищет помощь в создании промптов для ChatGPT. (ссылка)


Версию ChatGPT можно найти в правом нижнем углу под полем ввода промпта:

Модель указана в верхней части страницы, в центре:

image

1 лайк

Я… не люблю этого бота.

1 лайк

Расширяя эту идею, возможность взаимодействия пользователей с приложениями на естественном языке — это практически моя мечта в области ИИ. С помощью Discourse и плагина Data Explorer стало бы возможным получать результаты по запросам вроде «верни список пользователей, выразивших интерес к модерации». Или ещё лучше: «отправь приглашение группе community_moderation всем пользователям, выразившим интерес к модерации».

Вернёмся к тому, что возможно уже сейчас:

При тестировании с ChatGPT 3.0 и 3.5 я получал хорошие результаты, когда просил его вернуть запрос PostgreSQL и включал в промпт структуру таблиц, которые меня интересовали. Например:

Сводка

Я: Верни запрос PostgreSQL, который выводит все имена пользователей из группы “community_moderators” для следующей структуры базы данных:

# == Schema Information
#
# Table name: groups
#
#  id                                 :integer          not null, primary key
#  name                               :string           not null

# == Schema Information
#
# Table name: group_users
#
#  id                 :integer          not null, primary key
#  group_id           :integer          not null

# == Schema Information
#
# Table name: users
#
#  id                        :integer          not null, primary key
#  username                  :string(60)       not null

ChatGPT 3.5: Конечно, вот запрос PostgreSQL, который выводит все имена пользователей из группы “community_moderators” на основе указанной структуры базы данных:

SELECT u.username
FROM users u
JOIN group_users gu ON u.id = gu.user_id
JOIN groups g ON gu.group_id = g.id
WHERE g.name = 'community_moderators';

Этот запрос извлекает имена пользователей из таблицы users, присоединяя её к таблице group_users по ID пользователя, а затем присоединяя таблицу groups по ID группы. Результаты фильтруются так, чтобы включать только имена пользователей, состоящих в группе “community_moderators”.

Я: Вот структура таблиц topics и posts приложения:

# == Schema Information
#
# Table name: topics
#
#  id                        :integer          not null, primary key
#  title                     :string           not null

# == Schema Information
#
# Table name: posts
#
#  id                      :integer          not null, primary key
#  user_id                 :integer
#  topic_id                :integer          not null
#  post_number             :integer          not null
#  raw                     :text             not null

Верни запрос, который выводит все ID тем, ID постов и имена пользователей для всех постов, созданных участниками группы “community_moderators”, которые дают некоторое указание на интерес автора к тому, как модерировать поляризующие дискуссии.

ChatGPT 3.5: Для этого необходимо соединить таблицы posts, topics, users и group_users на основе предоставленной схемы. Вот запрос PostgreSQL, который извлекает запрошенную информацию:

SELECT t.id AS topic_id, p.id AS post_id, u.username
FROM posts p
JOIN topics t ON p.topic_id = t.id
JOIN users u ON p.user_id = u.id
JOIN group_users gu ON u.id = gu.user_id
JOIN groups g ON gu.group_id = g.id
WHERE g.name = 'community_moderators'
  AND (p.raw ILIKE '%moderate%' OR p.raw ILIKE '%polarizing%' OR p.raw ILIKE '%discussion%');

Этот запрос извлекает topic_id, post_id и username для всех постов, созданных участниками группы “community_moderators”, которые содержат определённые ключевые слова, указывающие на интерес к модерации поляризующих дискуссий. Оператор ILIKE используется для регистронезависимого поиска по шаблону в столбце raw таблицы posts.

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

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

ChatGPT 3.5: Для этого можно использовать следующий запрос PostgreSQL, который возвращает количество постов, созданных в каждом недельном периоде с сентября 2022 года, авторами которых являются участники группы “community_moderators” и которые указывают на интерес к тому, как модерировать поляризующие дискуссии:

SELECT
    DATE_TRUNC('week', p.created_at) AS week_start,
    COUNT(p.id) AS post_count
FROM
    posts p
JOIN
    users u ON p.user_id = u.id
JOIN
    group_users gu ON u.id = gu.user_id
JOIN
    groups g ON gu.group_id = g.id
WHERE
    g.name = 'community_moderators'
    AND (p.raw ILIKE '%moderate%'
         OR p.raw ILIKE '%polarizing%'
         OR p.raw ILIKE '%political%'
         OR p.raw ILIKE '%contentious%'
         OR p.raw ILIKE '%debate%'
         OR p.raw ILIKE '%controversial%'
         OR p.raw ILIKE '%discussion%')
    AND p.created_at >= '2022-09-01' -- Начальная дата: сентябрь 2022
GROUP BY
    week_start
ORDER BY
    week_start;

Этот запрос вычисляет количество постов, созданных участниками группы “community_moderators”, которые содержат указанные ключевые слова, в каждом недельном периоде с сентября 2022 года. Результаты группируются по неделям и сортируются в хронологическом порядке. Убедитесь, что вы скорректировали названия столбцов и связи таблиц в соответствии с вашей реальной схемой базы данных.


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

4 лайка

О, это здорово! У меня были неоднозначные результаты с SQL-запросами в ChatGPT Data Explorer, но такой подход кажется очень логичным. Я даже не подумал о том, чтобы предоставить структуру таблиц и попросить запросы для PostgreSQL. :woman_facepalming:t2: Спасибо за совет, @simon :slight_smile:

1 лайк

Можно ли где-то увидеть полную схему базы данных Discourse?

1 лайк

Привет @so-jordan-violet, я просто использую инструмент сворачиваемой таблицы (не знаю, как он называется! lol) справа в интерфейсе редактирования запросов в Data Explorer:

2 лайка

Если у нас будет текстовый документ (особенно в формате SQL CREATE TABLE), мы сможем использовать его в качестве инструкции и, скорее всего, получить довольно надёжные результаты.

1 лайк

Да, этот пункт находится в очереди задач команды ИИ с начала этого года. Идея заключается в том, чтобы включить в промпт всю (или наиболее важную часть) схему Discourse, чтобы модель могла формировать любые запросы.

Мы создали репозиторий GitHub - discourse/data-explorer-examples: Examples for Discourse Data Explorer · GitHub, чтобы предоставить модели примеры, что поможет улучшить её точность.

7 лайков

Жаль, что у меня нет больше времени, чтобы изучить кодовую базу, но у вас есть SQL-скрипты где-то (публично) для схем таблиц crests?

Я сейчас занимаюсь работой с LLM для своего собственного продукта/компании и с удовольствием бы поэкспериментировал с этим.

1 лайк

О, это замечательно! Спасибо за ссылку, Falco! :slight_smile:

3 лайка

Я просто генерирую это напрямую из схемы.

Что-то вроде этого должно помочь вам начать:


Я пробовал самые разные подходы к решению этой задачи. Однако одна проблема заключается в том, что GPT 3.5 настолько податлив, что начинает путаться.

Конечно, предоставление схемы помогает, но я обнаружил, что мне нужно быть предельно стратегичным в выборе примеров.

Просто рассказ ему истории о том, «как подсчитать архивированные темы для пользователя», приводит к тому, что запрос вроде «сколько постов было у пользователя» начинает относиться к архивированным темам.

Я думал так:

graph TD
A[Добавить общую полезную информацию] --> B[Сгенерировать эмбеддинги для вопроса]
B --> C[Выполнить поиск по сходству среди примеров]
C --> D[Добавить 3 примера в промпт]
D --> E[Добавить схему в промпт]
E --> F[Задать вопрос]
F --> G[Получить SQL]

Но оказалось, что если примеры не выдающиеся и вы не включаете никакие контрпримеры… всё идёт наперекосяк.

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

5 лайков

У вас есть полная схема, показывающая типы данных?

Не уверен, что это укладывается в лимит токенов, попробую

С ChatCPT 3.5 я получаю неожиданные результаты, когда предоставляю полную схему. Например, модель продолжает пытаться найти автора темы в таблице topic_users.

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

# Имя таблицы: user_actions
#
#  id              :integer          not null, primary key
#  action_type     :integer          not null (:like=>1,:was_liked=>2,:new_topic=>4,:reply=>5,:response=>6,:mention=>7,:quote=>9,:edit=>11,:new_private_message=>12,:got_private_message=>13,:solved=>15,:assigned=>16)
#  user_id         :integer          not null (пользователь, которому засчитывается действие)
#  target_topic_id :integer
#  acting_user_id  :integer (пользователь, выполнивший действие, например, модератор может выполнить действие от имени обычного пользователя)
#  created_at      :datetime         not null

Другой подход к решению этой задачи с помощью плагина Data Explorer — заставить пользователей заполнять динамически генерируемую форму, в которой они указывают, какие данные им нужны и какие условия применить к этим данным. Промпт может быть сгенерирован программно системой Discourse, а затем отправлен в LLM для написания запроса.

Редактирование: @jordan-violet, это может стать полезной отправной точкой. Вот аннотированная частичная схема, которая работает у меня. Она хорошо работает, пока я ограничиваю запросы так, чтобы на них можно было ответить, используя предоставленную схему. Я добавил в схему дополнительные детали, чтобы прояснить моменты, которые, похоже, сбивают ChatGPT с толку. Очевидный недостаток этого подхода заключается в том, что полностью аннотированная схема превысит лимит токенов ChatGPT 3.5. В схему включена некоторая информация, которую можно опустить, чтобы уменьшить количество используемых токенов.

Сводка
# == Информация о схеме
#
# Имя таблицы: application_requests
#
#  id       :integer          not null, primary key
#  date     :date             not null
#  req_type :integer          not null ("http_total"=>0,"http_2xx"=>1,"http_background"=>2,"http_3xx"=>3,"http_4xx"=>4,"http_5xx"=>5,"page_view_crawler"=>6,"page_view_logged_in"=>7,"page_view_anon"=>8,"page_view_logged_in_mobile"=>9,"page_view_anon_mobile"=>10,"api"=>11,"user_api"=>12)
#  count    :integer          default(0), not null
#
# Имя таблицы: users
#
#  id                        :integer          not null, primary key
#  username                  :string(60)       not null
#  created_at                :datetime         not null
#  updated_at                :datetime         not null
#  name                      :string           (настоящее имя пользователя)
#  last_posted_at            :datetime
#  active                    :boolean          default(FALSE), not null
#  username_lower            :string(60)       not null
#  last_seen_at              :datetime
#  admin                     :boolean          default(FALSE), not null
#  trust_level               :integer          not null
#  approved                  :boolean          default(FALSE), not null
#  approved_by_id            :integer
#  approved_at               :datetime
#  previous_visit_at         :datetime
#  suspended_at              :datetime
#  suspended_till            :datetime
#  date_of_birth             :date
#  ip_address                :inet
#  moderator                 :boolean          default(FALSE)
#  title                     :string
#  locale                    :string(10)
#  primary_group_id          :integer
#  registration_ip_address   :inet
#  staged                    :boolean          default(FALSE), not null
#  first_seen_at             :datetime
#  silenced_till             :datetime
#
# Имя таблицы: topics
#
#  id                        :integer          not null, primary key
#  title                     :string           not null
#  last_posted_at            :datetime
#  created_at                :datetime         not null
#  updated_at                :datetime         not null
#  views                     :integer          default(0), not null
#  posts_count               :integer          default(0), not null
#  user_id                   :integer          (id пользователя, создавшего тему)
#  last_post_user_id         :integer          not null (id пользователя, создавшего последний пост в теме)
#  reply_count               :integer          default(0), not null
#  deleted_at                :datetime
#  highest_post_number       :integer          default(0), not null
#  like_count                :integer          default(0), not null
#  category_id               :integer
#  visible                   :boolean          default(TRUE), not null
#  moderator_posts_count     :integer          default(0), not null
#  closed                    :boolean          default(FALSE), not null
#  archived                  :boolean          default(FALSE), not null
#  bumped_at                 :datetime         not null
#  archetype                 :string           default("regular"), not null (может быть установлено в «regular» или «private_message»)
#  slug                      :string
#  deleted_by_id             :integer          (id пользователя, удалившего тему)
#  participant_count         :integer          default(1)
#  word_count                :integer
#  excerpt                   :string
#  highest_staff_post_number :integer          default(0), not null
#
# Имя таблицы: posts
#
#  id                      :integer          not null, primary key
#  user_id                 :integer          (id пользователя, создавшего пост)
#  topic_id                :integer          not null
#  post_number             :integer          not null (указывает порядок поста в теме)
#  raw                     :text             not null (содержимое поста)
#  created_at              :datetime         not null
#  updated_at              :datetime         not null
#  reply_to_post_number    :integer          (post_number, на который отвечает пост)
#  reply_count             :integer          default(0), not null
#  deleted_at              :datetime
#  like_count              :integer          default(0), not null
#  bookmark_count          :integer          default(0), not null
#  reads                   :integer          default(0), not null (количество прочтений поста)
#  post_type               :integer          default(1), not null (:regular=>1, :moderator_action=>2, :small_action=>3, :whisper=>4)
#  last_editor_id          :integer          (id пользователя, последний отредактировавшего пост)
#  hidden                  :boolean          default(FALSE), not null
#  hidden_reason_id        :integer          (:flag_threshold_reached=>1,:flag_threshold_reached_again=>2,:new_user_spam_threshold_reached=>3,:flagged_by_tl3_user=>4,:email_spam_header_found=>5,:flagged_by_tl4_user=>6,:email_authentication_result_header=>7,:imported_as_unlisted=>8)
#  edit_reason             :string
#  word_count              :integer
#  wiki                    :boolean          default(FALSE), not null
#
# Имя таблицы: categories
#
#  id                                        :integer          not null, primary key
#  name                                      :string(50)       not null
#  topic_id                                  :integer          (id темы, используемой для описания категории)
#  topic_count                               :integer          default(0), not null
#  created_at                                :datetime         not null
#  updated_at                                :datetime         not null
#  user_id                                   :integer          not null (id пользователя, создавшего тему)
#  topics_year                               :integer          default(0)
#  topics_month                              :integer          default(0)
#  topics_week                               :integer          default(0)
#  slug                                      :string           not null
#  description                               :text
#  text_color                                :string(6)        default("FFFFFF"), not null
#  read_restricted                           :boolean          default(FALSE), not null
#  auto_close_hours                          :float
#  post_count                                :integer          default(0), not null
#  latest_post_id                            :integer
#  latest_topic_id                           :integer
#  position                                  :integer
#  parent_category_id                        :integer
#  posts_year                                :integer          default(0)
#  posts_month                               :integer          default(0)
#  posts_week                                :integer          default(0)
#  topics_day                                :integer          default(0)
#  posts_day                                 :integer          default(0)
#
# Имя таблицы: groups
#
#  id                                 :integer          not null, primary key
#  name                               :string           not null
#  created_at                         :datetime         not null
#  automatic                          :boolean          default(FALSE), not null
#  user_count                         :integer          default(0), not null
#  title                              :string
#  bio_raw                            :text             (описание группы)
#  allow_membership_requests          :boolean          default(FALSE), not null
#  full_name                          :string
#  visibility_level                   :integer          default(0), not null (кто может видеть группу: :public=>0, :logged_on_users=>1, :members=>2, :staff=>3, :owners=>4)
#  messageable_level                  :integer          default(0) (кто может писать в группу: :public=>0, :logged_on_users=>1, :members=>2, :staff=>3, :owners=>4)
#  mentionable_level                  :integer          default(0) (кто может упоминать группу: :public=>0, :logged_on_users=>1, :members=>2, :staff=>3, :owners=>4)
#  members_visibility_level           :integer          default(0), not null (кто видит участников группы: :public=>0, :logged_on_users=>1, :members=>2, :staff=>3, :owners=>4)
#
# Имя таблицы: group_users
#
#  id                 :integer          not null, primary key
#  group_id           :integer          not null
#  user_id            :integer          not null
#  created_at         :datetime         not null
#
# Имя таблицы: user_actions
#
#  id              :integer          not null, primary key
#  action_type     :integer          not null (:like=>1,:was_liked=>2,:new_topic=>4,:reply=>5,:response=>6,:mention=>7,:quote=>9,:edit=>11,:new_private_message=>12,:got_private_message=>13,:solved=>15,:assigned=>16)
#  user_id         :integer          not null (пользователь, которому засчитывается действие)
#  target_topic_id :integer
#  target_post_id  :integer
#  target_user_id  :integer          (например, id пользователя, чей пост был лайкнут)
#  acting_user_id  :integer          (пользователь, выполнивший действие, например, модератор может выполнить действие от имени обычного пользователя)
#  created_at      :datetime         not null
#  updated_at      :datetime         not null
#
# Имя таблицы: topic_views
#
#  topic_id   :integer          not null
#  viewed_at  :date             not null
#  user_id    :integer         (будет установлено, если тему просмотрел авторизованный пользователь)
#  ip_address :inet            (будет установлено, если тему просмотрел анонимный пользователь)
#
# Имя таблицы: user_visits
#
#  id         :integer          not null, primary key
#  user_id    :integer          not null
#  visited_at :date             not null
#  posts_read :integer          default(0)
#  mobile     :boolean          default(FALSE) (будет установлено в TRUE, если пользователь зашел с мобильного устройства)
#  time_read  :integer          default(0), not null (возвращаемое значение — количество секунд визита)

Вот ссылка на сессию чата, где я это опробовал: ChatGPT

Если вы хотите расширить этот список, самый простой способ — скопировать схему из нижней части модели, которая вас интересует, напрямую из кода Discourse: discourse/app/models at main · discourse/discourse · GitHub.

3 лайка

Было бы здорово получить именно это, но полный список всех таблиц. Откуда вы это взяли?

РЕДАКТИРОВАНИЕ: А, я вижу вашу ссылку внизу, извините. Скорее всего, у меня не будет времени собрать их все. Надеялся, что где-то есть общая SQL-схема :confused:

Проблема в том, что простого предоставления схемы недостаточно для ChatGPT. Необходимо предоставить ему детали о таких вещах, как:

  • что означают целочисленные коды req_type в таблице application_requests
  • для чего используется столбец user_id в таблице topics
  • что означают коды action_type в таблице user_actions и в чём разница между столбцами user_id, target_user_id и acting_user_id в этой таблице

При наличии таких деталей GPT 3.5, похоже, справляется хорошо без дополнительного обучения. Однако возникает проблема: предоставление такого уровня детализации для всей базы данных приведёт к превышению лимита токенов в промпте ChatGPT (4096 токенов, включая как текст промпта, так и сгенерированный вывод). Если использовать такой подход, потребуется механизм ограничения того, что включается в промпт, в зависимости от того, какую информацию пользователь хочет получить из запроса Data Explorer.

1 лайк

Это совсем не соответствует моему опыту. Вечером у меня было довольно приятное взаимодействие с ним. Позже я поделюсь результатами.

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

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

1 лайк

GPT 3.5 сегодня отлично справляется с 16k

Проблемы начинаются, когда запросы становятся сложными, требуют учёта пограничных случаев и так далее

1 лайк