智算多多



法律文本具备 强结构化、专业术语多、逻辑严密 的特点,正好契合大模型在 语义理解、推理生成 上的潜力。
基于以上考量,法律AI成为我们团队投入资源最多的垂直方向之一。🚀
| 类型 | 示例 | 链接 |
|---|---|---|
| 判决书 | 最高人民法院公开的刑事判决书 | https://wenshu.court.gov.cn/ |
| 法规 | 全国人大常委会发布的法律条文 | http://www.npc.gov.cn/ |
| 合同 | 公开的企业合作协议、租赁合同 | https://www.contracts.com(示例) |
| 问答 | 法律咨询网站上的用户提问 | https://www.12348.gov.cn/ |
为避免数据泄露,我们只使用 已公开、可授权 的数据,并对 个人信息 进行严格的脱敏处理。
下面给出一个 Python + pandas + regex 的典型清洗脚本,实现去除 HTML 标签、统一标点、过滤超短文本等操作。
# 📂 data_cleaning.py
import re
import pandas as pd
def clean_legal_text(text: str) -> str:
# 1️⃣ 去除 HTML 标签
text = re.sub(r'<[^>]+>', '', text)
# 2️⃣ 统一全角标点为半角
text = text.translate(str.maketrans(',。!?;:""''()', ',.!?;:""\'\'()'))
# 3️⃣ 删除多余换行和空格
text = re.sub(r'\s+', ' ', text).strip()
# 4️⃣ 过滤掉长度小于 20 字符的记录(法律文本往往较长)
if len(text) < 20:
return None
return text
# 假设 raw.csv 包含一列 `raw_text`
df = pd.read_csv('raw.csv')
df['clean_text'] = df['raw_text'].apply(clean_legal_text)
df = df.dropna(subset=['clean_text'])
df.to_csv('clean_legal_corpus.csv', index=False)
print(f"✅ 清洗完成,保留 {len(df)} 条有效记录")
小技巧:在实际项目中我们会加入 并行处理(
multiprocessing)或使用 Dask 处理上千万条数据,确保清洗速度不会成为瓶颈。💡
法律文本的语义往往非常细腻,单纯依赖模型自监督会产生 误导性标签。因此我们组建了 法律专家 + 标注平台 的双层标注体系:
通过这种“人机协同”,我们在 10 万条数据上实现了 ≈95% 的标注一致性。
| 模型 | 参数量 | 开源协议 | 关键优势 |
|---|---|---|---|
| LLaMA‑2‑7B | 7B | Llama 2 Community License | 开放权重、推理速度快 |
| ChatGLM‑2‑6B | 6B | 清华开源 | 中文表现优秀 |
| Baichuan‑2‑13B | 13B | Apache 2.0 | 中文推理能力强 |
我们最终选用了 ChatGLM‑2‑6B 作为基座,因为在中文字词粒度上表现更稳,同时可以在单卡 A100‑40GB 上完成全参数微调。
| 方法 | 显存需求 | 训练时间 | 效果提升 |
|---|---|---|---|
| 全参数微调(Full‑FT) | ~80GB(8 卡) | 3‑4 天 | 最高 |
| LoRA(Rank=8) | ~24GB(单卡) | 8‑12 小时 | 接近全参数 |
| P‑-tuning v2 | ~16GB(单卡) | 5‑6 小时 | 中等 |
| Adapter | ~20GB(单卡) | 6‑8 小时 | 略低于 LoRA |
结合 资源限制 与 效果需求,我们最终采用 LoRA + DeepSpeed ZeRO‑2 进行微调,兼顾速度与显存。
下面展示我们搭建的 数据 → 训练 → 保存 自动化流程(Mermaid 图已嵌入,不要放在文章末尾):
A → B:使用前文的 clean_legal_text 脚本。
F:通过 transformers + peft + deepspeed 组合实现 大模型低显存微调。
H:记录 loss、学习率、GPU 利用率,并在每个 epoch 结束后自动运行 评估脚本(详见 7️⃣)。
下面的示例完整演示了 数据加载、模型准备、训练启动 三个步骤,适配单卡 A100‑40GB:
# 🚀 fine_tune_lora.py
import os
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, DataCollatorForLanguageModeling
from peft import LoraConfig, get_peft_model, TaskType
from datasets import load_dataset
from trl import SFTTrainer
# 1️⃣ 加载基座模型与分词器
model_name = "THUDM/chatglm2-6b"
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16,
device_map="auto",
trust_remote_code=True
)
# 2️⃣ 配置 LoRA
lora_config = LoraConfig(
r=8,
lora_alpha=16,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
lora_dropout=0.05,
bias="none",
task_type=TaskType.CAUSAL_LM
)
# 3️⃣ 将原始模型转为 PEFT 模型
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# 输出: trainable params: 1,245,760 || all params: 6,767,411,200 || trainable%: 0.0184
# 4️⃣ 加载清洗后的法律数据集(假设为 jsonl 格式)
dataset = load_dataset("json", data_files={"train": "clean_legal_corpus.jsonl"})["train"]
def preprocess(example):
# 将文本直接拼接为 prompt 形式
return {"text": f"法律文本:{example['clean_text']}"}
dataset = dataset.map(preprocess, remove_columns=["clean_text"])
# 5️⃣ 训练参数
training_args = TrainingArguments(
output_dir="./legal_lora_chatglm2",
per_device_train_batch_size=4,
gradient_accumulation_steps=8,
num_train_epochs=3,
learning_rate=5e-5,
fp16=True,
logging_steps=20,
save_strategy="epoch",
save_total_limit=2,
deepspeed="./ds_config.json" # 需提前准备 ZeRO‑2 配置文件
)
# 6️⃣ 使用 SFTTrainer(对对话模型更友好)
trainer = SFTTrainer(
model=model,
args=training_args,
train_dataset=dataset,
data_collator=DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False),
)
# 7️⃣ 启动训练
trainer.train()
# 8️⃣ 保存微调后的 LoRA 权重
model.save_pretrained("legal_lora_adapter")
关键点:
deepspeed配置使用 ZeRO‑2 可把 模型状态 分散到多卡,极大降低显存。LoraConfig中的target_modules必须和模型结构对应,ChatGLM2 为q_proj、v_proj、k_proj、o_proj。- 使用
SFTTrainer能够自动完成 prompt‑template 的包装,避免手工拼接导致的 分布漂移。
| 任务 | 指标 | 说明 |
|---|---|---|
| 文本生成 | BLEU‑4、ROUGE‑L | 与参考答案的 n‑gram 重叠度 |
| 实体抽取 | Precision、Recall、F1 | 法官、法条、金额等实体 |
| 法律问答 | Exact Match、BERTScore | 答案与标准答案的语义相似度 |
| 法规匹配 | Top‑k 准确率 | 检索相似法条的召回率 |
我们使用 HuggingFace
evaluate库快速加载上述指标,配合 自研脚本 生成每日报表。
通过
| 坑点 | 描述 | 解决思路 |
|---|---|---|
| 数据泄露 | 训练集中出现测试集相同案例,导致评估指标虚高 | 使用 哈希去重 + 时间戳分割(训练早于测试) |
| 领域漂移 | 微调后模型在通用语言任务上表现下降 | 采用 混合训练(通用语料+法律语料)或 多任务学习 |
| 显存爆炸 | 预训练模型过大,单卡无法放入 | 使用 DeepSpeed ZeRO‑2/3,或 QLoRA(4‑bit 量化+LoRA) |
| 标注噪声 | 标注人员对同一文本理解不一致 | 引入 Krippendorff’s α 统计一致性,低于阈值则重新标注 |
| 推理延迟 | 法律机器人需要毫秒级响应 | 使用 bitsandbytes 进行 int8 量化 + ONNX Runtime 加速 |
| 合规风险 | 模型可能生成违规建议 | 部署 后处理规则过滤 + 法条白名单,并记录审计日志 |
经验之谈:在实际项目中,我把 数据清洗 与 错误归因 做成 自动化流水线,每次模型迭代都会自动触发这两步,极大提升了迭代速度。
# ⚙️ quantize_model.py
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(
load_in_8bit=True, # 8‑bit 量化
llm_int8_threshold=6.0,
llm_int8_has_fp16_weight=False
)
model = AutoModelForCausalLM.from_pretrained(
"legal_lora_adapter",
quantization_config=quantization_config,
device_map="auto"
)
print("✅ 模型已转换为 8‑bit 推理模式")
# 🌐 serve_legal_qa.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
app = FastAPI(title="法律问答服务")
# 加载量化模型与分词器
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
"legal_lora_adapter",
torch_dtype=torch.float16,
device_map="cpu", # 推理可用 CPU
trust_remote_code=True
)
class Query(BaseModel):
question: str
@app.post("/predict")
def predict(q: Query):
prompt = f"法律问题:{q.question}\n回答:"
inputs = tokenizer(prompt, return_tensors="pt")
with torch.no_grad():
outputs = model.generate(**inputs, max_new_tokens=256, do_sample=False)
answer = tokenizer.decode(outputs[0], skip_special_tokens=True)
return {"answer": answer}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
该模型已经在内部 合同审查系统 中上线,平均每份合同处理时间 < 2 s,审查人员只需核对系统抽取的条款,大幅降低人工审阅时间。
站在 大模型 与 法律 交叉的十字路口,持续的 数据迭代、模型创新 与 业务落地 是我们不变的方向。
希望这篇 “垂直行业大模型微调:法律AI训练心得与反思” 能为你在法律AI的研发路上提供一些实操思路与灵感。如果还有其他具体问题(比如数据标注工具选型、模型压缩细节等),欢迎随时交流。祝你们训练顺利、落地成功!⚖️🤖🚀