Files
daily_stock_analysis/tests/test_report_language_prompt_directives.py
HyunRyeol Park 043c60378e feat: 报告输出语言新增韩语支持 (Korean report language, ko) (#1614) (#1844)
* feat(i18n): add Korean to report language label maps

Extend the report language layer with a third code `ko` so reports can
render deterministic labels in Korean. Adds `ko` to the supported list,
aliases (korean/kr/ko-kr), every translation map, the full report label
set, sentiment bands, the config registry enum and `.env.example`.
`zh`/`en` behavior is unchanged and unknown languages still fall back to
the default. Prompt and Web surfaces follow in later changes.

Refs #1614

* feat(i18n): emit Korean output directives in analysis prompts

Make the analysis and market-review prompts produce Korean output when
REPORT_LANGUAGE=ko. The decision agent now appends a Korean
output-language directive (JSON keys and decision_type enum unchanged),
and the market-review prompt reuses the English structural scaffolding
while instructing the model to write the shell, headings and conclusion
in Korean. Market-phase and context-pack prompt sections route ko to the
English structural base. The market-review payload keeps the truthful
language code via a dedicated output-language helper, leaving zh/en
behavior unchanged.

Refs #1614

* fix(i18n): localize phase and market-context guardrails for Korean

Route Korean reports through the English structural scaffolding for
market-phase and market-context prompt sections, and add Korean output,
detection markers, negations and recap patterns to the phase-decision and
daily-market-context guardrails so they operate on Korean model output.
Confidence and operation labels now flow through the shared localize
helpers. zh/en behavior is unchanged.

Refs #1614

* feat(i18n): localize Korean fallback output across analysis pipeline

Add Korean output to the deterministic strings emitted outside the LLM:
per-stock and executor output-language directives, no-API-key / backend
/ parse error fallbacks, hold-watch advice and reasons, market-review
titles and summaries, and history and notification report labels. Fund
flow, trend and confidence values now flow through the shared localize
helpers, and language-keyed advice tables no longer raise KeyError for a
third language. Structural prompt sections route ko to the English
scaffolding. zh/en output is unchanged.

Refs #1614

* feat(web): add Korean report language rendering

Extend the Web ReportLanguage type with ko and add Korean copy to the
report detail surfaces: report text, sentiment labels, market-phase
labels, analysis-context summary, market-review view, diagnostics and
news source. Run-flow chrome that is keyed by UI language falls back to
English for ko. The report-language selector is driven by the backend
config schema, so Korean appears automatically. zh/en rendering is
unchanged.

Refs #1614

* docs(i18n): document Korean report language support

Note that REPORT_LANGUAGE accepts ko in the bilingual guides and the
analyze / market-review request-language parameters, and add a
CHANGELOG entry for Korean report output.

Refs #1614

* fix(i18n): canonicalize Korean values and accept ko in API schemas

Add Korean aliases to the operation-advice, trend, confidence, chip and
bias canonical maps so Korean model output (매수/매도/보유/관망 etc.)
resolves to the correct decision_type and signal level instead of
falling back to hold or a score-band signal. Accept ko in the
analyze, market-review and decision-signal request schemas (and the
static API spec) so the typed client and backend agree and per-request
Korean analysis is not rejected with 422.

Refs #1614
2026-06-30 19:02:46 +08:00

67 lines
2.7 KiB
Python

# -*- coding: utf-8 -*-
"""Tests for Korean (ko) output-language directives in analysis prompts (#1614)."""
import unittest
from src.agent.agents.decision_agent import DecisionAgent
from src.agent.protocols import AgentContext
from src.analysis_context_pack_prompt import normalize_analysis_context_pack_language
from src.market_phase_prompt import format_market_phase_prompt_section
def _phase_ctx():
return {
"market": "us",
"phase": "premarket",
"market_local_time": "2026-06-29T08:00:00-04:00",
"effective_daily_bar_date": "2026-06-27",
"minutes_to_open": 90,
"warnings": [],
}
class DecisionAgentLanguageDirectiveTestCase(unittest.TestCase):
def setUp(self) -> None:
self.agent = DecisionAgent(tool_registry=None, llm_adapter=None)
def _system_prompt(self, language: str, *, chat: bool = False) -> str:
meta = {"report_language": language}
if chat:
meta["response_mode"] = "chat"
ctx = AgentContext(stock_code="005930.KS", stock_name="삼성전자", meta=meta)
return self.agent.system_prompt(ctx)
def test_korean_dashboard_directive(self) -> None:
prompt = self._system_prompt("ko")
self.assertIn("Write all human-readable JSON values in Korean (한국어).", prompt)
self.assertIn("`decision_type` must remain `buy|hold|sell`.", prompt)
def test_korean_chat_directive(self) -> None:
prompt = self._system_prompt("ko", chat=True)
self.assertIn("항상 한국어로 답변하세요.", prompt)
def test_english_directive_unchanged(self) -> None:
prompt = self._system_prompt("en")
self.assertIn("Write all human-readable JSON values in English.", prompt)
def test_chinese_directive_unchanged(self) -> None:
prompt = self._system_prompt("zh")
self.assertIn("所有面向用户的人类可读文本值必须使用中文。", prompt)
class StructuralLanguageRoutingTestCase(unittest.TestCase):
def test_context_pack_korean_reuses_english_scaffolding(self) -> None:
self.assertEqual(normalize_analysis_context_pack_language("ko"), "en")
self.assertEqual(normalize_analysis_context_pack_language("en"), "en")
self.assertEqual(normalize_analysis_context_pack_language("zh"), "zh")
def test_market_phase_korean_matches_english_structure(self) -> None:
ko_section = format_market_phase_prompt_section(_phase_ctx(), report_language="ko")
en_section = format_market_phase_prompt_section(_phase_ctx(), report_language="en")
self.assertEqual(ko_section, en_section)
self.assertIn("## Market Phase Context", ko_section)
if __name__ == "__main__":
unittest.main()