Discourse AI + Data Explorer?

今日は特にクエリを作成したいと思いました。エンジニアに(あまり)迷惑をかけたくなかったので、知っていることと、知っていて欲しかったことに基づいて、ChatGPTにデータエクスプローラーのクエリを作成してもらうことにしました。セミコロンを最後に付けてしまった以外は、すべて正しく取得できたことにかなり驚きました。

月ごとの全ユーザーの累積合計数を取得するクエリを作成するように指示し、パラメータを与えたときに作成されたクエリは次のとおりです。

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

AIをデータエクスプローラー領域に統合することについて、検討はありましたか? :slight_smile:

「いいね!」 12

投稿が新しいトピックに分割されました:Explorerクエリを共有するためにトピックを再開できますか?

プロンプト、ChatGPTのバージョン、およびChatGPTで使用されたモデルを共有していただけますか?:slightly_smiling_face:


ChatGPT August 3 Version
Model: GPT-3.5
Prompt

Discourse Data Explorerとは何ですか?

Completion

私の最終更新は2021年9月時点のものであるため、私が認識している「Discourse Data Explorer」という特定のツールや製品はありません。しかし、それまでの情報に基づいて一般的な説明を提供することはできます。

Discourseは、オンラインコミュニティが議論や交流を行うための、オープンソースの最新フォーラムソフトウェアです。議論、Q&Aフォーラム、サポートコミュニティのホスティングに広く使用されています。Discourseは、議論、ユーザーエンゲージメント、モデレーションを管理するための豊富な機能を提供します。

Data Explorer」は通常、ユーザーがシステムまたはプラットフォーム内のデータをクエリおよび探索できるツールまたは機能を指します。これは、データベースまたはデータ分析プラットフォームのコンテキストでよく使用されます。

2つのコンポーネントを考慮すると、「Discourse Data Explorer」は、ユーザーがDiscourseフォーラム内のデータを探索およびクエリできる機能を提供する、架空のツールまたはプラグインである可能性があります。これは、コミュニティ管理者またはデータアナリストが、フォーラムでの議論に関連するユーザー行動、コンテンツのトレンド、またはその他の指標に関する洞察を得るのに役立つ可能性があります。

私の情報が古くなっている可能性があり、最終更新後に新しい開発が行われた可能性があることに注意することが重要です。「Discourse Data Explorer」が実際に存在する製品または機能である場合は、最新の情報を検索して、その機能と使用方法に関する正確な詳細を取得することを推奨します。


質問の理由は、素晴らしいアイデアをお持ちで、それが共有されているのを見て嬉しかったからです。しかし、将来的には他の人が別のプロンプトを試みる可能性があり、問題の理解に役立つ場合は、ChatGPTのプロンプト、完了、および詳細を共有することが必要になります。

