[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-10756":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":20,"hasPages":20,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":27,"readmeContent":28,"aiSummary":29,"trendingCount":16,"starSnapshotCount":16,"syncStatus":30,"lastSyncTime":31,"discoverSource":32},10756,"ChatLM-mini-Chinese","charent\u002FChatLM-mini-Chinese","charent","中文对话0.2B小模型（ChatLM-Chinese-0.2B），开源所有数据集来源、数据清洗、tokenizer训练、模型预训练、SFT指令微调、RLHF优化等流程的全部代码。支持下游任务sft微调，给出三元组信息抽取微调示例。","",null,"Python",1710,194,13,9,0,6,55.47,"Apache License 2.0",false,"main",[23,24,25,26],"chatbot","language-model","t5-model","text-generation","2026-06-12 04:00:52","\u003Cdiv align=\"center\">\n\n# 中文对话0.2B小模型 ChatLM-Chinese-0.2B  \n\n中文  | [English](.\u002FREADME.en.md)  \n\n\u003C\u002Fdiv>\n \n\n# 一、👋介绍 \n现在的大语言模型的参数往往较大，消费级电脑单纯做推理都比较慢，更别说想自己从头开始训练一个模型了。本项目的目标是从0开始训练一个生成式语言模型，包括数据清洗、tokenizer训练、模型预训练、SFT指令微调、RLHF优化等。 \n\nChatLM-mini-Chinese为中文对话小模型，模型参数只有0.2B（算共享权重约210M），可以在最低4GB显存的机器进行预训练（`batch_size=1`，`fp16`或者` bf16`），`float16`加载、推理最少只需要512MB显存。 \n\n\n- 公开所有预训练、SFT指令微调、DPO偏好优化数据集来源。\n- 使用`Huggingface`NLP框架，包括`transformers`、`accelerate`、`trl`、`peft`等。\n- 自实现`trainer`，支持单机单卡、单机多卡进行预训练、SFT微调。训练过程中支持在任意位置停止，及在任意位置继续训练。\n- 预训练：整合为端到端的`Text-to-Text`预训练，非`mask`掩码预测预训练。\n    - 开源所有数据清洗（如规范化、基于mini_hash的文档去重等）、数据集构造、数据集加载优化等流程；\n    - tokenizer多进程词频统计，支持`sentencepiece`、`huggingface tokenizers`的tokenizer训练；\n    - 预训练支持任意位置断点，可从断点处继续训练;\n    - 大数据集（GB级别）流式加载、支持缓冲区数据打乱，不利用内存、硬盘作为缓存，有效减少内存、磁盘占用。配置`batch_size=1, max_len=320`下，最低支持在16GB内存+4GB显存的机器上进行预训练；\n    - 训练日志记录。\n- SFT微调：开源SFT数据集及数据处理过程。\n    - 自实现`trainer`支持prompt指令微调， 支持任意断点继续训练；\n    - 支持`Huggingface trainer`的`sequence to sequence`微调；\n    - 支持传统的低学习率，只训练decoder层的微调。\n- RLHF偏好优化：使用DPO进行全量偏好优化。\n    - 支持使用`peft lora`进行偏好优化；\n    - 支持模型合并，可将`Lora adapter`合并到原始模型中。\n- 支持下游任务微调：[finetune_examples](.\u002Ffinetune_examples\u002Finfo_extract\u002F)给出**三元组信息抽取任务**的微调示例，微调后的模型对话能力仍在。\n\n如果需要做基于小模型的检索增强生成（RAG），可以参考我的另一个项目[Phi2-mini-Chinese](https:\u002F\u002Fgithub.com\u002Fcharent\u002FPhi2-mini-Chinese)，代码见[rag_with_langchain.ipynb](https:\u002F\u002Fgithub.com\u002Fcharent\u002FPhi2-mini-Chinese\u002Fblob\u002Fmain\u002Frag_with_langchain.ipynb)\n\n🟢**最近更新**\n\n\u003Cdetails open> \n\u003Csummary>  \u003Cb>2024-01-30\u003C\u002Fb> \u003C\u002Fsummary>\n- 模型文件更新到魔搭modelscope，可以通过`snapshot_download`快速下载。\u003Cbr\u002F>\n\u003C\u002Fdetails>\n\n\u003Cdetails close> \n\u003Csummary>  \u003Cb>2024-01-07\u003C\u002Fb> \u003C\u002Fsummary>\n- 添加数据清洗过程中基于mini hash实现的文档去重（在本项目中其实是数据集的样本去重），防止模型遇到多次重复数据后，在推理时吐出训练数据。\u003Cbr\u002F>\n- 添加`DropDatasetDuplicate`类实现对大数据集的文档去重。\u003Cbr\u002F>\n\u003C\u002Fdetails>\n\n\u003Cdetails close> \n\u003Csummary>  \u003Cb>2023-12-29\u003C\u002Fb> \u003C\u002Fsummary>\n- 更新模型代码（权重不变），可以直接使用`AutoModelForSeq2SeqLM.from_pretrained(...)`加载模型使用。\u003Cbr\u002F>\n- 更新readme文档。\u003Cbr\u002F>\n\u003C\u002Fdetails>\n\n\u003Cdetails close> \n\u003Csummary>  \u003Cb>2023-12-18\u003C\u002Fb> \u003C\u002Fsummary>\n- 补充利用`ChatLM-mini-0.2B`模型微调下游三元组信息抽取任务代码及抽取效果展示 。\u003Cbr\u002F>\n- 更新readme文档。\u003Cbr\u002F>\n\u003C\u002Fdetails>\n\n\u003Cdetails close> \n\u003Csummary>  \u003Cb>2023-12-14\u003C\u002Fb> \u003C\u002Fsummary>\n- 更新SFT、DPO后的模型权重文件。 \u003Cbr\u002F>\n- 更新预训练、SFT及DPO脚本。 \u003Cbr\u002F>\n- 更新`tokenizer`为`PreTrainedTokenizerFast`。 \u003Cbr\u002F>\n- 重构`dataset`代码，支持动态最大长度，每个批次的最大长度由该批次的最长文本决定，节省显存。 \u003Cbr\u002F>\n- 补充`tokenizer`训练细节。 \u003Cbr\u002F>\n\u003C\u002Fdetails>\n\n\u003Cdetails close> \n\u003Csummary> \u003Cb>2023-12-04\u003C\u002Fb> \u003C\u002Fsummary>\n- 更新`generate`参数及模型效果展示。\u003Cbr\u002F>\n- 更新readme文档。\u003Cbr\u002F>\n\u003C\u002Fdetails>\n\n\u003Cdetails close> \n\u003Csummary> \u003Cb>2023-11-28\u003C\u002Fb> \u003C\u002Fsummary>\n- 更新dpo训练代码及模型权重。\u003Cbr\u002F>\n\u003C\u002Fdetails>\n\n\u003Cdetails close> \n\u003Csummary> \u003Cb>2023-10-19\u003C\u002Fb> \u003C\u002Fsummary>\n- 项目开源， 开放模型权重供下载。 \u003Cbr\u002F>\n\u003C\u002Fdetails>\n\n\n# 二、🛠️ChatLM-0.2B-Chinese模型训练过程 \n\n## 2.1 预训练数据集\n所有数据集均来自互联网公开的**单轮对话**数据集，经过数据清洗、格式化后保存为parquet文件。数据处理过程见`utils\u002Fraw_data_process.py`。主要数据集包括： \n\n1. 社区问答json版webtext2019zh-大规模高质量数据集，见：[nlp_chinese_corpus](https:\u002F\u002Fgithub.com\u002Fbrightmart\u002Fnlp_chinese_corpus)。共410万，清洗后剩余260万。\n2. baike_qa2019百科类问答，见：\u003Chttps:\u002F\u002Faistudio.baidu.com\u002Fdatasetdetail\u002F107726>，共140万，清醒后剩余130万。\n3. 中国医药领域问答数据集，见：[Chinese-medical-dialogue-data](https:\u002F\u002Fgithub.com\u002FToyhom\u002FChinese-medical-dialogue-data)，共79万，清洗后剩余79万。\n4. ~~金融行业问答数据，见：\u003Chttps:\u002F\u002Fzhuanlan.zhihu.com\u002Fp\u002F609821974>，共77万，清洗后剩余52万。~~**数据质量太差，未采用。**\n5. 知乎问答数据，见：[Zhihu-KOL](https:\u002F\u002Fhuggingface.co\u002Fdatasets\u002Fwangrui6\u002FZhihu-KOL)，共100万行，清洗后剩余97万行。\n6. belle开源的指令训练数据，介绍：[BELLE](https:\u002F\u002Fgithub.com\u002FLianjiaTech\u002FBELLE)，下载：[BelleGroup](https:\u002F\u002Fhuggingface.co\u002FBelleGroup)，仅选取`Belle_open_source_1M`、`train_2M_CN`、及`train_3.5M_CN`中部分回答较短、不含复杂表格结构、翻译任务（没做英文词表）的数据，共370万行，清洗后剩余338万行。\n7. 维基百科（Wikipedia）词条数据，将词条拼凑为提示语，百科的前`N`个词为回答，使用`202309`的百科数据，清洗后剩余119万的词条提示语和回答。Wiki下载：[zhwiki](https:\u002F\u002Fdumps.wikimedia.org\u002Fzhwiki\u002F)，将下载的bz2文件转换为wiki.txt参考：[WikiExtractor](https:\u002F\u002Fgithub.com\u002Fapertium\u002FWikiExtractor)。 \n\n数据集总数量1023万：Text-to-Text预训练集：930万，评估集：2.5万（因为解码较慢，所以没有把评估集设置太大）。~~测试集：90万。~~ \nSFT微调和DPO优化数据集见下文。\n\n## 2.2 模型\nT5模型（Text-to-Text Transfer Transformer），详情见论文: [Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer](https:\u002F\u002Farxiv.org\u002Fabs\u002F1910.10683)。\n\n模型源码来自huggingface，见：[T5ForConditionalGeneration](https:\u002F\u002Fgithub.com\u002Fhuggingface\u002Ftransformers\u002Fblob\u002Fmain\u002Fsrc\u002Ftransformers\u002Fmodels\u002Ft5\u002Fmodeling_t5.py#L1557)。\n\n模型配置见[model_config.json](https:\u002F\u002Fhuggingface.co\u002Fcharent\u002FChatLM-mini-Chinese\u002Fblob\u002Fmain\u002Fconfig.json)，官方的`T5-base`：`encoder layer`和`decoder layer `均为为12层，本项目这两个参数修改为10层。 \n\n模型参数：0.2B。词表大小：29298，仅包含中文和少量英文。\n\n## 2.3 训练过程\n硬件：\n```bash\n# 预训练阶段：\nCPU: 28 vCPU Intel(R) Xeon(R) Gold 6330 CPU @ 2.00GHz\n内存：60 GB\n显卡：RTX A5000(24GB) * 2\n\n# sft及dpo阶段：\nCPU: Intel(R) i5-13600k @ 5.1GHz\n内存：32 GB\n显卡：NVIDIA GeForce RTX 4060 Ti 16GB * 1\n```\n1. **tokenizer 训练**： 现有`tokenizer`训练库遇到大语料时存在OOM问题，故全量语料按照类似`BPE`的方法根据词频合并、构造词库，运行耗时半天。\n\n2. **Text-to-Text 预训练**：学习率为`1e-4`到`5e-3`的动态学习率，预训练时间为8天。训练损失： \n\n![traing loss](img\u002Ftrain_loss.png) \n\n3. **prompt监督微调（SFT）**：使用`belle`指令训练数据集（指令和回答长度都在512以下），学习率为`1e-7`到`5e-5`的动态学习率，微调时间2天。微调损失： \n   \n![finetune loss](img\u002Fsft_loss.png) \n\n4. **dpo直接偏好优化（RLHF）**：数据集[alpaca-gpt4-data-zh](https:\u002F\u002Fhuggingface.co\u002Fdatasets\u002Fc-s-ale\u002Falpaca-gpt4-data-zh)作为`chosen`文本，步骤`2`中SFT模型对数据集中的prompt做批量`generate`，得到`rejected`文本，耗时1天，dpo全量偏好优化，学习率`le-5`，半精度`fp16`,共`2`个`epoch`，耗时3h。dpo损失： \n \n![dpo loss](img\u002Fdpo_loss.png) \n\n## 2.4 对话效果展示\n### 2.4.1 stream chat\n默认使用`huggingface transformers`的 `TextIteratorStreamer`实现流式对话，只支持`greedy search`，如果需要`beam sample`等其他生成方式，请将`cli_demo.py`的`stream_chat`参数修改为`False`。\n![](.\u002Fimg\u002Fstream_chat.gif)\n\n### 2.4.2 对话展示\n![](.\u002Fimg\u002Fshow1.png)\n\n存在问题：预训练数据集只有900多万，模型参数也仅0.2B，不能涵盖所有方面，会有答非所问、废话生成器的情况。\n\n# 三、📑使用说明\n\n## 3.1 快速开始：\n如果无法连接huggingface，请使用`modelscope.snapshot_download`从modelscope下载模型文件。\n```python\nfrom transformers import AutoTokenizer, AutoModelForSeq2SeqLM\nimport torch\n\nmodel_id = 'charent\u002FChatLM-mini-Chinese'\n\n# 如果无法连接huggingface，打开以下两行代码的注释，将从modelscope下载模型文件，模型文件保存到'.\u002Fmodel_save'目录\n# from modelscope import snapshot_download\n# model_id = snapshot_download(model_id, cache_dir='.\u002Fmodel_save')\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\ntokenizer = AutoTokenizer.from_pretrained(model_id)\nmodel = AutoModelForSeq2SeqLM.from_pretrained(model_id, trust_remote_code=True).to(device)\n\ntxt = '如何评价Apple这家公司？'\n\nencode_ids = tokenizer([txt])\ninput_ids, attention_mask = torch.LongTensor(encode_ids['input_ids']), torch.LongTensor(encode_ids['attention_mask'])\n\nouts = model.my_generate(\n    input_ids=input_ids.to(device),\n    attention_mask=attention_mask.to(device),\n    max_seq_len=256,\n    search_type='beam',\n)\n\nouts_txt = tokenizer.batch_decode(outs.cpu().numpy(), skip_special_tokens=True, clean_up_tokenization_spaces=True)\nprint(outs_txt[0])\n```\n```txt\nApple是一家专注于设计和用户体验的公司，其产品在设计上注重简约、流畅和功能性，而在用户体验方面则注重用户的反馈和使用体验。作为一家领先的科技公司，苹果公司一直致力于为用户提供最优质的产品和服务，不断推陈出新，不断创新和改进，以满足不断变化的市场需求。\n在iPhone、iPad和Mac等产品上，苹果公司一直保持着创新的态度，不断推出新的功能和设计，为用户提供更好的使用体验。在iPad上推出的iPad Pro和iPod touch等产品，也一直保持着优秀的用户体验。\n此外，苹果公司还致力于开发和销售软件和服务，例如iTunes、iCloud和App Store等，这些产品在市场上也获得了广泛的认可和好评。\n总的来说，苹果公司在设计、用户体验和产品创新方面都做得非常出色，为用户带来了许多便利和惊喜。\n\n```\n\n## 3.2 从克隆仓库代码开始\n\n> [!CAUTION]\n> 本项目模型为`TextToText`模型，在预训练、SFT、RLFH阶段的`prompt`、`response`等字段，请务必加上`[EOS]`序列结束标记。   \n\n\n### 3.2.1 克隆项目：\n```bash\ngit clone --depth 1 https:\u002F\u002Fgithub.com\u002Fcharent\u002FChatLM-mini-Chinese.git\n\ncd ChatLM-mini-Chinese\n```\n### 3.2.2 安装依赖 \n\n本项目推荐使用`python 3.10`，过老的python版本可能不兼容所依赖的第三方库。  \n\npip安装：\n```bash\npip install -r .\u002Frequirements.txt\n``` \n\n如果pip安装了CPU版本的pytorch，可以通过下面的命令安装CUDA版本的pytorch：\n```bash\n# pip 安装torch + cu118\npip3 install torch --index-url https:\u002F\u002Fdownload.pytorch.org\u002Fwhl\u002Fcu118\n```\n\nconda安装：\n```bash\nconda install --yes --file .\u002Frequirements.txt\n```\n\n### 3.2.3 下载预训练模型及模型配置文件\n\n用`git`命令从`Hugging Face Hub`下载模型权重及配置文件，需要先安装[Git LFS](https:\u002F\u002Fdocs.github.com\u002Fzh\u002Frepositories\u002Fworking-with-files\u002Fmanaging-large-files\u002Finstalling-git-large-file-storage)，然后运行: \n\n```bash \n# 使用git命令下载huggingface模型，先安装[Git LFS]，否则下载的模型文件不可用\ngit clone --depth 1 https:\u002F\u002Fhuggingface.co\u002Fcharent\u002FChatLM-mini-Chinese\n\n# 如果无法连接huggingface，请从modelscope下载\ngit clone --depth 1 https:\u002F\u002Fwww.modelscope.cn\u002Fcharent\u002FChatLM-mini-Chinese.git\n\nmv ChatLM-mini-Chinese model_save\n```\n\n也可以直接从`Hugging Face Hub`仓库[ChatLM-Chinese-0.2B](https:\u002F\u002Fhuggingface.co\u002Fcharent\u002FChatLM-mini-Chinese)手工下载，将下载的文件移动到`model_save`目录下即可。\n\n## 3.3 Tokenizer训练  \n\n1. 准备txt语料  \n\n语料要求尽可能全，建议添加多个语料，如百科、代码、论文、博客、对话等。   \n\n本项目以wiki中文百科为主。获取中文wiki语料方法：中文Wiki下载地址：[zhwiki](https:\u002F\u002Fdumps.wikimedia.org\u002Fzhwiki\u002F)，下载`zhwiki-[存档日期]-pages-articles-multistream.xml.bz2`文件，大概2.7GB， 将下载的bz2文件转换为wiki.txt参考：[WikiExtractor](https:\u002F\u002Fgithub.com\u002Fapertium\u002FWikiExtractor)，再利用python的`OpenCC`库转换为简体中文，最后将得到的`wiki.simple.txt`放到项目根目录的`data`目录下即可。多个语料请自行合并为一个`txt`文件。\n\n由于训练tokenizer非常耗内存，如果你的语料非常大（合并后的`txt`文件超过2G），建议对语料按照类别、比例进行采样，以减少训练时间和内存消耗。训练1.7GB的`txt`文件需要消耗48GB左右的内存（预估的，我只有32GB，频繁触发swap，电脑卡了好久T_T），13600k cpu耗时1小时左右。\n\n2. 训练tokenizer\n\n`char level`和`byte level`的区别如下（具体使用上的区别请自行检索资料）。默认训练`char level`的tokenizer，如果需要`byte level`，在`train_tokenizer.py`中设置`token_type='byte'`即可。\n\n```python\n# 原始文本\ntxt = '这是一段中英混输的句子, （chinese and English, here are words.）'\n\ntokens = charlevel_tokenizer.tokenize(txt)\nprint(tokens)\n# char level tokens输出\n# ['▁这是', '一段', '中英', '混', '输', '的', '句子', '▁,', '▁(', '▁ch', 'inese', '▁and', '▁Eng', 'lish', '▁,', '▁h', 'ere', '▁', 'are', '▁w', 'ord', 's', '▁.', '▁)']\n\ntokens = bytelevel_tokenizer.tokenize(txt)\nprint(tokens)\n# byte level tokens输出\n# ['Ġè¿Ļæĺ¯', 'ä¸Ģæ®µ', 'ä¸Ńèĭ±', 'æ··', 'è¾ĵ', 'çļĦ', 'åı¥åŃĲ', 'Ġ,', 'Ġ(', 'Ġch', 'inese', 'Ġand', 'ĠEng', 'lish', 'Ġ,', 'Ġh', 'ere', 'Ġare', 'Ġw', 'ord', 's', 'Ġ.', 'Ġ)']\n```\n开始训练：\n```python\n# 确保你的训练语料`txt`文件已经data目录下\npython train_tokenizer.py\n```\n\n## 3.4 Text-to-Text 预训练 \n\n1. 预训练数据集示例\n```json\n{\n    \"prompt\": \"对于花园街，你有什么了解或看法吗？\",\n    \"response\": \"花园街（是香港油尖旺区的一条富有特色的街道，位于九龙旺角东部，北至界限街，南至登打士街，与通菜街及洗衣街等街道平行。现时这条街道是香港著名的购物区之一。位于亚皆老街以南的一段花园街，也就是\\\"波鞋街\\\"整条街约150米长，有50多间售卖运动鞋和运动用品的店舖。旺角道至太子道西一段则为排档区，售卖成衣、蔬菜和水果等。花园街一共分成三段。明清时代，花园街是芒角村栽种花卉的地方。此外，根据历史专家郑宝鸿的考证：花园街曾是1910年代东方殷琴拿烟厂的花园。纵火案。自2005年起，花园街一带最少发生5宗纵火案，当中4宗涉及排档起火。2010年。2010年12月6日，花园街222号一个卖鞋的排档于凌晨5时许首先起火，浓烟涌往旁边住宅大厦，消防接报4\"\n}\n```\n   \n2. jupyter-lab 或者 jupyter notebook:  \n\n    见文件`train.ipynb`，推荐使用jupyter-lab，避免考虑与服务器断开后终端进程被杀的情况。 \n\n3. 控制台： \n\n    控制台训练需要考虑连接断开后进程被杀的，推荐使用进程守护工具`Supervisor`或者`screen`建立连接会话。\n\n    首先要配置`accelerate`，执行以下命令， 根据提示选择即可，参考`accelerate.yaml`，*注意：DeepSpeed在Windows安装比较麻烦*。\n    ```bash\n    accelerate config\n    ```\n\n    开始训练，如果要使用工程提供的配置请在下面的命令`accelerate launch`后加上参数`--config_file .\u002Faccelerate.yaml`，*该配置按照单机2xGPU配置。* \n\n    *预训练有两个脚本，本项目实现的trainer对应`train.py`，huggingface实现的trainer对应`pre_train.py`，用哪个都可以，效果一致。本项目实现的trainer训练信息展示更美观、更容易修改训练细节（如损失函数，日志记录等），均支持断点继续训练，本项目实现的trainer支持在任意位置断点后继续训练，按`ctrl+c`退出脚本时会保存断点信息。* \n\n    单机单卡：\n    ```bash\n    # 本项目实现的trainer\n    accelerate launch .\u002Ftrain.py train\n\n    # 或者使用 huggingface trainer\n    python pre_train.py\n    ```\n\n    单机多卡：\n    `2`为显卡数量，请根据自己的实际情况修改。\n    ```bash\n    # 本项目实现的trainer\n    accelerate launch --multi_gpu --num_processes 2 .\u002Ftrain.py train\n\n    # 或者使用 huggingface trainer\n    accelerate launch --multi_gpu --num_processes 2 pre_train.py\n    ```\n\n    从断点处继续训练：\n    ```bash\n    # 本项目实现的trainer\n    accelerate launch --multi_gpu --num_processes 2 .\u002Ftrain.py train --is_keep_training=True\n\n    # 或者使用 huggingface trainer\n    # 需要在`pre_train.py`中的`train`函数添加`resume_from_checkpoint=True`\n    accelerate launch --multi_gpu --num_processes 2 pre_train.py\n    ```\n\n## 3.5 SFT微调 \nSFT数据集全部来自[BELLE](https:\u002F\u002Fgithub.com\u002FLianjiaTech\u002FBELLE)大佬的贡献，感谢。SFT数据集分别为：[generated_chat_0.4M](https:\u002F\u002Fhuggingface.co\u002Fdatasets\u002FBelleGroup\u002Fgenerated_chat_0.4M)、[train_0.5M_CN](https:\u002F\u002Fhuggingface.co\u002Fdatasets\u002FBelleGroup\u002Ftrain_0.5M_CN)和[train_2M_CN](https:\u002F\u002Fhuggingface.co\u002Fdatasets\u002FBelleGroup\u002Ftrain_2M_CN)，清洗后剩余约137万行。\nsft指令微调数据集示例：\n```json\n{\n    \"prompt\": \"解释什么是欧洲启示录\",\n    \"response\": \"欧洲启示录（The Book of Revelation）是新约圣经的最后一卷书，也被称为《启示录》、《默示录》或《约翰默示录》。这本书从宗教的角度描述了世界末日的来临，以及上帝对世界的审判和拯救。 书中的主题包括来临的基督的荣耀，上帝对人性的惩罚和拯救，以及魔鬼和邪恶力量的存在。欧洲启示录是一个充满象征和暗示的文本，对于解读和理解有许多不同的方法和观点。\"\n}\n```\n\n参考`data`目录下的示例`parquet`文件制作自己的数据集，数据集格式：`parquet`文件分两列，一列`prompt`文本，表示提示语，一列`response`文本，表示期待的模型输出。\n微调细节见`model\u002Ftrainer.py`下的`train`方法, `is_finetune`设置为`True`时，将进行微调，微调默认会冻结embedding层和encoder层，只训练decoder层。如需要冻结其他参数，请自行调整代码。 \n\n运行SFT微调：\n``` bash\n# 本项目实现的trainer， 添加参数`--is_finetune=True`即可, 参数`--is_keep_training=True`可从任意断点处继续训练\naccelerate launch --multi_gpu --num_processes 2 .\u002Ftrain.py --is_finetune=True\n\n# 或者使用 huggingface trainer, 多GPU请用accelerate launch --multi_gpu --num_processes gpu个数 sft_train.py\npython sft_train.py\n```\n\n## 3.6 RLHF（强化学习人类反馈优化方法）\n\n偏好方法这里介绍常见的两种：PPO和DPO，具体实现请自行搜索论文及博客。\n\n1.  PPO方法（近似偏好优化,Proximal Policy Optimization）  \n    步骤1：使用微调数据集做有监督微调（SFT， Supervised Finetuning）。   \n    步骤2：使用偏好数据集（一个prompt至少包含2个回复，一个想要的回复，一个不想要的回复。多个回复可以按照分数排序，最想要的分数最高）训练奖励模型（RM， Reward Model）。可使用`peft`库快速搭建Lora奖励模型。   \n    步骤3：利用RM对SFT模型进行有监督PPO训练，使得模型满足偏好。   \n\n2.  使用DPO（直接偏好优化，Direct Preference Optimization）微调（**本项目采用DPO微调方法，比较节省显存**）\n    在获得SFT模型的基础上，无需训练奖励模型，取得正向回答（chosen）和负向回答（rejected）即可开始微调。微调的`chosen`文本来自原数据集[alpaca-gpt4-data-zh](https:\u002F\u002Fhuggingface.co\u002Fdatasets\u002Fc-s-ale\u002Falpaca-gpt4-data-zh)，拒绝文本`rejected`来自SFT微调1个epoch后的模型输出，另外两个数据集：[huozi_rlhf_data_json](https:\u002F\u002Fhuggingface.co\u002Fdatasets\u002FSkepsun\u002Fhuozi_rlhf_data_json)和[rlhf-reward-single-round-trans_chinese](https:\u002F\u002Fhuggingface.co\u002Fdatasets\u002Fbeyond\u002Frlhf-reward-single-round-trans_chinese)，合并后共8万条dpo数据。\n    \n    dpo数据集处理过程见`utils\u002Fdpo_data_process.py`。\n    \nDPO偏好优化数据集示例：\n```json\n    {\n        \"prompt\": \"为给定的产品创建一个创意标语。，输入：可重复使用的水瓶。\",\n        \"chosen\": \"\\\"保护地球，从拥有可重复使用的水瓶开始！\\\"\",\n        \"rejected\": \"\\\"让你的水瓶成为你的生活伴侣，使用可重复使用的水瓶，让你的水瓶成为你的伙伴\\\"\"\n    }\n```\n\n运行偏好优化：\n``` bash\n#  多GPU请用accelerate launch --multi_gpu --num_processes gpu个数 dpo_train.py\npython dpo_train.py\n```\n\n## 3.7 推理 \n确保`model_save`目录下有以下文件，这些文件都可以在`Hugging Face Hub`仓库[ChatLM-Chinese-0.2B](https:\u002F\u002Fhuggingface.co\u002Fcharent\u002FChatLM-mini-Chinese)中找到：\n```bash\nChatLM-mini-Chinese\n├─model_save\n|  ├─config.json\n|  ├─configuration_chat_model.py\n|  ├─generation_config.json\n|  ├─model.safetensors\n|  ├─modeling_chat_model.py\n|  ├─special_tokens_map.json\n|  ├─tokenizer.json\n|  └─tokenizer_config.json\n```\n\n1. 控制台运行：\n```bash\npython cli_demo.py\n```\n\n2. API调用\n```bash\npython api_demo.py\n```\n\nAPI调用示例：\n```bash\ncurl --location '127.0.0.1:8812\u002Fapi\u002Fchat' \\\n--header 'Content-Type: application\u002Fjson' \\\n--header 'Authorization: Bearer Bearer' \\\n--data '{\n    \"input_txt\": \"感冒了要怎么办\"\n}'\n```\n![api demo](.\u002Fimg\u002Fapi_example.png)\n\n## 3.8 下游任务微调\n\n这里以文本中三元组信息为例，做下游微调。该任务的传统深度学习抽取方法见仓库[pytorch_IE_model](https:\u002F\u002Fgithub.com\u002Fcharent\u002Fpytorch_IE_model)。抽取出一段文本中所有的三元组，如句子`《写生随笔》是冶金工业2006年出版的图书，作者是张来亮`，抽取出三元组`(写生随笔,作者,张来亮)`和`(写生随笔,出版社,冶金工业)`。 \n\n原始数据集为：[百度三元组抽取数据集](https:\u002F\u002Faistudio.baidu.com\u002Fdatasetdetail\u002F11384)。加工得到的微调数据集格式示例：\n```json\n{\n    \"prompt\": \"请抽取出给定句子中的所有三元组。给定句子：《家乡的月亮》是宋雪莱演唱的一首歌曲，所属专辑是《久违的哥们》\",\n    \"response\": \"[(家乡的月亮,歌手,宋雪莱),(家乡的月亮,所属专辑,久违的哥们)]\"\n}\n```\n\n可以直接使用`sft_train.py`脚本进行微调，脚本[finetune_IE_task.ipynb](.\u002Ffinetune_examples\u002Finfo_extract\u002Ffinetune_IE_task.ipynb)里面包含详细的解码过程。训练数据集约`17000`条，学习率`5e-5`，训练epoch`5`。微调后其他任务的对话能力也没有消失。\n\n![信息抽取任务微调后的对话能力](.\u002Fimg\u002Fie_task_chat.png)\n\n微调效果：\n将`百度三元组抽取数据集`公开的`dev`数据集作为测试集，对比传统方法[pytorch_IE_model](https:\u002F\u002Fgithub.com\u002Fcharent\u002Fpytorch_IE_model)。\n\n|          模型            |   F1分数  |  精确率P |  召回率R |\n|          :---            |  :----:  |    :---:  |  :---:   |\n| ChatLM-Chinese-0.2B微调  |   0.74    |  0.75   |  0.73    |\n| ChatLM-Chinese-0.2B无预训练| 0.51    |   0.53   | 0.49    |\n| 传统深度学习方法          |   0.80    |  0.79   |  80.1    |\n\n备注：`ChatLM-Chinese-0.2B无预训练`指直接初始化随机参数，开始训练，学习率`1e-4`，其他参数和微调一致。\n\n## 3.9 C-Eval分数\n模型本身没有使用较大的数据集训练，也没有针对回答选择题的指令做微调，C-Eval分数基本上是baseline水平，有需要的可以当个参考。C-Eval评测代码见：`eval\u002Fc_eavl.ipynb`\n\n| category   | correct | question_count| accuracy |\n|    :---    |  :----:    |    :---:      |  :---:   |\n| Humanities |  \t63    |    \t257       |\t  24.51% |\n| Other\t     |     89     |\t     384      |   23.18% |\n| STEM       |\t   89\t  |      430      |  20.70%  |\n| Social Science |   72   |\t     275      |\t  26.18% |\n\n# 四、🎓引用\n如果你觉得本项目对你有所帮助，欢迎引用。\n```conf\n@misc{Charent2023,\n    author={Charent Chen},\n    title={A small chinese chat language model with 0.2B parameters base on T5},\n    year={2023},\n    publisher = {GitHub},\n    journal = {GitHub repository},\n    howpublished = {\\url{https:\u002F\u002Fgithub.com\u002Fcharent\u002FChatLM-mini-Chinese}},\n}\n```\n\n# 五、🤔其他事项\n本项目不承担开源模型和代码导致的数据安全、舆情风险或发生任何模型被误导、滥用、传播、不当利用而产生的风险和责任。\n\n\u003C!-- # 提示\n```bash\n# 导出项目依赖的包：\npipreqs --encoding \"utf-8\" --force\n``` -->\n\n","ChatLM-mini-Chinese是一个中文对话0.2B小模型，旨在为资源有限的用户提供一个轻量级的语言模型解决方案。该项目开源了从数据清洗、tokenizer训练到模型预训练、SFT指令微调以及RLHF优化的全部流程代码，并支持下游任务如三元组信息抽取的微调。技术上，它基于Huggingface NLP框架，包括transformers、accelerate等库，自定义实现了一个trainer以支持单机单卡或多卡训练，并允许在任意位置中断和恢复训练过程。此外，通过流式加载大数据集等优化手段，使得即使是在显存仅为4GB的设备上也能进行预训练。此项目非常适合那些希望在有限计算资源条件下探索语言模型训练与应用的研究者或开发者使用。",2,"2026-06-11 03:30:01","top_topic"]