Repository navigation
feat(translate): translation instructions the model follows - #140
Merged
Merged
Conversation
Settings → Translation saves free text telling the model how to translate. It is appended to every LLM translator's prompt after the fixed rules, in a <user-instructions> fence, with the fixed rules winning on conflict; with none saved the prompt is byte-identical to before. BabelDOC's custom_system_prompt was not used: it is read only on the do_llm_translate path, which none of our translators implements. - Both caches key on the instructions, appended only when set, so no existing key moved. - Only an LLM that will really run gets them (capabilities.translation_instructions, asked of the effective service); chat, verify and pre-warm never do. - /translate/estimate counts them per paragraph, and the toolbar's estimate refetches when they change. - The toolbar shows "Instructions on" when they will be sent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Settings → Translation gets a box for free-text translation instructions: tone, terms to keep, how to render names. They are sent with every paragraph to the LLM that translates. Chat never receives them.
TranslationConfig.custom_system_promptwould have no effect: BabelDOC reads it only when a translator implementsdo_llm_translate, and none of ours does.BaseTranslator._user_instructions_blockappends them after the fixed rules, inside a<user-instructions>fence, and says the fixed rules (target language, reply with the translation alone, copy placeholders) win on conflict. With none saved, the prompt is byte-identical to before; a test pins the pre-change hashes.|instructions=<text>is appended only when they are set, likepages=. No existing key changes and no migration is needed. Without this, a changed instruction was served the old instruction's translations.capabilities.translation_instructions(settings, service)is asked once, of the effective service, so a keyless LLM that runs as Argos gets none. The processor hands that one value to the translator and to both ends of the PDF cache. Chat, verify and pre-warm build translators without them, and a factory test guards that.translation.instructions, at most 2,000 characters, trimmed, blank stored as unset.PUT /configtakestranslation_instructions: omitted leaves it unchanged,nullor blank clears it. Over-long text in a hand-editedconfig.tomldrops just that field./translate/estimatecounts the instructions on every paragraph. The constant was measured against the real prompt and is held within 10% by a test. The toolbar's estimate refetches when the instructions change.Docs: a new "Translation instructions" section in
docs/architecture/translators.md, plus an invariant and thePUT /configcontract inCLAUDE.md.Tests
Written test-first. A separate agent wrote the red tests from the spec before any production code existed, and an
opusreviewer checked the finished cycle. That review's findings are fixed here:Several guard tests were also mutation-checked: each was broken on purpose and confirmed to fail.
pytest tests: all pass, andruffis clean.pnpm test(654 tests) andpnpm buildpass.openapi.jsonandapi-types.d.tswere regenerated under FastAPI 0.156, matching CI.Checked by hand
A real EN→VI run on
gemini-2.5-flash-lite, through the sidecar, with a 2-page programming PDF:pnpm tauri devon Linux:Not covered by unit tests:
lib/translation-instructions.tsNotes for reviewers
Small models follow concrete instructions much better than vague ones. On flash-lite:
Translating several paragraphs per request (BabelDOC's
do_llm_translatepath) did not change that, so this PR keeps one paragraph per request.Typing Vietnamese with Lotus on Linux: the text box only takes it with Lotus in Preedit mode. Its default "Surrounding Text" mode doesn't work in WebKitGTK. This is environmental and not changed here.
🤖 Generated with Claude Code