ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于DeepSeek API的法律文书自动化:从460页模板到提示词工程

基于DeepSeek API的法律文书自动化:从460页模板到提示词工程 简介这份460页PDF面向法律从业者、法律科技产品经理与提示词工程学习者聚焦法律文书自动化落地难、模板复用率低的痛点以DeepSeek为技术底座系统梳理提示词工程在法律场景的适配方法。内容覆盖合同审查、起诉状起草、答辩状生成、法律意见书等12大核心场景包含风险条款识别、条款合规性校验、当事人信息结构化提取、诉讼请求规范化、证据清单关联匹配、反驳逻辑构建、法规检索关联等100余个高频模板并配套15合同类型、20案由、10典型纠纷的专项实例。资源包共1个PDF文件约13.33MB支持目录章节跳转、阅读器左侧书签大纲显示与章节快速定位文字、图表、目录均显示正常。已有109人学习下载。读者可借此掌握法律术语库与提示词交互设计、语义与逻辑层适配原理直接复用模板提升文书起草与审查效率适合作为法律科技入门到进阶的案头参考。1. 法律文书自动化从 460 页模板到可跑通的提示词工程一份 460 页的 PDF标题写着「12 大核心场景、100 高频模板」第一次看到这类材料的人容易走两个极端要么当成万能药直接复制粘贴要么觉得不过是把合同模板换了个壳。真正在一线做过法律文书自动化的人会告诉你这类方案的价值不在模板本身而在于它把「法律写作的隐性规则」显式化成了提示词结构。法律文书有极强的格式约束、术语约束和逻辑约束——一份起诉状的事实与理由部分段落顺序、称谓、金额大小写、法条引用格式都有硬性要求这些恰好是提示词工程最擅长固化的东西。这篇笔记拆的是怎么把一份 460 页的模板集变成一套能接 DeepSeek API、能批量产出、能人工复核的自动化流水线适合法务、律师助理、法律科技方向的工程师以及想用提示词工程啃下垂直领域的人。2. 拆解 460 页模板12 大场景怎么映射成提示词模块拿到一份几百页的模板集第一反应不该是「怎么全部塞进模型」而是先做结构化拆解。法律文书的本质是「事实 法律依据 请求」的三段式不同场景的差异集中在事实描述方式和法条引用范围上。把 12 大场景按这个维度切开你会发现很多模板共享同一套骨架真正需要单独写提示词的部分并不多。2.1 按文书类型归类而不是按页数归类460 页里通常混着起诉状、答辩状、代理词、法律意见书、合同审查意见、律师函、证据清单、执行申请书等。按页数顺序读是低效的正确做法是先建一张场景映射表把每类文书拆成「固定结构」和「可变字段」两部分。文书类型固定结构可变字段提示词复用度起诉状当事人信息、诉讼请求、事实与理由、证据清单案由、金额、时间线、法条高答辩状答辩人信息、答辩意见、事实反驳争议焦点、反证高法律意见书背景、分析、结论、风险提示交易结构、适用法律中合同审查意见条款逐条意见、修改建议合同类型、风险等级中律师函函告事项、法律依据、要求违约事实、期限高这张表的意义在于复用度高的类型可以共用一套系统提示词只在用户提示词里替换字段复用度低的类型需要单独设计推理链。100 模板听起来多按这个维度压缩后真正需要独立提示词的可能只有 20 到 30 套。2.2 把模板里的「填空位」翻译成变量声明法律模板里大量出现「____」「[ ]」「XX」这类占位符直接丢给模型它会瞎猜。正确做法是把每个占位符显式声明成变量并在提示词里给出类型和约束。比如金额字段要区分「数字」和「大写」日期要区分「行为日」和「起诉日」当事人要区分「自然人」和「法人」。# 把模板占位符转成结构化变量声明 template_vars { plaintiff_name: {type: str, desc: 原告全称自然人写姓名法人写工商登记名称}, plaintiff_type: {type: enum, values: [自然人, 法人, 非法人组织]}, claim_amount: {type: float, desc: 诉讼请求金额单位元保留两位小数}, claim_amount_cn: {type: str, desc: 金额中文大写由 claim_amount 自动生成}, fact_timeline: {type: list[dict], desc: 事实时间线每项含 date 和 event}, legal_basis: {type: list[str], desc: 引用的法条格式如《民法典》第X条} }这段声明的逻辑是把「模型需要猜的东西」变成「模型必须按格式填的东西」。参数上type决定校验方式enum类型要在后处理阶段做白名单校验list[dict]这种嵌套结构要在提示词里给出一个示例否则模型容易输出成字符串。金额大写这种确定性计算不要交给模型用 Python 的cn2an或自己写转换函数更稳。2.3 用系统提示词锁死格式用用户提示词注入事实很多人写法律提示词喜欢把所有要求塞进一段话结果模型顾此失彼。更可靠的分层是系统提示词只负责「角色 格式 禁止事项」用户提示词只负责「本案事实 变量值」。SYSTEM_PROMPT 你是一名执业十年以上的中国诉讼律师负责起草法律文书。 输出必须严格遵循以下规则 1. 只输出文书正文不输出解释、不输出 Markdown 标题符号。 2. 当事人称谓全文统一首次出现用全称之后用简称。 3. 法条引用格式为《法律名称》第X条第X款不得编造法条。 4. 金额同时给出阿拉伯数字和中文大写。 5. 事实部分按时间顺序叙述每段不超过 200 字。 如信息不足在对应位置输出【待补充具体缺什么】不要编造。 USER_PROMPT_TEMPLATE 请根据以下信息起草一份民事起诉状 原告{plaintiff_name}{plaintiff_type} 被告{defendant_name} 诉讼请求{claims} 事实与理由{facts} 证据{evidence_list} 系统提示词里的「不得编造法条」和「信息不足输出待补充」是两条血泪经验。法律场景对幻觉的容忍度极低一条编造的法条可能让整份文书作废。参数上temperature建议设在 0.2 到 0.4 之间太低会导致表达僵硬太高会引入不可控措辞。max_tokens按文书类型给起诉状一般 2000 到 4000 够用法律意见书可能要 6000 以上。3. 接 DeepSeek API 跑通第一份文书调用、参数与批处理模板拆完下一步是让它真的跑起来。DeepSeek 的 API 兼容 OpenAI 的调用格式这对已经有 OpenAI SDK 的项目很友好改个base_url和model就能切换。但法律文书场景有几个特殊参数需要单独调直接套默认值会翻车。3.1 最小可运行调用一份起诉状的完整链路先跑通单份文书确认格式和内容都对再考虑批处理。下面是最小调用示例包含变量填充、API 调用和结果落盘。import os import json from openai import OpenAI client OpenAI( api_keyos.environ[DEEPSEEK_API_KEY], base_urlhttps://api.deepseek.com/v1 # DeepSeek 兼容 OpenAI 格式 ) def generate_document(doc_type: str, variables: dict) - str: system_prompt SYSTEM_PROMPTS[doc_type] user_prompt USER_PROMPT_TEMPLATES[doc_type].format(**variables) response client.chat.completions.create( modeldeepseek-chat, messages[ {role: system, content: system_prompt}, {role: user, content: user_prompt} ], temperature0.3, # 法律文书要稳不要创意 max_tokens4096, top_p0.9, frequency_penalty0.1 # 轻微惩罚重复避免套话堆砌 ) return response.choices[0].message.content if __name__ __main__: variables { plaintiff_name: 张三, plaintiff_type: 自然人, defendant_name: 某某科技有限公司, claims: 1. 判令被告支付拖欠工资 85000 元2. 判令被告支付经济补偿金 21250 元。, facts: 原告于 2022 年 3 月入职被告公司……, evidence_list: 劳动合同、工资流水、考勤记录、解除通知 } result generate_document(起诉状, variables) with open(output/起诉状_张三.json, w, encodingutf-8) as f: json.dump({content: result, variables: variables}, f, ensure_asciiFalse, indent2)逻辑说明base_url指向 DeepSeek 的兼容端点model用deepseek-chat对应通用对话模型。参数上temperature0.3是法律文书的稳妥区间frequency_penalty0.1用来压制「综上所述」「众所周知」这类模型爱用的套话。落盘时把变量一起存下来是为了后续复核时能追溯「哪句话是根据哪个字段生成的」这个后悔药一定要留。3.2 批处理时的并发控制和失败重试单份跑通后实际场景往往是几十上百份一起生成。直接开多线程打 API 会遇到限流而且法律文书生成耗时长失败重试必须做。import time from concurrent.futures import ThreadPoolExecutor, as_completed def generate_with_retry(doc_type, variables, max_retries3): for attempt in range(max_retries): try: return generate_document(doc_type, variables) except Exception as e: if attempt max_retries - 1: raise # 指数退避避免触发限流 time.sleep(2 ** attempt) return None def batch_generate(tasks, max_workers4): results [] with ThreadPoolExecutor(max_workersmax_workers) as executor: futures {executor.submit(generate_with_retry, t[type], t[vars]): t for t in tasks} for future in as_completed(futures): task futures[future] try: results.append({task: task, content: future.result(), status: ok}) except Exception as e: results.append({task: task, error: str(e), status: failed}) return results参数上max_workers不要超过 4 到 6法律文书单次生成动辄十几秒并发太高反而容易触发服务端限流。指数退避的基数用 2 秒起步重试三次基本能覆盖偶发的网络抖动。失败的任务要单独落盘不要静默丢弃否则批量跑完发现少了几份排查起来很痛苦。3.3 输出后处理格式校验和法条核验模型输出不能直接当成品必须过两道校验。第一道是格式校验检查当事人称谓是否统一、金额大小写是否一致、段落数是否合理。第二道是法条核验把输出里所有《XX法》第X条抽出来和本地法条库比对。import re def validate_output(text: str, variables: dict) - dict: issues [] # 检查金额大小写一致性 if claim_amount in variables: amount_str f{variables[claim_amount]:.2f} if amount_str not in text: issues.append(f金额 {amount_str} 未在正文中出现) # 抽取法条引用 law_refs re.findall(r《[^》]》第[\d一二三四五六七八九十]条, text) for ref in law_refs: if ref not in LAW_DATABASE: issues.append(f疑似编造法条{ref}) # 检查是否残留占位符 if 【待补充 in text: issues.append(存在待补充字段需人工介入) return {issues: issues, law_refs: law_refs, passed: len(issues) 0}这段校验的核心思路是「用确定性规则兜住模型的随机性」。LAW_DATABASE可以先用一份常用法条清单覆盖民法典、劳动合同法、民事诉讼法等高频引用即可不必追求全量。【待补充的检查尤其重要它把「模型不确定的地方」显式暴露出来而不是让模型硬编。4. 100 模板的工程化管理版本、变量与复用模板数量上去之后管理成本会超过生成成本。100 模板如果散落在各个脚本里改一个格式要翻半天。这一章讲怎么把模板当代码管包括版本控制、变量 schema 和复用策略。4.1 模板文件化YAML 存元数据Jinja2 存正文不要把提示词硬编码在 Python 里。推荐做法是每个模板一个目录元数据用 YAML正文用 Jinja2 模板语法。Jinja2 的变量语法和条件判断足够表达法律文书的复杂结构比如「有反诉时插入反诉段落」。# templates/起诉状/meta.yaml name: 起诉状 category: 诉讼文书 version: 1.2.0 model: deepseek-chat parameters: temperature: 0.3 max_tokens: 4096 variables: - name: plaintiff_name type: str required: true - name: claims type: list[str] required: true - name: has_counterclaim type: bool default: false{# templates/起诉状/prompt.j2 #} 请根据以下信息起草民事起诉状 原告{{ plaintiff_name }}{{ plaintiff_type }} 被告{{ defendant_name }} 诉讼请求 {% for claim in claims %} {{ loop.index }}. {{ claim }} {% endfor %} 事实与理由 {{ facts }} {% if has_counterclaim %} 本案存在反诉请在答辩部分单独列明反诉请求。 {% endif %}用 Jinja2 的好处是条件分支、循环、默认值都能表达而且模板本身可读。参数上version字段必须严格维护每次改提示词都要升版本号否则出了问题无法回溯是哪版提示词导致的。required: true的变量在填充前要做校验缺失就报错不要让它带着空值进模型。4.2 变量 schema 校验在调用前拦住脏数据法律文书的变量来自各种上游系统格式参差不齐。在填充模板前做一层 schema 校验能省掉大量「模型输出莫名其妙」的排查时间。from pydantic import BaseModel, Field, validator from typing import List, Optional class 起诉状Vars(BaseModel): plaintiff_name: str Field(..., min_length2, max_length50) plaintiff_type: str Field(..., pattern^(自然人|法人|非法人组织)$) defendant_name: str claims: List[str] Field(..., min_items1) facts: str Field(..., min_length50) claim_amount: Optional[float] Field(None, gt0) has_counterclaim: bool False validator(claims) def claims_not_empty(cls, v): for c in v: if not c.strip(): raise ValueError(诉讼请求不能为空字符串) return v用 Pydantic 做校验的价值在于错误在调用 API 之前就暴露而不是等模型返回一堆废话才发现输入有问题。min_length50对facts的限制是经验值事实描述太短模型会自己脑补太长又容易超出上下文。pattern约束枚举字段防止上游传进来「个人」「公司」这种非标准值。4.3 模板复用继承与片段组合100 模板里有大量重复片段比如当事人信息块、证据清单格式、落款格式。用 Jinja2 的include和extends做片段复用改一处全局生效。{# templates/_partials/当事人信息.j2 #} {% macro render_party(role, name, party_type, contact) %} {{ role }}{{ name }}{{ party_type }} {% if contact %}联系方式{{ contact }}{% endif %} {% endmacro %}{# templates/起诉状/prompt.j2 #} {% from _partials/当事人信息.j2 import render_party %} {{ render_party(原告, plaintiff_name, plaintiff_type, plaintiff_contact) }} {{ render_party(被告, defendant_name, defendant_type, defendant_contact) }}宏和 include 的取舍宏适合带参数的片段include 适合纯静态片段。法律文书里当事人信息、证据清单、落款这三块最适合抽成宏因为它们在不同文书里结构一致但参数不同。注意 Jinja2 的宏不会自动转义法律文本里的特殊字符要自己处理否则可能生成出格式错乱的文书。5. 避坑与排查法律文书自动化最容易翻车的 5 个点这一章全是踩过的坑按「现象 → 原因 → 解决」写。法律场景对错误的容忍度比一般文本生成低得多下面这几条如果没处理好轻则返工重则产出有法律风险的文书。5.1 模型编造法条且格式看起来很像真的现象生成的文书里出现《民法典》第 1234 条这种不存在的条款但格式完全正确人工扫一眼很难发现。原因模型在训练数据里见过大量法条格式会按格式「生成」看起来合理的条款号而不是检索真实法条。解决后处理阶段用法条库做正则匹配核验所有引用必须命中白名单。同时把系统提示词里的「不得编造法条」改成更强的约束「只允许引用以下法条清单中的条款{law_list}」把清单直接注入提示词。5.2 金额大小写不一致或者大写转换错误现象正文里阿拉伯数字是 85000中文大写写成「捌万伍仟元」但漏了「整」或者干脆写成「八万五千元」这种非标准格式。原因模型做数值到中文大写的转换不稳定尤其是带角分的金额。解决金额大写不要交给模型用 Python 的cn2an库在填充变量时就转好把结果作为变量传给模型并在系统提示词里要求「金额大写必须原样使用不得改写」。5.3 长文书生成到一半被截断现象法律意见书生成到「风险提示」部分突然断掉或者最后一段不完整。原因max_tokens设小了或者模型在长上下文里「忘记」了输出格式要求。解决按文书类型设置max_tokens法律意见书这类长文书给到 8000 以上。如果还是截断把文书拆成「分析」和「结论」两次调用第二次调用时把第一次的输出作为上下文传入。另外检查finish_reason字段如果是length就说明被截断需要重试或调大限制。5.4 当事人称谓前后不一致现象开头写「原告张三」中间变成「张先生」后面又变成「张三先生」。原因模型在长文本里对简称的维护不稳定尤其是多当事人场景。解决在系统提示词里明确「首次出现用全称之后统一用『原告姓氏』格式」并在后处理阶段用正则统计各称谓出现次数发现不一致就标记人工复核。更彻底的做法是在变量填充阶段就把简称算好作为独立变量传入。5.5 批量生成时部分任务静默失败现象提交了 50 份实际只产出 47 份日志里没有明显报错。原因并发调用时部分请求超时异常被吞掉或者重试逻辑没覆盖到所有异常类型。解决每个任务单独记录状态失败的任务写入failed_tasks.json包含原始变量和错误信息。批处理结束后统计成功率和失败清单失败的任务用更低的并发单独重跑。不要用try/except: pass这种写法法律文书场景丢一份可能就是丢一个案子。6. 进阶用 few-shot 和自检链把文书质量再提一档模板和 API 都跑通之后想再往上走靠的是 few-shot 示例和自检链。这两个技巧在法律场景收益特别明显因为法律写作的「好」有明确参照模型能通过对比示例学到风格也能通过自检发现自己漏了什么。6.1 few-shot 示例怎么选、怎么放few-shot 不是随便找几份文书塞进去。示例要满足三个条件和目标任务同类型、结构完整、有代表性。比如做劳动争议起诉状就选一份事实清晰、法条引用规范的劳动争议案例不要混入合同纠纷的示例。FEW_SHOT_EXAMPLE 【示例】 原告李四自然人 被告某某贸易有限公司 诉讼请求 1. 判令被告支付违法解除劳动合同赔偿金 120000 元 2. 判令被告出具解除劳动合同证明。 事实与理由 原告于 2019 年 5 月入职被告公司任销售经理……略 综上被告的行为违反《劳动合同法》第八十七条应支付赔偿金。 SYSTEM_PROMPT_WITH_SHOT f你是一名执业十年以上的中国诉讼律师。 以下是一份高质量的起诉状示例请学习其结构、语气和法条引用方式 {FEW_SHOT_EXAMPLE} 现在请根据用户提供的信息起草一份新的起诉状保持同样的专业水准。示例放在系统提示词里位置在角色说明之后、规则说明之前。参数上示例长度控制在 800 到 1500 字太短学不到结构太长挤占上下文。如果任务类型多可以按类型准备多个示例运行时动态选择。6.2 自检链让模型自己找自己的问题自检链的思路是生成完文书后用第二次调用让模型扮演「审核律师」逐条检查文书是否符合要求。这一步能抓出不少格式和逻辑问题。REVIEW_PROMPT 你是一名资深法律文书审核律师。请审核以下文书逐项检查 1. 当事人称谓是否全文一致 2. 诉讼请求是否明确、可执行 3. 事实与理由是否按时间顺序、有无逻辑跳跃 4. 法条引用是否准确、有无编造 5. 金额大小写是否一致 6. 有无残留占位符或待补充标记 对每个问题给出「通过」或「问题具体描述」最后给出总体结论。 def review_document(content: str) - str: response client.chat.completions.create( modeldeepseek-chat, messages[ {role: system, content: REVIEW_PROMPT}, {role: user, content: content} ], temperature0.1 # 审核要严格不要发散 ) return response.choices[0].message.content自检链的temperature要压到 0.1 左右审核任务需要的是稳定判断不是创意。审核结果里如果出现「问题」把问题描述和原文一起回传给生成模型做一次修订形成「生成 → 审核 → 修订」的闭环。注意这个闭环最多跑两轮跑多了模型会过度修改反而把正确的地方改错。6.3 人工复核环节不能省再好的自动化法律文书最终也要人签字。把人工复核设计成流程的一部分而不是事后补救。具体做法是自动生成后把文书、变量来源、自检结果三样一起推给复核人复核人只需要看自检标记的问题点和关键字段不用从头读一遍。复核项自动检查人工确认当事人信息格式校验与委托材料比对诉讼请求非空校验金额、诉求合理性法条引用白名单匹配适用性判断事实叙述时间线完整性与证据一致性金额大小写自动转换抽查这张表的分工逻辑是机器管格式和确定性规则人管判断和策略。我一般会把自检结果按严重程度分三级红色必须人工处理黄色提示复核绿色直接通过。这样复核人的注意力集中在真正有风险的地方效率能提不少。做法律文书自动化这两年最大的教训是不要追求「全自动出成品」要追求「把人的重复劳动压缩到最低把判断权留给人」。模型能帮你把一份起诉状的初稿从两小时压到十分钟但那十分钟的复核不能省。希望这套拆解能帮到你少走点我踩过的弯路。本文还有配套的精品资源点击获取
返回列表