155 lines
5.6 KiB
Ruby
155 lines
5.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module DiscourseAi
|
|
module Summarization
|
|
module Strategies
|
|
class HotTopicGists < Base
|
|
def type
|
|
AiSummary.summary_types[:gist]
|
|
end
|
|
|
|
def feature
|
|
"gists"
|
|
end
|
|
|
|
def targets_data
|
|
op_post_number = 1
|
|
|
|
hot_topics_recent_cutoff = Time.zone.now - SiteSetting.hot_topics_recent_days.days
|
|
|
|
recent_hot_posts =
|
|
Post
|
|
.where(topic_id: target.id)
|
|
.where("post_type = ?", Post.types[:regular])
|
|
.where("NOT hidden")
|
|
.where("created_at >= ?", hot_topics_recent_cutoff)
|
|
.pluck(:post_number)
|
|
|
|
# It may happen that a topic is hot without any recent posts
|
|
# In that case, we'll just grab the last 20 posts
|
|
# for an useful summary of the current state of the topic
|
|
if recent_hot_posts.empty?
|
|
recent_hot_posts =
|
|
Post
|
|
.where(topic_id: target.id)
|
|
.where("post_type = ?", Post.types[:regular])
|
|
.where("NOT hidden")
|
|
.order("post_number DESC")
|
|
.limit(20)
|
|
.pluck(:post_number)
|
|
end
|
|
posts_data =
|
|
Post
|
|
.where(topic_id: target.id)
|
|
.joins(:user)
|
|
.where("post_number IN (?)", recent_hot_posts << op_post_number)
|
|
.order(:post_number)
|
|
.pluck(:post_number, :raw, :username)
|
|
|
|
posts_data.reduce([]) do |memo, (pn, raw, username)|
|
|
raw_text = raw
|
|
|
|
if pn == 1 && target.topic_embed&.embed_content_cache.present?
|
|
raw_text = target.topic_embed&.embed_content_cache
|
|
end
|
|
|
|
memo << { poster: username, id: pn, text: raw_text }
|
|
end
|
|
end
|
|
|
|
def summary_extension_prompt(summary, contents)
|
|
statements =
|
|
contents
|
|
.to_a
|
|
.map { |item| "(#{item[:id]} #{item[:poster]} said: #{item[:text]} " }
|
|
.join("\n")
|
|
|
|
prompt = DiscourseAi::Completions::Prompt.new(<<~TEXT.strip)
|
|
You are an advanced summarization bot. Your task is to update an existing single-sentence summary by integrating new developments from a conversation.
|
|
Analyze the most recent messages to identify key updates or shifts in the main topic and reflect these in the updated summary.
|
|
Emphasize new significant information or developments within the context of the initial conversation theme.
|
|
|
|
### Guidelines:
|
|
|
|
- Ensure the revised summary remains concise and objective, maintaining a focus on the central theme or issue.
|
|
- Omit extraneous details or subjective opinions.
|
|
- Use the original language of the text.
|
|
- Begin directly with the main topic or issue, avoiding introductory phrases.
|
|
- Limit the updated summary to a maximum of 20 words.
|
|
- Return the 20-word summary inside <ai></ai> tags.
|
|
|
|
TEXT
|
|
|
|
prompt.push(type: :user, content: <<~TEXT.strip)
|
|
### Context:
|
|
|
|
This is the existing single-sentence summary:
|
|
|
|
#{summary}
|
|
|
|
And these are the new developments in the conversation:
|
|
|
|
#{statements}
|
|
|
|
Your task is to update an existing single-sentence summary by integrating new developments from a conversation.
|
|
Return the 20-word summary inside <ai></ai> tags.
|
|
TEXT
|
|
|
|
prompt
|
|
end
|
|
|
|
def first_summary_prompt(contents)
|
|
content_title = target.title
|
|
statements =
|
|
contents.to_a.map { |item| "(#{item[:id]} #{item[:poster]} said: #{item[:text]} " }
|
|
|
|
prompt = DiscourseAi::Completions::Prompt.new(<<~TEXT.strip)
|
|
You are an advanced summarization bot. Analyze a given conversation and produce a concise,
|
|
single-sentence summary that conveys the main topic and current developments to someone with no prior context.
|
|
|
|
### Guidelines:
|
|
|
|
- Emphasize the most recent updates while considering their significance within the original post.
|
|
- Focus on the central theme or issue being addressed, maintaining an objective and neutral tone.
|
|
- Exclude extraneous details or subjective opinions.
|
|
- Use the original language of the text.
|
|
- Begin directly with the main topic or issue, avoiding introductory phrases.
|
|
- Limit the summary to a maximum of 20 words.
|
|
- Do *NOT* repeat the discussion title in the summary.
|
|
|
|
Return the summary inside <ai></ai> tags.\n
|
|
TEXT
|
|
|
|
context = +<<~TEXT
|
|
### Context:
|
|
|
|
#{content_title.present? ? "The discussion title is: " + content_title + ". (DO NOT REPEAT THIS IN THE SUMMARY)\n" : ""}
|
|
|
|
The conversation began with the following statement:
|
|
|
|
#{statements.shift}\n
|
|
TEXT
|
|
|
|
if statements.present?
|
|
context << <<~TEXT
|
|
Subsequent discussion includes the following:
|
|
|
|
#{statements.join("\n")}
|
|
|
|
Your task is to focus on these latest messages, capturing their meaning in the context of the initial statement.
|
|
TEXT
|
|
else
|
|
context << "Your task is to capture the meaning of the initial statement."
|
|
end
|
|
|
|
prompt.push(type: :user, content: <<~TEXT.strip)
|
|
#{context} Return the 20-word summary inside <ai></ai> tags.
|
|
TEXT
|
|
|
|
prompt
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|