From afacc34969fe53500c6697b29fa587a9329902b4 Mon Sep 17 00:00:00 2001 From: alvis Date: Wed, 6 May 2026 11:53:21 +0000 Subject: [PATCH] fix(agents): instruct orchestrator to output tip in English Small models (qwen2.5:1.5b) mirror the language of task title content in the prompt. Adding an explicit English note to snippets that embed raw task titles (focus-area, overdue-task) prevents language bleed. Also added the instruction to the orchestrator system prompt and user message as belt-and-suspenders. Co-Authored-By: Claude Sonnet 4.6 --- ml/agents/focus_area.py | 3 ++- ml/agents/overdue_task.py | 8 ++++---- ml/serving/prompts.py | 3 ++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ml/agents/focus_area.py b/ml/agents/focus_area.py index 159d481..49f963b 100644 --- a/ml/agents/focus_area.py +++ b/ml/agents/focus_area.py @@ -88,7 +88,8 @@ class FocusAreaAgent(BaseAgent): parts = [ f'The user\'s most active focus area is "{top.label}" ' f"({top.task_count} task{'s' if top.task_count != 1 else ''}, " - f"{top.overdue_count} overdue)." + f"{top.overdue_count} overdue). " + f"(Note: task titles may be in any language — always write the tip in English.)" ] if boosted: parts.append("This area matches the user's stated focus preferences.") diff --git a/ml/agents/overdue_task.py b/ml/agents/overdue_task.py index 7ea8062..7313d2e 100644 --- a/ml/agents/overdue_task.py +++ b/ml/agents/overdue_task.py @@ -128,15 +128,15 @@ class OverdueTaskAgent(BaseAgent): top = sorted(overdue, key=lambda t: -t.get("task_age_days", 0))[:3] if not overdue: - prompt = "The user has no overdue tasks at this time." + prompt = "The user has no overdue tasks at this time. (Always write the tip in English.)" elif len(overdue) == 1: t = top[0] r = _realness(t.get("project_id"), project_realness) item = _format_task(t, project_realness) if r < 0.4: - prompt = f"The user has 1 task past its target date: {item}." + prompt = f"The user has 1 task past its target date: {item}. (Task titles may be in any language — always write the tip in English.)" else: - prompt = f"The user has 1 overdue task: {item}." + prompt = f"The user has 1 overdue task: {item}. (Task titles may be in any language — always write the tip in English.)" else: items = ", ".join(_format_task(t, project_realness) for t in top) avg_realness = ( @@ -146,7 +146,7 @@ class OverdueTaskAgent(BaseAgent): label = "tasks past their target dates" if avg_realness < 0.4 else "overdue tasks" prompt = ( f"The user has {len(overdue)} {label}. " - f"Top {len(top)}: {items}." + f"Top {len(top)}: {items}. (Task titles may be in any language — always write the tip in English.)" ) snapshot = { diff --git a/ml/serving/prompts.py b/ml/serving/prompts.py index 6b9a91b..2c78aab 100644 --- a/ml/serving/prompts.py +++ b/ml/serving/prompts.py @@ -116,6 +116,7 @@ _SYS_V4_ORCHESTRATOR = ( "Multiple specialized agents have analyzed the user's current context and provided " "their insights below. Synthesize their combined perspective to generate exactly ONE " "tip that is specific, actionable, and relevant right now. " + "Always respond in English regardless of the language of task content. " "Respond ONLY with a JSON object with keys: " '"id" (short slug), "content" (the tip, ≤2 sentences), ' '"rationale" (why now, ≤1 sentence). ' @@ -147,7 +148,7 @@ def build_orchestrator_messages( ) for t in tasks[:3]: lines.append(f" - {t.get('content', '?')}") - lines.append("\nGenerate one tip as a JSON object.") + lines.append("\nGenerate one tip as a JSON object. Write the tip content in English only.") return [ {"role": "system", "content": _SYS_V4_ORCHESTRATOR}, {"role": "user", "content": "\n".join(lines)},