discourse-ai/db/fixtures/personas/603_ai_personas.rb
Rafael dos Santos Silva 478f31de47
FEATURE: add inferred concepts system (#1330)
* FEATURE: add inferred concepts system

This commit adds a new inferred concepts system that:
- Creates a model for storing concept labels that can be applied to topics
- Provides AI personas for finding new concepts and matching existing ones
- Adds jobs for generating concepts from popular topics
- Includes a scheduled job that automatically processes engaging topics

* FEATURE: Extend inferred concepts to include posts

* Adds support for concepts to be inferred from and applied to posts
* Replaces daily task with one that handles both topics and posts
* Adds database migration for posts_inferred_concepts join table
* Updates PersonaContext to include inferred concepts



Co-authored-by: Roman Rizzi <rizziromanalejandro@gmail.com>
Co-authored-by: Keegan George <kgeorge13@gmail.com>
2025-06-02 14:29:20 -03:00

88 lines
2.8 KiB
Ruby

# frozen_string_literal: true
summarization_personas = [DiscourseAi::Personas::Summarizer, DiscourseAi::Personas::ShortSummarizer]
def from_setting(setting_name)
DB.query_single(
"SELECT value FROM site_settings WHERE name = :setting_name",
setting_name: setting_name,
)
end
DiscourseAi::Personas::Persona.system_personas.each do |persona_class, id|
persona = AiPersona.find_by(id: id)
if !persona
persona = AiPersona.new
persona.id = id
if persona_class == DiscourseAi::Personas::WebArtifactCreator
# this is somewhat sensitive, so we default it to staff
persona.allowed_group_ids = [Group::AUTO_GROUPS[:staff]]
elsif summarization_personas.include?(persona_class)
# Copy group permissions from site settings.
default_groups = [Group::AUTO_GROUPS[:staff], Group::AUTO_GROUPS[:trust_level_3]]
setting_name = "ai_custom_summarization_allowed_groups"
if persona_class == DiscourseAi::Personas::ShortSummarizer
setting_name = "ai_summary_gists_allowed_groups"
default_groups = [Group::AUTO_GROUPS[:everyone]]
end
persona.allowed_group_ids = from_setting(setting_name).first&.split("|") || default_groups
else
persona.allowed_group_ids = [Group::AUTO_GROUPS[:trust_level_0]]
end
persona.enabled = persona_class.default_enabled
persona.priority = true if persona_class == DiscourseAi::Personas::General
end
names = [
persona_class.name,
persona_class.name + " 1",
persona_class.name + " 2",
persona_class.name + SecureRandom.hex,
]
persona.name = DB.query_single(<<~SQL, names, id).first
SELECT guess_name
FROM (
SELECT unnest(Array[?]) AS guess_name
FROM (SELECT 1) as t
) x
LEFT JOIN ai_personas ON ai_personas.name = x.guess_name AND ai_personas.id <> ?
WHERE ai_personas.id IS NULL
ORDER BY x.guess_name ASC
LIMIT 1
SQL
persona.description = persona_class.description
persona.system = true
instance = persona_class.new
tools = {}
instance.tools.map { |tool| tool.to_s.split("::").last }.each { |name| tools[name] = nil }
existing_tools = persona.tools || []
existing_tools.each do |tool|
if tool.is_a?(Array)
name, value = tool
tools[name] = value if tools.key?(name)
end
end
persona.tools = tools.map { |name, value| [name, value] }
# Only set response_format if it's not defined as a method in the persona class
if !instance.class.instance_methods.include?(:response_format)
persona.response_format = instance.response_format
end
# Only set examples if it's not defined as a method in the persona class
persona.examples = instance.examples if !instance.class.instance_methods.include?(:examples)
persona.system_prompt = instance.system_prompt
persona.top_p = instance.top_p
persona.temperature = instance.temperature
persona.save!(validate: false)
end