fix: sshfs polling, WebSocket broadcast, prompt progress bar, resizable stats panel
- log_watcher: add --reopen-log mode (close/reopen each poll) for sshfs/network filesystems; fix nonlocal clients bug causing UnboundLocalError on first broadcast; fix list(clients) copy to prevent RuntimeError on concurrent set mutation - log_parser: capture progress=X.XX from prompt timing lines into Metrics.prompt_progress - frontend: show progress bar during processing_prompt state with PROMPT N% label; widen stats panel to 300px; remove model name truncation; add drag handle on right border of stats panel to resize between 280px–840px Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -37,10 +37,11 @@ class LoadingInfo:
|
||||
|
||||
@dataclass
|
||||
class Metrics:
|
||||
prompt_speed: Optional[float] = None # tokens/sec during prompt eval
|
||||
prompt_tokens: Optional[int] = None # total prompt tokens
|
||||
gen_speed: Optional[float] = None # tokens/sec during generation
|
||||
n_decoded: Optional[int] = None # tokens decoded so far
|
||||
prompt_speed: Optional[float] = None # tokens/sec during prompt eval
|
||||
prompt_tokens: Optional[int] = None # total prompt tokens
|
||||
prompt_progress: Optional[float] = None # 0.0–1.0 from live prompt timing lines
|
||||
gen_speed: Optional[float] = None # tokens/sec during generation
|
||||
n_decoded: Optional[int] = None # tokens decoded so far
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -72,7 +73,7 @@ _IDLE_RE = re.compile(r'update_slots: all slots are idle')
|
||||
_PROXY_RE = re.compile(r'proxy_reques: proxying request')
|
||||
_LAUNCH_RE = re.compile(r'slot launch_slot_:.*processing task')
|
||||
_PROMPT_TIMING_RE = re.compile(
|
||||
r'slot print_timing:.*prompt processing, n_tokens =\s+(\d+),.*/ ([\d.]+) tokens per second'
|
||||
r'slot print_timing:.*prompt processing, n_tokens =\s+(\d+), progress = ([\d.]+),.*/ ([\d.]+) tokens per second'
|
||||
)
|
||||
_GEN_TIMING_RE = re.compile(
|
||||
r'slot print_timing:.*n_decoded =\s+(\d+), tg =\s+([\d.]+) t/s'
|
||||
@@ -137,8 +138,9 @@ class LogParser:
|
||||
return self._set(state="processing_prompt")
|
||||
if m := _PROMPT_TIMING_RE.search(content):
|
||||
metrics = Metrics(
|
||||
prompt_speed=float(m.group(2)),
|
||||
prompt_speed=float(m.group(3)),
|
||||
prompt_tokens=int(m.group(1)),
|
||||
prompt_progress=float(m.group(2)),
|
||||
gen_speed=self._state.metrics.gen_speed,
|
||||
n_decoded=self._state.metrics.n_decoded,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user