fix: dedup three-bucket projection + honest C3 error-handling note
This commit is contained in:
@@ -9,11 +9,14 @@
|
||||
4. 逐行 store.upsert 落盘,单行单事务 → 崩溃最多丢正在写的一行。
|
||||
|
||||
错误处理诚实标注(不谎称全传播):
|
||||
- run_diagnosis 内部对 judge/C3 判别异常是 `except Exception`→warning→默认
|
||||
lapse(core/evolution/diagnose.py:2186-2192),非全传播;judge 语义歧义
|
||||
按现有保护性 lapse 处理,本编排原样接受其判定,不二次兜底。
|
||||
- 网络/API 层失败经 GovernedLLMClient 重试栈后仍失败会从 run_diagnosis
|
||||
向上抛出,本编排不捕获、不掩盖,直接冒泡给调用方。
|
||||
- run_diagnosis 的 C1/C2 阶段(指标计算、错误归因)网络/API 失败经
|
||||
GovernedLLMClient 重试栈后仍失败会向上抛出,本编排不捕获、不掩盖,
|
||||
直接冒泡给调用方。
|
||||
- 但 C3 阶段(defect/lapse judge)的调用整体包在 `except Exception` 内
|
||||
(core/evolution/diagnose.py:2186),故 C3 judge 的**全部异常(含网络/API
|
||||
失败)都被吞并→warning→默认归为 lapse**,不会向上抛;judge 语义歧义同样
|
||||
按此保护性 fallback 处理。本编排原样接受该判定,不二次兜底、也不谎称
|
||||
C3 阶段网络失败会传播。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -166,13 +169,69 @@ def _project_and_persist(
|
||||
{tier: 行数} 计数字典(T2/T1/T0/uncertain),供上层日志与 manifest。
|
||||
|
||||
关键实现:
|
||||
逐行 upsert(单行单事务),中途崩溃最多丢正在写的一行;三类产物互斥,
|
||||
同一 question_id 不会在两类中重复出现(run_diagnosis 保证)。
|
||||
逐行 upsert(单行单事务),中途崩溃最多丢正在写的一行。三桶**非互斥**:
|
||||
同一 degraded 错题可能同时出现在 error_attributions(judge 解析失败仍建
|
||||
attribution)里,故按 **degraded > infra > attribution** 优先级去重——先落
|
||||
degraded/infra,再在 attribution 循环跳过已落题,保证**每题恰写一行、
|
||||
counts 恰计一次**(否则同 PK 覆盖会导致 counts 双计且分层错乱)。
|
||||
"""
|
||||
counts = {"T2": 0, "T1": 0, "T0": 0, "uncertain": 0}
|
||||
# 优先级去重:degraded > infra > attribution。先记录高优先集合,
|
||||
# attribution 循环遇到已落题即跳过,确保每题唯一落库。
|
||||
persisted: set[str] = set()
|
||||
|
||||
# error_attributions:defect→T2 / lapse→T1 / 其它→uncertain(由 score_signal 判定)
|
||||
# degraded_question_ids(最高优先):judge 解析失败降级 → uncertain,信号不可信排除出 T2
|
||||
for qid in result.degraded_question_ids:
|
||||
q = questions[qid]
|
||||
store.upsert(
|
||||
DiagnosisSignalRow(
|
||||
question_id=qid,
|
||||
video_id=q.video_id,
|
||||
baseline_run_id=baseline_run_id,
|
||||
diag_fingerprint=diag_fingerprint,
|
||||
task_type=q.task_type,
|
||||
error_type=None,
|
||||
cause_category=None,
|
||||
tier="uncertain",
|
||||
evolution_target=None,
|
||||
degraded=True,
|
||||
infra=False,
|
||||
session_id=None,
|
||||
)
|
||||
)
|
||||
persisted.add(qid)
|
||||
counts["uncertain"] += 1
|
||||
|
||||
# infra_question_ids:基础设施失败护栏排除 → T0,不参与训练主体
|
||||
# (防御性跳过已落 degraded 题,虽 infra 通常已在诊断前过滤不重叠)
|
||||
for qid in result.infra_question_ids:
|
||||
if qid in persisted:
|
||||
continue
|
||||
q = questions[qid]
|
||||
store.upsert(
|
||||
DiagnosisSignalRow(
|
||||
question_id=qid,
|
||||
video_id=q.video_id,
|
||||
baseline_run_id=baseline_run_id,
|
||||
diag_fingerprint=diag_fingerprint,
|
||||
task_type=q.task_type,
|
||||
error_type=None,
|
||||
cause_category=None,
|
||||
tier="T0",
|
||||
evolution_target=None,
|
||||
degraded=False,
|
||||
infra=True,
|
||||
session_id=None,
|
||||
)
|
||||
)
|
||||
persisted.add(qid)
|
||||
counts["T0"] += 1
|
||||
|
||||
# error_attributions(最低优先):defect→T2 / lapse→T1 / 其它→uncertain(由 score_signal 判定)
|
||||
# 跳过已作为 degraded/infra 落库的题,避免同 PK 覆盖与 counts 双计。
|
||||
for ea in result.error_attributions:
|
||||
if ea.question_id in persisted:
|
||||
continue
|
||||
q = questions[ea.question_id]
|
||||
tier = score_signal(cause_category=ea.cause_category, infra=False, degraded=False).tier
|
||||
# error_type 是 ErrorAttribution 必填字段(永远已知),确定性派生进化目标。
|
||||
@@ -193,48 +252,7 @@ def _project_and_persist(
|
||||
session_id=None,
|
||||
)
|
||||
)
|
||||
persisted.add(ea.question_id)
|
||||
counts[tier] = counts.get(tier, 0) + 1
|
||||
|
||||
# infra_question_ids:基础设施失败护栏排除 → T0,不参与训练主体
|
||||
for qid in result.infra_question_ids:
|
||||
q = questions[qid]
|
||||
store.upsert(
|
||||
DiagnosisSignalRow(
|
||||
question_id=qid,
|
||||
video_id=q.video_id,
|
||||
baseline_run_id=baseline_run_id,
|
||||
diag_fingerprint=diag_fingerprint,
|
||||
task_type=q.task_type,
|
||||
error_type=None,
|
||||
cause_category=None,
|
||||
tier="T0",
|
||||
evolution_target=None,
|
||||
degraded=False,
|
||||
infra=True,
|
||||
session_id=None,
|
||||
)
|
||||
)
|
||||
counts["T0"] += 1
|
||||
|
||||
# degraded_question_ids:judge 解析失败降级 → uncertain,信号不可信排除出 T2
|
||||
for qid in result.degraded_question_ids:
|
||||
q = questions[qid]
|
||||
store.upsert(
|
||||
DiagnosisSignalRow(
|
||||
question_id=qid,
|
||||
video_id=q.video_id,
|
||||
baseline_run_id=baseline_run_id,
|
||||
diag_fingerprint=diag_fingerprint,
|
||||
task_type=q.task_type,
|
||||
error_type=None,
|
||||
cause_category=None,
|
||||
tier="uncertain",
|
||||
evolution_target=None,
|
||||
degraded=True,
|
||||
infra=False,
|
||||
session_id=None,
|
||||
)
|
||||
)
|
||||
counts["uncertain"] += 1
|
||||
|
||||
return counts
|
||||
|
||||
Reference in New Issue
Block a user