
简介面向中文法律知识场景的大语言模型应用工程包定位为垂直领域大模型微调与推理的入门参考适合有一定技术基础、希望将大模型落地到法律等专业领域的开发者与研究人员。资源按数据处理、模型微调、推理合并、Web交互四大环节组织内置法律词汇表、指令微调与评测数据、LoRA权重目录、训练/推理/WebUI脚本以及模板配置与示例图片可帮助理解并复现完整的法律大模型应用流程。包体共42个文件以Python脚本12个、JSON数据6个、Shell脚本5个和JPEG示例图8个为主要构成辅以文本、PNG、Markdown、License等配置与说明材料压缩包整体仅3.41MB目录结构清晰、模块划分明确便于按需取用。目前已有120人学习/下载适合作为中文法律大模型工程落地与二次开发的参考样例。借助这些文件可掌握法律数据清洗、词表合并、LoRA微调、推理合并及WebUI展示的完整链路并基于可运行脚本快速搭建自己的实验环境。1. 中文法律大模型为什么通用大模型在法条面前失灵一位律师助理把某省高院的一份二审判决书喂给主流通用大模型问“该案争议焦点是什么”模型给出的答案是“房屋买卖合同纠纷——但判决书实际写的是股权转让纠纷”。这不是模型笨而是法律文本的语境密度远超日常语料法条之间有引用关系、有生效与废止状态、有地域司法解释差异通用模型预训练时根本没把这些“知识约束”当回事。所谓“基于中文法律知识的大语言模型”核心不在于“能聊天”而在于让模型在生成时尊重法条、尊重裁判逻辑、尊重文书结构。这类项目的实际落地形态通常不是从零预训练一个法律GPT——那需要几千张卡和PB级语料而是走“基座模型 法律指令微调 法律知识检索增强”的三层路线。适合谁来读如果你要做企业合规问答机器人、法院文书辅助生成、律所知识库检索或者只是想在自己机器上跑一个不胡说八道的法律助手这篇文把你需要的选型思路、部署命令和微调参数一次讲透。2. 基座模型选型与本地部署先把法律推理的“底座”立起来2.1 为什么选中文基座而不是直接套英文开源模型法律语言的特殊性在于“一词多义”极端明显民法中的“善意”和日常用语中的“善意”含义完全不同英文模型即使翻译准确也无法保留法言法语中的精确指代。因此基座模型必须选中文语料占比高、指令跟随能力强的开源模型。常见做法是选 Qwen 系列或 Baichuan 系列它们在中文法律文本上的字面理解能力优于同参数量级的 Llama 中文微调版因为预训练阶段的中文tokenizer切分更贴合法律术语。参数量怎么定如果你的场景只是“法条检索问答”7B 到 14B 足够如果要生成完整判决书或长篇法律意见书建议 32B 以上但显存成本会陡增。下面这张对比表是我在本地部署时常用的选型参考基座模型参数量推理显存需求BF164bit量化显存适合场景Qwen2.5-7B-Instruct7B约16GB约6GB法条问答、文书摘要Qwen2.5-14B-Instruct14B约30GB约10GB复杂法律推理、合同审查Baichuan2-13B-Chat13B约28GB约9GB中文法律长文本生成注意显存估算要加上 KV Cache 的占用实际部署时给上述数值再多留 20% 余量。4bit 量化会损失少量推理精度但如果只做检索问答损失几乎不可感知。2.2 用 Transformers 在本地拉起一个最小可用的法律问答服务部署这一步不需要先微调先把基座模型跑通确认它能理解法律指令的格式再做领域适配。下面是基于 Transformers 库的最小部署脚本我个人习惯先用这个脚本验证模型文件完整性和基础对话质量。from transformers import AutoModelForCausalLM, AutoTokenizer import torch model_path ./Qwen2.5-7B-Instruct tokenizer AutoTokenizer.from_pretrained(model_path, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained( model_path, torch_dtypetorch.bfloat16, device_mapauto, trust_remote_codeTrue ) query 根据《中华人民共和国民法典》第四百六十九条合同的形式有哪些 messages [{role: user, content: query}] text tokenizer.apply_chat_template( messages, tokenizeFalse, add_generation_promptTrue ) inputs tokenizer([text], return_tensorspt).to(model.device) outputs model.generate( inputs.input_ids, max_new_tokens1024, do_sampleFalse, temperature0.3, top_p0.9, repetition_penalty1.05 ) response tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokensTrue) print(response)这段脚本做了什么apply_chat_template把用户输入按模型预训练时的对话格式包好避免直接拼接导致指令跟随失效do_sampleFalse配合temperature0.3让输出偏确定性法律场景下不需要创造性发散repetition_penalty1.05防止模型在回答法条细节时翻来覆去说同一句。如果你先跑基座模型发现回答风格太“泛”不要急着调参那是预料之中的事法律知识的注入要靠微调和 RAG 解决。3. 中文法律指令数据构建与 LoRA 微调模型开始“说人话”3.1 法律指令数据的来源与清洗优先级没有高质量指令数据微调等于让模型学一堆废话。法律数据的来源优先级我一般这么排最高人民法院发布的指导性案例、公报案例、各地高院参考性案例这些文本结构完整、说理充分、法条引用规范其次是法律法规数据库中的法条原文与官方释义适合做“条文问答”对最后才是裁判文书网上的海量文书——但这部分噪声很大错别字、格式混乱、当事人信息混杂直接拿来微调会让模型学会“编造当事人名字”。数据清洗有两条硬规则。第一凡涉及当事人姓名、身份证号、住址等信息一律脱敏用占位符替换防止模型在生成时“回忆”出真实个人信息第二每条数据必须包含完整的“提问—回答”对而且问题不能只有一个标准答案要覆盖“法条查询”“案情分析”“文书生成”三种形态。下面是三种形态的指令模板示例。[ { instruction: 请根据以下案情判断该合同是否有效。案情张三与李四签订房屋买卖合同约定房屋售价为市场价的50%双方均已签字。, output: 该合同存在显失公平的可能。根据《中华人民共和国民法典》第一百五十一条一方利用对方处于危困状态、缺乏判断能力等情形致使民事法律行为成立时显失公平的受损害方有权请求人民法院或者仲裁机构予以撤销。若市场价50%的约定明显违反公平原则李四作为受损害方可主张撤销。 }, { instruction: 《民法典》第几条对格式条款的无效情形作了规定请列出条文原文。, output: 《中华人民共和国民法典》第四百九十七条规定有下列情形之一的该格式条款无效一具有本法第一编第六章第三节和本法第五百零六条规定的无效情形二提供格式条款一方不合理地免除或者减轻其责任、加重对方责任、限制对方主要权利三提供格式条款一方排除对方主要权利。 }, { instruction: 请根据以下信息生成一份民事起诉状的诉讼请求部分。原告甲公司被告乙公司事由乙公司拖欠货款50万元逾期3个月。, output: 诉讼请求1. 判令被告向原告支付货款人民币500,000元2. 判令被告向原告支付逾期付款利息以500,000元为基数自逾期之日起按全国银行间同业拆借中心公布的贷款市场报价利率的1.5倍计算至实际清偿之日止3. 本案诉讼费用由被告承担。 } ]3.2 用 LoRA 做参数高效微调显存不够也能训全参微调一个 7B 模型至少要 100GB 以上显存这不是大多数团队能负担的。常见做法是冻结基座模型参数只训练 LoRA 适配器可训练参数占比通常只有全参数的 1% 到 2%。这种方法的额外好处是法律知识被固化在一组低秩矩阵里切换业务场景时只需换适配器基座模型不动。下面是用 PEFT 库做 LoRA 微调的关键配置省略了数据处理细节聚焦在核心参数。from peft import LoraConfig, get_peft_model, TaskType from transformers import TrainingArguments, Trainer lora_config LoraConfig( task_typeTaskType.CAUSAL_LM, r64, lora_alpha16, lora_dropout0.05, target_modules[q_proj, k_proj, v_proj, o_proj, up_proj, down_proj] ) training_args TrainingArguments( output_dir./legal_lora_checkpoints, per_device_train_batch_size4, gradient_accumulation_steps8, learning_rate2e-4, num_train_epochs3, logging_steps50, save_steps500, fp16True, remove_unused_columnsFalse )r64是低秩矩阵的秩秩越大适配器容量越高但过拟合风险也上升法律数据量不到 10 万条时不需要超过 64lora_alpha16与r的比值影响最终缩放系数常见的经验值是alpha r / 4这样初始学习强度不会过大target_modules覆盖了注意力层和前馈层如果显存吃紧可以只保留q_proj和v_proj训练速度更快但效果会打折扣。微调完成后只保存 adapter 权重加载时用PeftModel.from_pretrained挂到基座模型上推理时和普通模型没有区别。注意微调数据里法条原文的“标准答案”必须精准到条、款、项。模型如果在一百条数据里学到同一个条文有两个版本它会自己“融合”出一个看似合理但实际不存在的条文——这在法律场景里是致命的。清洗时要做一次条文冲突检测同一个条号出现不同文本只保留最新效力版本。4. 检索增强生成RAG接入法律知识库让模型学会“查法条再回答”4.1 为什么微调之后还要 RAG微调把法律知识压缩进了模型权重但法律知识天然有时效性和版本性2020 年民法典生效后婚姻法、合同法、物权法同时废止模型即使在微调时记住了“旧法”的条文也不能因为新法没学透就答错。RAG 的作用是在生成前先检索知识库把最相关的法条片段拼进上下文让模型“照着条文说”。它既解决了知识时效问题也缓解了微调模型在长尾法条上的低置信度问题。RAG 的核心链路就四步知识库切片 → 向量化 → 相似度检索 → 注入上下文。切片这一步最容易踩坑——法律文本的语义边界和自然语言段落不一致一个法条可能横跨两页一个章节又包含多个独立规范。我常用的策略是以“条”为最小切片单位因为法律文书引用最少也是“第六百八十四条”模型需要的是完整的条而不是半句话。from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.vectorstores import Chroma from langchain_community.embeddings import HuggingFaceEmbeddings # 以条文为单位切分 splitter RecursiveCharacterTextSplitter( chunk_size800, chunk_overlap100, separators[\n\n第, \n第, \n, 。, ], ) with open(civil_code.txt, r, encodingutf-8) as f: full_text f.read() chunks splitter.split_text(full_text) embeddings HuggingFaceEmbeddings( model_nameBAAI/bge-large-zh-v1.5, encode_kwargs{normalize_embeddings: True} ) vectordb Chroma.from_texts( textschunks, embeddingembeddings, persist_directory./legal_kg, metadatas[{source: civil_code, chunk_index: i} for i in range(len(chunks))] ) vectordb.persist()这里的核心参数是separators的设定把“第”“条”作为切分锚点能最大程度保证一个 chunk 完整覆盖一条法条chunk_overlap100让相邻切片有重叠部分避免法条被从中间截断后语义断裂。选用 BGE embedding 模型是因为它在中文语义匹配任务上的综合表现优于同量级的 M3E 和 text2vec而且对短文本搜索更友好。法律文本中大段事实描述并不多长文档场景才需要考虑重排序模型知识库条目以法律条文为主的场景向量相似度已经够用。4.2 检索增强后的生成提示词设计拿到检索结果之后怎么塞给模型直接决定了回答质量。把检索到的法条原文全部堆进上下文不是一个好方案模型会迷失在冗长的条文里抓不住用户问题的核心。我一般会把检索结果按相关度排序取前 3 到 5 条然后用结构化的提示词让模型区分“可引用的依据”和“待回答的事实问题”。context_docs vectordb.similarity_search_with_score(query, k4) context_text \n\n.join([ f[法律依据 {i1}] {doc.page_content} for i, doc in enumerate(context_docs) ]) prompt f你是一名中国执业律师请基于以下法律依据回答用户问题。 回答要求先给出明确结论再说明依据如果检索到的法条不足以回答明确说“需要进一步审查案件事实”。 {context_text} 用户问题{query} 注意similarity_search_with_score返回的是文档和距离分数的元组score 越小表示相似度越高后续可以设置阈值过滤低相关片段。一个真实场景中常见的错误是用户问“合同违约金上限是多少”检索系统召回的是关于“定金”的条文因为字面相似度高而语义不符。这种情况靠调阈值没用需要在切片时给每一条法条增加“适用场景标签”元数据检索时做标签过滤而不是纯靠向量距离。5. 法律问答的结构化输出与正确性校验防止模型“一本正经地胡说八道”5.1 用 JSON Schema 约束模型输出法条引用法律场景和普通客服机器人的最大差异在于回答必须可以被复核。模型说“根据《民法典》第五百七十七条”时这条要真实存在、内容要对应、而且该条没有被废止。让模型自由生成文本你无法自动校验让模型先输出结构化引用信息再做程序化比对正确性才有保障。常见做法是在提示词中要求模型先输出一个 JSON 结构包含法条编号、条文内容和结论再用正则或代码解析校验。import json structured_prompt 请回答以下法律问题并严格按如下 JSON 格式输出 { conclusion: 结论性判断, legal_basis: [ { law_name: 法律名称, article_number: 条号, article_text: 条文原文 } ], analysis: 结合案情的分析过程 } 约束legal_basis 中的法律名称和条号必须在知识库中真实存在不得编造。 问题{query} response model_generate(structured_prompt) try: result json.loads(response) except json.JSONDecodeError: # 解析失败时回退到纯文本模式但要标记为“需要人工复核” result {conclusion: response, needs_review: True} legal_db_validate(result[legal_basis])这里有一个容易被忽视的工程点即使加了 JSON 格式约束开源模型偶尔也会输出残缺 JSON。不要只做异常捕获要做“回退策略”——解析失败时把原始输出交给人工复核队列而不是静默吞掉。legal_db_validate是一段比对函数去本地法条数据库查“法律名称 条号”是否存在以及条文文本和知识库是否一致不一致就标记为“引用疑似错误”绝不直接放给用户。5.2 用一致性校验发现模型幻觉的典型模式校验环节投入产出比最高的不是增加训练数据而是分析“幻觉出现的模式”。运行一批法律问答测试集后把模型的输出按错误类型分类你会发现幻觉高度集中在两种场景法条本身不存在模型自己“编”了一个条文号以及法条存在但内容张冠李戴把第六十条的内容说成第六十一条。第一种靠数据库比对就能拦截第二种需要判断语义一致性——提取条文文本和知识库对应文本的句子向量计算余弦相似度低于阈值就判为可疑。from sentence_transformers import SentenceTransformer import numpy as np model SentenceTransformer(BAAI/bge-large-zh-v1.5) def check_article_consistency(generated_text: str, db_text: str, threshold: float 0.82) - bool: emb_gen model.encode(generated_text, normalize_embeddingsTrue) emb_db model.encode(db_text, normalize_embeddingsTrue) similarity np.dot(emb_gen, emb_db) return similarity threshold阈值 0.82 是我在多个法律问答测试集上调出来的经验值对“引用错误条文号”的召回率约 97%但如果你把阈值提高到 0.9会误杀很多“模型用自己的话复述条文内容”的情况——复述和原文的向量相似度通常在 0.86 左右。这里的关键不是追求完美拦截而是把校验结果分成“通过”“可疑”“失败”三档可疑档进入人工抽查流程失败档直接拦截。6. 用裁判文书做回归评测验证法律微调效果的三个关键指标评测法律大模型不能只看对话流畅度——那会让“胡说八道但语气自信”的模型蒙混过关。我常用的评测方法是取 200 份真实裁判文书的“本院认为”部分把案情描述输入模型让模型生成法律结论然后与真实结论比对。三个指标最重要法条引用准确率生成的每一条法条引用是否真实存在且对应准确、结论方向一致性模型给出的支持/驳回/部分支持方向是否与判决一致、关键事实覆盖度判决书里提到的争议焦点模型是否在生成中覆盖到。python eval_legal_qa.py \ --model_path ./legal_lora_checkpoints \ --test_file judicial_opinions_200.jsonl \ --output_file eval_result.json \ --article_db ./legal_kg/law_articles.db \ --similarity_threshold 0.82评测脚本会输出一个结果矩阵每一行对应一条测试样本标记出法条引用列表、相似度得分、结论匹配情况。实际使用中的及格线是法条引用准确率不低于 90%结论方向一致性不低于 85%。如果你的模型卡在 80% 以下优先检查训练数据里有没有“旧法新条混用”的脏样本这比调 LoRA 的秩更有用。最后一个常见问题是“评测集从哪来”。网上能下到的开源中文法律 QA 数据集大多是编程题式的“法条一问一答”和真实裁判文书的复杂度差距很大。更可靠的方案是从公开裁判文书网站爬取 500 份文书自己做标注成本可控且领域贴合度高。本文还有配套的精品资源点击获取