Skip to content

Commit 4ee31b7

Browse files
committed
FIX: Use specific prompts for topic titles
1 parent e974006 commit 4ee31b7

File tree

7 files changed

+109
-55
lines changed

7 files changed

+109
-55
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# frozen_string_literal: true
2+
3+
module DiscourseAi
4+
class BaseTranslator
5+
def initialize(text, target_language)
6+
@text = text
7+
@target_language = target_language
8+
end
9+
10+
def translate
11+
prompt =
12+
DiscourseAi::Completions::Prompt.new(
13+
build_prompt(@target_language),
14+
messages: [{ type: :user, content: "#{@text}", id: "user" }],
15+
)
16+
17+
DiscourseAi::Completions::Llm.proxy(SiteSetting.ai_helper_model).generate(
18+
prompt,
19+
user: Discourse.system_user,
20+
feature_name: "translator-translate",
21+
)
22+
end
23+
24+
private
25+
26+
def build_prompt(target_language)
27+
prompt_template % { target_language: target_language }
28+
end
29+
30+
def prompt_template
31+
raise NotImplementedError
32+
end
33+
end
34+
end
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
module DiscourseAi
4+
class PostTranslator < BaseTranslator
5+
PROMPT_TEMPLATE = <<~TEXT.freeze
6+
Translate this content to "%{target_language}". You must:
7+
1. Translate the content accurately while preserving any Markdown, HTML elements, or newlines
8+
2. Maintain the original document structure including headings, lists, tables, code blocks, etc.
9+
3. Preserve all links, images, and other media references without translation
10+
4. Handle code snippets appropriately - don't translate variable names, functions, or syntax within code blocks (```), but translate comments
11+
5. When encountering technical terminology, provide the accepted target language term if it exists, or transliterate if no equivalent exists, with the original term in parentheses
12+
6. For ambiguous terms or phrases, choose the most contextually appropriate translation
13+
7. Do not add any content besides the translation
14+
8. You are being consumed via an API, only EVER return the translated text, do not return any other information
15+
TEXT
16+
17+
private def prompt_template
18+
PROMPT_TEMPLATE
19+
end
20+
end
21+
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# frozen_string_literal: true
2+
3+
module DiscourseAi
4+
class TopicTranslator < BaseTranslator
5+
PROMPT_TEMPLATE = <<~TEXT.freeze
6+
Translate this topic title to "%{target_language}"
7+
- Keep the original language when it is a proper noun or technical term
8+
- The translation should be around the same length as the original
9+
TEXT
10+
11+
private def prompt_template
12+
PROMPT_TEMPLATE
13+
end
14+
end
15+
end

app/services/discourse_ai/translator.rb

Lines changed: 0 additions & 41 deletions
This file was deleted.

app/services/discourse_translator/discourse_ai.rb

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,19 @@ def self.translate!(translatable, target_locale_sym = I18n.locale)
3333
),
3434
)
3535
end
36+
37+
language = get_language_name(target_locale_sym)
3638
translated =
37-
::DiscourseAi::Translator.new(
38-
text_for_translation(translatable, raw: true),
39-
target_locale_sym,
40-
).translate
39+
case translatable.class.name
40+
when "Post"
41+
::DiscourseAi::PostTranslator.new(
42+
text_for_translation(translatable, raw: true),
43+
language,
44+
).translate
45+
when "Topic"
46+
::DiscourseAi::TopicTranslator.new(text_for_translation(translatable), language).translate
47+
end
48+
4149
DiscourseTranslator::TranslatedContentNormalizer.normalize(translatable, translated)
4250
end
4351

@@ -47,5 +55,10 @@ def self.required_settings_enabled
4755
SiteSetting.translator_enabled && SiteSetting.translator_provider == "DiscourseAi" &&
4856
SiteSetting.discourse_ai_enabled && SiteSetting.ai_helper_enabled
4957
end
58+
59+
def self.get_language_name(target_locale_sym)
60+
LocaleSiteSetting.language_names.dig(target_locale_sym.to_s, "name") ||
61+
"locale \"#{target_locale_sym}\""
62+
end
5063
end
5164
end

