2025-05-29 17:28:06 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module DiscourseAi
|
|
|
|
module Translation
|
|
|
|
class LanguageDetector
|
|
|
|
DETECTION_CHAR_LIMIT = 1000
|
|
|
|
|
|
|
|
def initialize(text)
|
|
|
|
@text = text
|
|
|
|
end
|
|
|
|
|
|
|
|
def detect
|
2025-06-13 10:17:27 +08:00
|
|
|
return nil if !SiteSetting.ai_translation_enabled
|
|
|
|
if (
|
|
|
|
ai_persona = AiPersona.find_by(id: SiteSetting.ai_translation_locale_detector_persona)
|
|
|
|
).blank?
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
persona_klass = ai_persona.class_instance
|
|
|
|
persona = persona_klass.new
|
|
|
|
|
|
|
|
llm_model = LlmModel.find_by(id: preferred_llm_model(persona_klass))
|
|
|
|
return nil if llm_model.blank?
|
|
|
|
|
|
|
|
bot =
|
|
|
|
DiscourseAi::Personas::Bot.as(
|
|
|
|
ai_persona.user || Discourse.system_user,
|
|
|
|
persona: persona,
|
|
|
|
model: llm_model,
|
2025-05-29 17:28:06 +08:00
|
|
|
)
|
|
|
|
|
2025-06-13 10:17:27 +08:00
|
|
|
context =
|
|
|
|
DiscourseAi::Personas::BotContext.new(
|
|
|
|
user: ai_persona.user || Discourse.system_user,
|
|
|
|
skip_tool_details: true,
|
2025-05-29 17:28:06 +08:00
|
|
|
feature_name: "translation",
|
2025-06-13 10:17:27 +08:00
|
|
|
messages: [{ type: :user, content: @text }],
|
2025-05-29 17:28:06 +08:00
|
|
|
)
|
|
|
|
|
2025-06-13 10:17:27 +08:00
|
|
|
structured_output = nil
|
|
|
|
bot.reply(context) do |partial, _, type|
|
|
|
|
structured_output = partial if type == :structured_output
|
|
|
|
end
|
|
|
|
structured_output&.read_buffered_property(:locale) || []
|
2025-05-29 17:28:06 +08:00
|
|
|
end
|
|
|
|
|
2025-06-13 10:17:27 +08:00
|
|
|
private
|
|
|
|
|
|
|
|
def preferred_llm_model(persona_klass)
|
|
|
|
persona_klass.default_llm_id || SiteSetting.ai_translation_model&.split(":")&.last
|
2025-05-29 17:28:06 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|