Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 5d80a34

Browse files
authored
FIX: Add a max token limit based on the text to be translated (#1507)
We're seeing that some LLMs are using 65000+ tokens for raw text that is only 10-1000 characters long. This PR adds a max_token to be passed to the LLM API for each translation based on the length of the text.
1 parent 8630bc1 commit 5d80a34

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

lib/translation/base_translator.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,24 @@ def get_translation(text:, bot:, translation_user:)
4646
topic: @topic,
4747
post: @post,
4848
)
49+
max_tokens = get_max_tokens(text)
50+
llm_args = { max_tokens: }
4951

5052
result = +""
51-
bot.reply(context) { |partial| result << partial }
53+
bot.reply(context, llm_args:) { |partial| result << partial }
5254
result
5355
end
5456

57+
def get_max_tokens(text)
58+
if text.length < 100
59+
500
60+
elsif text.length < 500
61+
1000
62+
else
63+
text.length * 2
64+
end
65+
end
66+
5567
def persona_setting
5668
raise NotImplementedError
5769
end

spec/lib/translation/base_translator_spec.rb

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
let(:target_locale) { "de" }
2121
let(:llm_response) { "hur dur hur dur!" }
2222
fab!(:post)
23+
fab!(:topic) { post.topic }
2324

2425
it "creates the correct prompt" do
2526
post_translator =
@@ -36,6 +37,62 @@
3637
end
3738
end
3839

40+
it "creates BotContext with the correct parameters and calls bot.reply with correct args" do
41+
post_translator =
42+
DiscourseAi::Translation::PostRawTranslator.new(text:, target_locale:, post:, topic:)
43+
44+
expected_content = { content: text, target_locale: target_locale }.to_json
45+
46+
bot_context = instance_double(DiscourseAi::Personas::BotContext)
47+
allow(DiscourseAi::Personas::BotContext).to receive(:new).and_return(bot_context)
48+
49+
mock_bot = instance_double(DiscourseAi::Personas::Bot)
50+
allow(DiscourseAi::Personas::Bot).to receive(:as).and_return(mock_bot)
51+
allow(mock_bot).to receive(:reply).and_yield(llm_response)
52+
53+
post_translator.translate
54+
55+
expect(DiscourseAi::Personas::BotContext).to have_received(:new).with(
56+
user: an_instance_of(User),
57+
skip_tool_details: true,
58+
feature_name: "translation",
59+
messages: [{ type: :user, content: expected_content }],
60+
topic: topic,
61+
post: post,
62+
)
63+
64+
expect(DiscourseAi::Personas::Bot).to have_received(:as)
65+
expect(mock_bot).to have_received(:reply).with(bot_context, llm_args: { max_tokens: 500 })
66+
end
67+
68+
it "sets max_tokens correctly based on text length" do
69+
test_cases = [
70+
["Short text", 500], # Short text (< 100 chars)
71+
["a" * 200, 1000], # Medium text (100-500 chars)
72+
["a" * 600, 1200], # Long text (> 500 chars, 600*2=1200)
73+
]
74+
75+
test_cases.each do |text, expected_max_tokens|
76+
translator = DiscourseAi::Translation::PostRawTranslator.new(text: text, target_locale:)
77+
78+
bot_context = instance_double(DiscourseAi::Personas::BotContext)
79+
allow(DiscourseAi::Personas::BotContext).to receive(:new).and_return(bot_context)
80+
81+
mock_bot = instance_double(DiscourseAi::Personas::Bot)
82+
allow(DiscourseAi::Personas::Bot).to receive(:as).and_return(mock_bot)
83+
allow(mock_bot).to receive(:reply).and_yield("translated #{text[0..10]}")
84+
85+
translator.translate
86+
87+
expect(mock_bot).to have_received(:reply).with(
88+
bot_context,
89+
llm_args: {
90+
max_tokens: expected_max_tokens,
91+
},
92+
)
93+
end
94+
end
95+
3996
it "returns the translation from the llm's response" do
4097
DiscourseAi::Completions::Llm.with_prepared_responses([llm_response]) do
4198
expect(

0 commit comments

Comments
 (0)