diff --git a/backend/app/services/review_service.py b/backend/app/services/review_service.py index ecc7f9a1..efd7903c 100644 --- a/backend/app/services/review_service.py +++ b/backend/app/services/review_service.py @@ -185,6 +185,7 @@ CLAUSE_TYPE_DEFINITIONS = [ {"type": "payment", "label": "付款条款", "keywords": ["付款", "价款", "金额", "发票", "invoice", "payment", "milestone", "billing", "fees"]}, {"type": "acceptance", "label": "验收条款", "keywords": ["验收", "acceptance", "测试", "试运行", "上线", "验收标准"]}, {"type": "confidentiality", "label": "保密条款", "keywords": ["保密", "confidential", "non-disclosure", "nda", "商业秘密"]}, + {"type": "intellectual_property", "label": "知识产权", "keywords": ["知识产权", "著作权", "源代码", "软件著作权", "专利", "商标", "技术成果", "intellectual property", "copyright", "ip"]}, {"type": "breach", "label": "违约条款", "keywords": ["违约", "违约金", "赔偿", "liquidated damages", "default", "penalty"]}, {"type": "delivery", "label": "交付条款", "keywords": ["交付", "交货", "deliver", "delivery", "成果", "上线", "部署"]}, {"type": "liability", "label": "责任限制", "keywords": ["免责", "责任限制", "赔偿上限", "liability cap", "disclaimer", "exclusion of liability"]}, @@ -193,7 +194,7 @@ CLAUSE_TYPE_DEFINITIONS = [ {"type": "dispute_resolution", "label": "争议解决", "keywords": ["争议解决", "仲裁", "管辖", "法院", "arbitration", "jurisdiction"]}, ] CLAUSE_TYPE_LABEL_MAP = {item["type"]: item["label"] for item in CLAUSE_TYPE_DEFINITIONS} -STRUCTURE_SECTION_ORDER = ["payment", "acceptance", "delivery", "confidentiality", "breach", "liability", "renewal", "termination", "dispute_resolution"] +STRUCTURE_SECTION_ORDER = ["payment", "acceptance", "delivery", "confidentiality", "intellectual_property", "breach", "liability", "renewal", "termination", "dispute_resolution"] STRUCTURE_MISSING_SECTION_RULES = [ {"type": "payment", "message": "付款与结算安排"}, {"type": "acceptance", "message": "验收标准或验收流程"}, @@ -232,6 +233,9 @@ PAYMENT_TRIGGER_HINTS = [ ("交货", "delivery_completed"), ("交付", "delivery_completed"), ("上线", "go_live_completed"), + ("质保期满", "warranty_period_ended"), + ("质保期结束", "warranty_period_ended"), + ("质保金", "warranty_period_ended"), ] RISK_CERTAINTY_CONFIRMED = "confirmed" RISK_CERTAINTY_POSSIBLE = "possible" @@ -247,6 +251,11 @@ NON_CLAUSE_METADATA_PATTERNS = [ ] RELATION_STATUS_INFO = "info" RELATION_STATUS_ATTENTION = "attention" +PAYMENT_STAGE_ADVANCE = "advance" +PAYMENT_STAGE_ACCEPTANCE = "acceptance" +PAYMENT_STAGE_GO_LIVE = "go_live" +PAYMENT_STAGE_FINAL = "final" +PAYMENT_STAGE_WARRANTY = "warranty_retention" pdfmetrics.registerFont(UnicodeCIDFont(PDF_FONT_NAME)) @@ -821,11 +830,12 @@ class ReviewService: payment_terms = key_sections.get("payment") or [] acceptance_terms = key_sections.get("acceptance") or [] confidentiality_terms = key_sections.get("confidentiality") or [] + intellectual_property_terms = key_sections.get("intellectual_property") or [] breach_terms = key_sections.get("breach") or [] dispute_terms = key_sections.get("dispute_resolution") or [] payment_milestones = self._extract_payment_milestones(clauses) clause_relationships = self._build_clause_relationships(clauses, payment_milestones) - missing_sections = self._detect_missing_sections(clause_type_counts) + missing_sections = self._detect_missing_sections(clause_type_counts, detected_contract_type) return { "title": basic_info.get("contract_title") or review.title, "detected_contract_type": detected_contract_type, @@ -842,6 +852,7 @@ class ReviewService: "payment_terms": payment_terms, "acceptance_terms": acceptance_terms, "confidentiality_terms": confidentiality_terms, + "intellectual_property_terms": intellectual_property_terms, "breach_terms": breach_terms, "dispute_resolution_terms": dispute_terms, "payment_milestones": payment_milestones, @@ -853,6 +864,7 @@ class ReviewService: payment_terms=payment_terms, acceptance_terms=acceptance_terms, confidentiality_terms=confidentiality_terms, + intellectual_property_terms=intellectual_property_terms, breach_terms=breach_terms, payment_milestones=payment_milestones, clause_relationships=clause_relationships, @@ -1004,13 +1016,15 @@ class ReviewService: return title, content or normalized return None - def _detect_missing_sections(self, clause_type_counts: Dict[str, int]) -> List[str]: + def _detect_missing_sections(self, clause_type_counts: Dict[str, int], contract_type: str) -> List[str]: missing: List[str] = [] for item in STRUCTURE_MISSING_SECTION_RULES: if not clause_type_counts.get(item["type"]): missing.append(item["message"]) if clause_type_counts.get("payment") and not clause_type_counts.get("acceptance") and "验收标准或验收流程" not in missing: missing.append("验收标准或验收流程") + if contract_type in {"development", "service", "license"} and not clause_type_counts.get("intellectual_property"): + missing.append("知识产权归属或许可安排") return missing def _extract_payment_milestones(self, clauses: List[Dict[str, Any]]) -> List[Dict[str, Any]]: @@ -1028,12 +1042,14 @@ class ReviewService: deduped_dependencies.append(dependency) due_match = PAYMENT_DUE_PATTERN.search(segment) ratio_match = PAYMENT_RATIO_PATTERN.search(segment) + stage = self._classify_payment_stage(segment, deduped_dependencies) milestones.append( { "title": f"{clause.get('title') or '付款条款'}-节点{index}", "summary": self._summarize_clause_text(segment), "clause_title": clause.get("title"), "trigger_text": segment, + "stage": stage, "due_within": due_match.group(0) if due_match else None, "due_days": int(due_match.group(1)) if due_match else None, "due_unit": due_match.group(3) if due_match else None, @@ -1043,6 +1059,22 @@ class ReviewService: ) return milestones + def _classify_payment_stage(self, segment: str, dependencies: List[str]) -> str: + lowered = segment.lower() + if any(token in segment for token in ["质保金", "质保期满", "质保期结束"]): + return PAYMENT_STAGE_WARRANTY + if "尾款" in segment: + return PAYMENT_STAGE_FINAL + if "go_live_completed" in dependencies or "上线" in segment: + return PAYMENT_STAGE_GO_LIVE + if "acceptance_passed" in dependencies: + return PAYMENT_STAGE_ACCEPTANCE + if "contract_signed" in dependencies or any(token in segment for token in ["预付款", "首期款", "定金", "签署后"]): + return PAYMENT_STAGE_ADVANCE + if "invoice_received" in dependencies: + return PAYMENT_STAGE_FINAL + return PAYMENT_STAGE_FINAL + def _build_clause_relationships( self, clauses: List[Dict[str, Any]], @@ -1080,8 +1112,34 @@ class ReviewService: "reason": milestone.get("trigger_text"), } ) + if "go_live_completed" in milestone.get("dependencies", []): + relationships.append( + { + "type": "payment_depends_on_go_live", + "label": "付款依赖上线稳定运行", + "status": RELATION_STATUS_INFO, + "source_clause_title": milestone.get("clause_title"), + "target_clause_title": None, + "summary": "付款节点包含上线或稳定运行前置条件。", + "reason": milestone.get("trigger_text"), + } + ) + if milestone.get("stage") == PAYMENT_STAGE_WARRANTY or "warranty_period_ended" in milestone.get("dependencies", []): + relationships.append( + { + "type": "payment_after_warranty_period", + "label": "付款依赖质保期结束", + "status": RELATION_STATUS_ATTENTION, + "source_clause_title": milestone.get("clause_title"), + "target_clause_title": None, + "summary": "付款节点与质保期或质保金释放挂钩,需要关注质保终止条件是否明确。", + "reason": milestone.get("trigger_text"), + } + ) liability_clause = (clause_by_type.get("liability") or [None])[0] + confidentiality_clause = (clause_by_type.get("confidentiality") or [None])[0] + intellectual_property_clause = (clause_by_type.get("intellectual_property") or [None])[0] breach_clause = (clause_by_type.get("breach") or [None])[0] if liability_clause and breach_clause: liability_content = liability_clause.get("content") or "" @@ -1097,6 +1155,30 @@ class ReviewService: "reason": self._summarize_clause_text(liability_content), } ) + if confidentiality_clause and not any(token in liability_content for token in ["保密", "商业秘密"]): + relationships.append( + { + "type": "liability_cap_conflicts_with_confidentiality", + "label": "责任限制可能冲突保密义务", + "status": RELATION_STATUS_ATTENTION, + "source_clause_title": liability_clause.get("title"), + "target_clause_title": confidentiality_clause.get("title"), + "summary": "责任限制条款未显式排除保密义务风险,可能压缩保密违约后的救济范围。", + "reason": self._summarize_clause_text(liability_content), + } + ) + if intellectual_property_clause and not any(token in liability_content for token in ["知识产权", "著作权", "源代码", "软件著作权"]): + relationships.append( + { + "type": "liability_cap_conflicts_with_ip", + "label": "责任限制可能冲突知识产权责任", + "status": RELATION_STATUS_ATTENTION, + "source_clause_title": liability_clause.get("title"), + "target_clause_title": intellectual_property_clause.get("title"), + "summary": "责任限制条款未显式排除知识产权侵权或成果归属争议责任,需重点复核。", + "reason": self._summarize_clause_text(liability_content), + } + ) return relationships def _compose_contract_summary( @@ -1106,6 +1188,7 @@ class ReviewService: payment_terms: List[str], acceptance_terms: List[str], confidentiality_terms: List[str], + intellectual_property_terms: List[str], breach_terms: List[str], payment_milestones: List[Dict[str, Any]], clause_relationships: List[Dict[str, Any]], @@ -1118,6 +1201,8 @@ class ReviewService: observed.append("验收安排") if confidentiality_terms: observed.append("保密义务") + if intellectual_property_terms: + observed.append("知识产权") if breach_terms: observed.append("违约责任") observed_text = "、".join(observed) if observed else "关键条款仍较少" diff --git a/backend/tests/test_review_service.py b/backend/tests/test_review_service.py index 54fe1757..db182501 100644 --- a/backend/tests/test_review_service.py +++ b/backend/tests/test_review_service.py @@ -395,6 +395,38 @@ class ReviewServiceTestCase(unittest.TestCase): self.assertIn("invoice_received", milestones[1]["dependencies"]) self.assertIn("payment_depends_on_acceptance", {item["type"] for item in relationships}) + def test_relationships_cover_confidentiality_ip_and_warranty_retention(self): + text = "\n".join( + [ + "软件实施服务合同", + "合同金额:人民币1500000元", + "第一条 付款条款", + "甲方应在合同签署后5个工作日内支付预付款20%;系统验收合格并收到增值税专用发票后10个工作日内支付实施款50%;系统上线稳定运行30日后支付尾款20%;剩余10%作为质保金,在质保期满后10个工作日内支付。", + "第二条 验收条款", + "乙方完成实施并通过甲方书面验收后,方可进入后续付款节点。", + "第三条 保密条款", + "乙方应对甲方商业秘密承担保密义务。", + "第四条 知识产权", + "项目交付成果、源代码及相关文档的知识产权归甲方所有。", + "第五条 责任限制", + "任何一方因本合同产生的赔偿责任以合同总金额为上限,但故意或重大过失除外。", + "第六条 违约责任", + "乙方延迟交付、泄露保密信息或侵犯第三方知识产权的,应承担违约责任并赔偿损失。", + ] + ) + + clauses = self.service._enrich_clauses([], text) + milestones = self.service._extract_payment_milestones(clauses) + relationships = self.service._build_clause_relationships(clauses, milestones) + relationship_types = {item["type"] for item in relationships} + + self.assertGreaterEqual(len(milestones), 4) + self.assertIn("payment_depends_on_go_live", relationship_types) + self.assertIn("payment_after_warranty_period", relationship_types) + self.assertIn("liability_cap_conflicts_with_confidentiality", relationship_types) + self.assertIn("liability_cap_conflicts_with_ip", relationship_types) + self.assertIn("liability_cap_conflicts_with_breach", relationship_types) + def test_validate_review_upload_accepts_supported_suffix(self): self.service.validate_review_upload("contract.pdf", "application/pdf", b"%PDF-1.7") docx_buffer = io.BytesIO() diff --git a/backend/tools/review_structured_acceptance_gate.py b/backend/tools/review_structured_acceptance_gate.py index 7c70d9cf..236a19e7 100644 --- a/backend/tools/review_structured_acceptance_gate.py +++ b/backend/tools/review_structured_acceptance_gate.py @@ -159,6 +159,50 @@ CASES = [ expected_payment_milestones=2, expected_relationship_types=["payment_depends_on_acceptance", "payment_depends_on_invoice"], ), + StructuredReviewCase( + case_id="S-006", + label="复杂实施合同关系深化", + contract_type=None, + review_as="party_a", + file_name="structured-implementation.txt", + content="\n".join( + [ + "软件实施服务合同", + "甲方:甲方集团有限公司", + "乙方:乙方实施服务有限公司", + "合同金额:人民币1500000元", + "服务期限:自2026年8月1日至2027年8月1日", + "第一条 付款条款", + "甲方应在合同签署后5个工作日内支付预付款20%;系统验收合格并收到增值税专用发票后10个工作日内支付实施款50%;系统上线稳定运行30日后支付尾款20%;剩余10%作为质保金,在质保期满后10个工作日内支付。", + "第二条 验收条款", + "乙方完成实施并通过甲方书面验收后,方可进入后续付款节点。", + "第三条 保密条款", + "乙方应对甲方商业秘密、客户数据和项目资料承担严格保密义务。", + "第四条 知识产权", + "项目交付成果、源代码及相关文档的知识产权归甲方所有。", + "第五条 责任限制", + "任何一方因本合同产生的赔偿责任以合同总金额为上限,但故意或重大过失除外。", + "第六条 违约责任", + "乙方延迟交付、泄露保密信息或侵犯第三方知识产权的,应承担违约责任并赔偿损失。", + ] + ), + 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", + ], + ), ] diff --git a/frontend/src/app/reviews/[id]/page.tsx b/frontend/src/app/reviews/[id]/page.tsx index 4d5b0f94..d49036ca 100644 --- a/frontend/src/app/reviews/[id]/page.tsx +++ b/frontend/src/app/reviews/[id]/page.tsx @@ -207,6 +207,18 @@ function getRelationshipStatusColor(value: string | null | undefined) { return "default"; } +function formatPaymentStage(value: string | null | undefined) { + if (!value) return "付款节点"; + const stageMap: Record = { + advance: "预付款/首期款", + acceptance: "验收后付款", + go_live: "上线后付款", + final: "尾款/最终付款", + warranty_retention: "质保金/质保期尾款", + }; + return stageMap[value] ?? value; +} + function buildReviewChatRestorePayload( detail: ReviewDetail | null, result: ReviewResult | null, @@ -482,6 +494,7 @@ export default function ReviewDetailPage({ params }: { params: Promise<{ id: str { key: "payment_terms", label: "付款安排", items: contractStructure?.payment_terms ?? [] }, { key: "acceptance_terms", label: "验收安排", items: contractStructure?.acceptance_terms ?? [] }, { key: "confidentiality_terms", label: "保密义务", items: contractStructure?.confidentiality_terms ?? [] }, + { key: "intellectual_property_terms", label: "知识产权", items: contractStructure?.intellectual_property_terms ?? [] }, { key: "breach_terms", label: "违约责任", items: contractStructure?.breach_terms ?? [] }, { key: "dispute_resolution_terms", label: "争议解决", items: contractStructure?.dispute_resolution_terms ?? [] }, ].filter((item) => item.items.length > 0); @@ -936,6 +949,7 @@ export default function ReviewDetailPage({ params }: { params: Promise<{ id: str {item.title ?? `付款节点${index + 1}`} {item.summary ?? item.trigger_text ?? "-"} + {formatPaymentStage(item.stage)} {item.due_within ? {item.due_within} : null} {item.ratio_percent != null ? {item.ratio_percent}% : null} {(item.dependencies ?? []).map((dependency) => ( diff --git a/frontend/src/services/review.ts b/frontend/src/services/review.ts index d7290ff4..21c6811c 100644 --- a/frontend/src/services/review.ts +++ b/frontend/src/services/review.ts @@ -84,6 +84,7 @@ export type ReviewResult = { payment_terms?: string[]; acceptance_terms?: string[]; confidentiality_terms?: string[]; + intellectual_property_terms?: string[]; breach_terms?: string[]; dispute_resolution_terms?: string[]; payment_milestones?: Array<{ @@ -91,6 +92,7 @@ export type ReviewResult = { summary?: string; clause_title?: string | null; trigger_text?: string; + stage?: string; due_within?: string | null; due_days?: number | null; due_unit?: string | null; 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..5848ac2e --- /dev/null +++ b/project-docs/OCR后续能力扩展阶段1第四批执行记录-2026-05-04.md @@ -0,0 +1,192 @@ +# OCR 后续能力扩展阶段 1 第四批执行记录(2026-05-04) + +## 1. 本批目标 + +基于阶段 1 第三批已经完成的字段抽取深化与条款关系理解,继续推进第四批: + +1. 把更真实、更复杂的合同形态拉入结构化样本库。 +2. 深化付款分期、尾款、质保金等付款节点识别。 +3. 深化责任限制与保密、知识产权、违约之间的冲突关系规则。 +4. 让这些复杂关系在线上页面可直接观察和验证。 + +## 2. 本批改造 + +### 后端 + +1. `backend/app/services/review_service.py` + - 新增条款类型: + - `intellectual_property` + - 结构化结果新增: + - `contract_structure.intellectual_property_terms` + - `contract_structure.amount_details` + - `contract_structure.term_details` + - `contract_structure.payment_milestones` + - `contract_structure.clause_relationships` + - 新增金额明细抽取: + - 原始金额 + - 标准币种 + - 数值 + - 单位 + - 归一化人民币金额 + - 新增期限明细抽取: + - 原始期限 + - 开始日期 + - 结束日期 + - 新增付款节点深化: + - 预付款/首期款 + - 验收后付款 + - 上线后付款 + - 尾款 + - 质保金/质保期尾款 + - 新增付款节点依赖识别: + - `contract_signed` + - `acceptance_passed` + - `invoice_received` + - `go_live_completed` + - `warranty_period_ended` + - 新增条款关系: + - `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` + - 结构化分析元数据新增: + - `payment_milestone_count` + - `relationship_count` + - 审查报告导出同步增强: + - 付款节点列表 + - 条款关系列表 + +2. 条款分段与分类继续精修: + - `第一条 交货条款` 这类标题语义进一步保留。 + - `交货` 明确纳入交付条款识别。 + - `责任限制` 明确优先归入责任限制,而不是被违约语义抢走。 + +### 门禁与样本 + +1. `backend/tools/review_structured_acceptance_gate.py` + - 结构化验收门禁扩展到 6 个样本。 + - 断言范围从: + - 合同类型 + - 条款类型 + - 缺失条款 + - 扩展到: + - 金额片段 + - 期限起止 + - 付款节点数量 + - 关系类型 + +2. 新增复杂真实形态样本: + - `S-006` 复杂实施合同关系深化 + +3. 新增样本清单: + - [结构化复杂合同样本清单-2026-05-04.csv](D:/ai-contract-platform/project-docs/结构化复杂合同样本清单-2026-05-04.csv) + +### 前端 + +1. `frontend/src/services/review.ts` + - 承接第四批新增字段: + - `intellectual_property_terms` + - `amount_details` + - `term_details` + - `payment_milestones[].stage` + +2. `frontend/src/app/reviews/[id]/page.tsx` + - 结构化摘要区新增: + - 标准金额 + - 开始日期 / 结束日期 + - 付款节点数 + - 新增付款节点展示: + - 节点阶段 + - 支付时限 + - 支付比例 + - 依赖条件 + - 新增条款关系展示: + - 关系标签 + - 来源条款 + - 目标条款 + - 风险强度 + +## 3. 样本深化结果 + +当前结构化样本已经覆盖: + +1. 服务合同基础摘要 +2. 采购合同缺失条款 +3. 购销合同编号条款切分 +4. 租赁合同责任限制识别 +5. 开发合同付款节点拆解 +6. 复杂实施合同: + - 多阶段付款 + - 验收依赖 + - 发票依赖 + - 上线依赖 + - 质保金释放 + - 保密 + - 知识产权 + - 责任限制 + - 违约责任 + +## 4. 验证结果 + +### 本地验证 + +1. 后端定向: + - `backend\\.venv\\Scripts\\python.exe -m unittest tests.test_review_service tests.test_review_service_rules tests.test_reviews_api` + - `PASS` + +2. 前端构建: + - `frontend\\npm.cmd run build` + - `PASS` + +### 线上验证 + +1. 后端健康检查: + - `http://192.168.3.90:8001/health` + - `PASS` + +2. 结构化审查门禁: + - `project-docs/qa-artifacts/review-structured-acceptance-gate/2026-05-04T16-08-05-607/` + - 结果:`PASS` + +3. PDF 验收门禁: + - `project-docs/qa-artifacts/pdf-acceptance-gate/2026-05-04T16-08-06-016/` + - 结果:`PASS` + +4. 前端烟雾验证: + - `project-docs/qa-artifacts/stage1-batch4-front-smoke/2026-05-04T08-09-30-879Z/` + - 已确认: + - 结构化字段卡片可见 + - 付款节点区可见 + - 条款关系区可见 + - 证据关键词标签可见 + +## 5. 部署记录 + +1. 联合部署: + - `project-docs/qa-artifacts/stage1-batch4-full-deploy/2026-05-04T16-05-01/` + +## 6. 当前结论 + +阶段 1 第四批已经闭环: + +1. 样本库从“结构化演示样本”升级到了“更接近真实生产形态的复杂样本”。 +2. 付款节点已经可以拆出预付款、尾款、质保金等关键节点。 +3. 责任限制与保密、知识产权、违约之间的冲突关系已经进入规则层。 +4. 前端详情页已经能直接展示这些复杂结构和关系。 +5. 扩展后的结构化门禁和 PDF 门禁均已通过。 + +## 7. 下一步建议 + +下一步最自然的是进入: + +**阶段 1 第五批:真实业务合同批量入样与规则置信度校正** + +建议优先处理: + +1. 引入更多真实业务来源的合同文本样本。 +2. 建立字段抽取准确率与关系命中准确率对照表。 +3. 区分高置信关系与弱提示关系。 +4. 对付款节点、知识产权归属、责任限制 carve-out 继续做更细规则。 diff --git a/project-docs/结构化复杂合同样本清单-2026-05-04.csv b/project-docs/结构化复杂合同样本清单-2026-05-04.csv new file mode 100644 index 00000000..23881f2f --- /dev/null +++ b/project-docs/结构化复杂合同样本清单-2026-05-04.csv @@ -0,0 +1,7 @@ +sample_id,title,contract_family,shape,current_focus,expected_highlights +S-001,服务合同结构化摘要,service,text_contract,基础结构化摘要,合同类型/金额/期限/付款/保密/违约 +S-002,采购合同缺失条款提示,procurement,text_contract,缺失条款识别,付款/交付/缺失验收/缺失保密 +S-003,购销合同编号条款分段,sales,numbered_contract,编号条款切分,交货/付款/争议解决 +S-004,租赁合同责任限制识别,lease,liability_cap_contract,责任限制关系,交付/责任限制/违约 +S-005,开发合同付款节点拆解,development,milestone_contract,付款节点拆解,首期款/尾款/验收依赖/发票依赖 +S-006,复杂实施合同关系深化,service,complex_realistic_contract,复杂关系规则,付款分期/质保金/保密/知识产权/责任限制/违约