fix(intelligent-eval): parse minute-level time slots (1h windows)
All checks were successful
CI / test (push) Successful in 3m54s
All checks were successful
CI / test (push) Successful in 3m54s
planner 对短窗口(1h)产出分钟级时段(如 0-20min/20-40min/40-60min), 但 parse_time_slot 只支持小时级(8-10h),分钟格式解析失败返回 None → is_slot_due=False → 审批后评估永不入队、不触发 worker。 - parse_time_slot 支持 h/min 后缀,统一换算成小时(float)返回 - is_slot_due/get_current_slot/count_sessions_in_slot 用 timedelta(hours=float) 兼容两种格式;decision._parse_time_slot 类型标注同步 float 测试:+1(分钟格式时段解析与到期判断),898 passed
This commit is contained in:
parent
9d87ecf736
commit
60c54a67e4
@ -45,7 +45,7 @@ class Decision:
|
||||
}
|
||||
|
||||
|
||||
def _parse_time_slot(time_slot: str) -> Optional[tuple[int, int]]:
|
||||
def _parse_time_slot(time_slot: str) -> Optional[tuple[float, float]]:
|
||||
"""Thin wrapper delegating to :func:`agenteval.intelligent_eval.domain.parse_time_slot`."""
|
||||
from agenteval.intelligent_eval.domain import parse_time_slot as _impl
|
||||
return _impl(time_slot)
|
||||
|
||||
@ -21,13 +21,26 @@ from agenteval.storage.db import (
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def parse_time_slot(time_slot: str) -> Optional[tuple[int, int]]:
|
||||
"""Parse "8-10h" -> (8, 10). Returns None on bad format."""
|
||||
def parse_time_slot(time_slot: str) -> Optional[tuple[float, float]]:
|
||||
"""Parse a slot into (start_hours, end_hours), both in hours.
|
||||
|
||||
Supports hour-level ("8-10h" -> (8, 10)) and minute-level ("0-20min" ->
|
||||
(0, 1/3)) slots. planner 对短窗口(如 1h)会用分钟级时段,长窗口用
|
||||
小时级;统一换算成小时(float)供上层判断。Returns None on bad format.
|
||||
"""
|
||||
try:
|
||||
parts = time_slot.replace("h", "").split("-")
|
||||
raw = time_slot.strip().lower()
|
||||
factor = 1.0
|
||||
if raw.endswith("min"):
|
||||
raw = raw[:-3]
|
||||
factor = 1.0 / 60
|
||||
elif raw.endswith("h"):
|
||||
raw = raw[:-1]
|
||||
factor = 1.0
|
||||
parts = raw.split("-")
|
||||
if len(parts) != 2:
|
||||
return None
|
||||
return (int(parts[0]), int(parts[1]))
|
||||
return (int(parts[0]) * factor, int(parts[1]) * factor)
|
||||
except (ValueError, AttributeError):
|
||||
return None
|
||||
|
||||
|
||||
@ -2,9 +2,6 @@
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
import pytest
|
||||
from sqlmodel import Session, select
|
||||
|
||||
from agenteval.intelligent_eval import task_queue
|
||||
from agenteval.intelligent_eval.models import IntelligentEvalStatus
|
||||
from agenteval.storage.db import (
|
||||
@ -13,6 +10,7 @@ from agenteval.storage.db import (
|
||||
IntelligentEvalTaskQueueDB,
|
||||
utc_now,
|
||||
)
|
||||
from sqlmodel import Session, select
|
||||
|
||||
|
||||
def test_is_slot_due():
|
||||
@ -28,6 +26,25 @@ def test_is_slot_due():
|
||||
assert task_queue._is_slot_due({}, timedelta(hours=1)) is False
|
||||
|
||||
|
||||
def test_is_slot_due_minute_format():
|
||||
"""Minute-level slots (1h window: "0-20min") must be parsed and due on time."""
|
||||
from agenteval.intelligent_eval import domain
|
||||
|
||||
# 0-20min: due at 0min, not before
|
||||
assert task_queue._is_slot_due({"time_slot": "0-20min"}, timedelta(minutes=-1)) is False
|
||||
assert task_queue._is_slot_due({"time_slot": "0-20min"}, timedelta(minutes=0)) is True
|
||||
assert task_queue._is_slot_due({"time_slot": "0-20min"}, timedelta(minutes=5)) is True
|
||||
# 20-40min: not due before 20min, due at 20min
|
||||
assert task_queue._is_slot_due({"time_slot": "20-40min"}, timedelta(minutes=19)) is False
|
||||
assert task_queue._is_slot_due({"time_slot": "20-40min"}, timedelta(minutes=20)) is True
|
||||
|
||||
# parse both formats consistently (hours)
|
||||
assert domain.parse_time_slot("8-10h") == (8.0, 10.0)
|
||||
assert domain.parse_time_slot("0-20min") == (0.0, 1.0 / 3)
|
||||
assert domain.parse_time_slot("20-40min") == (1.0 / 3, 2.0 / 3)
|
||||
assert domain.parse_time_slot("bad") is None
|
||||
|
||||
|
||||
def test_calculate_session_deficit(db_session: Session):
|
||||
"""Test session deficit calculation."""
|
||||
# Create eval with plan
|
||||
|
||||
Loading…
Reference in New Issue
Block a user