@@ -139,6 +139,76 @@ def parse_research_verdict(output: str, candidate_id: str) -> dict:
139139 }
140140
141141
142+ class StrategyPrefillHeartbeat :
143+ def __init__ (
144+ self ,
145+ dashboard : str = "http://127.0.0.1:8090" ,
146+ interval_s : float = 10.0 ,
147+ ) -> None :
148+ self .dashboard = dashboard .rstrip ("/" )
149+ self .interval_s = interval_s
150+ self ._stop = threading .Event ()
151+ self ._thread : threading .Thread | None = None
152+ self ._baseline : dict = {}
153+ self ._last : tuple | None = None
154+
155+ def __enter__ (self ):
156+ try :
157+ self ._baseline = _json_request (
158+ f"{ self .dashboard } /v1/network/summary" ,
159+ ).get ("prefill" , {})
160+ except Exception as exc :
161+ print (
162+ "[autoresearch] Strategy Prefill telemetry warning: "
163+ f"{ type (exc ).__name__ } : { exc } " ,
164+ flush = True ,
165+ )
166+ self ._thread = threading .Thread (target = self ._run , daemon = True )
167+ self ._thread .start ()
168+ return self
169+
170+ def __exit__ (self , * _exc ) -> None :
171+ self ._stop .set ()
172+ if self ._thread is not None :
173+ self ._thread .join (timeout = self .interval_s + 2 )
174+ self ._emit ()
175+
176+ def _run (self ) -> None :
177+ while not self ._stop .wait (self .interval_s ):
178+ self ._emit ()
179+
180+ def _delta (self , current : dict , name : str ) -> int :
181+ return max (
182+ 0 ,
183+ int (current .get (name , 0 )) - int (self ._baseline .get (name , 0 )),
184+ )
185+
186+ def _emit (self ) -> None :
187+ try :
188+ current = _json_request (
189+ f"{ self .dashboard } /v1/network/summary" ,
190+ ).get ("prefill" , {})
191+ except Exception :
192+ return
193+ total = self ._delta (current , "remote_job_tokens_total" )
194+ computed = self ._delta (current , "remote_job_tokens_computed" )
195+ state = (
196+ computed ,
197+ total ,
198+ self ._delta (current , "remote_hits" ),
199+ self ._delta (current , "tokens_reused" ),
200+ )
201+ if not total or state == self ._last :
202+ return
203+ self ._last = state
204+ percent = min (100.0 , 100.0 * computed / total )
205+ print (
206+ f"[autoresearch] Strategy Prefill: { computed } /{ total } tokens "
207+ f"({ percent :.1f} %) · remote_hits={ state [2 ]} reused={ state [3 ]} " ,
208+ flush = True ,
209+ )
210+
211+
142212def propose_candidate (
143213 * ,
144214 address : str ,
@@ -175,15 +245,29 @@ def propose_candidate(
175245 enable_thinking = False ,
176246 )
177247 generated : list [int ] = []
248+ print (
249+ f"[autoresearch] Strategy Prefill: 0/{ len (ids )} tokens (0.0%)" ,
250+ flush = True ,
251+ )
178252 with Client (address ) as client :
179253 with client .create_session (
180254 eos_token_ids = _resolve_eos_token_ids (tokenizer ),
181255 client_label = "autoresearch-strategy" ,
182256 ) as session :
183- session .append (ids )
257+ with StrategyPrefillHeartbeat ():
258+ session .append (ids )
259+ print (
260+ f"[autoresearch] Strategy Prefill complete: { len (ids )} tokens" ,
261+ flush = True ,
262+ )
184263 while len (generated ) < 2048 :
185264 before = len (generated )
186265 generated .extend (int (token ) for token in session .generate (max_tokens = 64 ))
266+ print (
267+ f"[autoresearch] Strategy Decode: { len (generated )} tokens "
268+ f"stop_reason={ session .last_stop_reason } " ,
269+ flush = True ,
270+ )
187271 if session .last_stop_reason != 1 :
188272 break
189273 if len (generated ) == before :
0 commit comments