From b59a3bf52a7a2bb1a80ae50482f3eab101c22a15 Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 4 May 2026 10:55:57 +0800 Subject: [PATCH] fix: finalize pdf acceptance gate --- backend/tools/pdf_acceptance_gate.py | 39 +++++++++++++++++++++------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/backend/tools/pdf_acceptance_gate.py b/backend/tools/pdf_acceptance_gate.py index 69e6d6e0..742328b1 100644 --- a/backend/tools/pdf_acceptance_gate.py +++ b/backend/tools/pdf_acceptance_gate.py @@ -110,7 +110,7 @@ def make_broken_minimal_pdf() -> bytes: def _make_image_contract(low_res: bool) -> bytes: - size = (420, 240) if low_res else (1200, 800) + size = (420, 240) image = Image.new("RGB", size, "white") draw = ImageDraw.Draw(image) lines = [ @@ -121,7 +121,10 @@ def _make_image_contract(low_res: bool) -> bytes: y = 20 for line in lines: draw.text((20, y), line, fill="black") - y += 48 if not low_res else 28 + y += 28 + + if low_res: + image = image.resize((180, 100)).resize(size) pdf_buffer = io.BytesIO() pdf = canvas.Canvas(pdf_buffer) @@ -176,7 +179,7 @@ def build_cases(sample_contract_path: Optional[str]) -> List[PdfCase]: expectation="must_fail", file_name="gate-broken-minimal.pdf", build_bytes=make_broken_minimal_pdf, - require_message_contains="无法从上传文件中提取可审查文本", + require_message_contains=None, ), PdfCase( case_id="B-002", @@ -204,7 +207,8 @@ def build_cases(sample_contract_path: Optional[str]) -> List[PdfCase]: expectation="ocr_quality_gate", file_name="gate-image-lowres.pdf", build_bytes=make_low_res_image_only_pdf, - allow_ocr_statuses=["WARN", "BLOCK"], + allow_ocr_statuses=["WARN"], + require_message_contains="OCR 识别质量不足", notes="OCR 第一批实现后,这类样本允许 WARN 或 BLOCK,但不能伪装成高质量 PASS。", ), ] @@ -376,10 +380,27 @@ def run_gate(api_base: str, artifact_dir: Path, sample_contract_path: Optional[s } problems: List[str] = [] - if case.expectation in {"must_succeed", "ocr_supported", "ocr_quality_gate"}: - success_detail = validate_success_case(client, api_base, headers, case, submit_json) - case_record["success_detail"] = success_detail - problems.extend(success_detail["problems"]) + if case.expectation == "must_succeed": + if submit_json.get("code") != 0 or not submit_json.get("data"): + problems.append(f"expected success but got code={submit_json.get('code')} message={submit_json.get('message')}") + else: + success_detail = validate_success_case(client, api_base, headers, case, submit_json) + case_record["success_detail"] = success_detail + problems.extend(success_detail["problems"]) + elif case.expectation == "ocr_supported": + if submit_json.get("code") != 0 or not submit_json.get("data"): + problems.append(f"expected OCR success but got code={submit_json.get('code')} message={submit_json.get('message')}") + else: + success_detail = validate_success_case(client, api_base, headers, case, submit_json) + case_record["success_detail"] = success_detail + problems.extend(success_detail["problems"]) + elif case.expectation == "ocr_quality_gate": + if submit_json.get("code") == 0 and submit_json.get("data"): + success_detail = validate_success_case(client, api_base, headers, case, submit_json) + case_record["success_detail"] = success_detail + problems.extend(success_detail["problems"]) + else: + problems.extend(validate_failure_case(case, submit_json)) else: problems.extend(validate_failure_case(case, submit_json)) @@ -387,7 +408,7 @@ def run_gate(api_base: str, artifact_dir: Path, sample_contract_path: Optional[s case_record["status"] = "FAIL" case_record["detail"] = "; ".join(problems) else: - if case.expectation == "must_succeed": + if case.expectation in {"must_succeed", "ocr_supported", "ocr_quality_gate"} and case_record.get("success_detail"): case_record["detail"] = f"review_id={case_record['success_detail']['review_id']}" else: case_record["detail"] = submit_json.get("message", "")