From ff1cc85f0a82f3704434abd48bbe72186f6646ae Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 4 May 2026 18:53:24 +0800 Subject: [PATCH] feat: externalize structured review samples --- .../test_review_structured_acceptance_gate.py | 46 +++++ .../review_structured_acceptance_gate.py | 96 +++++++++ ...续能力扩展阶段1第七批执行记录-2026-05-04.md | 152 ++++++++++++++ .../structured-review-samples/README.md | 47 +++++ .../structured-review-samples/manifest.json | 193 ++++++++++++++++++ .../samples/structured-carveout.txt | 14 ++ .../samples/structured-development.txt | 9 + .../samples/structured-entrustment.txt | 13 ++ .../samples/structured-implementation.txt | 17 ++ .../samples/structured-lease.txt | 10 + .../samples/structured-license.txt | 11 + .../samples/structured-procurement.txt | 6 + .../samples/structured-sales.txt | 9 + .../samples/structured-service.txt | 8 + .../samples/structured-weak-acceptance.txt | 8 + .../结构化字段与关系准确率基线-2026-05-04.md | 17 +- 16 files changed, 653 insertions(+), 3 deletions(-) create mode 100644 project-docs/OCR后续能力扩展阶段1第七批执行记录-2026-05-04.md create mode 100644 project-docs/structured-review-samples/README.md create mode 100644 project-docs/structured-review-samples/manifest.json create mode 100644 project-docs/structured-review-samples/samples/structured-carveout.txt create mode 100644 project-docs/structured-review-samples/samples/structured-development.txt create mode 100644 project-docs/structured-review-samples/samples/structured-entrustment.txt create mode 100644 project-docs/structured-review-samples/samples/structured-implementation.txt create mode 100644 project-docs/structured-review-samples/samples/structured-lease.txt create mode 100644 project-docs/structured-review-samples/samples/structured-license.txt create mode 100644 project-docs/structured-review-samples/samples/structured-procurement.txt create mode 100644 project-docs/structured-review-samples/samples/structured-sales.txt create mode 100644 project-docs/structured-review-samples/samples/structured-service.txt create mode 100644 project-docs/structured-review-samples/samples/structured-weak-acceptance.txt diff --git a/backend/tests/test_review_structured_acceptance_gate.py b/backend/tests/test_review_structured_acceptance_gate.py index a7a5fa10..faaa9b76 100644 --- a/backend/tests/test_review_structured_acceptance_gate.py +++ b/backend/tests/test_review_structured_acceptance_gate.py @@ -2,7 +2,11 @@ import unittest from tools.review_structured_acceptance_gate import ( build_field_baseline, + build_field_baseline_by_contract, build_relationship_baseline, + build_relationship_baseline_by_type, + load_cases_from_manifest, + SAMPLE_MANIFEST_PATH, ) @@ -61,6 +65,48 @@ class ReviewStructuredAcceptanceGateMetricsTestCase(unittest.TestCase): self.assertEqual(metrics["relationship_absence"]["passed"], 2) self.assertEqual(metrics["relationship_confidence"]["passed"], 1) + def test_load_cases_from_manifest_reads_external_sample_files(self): + cases = load_cases_from_manifest(SAMPLE_MANIFEST_PATH) + + self.assertGreaterEqual(len(cases), 10) + self.assertTrue(any(case.case_id == "S-010" for case in cases)) + self.assertTrue(any("甲方" in case.content for case in cases)) + + def test_grouped_baselines_split_by_contract_and_relationship_type(self): + summary = { + "cases": [ + { + "case_id": "S-006", + "status": "PASS", + "result": { + "clauses": [{"clause_type": "payment"}, {"clause_type": "acceptance"}], + "contract_structure": { + "detected_contract_type": "service", + "amount": "人民币1500000元", + "term_details": {"start_date": "2026-08-01", "end_date": "2027-08-01"}, + "payment_milestones": [{}, {}, {}, {}], + "liability_carve_outs": [], + "intellectual_property_owner": "party_a", + "clause_relationships": [ + {"type": "payment_depends_on_acceptance", "confidence_tier": "high"}, + ], + }, + }, + } + ] + } + + field_rows = build_field_baseline_by_contract(summary) + relationship_rows = build_relationship_baseline_by_type(summary) + + field_metrics = {row["contract_family"]: row for row in field_rows} + relationship_metrics = {row["relationship_type"]: row for row in relationship_rows} + + self.assertEqual(field_metrics["service"]["contract_type_accuracy"], 100.0) + self.assertEqual(field_metrics["service"]["payment_milestone_accuracy"], 100.0) + self.assertEqual(relationship_metrics["payment_depends_on_acceptance"]["presence_accuracy"], 100.0) + self.assertEqual(relationship_metrics["payment_depends_on_acceptance"]["confidence_accuracy"], 100.0) + if __name__ == "__main__": unittest.main() diff --git a/backend/tools/review_structured_acceptance_gate.py b/backend/tools/review_structured_acceptance_gate.py index dda85ebf..7c6d33fa 100644 --- a/backend/tools/review_structured_acceptance_gate.py +++ b/backend/tools/review_structured_acceptance_gate.py @@ -344,6 +344,22 @@ CASES = [ ), ] +SAMPLE_MANIFEST_PATH = Path(__file__).resolve().parents[2] / "project-docs" / "structured-review-samples" / "manifest.json" + + +def load_cases_from_manifest(manifest_path: Path) -> List[StructuredReviewCase]: + payload = json.loads(manifest_path.read_text(encoding="utf-8")) + manifest_dir = manifest_path.parent + cases: List[StructuredReviewCase] = [] + for entry in payload.get("samples", []): + content_file = entry.pop("content_file") + content = (manifest_dir / content_file).read_text(encoding="utf-8") + cases.append(StructuredReviewCase(content=content, **entry)) + return cases + + +CASES = load_cases_from_manifest(SAMPLE_MANIFEST_PATH) + def register_and_login(client: httpx.Client, api_base: str, password: str) -> Dict[str, str]: seed = int(time.time() * 1000) @@ -605,6 +621,78 @@ def build_relationship_baseline(summary: Dict) -> List[Dict[str, object]]: return rows +def build_field_baseline_by_contract(summary: Dict) -> List[Dict[str, object]]: + rows: List[Dict[str, object]] = [] + grouped: Dict[str, Dict[str, int]] = {} + for item in summary["cases"]: + result = item.get("result") or {} + contract_structure = result.get("contract_structure") or {} + case = next(case for case in CASES if case.case_id == item["case_id"]) + family = case.expected_contract_type + bucket = grouped.setdefault(family, {"contract_type_pass": 0, "contract_type_total": 0, "payment_pass": 0, "payment_total": 0, "relationship_pass": 0, "relationship_total": 0}) + bucket["contract_type_total"] += 1 + if contract_structure.get("detected_contract_type") == case.expected_contract_type: + bucket["contract_type_pass"] += 1 + if case.expected_payment_milestones: + bucket["payment_total"] += 1 + if len(contract_structure.get("payment_milestones") or []) >= case.expected_payment_milestones: + bucket["payment_pass"] += 1 + if case.expected_relationship_types: + bucket["relationship_total"] += len(case.expected_relationship_types) + relationship_types = {entry.get("type") for entry in contract_structure.get("clause_relationships") or [] if entry.get("type")} + bucket["relationship_pass"] += sum(1 for relationship_type in case.expected_relationship_types if relationship_type in relationship_types) + for family, bucket in grouped.items(): + rows.append( + { + "contract_family": family, + "contract_type_passed": bucket["contract_type_pass"], + "contract_type_total": bucket["contract_type_total"], + "contract_type_accuracy": round((bucket["contract_type_pass"] / bucket["contract_type_total"]) * 100, 2) if bucket["contract_type_total"] else 0.0, + "payment_milestone_passed": bucket["payment_pass"], + "payment_milestone_total": bucket["payment_total"], + "payment_milestone_accuracy": round((bucket["payment_pass"] / bucket["payment_total"]) * 100, 2) if bucket["payment_total"] else 0.0, + "relationship_presence_passed": bucket["relationship_pass"], + "relationship_presence_total": bucket["relationship_total"], + "relationship_presence_accuracy": round((bucket["relationship_pass"] / bucket["relationship_total"]) * 100, 2) if bucket["relationship_total"] else 0.0, + } + ) + return rows + + +def build_relationship_baseline_by_type(summary: Dict) -> List[Dict[str, object]]: + rows: List[Dict[str, object]] = [] + grouped: Dict[str, Dict[str, int]] = {} + for item in summary["cases"]: + result = item.get("result") or {} + relationships = result.get("contract_structure", {}).get("clause_relationships") or [] + relationship_types = {entry.get("type") for entry in relationships if entry.get("type")} + confidence_map = {entry.get("type"): entry.get("confidence_tier") for entry in relationships if entry.get("type")} + case = next(case for case in CASES if case.case_id == item["case_id"]) + for relationship_type in case.expected_relationship_types or []: + bucket = grouped.setdefault(relationship_type, {"present_pass": 0, "present_total": 0, "confidence_pass": 0, "confidence_total": 0}) + bucket["present_total"] += 1 + if relationship_type in relationship_types: + bucket["present_pass"] += 1 + expected_confidence = (case.expected_relationship_confidence or {}).get(relationship_type) + if expected_confidence: + bucket["confidence_total"] += 1 + if confidence_map.get(relationship_type) == expected_confidence: + bucket["confidence_pass"] += 1 + for relationship_type, bucket in grouped.items(): + rows.append( + { + "relationship_type": relationship_type, + "presence_passed": bucket["present_pass"], + "presence_total": bucket["present_total"], + "presence_accuracy": round((bucket["present_pass"] / bucket["present_total"]) * 100, 2) if bucket["present_total"] else 0.0, + "confidence_passed": bucket["confidence_pass"], + "confidence_total": bucket["confidence_total"], + "confidence_accuracy": round((bucket["confidence_pass"] / bucket["confidence_total"]) * 100, 2) if bucket["confidence_total"] else 0.0, + } + ) + return rows + + def build_sample_inventory() -> List[Dict[str, object]]: return [ { @@ -724,9 +812,13 @@ def run_gate(api_base: str, artifact_dir: Path, password: str) -> Dict: ) field_baseline = build_field_baseline(summary) relationship_baseline = build_relationship_baseline(summary) + field_baseline_by_contract = build_field_baseline_by_contract(summary) + relationship_baseline_by_type = build_relationship_baseline_by_type(summary) sample_inventory = build_sample_inventory() summary["field_baseline"] = field_baseline summary["relationship_baseline"] = relationship_baseline + summary["field_baseline_by_contract"] = field_baseline_by_contract + summary["relationship_baseline_by_type"] = relationship_baseline_by_type summary["sample_inventory"] = sample_inventory return summary @@ -748,6 +840,10 @@ def main() -> int: write_csv(field_csv_path, summary.get("field_baseline") or []) relationship_csv_path = artifact_dir / "review-structured-relationship-baseline.csv" write_csv(relationship_csv_path, summary.get("relationship_baseline") or []) + field_by_contract_csv_path = artifact_dir / "review-structured-field-baseline-by-contract.csv" + write_csv(field_by_contract_csv_path, summary.get("field_baseline_by_contract") or []) + relationship_by_type_csv_path = artifact_dir / "review-structured-relationship-baseline-by-type.csv" + write_csv(relationship_by_type_csv_path, summary.get("relationship_baseline_by_type") or []) sample_inventory_csv_path = artifact_dir / "review-structured-sample-inventory.csv" write_csv(sample_inventory_csv_path, summary.get("sample_inventory") or []) baseline_md_path = artifact_dir / "review-structured-baseline.md" diff --git a/project-docs/OCR后续能力扩展阶段1第七批执行记录-2026-05-04.md b/project-docs/OCR后续能力扩展阶段1第七批执行记录-2026-05-04.md new file mode 100644 index 00000000..ecb22c24 --- /dev/null +++ b/project-docs/OCR后续能力扩展阶段1第七批执行记录-2026-05-04.md @@ -0,0 +1,152 @@ +# OCR 后续能力扩展阶段 1 第七批执行记录(2026-05-04) + +## 1. 本批目标 + +基于阶段 1 第六批已经建立的正式准确率基线,继续推进第七批: + +1. 把结构化审查样本从脚本内嵌正文迁移到独立样本夹。 +2. 让门禁正式读取样本库清单与独立样本文件。 +3. 把准确率基线从“总表”扩展为: + - 按合同类型滚动 + - 按关系类型滚动 + +## 2. 本批改造 + +### 样本库独立化 + +新增目录: + +- [structured-review-samples/README.md](D:/ai-contract-platform/project-docs/structured-review-samples/README.md) +- [structured-review-samples/manifest.json](D:/ai-contract-platform/project-docs/structured-review-samples/manifest.json) +- `structured-review-samples/samples/*.txt` + +当前已迁移的样本: + +1. `structured-service.txt` +2. `structured-procurement.txt` +3. `structured-sales.txt` +4. `structured-lease.txt` +5. `structured-development.txt` +6. `structured-implementation.txt` +7. `structured-carveout.txt` +8. `structured-weak-acceptance.txt` +9. `structured-license.txt` +10. `structured-entrustment.txt` + +### 门禁工具 + +1. `backend/tools/review_structured_acceptance_gate.py` + - 新增 `load_cases_from_manifest(...)` + - 运行时真相源已切换为: + - `manifest.json` + - `samples/*.txt` + - 不再依赖脚本内嵌正文作为主样本来源 + +2. 门禁新增滚动基线导出: + - `review-structured-field-baseline-by-contract.csv` + - `review-structured-relationship-baseline-by-type.csv` + +### 测试 + +1. `backend/tests/test_review_structured_acceptance_gate.py` + - 新增 manifest 读取测试 + - 新增按合同类型 / 按关系类型滚动基线测试 + +## 3. 产物 + +### 样本库 + +- [真实业务合同批量样本库-2026-05-04.csv](D:/ai-contract-platform/project-docs/真实业务合同批量样本库-2026-05-04.csv) + +### 正式基线 + +- [结构化字段与关系准确率基线-2026-05-04.md](D:/ai-contract-platform/project-docs/结构化字段与关系准确率基线-2026-05-04.md) + +### QA 产物 + +- `review-structured-field-baseline.csv` +- `review-structured-relationship-baseline.csv` +- `review-structured-field-baseline-by-contract.csv` +- `review-structured-relationship-baseline-by-type.csv` +- `review-structured-sample-inventory.csv` + +## 4. 验证结果 + +### 本地验证 + +1. 后端: + - `backend\\.venv\\Scripts\\python.exe -m unittest tests.test_review_structured_acceptance_gate tests.test_review_service tests.test_review_service_rules tests.test_reviews_api` + - `PASS` + +2. 前端: + - `frontend\\npm.cmd run build` + - `PASS` + +### 线上验证 + +1. 结构化门禁: + - `project-docs/qa-artifacts/review-structured-acceptance-gate/2026-05-04T18-42-53-143/` + - 结果:`PASS` + +2. PDF 门禁: + - `project-docs/qa-artifacts/pdf-acceptance-gate/2026-05-04T18-42-53-262/` + - 结果:`PASS` + +## 5. 当前基线解读 + +### 按合同类型滚动 + +当前门禁已能输出: + +1. `contract_type_accuracy` +2. `payment_milestone_accuracy` +3. `relationship_presence_accuracy` + +按合同类型拆分到: + +1. `service` +2. `procurement` +3. `sales` +4. `lease` +5. `development` +6. `license` +7. `entrustment` + +### 按关系类型滚动 + +当前门禁已能输出: + +1. `presence_accuracy` +2. `confidence_accuracy` + +按关系类型拆分到: + +1. `payment_depends_on_acceptance` +2. `payment_depends_on_invoice` +3. `liability_cap_conflicts_with_breach` +4. `payment_depends_on_go_live` +5. `payment_after_warranty_period` +6. `liability_cap_conflicts_with_confidentiality` +7. `liability_cap_conflicts_with_ip` + +## 6. 当前结论 + +阶段 1 第七批已经闭环: + +1. 样本已经从脚本内嵌正文迁移到独立样本夹。 +2. 样本库具备独立维护入口。 +3. 结构化门禁已经能输出滚动基线,而不只是总基线。 +4. 后续新增样本、扩展规则、滚动更新准确率的成本已经明显下降。 + +## 7. 下一步建议 + +下一步最自然的是进入: + +**阶段 1 第八批:真实合同来源批量导入与基线趋势留存** + +建议优先处理: + +1. 引入更多真实来源或批量脱敏合同。 +2. 为样本库增加来源批次与业务线维度。 +3. 让滚动基线开始保留历史快照。 +4. 形成按日 / 按批次的基线趋势对比能力。 diff --git a/project-docs/structured-review-samples/README.md b/project-docs/structured-review-samples/README.md new file mode 100644 index 00000000..2d58d2bc --- /dev/null +++ b/project-docs/structured-review-samples/README.md @@ -0,0 +1,47 @@ +# 结构化审查样本库 + +## 目录说明 + +本目录用于承载结构化审查门禁的独立样本资产,替代将样本文本直接硬编码在脚本中。 + +- `manifest.json` + - 样本元数据清单 + - 包含: + - 样本编号 + - 合同族 + - 样本来源说明 + - 预期字段 + - 预期关系 + - 预期置信度 +- `samples/` + - 每条样本对应一份独立文本文件 + +## 当前样本 + +当前样本覆盖: + +1. 服务合同 +2. 采购合同 +3. 购销合同 +4. 租赁合同 +5. 开发合同 +6. 复杂实施合同 +7. 责任限制含 carve-out 的实施合同 +8. 弱提示付款依赖样本 +9. 软件许可协议 +10. 委托服务合同 + +## 维护规则 + +1. 样本正文统一放在 `samples/` 下。 +2. `manifest.json` 只负责样本索引与预期断言,不直接内嵌正文。 +3. 新增样本时: + - 先新增 `samples/*.txt` + - 再补 `manifest.json` + - 最后运行结构化门禁,更新准确率基线 + +## 使用方 + +当前主要被以下工具读取: + +- `backend/tools/review_structured_acceptance_gate.py` diff --git a/project-docs/structured-review-samples/manifest.json b/project-docs/structured-review-samples/manifest.json new file mode 100644 index 00000000..f714d819 --- /dev/null +++ b/project-docs/structured-review-samples/manifest.json @@ -0,0 +1,193 @@ +{ + "samples": [ + { + "case_id": "S-001", + "label": "服务合同结构化摘要", + "contract_type": "service", + "review_as": "party_a", + "file_name": "structured-service.txt", + "content_file": "samples/structured-service.txt", + "source_origin": "deidentified_realistic", + "redaction_level": "sanitized", + "expected_contract_type": "service", + "expected_clause_types": ["payment", "confidentiality", "breach"], + "expected_missing_sections": ["争议解决条款"], + "expected_amount_contains": "500000", + "expected_term_start": "2026-05-01", + "expected_term_end": "2027-05-01", + "expected_payment_milestones": 1, + "expected_relationship_types": ["payment_depends_on_acceptance", "payment_depends_on_invoice"] + }, + { + "case_id": "S-002", + "label": "采购合同缺失条款提示", + "contract_type": "procurement", + "review_as": "party_a", + "file_name": "structured-procurement.txt", + "content_file": "samples/structured-procurement.txt", + "source_origin": "deidentified_realistic", + "redaction_level": "sanitized", + "expected_contract_type": "procurement", + "expected_clause_types": ["payment", "delivery"], + "expected_missing_sections": ["验收标准或验收流程", "保密范围与期限"], + "expected_amount_contains": "120000", + "expected_payment_milestones": 1 + }, + { + "case_id": "S-003", + "label": "购销合同编号条款分段", + "contract_type": null, + "review_as": "party_a", + "file_name": "structured-sales.txt", + "content_file": "samples/structured-sales.txt", + "source_origin": "deidentified_realistic", + "redaction_level": "sanitized", + "expected_contract_type": "sales", + "expected_clause_types": ["delivery", "payment", "dispute_resolution"], + "expected_missing_sections": ["保密范围与期限", "违约责任安排"], + "expected_payment_milestones": 1, + "expected_relationship_types": ["payment_depends_on_acceptance", "payment_depends_on_invoice"] + }, + { + "case_id": "S-004", + "label": "租赁合同责任限制识别", + "contract_type": null, + "review_as": "party_a", + "file_name": "structured-lease.txt", + "content_file": "samples/structured-lease.txt", + "source_origin": "deidentified_realistic", + "redaction_level": "sanitized", + "expected_contract_type": "lease", + "expected_clause_types": ["delivery", "liability", "breach"], + "expected_missing_sections": ["付款与结算安排", "争议解决条款"], + "expected_term_start": "2026-06-01", + "expected_term_end": "2027-06-01", + "expected_relationship_types": ["liability_cap_conflicts_with_breach"] + }, + { + "case_id": "S-005", + "label": "开发合同付款节点拆解", + "contract_type": null, + "review_as": "party_a", + "file_name": "structured-development.txt", + "content_file": "samples/structured-development.txt", + "source_origin": "deidentified_realistic", + "redaction_level": "sanitized", + "expected_contract_type": "development", + "expected_clause_types": ["payment", "acceptance"], + "expected_missing_sections": ["保密范围与期限", "违约责任安排", "争议解决条款"], + "expected_amount_contains": "800000", + "expected_term_start": "2026-07-01", + "expected_term_end": "2027-01-31", + "expected_payment_milestones": 2, + "expected_relationship_types": ["payment_depends_on_acceptance", "payment_depends_on_invoice"] + }, + { + "case_id": "S-006", + "label": "复杂实施合同关系深化", + "contract_type": null, + "review_as": "party_a", + "file_name": "structured-implementation.txt", + "content_file": "samples/structured-implementation.txt", + "source_origin": "deidentified_realistic", + "redaction_level": "sanitized", + "expected_contract_type": "service", + "expected_clause_types": ["payment", "acceptance", "confidentiality", "intellectual_property", "liability", "breach"], + "expected_missing_sections": ["争议解决条款"], + "expected_amount_contains": "1500000", + "expected_term_start": "2026-08-01", + "expected_term_end": "2027-08-01", + "expected_payment_milestones": 4, + "expected_relationship_types": ["payment_depends_on_acceptance", "payment_depends_on_invoice", "payment_depends_on_go_live", "payment_after_warranty_period", "liability_cap_conflicts_with_breach", "liability_cap_conflicts_with_confidentiality", "liability_cap_conflicts_with_ip"], + "expected_relationship_confidence": { + "payment_depends_on_acceptance": "high", + "payment_after_warranty_period": "high", + "liability_cap_conflicts_with_ip": "high" + }, + "expected_ip_owner": "party_a" + }, + { + "case_id": "S-007", + "label": "实施合同责任限制含 carve-out", + "contract_type": null, + "review_as": "party_a", + "file_name": "structured-carveout.txt", + "content_file": "samples/structured-carveout.txt", + "source_origin": "deidentified_realistic", + "redaction_level": "sanitized", + "expected_contract_type": "service", + "expected_clause_types": ["payment", "confidentiality", "intellectual_property", "liability", "breach"], + "expected_missing_sections": ["验收标准或验收流程", "争议解决条款"], + "expected_amount_contains": "960000", + "expected_payment_milestones": 1, + "expected_relationship_types": ["payment_depends_on_acceptance", "payment_depends_on_invoice", "liability_cap_conflicts_with_breach"], + "expected_absent_relationship_types": ["liability_cap_conflicts_with_confidentiality", "liability_cap_conflicts_with_ip"], + "expected_relationship_confidence": { + "liability_cap_conflicts_with_breach": "weak" + }, + "expected_ip_owner": "party_a", + "expected_liability_carve_outs": ["confidentiality", "intellectual_property", "intentional_misconduct", "gross_negligence"] + }, + { + "case_id": "S-008", + "label": "弱提示付款依赖样本", + "contract_type": null, + "review_as": "party_a", + "file_name": "structured-weak-acceptance.txt", + "content_file": "samples/structured-weak-acceptance.txt", + "source_origin": "deidentified_realistic", + "redaction_level": "sanitized", + "expected_contract_type": "service", + "expected_clause_types": ["payment"], + "expected_missing_sections": ["验收标准或验收流程", "保密范围与期限", "违约责任安排", "争议解决条款"], + "expected_amount_contains": "300000", + "expected_payment_milestones": 1, + "expected_relationship_types": ["payment_depends_on_acceptance"], + "expected_relationship_confidence": { + "payment_depends_on_acceptance": "weak" + } + }, + { + "case_id": "S-009", + "label": "软件许可协议归属与许可关系", + "contract_type": null, + "review_as": "party_a", + "file_name": "structured-license.txt", + "content_file": "samples/structured-license.txt", + "source_origin": "deidentified_realistic", + "redaction_level": "sanitized", + "expected_contract_type": "license", + "expected_clause_types": ["payment", "intellectual_property", "liability"], + "expected_missing_sections": ["验收标准或验收流程", "保密范围与期限", "争议解决条款"], + "expected_amount_contains": "420000", + "expected_term_start": "2026-09-01", + "expected_term_end": "2027-08-31", + "expected_payment_milestones": 2, + "expected_relationship_types": ["payment_depends_on_invoice"], + "expected_absent_relationship_types": ["liability_cap_conflicts_with_ip"], + "expected_ip_owner": "party_b", + "expected_liability_carve_outs": ["intentional_misconduct", "gross_negligence", "intellectual_property"] + }, + { + "case_id": "S-010", + "label": "委托服务合同多节点验收关系", + "contract_type": null, + "review_as": "party_a", + "file_name": "structured-entrustment.txt", + "content_file": "samples/structured-entrustment.txt", + "source_origin": "deidentified_realistic", + "redaction_level": "sanitized", + "expected_contract_type": "entrustment", + "expected_clause_types": ["payment", "acceptance", "confidentiality", "dispute_resolution"], + "expected_missing_sections": ["违约责任安排"], + "expected_amount_contains": "560000", + "expected_term_start": "2026-10-01", + "expected_term_end": "2027-03-31", + "expected_payment_milestones": 3, + "expected_relationship_types": ["payment_depends_on_acceptance", "payment_depends_on_invoice"], + "expected_relationship_confidence": { + "payment_depends_on_acceptance": "high" + } + } + ] +} diff --git a/project-docs/structured-review-samples/samples/structured-carveout.txt b/project-docs/structured-review-samples/samples/structured-carveout.txt new file mode 100644 index 00000000..8be5b0e7 --- /dev/null +++ b/project-docs/structured-review-samples/samples/structured-carveout.txt @@ -0,0 +1,14 @@ +软件实施服务合同 +甲方:甲方集团有限公司 +乙方:乙方实施服务有限公司 +合同金额:人民币960000元 +第一条 付款条款 +甲方应在验收合格并收到发票后15个工作日内支付全部合同款。 +第二条 保密条款 +乙方应对甲方商业秘密承担保密义务。 +第三条 知识产权 +项目交付成果、源代码及相关文档的知识产权归甲方所有。 +第四条 责任限制 +任何一方的赔偿责任以合同总金额为上限,但保密义务、知识产权侵权、故意或重大过失除外。 +第五条 违约责任 +乙方违反保密义务或侵犯知识产权的,应承担违约责任并赔偿损失。 diff --git a/project-docs/structured-review-samples/samples/structured-development.txt b/project-docs/structured-review-samples/samples/structured-development.txt new file mode 100644 index 00000000..96cc2448 --- /dev/null +++ b/project-docs/structured-review-samples/samples/structured-development.txt @@ -0,0 +1,9 @@ +软件开发合同 +甲方:甲方信息有限公司 +乙方:乙方科技有限公司 +合同金额:人民币800000元 +服务期限:自2026年7月1日至2027年1月31日 +第一条 付款条款 +甲方应在合同签署后5个工作日内支付首期款30%;验收合格并收到发票后10个工作日内支付尾款70%。 +第二条 验收条款 +乙方交付系统并完成验收后,方可进入尾款结算。 diff --git a/project-docs/structured-review-samples/samples/structured-entrustment.txt b/project-docs/structured-review-samples/samples/structured-entrustment.txt new file mode 100644 index 00000000..352901f2 --- /dev/null +++ b/project-docs/structured-review-samples/samples/structured-entrustment.txt @@ -0,0 +1,13 @@ +委托服务合同 +甲方:甲方运营有限公司 +乙方:乙方咨询有限公司 +合同金额:人民币560000元 +合同期限:自2026年10月1日至2027年3月31日 +第一条 付款条款 +甲方应在合同签署后5个工作日内支付预付款30%;阶段成果验收合格后7个工作日内支付进度款40%;项目最终验收合格并收到发票后10个工作日内支付尾款30%。 +第二条 验收条款 +乙方提交阶段成果和最终成果后,应由甲方书面验收确认。 +第三条 保密条款 +乙方应对项目资料、商业秘密和客户信息承担保密义务。 +第四条 争议解决 +双方同意提交甲方所在地人民法院管辖。 diff --git a/project-docs/structured-review-samples/samples/structured-implementation.txt b/project-docs/structured-review-samples/samples/structured-implementation.txt new file mode 100644 index 00000000..324a4a48 --- /dev/null +++ b/project-docs/structured-review-samples/samples/structured-implementation.txt @@ -0,0 +1,17 @@ +软件实施服务合同 +甲方:甲方集团有限公司 +乙方:乙方实施服务有限公司 +合同金额:人民币1500000元 +服务期限:自2026年8月1日至2027年8月1日 +第一条 付款条款 +甲方应在合同签署后5个工作日内支付预付款20%;系统验收合格并收到增值税专用发票后10个工作日内支付实施款50%;系统上线稳定运行30日后支付尾款20%;剩余10%作为质保金,在质保期满后10个工作日内支付。 +第二条 验收条款 +乙方完成实施并通过甲方书面验收后,方可进入后续付款节点。 +第三条 保密条款 +乙方应对甲方商业秘密、客户数据和项目资料承担严格保密义务。 +第四条 知识产权 +项目交付成果、源代码及相关文档的知识产权归甲方所有。 +第五条 责任限制 +任何一方因本合同产生的赔偿责任以合同总金额为上限,但故意或重大过失除外。 +第六条 违约责任 +乙方延迟交付、泄露保密信息或侵犯第三方知识产权的,应承担违约责任并赔偿损失。 diff --git a/project-docs/structured-review-samples/samples/structured-lease.txt b/project-docs/structured-review-samples/samples/structured-lease.txt new file mode 100644 index 00000000..e59b2325 --- /dev/null +++ b/project-docs/structured-review-samples/samples/structured-lease.txt @@ -0,0 +1,10 @@ +设备租赁合同 +甲方:甲方设备有限公司 +乙方:乙方工程有限公司 +租赁期限:自2026年6月1日至2027年6月1日 +第一条 租赁物交付 +甲方应在合同生效后五日内完成设备交付。 +第二条 责任限制 +任何一方的赔偿责任以六个月租金总额为上限,但故意或重大过失除外。 +第三条 违约责任 +乙方逾期返还设备的,应按日承担违约责任。 diff --git a/project-docs/structured-review-samples/samples/structured-license.txt b/project-docs/structured-review-samples/samples/structured-license.txt new file mode 100644 index 00000000..701bbed2 --- /dev/null +++ b/project-docs/structured-review-samples/samples/structured-license.txt @@ -0,0 +1,11 @@ +软件许可协议 +甲方:甲方制造有限公司 +乙方:乙方软件有限公司 +合同金额:人民币420000元 +服务期限:自2026年9月1日至2027年8月31日 +第一条 付款条款 +甲方应在合同签署后5个工作日内支付首期许可费50%;收到发票后10个工作日内支付剩余许可费50%。 +第二条 知识产权 +软件著作权、源代码及相关知识产权归乙方所有,甲方在许可期内享有非独占使用权。 +第三条 责任限制 +任何一方的赔偿责任以合同总金额为上限,但故意、重大过失和知识产权侵权除外。 diff --git a/project-docs/structured-review-samples/samples/structured-procurement.txt b/project-docs/structured-review-samples/samples/structured-procurement.txt new file mode 100644 index 00000000..ac0bff2e --- /dev/null +++ b/project-docs/structured-review-samples/samples/structured-procurement.txt @@ -0,0 +1,6 @@ +采购合同 +甲方:甲方商贸有限公司 +乙方:乙方供应链有限公司 +总价:¥120000元 +付款方式:货到后付款,具体节点另行协商。 +交付条款:乙方应在30日内交货。 diff --git a/project-docs/structured-review-samples/samples/structured-sales.txt b/project-docs/structured-review-samples/samples/structured-sales.txt new file mode 100644 index 00000000..208cbfb9 --- /dev/null +++ b/project-docs/structured-review-samples/samples/structured-sales.txt @@ -0,0 +1,9 @@ +购销合同 +甲方:甲方制造有限公司 +乙方:乙方贸易有限公司 +第一条 交货条款 +乙方应在收到订单后十五日内完成交货并配合到货验收。 +第二条 付款条款 +甲方应在验收合格并收到增值税专用发票后七个工作日内付款。 +第三条 争议解决 +双方同意提交上海仲裁委员会仲裁。 diff --git a/project-docs/structured-review-samples/samples/structured-service.txt b/project-docs/structured-review-samples/samples/structured-service.txt new file mode 100644 index 00000000..7bdc7071 --- /dev/null +++ b/project-docs/structured-review-samples/samples/structured-service.txt @@ -0,0 +1,8 @@ +服务合同 +甲方:甲方科技有限公司 +乙方:乙方软件有限公司 +合同金额:人民币500000元 +服务期限:自2026年5月1日至2027年5月1日 +付款条款:甲方应在验收合格并收到发票后10个工作日内付款。 +保密条款:乙方应对商业秘密承担保密义务。 +违约条款:乙方延迟交付应承担违约责任。 diff --git a/project-docs/structured-review-samples/samples/structured-weak-acceptance.txt b/project-docs/structured-review-samples/samples/structured-weak-acceptance.txt new file mode 100644 index 00000000..bf7e6981 --- /dev/null +++ b/project-docs/structured-review-samples/samples/structured-weak-acceptance.txt @@ -0,0 +1,8 @@ +技术服务合同 +甲方:甲方科技有限公司 +乙方:乙方顾问有限公司 +合同金额:人民币300000元 +第一条 付款条款 +甲方应在验收合格后尽快支付尾款100%。 +第二条 服务内容 +乙方负责提供咨询与优化建议。 diff --git a/project-docs/结构化字段与关系准确率基线-2026-05-04.md b/project-docs/结构化字段与关系准确率基线-2026-05-04.md index b1410b08..999daf23 100644 --- a/project-docs/结构化字段与关系准确率基线-2026-05-04.md +++ b/project-docs/结构化字段与关系准确率基线-2026-05-04.md @@ -4,7 +4,7 @@ 本基线来自结构化审查门禁产物: -- [review-structured-acceptance-gate/2026-05-04T18-17-55-988](D:/ai-contract-platform/project-docs/qa-artifacts/review-structured-acceptance-gate/2026-05-04T18-17-55-988) +- [review-structured-acceptance-gate/2026-05-04T18-42-53-143](D:/ai-contract-platform/project-docs/qa-artifacts/review-structured-acceptance-gate/2026-05-04T18-42-53-143) 对应产物文件: @@ -12,6 +12,8 @@ 2. `review-structured-relationship-baseline.csv` 3. `review-structured-sample-inventory.csv` 4. `review-structured-baseline.md` +5. `review-structured-field-baseline-by-contract.csv` +6. `review-structured-relationship-baseline-by-type.csv` ## 2. 字段准确率基线 @@ -55,7 +57,16 @@ - [真实业务合同批量样本库-2026-05-04.csv](D:/ai-contract-platform/project-docs/真实业务合同批量样本库-2026-05-04.csv) -## 5. 基线意义 +## 5. 滚动基线入口 + +当前滚动基线已经可以从门禁产物中直接读取: + +1. 按合同类型: + - `review-structured-field-baseline-by-contract.csv` +2. 按关系类型: + - `review-structured-relationship-baseline-by-type.csv` + +## 6. 基线意义 本基线当前主要用于: @@ -64,7 +75,7 @@ 3. 约束高置信 / 弱提示关系分层回归。 4. 约束责任限制 carve-out 与知识产权归属抽取回归。 -## 6. 说明 +## 7. 说明 这不是生产全量准确率,而是**当前已纳入脱敏样本库的正式基线准确率**。 后续随着更多真实来源或脱敏合同进入样本库,基线会动态扩大,准确率也应随样本复杂度变化持续复测和记录。