用Gemini API构建法律合同自动审查与知识库增强系统
这次我们来关注一个产品方向,而不是单纯某个模型版本:Google 把 Gemini 的能力直接下沉到了法律垂直场景,推出了 Gemini Enterprise for Legal。从公开信息看,它并不是简单地把通用聊天机器人换个皮套在律所里,而是围绕“合同自动化”和“法律研究”两条主线做了一套面向企业级用户的服务。对技术团队来说,真正值得研究的不是产品名,而是背后那套可复用的能力链路:文档解析、合同要素抽取、风险条款识别、法律知识检索增强,以及如何通过 API 把这些能力接进自己的业务系统。
这篇文章会用技术落地视角拆解这个产品方向。重点解决三个问题:它到底能帮法律和技术团队做什么;如果要基于 Gemini API 自己搭建一套类似的合同审查与法律研究流程,环境怎么准备、接口怎么调、批量任务怎么跑;以及在实际落地时有哪些合规、安全、错误处理和效果验证的坑。
如果你是做 LegalTech、企业内部合规系统、合同生命周期管理或知识库检索增强的工程师,这篇文章可以直接作为一套落地参考。
1. Gemini Enterprise for Legal 核心能力速览
先给一张速览表,把最核心的信息放在最前面。注意,部分参数并非 Google 官方文档直接给出的明确数值,而是基于 Gemini 模型的通用能力做出的合理推断,实际使用时要以你购买到的服务版本和 API 文档为准。
| 能力项 | 说明 |
|---|---|
| 产品定位 | 面向法律垂直场景的企业级 AI 服务,覆盖合同自动审查与法律研究 |
| 底层模型 | 基于 Gemini 系列大模型,对外通过 API 提供服务 |
| 核心功能 | 合同要素抽取、风险条款识别、条款摘要、法律问题检索、文档问答 |
| 输入类型 | 文本、PDF、DOCX 等常见文档格式,需要经过解析后调用模型 |
| 输出类型 | 结构化 JSON、Markdown 报告、风险标注、自然语言回答 |
| 部署方式 | 云端托管为主,企业可通过 Google Cloud 项目管理访问;也可基于 Vertex AI 做私有化定制 |
| API 能力 | 支持生成式对话、文档理解、批量任务提交 |
| 批量任务 | 可通过脚本批量提交合同文件,逐条调用模型分析并落盘结果 |
| 适合场景 | 律所合同初审、企业法务合规、采购合同风险筛查、法律案例检索 |
| 主要限制 | 结果不能替代律师专业判断,涉及隐私、保密、证据材料时需严格评估合规性 |
从这张表可以看出,Gemini Enterprise for Legal 本质上是“通用大模型 + 法律场景优化 + 企业级服务封装”。它不会代替律师出庭,也不会自动生成具有法律效力的意见书,而是把那些原来需要人工逐字阅读的合同文本,变成可搜索、可标注、可量化风险的数据。
2. 适用场景与使用边界
先聊场景,再聊边界,这两部分决定了项目是否值得启动。
2.1 适合哪些团队
第一类是律所和律师团队。日常工作中,律师大量时间消耗在合同初审、尽调文档翻阅、法规检索上。Gemini Enterprise for Legal 可以帮助做第一轮筛选:哪些条款是常规条款,哪些条款存在明显风险,哪些金额和期限需要人工复核。
第二类是企业法务和技术团队。企业内部的采购合同、销售合同、NDA 保密协议、劳动合动数量通常很大,法务人员有限,逐份审阅不现实。通过自动化流程抽取合同主体、金额、付款条件、违约责任、管辖法院等关键字段,可以显著提升前置筛查效率。
第三类是正在做 LegalTech 产品研发的技术团队。即使你暂时不采购 Google 的企业版服务,也可以参考这套产品逻辑,用 Gemini API 构建类似的合同批处理系统。
2.2 不适合什么场景
合同审查的自动化不等于完全无人化。涉及重大交易、复杂并购、诉讼证据、监管申报等高风险场景,目前不建议完全依赖大模型输出。另外,如果你的合同涉及高度敏感的企业商业秘密或个人隐私数据,直接调用云端 API 需要先确认数据出境、存储位置和保密协议是否符合要求。
2.3 合规与安全边界
涉及法律数据,必须把合规放在功能之前。以下几点建议直接写进项目评审清单:
- 合同、判决书、案例库等数据是否具备合法来源和授权。
- 数据中包含的自然人信息、商业机密、客户信息是否经过脱敏处理。
- API 调用日志是否会保存原始文档内容。
- 云端处理是否满足企业内部安全规范和所在地区的数据保护法律要求。
- 输出结果必须经过专业法律人员复核,AI 结果仅作为辅助参考。
3. 技术架构与数据处理流程
要落地一套类似 Gemini Enterprise for Legal 的合同分析系统,先要理解它的数据流水线。
一条完整的合同自动化审查链路通常包含以下环节:
原始文件上传(PDF/DOCX) -> 内容解析与文本提取 -> 文本预处理与分块 -> 调用大模型抽取结构化字段 -> 风险规则匹配 -> 生成审查报告 -> 人工复核对于法律研究场景,通常还要再叠加一个知识库检索层。你可以把法律条文、历史判例、内部合规政策提前切块并向量化,存储到向量数据库中。用户提问时,先做相似度检索,再把相关片段拼进 Prompt,一起交给模型回答。这样比直接把整个法律库塞进上下文更可控,也更容易追踪回答来源。
核心逻辑可以概括为:解析层负责把文档变成干净文本,模型层负责语义理解和结构化输出,规则层负责把模型输出映射到法律业务上的风险标签,人工层负责最终确认。
4. 接入 Gemini API 的环境准备
无论你是想直接体验 Gemini 模型,还是要构建合同审查系统,第一步都是准备环境。这里给出一套通用接入配置流程。
4.1 前置检查清单
下面这些条件不满足,后面调用接口大概率会出现各种问题:
- 一个有效的 Google Cloud 项目或具备模型访问权限的 Gemini API 账号。
- 已开通对应模型服务的 API 权限,并创建了 API Key 或服务账号。
- Python 3.9 以上环境,推荐 3.10 或 3.11。
- 需要安装
google-genai官方 SDK 或使用requests直接调用 HTTP 接口。 - 确保本机网络可以正常访问 Google Cloud 的服务端点。
- 如果使用 Vertex AI,还需要安装
google-cloud-aiplatformSDK 并完成本地身份认证。
这里特别说明一下:不同区域的 API 可用性、模型版本和数据存储位置可能不同。生产环境使用前,务必确认你所处的业务区域是否在官方支持范围内,并遵循当地法律和平台使用条款。
4.2 Python 环境初始化示例
python -m venv venv source venv/bin/activate # Windows 下使用 venv\Scripts\activate pip install --upgrade google-genai如果你更习惯直接走 HTTP,也可以只安装requests:
pip install requests4.3 获取 API 密钥
在 Google Cloud 控制台开启 Gemini API 后,创建 API Key,并把 Key 保存到环境变量中,避免写死在代码里。
export GEMINI_API_KEY="你的APIKey"Windows PowerShell 下可以这样设置:
$env:GEMINI_API_KEY="你的APIKey"5. 首次接入与合同分析 Demo
环境准备好之后,先用一个最小 Demo 验证模型能不能正常返回结果。这一步非常关键,可以提前排除账号权限、网络连通性和 SDK 版本问题。
下面示例以google-genaiSDK 为基础,实际模型名称需要根据你账号可访问的模型列表调整。
from google import genai import os client = genai.Client(api_key=os.getenv("GEMINI_API_KEY")) response = client.models.generate_content( model="gemini-2.5-flash-preview-05-20", contents="请提取以下合同条款中的付款期限和违约责任。", ) print(response.text)如果网络返回正常,说明 SDK 和 API Key 没有问题。接下来可以做一个真正有业务价值的测试:把一段合同原文传给模型,让它输出结构化结果。
contract_text = """ 甲方:北京某某科技有限公司 乙方:上海某某供应链管理有限公司 双方经友好协商,就软件采购事宜签订本合同。 合同总金额为人民币120万元,分三期支付。 合同生效后15个工作日内支付30%; 系统上线验收合格后支付50%; 质保期满后支付剩余20%。 如乙方逾期交货,每逾期一日,应按照合同总金额的0.5%向甲方支付违约金。 本合同适用中华人民共和国法律。 """ prompt = f""" 请从下面的合同文本中提取以下字段,并以 JSON 格式返回: - 甲方名称 - 乙方名称 - 合同总金额 - 付款节点 - 违约金条款 - 适用法律 合同文本: {contract_text} """ response = client.models.generate_content( model="gemini-2.5-flash-preview-05-20", contents=prompt, ) print(response.text)输出结构大致会是这样,实际字段名和格式会随模型输出略有变化:
{ "甲方名称": "北京某某科技有限公司", "乙方名称": "上海某某供应链管理有限公司", "合同总金额": "120万元", "付款节点": [ "合同生效后15个工作日内支付30%", "系统上线验收合格后支付50%", "质保期满后支付剩余20%" ], "违约金条款": "每逾期一日,按合同总金额的0.5%支付违约金", "适用法律": "中华人民共和国法律" }到这里,你就已经跑通了一条最小的合同信息抽取链路。后面所有进阶功能,都可以在这个基座上扩展。
6. 合同自动化审查功能测试
合同审查不是一个单一操作,而是多个子任务的有序组合。建议按照下面几个维度逐项测试。
6.1 合同要素抽取测试
测试目的:验证模型能否从非结构化的合同文本中,准确提取固定字段。
输入素材准备一份真实合同,建议先对涉及个人和商业敏感的部分做脱敏替换。
测试步骤:
- 将合同文本拆分为不超过模型上下文长度的片段。
- 构造结构化提取 Prompt,明确列出要提取的字段。
- 调用模型接口。
- 检查返回 JSON 是否完整、字段是否对应原文。
判断是否成功的标准:
- 所有字段均有值,且能在原文中找到对应位置。
- 金额、日期、公司名称没有错位或幻觉。
- 如果合同有多个付款节点,模型能返回完整列表。
6.2 风险条款识别测试
测试目的:验证模型能否标出合同中可能对己方不利的条款。
可以把风险类型定义成一套标签体系,例如:
- 付款条件苛刻:付款节点过早或比例不合理。
- 违约金过高:比例超过常见业务水平。
- 责任限制缺失:没有约定赔偿上限。
- 知识产权归属模糊。
- 管辖地与执行地不一致。
risk_prompt = f""" 你是一名资深合同审查律师助理。请根据以下风险标签,识别合同中可能存在的风险条款: 标签范围:付款条件苛刻、违约金过高、责任限制缺失、知识产权归属模糊、管辖法律不明。 对每一个识别出的风险,给出: - 风险类型 - 合同原文引用 - 风险等级(高/中/低) - 建议修改方向 合同文本: {contract_text} """ response = client.models.generate_content( model="gemini-2.5-flash-preview-05-20", contents=risk_prompt, ) print(response.text)这个测试的价值在于:模型不一定能自动给出专业法律判断,但它能通过语义理解找到那些值得人工注意的句子,本质上是一种大规模文本预筛选。
6.3 条款摘要与对比测试
如果你的业务里有“新旧版本合同对比”需求,可以让模型分别读取两份合同版本,再输出条款差异摘要。更稳妥的做法是交给模型一份整合后的文本,并在 Prompt 中指定对比要求。
实际测试时注意:模型输出质量受合同文本长度和清晰度影响较大。扫描版 PDF 需要先经过 OCR 解析,否则模型看到的只是乱码或空白。
7. 法律研究与知识库增强
合同审查跑通后,下一步通常是法律研究。Gemini Enterprise for Legal 的另一个重点就在这里。
纯靠模型内置知识做法律研究不够用,因为法律条文和判例更新频繁,而且不同地区差异很大。更可靠的方式是外挂知识库,也就是 RAG(Retrieval-Augmented Generation)方案。
一个可落地的流程是:
- 收集法律条文、司法解释、公司内部合规政策。
- 将文档切块,调用向量化模型将文本转为向量。
- 把向量存入向量数据库,例如 Chroma、Weaviate、Milvus 等。
- 用户提问时,先在向量库中查找相关片段。
- 将检索结果与问题一起拼入 Prompt,再调用 Gemini 生成回答。
示例流程如下:
query = "逾期交付的违约金比例上限是多少?" # 假设已有检索函数 related_docs = search_legal_docs(query) context = "\n".join(related_docs) prompt = f""" 请根据以下法律资料回答问题。 资料: {context} 问题: {query} """ response = client.models.generate_content( model="gemini-2.5-flash-preview-05-20", contents=prompt, ) print(response.text)这种做法的好处是:答案可以追溯来源,大大降低了模型凭空编造法律条文的概率。同时,知识库可以在本地和模型解耦,更新法律法规时只需重新灌入文本,不需要重复训练模型。
8. 接口 API 与批量任务队列
单份合同测试之后,真正能产生价值的是批量处理。一个企业法务部可能一次收到几十甚至上百份合同,人工逐份上传不可行,这时候必须走批量任务。
8.1 批量任务设计思路
建议按目录结构组织输入输出:
./contracts/input/ 存放待审核的合同 PDF 或 DOCX ./contracts/parsed/ 存放解析后的文本 ./contracts/output/ 存放每份合同的分析报告 ./contracts/logs/ 存放调用日志和错误信息批量流程如下:
- 扫描输入目录,获取所有文件。
- 解析每个文件,转换为纯文本。
- 按固定 Prompt 模板调用 Gemini API。
- 将返回结果保存为独立文件。
- 记录每份文件的状态:成功、失败、需要人工复核。
- 对失败文件设置重试机制。
8.2 Python 批量调用示例
下面给出一个参考实现,不代表 Gemini Enterprise for Legal 官方接口,但适用于多数 Gemini API 接入场景:
import json import os import time from google import genai client = genai.Client(api_key=os.getenv("GEMINI_API_KEY")) model_name = "gemini-2.5-flash-preview-05-20" input_dir = "./contracts/input" output_dir = "./contracts/output" os.makedirs(output_dir, exist_ok=True) def analyze_contract(file_path: str) -> str: with open(file_path, "r", encoding="utf-8") as f: text = f.read() prompt = f""" 请分析以下合同文本,输出 JSON 格式结果,包含: 合同主体、金额、付款条款、违约责任、风险点列表。 如果信息缺失,请标注为"未明确"。 合同文本: {text[:8000]} """ try: response = client.models.generate_content( model=model_name, contents=prompt, ) return response.text except Exception as e: return json.dumps({"error": str(e)}, ensure_ascii=False) for file_name in os.listdir(input_dir): if not file_name.endswith((".txt", ".md")): continue file_path = os.path.join(input_dir, file_name) output_path = os.path.join(output_dir, file_name + ".json") result = analyze_contract(file_path) with open(output_path, "w", encoding="utf-8") as f: f.write(result) print(f"processed: {file_name}") time.sleep(1) # 避免请求过快触发限流需要注意:上面的示例把模型输出当作 JSON 直接写到文件里,实际上模型可能返回带 Markdown 标记的内容,保存前最好做一次清理或解析校验。更严谨的做法是用函数调用或结构化输出能力,强制模型返回符合 Schema 的 JSON。
8.3 并发与限流控制
批量任务中,限流是最常见的问题。当文件数量超过 API 配额时,接口会返回 429 或类似错误。项目初期建议保持串行调用,随后再根据配额逐步提高并发数。加入指数退避重试机制,可以有效降低偶发失败的影响。
import time def call_with_retry(func, max_retries=3): for attempt in range(max_retries): try: return func() except Exception as e: print(f"retry {attempt + 1}: {e}") time.sleep(2 ** attempt) return None9. 资源占用、性能观察与成本控制
Gemini Enterprise for Legal 走的是云端 API 模式,本地不需要 GPU,不需要部署大模型,资源占用主要体现在几个不同层面。
9.1 本地资源占用
脚本运行时,本地主要消耗 CPU 和内存。合同文本解析、JSON 序列化、向量检索这些操作本身不会占用特别大的显存。以普通函数计算服务器或个人 PC 为例,只要不是同时处理超大文件,8GB 内存基本够用。
如果使用向量数据库做法律知识库检索,内存占用会随知识库规模上升。几千条法律条文大概占几百 MB 到几 GB,具体取决于向量维度和数据库实现。
9.2 API 延迟观察
API 延迟直接决定批量任务总耗时。影响延迟的主要因素包括:
- 输入文本长度。
- 输出内容长度。
- 模型版本和并发请求数。
- 网络链路。
单次调用如果输入合同文本 3000 字左右,输出限制在 2000 字以内,在模型服务正常的前提下,通常需要几秒到几十秒不等。生产环境建议把每次调用的耗时记录到日志里,方便后续做任务调度优化。
9.3 成本控制
云端大模型 API 通常按 Token 计费,但具体价格要以 Google Cloud 官方定价为准。这里提供三个通用控制思路:
- 控制输入长度:合同全文不需要一次性塞进模型,先提取关键段落再调用。
- 控制输出长度:明确要求模型输出 JSON 或短句摘要,减少无意义长文本。
- 建立缓存:同一份合同做重复分析时,直接读取历史结果,避免重复计费。
10. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| API 调用返回权限错误 | API Key 无效或未开通模型权限 | 检查 Key 是否写对、服务是否启用 | 重新生成 Key 并确认模型可用 |
| 返回内容与合同无关 | 输入文本过长被截断,或 PDF 解析乱码 | 检查解析后的文本内容 | 先做 OCR 和段落清洗,再调用模型 |
| 批量任务中途失败 | 网络波动或触发限流 | 查看错误码和日志 | 增加重试机制,降低并发 |
| 模型输出不是合法 JSON | 输出中包含 Markdown 或说明文字 | 打印原始响应 | 使用结构化输出或增加结果清洗函数 |
| 合同字段提取缺失 | 原文本身未写明该字段 | 对照原文确认 | 在 Prompt 中标注“未明确” |
| 知识库检索结果不相关 | 文本分块过粗或向量化模型不匹配 | 检查检索结果 top-k | 调整切分策略和向量模型 |
这里说一个容易被忽视的坑:PDF 解析。很多合同是扫描件或带水印的 PDF,直接提取文本会得到大量空格、错位和乱码。建议在进入模型之前单独建一层解析任务,先用 OCR 工具把扫描件转成可编辑文本,再做清理。
11. 最佳实践与合规边界
11.1 工程实践建议
第一,第一次测试不要直接上全量合同。先准备 5 到 10 份格式各异的样例合同,跑通完整链路后再扩展。
第二,Prompt 模板要版本化。合同审查项目里,Prompt 是最容易被改动也最容易出问题的部分。建议把 Prompt 单独保存成模板文件,记录每次修改原因和上线时间。
第三,输出结果要保留原文位置。只输出“违约金过高”这样的标签对律师没有意义,律师需要知道这个判断来自哪一条原文。字段抽取时要同时记录原文引用片段,最好包含条款序号。
第四,人工复核节点不能省。可以设计三档结果:无需复核、抽样复核、必须人工审核。高风险合同和模型置信度低的合同,自动进入人工队列。
11.2 数据合规与授权
法律数据不同于普通文本数据,合同可能包含当事人隐私、商业条款、未公开信息。使用云端 API 前,至少确认以下事项:
- 是否有权处理这部分合同数据。
- 数据存储地区是否符合企业安全要求。
- API 方是否会将输入数据用于模型训练。
- 是否需要签署数据处理协议。
- 输出结果中的自动分析是否会影响用户权益。
如果企业内部数据管控要求高,可以优先考虑私有化部署方案或本地模型,但私有化部署意味着需要额外的 GPU 资源和模型运维成本,前期要做完整的成本评估。
11.3 效果验证建议
建立一套小规模的“标准测试集”。挑选涵盖常见合同类型的样例,人工标注标准答案。每次调整 Prompt 或模型版本后,都跑一遍测试集,对比准确率和字段完整度。没有测试集,就没办法判断修改到底是变好还是变坏。
12. 总结与下一步
Gemini Enterprise for Legal 把通用大模型的能力真正下沉到了法律业务场景。对技术团队来说,启发在于:不要试图让模型直接生成法律意见,而是把它嵌入到“解析、抽取、标注、检索、复核”这条可控流水线里。通过 Gemini API,一个最小可用的合同自动审查系统可以在较短时间内搭建起来,再逐步扩展批量任务、知识库检索和人工复核流程。
最容易踩的坑有三个:PDF 解析质量不过关、Prompt 输出不稳定、批量任务没有重试机制。最先应该验证的能力是合同要素抽取,它能帮你快速判断模型输出是否满足业务要求。
后续可以从三个方向继续扩展:一是把合同审查结果与企业 OA 或合同管理系统打通;二是接入本地法律知识库,形成带来源说明的法律问答能力;三是建立标准评测集,持续跟踪不同模型版本的效果变化。如果你所在团队也要处理大量合同审核和法规检索场景,这套思路值得尽早试一遍。
