news: DeepSeek validation, vs_forecast fix, /status source health
Validation (llm_news_eval.py harness + 78-headline golden CSV + verdict doc): headline scoring 78/78 vs keyword baseline 24/78 — validated; event gold-direction calls misread close K/M numeric comparisons ~11% of the time (both claims cases in sample, JOLTS 8.79M vs 8.84M). Fix: event payload now carries code-computed "vs_forecast" (from EconomicEvent.surprise) and the prompt gains an explicit inverted- metrics rule + worked claims example — iteration 1 (field alone) fixed the arithmetic but exposed a masked inversion error. 18/18 on live re-verification (4 misreads fixed, 11 regression cases clean, 3 fresh both-side probes). /status: new "News & AI" section — per-source health for the calendar chain (which of FF/MyFXBook served), each RSS feed, and DeepSeek (daily count, last error kind), written passively by the existing fetch paths under _cache_lock. Failures WARN once on transition (repeats DEBUG, recovery INFO) so the rotating log carries outage stories without 10-min spam. test_all.py: +5 Module 19 tests (351 total); also carries the Module 22 fixed-RR-TP tests from the prior research session (shared file). Replay artifacts dir gitignored like commit_ladder. Claude-Session: https://claude.ai/code/session_017mbXs9HRawZhD1uZ3ze7zQ
This commit is contained in:
+11
-1
@@ -24,7 +24,8 @@ import datetime as _dt
|
||||
import json
|
||||
import logging
|
||||
import threading
|
||||
from typing import Any, Dict, Optional
|
||||
import time
|
||||
from typing import Any, Dict, Optional, Tuple
|
||||
|
||||
import requests
|
||||
|
||||
@@ -66,6 +67,10 @@ class DeepSeekClient:
|
||||
self._count_day: Optional[_dt.date] = None
|
||||
self._count = 0
|
||||
self._warned: set = set()
|
||||
# Health stamps for status displays: last successful call and
|
||||
# last failure (ts, kind). Read-only for consumers.
|
||||
self.last_ok: float = 0.0
|
||||
self.last_error: Optional[Tuple[float, str]] = None
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
@@ -125,9 +130,11 @@ class DeepSeekClient:
|
||||
resp = self._session.post(
|
||||
DEEPSEEK_URL, json=body, timeout=self._timeout)
|
||||
except requests.RequestException as e:
|
||||
self.last_error = (time.time(), "network")
|
||||
self._warn_once("network", "DeepSeek call failed: %s", e)
|
||||
return None
|
||||
if resp.status_code != 200:
|
||||
self.last_error = (time.time(), f"http_{resp.status_code}")
|
||||
self._warn_once(
|
||||
f"http_{resp.status_code}",
|
||||
"DeepSeek HTTP %s: %s", resp.status_code, resp.text[:200])
|
||||
@@ -137,8 +144,11 @@ class DeepSeekClient:
|
||||
except ValueError:
|
||||
parsed = None
|
||||
if parsed is None:
|
||||
self.last_error = (time.time(), "parse")
|
||||
self._warn_once("parse", "DeepSeek response was not the "
|
||||
"expected JSON object — ignoring")
|
||||
else:
|
||||
self.last_ok = time.time()
|
||||
return parsed
|
||||
|
||||
@staticmethod
|
||||
|
||||
Reference in New Issue
Block a user