Discourse AI + Data Explorer?

Decidí que quería una consulta particular hoy. Al no querer molestar a mis ingenieros (demasiado), decidí pedirle a ChatGPT que me escribiera una consulta de explorador de datos basándome en lo que sabía y en lo que sabía que quería. Me quedé bastante impresionado de que acertara en todo (aparte de añadir un punto y coma al final que no debería haber añadido).

Aquí está la consulta que me creó cuando le di algunos parámetros y le pedí que me creara una consulta que me diera un total acumulado de todos los usuarios por mes:

SELECT 
    timeframe "Mes, Año",
    user_count as "Usuarios Unidos Este Mes",
    SUM(user_count) OVER (ORDER BY TO_DATE(timeframe, 'Month, YYYY'))::integer as "Usuarios (Total Acumulado)"
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')

¿Se ha considerado la integración de la IA en el área del explorador de datos? :slight_smile:

12 Me gusta

Se dividió una publicación en un nuevo tema: ¿Podríamos reabrir el tema para compartir consultas de Explorer?

¿Te importaría compartir el prompt, la versión de ChatGPT y el modelo utilizado con ChatGPT? :slightly_smiling_face:

Por ejemplo


Versión de ChatGPT del 3 de agosto
Modelo: GPT-3.5
Prompt

¿Qué es el Explorador de Datos de Discourse?

Completado

Hasta mi última actualización en septiembre de 2021, no tengo conocimiento de ninguna herramienta o producto específico llamado “Explorador de Datos de Discourse”. Sin embargo, puedo proporcionar una explicación general basada en la información disponible hasta ese momento.

Discourse es un software de foro moderno y de código abierto que permite a las comunidades en línea tener discusiones e interacciones. Se utiliza ampliamente para albergar debates, foros de preguntas y respuestas y comunidades de soporte. Discourse proporciona un rico conjunto de características para gestionar discusiones, la participación de los usuarios y la moderación.

Un “Explorador de Datos” generalmente se refiere a una herramienta o función que permite a los usuarios consultar y explorar datos dentro de un sistema o plataforma. A menudo se utiliza en el contexto de bases de datos o plataformas de análisis de datos.

Dados los dos componentes, “Explorador de Datos de Discourse” podría ser potencialmente una herramienta o plugin hipotético que brinde a los usuarios la capacidad de explorar y consultar datos dentro de un foro de Discourse. Esto podría ser útil para los administradores de la comunidad o los analistas de datos que desean obtener información sobre el comportamiento de los usuarios, las tendencias de contenido u otras métricas relacionadas con las discusiones que tienen lugar en el foro.

Es importante tener en cuenta que mi información puede estar desactualizada y que pueden haber ocurrido nuevos desarrollos después de mi última actualización. Si “Explorador de Datos de Discourse” es realmente un producto o característica real, recomiendo buscar la información más reciente para obtener detalles precisos sobre sus capacidades y uso.


La razón de la pregunta es que tienes una excelente idea y fue agradable verla compartida, pero en el futuro otros pueden intentar hacer otra pregunta y compartir el prompt, la completación y los detalles de ChatGPT son necesarios si se necesita ayuda para comprender algún problema.

Nota: Soy moderador de categoría en el foro de OpenAI Discourse, por lo que tengo mucha experiencia con aquellos que buscan ayuda con los prompts de ChatGPT. (ref)


La versión de ChatGPT se puede encontrar en la parte inferior derecha, debajo de donde se ingresa un prompt

El modelo se puede encontrar cerca de la parte superior de la página, en el centro

image

1 me gusta

Yo…no me gusta este bot.

1 me gusta

Ampliando un poco esta idea, permitir a los usuarios interactuar con aplicaciones utilizando lenguaje natural es prácticamente mi sueño en lo que respecta a la IA. Con Discourse y el plugin Data Explorer, podría ser posible obtener resultados de indicaciones como “devuelve una lista de usuarios que han expresado interés en la moderación”. O aún mejor, “envía una invitación al grupo community_moderation a todos los usuarios que hayan expresado interés en la moderación”.

Volviendo a lo que es posible ahora:

