style: format distractor_selector

This commit is contained in:
2026-07-14 14:41:21 -04:00
parent 76f719018c
commit e64c26e578
+25 -13
View File
@@ -87,9 +87,7 @@ def _select_in_interval(
upper = correct_score - delta_low upper = correct_score - delta_low
lower = correct_score - delta_high lower = correct_score - delta_high
eligible = [ eligible = [
(c, s) (c, s) for c, s in zip(candidates, candidate_scores, strict=True) if lower <= s <= upper
for c, s in zip(candidates, candidate_scores, strict=True)
if lower <= s <= upper
] ]
if len(eligible) < 3: if len(eligible) < 3:
return None return None
@@ -134,12 +132,20 @@ def _parse_json_object(raw: str) -> dict:
async def _generate_pool( async def _generate_pool(
vlm: VLMProvider, question: str, correct_text: str, vlm: VLMProvider,
material: MaterialContext, n: int, *, session_id: str, question: str,
correct_text: str,
material: MaterialContext,
n: int,
*,
session_id: str,
) -> list[str]: ) -> list[str]:
"""VLM 生成 n 个候选干扰项文本。""" """VLM 生成 n 个候选干扰项文本。"""
system = _load_prompt("ar_distractor_pool.md") system = _load_prompt("ar_distractor_pool.md")
user = _material_context_block(question, correct_text, material) + f"\n## N\nGenerate exactly {n} distractors." user = (
_material_context_block(question, correct_text, material)
+ f"\n## N\nGenerate exactly {n} distractors."
)
messages = [{"role": "system", "content": system}, {"role": "user", "content": user}] messages = [{"role": "system", "content": system}, {"role": "user", "content": user}]
resp = await vlm.chat_with_images(messages, list(material.frame_paths), session_id=session_id) resp = await vlm.chat_with_images(messages, list(material.frame_paths), session_id=session_id)
# graceful 降级:解析爆炸时返回空池,让退火/hard_fail 接管(区别于契约违反的打分校验) # graceful 降级:解析爆炸时返回空池,让退火/hard_fail 接管(区别于契约违反的打分校验)
@@ -164,8 +170,12 @@ async def _generate_pool(
async def _score_options( async def _score_options(
vlm: VLMProvider, question: str, options: list[str], vlm: VLMProvider,
material: MaterialContext, *, session_id: str, question: str,
options: list[str],
material: MaterialContext,
*,
session_id: str,
) -> list[float]: ) -> list[float]:
"""VLM 对 options(首个为正解)逐一打视觉可信度分 [0,1],返回对齐分数列表。""" """VLM 对 options(首个为正解)逐一打视觉可信度分 [0,1],返回对齐分数列表。"""
system = _load_prompt("ar_distractor_score.md") system = _load_prompt("ar_distractor_score.md")
@@ -211,7 +221,9 @@ async def build_grounded_options(
vlm, question, correct_text, material, config.candidate_pool_size, session_id=session_id vlm, question, correct_text, material, config.candidate_pool_size, session_id=session_id
) )
# options[0] 恒为正解 # options[0] 恒为正解
scored = await _score_options(vlm, question, [correct_text, *candidates], material, session_id=session_id) scored = await _score_options(
vlm, question, [correct_text, *candidates], material, session_id=session_id
)
correct_score, cand_scores = scored[0], scored[1:] correct_score, cand_scores = scored[0], scored[1:]
anneal_rounds = 0 anneal_rounds = 0
@@ -250,9 +262,7 @@ async def build_grounded_options(
hard_fail = chosen is None hard_fail = chosen is None
observation: dict[str, object] = { observation: dict[str, object] = {
"correct_score": correct_score, "correct_score": correct_score,
"chosen": [ "chosen": [cand_scores[candidates.index(c)] for c in (chosen or [])],
cand_scores[candidates.index(c)] for c in (chosen or [])
],
"pool_size": len(candidates), "pool_size": len(candidates),
"anneal_rounds": anneal_rounds, "anneal_rounds": anneal_rounds,
"delta_high_final": delta_high, "delta_high_final": delta_high,
@@ -261,7 +271,9 @@ async def build_grounded_options(
if hard_fail: if hard_fail:
logger.warning( logger.warning(
"grounded selector 硬失败: correct={:.3f}, pool={}, anneal={}", "grounded selector 硬失败: correct={:.3f}, pool={}, anneal={}",
correct_score, len(candidates), anneal_rounds, correct_score,
len(candidates),
anneal_rounds,
) )
# observation 仍返回,供 pipeline 落 selector_scores(设计 §3.3 退化观测) # observation 仍返回,供 pipeline 落 selector_scores(设计 §3.3 退化观测)
return SelectorOutcome(observation=observation) return SelectorOutcome(observation=observation)