i18n: prepend a strong language directive for portfolio + chat
Reports that portfolio AI analysis was coming back in English even for IT-toggled users. Traced the chain (DB user.lang IS set to it, router passes it into the payload, parse_request reads it, build_prompt appends respond_in_clause), so the wiring is correct end-to-end. The model was simply ignoring the single-sentence tail nudge: when the system prompt is hundreds of lines of English and the user message adds more English context, "Respond in Italian." at the end is easy to drop on the floor. Add a new services/i18n.language_directive_lead() that returns a strong, explicit top-of-prompt block — "# LANGUAGE — write everything in <X>" plus the verbatim-tickers-and-numbers carve-out — meant to be PREPENDED so the model anchors on the target language before it reads the bulk of the instructions. Combined with the existing tail clause it's belt-and-suspenders: top + bottom of the prompt both say "in this language". Applied to portfolio_analysis.build_prompt() and chat.py — the two surfaces that generate user-facing prose in real time (the strategic log + indicator summaries get post-hoc translation via translate(), so the directive isn't needed there). Empty-string return for en / unknown lang means callers can wire it in unconditionally; no extra plumbing in i18n callsites. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
736d161990
commit
13dd3a8330
3 changed files with 52 additions and 9 deletions
|
|
@ -21,7 +21,7 @@ from app.db import get_session, utcnow
|
|||
from app.jobs._market_context import REFERENCE_LINE
|
||||
from app.models import AICall, Headline, Quote, StrategicLog
|
||||
from app.routers.api import _md_to_html
|
||||
from app.services.i18n import respond_in_clause
|
||||
from app.services.i18n import language_directive_lead, respond_in_clause
|
||||
from app.services.llm_prompts import build_chat_system_prompt
|
||||
from app.services.openrouter import call_llm, month_start
|
||||
from app.services.output_review import review_read
|
||||
|
|
@ -165,13 +165,17 @@ async def chat(
|
|||
headlines=headlines,
|
||||
reference_line=REFERENCE_LINE,
|
||||
)
|
||||
# Respect the user's interface language preference: append a single
|
||||
# localized "respond in" nudge so the assistant answers in IT when
|
||||
# the user has lang=it. The prompt + history (which includes the
|
||||
# user's own question, often in their language) are usually enough,
|
||||
# but the nudge guarantees the first reply lands correctly.
|
||||
# Respect the user's interface language preference. The tail
|
||||
# "Respond in X" clause is easy for the model to drop when the
|
||||
# rest of the prompt is English (long log content, English
|
||||
# market data, English headlines), so we ALSO prepend a stronger
|
||||
# language directive at the top — see services/i18n.
|
||||
user_lang = principal.user.lang if principal and principal.user else "en"
|
||||
system_prompt = system_prompt + respond_in_clause(user_lang)
|
||||
system_prompt = (
|
||||
language_directive_lead(user_lang)
|
||||
+ system_prompt
|
||||
+ respond_in_clause(user_lang)
|
||||
)
|
||||
|
||||
msgs = [{"role": "system", "content": system_prompt}]
|
||||
for m in history:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue