十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

天机 Tianji:基于 Xtuner QLoRA 微调 InternLM2 打造中文“送祝福“社交大模型全流程实战

天机 Tianji:基于 Xtuner QLoRA 微调 InternLM2 打造中文“送祝福“社交大模型全流程实战 天机 Tianji基于 Xtuner QLoRA 微调 InternLM2 打造中文送祝福社交大模型全流程实战【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm在《开源大模型食用指南》的 Examples 系列中天机 Tianji 是一个聚焦中文人情世故场景的社交大模型应用项目涵盖送祝福、敬酒、请客、送礼、人际交流、化解尴尬与应对矛盾等场景。本文以天机送祝福模块为例完整讲解基于 Xtuner QLoRA 对 internlm2-chat-7b 进行微调的端到端流程覆盖数据制造、数据合并与清洗、环境准备、配置修改、正式微调、权重转换合并、命令行对话验证与 Streamlit WebDemo 部署。读完本文你将掌握从原始语料到大模型微调上线的全链路能力并可迁移到任何自定义场景的 LLM 应用开发中。天机项目速览天机Tianji由 Social 团队开源其核心理念是通过深入理解中文语境、文化特点与丰富语料为各类中国式社交场景提供应对方法、对话案例与情景模拟。项目定位不仅是一个好玩的社交大模型更是一份完整的全栈大语言模型应用入门学习仓库涵盖提示词工程、智能体制作、模型微调、RAG 数据清洗与使用、代码规范等知识。该项目曾获2024 书生·浦语社区优秀大模型应用称号见 examples/readme.md。由于内容众多本篇教程聚焦天机送祝福微调模型的快速复现更多玩法可自行探索天机项目仓库与官方文档。总体思路微调送祝福模型的关键在于数据本次微调示范选用internlm2-chat-7b基座模型需要一台 24G 显存的机器3090 即可。整体流程为数据制造收集祝福语素材借助大模型 API 生成结构化 QA 对数据合并与二次清洗合并多轮生成的 JSON 文件过滤低质量样本环境准备安装依赖、Xtuner 与下载基座模型正式微调基于internlm2_chat_7b_qlora_oasst1_e3配置改造使用 Xtuner QLoRA 训练效果验证权重转 HF 格式、合并 LoRA、命令行对话WebDemo 部署基于 Streamlit 提供可视化对话界面。文档中反复强调当你打通微调后会发现真正复杂的工作都在清洗数据、处理、生成数据、归类数据上这才是影响最终效果的最大难点。数据制造时建议使用本地 LLM如本地部署的 llama3-chinese 或 qwen避免 API Key 在反复调用中快速耗尽。第一步数据制造——用大模型生成祝福语 QA 对微调模型的第一步是准备高质量训练数据。对于送祝福模型需要收集各种祝福语数据来源可以是公开祝福语数据集、社交媒体、电子书籍等。获取原始文本后需要通过数据制造生成知识切块 → QA 对的结构化数据而不是直接把原始文本喂给模型。理论上最优的数据制造方式是让一个更聪明的大模型基于现有知识生成高精度 QA 对也有人用大模型抽取小说文本对话来构造数据核心是用无限火力的聪明大模型完成文本清洗与格式化。完整数据制造脚本在清洗数据前请确保已安装对应 SDK如zhipuai与openai。以下脚本同时提供了智谱 GLM-4 与 DeepSeek 两种调用方式并通过对象 × 场景 × 风格的笛卡尔遍历批量生成祝福语from zhipuai import ZhipuAI import time import json import random import datetime # zhipuai # 此处填写您自己的APIKey # zhipu_api_key # client ZhipuAI(api_keyzhipu_api_key) # def get_data_zhipu(content): # response client.chat.completions.create( # modelglm-4, # 填写需要调用的模型名称 # messages[ # {role: system, content: 你现在是一个精通言语表达、热爱他人、尊重长辈、富有文采的送祝福大师请你编辑一条文本表示对应场景的祝福语}, # {role: user, # content: content, # temperature: 1} # 多样化输出 # ], # ) # res response.choices[0].message.content # return res # deepseek from openai import OpenAI deepseek_key #此处填写deepseek的key client OpenAI(api_keydeepseek_key, base_urlhttps://api.deepseek.com/v1) def get_data_ds(content): response client.chat.completions.create( modeldeepseek-chat, messages[ {role: system, content: 你现在是一个精通言语表达、热爱他人、尊重长辈、富有文采的送祝福大师请你编辑一条文本表示对应场景的祝福语}, {role: user, content: content, temperature: 1} # 多样化输出 ] ) res response.choices[0].message.content return res # 可利用大模型补充不同对象 当前28种 name_list [赵老师, 大舅, 大伯, 李总, 邻居赵大妈, 母亲, 姐姐, 妹妹, 哥哥, 弟弟, 爷爷, 奶奶, 外公, 外婆, 伯母, 叔叔, 阿姨, 堂兄, 堂妹, 表哥, 表妹, 导师, 同学, 同事, 领导, 邻居, 老板, 医生, ] # 可利用大模型补充对应场景 当前18种 scenes [生日, 春节, 元宵节, 端午节, 七夕节, 中秋节, 重阳节, 除夕, 腊八节,谈判顺利,乔迁新居, 周年纪念 ,新婚快乐 ,家庭和睦, 比赛取得好成绩 ,发财,工作升职 ,康复, ] # 可利用大模型补充不同风格加入更多 fewshot 造出更好的数据 styles { 小红书: { style_temple:小红书风格每条加入1-2个emoji表情包来增加趣味性。\n### 注意你要参考下列句子的艺术风格进行祝福语撰写注意只看造句风格祝福语结尾都带上语气助词词参考句子为{} ###, if_example:True, examples: [ 默念你的名,祝你前途云蒸霞蔚灿若星河。愿你度过的叫吉时得到的叫如愿, 希望你岁末将至敬颂冬绥平安喜乐万事胜意。, 希望你不用奔赴大海也能看到春暖花开不用颠沛流离也能遇到一生所伴, 祝我们好在春夏秋冬,祝你阔谈祝你烂漫祝你和自己相约在风里此后只剩欢愉。, 希望你可以明确地爱直接的厌恶真诚的喜欢站在太阳下的坦荡大声无愧地称赞自己学会爱自己, 前方荣光万丈身后温暖一方凡是过往皆为序章。, 愿所念之人 平安喜乐。愿所想之事 顺心如意, ] }, 正常: { style_temple:正常风格有礼貌即可, if_example:False, examples:[] }, 严肃: { style_temple:商业严肃风格要求用在职场或长辈祝福上显得有礼貌、干练,句子可以长一些, if_example:False, examples:[] } } random_finalprompt_sentence [ , #默认情况 回答中可以不出现对象称谓和场景信息也不用出现愿你祝你对自己的长辈需要出现对象称谓和祝你, 回答中可以不出现对象称谓和场景信息, 回答中不用出现愿你祝你, ] final_prompt 该祝福语字数小于 {} 字。 \n 请根据对象称谓及场景写出符合对象的身份和场景气氛的祝福文案。要求的风格是{} \n注意不要有标题混在其中对象称谓是{}祝福场景是{}。 \n {} 根据不同对象用不同的语气尊敬、诙谐搞笑、亲近请直接返回祝福文本不要说任何其他话 if __name__ __main__: ##### 此处配置 ##### roop_count 2 now_count 0 stylename 小红书 # 小红书、正常、严肃 output_number_limit 50 # 限制回答输出长度严肃的100普通的小于20 ##### 此处配置 ##### for roop in range(roop_count): conversations [] for name in name_list: for scene in scenes: try: if styles[stylename][if_example]: style_prompt styles[stylename][style_temple].format(random.choice(styles[stylename][examples])) else: style_prompt styles[stylename][style_temple] input_prompt final_prompt.format(output_number_limit, style_prompt, name, scene,random.choice(random_finalprompt_sentence)) response get_data_ds(input_prompt) now_count 1 if \n in str(response): response str(response).split(\n)[0] print(name,scene,response:,response) print(当前生成数目, now_count) if stylename 正常: # 默认不加风格指定 _input_prompt f祝{name}{scene} else: _input_prompt f祝{name}{scene},{stylename}风格 print(input:,_input_prompt) conversation { conversation: [ { system: 你现在是一个送祝福大师帮我针对不同人和事情、节日送对应的祝福, src_input:input_prompt, style_name:stylename, input: _input_prompt, output: str(response).replace(\,) } ] } # 将对话加入到列表中 conversations.append(conversation) except Exception as e: print(e) continue now_time datetime.datetime.now().strftime(%Y-%m-%d-%H-%M-%S) file_path f./wishes_{stylename}_{now_time}.json with open(file_path, w, encodingutf8) as f: json.dump(conversations, f, ensure_asciiFalse, indent4)数据制造脚本的关键设计点输入与输出的分离注意为什么需要把input替换成f祝{name}{scene}或加风格后缀的格式——因为这里的input需要尽可能模拟真人的输入而不能使用制造数据时的完整提示词否则训练出的模型只能响应提示词腔的问法。脚本同时保留src_input记录原始制造提示词便于追溯。三种风格控制正常、小红书、严肃。当用户输入触发风格名如小红书风格时模型应给出对应风格的输出这一能力正是靠数据中的style_name字段与风格化的input学到的。随机性注入代码中random_xxxxxxx_sentence部分是随机性注入列表random_finalprompt_sentence用于维护一些附加条件语句让大模型返回的结果更具特色、减少重复。Few-shot 参考句小红书风格通过if_example开启从examples中随机抽取一句作为风格参考只看造句风格保证造出的数据长度与文风符合预期。若成功运行你将看到类似如下输出等待片刻后得到本地 JSON 文件同学 家庭和睦 response: 烟火年年暖意洋洋❤️家是心之所向。 当前生成数目 914 同学 比赛取得好成绩 response: 灿若星河前程似锦所得皆所愿 当前生成数目 915 同学 发财 response: 春风得意马蹄疾财源滚滚至君前 当前生成数目 916 同学 工作升职 response: 升职之光照亮星河未来灿烂如霞。 当前生成数目 917 同学 康复祝福 response: 挥别病痛如花开坚强。✨愿你前程云蒸霞蔚身心俱灿。 当前生成数目 918注意这里只是粗暴地遍历所有角色与场景但并非所有角色都适配所有场景。改进方向是做一张角色-场景的 heatmap 映射不合适的组合直接跳过生成或者在得到数据后做一轮匹配将不合适角色 场景的 QA 对删除。进阶控制祝福语长短与语法风格这只是最小示例。想要控制祝福语长短需要在制造条件中对象、场景之外加入长度控制条件如本脚本的小红书与正常风且此时 few-shot 参考句也应当不同才能保证造数据的大模型返回预期长度。想控制语法风格则需要爬取大量文艺书籍、小红书等真人文案进行清洗再用这些高质量文案作为 few-shot 得到严格返回必要时可单独微调一个属于该文艺范畴的模型版本来制造对应数据有时 few-shot 指令跟随并不够用。第二步数据合并与二次清洗数据合并由于数据制造是跑完一轮存一次以防前功尽弃会产生多个 JSON 文件。合并脚本遍历指定文件夹提取system/input/output字段并清洗为与训练脚本一致的格式import os import json def extract_and_merge_conversations(folder_path, output_file): all_conversations [] # 遍历指定文件夹 for filename in os.listdir(folder_path): if filename.endswith(.json): file_path os.path.join(folder_path, filename) # 打开并读取JSON文件 with open(file_path, r, encodingutf-8) as file: data json.load(file) # 提取需要的字段 for item in data: for conversation in item[conversation]: extracted { system: conversation[system], input: conversation[input], output: conversation[output] } # 将每个对话包装在一个 conversation 键中并作为独立对象加入列表 all_conversations.append({conversation: [extracted]}) # 将合并后的所有对话数据写入一个新的JSON文件 with open(output_file, w, encodingutf-8) as file: json.dump(all_conversations, file, ensure_asciiFalse, indent4) # 使用示例 folder_path tianji_wishes_datasets # 要扫描的文件夹路径 output_file tianji-wishes-chinese-v0.1.json # 输出文件的名称和路径 extract_and_merge_conversations(folder_path, output_file)合并后即为微调所需的最终数据集。二次清洗得到最初数据后可能存在异常样本句子长度返回错误模型没有回答问题而只输出一句当前祝福语如下加入语气助词后出现啦~、。哦这样前面带标点的奇怪现象。因此需要利用清洗脚本对数据进行筛选清洗脚本在 Tianji 主仓库可自行查看。当然若有时间精力人工清洗是最可靠的而更重要的经验是在数据制造时就记录完整信息、生成高质量 output能大大节约二次清洗的时间。直接下载现成数据集为方便使用天机已提供制造好的数据可从 HuggingFace 获取tianji-wishes-chinese-v0.1.json国内用户可使用 hf-mirror 镜像站下载具体地址见天机项目文档。第三步环境准备Python 3.10以下基于Python 3.10构建全过程请注意版本一致性。先创建虚拟环境再安装依赖python -m pip install --upgrade pip pip install modelscope1.9.5 pip install transformers4.36.2 pip install streamlit1.39.0 pip install sentencepiece0.1.99 pip install accelerate0.24.1 pip install transformers_stream_generator0.0.4 pip install einops ujson pip install protobuf安装 Xtuner注意天机教程基于v0.1.18分支git clone -b v0.1.18 https://github.com/InternLM/xtuner cd xtuner pip install -e .[all] # 验证成功 xtuner version下载基座模型使用 ModelScope 的 snapshot_downloadcache_dir指定下载路径from modelscope import snapshot_download model_dir snapshot_download(Shanghai_AI_Laboratory/internlm2-chat-7b, cache_dir./model_temp, revisionmaster)关于 Xtuner 的完整介绍与环境搭建细节可对照参考仓库中 InternLM2-7B-chat Xtuner Qlora 微调 一文——XTuner 是上海人工智能实验室开发的轻量化微调工具箱支持 QLoRA/LoRA/全量微调兼容 DeepSpeed最低 8GB 显存即可微调 7B 模型。天机教程为保证可复现性指定了版本号若与最新 Xtuner 存在差异可参考该文档中的通用操作流程。第四步正式微调Xtuner QLoRA查看并复制配置先查看 Xtuner 内置的 internlm2 相关配置xtuner list-cfg | grep internlm2输出中可见internlm2_7b_qlora_oasst1_e3等配置。新建微调工作文件夹并复制配置mkdir /home/finetune cd /home/finetune xtuner copy-cfg internlm2_chat_7b_qlora_oasst1_e3 ./配置文件修改要点需要修改四处关键内容# 修改模型为本地路径 - pretrained_model_name_or_path internlm2/internlm2-chat-7b pretrained_model_name_or_path /home/model_temp/Shanghai_AI_Laboratory/internlm2-chat-7b # 修改训练数据集为本地路径 - data_path timdettmers/openassistant-guanaco data_path /home/merged_data.json # 修改Evaluate - evaluation_freq 500 SYSTEM evaluation_inputs [ 请给我介绍五个上海的景点, Please tell me five scenic spots in Shanghai ] evaluation_freq 50 SYSTEM 你现在是一个送祝福大师帮我针对不同人和事情、节日送对应的祝福 evaluation_inputs [ 祝姐姐生日快乐, 祝妹妹谈判顺利,祝大家元宵节快乐 ] # 修改数据集加载 - datasetdict(typeload_dataset, pathdata_path), datasetdict(typeload_dataset, pathjson, data_filesdict(traindata_path)),关键点说明数据集加载方式必须把load_dataset的path改为json并用data_files指向本地 JSON 文件否则无法直接读取本地 json 格式数据集这与 InternLM2 Xtuner 微调 文档中的注意事项一致且该文档还提示此场景下应将dataset_map_fn设为None否则会报 KeyError。Evaluate 配置将验证问题替换为送祝福场景的真实提问并设置SYSTEM系统提示词evaluation_freq从 500 调低到 50可更频繁地在训练日志中看到生成效果。数据格式天机数据即{conversation: [{system: ..., input: ..., output: ...}]}的单轮对话结构符合 Xtuner 对话数据集约定多轮对话时conversation列表长度大于 1只有 output 部分参与 loss 回传。完整训练配置文件以下是修改后的完整配置可直接复制使用——只需修改模型路径、训练集路径与 Evaluate 的 input即可变成自己的配置文件# Copyright (c) OpenMMLab. All rights reserved. import torch from datasets import load_dataset from mmengine.dataset import DefaultSampler from mmengine.hooks import (CheckpointHook, DistSamplerSeedHook, IterTimerHook, LoggerHook, ParamSchedulerHook) from mmengine.optim import AmpOptimWrapper, CosineAnnealingLR, LinearLR from peft import LoraConfig from torch.optim import AdamW from transformers import (AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig) from xtuner.dataset import process_hf_dataset from xtuner.dataset.collate_fns import default_collate_fn from xtuner.dataset.map_fns import oasst1_map_fn, template_map_fn_factory from xtuner.engine.hooks import (DatasetInfoHook, EvaluateChatHook, VarlenAttnArgsToMessageHubHook) from xtuner.engine.runner import TrainLoop from xtuner.model import SupervisedFinetune from xtuner.utils import PROMPT_TEMPLATE ####################################################################### # PART 1 Settings # ####################################################################### # Model pretrained_model_name_or_path /home/model_temp/Shanghai_AI_Laboratory/internlm2-chat-7b use_varlen_attn False # Data data_path /home/tianji-wishes-test_0502.json prompt_template PROMPT_TEMPLATE.internlm2_chat max_length 2048 pack_to_max_length True # Scheduler Optimizer batch_size 1 # per_device accumulative_counts 16 dataloader_num_workers 0 max_epochs 3 optim_type AdamW lr 2e-4 betas (0.9, 0.999) weight_decay 0 max_norm 1 # grad clip warmup_ratio 0.03 # Save save_steps 50 save_total_limit 10 # Maximum checkpoints to keep (-1 means unlimited) # Evaluate the generation performance during the training evaluation_freq 50 SYSTEM 你现在是一个送祝福大师帮我针对不同人和事情、节日送对应的祝福 evaluation_inputs [ 祝姐姐生日快乐,祝姐姐生日快乐严肃风格,祝姐姐生日快乐,小红书风格, 祝妹妹谈判顺利小红书风格,祝大家元宵节快乐,祝领导春节快乐严肃风格 ] ####################################################################### # PART 2 Model Tokenizer # ####################################################################### tokenizer dict( typeAutoTokenizer.from_pretrained, pretrained_model_name_or_pathpretrained_model_name_or_path, trust_remote_codeTrue, padding_sideright) model dict( typeSupervisedFinetune, use_varlen_attnuse_varlen_attn, llmdict( typeAutoModelForCausalLM.from_pretrained, pretrained_model_name_or_pathpretrained_model_name_or_path, trust_remote_codeTrue, torch_dtypetorch.float16, quantization_configdict( typeBitsAndBytesConfig, load_in_4bitTrue, load_in_8bitFalse, llm_int8_threshold6.0, llm_int8_has_fp16_weightFalse, bnb_4bit_compute_dtypetorch.float16, bnb_4bit_use_double_quantTrue, bnb_4bit_quant_typenf4)), loradict( typeLoraConfig, r64, lora_alpha16, lora_dropout0.1, biasnone, task_typeCAUSAL_LM)) ####################################################################### # PART 3 Dataset Dataloader # ####################################################################### train_dataset dict( typeprocess_hf_dataset, datasetdict(typeload_dataset, pathjson, data_filesdict(traindata_path)), tokenizertokenizer, max_lengthmax_length, dataset_map_fnNone, template_map_fndict( typetemplate_map_fn_factory, templateprompt_template), remove_unused_columnsTrue, shuffle_before_packTrue, pack_to_max_lengthpack_to_max_length, use_varlen_attnuse_varlen_attn) train_dataloader dict( batch_sizebatch_size, num_workersdataloader_num_workers, datasettrain_dataset, samplerdict(typeDefaultSampler, shuffleTrue), collate_fndict(typedefault_collate_fn, use_varlen_attnuse_varlen_attn)) ####################################################################### # PART 4 Scheduler Optimizer # ####################################################################### # optimizer optim_wrapper dict( typeAmpOptimWrapper, optimizerdict( typeoptim_type, lrlr, betasbetas, weight_decayweight_decay), clip_graddict(max_normmax_norm, error_if_nonfiniteFalse), accumulative_countsaccumulative_counts, loss_scaledynamic, dtypefloat16) # learning policy param_scheduler [ dict( typeLinearLR, start_factor1e-5, by_epochTrue, begin0, endwarmup_ratio * max_epochs, convert_to_iter_basedTrue), dict( typeCosineAnnealingLR, eta_min0.0, by_epochTrue, beginwarmup_ratio * max_epochs, endmax_epochs, convert_to_iter_basedTrue) ] # train, val, test setting train_cfg dict(typeTrainLoop, max_epochsmax_epochs) ####################################################################### # PART 5 Runtime # ####################################################################### # Log the dialogue periodically during the training process, optional custom_hooks [ dict(typeDatasetInfoHook, tokenizertokenizer), dict( typeEvaluateChatHook, tokenizertokenizer, every_n_itersevaluation_freq, evaluation_inputsevaluation_inputs, systemSYSTEM, prompt_templateprompt_template) ] if use_varlen_attn: custom_hooks [dict(typeVarlenAttnArgsToMessageHubHook)] # configure default hooks default_hooks dict( # record the time of every iteration. timerdict(typeIterTimerHook), # print log every 10 iterations. loggerdict(typeLoggerHook, log_metric_by_epochFalse, interval10), # enable the parameter scheduler. param_schedulerdict(typeParamSchedulerHook), # save checkpoint per save_steps. checkpointdict( typeCheckpointHook, by_epochFalse, intervalsave_steps, max_keep_ckptssave_total_limit), # set sampler seed in distributed evrionment. sampler_seeddict(typeDistSamplerSeedHook), ) # configure environment env_cfg dict( # whether to enable cudnn benchmark cudnn_benchmarkFalse, # set multi process parameters mp_cfgdict(mp_start_methodfork, opencv_num_threads0), # set distributed parameters dist_cfgdict(backendnccl), ) # set visualizer visualizer None # set log level log_level INFO # load from which checkpoint load_from None # whether to resume training from the loaded checkpoint resume False # Defaults to use random seed and disable deterministic randomness dict(seedNone, deterministicFalse) # set log processor log_processor dict(by_epochFalse)关键超参数解读参数配置值作用说明max_length2048训练样本最大文本长度超过会被截断pack_to_max_lengthTrue是否将多条短样本拼接至最大长度提升训练效率batch_size1per_device单卡批大小配合 24G 显存accumulative_counts16梯度累积步数等效 batch size 1×16max_epochs3最大训练轮数文档建议实际通常 1 轮即可lr/warmup_ratio2e-4 / 0.03学习率与 warmup 比例调度策略为 LinearLR CosineAnnealingLRr/lora_alpha64 / 16LoRA 秩与缩放系数lora_dropout0.1load_in_4bitTrueQLoRA 4bit 量化nf4 双重量化这是显存占用低的关键save_steps50每 50 步保存一次 checkpointsave_total_limit10控制保留份数启动训练xtuner train ./internlm2_chat_7b_qlora_oasst1_e3_copy.py --deepspeed deepspeed_zero2如果显存不够可以切换为--deepspeed deepspeed_zero3。训练结束后所有权重文件保存在训练目录下的work_dirs中目录结构大致为drwxr-xr-x 3 root root 4096 May 2 12:23 20240502_122337/ -rw-r--r-- 1 root root 6413 May 2 12:24 internlm2_chat_7b_qlora_oasst1_e3_copy.py -rw-r--r-- 1 root root 1886589762 May 2 12:43 iter_500.pth -rw-r--r-- 1 root root 1886601474 May 2 12:50 iter_657.pth -rw-r--r-- 1 root root 76 May 2 12:50 last_checkpoint值得注意通常只需要微调一轮就好因为 LLM 往往过目不忘相关研究很多多轮训练容易过拟合。关于全量微调若想使用全量微调对于 internlm2-7B 至少需要 2×A100 80G 显卡使用NPROC_PER_NODE2 xtuner train ./全量微调配置.py --deepspeed deepspeed_zero3启动双卡每卡显存占用接近 79G。文档建议使用万级别的数据再进行全量微调目前天机相关数据量还不足以支撑好的全量微调并推荐混入更多正常对话数据以确保全量微调效果正常。想深入了解 LoRA/QLoRA 超参数对结果的影响可参考社区中LoRA 和 QLoRA 微调语言大模型数百次实验后的见解等实验类文章。第五步效果验证——权重转换、合并与对话将 LoRA 权重转为 HF 格式并合并回原模型提供统一脚本完成pth → HF转换与HF adapter 原模型合并HF_OUTPUT_DIR./hf # lora转为hf格式后的输出地址 MERGE_OUTPUT_DIR./merge # 与原模型合并后的输出地址 SCRIPT_PATH./internlm2_chat_7b_qlora_oasst1_e3_copy.py # 训练配置文件 SRC_MODEL_PATH/home/model_temp/Shanghai_AI_Laboratory/internlm2-chat-7b # 原模型地址 WEIGHTS_PATH/home/finetune/work_dirs/internlm2_chat_7b_qlora_oasst1_e3_copy/iter_150.pth # lora权重地址 rm -rf $HF_OUTPUT_DIR rm -rf $MERGE_OUTPUT_DIR mkdir -p $HF_OUTPUT_DIR mkdir -p $MERGE_OUTPUT_DIR xtuner convert pth_to_hf ${SCRIPT_PATH} ${WEIGHTS_PATH} ${HF_OUTPUT_DIR} xtuner convert merge \ ${SRC_MODEL_PATH} \ ${HF_OUTPUT_DIR} \ ${MERGE_OUTPUT_DIR} \ --max-shard-size 2GB如果这步报错请检查WEIGHTS_PATH是否正确注意work_dirs下是iter_xxx.pth文件而非文件夹。不合并、直接加载 LoRA 对话也可以不合并合并后就可以上传权重转换后直接加载 LoRA 进行对话HF_OUTPUT_DIR./hf # lora转为hf格式后的输出地址 SCRIPT_PATH./internlm2_chat_7b_qlora_oasst1_e3_copy.py # 训练配置文件 SRC_MODEL_PATH/home/model_temp/Shanghai_AI_Laboratory/internlm2-chat-7b WEIGHTS_PATH/home/finetune/work_dirs/internlm2_chat_7b_qlora_oasst1_e3_copy/iter_150.pth rm -rf $HF_OUTPUT_DIR rm -rf $MERGE_OUTPUT_DIR mkdir -p $HF_OUTPUT_DIR xtuner convert pth_to_hf ${SCRIPT_PATH} ${WEIGHTS_PATH} ${HF_OUTPUT_DIR} xtuner chat ${SRC_MODEL_PATH} --adapter ${HF_OUTPUT_DIR} --prompt-template internlm2_chat --system 你现在是一个送祝福大师帮我针对不同人和事情、节日送对应的祝福 --temperature 0.7启动合并后模型的对话# 如果想要多样性更强加上 --temperature 1 xtuner chat ./merge --prompt-template internlm2_chat --system 你现在是一个送祝福大师帮我针对不同人和事情、节日送对应的祝福 --temperature 0.7此时输入之前的 prompt 并触发风格即可验证。注意为去除上下文影响需要反复输入RESET重置历史。对话效果示例如下double enter to end input (EXIT: exit chat, RESET: reset history) 祝弟弟工作升职 ,小红书风格 弟弟呀你的才华如同春日里的花朵绽放出绚烂的光彩。工作如鱼得水升职之路顺顺利利愿你继续闪耀成为职场的明星加油哦|im_end| double enter to end input (EXIT: exit chat, RESET: reset history) RESET Log: History responses have been removed! double enter to end input (EXIT: exit chat, RESET: reset history) 我想送哥哥中秋节祝福,小红书风格 哥中秋月圆人团圆愿你事业如月圆家庭幸福似团圆快乐满怀幸福满满|im_end| double enter to end input (EXIT: exit chat, RESET: reset history) RESET Log: History responses have been removed! double enter to end input (EXIT: exit chat, RESET: reset history) 我想送赵老师生日祝福,严肃风格 尊敬的赵老师值此佳辰恭祝您福寿安康事业蒸蒸日上。愿您在未来的岁月里如同春日之花绽放出更加绚烂的光彩为莘莘学子树立起崇高的榜样。愿您的生活如同诗篇般美好每一天都充满着智慧与喜悦。愿您的工作如同乐章般动听每一个音符都承载着对教育事业的热爱与执着。在此衷心祝愿您生日快乐万事胜意|im_end|可以看到模型已经学会了风格区分小红书风格活泼带 emoji 与语气助词严肃风格则正式、长句、对长辈用敬称这正是数据制造阶段风格化设计在模型中的体现。第六步网页 Demo 部署Streamlit为了方便测试可以使用 Streamlit Demo使用方法如下pip install streamlit1.39.0然后克隆 InternLM 官方仓库git clone https://github.com/InternLM/InternLM.git将web_demo.py中第 29 行和 33 行的模型路径更换为 Merge 后存放参数的路径/home/finetune/merge不同版本源码行号可能略有差异定位到加载模型与分词器的两处即可。随后在对应目录下运行streamlit run /root/personal_assistant/code/InternLM/web_demo.py --server.address 127.0.0.1 --server.port 6006Streamlit 环境搭建与端口转发的更多细节可参考仓库中 InternLM2-7B-chat WebDemo 部署 一文含 Autodl 机器 SSH 端口映射到本地的方法。通过以上步骤你就可以成功微调出最初版本的天机送祝福模块并运行推理。由于制造数据的质量仍有改善空间回答随机性注入与输入随机性加强也还有很多实现方式送祝福模型完全可以做得更好、更智能、更通用从而真正更贴近中文使用场景让 LLM 对话更富人情味。从本案例学到的全栈 LLM 应用方法论天机送祝福微调案例虽然只是一个小场景却浓缩了大模型应用开发的完整方法论与 examples/readme.md 中通过实际案例掌握大模型应用开发核心技术的目标一脉相承数据制造决定模型上限对象、场景、风格的三维组合设计 随机性注入 few-shot 参考是生成高质量结构化数据的关键微调后你会发现真正耗时耗力的永远是数据清洗与生成环节。训练配置可以模板化改造基于 Xtuner 内置配置internlm2_chat_7b_qlora_oasst1_e3只需改动模型路径、数据路径、评估输入与数据集加载方式四处即可适配任意新场景。风格化能力来自训练数据的刻意设计想让模型区分小红书风/正常风/严肃风就必须在制造数据时让input带上风格触发词祝{name}{scene},{stylename}风格并让输出与之一一对应。验证闭环训练中通过EvaluateChatHook定期观察生成效果训练后通过xtuner convertxtuner chat完成推理验证最终以 Streamlit WebDemo 交付。掌握了这套数据制造 → QLoRA 微调 → 权重合并 → 对话验证 → WebDemo 部署的流程你就可以快速改造出属于自己的新的大语言模型项目成为下一个大模型应用开发高手。【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表