Probando con ChatGPT 3.0 y 3.5, he obtenido buenos resultados al pedirle que devuelva una consulta PostgreSQL y copiando la estructura de las tablas que me interesan en la indicación. Por ejemplo:

Resumen

Yo: Devuelve una consulta postgresql que liste todos los nombres de usuario de los usuarios que están en el grupo “community_moderators” para la siguiente estructura de base de datos:

# == 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: Claro, aquí tienes una consulta PostgreSQL que lista todos los nombres de usuario de los usuarios que están en el grupo “community_moderators” basándose en la estructura de la base de datos proporcionada:

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

Esta consulta recupera los nombres de usuario de la tabla users uniéndola con la tabla group_users por el ID de usuario y luego uniéndola con la tabla groups por el ID de grupo. Filtra los resultados para incluir solo los nombres de usuario de los usuarios que están en el grupo “community_moderators”.

Yo: Aquí está la estructura de las tablas de temas y publicaciones de la aplicación:

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

Devuelve una consulta que liste todos los IDs de tema, IDs de publicación y nombres de usuario de todas las publicaciones creadas por miembros del grupo “community_moderators” que indiquen de alguna manera que el autor está interesado en cómo moderar discusiones polarizantes.

ChatGPT 3.5: Para lograr esto, necesitarías unir las tablas posts, topics, users y group_users basándote en el esquema proporcionado. Aquí tienes una consulta PostgreSQL que recupera la información solicitada:

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

Esta consulta recupera el topic_id, post_id y username de todas las publicaciones creadas por miembros del grupo “community_moderators” que contienen ciertas palabras clave que indican un interés en moderar discusiones polarizantes. El operador ILIKE se utiliza para la coincidencia de patrones sin distinción entre mayúsculas y minúsculas en la columna raw de la tabla posts.

Ten en cuenta que esta consulta asume que las palabras clave que proporcionaste son indicativas de las publicaciones deseadas. Es posible que necesites ajustar o ampliar las palabras clave según tus criterios específicos.

Yo: Escribe una consulta que devuelva un recuento de publicaciones creadas en cada período semanal desde septiembre de 2022, creadas por miembros del grupo community_moderators que indiquen algún interés en cómo moderar discusiones polarizantes.

ChatGPT 3.5: Para lograr esto, puedes usar la siguiente consulta PostgreSQL para devolver un recuento de publicaciones creadas en cada período semanal desde septiembre de 2022, creadas por miembros del grupo “community_moderators” que indiquen un interés en cómo moderar discusiones polarizantes:

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' -- Fecha de inicio: Septiembre de 2022
GROUP BY
    week_start
ORDER BY
    week_start;

Esta consulta calcula el recuento de publicaciones creadas por miembros del grupo “community_moderators” que contienen las palabras clave especificadas en cada período semanal desde septiembre de 2022. Agrupa los resultados por semana y los ordena cronológicamente. Asegúrate de ajustar los nombres de las columnas y las relaciones de las tablas según el esquema real de tu base de datos.


Los resultados me parecen buenos y representan los tipos de consultas que me llevaban bastante tiempo escribir en el pasado. Supongo que sería posible entrenar un modelo con la estructura de la base de datos de Discourse para que los detalles sobre la estructura pudieran omitirse de las indicaciones.

4 Me gusta

oh, esto es genial, he tenido resultados mixtos con las consultas SQL del explorador de datos de ChatGPT, pero hacerlo de esta manera tiene mucho sentido. Ni siquiera pensé en proporcionar la estructura de la tabla y pedir consultas PostgreSQL. :woman_facepalming:t2: gracias por el consejo @simon :slight_smile:

1 me gusta

¿Hay algún lugar donde pueda ver un esquema completo de las bases de datos de Discourse?

1 me gusta

Hola @so-jordan-violet, solo uso la herramienta de tabla colapsable (¡no sé cómo se llama! jajaja) en el lado derecho de la interfaz de edición de consultas del explorador de datos:

2 Me gusta

Si pudiéramos obtener un documento basado en texto (especialmente si está en formato sql create table) podríamos proporcionarlo como instrucciones y probablemente obtener resultados bastante fiables.

1 me gusta

