discourse-ai/lib/classificator.rb

82 lines
2.1 KiB
Ruby

# frozen_string_literal: true
module ::DiscourseAi
class Classificator
def initialize(classification_model)
@classification_model = classification_model
end
def classify!(target)
return :cannot_classify unless classification_model.can_classify?(target)
classification_model
.request(target)
.tap do |classification|
store_classification(target, classification)
verdicts = classification_model.get_verdicts(classification)
if classification_model.should_flag_based_on?(verdicts)
accuracies = get_model_accuracies(verdicts.keys)
flag!(target, classification, verdicts, accuracies)
end
end
end
protected
attr_reader :classification_model
def flag!(_target, _classification, _verdicts, _accuracies)
raise NotImplemented
end
def get_model_accuracies(models)
models
.map do |name|
accuracy =
ModelAccuracy.find_or_create_by(
model: name,
classification_type: classification_model.type,
)
[name, accuracy.calculate_accuracy]
end
.to_h
end
def add_score(reviewable)
reviewable.add_score(
Discourse.system_user,
ReviewableScore.types[:inappropriate],
reason: "flagged_by_#{classification_model.type}",
force_review: true,
)
end
def store_classification(target, classification)
attrs =
classification.map do |model_name, classifications|
{
model_used: model_name,
target_id: target.id,
target_type: target.class.sti_name,
classification_type: classification_model.type,
classification: classifications,
updated_at: DateTime.now,
created_at: DateTime.now,
}
end
ClassificationResult.upsert_all(
attrs,
unique_by: %i[target_id target_type model_used],
update_only: %i[classification],
)
end
def flagger
Discourse.system_user
end
end
end