feat: default two structured re-asks and sharper AIMD cut
Round 5 left three residual failure classes; ladder exhaustion (3.2% of structured calls with a single re-ask) and 429 leakage (5.8%, AIMD oscillating above the sustainable point) are addressable: re-ask default goes 1 to 2 (conservative vs instructor's 3) and the AIMD cut factor drops to 0.5.
This commit is contained in:
@@ -148,6 +148,13 @@ class TestResilienceKeys:
|
||||
|
||||
|
||||
class TestAssemblyGuards:
|
||||
def test_structured_retries_default_two(self):
|
||||
# M2.5 迭代 4: 缺省重问 1→2(instructor 缺省 3 的保守版;P6 阶梯死亡 3.2% 实证)
|
||||
s = GatewaySettings.from_env("LLM", env=_env())
|
||||
assert s.structured_max_retries == 2
|
||||
s2 = GatewaySettings.from_env("LLM", env=_env(PGW_STRUCTURED_MAX_RETRIES="0"))
|
||||
assert s2.structured_max_retries == 0
|
||||
|
||||
def test_cache_requires_namespace_and_ttl(self):
|
||||
env = _env(PGW_CACHE_BACKEND="memory")
|
||||
with pytest.raises(ValueError, match="NAMESPACE"):
|
||||
|
||||
@@ -101,7 +101,7 @@ class TestAdaptivePacer:
|
||||
|
||||
pacer = AdaptivePacer(ceiling=32.0)
|
||||
pacer.on_backpressure("s1")
|
||||
assert pacer.limit("s1") == pytest.approx(8.0 * 0.7)
|
||||
assert pacer.limit("s1") == pytest.approx(8.0 * 0.5)
|
||||
before = pacer.limit("s1")
|
||||
pacer.on_success("s1")
|
||||
assert pacer.limit("s1") == pytest.approx(before + 1.0 / before)
|
||||
|
||||
@@ -482,8 +482,8 @@ class TestAdaptivePacing:
|
||||
pacer=pacer,
|
||||
)
|
||||
await mw(_REQ)
|
||||
# 429 削减一次(8→5.6),随后成功加性增长(5.6 + 1/5.6)
|
||||
assert pacer.limit("a") == pytest.approx(8.0 * 0.7 + 1.0 / (8.0 * 0.7))
|
||||
# 429 削减一次(8→4),随后成功加性增长(4 + 1/4)
|
||||
assert pacer.limit("a") == pytest.approx(8.0 * 0.5 + 1.0 / (8.0 * 0.5))
|
||||
|
||||
async def test_inflight_returns_to_zero_after_call(self):
|
||||
from polygateway.sources import AdaptivePacer
|
||||
|
||||
Reference in New Issue
Block a user