fix: search faqs in account language (#13428)

# Pull Request Template

## Description

Reply suggestions uses `search_documentation`. While this is useful,
there is a subtle bug, a user's message may be in a different language
(say spanish) than the FAQs present (english).
This results in embedding search in spanish and compared against english
vectors, which results in poor retrieval and poor suggestions.


Fixes # (issue)
This PR fixes the above behaviour by making a small llm call translate
the query before searching in the search documentation tool


## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

before:
<img width="894" height="157" alt="image"
src="https://github.com/user-attachments/assets/83871ee5-511e-4432-8b99-39e803759f63"
/>

after:
<img width="1149" height="294" alt="image"
src="https://github.com/user-attachments/assets/f9617d7a-6d48-4ca1-ad1c-2181e16c1f3d"
/>


test on rails console:
<img width="2094" height="380" alt="image"
src="https://github.com/user-attachments/assets/159fdaa5-8808-49d2-be5d-304d69fa97f7"
/>


## 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
- [x] Any dependent changes have been merged and published in downstream
modules
This commit is contained in:
Aakash Bakhle
2026-02-09 17:25:11 +05:30
committed by GitHub
parent 67112647e8
commit bd732f1fa9
7 changed files with 80 additions and 16 deletions

View File

@@ -0,0 +1,49 @@
class Captain::Llm::TranslateQueryService < Captain::BaseTaskService
MODEL = 'gpt-4.1-nano'.freeze
pattr_initialize [:account!]
def translate(query, target_language:)
return query if query_in_target_language?(query)
messages = [
{ role: 'system', content: system_prompt(target_language) },
{ role: 'user', content: query }
]
response = make_api_call(model: MODEL, messages: messages)
return query if response[:error]
response[:message].strip
rescue StandardError => e
Rails.logger.warn "TranslateQueryService failed: #{e.message}, falling back to original query"
query
end
private
def event_name
'translate_query'
end
def query_in_target_language?(query)
detector = CLD3::NNetLanguageIdentifier.new(0, 1000)
result = detector.find_language(query)
result.reliable? && result.language == account_language_code
rescue StandardError
false
end
def account_language_code
account.locale&.split('_')&.first
end
def system_prompt(target_language)
<<~SYSTEM_PROMPT_MESSAGE
You are a helpful assistant that translates queries from one language to another.
Translate the query to #{target_language}.
Return just the translated query, no other text.
SYSTEM_PROMPT_MESSAGE
end
end

View File

@@ -9,7 +9,11 @@ class Captain::Tools::SearchDocumentationService < Captain::Tools::BaseTool
def execute(query:)
Rails.logger.info { "#{self.class.name}: #{query}" }
responses = assistant.responses.approved.search(query)
translated_query = Captain::Llm::TranslateQueryService
.new(account: assistant.account)
.translate(query, target_language: assistant.account.locale_english_name)
responses = assistant.responses.approved.search(translated_query)
return 'No FAQs found for the given query' if responses.empty?

View File

@@ -18,7 +18,11 @@ class Captain::Tools::SearchReplyDocumentationService < RubyLLM::Tool
def execute(query:)
Rails.logger.info { "#{self.class.name}: #{query}" }
responses = search_responses(query)
translated_query = Captain::Llm::TranslateQueryService
.new(account: @account)
.translate(query, target_language: @account.locale_english_name)
responses = search_responses(translated_query)
return 'No FAQs found for the given query' if responses.empty?
responses.map { |response| format_response(response) }.join