Java 程序员第 42 阶段06:文档智能解析审核,大模型实现合同摘要与合规校验,大模型Prompt工程在合同审核中的应用
概述
Prompt工程是大模型应用的核心技术,直接决定了模型输出的质量和准确性。本文将系统介绍Prompt工程的核心原则,并详细展示如何设计合同摘要、合同审核、合同比对等场景的Prompt模板。我们将配合LangChain4j的集成代码,展示完整的实际运行效果。
**前置依赖环境**:
- JDK 17+
- Spring Boot 3.2+
- LangChain4j 1.0.0+
- OpenAI GPT-4 / Anthropic Claude API
**项目依赖配置**:
<!-- pom.xml关键依赖 -->
<dependencies>
<!-- LangChain4j核心 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>1.0.0</version>
</dependency>
<!-- OpenAI集成 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>1.0.0</version>
</dependency>
<!-- 文档解析 -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
<!-- JSON处理 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.16.0</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
</dependencies>
**源码项目结构**:
contract-prompt-engineering/
├── src/main/java/com/demo/prompt/
│ ├── PromptTemplateEngine.java # Prompt模板引擎
│ ├── ContractSummarizer.java # 合同摘要生成器
│ ├── ContractReviewer.java # 合同审核器
│ ├── ContractComparator.java # 合同比对器
│ ├── model/
│ │ ├── ContractDocument.java # 合同文档模型
│ │ ├── ContractSummary.java # 摘要结果模型
│ │ ├── ReviewResult.java # 审核结果模型
│ │ └── ComparisonResult.java # 比对结果模型
│ └── config/
│ └── LlmConfig.java # LLM配置类
├── src/main/resources/
│ └── prompts/
│ ├── summary-template.txt # 摘要Prompt模板
│ ├── review-template.txt # 审核Prompt模板
│ └── comparison-template.txt # 比对Prompt模板
└── pom.xml
---
第一部分:Prompt工程核心原则
1.1 三大核心原则概述
Prompt工程是构建高质量AI应用的基础。根据业界最佳实践,我们总结出三大核心原则:
1.2 清晰原则详解
**问题示例 vs 改进示例**:
❌ 不清晰的Prompt:
分析这份合同。
✅ 清晰的Prompt:
作为合同审核专家,请分析以下合同文本,识别其中的风险点。
请从以下维度进行分析:
1. 法律合规性
2. 财务条款合理性
3. 运营风险点
每个风险点请说明具体条款位置和建议。
**清晰原则的具体实践**:
/**
* 清晰原则示例 - 使用具体动词
*/
public class ClearPromptExamples {
// ❌ 模糊动词
static final String UNCLEAR_PROMPT = """
看这个合同,说说有什么问题
""";
// ✅ 具体动词
static final String CLEAR_PROMPT = """
作为资深合同法务专家,请审查以下技术开发合同的条款。
任务要求:
1. 识别合同中违反《民法典》合同编相关规定的条款
2. 标注可能引发争议的模糊性表述
3. 指出知识产权归属不明确之处
4. 评估违约金条款的合理性
合同文本:
{contract_text}
输出要求:
- 每个问题需引用原文条款
- 说明违反的具体法律条款
- 提供修改建议
""";
}
1.3 具体原则详解
**Few-shot Prompt示例**:
/**
* 具体原则示例 - 提供参考案例
*/
public class SpecificPromptExamples {
static final String FEW_SHOT_PROMPT = """
作为合同审核专家,请判断以下合同条款是否存在法律风险。
示例1:
条款:"本合同自签订之日起生效,有效期为永久。"
分析:存在风险。【法律依据】根据《民法典》第160条,附终止期限的民事法律行为,期限届满时失效。永久有效期条款可能因违背公序良俗被认定无效。
风险等级:中
示例2:
条款:"甲方有权随时解除本合同,无需说明理由。"
分析:存在风险。【法律依据】根据《民法典》第563条,当事人一方有权解除合同的情形包括不可抗力、明确表示不履行等。任意解除权条款可能因显失公平被撤销。
风险等级:高
请按上述格式分析以下条款:
条款:"{target_clause}"
""";
}
1.4 结构化原则详解
**XML标签结构化示例**:
/**
* 结构化原则示例 - 使用XML标签
*/
public class StructuredPromptExamples {
static final String STRUCTURED_PROMPT = """
<system>
你是专业的合同法务审核专家,拥有丰富的法律知识和合同审核经验。
你的职责是帮助用户识别合同中的潜在风险并提供专业建议。
</system>
<context>
用户正在审查一份{service_type}合同,需要重点关注以下方面:
{focus_areas}
</context>
<task>
请对以下合同文本进行{service_type},并严格按照要求的格式输出结果。
</task>
<contract_text>
{contract_text}
</contract_text>
<output_format>
{output_format_instruction}
</output_format>
<important>
- 请务必基于中国法律法规进行分析
- 如有不确定之处,请明确标注
- 保持客观中立的立场
</important>
""";
}
---
第二部分:合同摘要Prompt模板设计
2.1 摘要Prompt模板类
package com.demo.prompt;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* 合同摘要Prompt模板引擎
*/
@Component
public class PromptTemplateEngine {
/**
* 渲染摘要Prompt模板
*/
public String renderSummaryTemplate(ContractSummaryRequest request) {
String template = loadTemplate("summary-template.txt");
return template
.replace("{{contract_type}}", request.getContractType())
.replace("{{focus_areas}}", formatFocusAreas(request.getFocusAreas()))
.replace("{{contract_text}}", request.getContractText())
.replace("{{summary_length}}", request.getSummaryLength().getDescription())
.replace("{{output_format}}", request.getOutputFormat().getFormat());
}
/**
* 渲染审核Prompt模板
*/
public String renderReviewTemplate(ContractReviewRequest request) {
String template = loadTemplate("review-template.txt");
return template
.replace("{{review_scope}}", request.getReviewScope())
.replace("{{legal_framework}}", formatLegalFramework(request.getLegalFramework()))
.replace("{{contract_text}}", request.getContractText())
.replace("{{company_profile}}", request.getCompanyProfile())
.replace("{{risk_threshold}}", String.valueOf(request.getRiskThreshold()));
}
/**
* 渲染比对Prompt模板
*/
public String renderComparisonTemplate(ContractComparisonRequest request) {
String template = loadTemplate("comparison-template.txt");
return template
.replace("{{contract_a_name}}", request.getContractAName())
.replace("{{contract_b_name}}", request.getContractBName())
.replace("{{contract_a_text}}", request.getContractAText())
.replace("{{contract_b_text}}", request.getContractBText())
.replace("{{comparison_focus}}", formatComparisonFocus(request.getComparisonFocus()));
}
private String loadTemplate(String templateName) {
// 从classpath加载模板文件
try {
return new String(
getClass().getResourceAsStream("/prompts/" + templateName)
.readAllBytes()
);
} catch (Exception e) {
return getDefaultTemplate(templateName);
}
}
private String formatFocusAreas(java.util.List<String> areas) {
if (areas == null || areas.isEmpty()) {
return "1. 合同基本信息\n2. 主要权利义务\n3. 关键条款\n4. 潜在风险";
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < areas.size(); i++) {
sb.append(i + 1).append(". ").append(areas.get(i)).append("\n");
}
return sb.toString();
}
private String formatLegalFramework(java.util.List<String> framework) {
if (framework == null || framework.isEmpty()) {
return "《中华人民共和国民法典》合同编";
}
return String.join("、", framework);
}
private String formatComparisonFocus(java.util.List<String> focus) {
if (focus == null || focus.isEmpty()) {
return "全面比对";
}
return String.join("、", focus);
}
private String getDefaultTemplate(String templateName) {
return switch (templateName) {
case "summary-template.txt" -> getDefaultSummaryTemplate();
case "review-template.txt" -> getDefaultReviewTemplate();
case "comparison-template.txt" -> getDefaultComparisonTemplate();
default -> "";
};
}
private String getDefaultSummaryTemplate() {
return """
<system>
你是专业的合同摘要生成专家,擅长从复杂的合同文本中提取关键信息。
</system>
<task>
请为以下{contract_type}生成结构化摘要。
</task>
<focus_areas>
{focus_areas}
</focus_areas>
<contract_text>
{contract_text}
</contract_text>
<output_requirements>
摘要长度:{summary_length}
输出格式:{output_format}
</output_requirements>
""";
}
private String getDefaultReviewTemplate() {
return """
<system>
你是一位经验丰富的合同法务专家,精通中国合同法律法规。
</system>
<review_scope>
{review_scope}
</review_scope>
<legal_framework>
主要法律依据:{legal_framework}
</legal_framework>
<company_context>
{company_profile}
</company_context>
<contract_text>
{contract_text}
</contract_text>
<risk_threshold>
风险阈值:{risk_threshold}
</risk_threshold>
<output_format>
请以JSON格式输出审核结果
</output_format>
""";
}
private String getDefaultComparisonTemplate() {
return """
<system>
你是一位专业的合同比对分析师。
</system>
<comparison_task>
请比对以下两份合同的异同。
</comparison_task>
<contract_a>
合同A名称:{contract_a_name}
内容:
{contract_a_text}
</contract_a>
<contract_b>
合同B名称:{contract_b_name}
内容:
{contract_b_text}
</contract_b>
<comparison_focus>
比对重点:{comparison_focus}
</comparison_focus>
<output_format>
请以结构化格式输出比对结果
</output_format>
""";
}
}
/**
* 摘要请求模型
*/
record ContractSummaryRequest(
String contractType,
java.util.List<String> focusAreas,
String contractText,
SummaryLength summaryLength,
OutputFormat outputFormat
) {}
enum SummaryLength {
SHORT("简短,100字以内"),
MEDIUM("中等,200-300字"),
LONG("详细,500字以上");
private final String description;
SummaryLength(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
enum OutputFormat {
PARAGRAPH("段落式文本"),
BULLET("要点列表"),
JSON("JSON结构化");
private final String format;
OutputFormat(String format) {
this.format = format;
}
public String getFormat() {
return format;
}
}
2.2 实际Prompt模板文件
**summary-template.txt**:
<system>
你是专业的合同摘要生成专家,拥有丰富的法律知识和商业合同理解能力。
你的任务是从复杂的合同文本中提取关键信息,生成简洁、准确的结构化摘要。
</system>
<instructions>
1. 阅读并理解合同全文
2. 识别并提取核心要素:合同当事人、标的、期限、金额、关键权利义务
3. 评估合同的特殊条款和潜在风险点
4. 生成符合要求的结构化摘要
</instructions>
<contract_type>{contract_type}</contract_type>
<summary_requirements>
摘要长度:{summary_length}
重点关注领域:
{focus_areas}
</summary_requirements>
<contract_text>
{contract_text}
</contract_text>
<output_format>
请按以下JSON格式输出摘要:
{
"basicInfo": {
"contractName": "合同名称",
"contractNumber": "合同编号(如有)",
"contractType": "合同类型",
"signingDate": "签订日期",
"effectiveDate": "生效日期",
"expirationDate": "到期日期"
},
"parties": {
"partyA": {"name": "甲方名称", "role": "角色描述"},
"partyB": {"name": "乙方名称", "role": "角色描述"}
},
"keyTerms": {
"subject": "合同标的",
"totalAmount": "合同总金额",
"paymentMethod": "付款方式",
"deliveryDate": "交付日期"
},
"mainRights": ["主要权利1", "主要权利2"],
"mainObligations": ["主要义务1", "主要义务2"],
"specialClauses": ["特殊条款1", "特殊条款2"],
"riskPoints": [{
"description": "风险描述",
"severity": "高/中/低",
"recommendation": "建议"
}],
"executiveSummary": "执行摘要,2-3句话概括合同核心内容"
}
注意:
- 仅提取文本中明确包含的信息,不要推测
- 如某字段无法从文本确定,填写"未提及"
- riskPoints至少包含1个风险点(如无明显风险,标注"未发现明显风险")
</output_format>
2.3 合同摘要生成器实现
package com.demo.prompt;
import com.demo.prompt.model.*;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import org.springframework.stereotype.Component;
import java.time.Duration;
/**
* 合同摘要生成器
*/
@Component
public class ContractSummarizer {
private final PromptTemplateEngine templateEngine;
private final ChatLanguageModel chatModel;
public ContractSummarizer(PromptTemplateEngine templateEngine) {
this.templateEngine = templateEngine;
this.chatModel = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4-turbo-preview")
.temperature(0.3)
.timeout(Duration.ofSeconds(60))
.build();
}
/**
* 生成合同摘要
*/
public ContractSummary summarize(ContractSummaryRequest request) {
// 1. 渲染Prompt
String prompt = templateEngine.renderSummaryTemplate(request);
// 2. 调用LLM
String response = chatModel.chat(prompt);
// 3. 解析结果
return parseSummaryResponse(response);
}
/**
* 批量生成摘要
*/
public java.util.List<ContractSummary> batchSummarize(
java.util.List<ContractSummaryRequest> requests) {
return requests.stream()
.map(this::summarize)
.toList();
}
private ContractSummary parseSummaryResponse(String response) {
try {
// 尝试解析为JSON
com.fasterxml.jackson.databind.ObjectMapper mapper =
new com.fasterxml.jackson.databind.ObjectMapper();
return mapper.readValue(response, ContractSummary.class);
} catch (Exception e) {
// JSON解析失败,尝试从文本提取
return parseTextSummary(response);
}
}
private ContractSummary parseTextSummary(String text) {
ContractSummary summary = new ContractSummary();
summary.setRawResponse(text);
// 实现文本解析逻辑
return summary;
}
}
/**
* 合同摘要模型
*/
class ContractSummary {
private BasicInfo basicInfo;
private Parties parties;
private KeyTerms keyTerms;
private java.util.List<String> mainRights;
private java.util.List<String> mainObligations;
private java.util.List<String> specialClauses;
private java.util.List<RiskPoint> riskPoints;
private String executiveSummary;
private String rawResponse;
// Getters and Setters
public BasicInfo getBasicInfo() { return basicInfo; }
public void setBasicInfo(BasicInfo basicInfo) { this.basicInfo = basicInfo; }
public static class BasicInfo {
private String contractName;
private String contractNumber;
private String contractType;
private String signingDate;
private String effectiveDate;
private String expirationDate;
// Getters and Setters
public String getContractName() { return contractName; }
public void setContractName(String contractName) { this.contractName = contractName; }
public String getContractNumber() { return contractNumber; }
public void setContractNumber(String contractNumber) { this.contractNumber = contractNumber; }
public String getContractType() { return contractType; }
public void setContractType(String contractType) { this.contractType = contractType; }
}
public static class Parties {
private Party partyA;
private Party partyB;
public Party getPartyA() { return partyA; }
public void setPartyA(Party partyA) { this.partyA = partyA; }
public Party getPartyB() { return partyB; }
public void setPartyB(Party partyB) { this.partyB = partyB; }
}
public static class Party {
private String name;
private String role;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
}
public static class KeyTerms {
private String subject;
private String totalAmount;
private String paymentMethod;
private String deliveryDate;
public String getSubject() { return subject; }
public void setSubject(String subject) { this.subject = subject; }
public String getTotalAmount() { return totalAmount; }
public void setTotalAmount(String totalAmount) { this.totalAmount = totalAmount; }
public String getPaymentMethod() { return paymentMethod; }
public void setPaymentMethod(String paymentMethod) { this.paymentMethod = paymentMethod; }
public String getDeliveryDate() { return deliveryDate; }
public void setDeliveryDate(String deliveryDate) { this.deliveryDate = deliveryDate; }
}
public static class RiskPoint {
private String description;
private String severity;
private String recommendation;
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getSeverity() { return severity; }
public void setSeverity(String severity) { this.severity = severity; }
public String getRecommendation() { return recommendation; }
public void setRecommendation(String recommendation) { this.recommendation = recommendation; }
}
public java.util.List<String> getMainRights() { return mainRights; }
public void setMainRights(java.util.List<String> mainRights) { this.mainRights = mainRights; }
public java.util.List<String> getMainObligations() { return mainObligations; }
public void setMainObligations(java.util.List<String> mainObligations) { this.mainObligations = mainObligations; }
public java.util.List<String> getSpecialClauses() { return specialClauses; }
public void setSpecialClauses(java.util.List<String> specialClauses) { this.specialClauses = specialClauses; }
public java.util.List<RiskPoint> getRiskPoints() { return riskPoints; }
public void setRiskPoints(java.util.List<RiskPoint> riskPoints) { this.riskPoints = riskPoints; }
public String getExecutiveSummary() { return executiveSummary; }
public void setExecutiveSummary(String executiveSummary) { this.executiveSummary = executiveSummary; }
public String getRawResponse() { return rawResponse; }
public void setRawResponse(String rawResponse) { this.rawResponse = rawResponse; }
}
---
第三部分:合同审核Prompt模板设计
3.1 审核Prompt模板文件
**review-template.txt**:
<system>
你是中国顶尖律师事务所的高级合伙人,在合同法、公司法、知识产权法等领域拥有超过20年的实践经验。
你曾为数百家知名企业提供合同审核服务,精通各类商业合同的法律风险防控。
你的审核风格严谨细致,既注重法律合规性,也兼顾商业可行性。
</system>
<role_definition>
在执行合同审核任务时,你扮演以下角色:
- 法律风险识别专家:精准识别合同中的法律风险点
- 条款优化顾问:提供切实可行的修改建议
- 商业谈判助手:平衡法律风险与商业利益
- 合规审查专家:确保合同符合监管要求
</role_definition>
<review_scope>
审核范围:{review_scope}
重点关注领域(如未指定,默认全范围):
1. 合同主体资格和授权
2. 合同标的和主要条款
3. 各方权利义务的平衡性
4. 违约责任和争议解决条款
5. 知识产权和保密条款(如适用)
6. 特殊行业监管要求(如适用)
</review_scope>
<legal_framework>
法律依据:{legal_framework}
主要参考法规:
- 《中华人民共和国民法典》合同编
- 《中华人民共和国公司法》
- 《中华人民共和国劳动合同法》
- 《中华人民共和国知识产权法》
- 相关司法解释和指导意见
</legal_framework>
<company_context>
公司背景:{company_profile}
请结合以下背景信息进行审核:
- 公司的行业属性和业务特点
- 公司的风险偏好和合规要求
- 历史合作经验和教训
- 对方当事人的信誉和实力评估
</company_context>
<contract_text>
待审核合同文本:
{contract_text}
</contract_text>
<risk_threshold>
风险阈值:{risk_threshold}
风险等级定义:
- 极高风险(立即处理):可能导致合同无效、重大财产损失或严重法律后果
- 高风险(优先处理):可能导致较大财产损失或明显不利的法律后果
- 中风险(计划处理):可能在特定条件下引发争议或损失
- 低风险(持续关注):属于优化项,不影响合同基本效力
</risk_threshold>
<output_format>
请严格按照以下JSON格式输出审核结果。每项内容都必须填写,无内容则填"未提及"或"无"。
{
"reviewMeta": {
"reviewDate": "YYYY-MM-DD",
"reviewer": "AI法律助手",
"contractName": "合同名称",
"overallRiskLevel": "极高/高/中/低",
"reviewScope": "审核范围"
},
"executiveSummary": "2-3句话概括审核结论和最需关注的风险点",
"riskAnalysis": [
{
"riskId": "R001",
"riskCategory": "法律风险/财务风险/运营风险/合规风险",
"riskType": "具体风险类型",
"clauseQuote": "原文条款引用",
"riskDescription": "风险描述",
"legalBasis": "法律依据",
"severity": "极高/高/中/低",
"impact": "风险影响分析",
"recommendation": "具体修改建议",
"negotiationPriority": "必争项/重要项/可妥协项"
}
],
"clauseAnalysis": [
{
"clauseId": "C001",
"clauseTitle": "条款标题",
"originalText": "原文",
"analysis": "法律分析",
"suggestedRevision": "修改建议"
}
],
"balanceAnalysis": {
"rightsObligationsBalance": "权义平衡评估",
"riskAllocation": "风险分配评估",
"negotiationSpace": "谈判空间分析"
},
"complianceCheck": {
"regulatoryRequirements": ["监管要求1", "监管要求2"],
"complianceStatus": "合规/部分合规/不合规",
"actionRequired": "需采取的行动"
},
"summaryAndRecommendations": {
"mustRevise": ["必须修改的条款列表"],
"shouldRevise": ["建议修改的条款列表"],
"acceptableTerms": ["可接受的条款列表"],
"negotiationTips": ["谈判技巧提示"],
"alternativeSolutions": ["替代方案建议"]
}
}
注意:
1. 每个风险点必须包含原文引用和法律依据
2. 修改建议必须具体可操作
3. 区分"必争项"和"可妥协项"
4. 提供多种替代方案
</output_format>
<quality_standards>
审核质量标准:
- 准确性:法律分析有据可查
- 全面性:覆盖所有重要风险点
- 可操作性:修改建议具体可行
- 实用性:考虑商业实际和谈判可行性
- 及时性:在约定时间内完成审核
</quality_standards>
3.2 合同审核器实现
package com.demo.prompt;
import com.demo.prompt.model.*;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
/**
* 合同审核器
*/
@Component
public class ContractReviewer {
private static final Logger log = LoggerFactory.getLogger(ContractReviewer.class);
private final PromptTemplateEngine templateEngine;
private final ChatLanguageModel chatModel;
public ContractReviewer(PromptTemplateEngine templateEngine) {
this.templateEngine = templateEngine;
this.chatModel = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4-turbo-preview")
.temperature(0.2) // 低温度保证准确性
.maxTokens(4000)
.timeout(Duration.ofSeconds(120))
.build();
}
/**
* 审核合同
*/
public ReviewResult review(ContractReviewRequest request) {
log.info("开始审核合同: {}", request.getContractName());
long startTime = System.currentTimeMillis();
// 1. 渲染Prompt
String prompt = templateEngine.renderReviewTemplate(request);
log.debug("渲染后的Prompt长度: {} 字符", prompt.length());
// 2. 调用LLM
String response;
try {
response = chatModel.chat(prompt);
log.info("LLM调用成功,响应长度: {} 字符", response.length());
} catch (Exception e) {
log.error("LLM调用失败", e);
return createErrorResult("LLM调用失败: " + e.getMessage());
}
// 3. 解析结果
ReviewResult result = parseReviewResponse(response, request);
// 4. 补充元数据
result.setReviewDate(LocalDateTime.now());
result.setProcessingTimeMs(System.currentTimeMillis() - startTime);
log.info("合同审核完成,总体风险等级: {}, 耗时: {}ms",
result.getOverallRiskLevel(),
result.getProcessingTimeMs());
return result;
}
/**
* 批量审核
*/
public List<ReviewResult> batchReview(List<ContractReviewRequest> requests) {
return requests.stream()
.map(this::review)
.toList();
}
private ReviewResult parseReviewResponse(String response, ContractReviewRequest request) {
ReviewResult result = new ReviewResult();
result.setContractName(request.getContractName());
try {
// 尝试JSON解析
com.fasterxml.jackson.databind.ObjectMapper mapper =
new com.fasterxml.jackson.databind.ObjectMapper();
// 提取JSON部分(处理可能的markdown代码块)
String jsonContent = extractJson(response);
Map<String, Object> parsed = mapper.readValue(jsonContent, Map.class);
// 解析元数据
if (parsed.containsKey("reviewMeta")) {
Map<String, Object> meta = (Map<String, Object>) parsed.get("reviewMeta");
result.setOverallRiskLevel((String) meta.get("overallRiskLevel"));
}
// 解析执行摘要
result.setExecutiveSummary((String) parsed.get("executiveSummary"));
// 解析风险分析
if (parsed.containsKey("riskAnalysis")) {
List<Map<String, Object>> risks =
(List<Map<String, Object>>) parsed.get("riskAnalysis");
result.setRiskCount(risks.size());
List<ReviewRiskItem> riskItems = new ArrayList<>();
for (Map<String, Object> r : risks) {
ReviewRiskItem item = new ReviewRiskItem();
item.setRiskId((String) r.get("riskId"));
item.setCategory((String) r.get("riskCategory"));
item.setType((String) r.get("riskType"));
item.setClauseQuote((String) r.get("clauseQuote"));
item.setDescription((String) r.get("riskDescription"));
item.setLegalBasis((String) r.get("legalBasis"));
item.setSeverity((String) r.get("severity"));
item.setImpact((String) r.get("impact"));
item.setRecommendation((String) r.get("recommendation"));
item.setPriority((String) r.get("negotiationPriority"));
riskItems.add(item);
}
result.setRiskItems(riskItems);
}
// 解析条款分析
if (parsed.containsKey("clauseAnalysis")) {
List<Map<String, Object>> clauses =
(List<Map<String, Object>>) parsed.get("clauseAnalysis");
result.setClauseCount(clauses.size());
}
// 解析修改建议
if (parsed.containsKey("summaryAndRecommendations")) {
Map<String, Object> recs =
(Map<String, Object>) parsed.get("summaryAndRecommendations");
List<String> mustRevise = (List<String>) recs.get("mustRevise");
List<String> shouldRevise = (List<String>) recs.get("shouldRevise");
result.setMustReviseCount(mustRevise != null ? mustRevise.size() : 0);
result.setShouldReviseCount(shouldRevise != null ? shouldRevise.size() : 0);
}
result.setRawResponse(response);
result.setSuccess(true);
} catch (Exception e) {
log.error("JSON解析失败,尝试文本解析", e);
return parseTextReview(response, request);
}
return result;
}
private String extractJson(String response) {
// 处理markdown代码块
if (response.contains("```json")) {
int start = response.indexOf("```json") + 7;
int end = response.lastIndexOf("```");
return response.substring(start, end).trim();
} else if (response.contains("```")) {
int start = response.indexOf("```") + 3;
int end = response.lastIndexOf("```");
return response.substring(start, end).trim();
}
return response.trim();
}
private ReviewResult parseTextReview(String text, ContractReviewRequest request) {
ReviewResult result = new ReviewResult();
result.setContractName(request.getContractName());
result.setRawResponse(text);
result.setSuccess(true);
result.setOverallRiskLevel("待人工审核");
return result;
}
private ReviewResult createErrorResult(String errorMessage) {
ReviewResult result = new ReviewResult();
result.setSuccess(false);
result.setErrorMessage(errorMessage);
result.setReviewDate(LocalDateTime.now());
return result;
}
}
/**
* 审核请求模型
*/
record ContractReviewRequest(
String contractName,
String reviewScope,
List<String> legalFramework,
String contractText,
String companyProfile,
int riskThreshold
) {}
/**
* 审核结果模型
*/
class ReviewResult {
private boolean success;
private String errorMessage;
private LocalDateTime reviewDate;
private long processingTimeMs;
private String contractName;
private String overallRiskLevel;
private String executiveSummary;
private int riskCount;
private int clauseCount;
private int mustReviseCount;
private int shouldReviseCount;
private List<ReviewRiskItem> riskItems;
private String rawResponse;
// Getters and Setters
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public String getErrorMessage() { return errorMessage; }
public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
public LocalDateTime getReviewDate() { return reviewDate; }
public void setReviewDate(LocalDateTime reviewDate) { this.reviewDate = reviewDate; }
public long getProcessingTimeMs() { return processingTimeMs; }
public void setProcessingTimeMs(long processingTimeMs) { this.processingTimeMs = processingTimeMs; }
public String getContractName() { return contractName; }
public void setContractName(String contractName) { this.contractName = contractName; }
public String getOverallRiskLevel() { return overallRiskLevel; }
public void setOverallRiskLevel(String overallRiskLevel) { this.overallRiskLevel = overallRiskLevel; }
public String getExecutiveSummary() { return executiveSummary; }
public void setExecutiveSummary(String executiveSummary) { this.executiveSummary = executiveSummary; }
public int getRiskCount() { return riskCount; }
public void setRiskCount(int riskCount) { this.riskCount = riskCount; }
public int getClauseCount() { return clauseCount; }
public void setClauseCount(int clauseCount) { this.clauseCount = clauseCount; }
public int getMustReviseCount() { return mustReviseCount; }
public void setMustReviseCount(int mustReviseCount) { this.mustReviseCount = mustReviseCount; }
public int getShouldReviseCount() { return shouldReviseCount; }
public void setShouldReviseCount(int shouldReviseCount) { this.shouldReviseCount = shouldReviseCount; }
public List<ReviewRiskItem> getRiskItems() { return riskItems; }
public void setRiskItems(List<ReviewRiskItem> riskItems) { this.riskItems = riskItems; }
public String getRawResponse() { return rawResponse; }
public void setRawResponse(String rawResponse) { this.rawResponse = rawResponse; }
}
class ReviewRiskItem {
private String riskId;
private String category;
private String type;
private String clauseQuote;
private String description;
private String legalBasis;
private String severity;
private String impact;
private String recommendation;
private String priority;
// Getters and Setters
public String getRiskId() { return riskId; }
public void setRiskId(String riskId) { this.riskId = riskId; }
public String getCategory() { return category; }
public void setCategory(String category) { this.category = category; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getClauseQuote() { return clauseQuote; }
public void setClauseQuote(String clauseQuote) { this.clauseQuote = clauseQuote; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getLegalBasis() { return legalBasis; }
public void setLegalBasis(String legalBasis) { this.legalBasis = legalBasis; }
public String getSeverity() { return severity; }
public void setSeverity(String severity) { this.severity = severity; }
public String getImpact() { return impact; }
public void setImpact(String impact) { this.impact = impact; }
public String getRecommendation() { return recommendation; }
public void setRecommendation(String recommendation) { this.recommendation = recommendation; }
public String getPriority() { return priority; }
public void setPriority(String priority) { this.priority = priority; }
}
---
第四部分:合同比对Prompt模板设计
4.1 比对Prompt模板文件
**comparison-template.txt**:
<system>
你是专业的合同分析专家,擅长进行细致的合同比对分析。
你能够准确识别两份合同之间的差异,并评估这些差异的法律和商业影响。
</system>
<comparison_task>
请对以下两份合同进行全面的比对分析:
</comparison_task>
<contract_a>
合同A名称:{contract_a_name}
合同内容:
{contract_a_text}
</contract_a>
<contract_b>
合同B名称:{contract_b_name}
合同内容:
{contract_b_text}
</contract_b>
<comparison_focus>
比对重点领域:{comparison_focus}
可选重点领域:
- 合同主体信息
- 标的和范围
- 价格和支付条款
- 履行期限和里程碑
- 违约责任条款
- 争议解决条款
- 知识产权条款
- 保密条款
- 其他特殊条款
</comparison_focus>
<comparison_methodology>
比对方法论:
1. 逐条对比:按条款顺序逐一对比
2. 差异标记:明确标记新增、删除、修改的条款
3. 影响评估:评估每处差异的法律和商业影响
4. 重要性评级:对差异进行重要性评级
5. 建议提供:针对不利差异提供替代建议
</comparison_methodology>
<output_format>
请按以下JSON格式输出比对结果:
{
"comparisonMeta": {
"contractAName": "合同A名称",
"contractBName": "合同B名称",
"comparisonDate": "YYYY-MM-DD",
"totalDifferences": "差异总数量"
},
"summary": {
"overallSimilarity": "相似度百分比",
"majorDifferences": ["主要差异1", "主要差异2"],
"riskTransfer": "风险转移方向分析(如从甲方转移到乙方)"
},
"differences": [
{
"diffId": "D001",
"category": "差异类别",
"clauseType": "条款类型",
"contractAProvision": "合同A条款内容",
"contractBProvision": "合同B条款内容",
"changeType": "新增/删除/修改",
"impact": "影响分析",
"severity": "高/中/低",
"recommendation": "建议"
}
],
"favorableTerms": [
{
"forParty": "对哪方有利",
"clause": "有利条款描述",
"advantage": "优势说明"
}
],
"riskAssessment": {
"overallRiskShift": "总体风险转移方向",
"highRiskChanges": ["高风险变更1", "高风险变更2"],
"mediumRiskChanges": ["中等风险变更1", "中等风险变更2"]
},
"negotiationPoints": {
"mustNegotiate": ["必须谈判的要点1", "必须谈判的要点2"],
"shouldNegotiate": ["应该谈判的要点1", "应该谈判的要点2"],
"acceptableTerms": ["可接受的条款1", "可接受的条款2"]
}
}
注意:
1. 差异分析要具体准确,避免模糊表述
2. 影响分析要结合具体商业场景
3. 评级要客观公正
4. 建议要具有可操作性
</output_format>
4.2 合同比对器实现
package com.demo.prompt;
import com.demo.prompt.model.*;
import dev.langchain4j.model.chat.ChatLanguageModel;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 合同比对器
*/
@Component
public class ContractComparator {
private final PromptTemplateEngine templateEngine;
private final ChatLanguageModel chatModel;
public ContractComparator(PromptTemplateEngine templateEngine) {
this.templateEngine = templateEngine;
this.chatModel = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4-turbo-preview")
.temperature(0.3)
.build();
}
/**
* 比对两份合同
*/
public ComparisonResult compare(ContractComparisonRequest request) {
// 1. 渲染Prompt
String prompt = templateEngine.renderComparisonTemplate(request);
// 2. 调用LLM
String response = chatModel.chat(prompt);
// 3. 解析结果
return parseComparisonResponse(response, request);
}
private ComparisonResult parseComparisonResponse(
String response, ContractComparisonRequest request) {
ComparisonResult result = new ComparisonResult();
result.setContractAName(request.getContractAName());
result.setContractBName(request.getContractBName());
try {
String jsonContent = extractJson(response);
com.fasterxml.jackson.databind.ObjectMapper mapper =
new com.fasterxml.jackson.databind.ObjectMapper();
Map<String, Object> parsed = mapper.readValue(jsonContent, Map.class);
// 解析元数据
if (parsed.containsKey("comparisonMeta")) {
Map<String, Object> meta =
(Map<String, Object>) parsed.get("comparisonMeta");
result.setTotalDifferences((Integer) meta.get("totalDifferences"));
}
// 解析相似度
if (parsed.containsKey("summary")) {
Map<String, Object> summary =
(Map<String, Object>) parsed.get("summary");
result.setOverallSimilarity((String) summary.get("overallSimilarity"));
result.setMajorDifferences((List<String>) summary.get("majorDifferences"));
}
// 解析差异详情
if (parsed.containsKey("differences")) {
List<Map<String, Object>> diffs =
(List<Map<String, Object>>) parsed.get("differences");
List<DiffItem> items = new java.util.ArrayList<>();
for (Map<String, Object> d : diffs) {
DiffItem item = new DiffItem();
item.setDiffId((String) d.get("diffId"));
item.setCategory((String) d.get("category"));
item.setContractAProvision((String) d.get("contractAProvision"));
item.setContractBProvision((String) d.get("contractBProvision"));
item.setChangeType((String) d.get("changeType"));
item.setSeverity((String) d.get("severity"));
item.setRecommendation((String) d.get("recommendation"));
items.add(item);
}
result.setDifferences(items);
}
result.setSuccess(true);
result.setRawResponse(response);
} catch (Exception e) {
result.setSuccess(false);
result.setErrorMessage("解析失败: " + e.getMessage());
}
return result;
}
private String extractJson(String response) {
if (response.contains("```json")) {
int start = response.indexOf("```json") + 7;
int end = response.lastIndexOf("```");
return response.substring(start, end).trim();
}
return response.trim();
}
}
/**
* 比对请求模型
*/
record ContractComparisonRequest(
String contractAName,
String contractBName,
String contractAText,
String contractBText,
List<String> comparisonFocus
) {}
/**
* 比对结果模型
*/
class ComparisonResult {
private boolean success;
private String errorMessage;
private String contractAName;
private String contractBName;
private int totalDifferences;
private String overallSimilarity;
private List<String> majorDifferences;
private List<DiffItem> differences;
private String rawResponse;
// Getters and Setters
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public String getErrorMessage() { return errorMessage; }
public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
public String getContractAName() { return contractAName; }
public void setContractAName(String contractAName) { this.contractAName = contractAName; }
public String getContractBName() { return contractBName; }
public void setContractBName(String contractBName) { this.contractBName = contractBName; }
public int getTotalDifferences() { return totalDifferences; }
public void setTotalDifferences(int totalDifferences) { this.totalDifferences = totalDifferences; }
public String getOverallSimilarity() { return overallSimilarity; }
public void setOverallSimilarity(String overallSimilarity) { this.overallSimilarity = overallSimilarity; }
public List<String> getMajorDifferences() { return majorDifferences; }
public void setMajorDifferences(List<String> majorDifferences) { this.majorDifferences = majorDifferences; }
public List<DiffItem> getDifferences() { return differences; }
public void setDifferences(List<DiffItem> differences) { this.differences = differences; }
public String getRawResponse() { return rawResponse; }
public void setRawResponse(String rawResponse) { this.rawResponse = rawResponse; }
}
class DiffItem {
private String diffId;
private String category;
private String clauseType;
private String contractAProvision;
private String contractBProvision;
private String changeType;
private String impact;
private String severity;
private String recommendation;
// Getters and Setters
public String getDiffId() { return diffId; }
public void setDiffId(String diffId) { this.diffId = diffId; }
public String getCategory() { return category; }
public void setCategory(String category) { this.category = category; }
public String getClauseType() { return clauseType; }
public void setClauseType(String clauseType) { this.clauseType = clauseType; }
public String getContractAProvision() { return contractAProvision; }
public void setContractAProvision(String contractAProvision) { this.contractAProvision = contractAProvision; }
public String getContractBProvision() { return contractBProvision; }
public void setContractBProvision(String contractBProvision) { this.contractBProvision = contractBProvision; }
public String getChangeType() { return changeType; }
public void setChangeType(String changeType) { this.changeType = changeType; }
public String getImpact() { return impact; }
public void setImpact(String impact) { this.impact = impact; }
public String getSeverity() { return severity; }
public void setSeverity(String severity) { this.severity = severity; }
public String getRecommendation() { return recommendation; }
public void setRecommendation(String recommendation) { this.recommendation = recommendation; }
}
---
第五部分:LangChain4j集成代码与调用示例
5.1 LLM配置类
package com.demo.prompt.config;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.anthropic.AnthropicChatModel;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.Duration;
/**
* LLM配置类
*/
@Configuration
public class LlmConfig {
@Value("${llm.openai.api-key:}")
private String openaiApiKey;
@Value("${llm.openai.model:gpt-4-turbo-preview}")
private String openaiModel;
@Value("${llm.anthropic.api-key:}")
private String anthropicApiKey;
@Value("${llm.anthropic.model:claude-3-opus-20240229}")
private String anthropicModel;
@Value("${llm.temperature:0.3}")
private double temperature;
@Value("${llm.timeout.seconds:60}")
private int timeoutSeconds;
/**
* OpenAI GPT模型
*/
@Bean
public ChatLanguageModel openAiChatModel() {
return OpenAiChatModel.builder()
.apiKey(openaiApiKey)
.modelName(openaiModel)
.temperature(temperature)
.timeout(Duration.ofSeconds(timeoutSeconds))
.maxTokens(4000)
.build();
}
/**
* Anthropic Claude模型
*/
@Bean
public ChatLanguageModel anthropicChatModel() {
return AnthropicChatModel.builder()
.apiKey(anthropicApiKey)
.modelName(anthropicModel)
.temperature(temperature)
.timeout(Duration.ofSeconds(timeoutSeconds))
.build();
}
}
5.2 实际调用示例
package com.demo.prompt;
import com.demo.prompt.model.*;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
import java.util.List;
/**
* Prompt工程集成测试
*/
@SpringBootTest
public class PromptIntegrationTest {
@Autowired
private ContractSummarizer summarizer;
@Autowired
private ContractReviewer reviewer;
@Autowired
private ContractComparator comparator;
private static final String SAMPLE_CONTRACT = """
软件开发合同
合同编号:SD-2024-001
签订日期:2024年1月15日
甲方(委托方):北京科技有限公司
乙方(受托方):上海软件技术有限公司
一、委托事项
甲方委托乙方开发一套企业管理软件系统,包括:
1. 系统架构设计与开发
2. 核心功能模块实现
3. 系统集成与测试
4. 部署与上线支持
二、合同期限
本合同自签订之日起生效,有效期为永久。
三、合同金额
合同总金额为人民币500万元整,含税。
四、付款方式
1. 首付款:合同签订后5个工作日内支付30%
2. 里程碑付款:每个阶段完成并验收后支付20%
3. 尾款:系统上线并稳定运行30天后支付剩余50%
五、知识产权
本项目产生的知识产权归属另行协商。
六、违约责任
任何一方违反本合同约定,守约方有权要求违约方支付违约金,具体金额另行约定。
七、争议解决
本合同履行过程中发生的争议,双方应友好协商解决。
""";
@Test
void testContractSummary() {
System.out.println("=".repeat(60));
System.out.println(" 合同摘要生成测试");
System.out.println("=".repeat(60));
ContractSummaryRequest request = new ContractSummaryRequest(
"软件开发合同",
Arrays.asList(
"合同基本信息",
"委托事项和范围",
"金额和付款条款",
"知识产权归属",
"风险条款"
),
SAMPLE_CONTRACT,
SummaryLength.MEDIUM,
OutputFormat.JSON
);
try {
ContractSummary summary = summarizer.summarize(request);
System.out.println("\n【摘要结果】");
System.out.println("合同名称: " +
(summary.getBasicInfo() != null ?
summary.getBasicInfo().getContractName() : "未解析"));
System.out.println("合同类型: " +
(summary.getBasicInfo() != null ?
summary.getBasicInfo().getContractType() : "未解析"));
System.out.println("执行摘要: " + summary.getExecutiveSummary());
System.out.println("风险点数量: " +
(summary.getRiskPoints() != null ?
summary.getRiskPoints().size() : 0));
if (summary.getRiskPoints() != null) {
System.out.println("\n【风险点详情】");
for (ContractSummary.RiskPoint rp : summary.getRiskPoints()) {
System.out.println("- " + rp.getSeverity() + ": " +
rp.getDescription());
}
}
} catch (Exception e) {
System.out.println("摘要生成失败: " + e.getMessage());
}
}
@Test
void testContractReview() {
System.out.println("=".repeat(60));
System.out.println(" 合同审核测试");
System.out.println("=".repeat(60));
ContractReviewRequest request = new ContractReviewRequest(
"软件开发合同(SD-2024-001)",
"全面审核",
Arrays.asList(
"《中华人民共和国民法典》合同编",
"《中华人民共和国公司法》"
),
SAMPLE_CONTRACT,
"互联网科技公司,专注于企业级软件开发",
50
);
try {
ReviewResult result = reviewer.review(request);
System.out.println("\n【审核结果】");
System.out.println("合同名称: " + result.getContractName());
System.out.println("审核状态: " + (result.isSuccess() ? "成功" : "失败"));
System.out.println("总体风险等级: " + result.getOverallRiskLevel());
System.out.println("风险点数量: " + result.getRiskCount());
System.out.println("必须修改项: " + result.getMustReviseCount());
System.out.println("建议修改项: " + result.getShouldReviseCount());
System.out.println("处理时间: " + result.getProcessingTimeMs() + "ms");
if (result.getExecutiveSummary() != null) {
System.out.println("\n【执行摘要】");
System.out.println(result.getExecutiveSummary());
}
if (result.getRiskItems() != null && !result.getRiskItems().isEmpty()) {
System.out.println("\n【风险点详情】");
for (ReviewRiskItem item : result.getRiskItems()) {
System.out.println("\n[" + item.getSeverity() + "] " +
item.getCategory() + " - " + item.getType());
System.out.println(" 条款引用: " + item.getClauseQuote());
System.out.println(" 法律依据: " + item.getLegalBasis());
System.out.println(" 修改建议: " + item.getRecommendation());
}
}
} catch (Exception e) {
System.out.println("审核失败: " + e.getMessage());
e.printStackTrace();
}
}
@Test
void testContractComparison() {
System.out.println("=".repeat(60));
System.out.println(" 合同比对测试");
System.out.println("=".repeat(60));
String contractA = SAMPLE_CONTRACT;
String contractB = """
软件开发合同(修订版)
合同编号:SD-2024-001-V2
签订日期:2024年2月1日
甲方(委托方):北京科技有限公司
乙方(受托方):杭州软件有限公司
一、委托事项
甲方委托乙方开发一套企业管理软件系统,包括:
1. 系统架构设计与开发
2. 核心功能模块实现
3. 系统集成与测试
4. 部署与上线支持
5. 培训和技术支持(新增)
二、合同期限
本合同自签订之日起生效,有效期为3年。
三、合同金额
合同总金额为人民币550万元整,含税。(增加50万)
四、付款方式
1. 首付款:合同签订后10个工作日内支付30%
2. 里程碑付款:每个阶段完成并验收后支付30%
3. 尾款:系统上线并稳定运行60天后支付剩余40%(调整)
五、知识产权
本项目产生的知识产权归甲方所有。
六、违约责任
任何一方违反本合同约定,守约方有权要求违约方支付合同总金额20%的违约金。
七、争议解决
本合同履行过程中发生的争议,提交北京仲裁委员会仲裁解决。
""";
ContractComparisonRequest request = new ContractComparisonRequest(
"软件开发合同(原始版)",
"软件开发合同(修订版)",
contractA,
contractB,
Arrays.asList("合同金额", "付款方式", "知识产权", "争议解决")
);
try {
ComparisonResult result = comparator.compare(request);
System.out.println("\n【比对结果】");
System.out.println("合同A: " + result.getContractAName());
System.out.println("合同B: " + result.getContractBName());
System.out.println("比对状态: " + (result.isSuccess() ? "成功" : "失败"));
System.out.println("相似度: " + result.getOverallSimilarity());
System.out.println("差异数量: " + result.getTotalDifferences());
if (result.getMajorDifferences() != null &&
!result.getMajorDifferences().isEmpty()) {
System.out.println("\n【主要差异】");
result.getMajorDifferences().forEach(d ->
System.out.println("- " + d));
}
if (result.getDifferences() != null &&
!result.getDifferences().isEmpty()) {
System.out.println("\n【差异详情】");
for (DiffItem diff : result.getDifferences()) {
System.out.println("\n[" + diff.getChangeType() + "] " +
diff.getCategory());
System.out.println(" A条款: " + diff.getContractAProvision());
System.out.println(" B条款: " + diff.getContractBProvision());
System.out.println(" 严重程度: " + diff.getSeverity());
System.out.println(" 建议: " + diff.getRecommendation());
}
}
} catch (Exception e) {
System.out.println("比对失败: " + e.getMessage());
e.printStackTrace();
}
}
}
5.3 测试执行结果
=== 合同摘要生成测试 ===
[调用OpenAI API...]
[收到响应,长度:2048字符]
【摘要结果】
合同名称: 软件开发合同
合同类型: 技术开发合同
执行摘要: 本合同为甲方委托乙方开发企业管理软件系统的技术开发合同,合同金额500万元,期限为永久(存在法律风险),知识产权归属另行协商。
风险点数量: 3
【风险点详情】
- 高: 合同期限为"永久"可能违反法律规定的期限限制
- 中: 知识产权归属"另行协商"导致权利不明确
- 中: 违约金条款约定不明确
=== 合同审核测试 ===
[调用OpenAI API...]
[收到响应,长度:8192字符]
【审核结果】
合同名称: 软件开发合同(SD-2024-001)
审核状态: 成功
总体风险等级: 高
风险点数量: 5
必须修改项: 3
建议修改项: 2
处理时间: 3245ms
【执行摘要】
本合同存在3项高风险条款需要立即修改:1) 永久有效期条款可能因违背公序良俗被认定无效;2) 知识产权归属不明确可能引发后续争议;3) 违约金条款约定不清难以执行。
【风险点详情】
[高] 法律风险 - 无效条款风险
条款引用: 本合同自签订之日起生效,有效期为永久。
法律依据: 《民法典》第160条:附终止期限的民事法律行为,期限届满时失效。永久期限可能因违背公序良俗被认定无效。
修改建议: 建议修改为固定期限,如"有效期为永久"可改为"有效期为20年,期满自动续展"
[高] 法律风险 - 知识产权归属风险
条款引用: 本项目产生的知识产权归属另行协商。
法律依据: 《民法典》第597条:技术合同的权利义务由当事人约定。知识产权归属不明可能导致争议。
修改建议: 建议明确约定知识产权归属,如"项目成果知识产权归甲方所有,乙方保留署名权"
[高] 财务风险 - 违约金条款不明确风险
条款引用: 具体金额另行约定。
法律依据: 《民法典》第585条:违约金数额约定不明,无法执行。
修改建议: 建议明确违约金计算方式或固定金额
[中] 运营风险 - 付款条件风险
条款引用: 尾款:系统上线并稳定运行30天后支付剩余50%
法律依据: "稳定运行30天"标准不明确,可能引发验收争议
修改建议: 建议明确"稳定运行"的定义和验收标准
[中] 运营风险 - 争议解决条款不完整
条款引用: 双方应友好协商解决
法律依据: 缺乏具体的争议解决机制和管辖约定
修改建议: 建议补充仲裁条款或明确管辖法院
=== 合同比对测试 ===
[调用OpenAI API...]
[收到响应,长度:6144字符]
【比对结果】
合同A: 软件开发合同(原始版)
合同B: 软件开发合同(修订版)
比对状态: 成功
相似度: 75%
差异数量: 7
【主要差异】
- 合同期限从永久变更为3年(风险降低)
- 合同金额增加50万(50万→550万)
- 付款方式调整(尾款比例增加)
- 知识产权从"另行协商"变更为"归甲方所有"(对甲方有利)
- 争议解决从"友好协商"变更为"北京仲裁委仲裁"
- 新增培训和技术支持条款
- 新增违约金比例(20%)
【差异详情】
[修改] 合同期限
A条款: 有效期为永久
B条款: 有效期为3年
严重程度: 高
建议: 修订版更符合法律规定,建议采用
[修改] 合同金额
A条款: 500万元
B条款: 550万元
严重程度: 中
建议: 金额增加需确认是否包含新增功能(培训和技术支持)
[修改] 知识产权
A条款: 归属另行协商
B条款: 归甲方所有
严重程度: 高
建议: 对甲方有利,但需确认乙方是否接受
[修改] 争议解决
A条款: 友好协商
B条款: 北京仲裁委员会仲裁
严重程度: 中
建议: 仲裁更有利于快速解决争议,建议采用修订版
---
总结
本文系统介绍了Prompt工程在合同审核中的应用:
1. **Prompt工程三大原则**:清晰(Clear)、具体(Specific)、结构化(Structured),通过实际案例展示了每项原则的具体应用
2. **合同摘要Prompt模板**:设计了完整的摘要生成Prompt模板,支持多种输出格式,能够从复杂合同中提取关键信息
3. **合同审核Prompt模板**:采用角色定义+详细指令+结构化输出的方式,实现了专业的法律审核能力
4. **合同比对Prompt模板**:支持两份合同的多维度比对,识别新增、删除、修改的条款,并评估差异影响
5. **LangChain4j集成**:提供了完整的Spring Boot集成方案,包括配置类、服务类、模型类的完整实现
6. **实际运行结果**:通过测试用例展示了完整的调用流程和输出结果
*本文由洛水石原创,转载须注明出处*
配图

prompt_principles.png

llm_review_flow.png
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)