결론
오늘 06:45 자동 발화(msg_id 2375)가 “내용 이상”으로 보인 원인은 3개였다.
- 시장지표 0개로 LLM이 작성:
market-indicators최신 파일 선택 로직이industry_news_latest.json을 주 데이터로 골라indicators_count=0이 됨. - 작은 모델 fallback 출력이 그대로 발송:
gpt-5.4호출은 401/실패 후github-copilot/gpt-4o-mini로 폴백했고, 이 출력이 시장 데이터 없이 문장을 만들어냄. - Telegram HTML 본문에 Markdown/메타가 노출: 실제 06:45 preview에
/ LLM,#,##가 그대로 들어감.
수정 후 08:19에 report 토픽으로 재발송 성공: message_id 2387.
06:45 실제 발화 근거
~/.hermes/logs/morning-briefing-telegram.log는 전문이 아니라 preview만 저장한다. 확인 가능한 실제 발송 로그는 아래와 같다.
[briefing_wrapper] kind=morning chars=644 meta={"morning_briefing_ok": true, "stderr_signal": ""}
[SECTOR_TRACE] send_sector(report) caller=telegram_briefing_wrapper.py text='<b>🌅 아침 투자 브리핑</b>\n<i>2026-04-16 06:45 KST / LLM</i>\n\n# 🌅 아침 투자 브리핑 — 2026-04-16'
[briefing_wrapper] send_result={"ok": true, "message_ids": [2375], "error": null, "chat_id": -1003522748967, "topic_id": 8, "transport": "telegram_api"}
동시간대 morning_briefing.log:
[2026-04-16 06:45:00] 수집 완료: {"indicators_count": 0, "anomalies_count": 0, "hypotheses_count": 6, "experiments_count": 1, "ideas_count": 20, "sector_news_count": 0}
[2026-04-16 06:45:00] LLM 호출: 모델체인=['openai-codex/gpt-5.4', 'github-copilot/gpt-4o-mini'], 프롬프트 2141자
[2026-04-16 06:45:05] 브리핑 생성 완료: 585자 (모델: github-copilot/gpt-4o-mini)
동시간대 gateway 로그에는 gpt-5.4 경로의 토큰 refresh 401이 있었고, LLM jsonl에는 github-copilot/gpt-4o-mini가 응답한 preview만 남아 있었다. 따라서 전문은 로컬 로그에 보존되어 있지 않지만, 발송 preview와 생성 로그만으로도 “데이터 없이 작은 모델이 쓴 본문 + Markdown 노출”은 재현된다.
수정 내역
1) morning_briefing.py
market-indicatorsfallback이 보조 파일(industry_news_latest.json)을 고르지 않도록 수정.- 날짜형 주 파일(
YYYY-MM-DD.json)을 우선 선택하도록 수정. - 시장 데이터 기준일을 본문에 명시하도록 추가.
- 채권 브리핑(
memory/bond-briefing/latest.json)을 수집/요약에 포함. github-copilot/gpt-4o-mini등 작은 fallback 모델 출력은 해리 발송용으로 쓰지 않고 deterministic compact 한국어 본문으로 전환하는 품질 게이트 추가.- 유동성 라인을 한 줄 판단형으로 축약.
- 이상치 라벨에서 영문 ticker가 제거되어 의미가 사라지는 문제 보정.
2) telegram_briefing_wrapper.py
/ LLM,source=...같은 메타정보를 본문에서 제거.- Markdown
#,##,**숫자**를 Telegram HTML로 변환. - 섹션 이모지/제목 형식 적용.
- 오류가 있어도
<pre>traceback 블록을 사용자 본문에 노출하지 않도록 변경.
검증
dry-run
명령:
python3 -m py_compile ~/.hermes/workspace/scripts/pipeline/morning_briefing.py ~/.hermes/workspace/scripts/pipeline/telegram_briefing_wrapper.py
python3 ~/.hermes/workspace/scripts/pipeline/telegram_briefing_wrapper.py --kind morning --dry-run
결과:
- 구문 검사: 통과
indicators_count: 0 → 87anomalies_count: 0 → 32market_data_date: 2026-04-15 명시bond_data_date: 2026-04-15 포함<pre>없음/ LLM없음source=...없음- literal
#,##없음 - 작은 모델 출력은 품질 게이트로 차단됨
최종 dry-run 본문 샘플:
<b>🌅 아침 투자 브리핑</b>
<i>2026-04-16 08:19 KST</i>
<b>🧭 오늘 한 줄</b>
• 유가 하락과 금 강세가 동시에 보이는 만큼, 성장주 반등보다 매크로 위험 신호를 먼저 확인해야 합니다.
<b>🌡️ 시장 온도</b>
• 시장 지표는 <b>2026-04-15 수집/전일 종가 기준</b>입니다.
• 미국 대형주 <b>6951.24</b> (+0.9%)
• 나스닥 <b>23558.09</b> (+1.6%)
• 변동성지수 <b>18.46</b> (-3.5%)
• 미국 10년금리 <b>4.26</b> (-0.9%)
• 달러지수 <b>98.14</b> (-0.2%)
• 원달러 <b>1471.88</b> (-0.7%)
• 서부텍사스유 <b>91.87</b> (-7.3%)
• 금 <b>4857.9</b> (+2.4%)
live 재발송
명령:
python3 ~/.hermes/workspace/scripts/pipeline/telegram_briefing_wrapper.py --kind morning
결과:
{"ok": true, "message_ids": [2387], "error": null, "chat_id": -1003522748967, "topic_id": 8, "transport": "telegram_api"}
sector_trace.log 확인:
2026-04-16 08:19:56 [SECTOR_TRACE] send_sector(report) caller=telegram_briefing_wrapper.py text='<b>🌅 아침 투자 브리핑</b>\n<i>2026-04-16 08:19 KST</i>\n\n<b>🧭 오늘 한 줄</b>\n• 유가 하락과 금 강세가 동'
남은 리스크
- 오늘 시장 데이터 자체가
2026-04-15 수집/전일 종가 기준이라 아침 06:45 기준 최신 장중 데이터는 아니다. 본문에 기준일을 명시하게 했으나, 데이터 수집 cron freshness는 별도 감시가 필요하다. gpt-5.4경로는 06:45에 gateway token refresh 401이 발생했다. 이번 수정은 작은 모델 출력 차단으로 품질을 방어했지만, 원 provider 인증 문제는 별도 복구 대상이다.- Telegram API는 과거 message_id 본문 전문 조회를 제공하지 않아 2375 전문은 로컬에 남은 preview/LLM preview 기반으로만 검증했다.
자체평가
- 정확성: 4.6/5 — 원인 3개를 로그로 확인하고 실제 재발송까지 완료.
- 완성도: 4.5/5 — 본문 오염/데이터 선택/작은 모델 품질 문제를 모두 막음.
- 검증: 4.7/5 — py_compile, dry-run, live Telegram send 모두 확인.
- 최소 변경: 4.5/5 — TTS 루틴과 plist는 건드리지 않고 브리핑 생성/렌더러만 수정.
종합: 4.6/5