spec/services/discourse_ai/translator_spec.rb renamed to spec/services/discourse_ai/base_translator_spec.rb

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
require "rails_helper"
44

5-
describe DiscourseAi::Translator do
5+
describe DiscourseAi::BaseTranslator do
66
before do
77
Fabricate(:fake_model).tap do |fake_llm|
88
SiteSetting.public_send("ai_helper_model=", "custom:#{fake_llm.id}")
@@ -17,19 +17,20 @@
1717
it "creates the correct prompt" do
1818
allow(DiscourseAi::Completions::Prompt).to receive(:new).with(
1919
<<~TEXT,
20-
You are an expert translator specializing in converting Markdown content from any source language to target locale "de". Your task is to:
21-
1. Translate the content accurately while preserving all Markdown formatting elements
20+
Translate this content to "de". You must:
21+
1. Translate the content accurately while preserving any Markdown, HTML elements, or newlines
2222
2. Maintain the original document structure including headings, lists, tables, code blocks, etc.
2323
3. Preserve all links, images, and other media references without translation
2424
4. Handle code snippets appropriately - don't translate variable names, functions, or syntax within code blocks (```), but translate comments
2525
5. When encountering technical terminology, provide the accepted target language term if it exists, or transliterate if no equivalent exists, with the original term in parentheses
2626
6. For ambiguous terms or phrases, choose the most contextually appropriate translation
27-
7. You are being consumed via an API, only EVER return the translated text, do not return any other information
27+
7. Do not add any content besides the translation
28+
8. You are being consumed via an API, only EVER return the translated text, do not return any other information
2829
TEXT
2930
messages: [{ type: :user, content: "cats are great", id: "user" }],
3031
).and_call_original
3132

32-
described_class.new(text_to_translate, target_language).translate
33+
DiscourseAi::PostTranslator.new(text_to_translate, target_language).translate
3334
end
3435

3536
it "sends the translation prompt to the selected ai helper model" do
@@ -46,13 +47,13 @@
4647
feature_name: "translator-translate",
4748
)
4849

49-
described_class.new(text_to_translate, target_language).translate
50+
DiscourseAi::PostTranslator.new(text_to_translate, target_language).translate
5051
end
5152

5253
it "returns the translation from the llm's response" do
5354
DiscourseAi::Completions::Llm.with_prepared_responses(["hur dur hur dur!"]) do
5455
expect(
55-
described_class.new(text_to_translate, target_language).translate,
56+
DiscourseAi::PostTranslator.new(text_to_translate, target_language).translate,
5657
).to eq "hur dur hur dur!"
5758
end
5859
end

spec/services/discourse_ai_spec.rb

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
# frozen_string_literal: true
22

3-
require "rails_helper"
4-
53
describe DiscourseTranslator::DiscourseAi do
64
fab!(:post)
5+
fab!(:topic)
76

87
before do
98
Fabricate(:fake_model).tap do |fake_llm|
@@ -36,7 +35,10 @@
3635
end
3736

3837
describe ".translate" do
39-
before { post.set_detected_locale("de") }
38+
before do
39+
post.set_detected_locale("de")
40+
topic.set_detected_locale("de")
41+
end
4042

4143
it "translates the post and returns [locale, translated_text]" do
4244
DiscourseAi::Completions::Llm.with_prepared_responses(["some translated text"]) do
@@ -45,5 +47,14 @@
4547
expect(translated_text).to eq "<p>some translated text</p>"
4648
end
4749
end
50+
51+
it "translates the topic" do
52+
expect(::DiscourseAi::TopicTranslator).to receive(:new).and_call_original
53+
DiscourseAi::Completions::Llm.with_prepared_responses(["some translated text"]) do
54+
locale, translated_text = DiscourseTranslator::DiscourseAi.translate(topic)
55+
expect(locale).to eq "de"
56+
expect(translated_text).to eq "some translated text"
57+
end
58+
end
4859
end
4960
end

0 commit comments

Comments
 (0)