注:私はOpenAI Discourseフォーラムのカテゴリモデレーターであり、ChatGPTプロンプトのヘルプを求める人々との経験が豊富です。(ref


ChatGPTのバージョンは、プロンプトが入力される場所の下の右下で見つけることができます。

モデルは、ページの上部中央付近で見つけることができます。

image

「いいね!」 1

私は…このボットは好きではありません。

「いいね!」 1

このアイデアを少し拡張すると、ユーザーが自然言語でアプリケーションと対話できるようにすることは、AI に関する私の夢そのものです。Discourse と Data Explorer プラグインを使用すれば、「モデレーションに関心を示したユーザーのリストを返す」といったプロンプトから結果を得られる可能性があります。さらに、「モデレーションに関心を示したすべてのユーザーに community_moderation グループへの招待を送信する」といったことも可能です。

現在可能なことについてに戻ります。

ChatGPT 3.0 および 3.5 でテストしたところ、PostgreSQL クエリを返すように依頼し、関心のあるテーブルの構造をプロンプトにコピーした場合、良好な結果が得られました。たとえば、次のようになります。

概要

: 指定されたデータベース構造に基づいて、「community_moderators」グループに属するユーザーのすべてのユーザー名を一覧表示する postgresql クエリを返してください。

# == 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: はい、指定されたデータベース構造に基づいて、「community_moderators」グループに属するユーザーのすべてのユーザー名を一覧表示する PostgreSQL クエリを次に示します。

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」グループに属するユーザーのユーザー名のみに絞り込まれます。

: アプリケーションのトピックと投稿のテーブルの構造を次に示します。

# == 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

「community_moderators」グループのメンバーによって作成されたすべての投稿について、投稿者が意見が分かれる議論のモデレーション方法に関心があることを示す投稿のトピック ID、投稿 ID、およびユーザー名を一覧表示するクエリを返してください。

ChatGPT 3.5: これを実現するには、指定されたスキーマに基づいて poststopicsusers、および 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%');

このクエリは、「community_moderators」グループのメンバーによって作成され、意見が分かれる議論のモデレーションに関心があることを示す特定のキーワードを含む投稿の topic_idpost_id、および username を取得します。ILIKE 演算子は、posts テーブルの raw 列での大文字小文字を区別しないパターンマッチングに使用されます。

このクエリは、指定されたキーワードが望ましい投稿の指標であると想定しています。特定の基準に基づいてキーワードを調整または拡張する必要がある場合があります。

: 2022年9月以降、毎週作成された投稿の数を、意見が分かれる議論のモデレーション方法に関心を示す community_moderators グループのメンバーによって作成された投稿について、カウントを返すクエリを作成してください。

ChatGPT 3.5: これを実現するには、次の PostgreSQL クエリを使用して、2022年9月以降の各週に作成された投稿の数を、意見が分かれる議論のモデレーションに関心を示す 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年9月
GROUP BY
    week_start
ORDER BY
    week_start;

このクエリは、2022年9月以降の各週に作成された、指定されたキーワードを含む「community_moderators」グループのメンバーによって作成された投稿の数を計算します。結果を週ごとにグループ化し、時系列順に並べ替えます。実際のデータベーススキーマに基づいて、列名とテーブルの関係を調整してください。


結果は私にとって良好であり、過去に私が書くのにかなりの時間を費やしたクエリの種類を表しています。Discourse データベース構造でモデルをトレーニングできると仮定すると、プロンプトから構造に関する詳細を省略できるでしょう。

「いいね!」 4

おお、これは素晴らしいですね。ChatGPTのデータエクスプローラーのSQLクエリでは結果がまちまちでしたが、この方法なら理にかなっています。テーブル構造を提供してPostgreSQLクエリを要求するという発想はありませんでした。:woman_facepalming:t2: ヒントをありがとうございます、@simon :slight_smile:

「いいね!」 1

Discourseデータベースの完全なスキーマを確認できる場所はありますか?

「いいね!」 1

hi @so-jordan-violet、データエクスプローラーのクエリ編集インターフェースの右側にある(名前は知りませんが!笑)折りたたみ可能なテーブルツールを使っています。

「いいね!」 2

テキストベースのドキュメント(特に sql create table 形式のもの)があれば、それを指示として提供でき、かなり信頼性の高い結果を得られる可能性があります。

「いいね!」 1

はい、AIチームのバックログには今年の初めからこの項目があります。アイデアは、Discourseスキーマ全体(または重要な部分)をプロンプトに取り込み、あらゆるクエリを作成できるようにすることです。

モデルがより適切に動作するように、モデルへの例を提供するために GitHub - discourse/data-explorer-examples: Examples for Discourse Data Explorer を構築しています。

「いいね!」 7

コードベースを詳しく調べる時間がもっとあればよかったのですが、crestテーブルスキーマのSQLは(公開で)どこかに保存されていますか?

現在、自分の製品/会社で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

データ型を示す完全なスキーマはありますか?

トークン予算に収まるかどうかわかりませんが、試してみます

With ChatCPT 3.5 I’m getting unexpected results when I provide the full schema. For example, it keeps trying to find the topic author in the topic_users table.

I get successful results by limiting the information in the prompt to the tables and columns that are required to write the query. Also by adding some additional information about how the columns are used. For example:

# Table name: 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 (the user who is to be credited with the action)
#  target_topic_id :integer
#  acting_user_id  :integer (the user who performed the action, for example, a staff user can perform an action on behalf of a regular user)
#  created_at      :datetime         not null

Another way to look at getting this to work with the Data Explorer plugin would be to have users fill out a dynamically generate form that lists the data they are looking for, and what conditions they want to apply to the data. The prompt could be generated programmatically by Discourse, then sent to the LLM to have the query written.

Edit: @jordan-violet, this might be a useful starting point. Here’s an annotated partial schema that’s working for me. It works well as long as I limit my queries so that they can be answered by the provided schema. I’ve added additional details to the schema to clarify details that seem to confuse ChatGPT. The obvious downside of this approach is that a fully annotated schema will exceed ChatGPT 3.5’s token limit. I’ve included some information in the schema that could be omitted to reduce the number of tokens that are used.

Summary
# == Schema Information
#
# Table name: 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
#
# Table name: users
#
#  id                        :integer          not null, primary key
#  username                  :string(60)       not null
#  created_at                :datetime         not null
#  updated_at                :datetime         not null
#  name                      :string           (the user's real name)
#  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
#
# Table name: 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          (the id of the user who created the topic)
#  last_post_user_id         :integer          not null (the id of the user who created the last post in the topic)
#  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 (can be set to either "regular" or "private_message")
#  slug                      :string
#  deleted_by_id             :integer          (the id of the user who deleted the topic)
#  participant_count         :integer          default(1)
#  word_count                :integer
#  excerpt                   :string
#  highest_staff_post_number :integer          default(0), not null
#
# Table name: posts
#
#  id                      :integer          not null, primary key
#  user_id                 :integer          (the id of the user who created the post)
#  topic_id                :integer          not null
#  post_number             :integer          not null (indicates the post's order in its topic)
#  raw                     :text             not null (the post's content)
#  created_at              :datetime         not null
#  updated_at              :datetime         not null
#  reply_to_post_number    :integer          (the post_number that the post is a reply to)
#  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 (the number of times the post has been read)
#  post_type               :integer          default(1), not null (:regular=>1, :moderator_action=>2, :small_action=>3, :whisper=>4)
#  last_editor_id          :integer          (the id of the user who last edited the post)
#  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
#
# Table name: categories
#
#  id                                        :integer          not null, primary key
#  name                                      :string(50)       not null
#  topic_id                                  :integer          (the id of the topic that is used for the category's description)
#  topic_count                               :integer          default(0), not null
#  created_at                                :datetime         not null
#  updated_at                                :datetime         not null
#  user_id                                   :integer          not null (the id of the user who created the topic)
#  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)
#
# Table name: 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             (the group's description)
#  allow_membership_requests          :boolean          default(FALSE), not null
#  full_name                          :string
#  visibility_level                   :integer          default(0), not null (who can see the group :public=>0, :logged_on_users=>1, :members=>2, :staff=>3, :owners=>4)
#  messageable_level                  :integer          default(0) (who can message the group :public=>0, :logged_on_users=>1, :members=>2, :staff=>3, :owners=>4)
#  mentionable_level                  :integer          default(0) (who can mention the group :public=>0, :logged_on_users=>1, :members=>2, :staff=>3, :owners=>4)
#  members_visibility_level           :integer          default(0), not null (who see the group's members :public=>0, :logged_on_users=>1, :members=>2, :staff=>3, :owners=>4)
#
# Table name: group_users
#
#  id                 :integer          not null, primary key
#  group_id           :integer          not null
#  user_id            :integer          not null
#  created_at         :datetime         not null
#
# Table name: 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 (the user who is to be credited with the action)
#  target_topic_id :integer
#  target_post_id  :integer
#  target_user_id  :integer          (for example, the id of the user whose post was liked)
#  acting_user_id  :integer          (the user who performed the action, for example, a staff user can perform an action on behalf of a regular user)
#  created_at      :datetime         not null
#  updated_at      :datetime         not null
#
# Table name: topic_views
#
#  topic_id   :integer          not null
#  viewed_at  :date             not null
#  user_id    :integer         (will be set if the topic was viewed by a logged in user)
#  ip_address :inet            (will be set if the topic was viewed by an anonymous user)
#
# Table name: 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) (will be set to TRUE if the user visited on a mobile device)
#  time_read  :integer          default(0), not null (the value returned is the number of seconds of the visit)

Here’s a link to a chat session where I tried it out: https://chat.openai.com/share/d108c104-3aa3-45d9-9161-6da21d5b3a77

If you want to try expanding on this list, the easiest way to do it is to copy the schema from the bottom of the model you’re interested in, directly from the Discourse code: discourse/app/models at main · discourse/discourse · GitHub.

「いいね!」 3

これを正確に、しかしすべてのテーブルの包括的なリストで取得できると素晴らしいのですが。どこから入手しましたか?

編集:ああ、一番下のリンクが見えました。すみません。すべてをまとめる時間がなかったかもしれません。マスターSQLスキーマがどこかにあることを期待していました :confused:

問題は、スキーマを提供するだけではChatGPTには十分な情報にならないことです。以下のような詳細を提供する必要があります。

  • application_requestsreq_type 整数コードが何を表すか
  • topicsuser_id 列が何に使用されるか
  • user_actions テーブルの action_type コードが何を表すか、またそのテーブルの user_idtarget_user_idacting_user_id 列の違いは何か

これらの詳細があれば、GPT 3.5 は追加のトレーニングなしでうまく機能するようです。問題は、データベース全体の詳細レベルを提供すると、プロンプトがChatGPTのトークン制限(プロンプトテキストと生成された出力の両方を含む4096トークン)を超えることです。このタイプのアプローチが使用される場合、ユーザーがData Explorerクエリからどのような情報を取得したいかに基づいて、プロンプトに含めるものを制限する方法が必要になります。

「いいね!」 1

まったくそんな経験はありません。今夜はかなり楽しい経験をしました。後で結果を共有します。

有能ではあるが、非常に初級/ジュニアレベルの役割という感覚を与えてくれます。物事を近づけてくれます。私が間違ったことを伝えると、修正してくれます。繰り返します。

今夜の使用に基づいて、それが私に提供してくれるものと、それが私を節約してくれる時間に、実は本当に満足しています。

「いいね!」 1

GPT 3.5 は今日、16k を問題なく処理します。

問題は、リクエストが複雑になり、エッジケースなどを考慮するようになると発生し始めます。

「いいね!」 1