fix: make the sampling invariant test actually enforce the constraint
The test passed overlay and sampling as separate objects while production aliases them, so an in-place mutation slipped through it. Also syncs the telemetry schema page and adds the missing postgres round-trip assertion.
This commit is contained in:
@@ -11,6 +11,7 @@ DSN 走 .env `PGW_TELEMETRY_PG_DSN`,缺则 skip。该实例上有 app/chs_prod
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
from uuid import uuid4
|
||||
|
||||
@@ -180,9 +181,12 @@ class TestObservabilityColumns:
|
||||
await _record_minimal(recorder, call_id=_cid("hit"), cached_prompt_tokens=64)
|
||||
await _record_minimal(recorder, call_id=_cid("zero"), cached_prompt_tokens=0)
|
||||
await _record_minimal(recorder, call_id=_cid("model"), model_reported="MiniMax-01")
|
||||
await _record_minimal(
|
||||
recorder, call_id=_cid("samp"), sampling='{"seed": 42, "temperature": 0}'
|
||||
)
|
||||
rows = await _fetch(
|
||||
dsn,
|
||||
"SELECT call_id, cached_prompt_tokens, model_reported FROM llm_calls "
|
||||
"SELECT call_id, cached_prompt_tokens, model_reported, sampling FROM llm_calls "
|
||||
"WHERE call_id LIKE $1",
|
||||
f"{_RUN_PREFIX}-%",
|
||||
)
|
||||
@@ -191,6 +195,9 @@ class TestObservabilityColumns:
|
||||
assert by_id[_cid("zero")]["cached_prompt_tokens"] == 0 # 真实零命中 ≠ NULL
|
||||
assert by_id[_cid("model")]["cached_prompt_tokens"] is None
|
||||
assert by_id[_cid("model")]["model_reported"] == "MiniMax-01"
|
||||
# issue #4: PG 侧也须验非空 sampling 能读回原值(不只是列存在)
|
||||
assert json.loads(by_id[_cid("samp")]["sampling"]) == {"seed": 42, "temperature": 0}
|
||||
assert by_id[_cid("hit")]["sampling"] is None
|
||||
finally:
|
||||
await recorder.aclose()
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ class _DummyRecorder:
|
||||
cost,
|
||||
cached_prompt_tokens,
|
||||
model_reported,
|
||||
sampling,
|
||||
) -> None: ...
|
||||
|
||||
|
||||
|
||||
@@ -193,7 +193,14 @@ class TestSamplingSnapshotInvariant:
|
||||
terminal = ScriptedTerminal(["not json at all", '{"answer": 1, "reason": "r"}'])
|
||||
mw = _mw(strategy=NativeSchemaStrategy(), max_retries=1)
|
||||
await mw(
|
||||
ChatRequest(messages=_MSGS, structured=Verdict, sampling=caller_sampling),
|
||||
# overlay 与 sampling 传**同一个对象**,复现 client.py 的别名关系
|
||||
# ——否则中间件就地改写 overlay 时不会波及 sampling,这条执法就是空的
|
||||
ChatRequest(
|
||||
messages=_MSGS,
|
||||
structured=Verdict,
|
||||
overlay=caller_sampling,
|
||||
sampling=caller_sampling,
|
||||
),
|
||||
terminal,
|
||||
)
|
||||
assert len(terminal.requests) == 2 # 确实重问过
|
||||
@@ -205,11 +212,20 @@ class TestSamplingSnapshotInvariant:
|
||||
assert "response_format" not in seen.sampling
|
||||
|
||||
async def test_middleware_does_not_mutate_caller_mapping(self):
|
||||
"""决策 E 的第二条约束: 中间件只能 replace 派生,不得就地改这两个 dict。"""
|
||||
"""决策 E 的第二条约束: 中间件只能 replace 派生,不得就地改这两个 dict。
|
||||
|
||||
同样传同一对象: 生产中 overlay 与 sampling 是别名,任何对 overlay 的
|
||||
就地改写都会同步毒化缓存 key 与遥测列。
|
||||
"""
|
||||
caller_sampling = {"seed": 7}
|
||||
terminal = ScriptedTerminal(['{"answer": 1, "reason": "r"}'])
|
||||
await _mw(strategy=NativeSchemaStrategy())(
|
||||
ChatRequest(messages=_MSGS, structured=Verdict, sampling=caller_sampling),
|
||||
ChatRequest(
|
||||
messages=_MSGS,
|
||||
structured=Verdict,
|
||||
overlay=caller_sampling,
|
||||
sampling=caller_sampling,
|
||||
),
|
||||
terminal,
|
||||
)
|
||||
assert caller_sampling == {"seed": 7} # 调用方的对象未被污染
|
||||
|
||||
Reference in New Issue
Block a user