Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 5b63e59

Browse files
authored
DEV: A rake task to generate topics (#1171)
Adds a new rake task to generate topics using the AI helper model. Generate topics using ``` bundle exec rake "ai:generate_topics[Don Quijote de la Mancha\, Cien años de soledad\, Os Lusíadas\,三国演义]" ``` For now it randomly chooses a non-read-restricted category and a random bunch of users.
1 parent 01893bb commit 5b63e59

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

lib/tasks/create_topics.rake

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# frozen_string_literal: true
2+
3+
namespace :ai do
4+
desc "Generate topics with AI post content using random users and categories. Use it this way rake ai:generate_topics['title1\,title2\,title3']"
5+
task :generate_topics, [:titles] => [:environment] do |task, args|
6+
titles = args[:titles].include?(",") ? args[:titles].split(",").map(&:strip) : [args[:titles]]
7+
puts "Will create #{titles.size} #{"topics".pluralize(titles.size)}: #{titles.join(", ")}"
8+
9+
titles.each do |title|
10+
next if Topic.find_by_title(TextCleaner.clean_title(TextSentinel.title_sentinel(title).text))
11+
category =
12+
Category
13+
.where.not(id: SiteSetting.uncategorized_category_id)
14+
.where(read_restricted: false)
15+
.order("RANDOM()")
16+
.first
17+
users = User.real.activated.not_suspended.where(staged: false).order("RANDOM()").limit(12)
18+
RateLimiter.disable
19+
20+
creator = TopicGenerator.new(title)
21+
first_post = creator.get_first_post
22+
replies_count = rand(4..10)
23+
replies = creator.get_replies(replies_count)
24+
25+
post = create_topic(category, first_post, title, users)
26+
replies.each_with_index { |reply, i| create_post(users[i + 1], post.topic_id, reply) }
27+
puts "'#{title}' has #{replies.size} replies"
28+
end
29+
end
30+
31+
def create_topic(category, first_post, title, users)
32+
puts "#{users.first.username} will create topic '#{title}' in category '#{category.name}'"
33+
post =
34+
PostCreator.create!(
35+
users.first,
36+
title: title,
37+
raw: first_post,
38+
category: category.id,
39+
skip_guardian: true,
40+
)
41+
puts "Created topic '#{title}' (#{post.topic_id}) in category '#{category.name}'"
42+
post
43+
end
44+
45+
def create_post(user, topic_id, raw)
46+
puts "#{user.username} will reply to topic #{topic_id}"
47+
PostCreator.create!(user, topic_id:, raw:, skip_guardian: true)
48+
end
49+
50+
class TopicGenerator
51+
def initialize(title)
52+
@title = title
53+
end
54+
55+
def get_first_post
56+
TopicGenerator.generate(<<~PROMPT)
57+
Write and opening topic about title: #{@title}.
58+
- content must be in the same language as title
59+
- content in markdown
60+
- content should exclude the title
61+
- maximum of 200 words
62+
PROMPT
63+
end
64+
65+
def get_replies(count)
66+
JSON.parse(
67+
TopicGenerator.generate(<<~PROMPT).gsub(/```json\n?|\```/, "").gsub(/,\n\n/, ",\n").strip,
68+
Write #{count} replies to a topic with title #{@title}.
69+
- respond in an array of strings within double quotes ["", "", ""]
70+
- each with a maximum of 100 words
71+
- keep to same language of title
72+
- each reply may contain markdown to bold, italicize, link, or bullet point
73+
- do not return anything else other than the array
74+
- the last item in the array should not have a trailing comma
75+
- Example return value ["I agree with you. So and so...", "It is fun ... etc"]
76+
PROMPT
77+
)
78+
end
79+
80+
private
81+
82+
def self.generate(prompt)
83+
return "" if prompt.blank?
84+
85+
prompt =
86+
DiscourseAi::Completions::Prompt.new(
87+
"You are a forum user writing concise, informative posts. Keep responses focused and natural.",
88+
messages: [{ type: :user, content: prompt, id: "user" }],
89+
)
90+
91+
DiscourseAi::Completions::Llm.proxy(SiteSetting.ai_helper_model).generate(
92+
prompt,
93+
user: Discourse.system_user,
94+
feature_name: "topic-generator",
95+
)
96+
rescue => e
97+
Rails.logger.error("AI TopicGenerator Error: #{e.message}")
98+
""
99+
end
100+
end
101+
end

0 commit comments

Comments
 (0)