0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-08 17:53:55 +08:00
discourse/plugins/discourse-ai/lib/configuration/llm_validator.rb
Rafael dos Santos Silva b8e75bd45d
DEV: Remove hard-coded temperatures from built-in agents (#42441)
Previously, most built-in agents overrode `temperature` with a fixed
value, along with a handful of other call sites (the LLM connectivity
probe, the Hugging Face default options, the LLM report automation
default, and the evals judge). This was a historical artifact from when
temperature was a meaningful toggle across models.

This change drops those overrides so everything runs at the model's
native temperature, which is what modern models expect and what several
providers enforce regardless.
2026-08-07 13:48:29 -03:00

103 lines
2.5 KiB
Ruby
Vendored

# frozen_string_literal: true
module DiscourseAi
module Configuration
class LlmValidator
TEST_PROMPT = "How much is 1 + 1?"
attr_reader :last_failed_mode
def initialize(opts = {})
@opts = opts
end
def valid_value?(val)
if val == ""
if @opts[:name] == :ai_default_llm_model
@parent_module_names = []
enabled_settings.each do |setting_name|
if SiteSetting.public_send(setting_name) == true
@parent_module_names << setting_name
@parent_enabled = true
end
end
return !@parent_enabled
end
end
run_test(val).tap { |result| @unreachable = result }
rescue StandardError => e
raise e if Rails.env.test?
@unreachable = true
true
end
def run_test(val)
llm = DiscourseAi::Completions::Llm.proxy(val)
@last_failed_mode = :non_streaming
raise empty_response_error if probe(llm).blank?
@last_failed_mode = :streaming
streamed = +""
probe(llm) { |partial| streamed << partial.to_s if partial.is_a?(String) }
raise empty_response_error if streamed.blank?
@last_failed_mode = nil
true
end
def is_using(llm_model)
in_use_by = AiAgent.where(default_llm_id: llm_model.id).pluck(:name)
in_use_by << "ai_default_llm_model" if SiteSetting.ai_default_llm_model.to_i == llm_model.id
in_use_by
end
def error_message
if @parent_enabled && @parent_module_names.present?
return(
I18n.t(
"discourse_ai.llm.configuration.disable_modules_first",
settings: @parent_module_names.join(", "),
)
)
end
return unless @unreachable
I18n.t("discourse_ai.llm.configuration.model_unreachable")
end
def enabled_settings
%i[
ai_embeddings_semantic_search_enabled
ai_helper_enabled
ai_summarization_enabled
ai_translation_enabled
]
end
private
def probe(llm, &blk)
llm.generate(
TEST_PROMPT,
user: @opts[:user] || Discourse.system_user,
feature_name: "llm_validator",
top_p: 0.9,
&blk
)
end
def empty_response_error
DiscourseAi::Completions::Endpoints::Base::CompletionFailed.new(
I18n.t("discourse_ai.llm.configuration.empty_response"),
)
end
end
end
end