Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions app/services/discourse_ai/translator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
module DiscourseAi
class Translator
PROMPT_TEMPLATE = <<~TEXT.freeze
You are a highly skilled linguist and web programmer, with expertise in many languages, and very well versed in HTML.
You are a highly skilled linguist of many languages and have expert knowledge in HTML.
Your task is to identify the language of the text I provide and accurately translate it into this language locale "%{target_language}" while preserving the meaning, tone, and nuance of the original text.
The text will contain html tags, which must absolutely be preserved in the translation.
The text may or may not contain html tags. If they do, preserve them.
Maintain proper grammar, spelling, and punctuation in the translated version.
Wrap the translated text in a <translation> tag.
You will find the text between <input></input> XML tags.
Include your translation between <output></output> XML tags.
Do not write explanations.
TEXT

def initialize(text, target_language)
Expand All @@ -19,7 +21,7 @@ def translate
prompt =
DiscourseAi::Completions::Prompt.new(
build_prompt(@target_language),
messages: [{ type: :user, content: @text, id: "user" }],
messages: [{ type: :user, content: "<input>#{@text}</input>", id: "user" }],
)

llm_translation =
Expand All @@ -29,7 +31,7 @@ def translate
feature_name: "translator-translate",
)

(Nokogiri::HTML5.fragment(llm_translation).at("translation")&.inner_html || llm_translation)
(Nokogiri::HTML5.fragment(llm_translation).at("output")&.inner_html || "").strip
end

private
Expand Down
16 changes: 16 additions & 0 deletions db/migrate/20250224120505_cleanup_ai_translations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

class CleanupAiTranslations < ActiveRecord::Migration[7.2]
def up
execute <<~SQL
DELETE FROM discourse_translator_topic_translations
WHERE translation LIKE 'To%'
AND translation ILIKE '%translat%'
AND LENGTH(translation) > 100;
SQL
end

def down
raise ActiveRecord::IrreversibleMigration
end
end
18 changes: 9 additions & 9 deletions spec/services/discourse_ai/translator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
it "creates the correct prompt" do
allow(DiscourseAi::Completions::Prompt).to receive(:new).with(
<<~TEXT,
You are a highly skilled linguist and web programmer, with expertise in many languages, and very well versed in HTML.
You are a highly skilled linguist of many languages and have expert knowledge in HTML.
Your task is to identify the language of the text I provide and accurately translate it into this language locale "de" while preserving the meaning, tone, and nuance of the original text.
The text will contain html tags, which must absolutely be preserved in the translation.
The text may or may not contain html tags. If they do, preserve them.
Maintain proper grammar, spelling, and punctuation in the translated version.
Wrap the translated text in a <translation> tag.
You will find the text between <input></input> XML tags.
Include your translation between <output></output> XML tags.
Do not write explanations.
TEXT
messages: [{ type: :user, content: text_to_translate, id: "user" }],
messages: [{ type: :user, content: "<input>cats are great</input>", id: "user" }],
).and_call_original

described_class.new(text_to_translate, target_language).translate
Expand All @@ -48,19 +50,17 @@

it "returns the translation from the llm's response in the translation tag" do
DiscourseAi::Completions::Llm.with_prepared_responses(
["<translation>hur dur hur dur!</translation>"],
["<output>hur dur hur dur!</output>"],
) do
expect(
described_class.new(text_to_translate, target_language).translate,
).to eq "hur dur hur dur!"
end
end

it "returns the raw response if the translation tag is not present" do
it "returns the nothing if the translation tag is not present" do
DiscourseAi::Completions::Llm.with_prepared_responses(["raw response."]) do
expect(
described_class.new(text_to_translate, target_language).translate,
).to eq "raw response."
expect(described_class.new(text_to_translate, target_language).translate).to eq ""
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/services/discourse_ai_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

it "translates the post and returns [locale, translated_text]" do
DiscourseAi::Completions::Llm.with_prepared_responses(
["<translation>some translated text</translation>"],
["<output>some translated text</output>"],
) do
locale, translated_text = DiscourseTranslator::DiscourseAi.translate(post)
expect(locale).to eq "de"
Expand Down
Loading