概述

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

Logo

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

更多推荐