digest: factor tone clause; kw-only digest helper; empty-data test
This commit is contained in:
parent
ca6b174b51
commit
1391f15c28
2 changed files with 39 additions and 15 deletions
|
|
@ -508,6 +508,12 @@ def build_user_prompt(
|
||||||
return "\n".join(parts)
|
return "\n".join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
def _digest_tone_clause(tone: str) -> str:
|
||||||
|
if tone.upper() == "NOVICE":
|
||||||
|
return "Use plain English. Define any jargon on first use."
|
||||||
|
return "Write for a reader who already speaks markets fluently."
|
||||||
|
|
||||||
|
|
||||||
def build_daily_digest_prompt(
|
def build_daily_digest_prompt(
|
||||||
*,
|
*,
|
||||||
tone: str,
|
tone: str,
|
||||||
|
|
@ -521,21 +527,19 @@ def build_daily_digest_prompt(
|
||||||
Different from the hourly log: the daily digest reflects on the past
|
Different from the hourly log: the daily digest reflects on the past
|
||||||
24h and looks forward to the upcoming session. Longer, less
|
24h and looks forward to the upcoming session. Longer, less
|
||||||
'live-blogging,' more contextual. Target ~600 words."""
|
'live-blogging,' more contextual. Target ~600 words."""
|
||||||
tone_clause = (
|
|
||||||
"Use plain English. Define any jargon on first use."
|
|
||||||
if tone.upper() == "NOVICE"
|
|
||||||
else "Write for a reader who already speaks markets fluently."
|
|
||||||
)
|
|
||||||
system = (
|
system = (
|
||||||
"You write the daily editorial digest for Read the Markets. "
|
"You write the daily editorial digest for Read the Markets. "
|
||||||
f"Audience tone: {tone.upper()}. {tone_clause} "
|
f"Audience tone: {tone.upper()}. {_digest_tone_clause(tone)} "
|
||||||
"Cover: (1) what mattered yesterday, (2) what to watch in today's "
|
"Cover: (1) what mattered yesterday, (2) what to watch in today's "
|
||||||
"EU and US sessions, (3) one cross-asset thread connecting them. "
|
"EU and US sessions, (3) one cross-asset thread connecting them. "
|
||||||
"No predictions of price level, no buy/sell language. Target ~600 "
|
"No predictions of price level, no buy/sell language. Target ~600 "
|
||||||
"words. Output HTML using only <p>, <h3>, <ul>, <li>, <strong>, "
|
"words. Output HTML using only <p>, <h3>, <ul>, <li>, <strong>, "
|
||||||
"<em> — no <html>, <head>, or <body> wrapper, no inline styles."
|
"<em> — no <html>, <head>, or <body> wrapper, no inline styles."
|
||||||
)
|
)
|
||||||
user = _digest_user_prompt(today, quotes_by_group, headlines_by_bucket, reference_line)
|
user = _digest_user_prompt(
|
||||||
|
today=today, quotes_by_group=quotes_by_group,
|
||||||
|
headlines_by_bucket=headlines_by_bucket, reference_line=reference_line,
|
||||||
|
)
|
||||||
return system, user
|
return system, user
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -550,14 +554,9 @@ def build_weekly_digest_prompt(
|
||||||
"""System + user prompt for the Sunday weekly recap + look-ahead.
|
"""System + user prompt for the Sunday weekly recap + look-ahead.
|
||||||
|
|
||||||
Sent to ALL opt-in users (free and paid). Target ~900 words."""
|
Sent to ALL opt-in users (free and paid). Target ~900 words."""
|
||||||
tone_clause = (
|
|
||||||
"Use plain English. Define any jargon on first use."
|
|
||||||
if tone.upper() == "NOVICE"
|
|
||||||
else "Write for a reader who already speaks markets fluently."
|
|
||||||
)
|
|
||||||
system = (
|
system = (
|
||||||
"You write the Sunday weekly digest for Read the Markets. "
|
"You write the Sunday weekly digest for Read the Markets. "
|
||||||
f"Audience tone: {tone.upper()}. {tone_clause} "
|
f"Audience tone: {tone.upper()}. {_digest_tone_clause(tone)} "
|
||||||
"Cover: (1) the week behind — what moved and why, "
|
"Cover: (1) the week behind — what moved and why, "
|
||||||
"(2) the week ahead — releases, earnings, central-bank meetings, "
|
"(2) the week ahead — releases, earnings, central-bank meetings, "
|
||||||
"(3) the cross-asset story to keep in mind. "
|
"(3) the cross-asset story to keep in mind. "
|
||||||
|
|
@ -565,11 +564,20 @@ def build_weekly_digest_prompt(
|
||||||
"words. Output HTML using only <p>, <h3>, <ul>, <li>, <strong>, "
|
"words. Output HTML using only <p>, <h3>, <ul>, <li>, <strong>, "
|
||||||
"<em> — no <html>, <head>, or <body> wrapper, no inline styles."
|
"<em> — no <html>, <head>, or <body> wrapper, no inline styles."
|
||||||
)
|
)
|
||||||
user = _digest_user_prompt(today, quotes_by_group, headlines_by_bucket, reference_line)
|
user = _digest_user_prompt(
|
||||||
|
today=today, quotes_by_group=quotes_by_group,
|
||||||
|
headlines_by_bucket=headlines_by_bucket, reference_line=reference_line,
|
||||||
|
)
|
||||||
return system, user
|
return system, user
|
||||||
|
|
||||||
|
|
||||||
def _digest_user_prompt(today, quotes_by_group, headlines_by_bucket, reference_line):
|
def _digest_user_prompt(
|
||||||
|
*,
|
||||||
|
today,
|
||||||
|
quotes_by_group: dict,
|
||||||
|
headlines_by_bucket: dict,
|
||||||
|
reference_line: str,
|
||||||
|
) -> str:
|
||||||
"""Shared user-message body used by both digest prompts. Same data
|
"""Shared user-message body used by both digest prompts. Same data
|
||||||
shape as the hourly user prompt; reformatted for the digest context."""
|
shape as the hourly user prompt; reformatted for the digest context."""
|
||||||
today_str = today.strftime("%A %d %B %Y") if hasattr(today, "strftime") else str(today)
|
today_str = today.strftime("%A %d %B %Y") if hasattr(today, "strftime") else str(today)
|
||||||
|
|
|
||||||
|
|
@ -46,3 +46,19 @@ def test_prompts_return_strings():
|
||||||
sys_, usr = fn(tone="INTERMEDIATE", **_ctx())
|
sys_, usr = fn(tone="INTERMEDIATE", **_ctx())
|
||||||
assert isinstance(sys_, str) and isinstance(usr, str)
|
assert isinstance(sys_, str) and isinstance(usr, str)
|
||||||
assert len(sys_) > 50 and len(usr) > 50
|
assert len(sys_) > 50 and len(usr) > 50
|
||||||
|
|
||||||
|
|
||||||
|
def test_prompts_tolerate_empty_data():
|
||||||
|
"""No quotes, no headlines — builders must still produce non-empty
|
||||||
|
prompts without raising. Guards the `if headlines_by_bucket` and
|
||||||
|
`if quotes_by_group` branches in _digest_user_prompt."""
|
||||||
|
empty_ctx = dict(
|
||||||
|
today=datetime(2026, 5, 25, 6, 30, tzinfo=timezone.utc),
|
||||||
|
quotes_by_group={},
|
||||||
|
headlines_by_bucket={},
|
||||||
|
reference_line="S&P 7,501 (ATH)",
|
||||||
|
)
|
||||||
|
for fn in (build_daily_digest_prompt, build_weekly_digest_prompt):
|
||||||
|
sys_, usr = fn(tone="INTERMEDIATE", **empty_ctx)
|
||||||
|
assert "S&P 7,501" in usr
|
||||||
|
assert len(sys_) > 50
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue