# Pull Request Template ## Description Adjusts the Captain LLM feature defaults after feature routing so the defaults stay intentional and avoid unintended high-cost model upgrades. Assistant, copilot, and onboarding content generation now default to `gpt-4.1`; audio transcription keeps `gpt-4o-mini-transcribe` as the default while exposing `whisper-1` as an available account override option. Related: https://linear.app/chatwoot/issue/CW-7425/test-new-models ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? - `ruby -ryaml -e 'yaml = YAML.load_file("config/llm.yml"); features = yaml.fetch("features"); models = yaml.fetch("models"); features.each { |name, cfg| missing = Array(cfg["models"]) - models.keys; raise "#{name}: missing #{missing.join(",")}" if missing.any?; raise "#{name}: default not in models" unless Array(cfg["models"]).include?(cfg["default"]) }'` - `node -e "JSON.parse(require('fs').readFileSync('app/javascript/dashboard/i18n/locale/en/settings.json', 'utf8'))"` - `pnpm exec prettier --check app/javascript/dashboard/i18n/locale/en/settings.json` - `bundle exec rspec spec/lib/llm/feature_router_spec.rb spec/enterprise/services/llm/base_ai_service_spec.rb spec/enterprise/models/concerns/agentable_spec.rb spec/enterprise/services/messages/audio_transcription_service_spec.rb spec/models/concerns/captain_featurable_spec.rb spec/models/account_spec.rb spec/controllers/api/v1/accounts/captain/preferences_controller_spec.rb spec/controllers/super_admin/accounts_controller_spec.rb` - `bundle exec rspec spec/enterprise/services/captain/llm/article_translation_service_spec.rb spec/enterprise/services/messages/audio_transcription_service_spec.rb spec/enterprise/services/llm/base_ai_service_spec.rb` - `RUBOCOP_CACHE_ROOT=/private/tmp/rubocop_cache bundle exec rubocop enterprise/app/services/captain/llm/article_translation_service.rb enterprise/app/services/messages/audio_transcription_service.rb spec/enterprise/services/captain/llm/article_translation_service_spec.rb spec/enterprise/services/llm/base_ai_service_spec.rb spec/enterprise/services/messages/audio_transcription_service_spec.rb` - `git diff --check` ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules
63 lines
2.2 KiB
Ruby
63 lines
2.2 KiB
Ruby
class Captain::Llm::ArticleTranslationService < Captain::BaseTaskService
|
|
TYPES = %i[title content].freeze
|
|
|
|
pattr_initialize [:account!, :text!, :target_language!, :type!]
|
|
|
|
def perform
|
|
raise ArgumentError, "Invalid type: #{type}" unless TYPES.include?(type)
|
|
|
|
response = make_api_call(feature: 'help_center_article_generation', model: translation_model, messages: messages)
|
|
return response if response[:error]
|
|
|
|
response.merge(message: response[:message].strip)
|
|
end
|
|
|
|
private
|
|
|
|
def messages
|
|
[
|
|
{ role: 'system', content: system_prompt },
|
|
{ role: 'user', content: text }
|
|
]
|
|
end
|
|
|
|
def system_prompt
|
|
type == :title ? title_system_prompt : content_system_prompt
|
|
end
|
|
|
|
def event_name
|
|
'article_translation'
|
|
end
|
|
|
|
def llm_credential
|
|
@llm_credential ||= system_llm_credential
|
|
end
|
|
|
|
def translation_model
|
|
@translation_model ||= InstallationConfig.find_by(name: 'CAPTAIN_OPEN_AI_MODEL')&.value.presence || GPT_MODEL
|
|
end
|
|
|
|
def title_system_prompt
|
|
<<~SYSTEM_PROMPT_MESSAGE
|
|
You are a professional translator.
|
|
Translate the following text to #{target_language}.
|
|
Return only the translated text, no explanations or extra formatting.
|
|
SYSTEM_PROMPT_MESSAGE
|
|
end
|
|
|
|
def content_system_prompt
|
|
<<~SYSTEM_PROMPT_MESSAGE
|
|
You are a professional translator. Translate the following content to #{target_language}.
|
|
The content is markdown that may contain embedded HTML blocks.
|
|
Rules:
|
|
- Translate ONLY the visible text content (headings, paragraphs, list items, table cells, etc.).
|
|
- Preserve ALL markdown formatting exactly: headings (#), bold (**), italic (*), links, lists, code blocks, blockquotes, tables, horizontal rules.
|
|
- Preserve ALL HTML tags, attributes, and structure exactly as they are.
|
|
- Do NOT translate or modify: URLs, image src/alt attributes, link href values, class names, IDs, data attributes, code blocks, or any HTML attribute values.
|
|
- Keep all image tags (both markdown  and HTML <img>), iframes, and embedded media completely unchanged.
|
|
- Preserve all line breaks, blank lines, and whitespace patterns.
|
|
- Return ONLY the translated content, no wrapping or explanations.
|
|
SYSTEM_PROMPT_MESSAGE
|
|
end
|
|
end
|