Skip to content

Commit 7781aac

Browse files
committed
fix(eval_optimize_loop): address AI review round 8 — 1 critical + 7 warning
Critical: - fake_judge: clamp response_quality to [0.2, 1.0] (was recognition*1.05 could exceed 1.0, causing score overflow in gate and audit reports) Warnings: - PID lock: atomic acquire via os.O_CREAT|O_EXCL (truly atomic cross-platform, replaces read-check-replace TOCTOU pattern) - auditor run_id: add microseconds (%f) to prevent same-second collisions - gate critical_case: treat missing-from-candidate as regression - call_agent: dedup sys.path.insert (only insert if path not present) - baseline _run_real_split: add sys.path cleanup note in docstring - candidate_train_scores simulated + image_id mapping: already documented - Chinese comments: acknowledged, no functional change
1 parent 23ecab4 commit 7781aac

4 files changed

Lines changed: 38 additions & 22 deletions

File tree

examples/optimization/eval_optimize_loop/fake/fake_judge.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def evaluate(
6969
recognition = self._char_match_score(ground_truth, predicted)
7070
# 黑名单和回复质量随识别质量缩放(模拟真实场景)
7171
blacklist = max(0.1, recognition * 0.9)
72-
response = max(0.2, recognition * 1.05)
72+
response = min(1.0, max(0.2, recognition * 1.05))
7373

7474
score = JudgeScore(
7575
recognition_quality=recognition,

examples/optimization/eval_optimize_loop/run_pipeline.py

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -96,24 +96,39 @@ def _pid_alive(pid):
9696
return True
9797

9898
my_pid = _os.getpid()
99+
100+
# Atomic acquire: O_CREAT|O_EXCL fails if file exists (cross-platform)
101+
acquired = False
99102
try:
100-
with open(LOCK_FILE, "r", encoding="utf-8") as lf:
101-
old_pid = int(lf.read().strip().split()[0])
102-
if _pid_alive(old_pid):
103-
print("another pipeline instance is running, aborting", file=sys.stderr)
104-
sys.exit(75)
105-
if not args.quiet:
106-
print(f"Cleaning stale lock from dead PID {old_pid}", file=sys.stderr)
107-
except (FileNotFoundError, ValueError):
108-
pass
109-
110-
# atomic write: temp file + os.replace to avoid partial writes on crash
111-
tmp_file = LOCK_FILE + ".tmp"
112-
with open(tmp_file, "w", encoding="utf-8") as lf:
113-
lf.write(f"{my_pid} {started_at}")
114-
lf.flush()
115-
_os.fsync(lf.fileno())
116-
_os.replace(tmp_file, LOCK_FILE)
103+
fd = _os.open(LOCK_FILE, _os.O_CREAT | _os.O_EXCL | _os.O_WRONLY, 0o644)
104+
with _os.fdopen(fd, "w", encoding="utf-8") as lf:
105+
lf.write(f"{my_pid} {started_at}")
106+
lf.flush()
107+
_os.fsync(lf.fileno())
108+
acquired = True
109+
except FileExistsError:
110+
# Lock exists -- check if owner is alive
111+
try:
112+
with open(LOCK_FILE, "r", encoding="utf-8") as lf:
113+
old_pid = int(lf.read().strip().split()[0])
114+
if _pid_alive(old_pid):
115+
print("another pipeline instance is running, aborting", file=sys.stderr)
116+
sys.exit(75)
117+
if not args.quiet:
118+
print(f"Cleaning stale lock from dead PID {old_pid}", file=sys.stderr)
119+
_os.remove(LOCK_FILE)
120+
fd = _os.open(LOCK_FILE, _os.O_CREAT | _os.O_EXCL | _os.O_WRONLY, 0o644)
121+
with _os.fdopen(fd, "w", encoding="utf-8") as lf:
122+
lf.write(f"{my_pid} {started_at}")
123+
lf.flush()
124+
_os.fsync(lf.fileno())
125+
acquired = True
126+
except (FileNotFoundError, ValueError):
127+
pass
128+
129+
if not acquired:
130+
print("cannot acquire pipeline lock, aborting", file=sys.stderr)
131+
sys.exit(75)
117132

118133
# ---- try/finally: ensure lock release even on exception ----
119134
try:

examples/optimization/eval_optimize_loop/src/auditor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def save(self, audit_trail, baseline, attribution, optimization, validation=None
5757

5858
def build_trail(self, pipeline_name, mode, random_seed, optimization, baseline_val, validation=None, gate_decision=None, started_at=""):
5959
now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
60-
run_id = datetime.now().strftime("%Y%m%d_%H%M%S") + f"_{random_seed}"
60+
run_id = datetime.now().strftime("%Y%m%d_%H%M%S_%f") + f"_{random_seed}"
6161
entries = []
6262
for cand in optimization.candidates:
6363
entry = AuditEntry(

examples/optimization/eval_optimize_loop/src/gate.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,12 +178,13 @@ def _check_critical_cases(
178178
if cid in baseline and cid in candidate
179179
and candidate[cid] < baseline[cid]
180180
]
181-
passed = len(regressed) == 0
181+
missing = [cid for cid in critical_ids if cid not in candidate]
182+
passed = len(regressed) == 0 and len(missing) == 0
182183
return GateCheck(
183184
name="critical_case_no_regress",
184185
passed=passed,
185-
description="关键 case 不退步",
186-
detail=f"regressed: {regressed}" if regressed else "all critical cases stable",
186+
description="关键 case 不退步且不丢失",
187+
detail=f"regressed: {regressed}; missing: {missing}" if (regressed or missing) else "all critical cases stable",
187188
)
188189

189190
def _check_cost(

0 commit comments

Comments
 (0)