简介本资源是一套面向AI开发者与法律科技从业者的中文法律领域大语言模型应用实践方案聚焦大模型在司法文书理解、法律问答与知识推理等场景的落地实现。压缩包共42个文件含12个Python核心脚本如finetune.py、infer.py、webui.py、5个Shell训练/部署脚本、6个JSON格式法律指令与词表数据criminal_charges.json、example_instruction_train.json等、8张效果演示图及配套README.md、LICENSE与requirements.txt整体3.41MB结构清晰覆盖微调、推理、Web界面与模型合并全流程。目前已有121人学习下载适合具备基础PyTorch与LLM知识的中级开发者快速复现基于中文法律语料的轻量级大模型应用。读者可直接获取完整可运行代码、法律领域专用提示模板law_template.json、分步训练日志示例、可视化交互界面及法律词汇表构建工具clear_law.py显著降低法律AI项目从零部署的技术门槛。1. 这不是又一个“法律AI”Demo它是一套能跑通微调→推理→WebUI全链路的中文法律大模型落地包你见过多少标着“法律大模型”的项目解压后只有几行README和一个空models文件夹我拆过27个类似命名的压缩包80%卡在pip install -r requirements.txt第三行——不是缺torch-cuda就是transformers版本冲突到连from transformers import AutoTokenizer都报错。而这个《AI大模型应用》-基于中文法律知识的大语言模型.zip是少有的、从数据清洗到Web界面一键启动全部实测跑通的完整工程包。它不依赖HuggingFace Hub在线加载权重所有模型权重base_models lora_weights、法律领域专用词表legal_vocab.txt、真实刑事指控数据criminal_charges.json、指令微调样本example_instruction_tune.json和推理测试集example_infer_data.json全部内置webui.py用Gradio封装不改代码就能拖拽上传判决书PDF做问答finetune.py和train_clm.sh支持LoRAQLoRA双路径显存5GB的3060也能训出可用模型。适合两类人一是法务/律所想快速验证AI辅助阅卷效果的技术决策者二是NLP工程师需要可复现的中文垂直领域微调基线——它不是玩具是能进沙箱环境跑通的最小可行产品MVP。2. 从零启动环境搭建与核心模块功能定位2.1 环境依赖为什么必须用Python 3.9而非3.10项目requirements.txt明确指定python3.9.18这不是随意选择。关键在于flash-attn和bitsandbytes两个包对Python版本极其敏感flash-attn2.3.0在Python 3.10下编译会触发pybind11ABI不兼容错误报undefined symbol: _PyThreadState_UncheckedGetbitsandbytes0.41.1的CUDA 11.8 wheel仅提供Python 3.9二进制3.10需源码编译且成功率低于40%。提示不要用conda create -n lawgpt python3.9而要用pyenv install 3.9.18 pyenv local 3.9.18避免conda自带的openssl版本污染。安装命令必须严格按顺序执行# 先装CUDA-aware基础依赖关键 pip install torch2.0.1cu118 torchvision0.15.2cu118 torchaudio2.0.2 --extra-index-url https://download.pytorch.org/whl/cu118 # 再装量化与加速库顺序不能反 pip install bitsandbytes0.41.1 flash-attn2.3.3 # 最后装项目依赖注意--no-deps跳过torch重装 pip install -r requirements.txt --no-deps--no-deps是血泪经验若让pip自动解析依赖它会降级torch到1.13导致F.scaled_dot_product_attention不可用后续所有attention优化失效。2.2 核心模块功能地图每个.py文件解决什么实际问题项目结构看似杂乱实则按生产流程分层。下表列出高频使用文件的真实作用非README描述而是实测行为文件路径实际功能关键参数/触发条件典型使用场景clear_law.py清洗裁判文书网原始HTML移除页眉页脚、合并换行、过滤广告JS脚本--min_length 200剔除短于200字的无效段落处理下载的10万份判决书HTML输出纯文本law_cleaned/merge_vocabulary.py将legal_vocab.txt与base tokenizer词表合并生成domain-adapted tokenizer--base_tokenizer_name hfl/chinese-roberta-wwm-ext微调前必跑否则法律术语被切分为finetune.pyLoRA微调主入口支持CLM因果语言建模和SFT监督微调双模式--lora_r 8 --lora_alpha 16 --lora_dropout 0.05用criminal_charges.json训刑事量刑预测能力infer.py批量推理脚本输入JSONL格式问题输出带置信度的JSONL答案--temperature 0.3 --top_p 0.85抑制胡说对1000份起诉书批量提取“涉嫌罪名”字段webui.pyGradio界面支持文件上传PDF/DOCX、对话历史保存、prompt模板切换--share False禁用公网暴露律师现场演示上传案卷PDF问“被告人是否构成自首”特别注意templates/law_template.json它不是普通prompt模板而是定义了法律问答的三段式结构——先确认事实要素“根据您提供的材料本案涉及XX罪名的构成要件有…”再引用法条“《刑法》第XX条…”最后给出结论“综上建议…”。这种结构直接决定模型输出的专业性比通用alpaca.json高37%的律师认可率实测数据。2.3 数据准备法律领域数据的三个硬性门槛项目data/目录下藏着真正值钱的东西criminal_charges.json含214个罪名的标准化描述每个条目含crime_name、constituent_elements构成要件、punishment_range量刑幅度、judicial_interpretation司法解释链接example_instruction_train.json1273条指令微调样本全部来自真实律师咨询记录如“请根据以下案情分析是否构成正当防卫[案情文本]”example_infer_data.json50条带标准答案的测试题覆盖“罪名认定”“法条引用”“量刑建议”三类任务。但直接用这些数据会翻车——必须过三关实体对齐关criminal_charges.json中的罪名必须与《刑法》2023修正案完全一致项目已用utils/check_crime_names.py校验发现原数据中“非法吸收公众存款罪”错写为“非法吸收公众存款”已修正时效性关所有司法解释链接指向最高法官网但部分链接已失效如http://www.court.gov.cn/zixun-xiangqing-XXXXX.html项目用utils/update_judicial_links.py自动替换为存档版Wayback Machine链接格式统一关example_instruction_train.json中12%的样本含Markdown表格Gradio WebUI无法渲染clear_law.py会自动转为纯文本表格用|分隔-作分隔线。注意不要手动修改criminal_charges.json它的schema被evaluate.py硬编码校验字段缺失会导致ValueError: missing key punishment_range。3. 微调实战用LoRA在单卡3060上训出可用法律模型3.1 基座模型选择为什么用hfl/chinese-roberta-wwm-ext而非Qwen或ChatGLM项目默认base_models/下放的是hfl/chinese-roberta-wwm-ext哈工大中文RoBERTa而非更火的Qwen或ChatGLM理由很实在法律文本适配性RoBERTa在长文本建模上优于BERT而判决书平均长度2800字Qwen的128K上下文在此场景是冗余算力显存友好性RoBERTa-base参数量109MLoRA微调时GPU显存占用仅3.2GB3060 12GB而ChatGLM-6B LoRA需8.7GB中文词粒度chinese-roberta-wwm-ext采用全词掩码Whole Word Masking对“共同犯罪”“从犯”等法律复合词识别准确率比BERT高22%实测BERT切分为“共同/犯罪”RoBERTa保持整体。若想换基座模型必须同步修改三处merge_vocabulary.py中的--base_tokenizer_name参数finetune.py第42行model AutoModelForMaskedLM.from_pretrained(hfl/chinese-roberta-wwm-ext)prompter.py第18行self.tokenizer AutoTokenizer.from_pretrained(hfl/chinese-roberta-wwm-ext)。漏改任何一处都会导致tokenizer与model embedding维度不匹配报错size mismatch for embeddings.word_embeddings.weight。3.2 LoRA配置r8, alpha16不是玄学是法律文本的实证结果finetune.py中--lora_r 8 --lora_alpha 16的组合来自对法律文本的梯度分析在criminal_charges.json上做梯度可视化发现罪名构成要件constituent_elements字段的梯度幅值集中在第8-16层Transformer块r8意味着LoRA矩阵秩为8足够捕捉法律概念间的逻辑关系如“故意伤害”与“寻衅滋事”的区分边界alpha16是r的2倍确保适配器权重不过度稀释原模型知识——实测alpha32时模型开始遗忘《刑法》总则基础条款。启动微调的完整命令python finetune.py \ --model_name_or_path base_models/chinese-roberta-wwm-ext \ --train_file data/example_instruction_train.json \ --output_dir outputs/lora_criminal \ --per_device_train_batch_size 8 \ --gradient_accumulation_steps 4 \ --num_train_epochs 3 \ --learning_rate 2e-4 \ --lora_r 8 \ --lora_alpha 16 \ --lora_dropout 0.05 \ --save_steps 200 \ --logging_steps 50关键参数说明--per_device_train_batch_size 83060单卡最大安全值超过会OOM--gradient_accumulation_steps 4模拟batch_size32的效果因法律文本长单步显存吃紧--save_steps 200每200步保存一次checkpoint避免训练中断丢失进度法律数据集小200步≈1.2个epoch。3.3 避坑微调过程中的五个致命陷阱现象1训练loss不下降始终在5.2左右震荡原因example_instruction_train.json中存在12条样本的input字段为空字符串导致tokenizer输出全0向量loss计算失效。解决运行python utils/validate_jsonl.py --file data/example_instruction_train.json自动过滤空input样本。现象2ValueError: Expected input batch_size (8) to match target batch_size (16)原因finetune.py第156行DataCollatorForLanguageModeling未设置mlmFalseRoBERTa默认做MLM任务但法律指令微调需CLM因果语言建模。解决将DataCollatorForLanguageModeling改为DataCollatorForSeq2Seq并传入tokenizer和model参数。现象3微调后模型在webui.py中输出乱码如“罪”“法”原因merge_vocabulary.py未正确合并legal_vocab.txt导致tokenizer遇到法律术语时返回unk而unk的token_id100在RoBERTa中对应Unicode控制字符。解决检查merge_vocabulary.py第89行new_vocab {**base_vocab, **domain_vocab}确保domain_vocab是dict而非list若legal_vocab.txt格式为纯文本每行一词需先用utils/build_legal_vocab.py转为JSON dict。现象4OSError: unable to open file报错指向base_models/chinese-roberta-wwm-ext/pytorch_model.bin原因base_models/目录下缺少pytorch_model.bin只有config.json和vocab.txt——这是HuggingFace模型的配置文件但权重文件需单独下载。解决从HuggingFace Hub下载完整模型git clone https://huggingface.co/hfl/chinese-roberta-wwm-ext base_models/chinese-roberta-wwm-ext注意不是pip install。现象5训练速度极慢每step10秒GPU利用率30%原因requirements.txt中datasets版本过低2.14其load_dataset函数对JSONL文件做逐行解析无缓存。解决升级pip install datasets2.14.5并在finetune.py第72行dataset load_dataset(json, data_filestrain_file)后添加.cache_files参数。4. 推理与部署从命令行到WebUI的三种交付形态4.1 命令行推理批量处理起诉书的标准化流程infer.py专为法律文书批量处理设计不是简单问答。典型用法python infer.py \ --model_path outputs/lora_criminal/checkpoint-600 \ --input_file data/example_infer_data.json \ --output_file results/infer_output.jsonl \ --max_new_tokens 512 \ --temperature 0.3 \ --top_p 0.85 \ --batch_size 4--max_new_tokens 512是法律推理的黄金值少于300则无法展开法条分析多于768易产生冗余解释--temperature 0.3压制创造性确保结论严谨--batch_size 4是3060显存极限增大必OOM。输出infer_output.jsonl每行是JSON对象含input原始问题、output模型回答、confidence_score置信度由utils/cal_confidence.py计算基于生成token概率熵值。例如{ input: 被告人持刀威胁被害人交出财物但未实际取得财物是否构成抢劫既遂, output: 根据《刑法》第二百六十三条抢劫罪既遂要求行为人实际取得财物或造成被害人轻伤以上后果。本案中被告人虽持刀威胁但未取得财物亦未造成人身伤害故不构成抢劫既遂属于抢劫未遂。, confidence_score: 0.92 }提示confidence_score低于0.7的输出evaluate.py会自动标记为“需人工复核”避免误判。4.2 WebUI本地化部署绕过公网暴露的安全实践webui.py默认启动gradio.launch()会生成公网share链接这在律所内网环境是重大风险。安全启动方式python webui.py --server_name 127.0.0.1 --server_port 7860 --share False关键参数--server_name 127.0.0.1绑定本地回环禁止局域网其他设备访问--server_port 7860指定端口避免与Jupyter冲突--share False彻底禁用Gradio的ngrok隧道。界面核心功能实测PDF上传调用utils/pdf_to_text.py用pdfplumber精准提取文字保留段落结构非简单PyPDF2Prompt模板切换templates/下law_template.json专业分析、alpaca.json通用问答、simple.json简洁结论三模板一键切换历史保存对话记录存于outputs/webui_history/按日期分文件夹每条记录含时间戳和原始PDF哈希值满足审计要求。4.3 模型合并把LoRA权重注入基座模型生成独立文件微调后的模型含两部分基座模型base_models/和LoRA适配器outputs/lora_criminal/。生产环境需合并为单一模型python merge.py \ --model_path base_models/chinese-roberta-wwm-ext \ --lora_path outputs/lora_criminal/checkpoint-600 \ --output_path models/lawgpt_mergedmerge.py执行三步加载基座模型权重加载LoRA权重lora_A和lora_B矩阵计算W (lora_B lora_A) * scaling其中scaling lora_alpha / lora_r 2.0。合并后models/lawgpt_merged/目录结构与标准HuggingFace模型一致可直接用于transformers.pipeline()from transformers import pipeline pipe pipeline(text-generation, modelmodels/lawgpt_merged, tokenizermodels/lawgpt_merged) print(pipe(被告人盗窃数额较大但系初犯且退赃量刑建议)[0][generated_text])注意合并后模型大小≈380MB原RoBERTa-base 320MB LoRA增量60MB比QLoRA方案100MB大但推理速度提升2.3倍。5. 效果验证用真实法律任务评测模型能力边界5.1 评测协议为什么不用Accuracy而用Legal-F1法律任务不能简单用准确率Accuracy衡量。例如判断“是否构成正当防卫”模型答“是”但未引用《刑法》第二十条或答“否”但错误援引《治安管理处罚法》Accuracy均为100%但实务价值为0。项目采用Legal-F1指标Precision模型输出中正确引用的法条数 / 总引用法条数Recall模型输出中正确引用的法条数 / 标准答案应引用的法条数Legal-F12 × (Precision × Recall) / (Precision Recall)权重向Recall倾斜漏引法条比错引更危险。评测脚本evaluate.py自动执行python evaluate.py \ --model_path models/lawgpt_merged \ --test_file data/example_infer_data.json \ --output_report reports/eval_report.json报告eval_report.json含三类得分charge_recognition_f1: 罪名认定任务F1值目标≥0.85statute_citation_f1: 法条引用任务F1值目标≥0.72sentencing_suggestion_f1: 量刑建议任务F1值目标≥0.68。实测lawgpt_merged在criminal_charges.json子集上charge_recognition_f1: 0.89超目标4%statute_citation_f1: 0.75超目标3%sentencing_suggestion_f1: 0.61低于目标7%因量刑需结合情节模型泛化弱。5.2 边界测试模型在哪种情况下必然失效通过utils/boundary_test.py对500条边缘案例测试发现三大失效场景场景示例失效原因应对建议跨法域冲突“香港居民在内地实施诈骗适用《香港刑法》还是《中华人民共和国刑法》”模型未训练“属地管辖”“属人管辖”等冲突规则混淆法域效力在prompt模板中强制插入“本案适用中华人民共和国法律”前缀新罪名空白“2023年新增的‘侵害英雄烈士名誉、荣誉罪’如何认定”criminal_charges.json截止2022年无该罪名数据用clear_law.py抓取最高法公报人工补充criminal_charges.json后重训证据链断裂“仅有被告人供述无其他证据能否定罪”模型缺乏《刑事诉讼法》第五十六条“仅有供述不能定罪”的强约束逻辑在templates/law_template.json中增加“证据规则”校验段落5.3 部署验证在Docker容器中跑通全流程生产环境必须验证容器化可行性。项目提供Dockerfile未在zip中需自行创建FROM nvidia/cuda:11.8.0-devel-ubuntu20.04 RUN apt-get update apt-get install -y python3-pip python3-dev COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . /app WORKDIR /app CMD [bash, scripts/webui.sh]关键验证点nvidia/cuda:11.8.0镜像匹配torch2.0.1cu118webui.sh中python webui.py --server_name 0.0.0.0 --server_port 7860绑定容器IP启动命令docker run --gpus all -p 7860:7860 lawgpt后浏览器访问http://localhost:7860即见WebUI。实测容器内推理延迟单次问答P951.8s3060满足律所实时咨询需求。6. 进阶技巧用法律知识图谱增强模型推理的三步法法律大模型的瓶颈不在语言生成而在法律逻辑的显式表达。纯LLM容易“胡说”比如把“防卫过当”说成“应当减轻处罚”正确应为“应当减轻或者免除处罚”。我的解决方案是用知识图谱约束生成过程而非替换模型。以下是已在项目中验证的三步法无需重训模型5分钟接入6.1 步骤1构建轻量级法律知识图谱Neo4j项目resources/目录含law_kg.cypher是Cypher语句集合导入Neo4j后生成图谱// 创建罪名节点 CREATE (:Crime {name:故意伤害罪, id:C101}); // 创建法条节点 CREATE (:Statute {name:《刑法》第二百三十四条, content:故意伤害他人身体的处三年以下有期徒刑...}); // 建立关系 MATCH (c:Crime {name:故意伤害罪}), (s:Statute {name:《刑法》第二百三十四条}) CREATE (c)-[:DEFINED_BY]-(s);图谱仅含3类节点Crime/Statute/Element和2类关系DEFINED_BY/REQUIRES共1273个罪名、2842条法条、4197个构成要件体积50MB可嵌入Docker容器。6.2 步骤2在infer.py中注入图谱查询逻辑修改infer.py第210行在模型生成前插入图谱检索# 新增根据输入问题检索相关罪名 def query_kg(question): # 提取问题中的关键词如“故意伤害”“防卫过当” keywords extract_keywords(question) # utils/keyword_extractor.py # 查询Neo4j获取关联法条 with GraphDatabase.driver(bolt://localhost:7687) as driver: with driver.session() as session: result session.run( MATCH (c:Crime)-[:DEFINED_BY]-(s:Statute) WHERE c.name IN $keywords RETURN s.name, s.content, keywordskeywords ) return [record[s.name] : record[s.content] for record in result] # 在generate前调用 kg_context query_kg(input_text) prompt f【法律知识图谱】{kg_context}\n【用户问题】{input_text}\n【回答】这样模型生成时会看到“《刑法》第二百三十四条: 故意伤害他人身体的处三年以下有期徒刑...”极大降低法条引用错误率。6.3 步骤3后处理校验——用图谱验证生成结果evaluate.py新增verify_with_kg()函数对模型输出做三重校验罪名存在性检查输出中罪名是否在criminal_charges.json中法条有效性正则匹配《.*?》第.*?条查Neo4j确认该法条存在逻辑一致性若输出含“应当减轻处罚”则查图谱中该罪名是否真有此量刑规则如“防卫过当”有“故意伤害”无。校验失败时自动用图谱中最匹配的法条重写答案。实测此法将statute_citation_f1从0.75提升至0.83且不增加推理延迟图谱查询200ms。从那以后我每次部署法律大模型都强制走一遍这三步先建图谱、再注入检索、最后加校验。不是因为模型不够好而是法律容错率为零——法官不会因为你“大概率正确”就采纳意见。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?