Download src/agentcade/progress.py from left0ver/WatcherRobot-com.left0ver.agentcade: direct link, hf CLI and curl.
- Browser
- Download file 2.8 kB
-
https://huggingface.co/spaces/left0ver/WatcherRobot-com.left0ver.agentcade/resolve/main/src/agentcade/progress.py
- Command line
-
hf download hf://spaces/left0ver/WatcherRobot-com.left0ver.agentcade/src/agentcade/progress.py
-
curl -L -o progress.py https://huggingface.co/spaces/left0ver/WatcherRobot-com.left0ver.agentcade/resolve/main/src/agentcade/progress.py
2.8 kB
| import asyncio | |
| import logging | |
| import math | |
| import time | |
| from collections.abc import Awaitable, Callable | |
| from contextlib import suppress | |
| from agentcade.expressions import segmented_progress_vector | |
| from observability import describe | |
| logger = logging.getLogger(__name__) | |
| class ProgressDisplay: | |
| def __init__(self, show: Callable[[str], Awaitable[None]], lock: asyncio.Lock): | |
| self.show = show | |
| self.lock = lock | |
| self.task: asyncio.Task | None = None | |
| self.token = 0 | |
| self.active = False | |
| self.step = 0 | |
| async def frame(self, token: int, step: int) -> None: | |
| async with self.lock: | |
| if self.active and token == self.token: | |
| await self.show(segmented_progress_vector(step)) | |
| self.step = step | |
| async def start(self) -> int: | |
| await self.cancel() | |
| self.active = True | |
| self.step = 0 | |
| await self.frame(self.token, 0) | |
| return self.token | |
| def advance(self, token: int, seconds: float) -> None: | |
| if not math.isfinite(seconds) or seconds <= 0: | |
| raise ValueError("预计生成时间必须是有限正数") | |
| if not self.active or token != self.token: | |
| return | |
| if self.task is not None: | |
| raise RuntimeError("当前进度任务已经开始计时") | |
| self.task = asyncio.create_task(self.animate(token, seconds)) | |
| async def animate(self, token: int, seconds: float) -> None: | |
| started = time.monotonic() | |
| while self.active and token == self.token and self.step < 9: | |
| deadline = started + (self.step + 1) * seconds / 10 | |
| await asyncio.sleep(max(0, deadline - time.monotonic())) | |
| step = min(9, int((time.monotonic() - started) * 10 / seconds)) | |
| await self.frame(token, step) | |
| async def stop_timer(self) -> None: | |
| task, self.task = self.task, None | |
| if task is not None: | |
| task.cancel() | |
| try: | |
| with suppress(asyncio.CancelledError): | |
| await task | |
| except Exception as error: | |
| # 进度画面只是提示,显示失败不影响后面的输出。 | |
| logger.warning("进度显示失败:%s", describe(error), exc_info=True) | |
| async def finish(self) -> None: | |
| await self.stop_timer() | |
| if self.active: | |
| await self.frame(self.token, 10) | |
| self.active = False | |
| self.token += 1 | |
| await asyncio.sleep(0.25) | |
| async def cancel(self) -> None: | |
| self.active = False | |
| self.token += 1 | |
| await self.stop_timer() | |
| async with self.lock: | |
| pass | |
| async def check(self) -> None: | |
| if self.task is not None and self.task.done(): | |
| await self.stop_timer() | |