Sí, tenemos este elemento en la lista de tareas del equipo de IA desde principios de este año. La idea es ingerir la totalidad (o la parte importante) del esquema de Discourse en el prompt para permitirle crear cualquier consulta.

Hemos estado creando GitHub - discourse/data-explorer-examples: Examples for Discourse Data Explorer para ayudar a proporcionar ejemplos al modelo, para que pueda estar mejor fundamentado.

7 Me gusta

Desearía tener más tiempo para examinar la base de código, pero ¿tienen el SQL almacenado en algún lugar (públicamente) para los esquemas de la tabla crest?

Estoy trabajando con LLM en mi propio producto/empresa en este momento y me encantaría jugar con esto.

1 me gusta

oh, esto es genial. ¡gracias por el enlace Falco! :slight_smile:

3 Me gusta

Simplemente genero esto directamente del esquema

Algo como esto debería servirte para empezar:


He estado explorando todo tipo de enfoques para poner esto en marcha. Sin embargo, un problema es que GPT 3.5 es tan difícil de dirigir que se confunde.

Darle el esquema ciertamente ayuda, pero me doy cuenta de que necesito ser ultra estratégico con los ejemplos.

Simplemente contarle una historia sobre “cómo contar los temas archivados para un usuario” termina dirigiendo una consulta como “cuántas publicaciones tuvo un usuario” hacia temas archivados.

Estaba pensando:

graph TD
A[Añadir información genérica útil] --> B[Generar embeddings para la pregunta]
B --> C[Hacer una búsqueda de similitud entre ejemplos]
C --> D[Añadir 3 ejemplos al prompt]
D --> E[Añadir esquema al prompt]
E --> F[Hacer la pregunta]
F --> G[Obtener SQL]

Pero resulta que a menos que los ejemplos sean espectaculares y no incluyas contraejemplos… las cosas se ponen mal.

Estoy empezando a pensar que lo mejor que tenemos por ahora es simplemente darle el esquema y un preámbulo. Quizás añadir otro paso al final para la validación y reintento de la consulta.

5 Me gusta

¿Tendrías un esquema completo que muestre los tipos de datos?

No estoy seguro de si encaja en el presupuesto de tokens, lo intentaré.

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 Me gusta

Sería genial tener exactamente esto, pero una lista completa de todas las tablas. ¿De dónde sacaste esto?

EDITAR: Ah, veo tu enlace al final, lo siento. Probablemente no tendré tiempo de juntarlos todos. Esperaba que hubiera un esquema SQL maestro en alguna parte :confused:

El problema es que solo proporcionar el esquema no es suficiente información para ChatGPT. Necesitas proporcionarle detalles sobre cosas como:

  • qué significan los códigos enteros de req_type de application_requests
  • para qué se utiliza la columna user_id de topics
  • qué significan los códigos de action_type de la tabla user_actions y cuál es la diferencia entre las columnas user_id, target_user_id y acting_user_id de esa tabla

Con ese tipo de detalles, GPT 3.5 parece hacer un buen trabajo sin ningún entrenamiento adicional. El problema entonces se convierte en que proporcionar este nivel de detalle sobre toda la base de datos resultará en que el prompt exceda el límite de tokens de ChatGPT (4096 tokens, incluyendo tanto el texto del prompt como la salida generada). Si se utilizara este tipo de enfoque, tendría que haber una manera de limitar lo que se incluye en el prompt en función de la información que el usuario quería obtener de la consulta del Explorador de Datos.

1 me gusta

Esa no ha sido en absoluto mi experiencia. He tenido una experiencia bastante agradable con él esta noche. Compartiré algunos resultados más tarde.

Me da la sensación de un rol competente, pero muy de nivel de entrada/junior. Se acerca a las cosas, le digo lo que hizo mal y lo arregla. Repetir.

De hecho, estoy disfrutando mucho de lo que me está dando, y del tiempo que me ahorra según mi uso de esta noche.

1 me gusta

GPT 3.5 maneja 16k sin problemas hoy

El problema comienza a ocurrir cuando las solicitudes son complicadas, tienen en cuenta los casos extremos, etc.

1 me gusta