Environment
- Lingarr image:
ghcr.io/lingarr-translate/lingarr:latest
- Service type: LocalAI (OpenAI-compatible
/v1/chat/completions)
- Endpoint:
https://nano-gpt.com/api/v1/chat/completions
- Model:
deepseek/deepseek-v4-flash
Summary
When TranslateBatchWithStructuredOutput is used, the batch_translation_response schema's line field has no language constraint. With smaller models, strict schema-constrained decoding dominates attention and the target-language directive in the system prompt is effectively ignored — every line is returned in an arbitrary non-target language (Hindi, Indonesian, Chinese, or pass-through English).
Reproduce
- In Lingarr → Settings → Services → LocalAI, configure:
- Endpoint:
https://nano-gpt.com/api/v1/chat/completions
- Model:
deepseek/deepseek-v4-flash
- API key: your Nano-GPT key
- Leave AI Prompt at its default (
Translate from {sourceLanguage} to {targetLanguage}, …).
- Set source language = English, target language = Danish.
- From Bazarr or directly in Lingarr, trigger translation of any English subtitle file (~100+ lines is enough; the issue is visible on the first batch).
- Wait for
status = Completed.
- Open the produced
.da.srt (or inspect translation_request_lines.target in the DB).
Expected: lines translated to Danish.
Actual: lines returned in Hindi (Devanagari), Indonesian, Chinese, or unchanged English — the language varies between runs but is never Danish.
A 1471-line subtitle I tested completed cleanly (en → da, status = Completed), but 0 of 1471 stored target lines contained any Danish letter (æ/ø/å); 300+ contained Devanagari.
Evidence
I intercepted Lingarr's outgoing request with a logging proxy and replayed it with only the model and response_format varied:
| Model |
response_format |
Output |
deepseek-v4-flash |
absent |
Danish ✅ |
deepseek-v4-flash |
strict schema (as Lingarr sends) |
Hindi / Indonesian / Chinese / pass-through English ❌ |
deepseek-v4-pro |
strict schema |
Danish ✅ |
Stronger system prompts, temperature: 0, and moving the directive to the user role did not help. The only mitigation that worked on Flash was adding the target language to the line field's description inside the schema:
"line": {
"type": "string",
"description": "Subtitle text translated into Danish (da). Must be Danish, never any other language."
}
With that single change, output was Danish across all trials.
Captured request/response from Lingarr (one batch, 100 lines)
Suggested fix
In TranslateBatchWithStructuredOutput, include the target language in the JSON-schema field descriptions, e.g.:
properties: new {
position = new { type = "integer", description = "Position number of the subtitle item" },
line = new { type = "string", description = $"Subtitle text translated into {targetLanguageName} ({targetLanguageCode}). Must be {targetLanguageName} only." }
}
This anchors the language directive inside the schema, where attention is concentrated during constrained decoding. It's a no-op for strong models (they already follow the system prompt) and a fix for smaller, faster models like DeepSeek V4 Flash.
Environment
ghcr.io/lingarr-translate/lingarr:latest/v1/chat/completions)https://nano-gpt.com/api/v1/chat/completionsdeepseek/deepseek-v4-flashSummary
When
TranslateBatchWithStructuredOutputis used, thebatch_translation_responseschema'slinefield has no language constraint. With smaller models, strict schema-constrained decoding dominates attention and the target-language directive in the system prompt is effectively ignored — everylineis returned in an arbitrary non-target language (Hindi, Indonesian, Chinese, or pass-through English).Reproduce
https://nano-gpt.com/api/v1/chat/completionsdeepseek/deepseek-v4-flashTranslate from {sourceLanguage} to {targetLanguage}, …).status = Completed..da.srt(or inspecttranslation_request_lines.targetin the DB).Expected: lines translated to Danish.
Actual: lines returned in Hindi (Devanagari), Indonesian, Chinese, or unchanged English — the language varies between runs but is never Danish.
A 1471-line subtitle I tested completed cleanly (
en → da,status = Completed), but 0 of 1471 stored target lines contained any Danish letter (æ/ø/å); 300+ contained Devanagari.Evidence
I intercepted Lingarr's outgoing request with a logging proxy and replayed it with only the model and
response_formatvaried:response_formatdeepseek-v4-flashdeepseek-v4-flashdeepseek-v4-proStronger system prompts,
temperature: 0, and moving the directive to the user role did not help. The only mitigation that worked on Flash was adding the target language to thelinefield'sdescriptioninside the schema:With that single change, output was Danish across all trials.
Captured request/response from Lingarr (one batch, 100 lines)
linevalues returned in Hindi): https://logs.notifiarr.com?cfafa656e719fa6b#68bYNPhx2zZjn5CzhEZ8hrP8yqL3RBzzzHN7iRqmdTcjSuggested fix
In
TranslateBatchWithStructuredOutput, include the target language in the JSON-schema field descriptions, e.g.:This anchors the language directive inside the schema, where attention is concentrated during constrained decoding. It's a no-op for strong models (they already follow the system prompt) and a fix for smaller, faster models like DeepSeek V4 Flash.