defaults are read from llm.yml

This commit is contained in:
aakashb95
2025-12-19 13:55:48 +05:30
parent 379bfa1b89
commit 2161690ec4
11 changed files with 64 additions and 25 deletions
@@ -20,7 +20,7 @@ module Captain::ChatHelper
private
def build_chat
llm_chat = chat(model: @model, temperature: temperature)
llm_chat = chat(model: model, temperature: temperature)
llm_chat = llm_chat.with_params(response_format: { type: 'json_object' })
llm_chat = setup_tools(llm_chat)
@@ -74,7 +74,7 @@ module Captain::ChatHelper
account_id: resolved_account_id,
conversation_id: @conversation_id,
feature_name: feature_name,
model: @model,
model: model,
messages: chat ? chat.messages.map { |m| { role: m.role.to_s, content: m.content.to_s } } : @messages,
temperature: temperature,
metadata: {
@@ -45,4 +45,8 @@ class Captain::Llm::AssistantChatService < Llm::BaseAiService
def feature_name
'assistant'
end
def account
@assistant&.account
end
end
@@ -33,8 +33,8 @@ class Captain::Llm::ContactAttributesService < Llm::BaseAiService
def instrumentation_params
{
span_name: 'llm.captain.contact_attributes',
model: @model,
temperature: @temperature,
model: model,
temperature: temperature,
account_id: @conversation.account_id,
feature_name: 'contact_attributes',
messages: [
@@ -34,8 +34,8 @@ class Captain::Llm::ContactNotesService < Llm::BaseAiService
def instrumentation_params
{
span_name: 'llm.captain.contact_notes',
model: @model,
temperature: @temperature,
model: model,
temperature: temperature,
account_id: @conversation.account_id,
feature_name: 'contact_notes',
messages: [
@@ -97,8 +97,8 @@ class Captain::Llm::ConversationFaqService < Llm::BaseAiService
def instrumentation_params
{
span_name: 'llm.captain.conversation_faq',
model: @model,
temperature: @temperature,
model: model,
temperature: temperature,
account_id: @conversation.account_id,
conversation_id: @conversation.id,
feature_name: 'conversation_faq',
@@ -33,8 +33,8 @@ class Captain::Llm::FaqGeneratorService < Llm::BaseAiService
def instrumentation_params
{
span_name: 'llm.captain.faq_generator',
model: @model,
temperature: @temperature,
model: model,
temperature: temperature,
feature_name: 'faq_generator',
account_id: @account_id,
messages: [
@@ -72,7 +72,7 @@ class Captain::Onboarding::WebsiteAnalyzerService < Llm::BaseAiService
def instrumentation_params
{
span_name: 'llm.captain.website_analyzer',
model: @model,
model: model,
temperature: 0.1,
feature_name: 'website_analyzer',
messages: [
+19 -5
View File
@@ -2,27 +2,41 @@
# Base service for LLM operations using RubyLLM.
# New features should inherit from this class.
#
# Subclasses should implement:
# - feature_name: Returns the feature key (e.g., 'assistant', 'copilot') for model lookup
# - account: Returns the Account instance for per-account model configuration
#
# If these methods are not implemented, falls back to InstallationConfig or DEFAULT_MODEL.
class Llm::BaseAiService
DEFAULT_MODEL = Llm::Config::DEFAULT_MODEL
DEFAULT_TEMPERATURE = 1.0
attr_reader :model, :temperature
attr_reader :temperature
def initialize
Llm::Config.initialize!
setup_model
setup_temperature
end
def chat(model: @model, temperature: @temperature)
def model
@model ||= determine_model
end
def chat(model: self.model, temperature: @temperature)
RubyLLM.chat(model: model).with_temperature(temperature)
end
private
def setup_model
def determine_model
if respond_to?(:feature_name, true) && respond_to?(:account, true) && account.present?
account_model = account.captain_preferences.dig(:models, feature_name.to_s)
return account_model if account_model.present?
end
config_value = InstallationConfig.find_by(name: 'CAPTAIN_OPEN_AI_MODEL')&.value
@model = (config_value.presence || DEFAULT_MODEL)
config_value.presence || DEFAULT_MODEL
end
def setup_temperature
@@ -1,7 +1,6 @@
module Enterprise::Integrations::OpenaiProcessorService
ALLOWED_EVENT_NAMES = %w[rephrase summarize reply_suggestion label_suggestion fix_spelling_grammar shorten expand
make_friendly make_formal simplify].freeze
CACHEABLE_EVENTS = %w[label_suggestion].freeze
ALLOWED_EVENT_NAMES = (Integrations::LlmBaseService::ALLOWED_EVENT_NAMES + Integrations::LlmBaseService::LABEL_SUGGESTION_EVENTS).freeze
CACHEABLE_EVENTS = Integrations::LlmBaseService::LABEL_SUGGESTION_EVENTS.freeze
def label_suggestion_message
payload = label_suggestion_body
@@ -49,7 +48,7 @@ module Enterprise::Integrations::OpenaiProcessorService
def summarize_body
{
model: self.class::GPT_MODEL,
model: model_for_event,
messages: [
{ role: 'system',
content: prompt_from_file('summary', enterprise: true) },
@@ -65,7 +64,7 @@ module Enterprise::Integrations::OpenaiProcessorService
return value_from_cache if content.blank?
{
model: self.class::GPT_MODEL,
model: model_for_event,
messages: [
{
role: 'system',
+23 -1
View File
@@ -7,11 +7,25 @@ class Integrations::LlmBaseService
# 120000 * 4 = 480,000 characters (rounding off downwards to 400,000 to be safe)
TOKEN_LIMIT = 400_000
GPT_MODEL = Llm::Config::DEFAULT_MODEL
ALLOWED_EVENT_NAMES = %w[rephrase summarize reply_suggestion fix_spelling_grammar shorten expand make_friendly make_formal simplify].freeze
CACHEABLE_EVENTS = %w[].freeze
# Maps event names to feature keys in config/llm.yml
EDITOR_EVENTS = %w[rephrase fix_spelling_grammar shorten expand make_friendly make_formal simplify].freeze
ASSISTANT_EVENTS = %w[summarize reply_suggestion].freeze
LABEL_SUGGESTION_EVENTS = %w[label_suggestion].freeze
ALLOWED_EVENT_NAMES = (EDITOR_EVENTS + ASSISTANT_EVENTS).freeze
pattr_initialize [:hook!, :event!]
def model_for_event
feature = feature_name_for_event
return self.class::GPT_MODEL unless feature && hook&.account
account_model = hook.account.captain_preferences.dig(:models, feature)
account_model.presence || self.class::GPT_MODEL
end
def perform
return nil unless valid_event_name?
@@ -25,6 +39,14 @@ class Integrations::LlmBaseService
private
def feature_name_for_event
return 'editor' if EDITOR_EVENTS.include?(event_name)
return 'assistant' if ASSISTANT_EVENTS.include?(event_name)
return 'label_suggestion' if LABEL_SUGGESTION_EVENTS.include?(event_name)
nil
end
def event_name
event['name']
end
+3 -3
View File
@@ -53,7 +53,7 @@ class Integrations::Openai::ProcessorService < Integrations::LlmBaseService
def build_api_call_body(system_content, user_content = event['data']['content'])
{
model: GPT_MODEL,
model: model_for_event,
messages: [
{ role: 'system', content: system_content },
{ role: 'user', content: user_content }
@@ -115,7 +115,7 @@ class Integrations::Openai::ProcessorService < Integrations::LlmBaseService
def summarize_body
{
model: GPT_MODEL,
model: model_for_event,
messages: [
{ role: 'system',
content: prompt_from_file('summary', enterprise: false) },
@@ -126,7 +126,7 @@ class Integrations::Openai::ProcessorService < Integrations::LlmBaseService
def reply_suggestion_body
{
model: GPT_MODEL,
model: model_for_event,
messages: [
{ role: 'system',
content: prompt_from_file('reply', enterprise: false) }