Nhật ký công việc cho nhiệm vụ "Sửa trình dịch"
Это поправил. Проблема была в том, что агент нарушал форматирование в yaml-документе. Текстовый ответ прилетал такой:
en:
name: |
Growth in Specialist Productivity Requires Corresponding Development of the Business Technological Environment
description: |
Business gets the maximum out of new technologies and strong specialists only when its own technological environment allows realizing their productivity.
content: |
New technologies increase specialist productivity, but this productivity is not realized in a vacuum.
Тут description и content являлись не вложенностью в en, как name, а уже новыеми разделами. В итоге получалась вот такая конечная структура ответа:
{
en: {
name: 'Growth in Specialist Productivity Requires Corresponding Development of the Business Technological Environment\n'
},
description: 'Business gets the maximum out of new technologies and strong specialists only when its own technological environment allows realizing their productivity.\n',
content: 'New technologies increase specialist productivity, but this productivity is not realized in a vacuum.
То есть переведенным у нас тут являлось только название, а все остальное не попадало в обработку.
В итоге сделал две вещи:
1. Вынес в разные сообщения отдельно системный промпт со всеми правилась, а документ для перевода в пользовательское сообщение. При таком подходе логическая структура данных для llm более различима.
2. Усилил правила для форматирования yaml.
Получилось вот так:
const fieldsYaml = fieldsToTranslate
.map(
({ field, value }) =>
`${field}: |\n${value
.split('\n')
.map((line) => ' ' + line)
.join('\n')}`,
)
.join('\n')
const fieldNames = fieldsToTranslate.map((f) => f.field)
const systemPrompt = `You are a professional translator specializing in technical documentation and web content.
# YAML OUTPUT RULES (CRITICAL)
You MUST output valid YAML with this EXACT structure:
\`\`\`
<lang_code>:
<field_name>: |
<translated text line 1>
<translated text line 2>
\`\`\`
**STRICT REQUIREMENTS:**
1. Each language code (en, de, etc.) MUST be at the ROOT level (no indentation)
2. Each field (name, description, content) MUST be indented with exactly 2 spaces under its language
3. Field values MUST use the literal block scalar (|) syntax
4. Text content MUST be indented with exactly 4 spaces (2 for field + 2 for content)
5. NEVER put fields at the root level - they MUST always be nested under a language code
# TRANSLATION RULES
1. **Translate, do not transliterate.** Convert meaning, not just letters.
2. Only include fields that were provided in the source.
3. Preserve all markdown and HTML formatting exactly.
4. Exception: Proper nouns, brand names, company names, and product names should be transliterated to Latin script.
# OUTPUT FORMAT
Respond ONLY with valid YAML. No markdown code blocks, no explanations, no comments - just raw YAML.`
const userPrompt = `Translate the following fields from Russian into: ${targetLangs.join(', ')}
## Source fields:
${fieldsYaml}
## Expected output structure:
${targetLangs
.map(
(lang) =>
`${lang}:\n${fieldNames.map((f) => ` ${f}: |\n <translated ${f}>`).join('\n')}`,
)
.join('\n')}`
const chatResponse = await llmChatCompletionResolver(
null,
{
input: {
provider: LlmProvider.OpenRouter,
messages: [
{
role: LLMChatMessageRole.system,
content: systemPrompt,
},
{
role: LLMChatMessageRole.user,
content: userPrompt,
},
],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
model: LlmModel.GEMINI_3_5_FLASH_LITE as any,
},
},
ctx,
)
const responseContent = chatResponse.choices?.[0]?.message?.content
Справедливости ради стоит отметить, что тут все равно в пользовательское сообщение примешены и технические инструкции, но все равно, работать стало значительно стабильней.