基于Qwen、RAG与LoRA构建垂直领域大模型:以法律智能应用为例

📅 2026/8/18 22:00:14
基于Qwen、RAG与LoRA构建垂直领域大模型:以法律智能应用为例
在尝试将大模型应用于法律领域时你是否遇到过这样的困境模型对专业法律术语理解不深回答流于表面甚至“一本正经地胡说八道”或者想针对特定法律任务微调模型却苦于数据量小、算力有限不知从何下手本文将以“刑法大模型”为实战目标手把手带你打通从零到一的全链路。我们将融合Qwen通义千问作为基座模型利用RAG检索增强生成注入精准的法律知识库并通过LoRA低秩适应进行轻量化微调最终实现罪名识别、刑期预测、司法解释生成三大核心功能。整个过程不仅包含清晰的代码和配置更会以“学长带debug”的视角剖析每一步可能遇到的坑及其解决方案确保你能成功复现并应用于自己的领域。无论你是想入门大模型应用开发的学生还是希望将AI能力落地到垂直领域的开发者这篇涵盖环境搭建、数据处理、模型训练与部署的完整教程都将为你提供一套可直接复用的工程化方案。1. 项目背景与核心技术栈解析在深入代码之前我们有必要厘清这个项目要解决的核心问题以及为什么选择Qwen、RAG、LoRA这三项技术。1.1 为什么需要“刑法大模型”通用大模型如ChatGPT、通义千问在开放域对话上表现卓越但在法律、医疗等高度专业化、强逻辑、重事实的垂直领域往往存在以下短板知识幻觉可能编造不存在的法条或司法解释。精度不足对相似罪名如“盗窃罪”与“侵占罪”的区分能力弱。缺乏推理刑期预测需要综合考量情节、数额、悔罪表现等多重因素通用模型难以进行量化推理。知识更新滞后模型训练数据有截止日期无法即时获取最新的法律修订和判例。因此我们需要一个专精于刑法领域的“专家模型”。1.2 技术选型Qwen RAG LoRA我们采用“基座模型 知识增强 轻量微调”的三层架构在效果、成本与可行性间取得平衡。基座模型Qwen通义千问为什么选它Qwen系列模型由阿里云开源具有优秀的中文理解与生成能力对中文法律文本友好。其开源协议宽松支持商用且提供了从1.8B到72B的不同规模版本便于根据算力选择。本文将以Qwen2.5-7B-Instruct版本为例它在指令跟随和推理上表现更佳。作用提供强大的语言理解和生成基础能力。知识增强RAG检索增强生成是什么RAG通过外挂一个知识库如法律条文、判例文书来弥补大模型内部知识的不足或过时。其工作流程为用户提问 - 从知识库中检索相关文档 - 将文档作为上下文与大模型问题一并输入 - 模型生成基于可靠知识的答案。为什么需要确保模型回答的法律依据如刑法第几条绝对准确、可追溯杜绝知识幻觉。对于“根据XX法盗窃罪如何量刑”这类问题RAG能直接检索出法条原文作为生成依据。技术组件通常包含文档加载器、文本分割器、向量数据库如ChromaDB, FAISS、嵌入模型如BGE和检索链。能力微调LoRA低秩适应是什么LoRA是一种高效的微调技术。它不在整个庞大的模型参数上做调整而是通过注入额外的、秩很低的矩阵来模拟全参数微调的效果。这些新增的参数远小于原模型训练速度快显存占用低。为什么需要为了让模型学会“刑法领域”特有的任务格式和推理模式。例如教会模型按照“案情描述 - 罪名分析 - 法条引用 - 刑期预测”的结构化方式输出。仅靠RAG提供知识模型可能不会以我们想要的格式回答。LoRA就是用来调整模型“行为模式”的。优势轻量、高效、可插拔。训练好的LoRA权重文件很小通常几十到几百MB可以轻松加载到基座模型上实现能力增强。三者关系总结Qwen是大脑RAG是随时可查阅的精准法律图书馆LoRA是让大脑更擅长处理法律考题的特训课程。三者结合才能打造出既知识准确又擅长法律推理的专用模型。2. 环境准备与项目搭建工欲善其事必先利其器。我们先搭建一个清晰、可复现的开发环境。2.1 硬件与软件要求操作系统Linux (Ubuntu 20.04/22.04) 或 Windows (WSL2)。本文以 Ubuntu 22.04 为例。GPU强烈推荐使用 NVIDIA GPU 进行微调和推理。训练LoRARTX 3090 (24GB) 或 RTX 4090 (24GB) 是较好的起点。仅推理可使用显存更小的GPU或CPU速度较慢。Python3.9 或 3.10。CUDA 11.8与PyTorch版本匹配。2.2 创建虚拟环境与安装依赖首先创建一个独立的Python环境以避免包冲突。# 创建并激活虚拟环境 conda create -n law_llm python3.10 -y conda activate law_llm # 或使用 venv # python -m venv law_llm # source law_llm/bin/activate # Linux # law_llm\Scripts\activate # Windows接下来安装核心依赖。我们将使用transformers,peft(用于LoRA),accelerate,langchain和chromadb。# 安装PyTorch (请根据你的CUDA版本访问 https://pytorch.org/ 获取最新命令) # 例如对于 CUDA 11.8 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 安装 transformers, datasets, peft, accelerate (用于模型加载和训练) pip install transformers datasets peft accelerate # 安装 langchain 及相关组件 (用于构建RAG) pip install langchain langchain-community langchain-chroma # 安装向量数据库和嵌入模型 pip install chromadb sentence-transformers # 安装其他工具库 pip install jupyter pandas tqdm2.3 项目目录结构一个清晰的项目结构有助于管理代码、数据和模型。law_llm_project/ ├── data/ # 存放原始和预处理后的数据 │ ├── raw/ # 原始法律文本刑法条文、司法解释等 │ ├── processed/ # 处理后的数据用于RAG和微调 │ └── dataset/ # 微调任务数据集 ├── knowledge_base/ # RAG知识库存储ChromaDB持久化路径 ├── scripts/ # 执行脚本 │ ├── build_kb.py # 构建知识库脚本 │ ├── train_lora.py # LoRA微调脚本 │ └── inference.py # 推理演示脚本 ├── models/ # 存放下载的基座模型和训练好的LoRA权重 │ ├── Qwen2.5-7B-Instruct/ │ └── lora_law/ ├── config/ # 配置文件 │ └── lora_config.json ├── requirements.txt # 项目依赖 └── README.md你可以使用以下命令快速创建这个结构mkdir -p law_llm_project/{data/{raw,processed,dataset},knowledge_base,scripts,models,config} cd law_llm_project3. 构建法律知识库RAG核心RAG的效果高度依赖于知识库的质量。我们的知识库需要包含《中华人民共和国刑法》条文、重要的司法解释如关于盗窃、诈骗等罪的数额认定标准以及典型的指导案例摘要。3.1 数据收集与预处理步骤1准备原始文本将刑法全文可从权威法律网站获取保存为data/raw/criminal_law.txt。每一条文最好单独一行或用一个分隔符隔开。 示例criminal_law.txt内容格式第二百六十四条 【盗窃罪】盗窃公私财物数额较大的或者多次盗窃、入户盗窃、携带凶器盗窃、扒窃的处三年以下有期徒刑、拘役或者管制并处或者单处罚金数额巨大或者有其他严重情节的处三年以上十年以下有期徒刑并处罚金数额特别巨大或者有其他特别严重情节的处十年以上有期徒刑或者无期徒刑并处罚金或者没收财产。 第二百六十六条 【诈骗罪】诈骗公私财物数额较大的处三年以下有期徒刑、拘役或者管制并处或者单处罚金数额巨大或者有其他严重情节的处三年以上十年以下有期徒刑并处罚金数额特别巨大或者有其他特别严重情节的处十年以上有期徒刑或者无期徒刑并处罚金或者没收财产。 ...步骤2编写知识库构建脚本创建scripts/build_kb.py# scripts/build_kb.py import os from langchain_community.document_loaders import TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.embeddings import HuggingFaceEmbeddings from langchain_community.vectorstores import Chroma from langchain.docstore.document import Document def build_knowledge_base(): # 1. 加载法律文本 raw_path ./data/raw/criminal_law.txt if not os.path.exists(raw_path): print(f错误未找到原始法律文件 {raw_path}) return loader TextLoader(raw_path, encodingutf-8) documents loader.load() # 2. 分割文本 # 法律条文本身有结构适合按章节或条文分割这里使用递归字符分割作为备选 text_splitter RecursiveCharacterTextSplitter( chunk_size500, # 每个片段约500字符 chunk_overlap50, # 片段间重叠50字符保持上下文 separators[\n\n, \n, 。, , , , ] # 中文分隔符优先 ) splits text_splitter.split_documents(documents) print(f原始文档分割为 {len(splits)} 个片段。) # 3. 选择嵌入模型 (使用轻量且效果好的中文模型) # 也可以使用 OpenAI API但本地部署推荐开源模型 model_name BAAI/bge-small-zh-v1.5 # 中文嵌入模型效果不错且速度快 embeddings HuggingFaceEmbeddings( model_namemodel_name, model_kwargs{device: cuda}, # 使用GPU加速 encode_kwargs{normalize_embeddings: True} # 归一化提升检索效果 ) # 4. 创建并持久化向量数据库 persist_directory ./knowledge_base/chroma_law vectordb Chroma.from_documents( documentssplits, embeddingembeddings, persist_directorypersist_directory ) vectordb.persist() # 持久化到磁盘 print(f知识库已构建并保存至 {persist_directory}) # 5. 简单测试检索 query 盗窃罪如何量刑 docs vectordb.similarity_search(query, k2) print(f\n测试检索问题{query}) for i, doc in enumerate(docs): print(f\n--- 相关片段 {i1} ---) print(doc.page_content[:200] ...) # 打印前200字符 if __name__ __main__: build_knowledge_base()步骤3运行脚本构建知识库cd law_llm_project python scripts/build_kb.py如果一切顺利你会看到知识库构建完成并输出与“盗窃罪”相关的法条片段。3.2 Debug 要点知识库构建常见问题问题1No module named langchain_community原因LangChain 版本更新部分模块路径发生变化。解决确保安装的是较新版本pip install langchain-community。如果还报错可以尝试from langchain.embeddings import HuggingFaceEmbeddings旧路径但建议使用新路径以保持兼容性。问题2嵌入模型下载慢或失败原因从Hugging Face下载模型可能受网络影响。解决使用国内镜像源export HF_ENDPOINThttps://hf-mirror.com(Linux) 或设置环境变量。或者先手动下载模型到本地然后修改model_name为本地路径。# 假设模型下载到了 ./models/bge-small-zh model_name ./models/bge-small-zh问题3检索结果不相关原因文本分割策略不当或嵌入模型不适合中文法律文本。解决调整分割器尝试CharacterTextSplitter或按特定分隔符如“第xxx条”分割。尝试其他嵌入模型如moka-ai/m3e-base在中文语义搜索上表现也很好。检查原始文本质量确保文本清晰没有乱码或多余格式。4. 准备LoRA微调数据集为了让模型学会执行“罪名识别”、“刑期预测”等特定任务我们需要准备指令微调数据集。数据格式通常为instruction-input-output。4.1 数据集格式设计我们创建一个合成数据集。在实际项目中应使用更高质量的标注数据。创建data/dataset/train.jsonl(JSON Lines格式)每条数据如下{ instruction: 请根据以下案情描述分析可能构成的罪名并预测可能的刑期范围。请以罪名法条依据刑期预测的格式回答。, input: 张三于2023年5月夜间潜入某小区多户居民家中窃取手机、笔记本电脑等财物总计价值人民币5万元。归案后张三如实供述了自己的罪行并积极退赔了部分赃款。, output: 罪名盗窃罪。\n法条依据《中华人民共和国刑法》第二百六十四条。盗窃公私财物数额巨大的处三年以上十年以下有期徒刑并处罚金。本案盗窃数额为5万元根据相关司法解释属于‘数额巨大’范畴。\n刑期预测考虑到张三有入户盗窃情节法定加重情节但具有如实供述、部分退赔等酌定从轻情节综合预测刑期可能在四年至六年有期徒刑之间并处罚金。 }{ instruction: 请生成关于‘抢劫罪’中‘携带凶器抢夺’认定的司法解释摘要。, input: , output: 根据《最高人民法院关于审理抢劫刑事案件适用法律若干问题的解释》第六条规定携带凶器抢夺是指行为人随身携带枪支、爆炸物、管制刀具等国家禁止个人携带的器械进行抢夺或者为了实施犯罪而携带其他器械进行抢夺的行为。行为人将随身携带凶器有意加以显示、能为被害人察觉到的直接适用刑法第二百六十三条的规定定罪处罚即认定为抢劫罪。 }你需要准备数百到数千条这样的高质量数据涵盖多种罪名、情节和任务类型。4.2 数据集加载脚本创建scripts/prepare_data.py来加载和格式化数据供训练使用。# scripts/prepare_data.py import json from datasets import Dataset def load_and_format_data(file_path): instructions [] inputs [] outputs [] with open(file_path, r, encodingutf-8) as f: for line in f: data json.loads(line.strip()) instructions.append(data[instruction]) inputs.append(data[input]) outputs.append(data[output]) # 构建模型输入格式将instruction和input组合成prompt prompts [] for instr, inp in zip(instructions, inputs): if inp: prompt f{instr}\n\n{inp} else: prompt instr prompts.append(prompt) # 创建 Hugging Face Dataset 对象 dataset_dict { prompt: prompts, completion: outputs } dataset Dataset.from_dict(dataset_dict) return dataset if __name__ __main__: train_dataset load_and_format_data(./data/dataset/train.jsonl) print(f训练集样本数{len(train_dataset)}) print(train_dataset[0])5. LoRA微调Qwen模型这是项目的核心环节。我们将使用peft和transformers库来微调Qwen2.5-7B-Instruct模型。5.1 下载基座模型建议使用huggingface-cli或snapshot_download下载模型。确保你有足够的磁盘空间约15GB。# 方法1使用 huggingface-cli (需先登录 huggingface-cli login) pip install huggingface-hub huggingface-cli download Qwen/Qwen2.5-7B-Instruct --local-dir ./models/Qwen2.5-7B-Instruct # 方法2在Python代码中下载如下一步脚本所示5.2 编写LoRA微调脚本创建scripts/train_lora.py。这是一个完整的训练脚本包含了模型加载、LoRA配置、训练参数设置和训练循环。# scripts/train_lora.py import torch from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer from peft import LoraConfig, get_peft_model, TaskType from datasets import load_from_disk import os from huggingface_hub import snapshot_download # 1. 模型与分词器加载 model_name_or_path Qwen/Qwen2.5-7B-Instruct local_model_path ./models/Qwen2.5-7B-Instruct # 如果本地没有模型则下载 if not os.path.exists(local_model_path): print(f本地未找到模型正在从Hugging Face下载 {model_name_or_path} ...) snapshot_download(repo_idmodel_name_or_path, local_dirlocal_model_path) print(下载完成。) print(加载分词器...) tokenizer AutoTokenizer.from_pretrained(local_model_path, trust_remote_codeTrue) # Qwen模型需要设置padding_side通常为left用于生成 tokenizer.padding_side left if tokenizer.pad_token is None: tokenizer.pad_token tokenizer.eos_token # 设置pad token print(加载模型...) model AutoModelForCausalLM.from_pretrained( local_model_path, torch_dtypetorch.bfloat16, # 使用BF16节省显存并保持精度 device_mapauto, # 自动分配模型层到可用设备GPU/CPU trust_remote_codeTrue ) # 2. 配置LoRA lora_config LoraConfig( task_typeTaskType.CAUSAL_LM, # 因果语言模型任务 r8, # LoRA秩影响参数量通常8,16,32 lora_alpha32, # 缩放因子 lora_dropout0.1, # Dropout概率防止过拟合 target_modules[q_proj, k_proj, v_proj, o_proj], # 在QKV和输出投影层添加LoRA biasnone, # 是否训练偏置 ) # 将原模型转换为PeftModel仅训练LoRA参数 model get_peft_model(model, lora_config) model.print_trainable_parameters() # 打印可训练参数量应该只占原模型很小一部分 # 3. 数据准备 from prepare_data import load_and_format_data # 导入之前写的数据处理函数 train_dataset load_and_format_data(./data/dataset/train.jsonl) # 假设我们划分一小部分作为验证集 split_dataset train_dataset.train_test_split(test_size0.1, seed42) train_data split_dataset[train] eval_data split_dataset[test] # 数据预处理函数将文本转换为模型输入所需的token IDs def tokenize_function(examples): # 将prompt和completion拼接中间加一个分隔符如\n\nAssistant: # 对于Qwen Instruct模型通常格式为|im_start|user\n{prompt}|im_end|\n|im_start|assistant\n{completion}|im_end| # 这里我们简化处理直接拼接。更严谨的做法是使用模型特定的chat template。 texts [p \n\n c for p, c in zip(examples[prompt], examples[completion])] # 对拼接后的文本进行tokenize tokenized tokenizer(texts, truncationTrue, paddingmax_length, max_length512) # 将标签设置为与输入相同用于计算损失但需要忽略掉prompt部分的损失 labels tokenized[input_ids].copy() # 假设我们只想计算completion部分的损失需要将prompt部分的标签设为-100 # 这里简化处理实际应根据模型模板和prompt长度精确计算 # 这是一个需要根据实际情况调整的关键点 prompt_lengths [len(tokenizer.encode(p, truncationTrue, max_length512)) for p in examples[prompt]] for i, label in enumerate(labels): prompt_len prompt_lengths[i] label[:prompt_len] [-100] * prompt_len # 将prompt部分的标签设为-100忽略损失 tokenized[labels] labels return tokenized tokenized_train train_data.map(tokenize_function, batchedTrue) tokenized_eval eval_data.map(tokenize_function, batchedTrue) # 4. 设置训练参数 training_args TrainingArguments( output_dir./models/lora_law, # 输出目录 num_train_epochs3, # 训练轮数 per_device_train_batch_size2, # 每个设备的训练批次大小根据GPU显存调整 per_device_eval_batch_size2, gradient_accumulation_steps4, # 梯度累积步数模拟更大batch size warmup_steps100, # 学习率预热步数 logging_steps10, # 每多少步打印一次日志 eval_steps50, # 每多少步评估一次 save_steps200, # 每多少步保存一次检查点 evaluation_strategysteps, save_strategysteps, load_best_model_at_endTrue, # 训练结束后加载最佳模型 metric_for_best_modeleval_loss, # 根据评估损失选择最佳模型 greater_is_betterFalse, learning_rate2e-4, # 学习率LoRA通常可以设大一点 fp16True, # 使用混合精度训练节省显存 # bf16True, # 如果GPU支持BF16优先用BF16 gradient_checkpointingTrue, # 梯度检查点用时间换显存 optimpaged_adamw_8bit, # 使用8-bit优化器进一步节省显存 report_totensorboard, # 可选记录到tensorboard save_total_limit3, # 最多保存3个检查点 ) # 5. 创建Trainer并开始训练 trainer Trainer( modelmodel, argstraining_args, train_datasettokenized_train, eval_datasettokenized_eval, tokenizertokenizer, # data_collator..., # 可以使用默认的 ) print(开始训练...) trainer.train() # 6. 保存LoRA权重 print(训练完成保存LoRA适配器...) model.save_pretrained(./models/lora_law_final) tokenizer.save_pretrained(./models/lora_law_final) print(LoRA权重已保存至 ./models/lora_law_final)5.3 Debug 要点LoRA训练常见坑问题1CUDA Out Of Memory (OOM)原因模型、批次大小、序列长度超出GPU显存。解决减小per_device_train_batch_size。启用梯度检查点(gradient_checkpointingTrue)。使用更低的精度(fp16True或bf16True)。使用optimpaged_adamw_8bit或adamw_bnb_8bit优化器。减小max_length如从512降到256。使用device_mapauto让accelerate自动将部分层卸载到CPU或磁盘速度会慢。问题2损失不下降或输出乱码原因学习率不合适LoRA学习率通常可以设得比全参数微调大如1e-4到5e-4。数据格式错误模型没有正确理解指令格式。这是最常见的问题标签掩码错误在tokenize_function中没有正确地将prompt部分的损失忽略标签设为-100。解决调整学习率。严格按照基座模型要求的对话模板格式化数据。对于Qwen Instruct应使用其apply_chat_template方法。修改数据预处理部分from transformers import AutoTokenizer tokenizer AutoTokenizer.from_pretrained(local_model_path, trust_remote_codeTrue) # 使用模型的chat template messages [ {role: user, content: prompt}, {role: assistant, content: completion} ] text tokenizer.apply_chat_template(messages, tokenizeFalse, add_generation_promptFalse) tokenized tokenizer(text, ...)仔细检查并修正标签掩码逻辑。问题3RuntimeError: expected scalar type Float but found Half原因混合精度训练时数据类型不匹配。解决确保模型加载时指定了torch_dtype如torch.float16或torch.bfloat16并与TrainingArguments中的fp16/bf16设置一致。6. 整合推理RAG LoRA Qwen训练完成后我们将加载基础模型、LoRA权重以及RAG知识库构建一个完整的推理管道。6.1 推理脚本编写创建scripts/inference.py# scripts/inference.py import torch from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline from peft import PeftModel, PeftConfig from langchain_community.vectorstores import Chroma from langchain_community.embeddings import HuggingFaceEmbeddings class LawRAGLoRAAssistant: def __init__(self, base_model_path, lora_model_path, knowledge_base_path): # 1. 加载模型和分词器 (基座 LoRA) print(加载基座模型和分词器...) self.tokenizer AutoTokenizer.from_pretrained(base_model_path, trust_remote_codeTrue) self.tokenizer.padding_side left if self.tokenizer.pad_token is None: self.tokenizer.pad_token self.tokenizer.eos_token base_model AutoModelForCausalLM.from_pretrained( base_model_path, torch_dtypetorch.bfloat16, device_mapauto, trust_remote_codeTrue ) print(加载LoRA适配器...) self.model PeftModel.from_pretrained(base_model, lora_model_path) self.model.eval() # 设置为评估模式 print(模型加载完成。) # 2. 加载RAG知识库 print(加载法律知识库...) embeddings HuggingFaceEmbeddings( model_nameBAAI/bge-small-zh-v1.5, model_kwargs{device: cpu}, # 嵌入模型可以放在CPU encode_kwargs{normalize_embeddings: True} ) self.vectordb Chroma( persist_directoryknowledge_base_path, embedding_functionembeddings ) self.retriever self.vectordb.as_retriever(search_kwargs{k: 3}) # 检索最相关的3个片段 print(知识库加载完成。) def retrieve_context(self, query): 从知识库中检索相关上下文 docs self.retriever.get_relevant_documents(query) context \n\n.join([doc.page_content for doc in docs]) return context def generate_answer(self, user_query, use_ragTrue): 生成回答 prompt user_query if use_rag: # 检索增强 context self.retrieve_context(user_query) if context: # 构建包含上下文的提示词 enhanced_prompt f请基于以下提供的法律条文信息回答用户的问题。如果信息不足以完全回答问题你可以结合自身的法律知识进行补充但请明确指出哪些信息来自提供的条文。 相关法律条文 {context} 用户问题 {user_query} 请给出专业、准确的分析 prompt enhanced_prompt else: print(警告未检索到相关法律条文。) # 使用模型的chat template构建输入 messages [{role: user, content: prompt}] text self.tokenizer.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue) # 将输入转换为tensor inputs self.tokenizer(text, return_tensorspt, paddingTrue).to(self.model.device) # 生成 with torch.no_grad(): outputs self.model.generate( **inputs, max_new_tokens512, # 生成的最大token数 temperature0.7, # 创造性越低越确定 top_p0.9, # 核采样参数 do_sampleTrue, repetition_penalty1.1, # 重复惩罚 pad_token_idself.tokenizer.pad_token_id, eos_token_idself.tokenizer.eos_token_id, ) # 解码输出并去掉输入部分 generated_ids outputs[0][inputs[input_ids].shape[1]:] response self.tokenizer.decode(generated_ids, skip_special_tokensTrue) return response def interactive_chat(self): 交互式对话 print(\n 法律AI助手已启动 (输入 quit 退出) ) print(模式RAG增强 LoRA微调模型) while True: try: user_input input(\n您) if user_input.lower() in [quit, exit, q]: print(再见) break if not user_input.strip(): continue answer self.generate_answer(user_input, use_ragTrue) print(f\n助手{answer}) except KeyboardInterrupt: print(\n程序被中断。) break except Exception as e: print(f\n生成时发生错误{e}) if __name__ __main__: # 路径配置 BASE_MODEL_PATH ./models/Qwen2.5-7B-Instruct LORA_MODEL_PATH ./models/lora_law_final KB_PATH ./knowledge_base/chroma_law # 初始化助手 assistant LawRAGLoRAAssistant(BASE_MODEL_PATH, LORA_MODEL_PATH, KB_PATH) # 运行交互式对话 assistant.interactive_chat()6.2 运行与测试运行推理脚本开始与你的“刑法大模型”对话吧cd law_llm_project python scripts/inference.py你可以尝试提问“张三盗窃了价值3万元的财物会判多久”“抢劫罪和抢夺罪有什么区别”“请解释一下什么是‘故意伤害罪致人重伤’的认定标准。”观察模型的回答是否引用了正确的法条来自RAG知识库。按照我们微调的结构化格式罪名、法条依据、刑期预测进行回答。推理过程符合法律逻辑。7. 常见问题与优化方向7.1 项目运行问题排查清单问题现象可能原因解决思路导入LangChain模块失败版本不兼容或未安装langchain-communitypip install langchain-community langchain-chromaChromaDB 无法持久化或读取路径权限问题或版本冲突检查路径是否存在且可写尝试pip install chromadb0.4.22(一个稳定版本)模型下载极慢或失败网络连接Hugging Face不畅使用镜像源export HF_ENDPOINThttps://hf-mirror.com训练时GPU显存不足批次大小、序列长度或模型太大减小per_device_train_batch_size、max_length启用gradient_checkpointing和fp16使用optim“paged_adamw_8bit”模型生成无关内容或格式错误1. 数据格式未按模型模板处理2. LoRA训练不充分或过拟合1. 使用tokenizer.apply_chat_template严格格式化数据2. 检查训练损失曲线增加数据量或调整超参如学习率、dropoutRAG检索结果不准确1. 文本分割策略差2. 嵌入模型不匹配3. 检索top_k值不合适1. 按法律条文自然结构如“第X条”分割2. 尝试moka-ai/m3e-base等中文模型3. 调整search_kwargs{“k”: 3}中的k值7.2 效果优化与进阶方向知识库优化多源数据加入司法解释、权威判例、学术观点构建更立体的知识体系。混合检索结合关键词检索BM25和向量检索提升召回率。重排序使用更精细的模型对检索结果进行重排序提升top1精度。微调策略优化更多任务数据收集更多高质量的案情判决配对数据。数据格式尝试不同的指令模板找到最适合Qwen模型的格式。LoRA参数调整r秩、alpha、target_modules甚至尝试DoRA等更先进的微调方法。全参数微调如果数据量和算力充足可以对整个模型进行全参数微调效果通常更好。推理优化模型量化使用GPTQ、AWQ等技术将模型量化到4bit或8bit大幅降低推理显存和加速。推理框架使用vLLM、TGI(Text Generation Inference) 等高性能推理框架部署支持动态批处理提高吞吐量。前端集成使用Gradio或Streamlit快速构建Web界面方便演示和测试。工程化部署API服务化使用FastAPI将模型封装成RESTful API。配置管理将模型路径、超参数等写入配置文件如YAML。日志与监控添加详细的日志记录和性能监控。通过以上步骤你不仅完成了一个融合RAG与LoRA的“刑法大模型”原型更掌握了一套在垂直领域构建专业大模型应用的通用方法论。这套方法可以迁移到医疗、金融、教育等任何需要专业知识与复杂推理的领域。