Discourse AI + Data Explorer?

我今天想做一个特别的查询。我不想(过度)打扰我的工程师,所以我决定让 ChatGPT 根据我所知道的信息和我想要的东西为我编写一个数据探索器查询。令我非常惊讶的是,它把所有东西都做对了(除了在末尾添加了一个不应该有的分号)。

当我给出一些参数并要求它为我构建一个显示每月用户总数的运行总计的查询时,它为我构建的查询如下:

SELECT 
    timeframe "月份, 年份",
    user_count as "本月加入用户数",
    SUM(user_count) OVER (ORDER BY TO_DATE(timeframe, 'Month, YYYY'))::integer as "用户数(运行总计)"
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')

是否考虑过将人工智能集成到数据探索器领域? :slight_smile:

12 个赞

帖子已拆分为新主题:我们能否重新开放该主题以共享 Explorer 查询?

请分享您使用的提示词、ChatGPT 的版本以及在 ChatGPT 中使用的模型。 :slightly_smiling_face:

例如


ChatGPT 8 月 3 日版本
模型:GPT-3.5
提示词

什么是 Discourse 数据浏览器?

完成

根据我截至 2021 年 9 月的最后更新,我不知道有任何名为“Discourse 数据浏览器”的特定工具或产品。但是,我可以根据截至该时间点可用的信息提供一般性解释。

Discourse 是一款开源的现代论坛软件,允许在线社区进行讨论和互动。它广泛用于托管讨论、问答论坛和支持社区。Discourse 提供了一套丰富的功能来管理讨论、用户参与和审核。

“数据浏览器”通常指的是允许用户查询和探索系统或平台内数据的工具或功能。它通常在数据库或数据分析平台的背景下使用。

考虑到这两个组成部分,“Discourse 数据浏览器”可能是一个假设的工具或插件,它使用户能够探索和查询 Discourse 论坛内的数据。这对于希望深入了解用户行为、内容趋势或与论坛讨论相关的其他指标的社区管理员或数据分析师来说可能很有用。

请注意,我的信息可能已过时,并且在我最后更新后可能已发生新的发展。如果“Discourse 数据浏览器”确实是一个真实的产品或功能,我建议搜索最新信息以获取有关其功能和用法的准确详细信息。


要求这样做的原因是,您有一个绝妙的想法,并且很高兴看到它被分享,但将来其他人可能会尝试提出另一个提示词,如果需要帮助来理解任何问题,则需要分享 ChatGPT 的提示词、完成内容和详细信息。

注意:我是 OpenAI Discourse 论坛上的版主,因此在帮助 ChatGPT 提示词方面经验丰富。 (参考)


ChatGPT 的版本可以在输入提示词的右下方找到

模型可以在页面顶部中间附近找到

image

1 个赞

我……不喜欢这个机器人。

1 个赞

稍微扩展一下这个想法,让用户能够使用自然语言与应用程序进行交互,这几乎是我对AI的梦想。通过Discourse和Data Explorer插件,可以实现诸如“返回对版主感兴趣的用户列表”之类的提示。甚至更好,“向社区版主群组发送邀请给所有对版主感兴趣的用户。”

回到现在可能实现的功能:

通过测试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上连接来检索users表中的用户名。它过滤结果,只包括属于“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

返回一个查询,列出所有由“community_moderators”群组的成员创建的帖子的所有主题ID、帖子ID和用户名,这些帖子表明发帖人对如何管理极化讨论感兴趣。

ChatGPT 3.5: 要实现这一点,您需要根据提供的模式连接poststopicsusersgroup_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_idusernameILIKE运算符用于postsraw列中的不区分大小写的模式匹配。

请注意,此查询假定您提供的关键字指示了所需的帖子。您可能需要根据您的具体标准调整或扩展关键字。

: 编写一个查询,返回自2022年9月以来,由社区版主群组的成员创建的、表明对如何管理极化讨论感兴趣的帖子的每周发布数量。

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' -- Start date: September 2022
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 个赞

是的,我们从今年年初开始就在人工智能团队的待办事项中列出了这个项目。想法是将整个(或重要部分)的 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:

问题在于,仅仅提供 schema 对 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 个赞