discourse/lib/summarization/base.rb

103 lines
3.7 KiB
Ruby

# frozen_string_literal: true
# TODO(@keegan): Remove after removing SiteSetting.summarization_strategy
# Keeping because its still needed for SiteSetting to function.
# Remove after settings are migrated to AI
# Base class that defines the interface that every summarization
# strategy must implement.
# Above each method, you'll find an explanation of what
# it does and what it should return.
module Summarization
class Base
class << self
def available_strategies
DiscoursePluginRegistry.summarization_strategies
end
def find_strategy(strategy_model)
available_strategies.detect { |s| s.model == strategy_model }
end
def selected_strategy
return if SiteSetting.summarization_strategy.blank?
find_strategy(SiteSetting.summarization_strategy)
end
def can_see_summary?(target, user)
return false if SiteSetting.summarization_strategy.blank?
return false if target.class == Topic && target.private_message?
has_cached_summary = SummarySection.exists?(target: target, meta_section_id: nil)
return has_cached_summary if user.nil?
has_cached_summary || can_request_summary_for?(user)
end
def can_request_summary_for?(user)
return false unless user
user_group_ids = user.group_ids
SiteSetting.custom_summarization_allowed_groups_map.any? do |group_id|
user_group_ids.include?(group_id)
end
end
end
# Some strategies could require other conditions to work correctly,
# like site settings.
# This method gets called when admins attempt to select it,
# checking if we met those conditions.
def correctly_configured?
raise NotImplemented
end
# Strategy name to display to admins in the available strategies dropdown.
def display_name
raise NotImplemented
end
# If we don't meet the conditions to enable this strategy,
# we'll display this hint as an error to admins.
def configuration_hint
raise NotImplemented
end
# The idea behind this method is "give me a collection of texts,
# and I'll handle the summarization to the best of my capabilities.".
# It's important to emphasize the "collection of texts" part, which implies
# it's not tied to any model and expects the "content" to be a hash instead.
#
# @param content { Hash } - Includes the content to summarize, plus additional
# context to help the strategy produce a better result. Keys present in the content hash:
# - resource_path (optional): Helps the strategy build links to the content in the summary (e.g. "/t/-/:topic_id/POST_NUMBER")
# - content_title (optional): Provides guidance about what the content is about.
# - contents (required): Array of hashes with content to summarize (e.g. [{ poster: "asd", id: 1, text: "This is a text" }])
# All keys are required.
# @param &on_partial_blk { Block - Optional } - If the strategy supports it, the passed block
# will get called with partial summarized text as its generated.
#
# @param current_user { User } - User requesting the summary.
#
# @returns { Hash } - The summarized content, plus chunks if the content couldn't be summarized in one pass. Example:
# {
# summary: "This is the final summary",
# chunks: [
# { ids: [topic.first_post.post_number], summary: "this is the first chunk" },
# { ids: [post_1.post_number, post_2.post_number], summary: "this is the second chunk" },
# ],
# }
def summarize(content, current_user)
raise NotImplemented
end
# Returns the string we'll store in the selected strategy site setting.
def model
raise NotImplemented
end
end
end