test: cover backfill params end-to-end (mutation isolation + seq_offset)

This commit is contained in:
2026-07-14 15:44:43 -04:00
parent 8b9e8aa19f
commit ac115d96fb
+84
View File
@@ -580,6 +580,90 @@ class TestPipelineV2:
if result.accepted: if result.accepted:
assert len(result.heavy_sampled) == len(result.accepted) assert len(result.heavy_sampled) == len(result.accepted)
@pytest.mark.asyncio
async def test_backfill_params_do_not_mutate_caller_objects(
self, tree, default_config, store, tmp_path
):
"""补生成三参:传入的 used_node_ids / embed_pool 对象不被就地修改。
内部应复制而非别名 —— run 完之后调用方传入的容器长度/内容保持原样。
"""
vlm = MockVLM([_make_candidate_json(f"Q{i}?") for i in range(20)])
llm = MockLLM([_make_gate_pass_response()] * 100)
config = PipelineConfig(
per_type=2,
retry_limit=2,
heavy_sample_rate=0.0,
dedup_threshold=0.85,
concurrency=1,
seed=42,
output_dir=tmp_path / "out",
)
initial_used_node_ids = {"some_node"}
seed_vec = _mock_embed_fn("seed embedding text")
initial_embed_pool = [seed_vec]
result = await run_pipeline_v2(
video_ids=["vid_L1_000"],
trees={"vid_L1_000": tree},
vlm=vlm,
llm=llm,
embed_fn=_mock_embed_fn,
store=store,
config=config,
task_types=["Action Recognition"],
initial_used_node_ids=initial_used_node_ids,
initial_embed_pool=initial_embed_pool,
)
# 至少接受一题,确保内部确实往副本里追加了 node/embedding
assert len(result.accepted) > 0
# 调用方对象未被 mutation:集合仍只含原始节点
assert initial_used_node_ids == {"some_node"}
# embed_pool 仍只含最初的一个向量,且内容未变
assert len(initial_embed_pool) == 1
assert np.array_equal(initial_embed_pool[0], seed_vec)
@pytest.mark.asyncio
async def test_seq_offset_continues_question_ids(
self, tree, default_config, store, tmp_path
):
"""补生成三参:seq_offset 端到端续编 question_id 的 seq,避开旧 run 号段。"""
vlm = MockVLM([_make_candidate_json(f"Q{i}?") for i in range(20)])
llm = MockLLM([_make_gate_pass_response()] * 100)
config = PipelineConfig(
per_type=2,
retry_limit=2,
heavy_sample_rate=0.0,
dedup_threshold=0.85,
concurrency=1,
seed=42,
output_dir=tmp_path / "out",
)
result = await run_pipeline_v2(
video_ids=["vid_L1_000"],
trees={"vid_L1_000": tree},
vlm=vlm,
llm=llm,
embed_fn=_mock_embed_fn,
store=store,
config=config,
task_types=["Action Recognition"],
seq_offset=30,
)
assert len(result.accepted) > 0
# question_id 格式 "{video_id}_{task_type}_{seq:04d}"seq 是最后一段 4 位数字
seqs = [int(q.question_id.rsplit("_", 1)[1]) for q in result.accepted]
assert all(s > 30 for s in seqs), seqs
# per_type=2 → seq 从 31 起续编,不与 0-30 撞
assert min(seqs) == 31
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_store_records_all(self, tree, default_config, store, tmp_path): async def test_store_records_all(self, tree, default_config, store, tmp_path):
"""验证 store 中记录了每道题的生成与门控结果。""" """验证 store 中记录了每道题的生成与门控结果。"""