mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 03:11:59 +00:00
收紧后的时长取到 0.1 秒、往下取:核查 agent 触顶时时间线写「时长上限 69.7 秒」,不写 69.7012 这样一串小数;往下取不会超出算好的余量,差一点不够的照样不开始
另把 segment、allot 的说明补全:deadline 为 None 时放的是 None(里面看不到外面的截止时刻),配置的是不限时按收尾宽限算最短时长。
This commit is contained in:
@@ -17,6 +17,7 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import contextlib
|
||||
import math
|
||||
from collections.abc import AsyncIterator
|
||||
from contextvars import ContextVar
|
||||
from dataclasses import dataclass
|
||||
@@ -42,7 +43,7 @@ _SEGMENT: ContextVar[Segment | None] = ContextVar("agentlab_segment", default=No
|
||||
@contextlib.asynccontextmanager
|
||||
async def segment(deadline: float | None, seconds: float) -> AsyncIterator[None]:
|
||||
"""runner 用:这一段执行的截止时刻(asyncio.Timeout.when())和总时长,退出时清掉。写成异步的上下文管理器,好和
|
||||
时长上限写在同一个 async with 里。deadline 为 None(没有上限)时什么都不放。"""
|
||||
时长上限写在同一个 async with 里。deadline 为 None(没有上限)时放 None:里面看不到外面的截止时刻。"""
|
||||
token = _SEGMENT.set(Segment(float(deadline), float(seconds)) if deadline is not None else None)
|
||||
try:
|
||||
yield
|
||||
@@ -81,13 +82,14 @@ def allot(timeout_s: float | None, *, grace: float) -> Allot:
|
||||
grace 是到点之后收尾那次调用的宽限(verify_agent.SETTLE_GRACE_S)。
|
||||
|
||||
一项最坏要用「时长上限 + 收尾宽限」。剩下的时间先扣掉给下游的余量、再扣掉收尾宽限,就是这一项查库最多能用的时长:
|
||||
比配置的短就收紧到它。收紧之后不到 min(配置的时长上限, 收尾宽限) 就不再开始:收尾宽限是留给一次模型调用的时间,
|
||||
查库的时长比它还短,连一轮都做不完,只会白花一次收尾的钱、记成没能核查。配置的时长上限本来就比它短的,按配置的
|
||||
整段算。没有上限时原样放行。"""
|
||||
比配置的短就收紧到它(取到 0.1 秒,往下取:时间线上写「时长上限 69.7 秒」,不写一串小数)。收紧之后不到
|
||||
min(配置的时长上限, 收尾宽限) 就不再开始:收尾宽限是留给一次模型调用的时间,查库的时长比它还短,连一轮都做不完,
|
||||
只会白花一次收尾的钱、记成没能核查。配置的时长上限本来就比它短的,按配置的整段算;配置的是不限的,按收尾宽限算。
|
||||
没有上限时原样放行。"""
|
||||
found = _SEGMENT.get()
|
||||
if found is None:
|
||||
return Allot(True, timeout_s)
|
||||
room = found.deadline - _now() - reserve(found.seconds) - grace
|
||||
room = math.floor((found.deadline - _now() - reserve(found.seconds) - grace) * 10) / 10
|
||||
limit = room if timeout_s is None else min(timeout_s, room)
|
||||
floor = grace if timeout_s is None else min(timeout_s, grace)
|
||||
if limit < floor:
|
||||
|
||||
@@ -76,6 +76,16 @@ async def test_a_configured_limit_shorter_than_the_grace_runs_whole_or_not_at_al
|
||||
assert deadline.allot(10, grace=30.0) == deadline.Allot(False, None, seconds=600)
|
||||
|
||||
|
||||
async def test_a_tightened_limit_is_cut_to_a_tenth_of_a_second(clock):
|
||||
"""收紧到的时长取到 0.1 秒、往下取:时间线上写「时长上限 69.7 秒」,不写 69.7012;往下取不会超出算好的余量。"""
|
||||
async with deadline.segment(clock.now + 159.7012, 600):
|
||||
assert deadline.allot(90, grace=30.0).timeout_s == 69.7
|
||||
async with deadline.segment(clock.now + 120.05, 600):
|
||||
assert deadline.allot(90, grace=30.0).timeout_s == 30.0
|
||||
async with deadline.segment(clock.now + 119.99, 600):
|
||||
assert not deadline.allot(90, grace=30.0).start, "差一点也是不够:往下取之后不到 30 秒"
|
||||
|
||||
|
||||
async def test_an_unlimited_item_is_bounded_by_the_deadline(clock):
|
||||
"""配置的是不限(None):有截止时刻时照样按剩余时间收紧,不然它能一直查到运行被中止。"""
|
||||
async with deadline.segment(clock.now + 400, 600):
|
||||
|
||||
Reference in New Issue
Block a user