爆火的微信聊天记录整理工具,功能超强!可对微信聊天记录进行解密加密,支持把聊天转移存储,支持对任意联系人和聊天记录搜索,提取微信聊天记录,将其导出成HTML、Word、Excel文档永久保存,对聊天记录进行分析生成年度聊天报告,用聊天数据训练专属于个人的AI聊天助手。
我深信有意义的不是微信,而是隐藏在对话框背后的一个个深刻故事。未来,每个人都能拥有AI的陪伴,而你的数据能够赋予它有关于你过去的珍贵记忆。我希望每个人都有将自己的生活痕迹👨👩👦👚🥗🏠️🚴🧋⛹️🛌🛀留存的权利,而不是遗忘💀。
AI的发展不仅仅是技术的提升,更是情感💞的延续。每一个对话、每一个互动都是生活中独一无二的片段,是真实而动人的情感交流。因此,我希望AI工作者们能够善用这些自己的数据,用于培训独特的、属于个体的人工智能。让个人AI成为生活中的朋友,能够理解、记录并分享我们的欢笑、泪水和成长。
那天,AI不再是高不可攀的存在,而是融入寻常百姓家的一部分。因为每个人能拥有自己的AI,将科技的力量融入生活的方方面面。这是一场关于真情实感的革命,一场让技术变得更加人性化的探索,让我们共同见证未来的美好。
🍉功能
🔒️🔑🔓️Windows本地微信数据库
还原微信聊天界面
🗨文本✅
🏝图片✅
拍一拍等系统消息✅
导出数据
批量导出数据✅
导出联系人✅
sqlite数据库✅
HTML✅
文本、图片、视频、表情包、语音、文件、分享链接、系统消息、引用消息、合并转发的聊天记录、转账、音视频通话、位置分享、名片、小程序、视频号
支持时间轴跳转
引用消息可定位到原文
分享链接、小程序支持超链接跳转
合并转发的聊天记录支持展开
CSV文档✅
TXT文档✅
Word文档✅
效果
开发者手册
源码运行
运行前请确保您的电脑上已经安装了Git、版本不低于3.10的Python、部分第三方库需要用到MSVC,需要提前安装Windows构建工具
1. 安装
# Python>=3.10 仅支持3.10、3.11、3.12,请勿使用其他Python版本
git clone https://github.com/LC044/WeChatMsg
# 网络不好推荐用Gitee
# git clone https://gitee.com/lc044/WeChatMsg.git
cd WeChatMsg
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
2. 使用
- 登录微信
手机端使用聊天记录迁移功能将聊天数据迁移到电脑上(可选)
操作步骤:
- 安卓: 手机微信->我->设置->聊天->聊天记录迁移与备份->迁移-> 迁移到电脑微信(迁移完成后重启微信)否则
- iOS: 手机微信->我->设置->通用->聊天记录迁移与备份->迁移-> 迁移到电脑微信(迁移完成后重启微信)否则
- 运行程序
python main.py
- 点击获取信息
- 设置微信安装路径(如果自动设置好了就不用管了)
可以到微信->设置->文件管理查看
点击设置微信路径按钮,选择该文件夹路径下的带有wxid_xxx的路径(没有wxid的话先选择其中一个文件夹不对的话换其他文件夹)
- 获取到key和微信路径之后点击开始启动
- 数据库文件保存在./app/DataBase/Msg路径下
3. 查看
随便下载一个SQLite数据库查看软件就能打开数据库,例如DB Browser for SQLite
微信数据库介绍
微信PC端各个数据库简述
- 说明:针对 …/WeChat Files/wxid_xxxxxxxx/Msg下的各个文件解密后的内容进行概述
- 未作特别说明的情况下,“聊天记录数据”指代的数据结构上都和Multi文件夹中的完整聊天记录数据相同或类似。
- 本文档仅供学习交流使用,严禁用于商业用途及非法用途,否则后果自负
一、微信小程序相关
微信小程序的相关数据,包括但不限于:
- 你使用过的小程序 RecentWxApp
- 星标的小程序 StarWxApp
- 各个小程序的基本信息 WAContact
用处不大,不过可以看到你使用过的小程序的名称和图标,以及小程序的AppID
二、企业微信相关
BizChat
企业微信联系人数据,包括但不限于:
- 在微信中可以访问的企业微信会话ChatInfo
- 一部分会话的信息ChatSession(未确认与ChatInfo的关系;这其中的Content字段是最近一条消息,疑似用于缓存展示的内容)
- 包括群聊在内的聊天涉及的所有企业微信用户身份信息UsrInfo
- 该微信账号绑定的企业微信身份MyUsrInfo
- 特别说明:未经详细查证,这其中的聊天是否包含使用普通微信身份与企业微信用户发起的聊天,还是只包含使用绑定到普通微信的企业微信身份与其它企业微信身份发起的聊天。
BizChatMsg
- 企业微信聊天记录数据,包括所有和企业微信聊天的数据。
- 与BizChat一样,未确定涉及的范围究竟是只有企业微信-企业微信还是同时包含普通微信-企业微信。
- 另外,此处的消息与Multi文件夹中真正的微信消息不同的是在于没有拆分数据库。
OpenIM 前缀
- 这个也是企业微信的数据,包括联系人、企业信息、与企业微信联系人的消息等。
- 这个是普通微信-企业微信的数据,上面biz前缀的是企业微信-企业微信
- 这个不常用,而且也没有全新的数据结构,不再详细说了。
PublicMsg
- 看起来像是企业微信的通知消息,可以理解为企业微信的企业应用消息
三、微信功能相关
Emotion
顾名思义表情包相关,包括但不限于以下内容:
- CustomEmotion:顾名思义用户手动上传的GIF表情,包含下载链接,不过看起来似乎有加密(内有aesKey字段但我没测试)
- EmotionDes1 和 EmotionItem 应该也是类似的内容,没仔细研究
- EmotionPackageItem:账号添加的表情包的集合列表(从商店下载的那种)
ps:用处不大,微信的MSG文件夹有表情包的url链接,可以直接网络获取聊天记录中的表情包。
Favorite
- FavItems:收藏的消息条目列表
- FavDataItem:收藏的具体数据。没有自习去看他的存储逻辑,不过大概可以确定以下两点
- 即使只是简单收藏一篇公众号文章也会在 FavDataItem 中有一个对应的记录
- 对于收藏的合并转发类型的消息,合并转发中的每一条消息在 FavDataItem 中都是一个独立的记录
- FavTags:为收藏内容添加的标签
Misc
- 有BizContactHeadImg和ContactHeadImg1两张表,应该是二进制格式的各个头像
Sns
微信朋友圈的相关数据:
- FeedsV20:朋友圈的XML数据
- CommentV20:朋友圈点赞或评论记录
- NotificationV7:朋友圈通知
- SnsConfigV20:一些配置信息,能读懂的是其中有你的朋友圈背景图
- SnsGroupInfoV5:猜测是旧版微信朋友圈可见范围的可见或不可见名单
FTS(搜索)
- 前缀为 FTS 的数据库可能都和全文搜索(Full-Text Search)相关(就是微信那个搜索框)
FTSContact
有一堆表
- FTSChatroom15_content 和 FTSContact15_content
分别对应的是微信“聊天”界面会展示的消息会话(包括公众号等)和“联系人”界面会出现的所有人(有的时候并不是所有联系人都会出现在“聊天”中),信息包含昵称、备注名和微信号,也和微信支持搜索的字段相匹配。
FTSFavorite
搜索收藏内容的索引
- 命名方式类似上面一条
ps:对于收藏内容通过文字搜索,电脑版是把所有东西拼接成一个超长字符串来实现的。这对于文本、链接等没啥问题,但是对于合并转发消息,就会出现搜索[图片]
这一关键词。
MultiSearchChatMsg
- 这个数据库前缀不一样,但是看内容和结构应该还是一个搜索相关,搜索的是聊天记录中的文件
- 存储了文件名和其所在的聊天
- 不过FTSMsgSearch18_content和SessionAttachInfo两张表记录数量有显著差异,不确定是哪个少了或是怎样。
HardLink(文件在磁盘存储的位置)
- 将文件/图片/视频的文件名指向保存它们的文件夹名称(例如2023-04),有用但不多。
Media
- ChatCRVoice和MediaInfo 可能为语音信息
三、MicroMsg (联系人核心)
一个数据库,不应该和分类平级,但是我认为这是分析到目前以来最核心的,因此单独来说了。
AppInfo(表)
一些软件的介绍,猜测可能是关于某些直接从手机APP跳转到微信的转发会带有的转发来源小尾巴的信息
Biz 前缀
与公众号相关的内容,应该主要是账号本身相关。
能确定的是 BizSessionNewFeeds 这张表保存的是订阅号大分类底下的会话信息,包括头像、最近一条推送等。
ChatInfo
保存“聊天”列表中每个会话最后一次标记已读的时间
ChatRoom 和 ChatRoomInfo
存储群聊相关信息
- ChatRoom:存储每个群聊的用户列表(包括微信号列表和群昵称列表)和个人群昵称等信息
- ChatRoomInfo:群聊相关信息,主要是群公告内容,与成员无关
顺便再吐槽一下,微信这个位置有一个命名出现异常的,别的表前缀都是ChatRoom,而突然出现一个ChatroomTool
Contact
顾名思义,联系人。不过这里的联系人并不是指你的好友,而是所有你可能看见的人,除好友外还有所有群聊中的所有陌生人。
- Contact:这张表存储的是用户基本信息,包括但不限于微信号(没有好友的陌生人也能看!)、昵称、备注名、设置的标签等等,甚至还有生成的各种字段的拼音,可能是用于方便搜索的吧
- ContactHeadImgUrl:头像地址
- ContactLabel:好友标签 ID 与名称对照
- ExtraBuf: 存储位置信息、手机号、邮箱等信息
PatInfo
存了一部分好友的拍一拍后缀,但是只有几个,我记得我电脑上显示过的拍一拍似乎没有这么少?
Session
真正的“聊天”栏目显示的会话列表,一个不多一个不少,包括“折叠的群聊”这样子的特殊会话;信息包括名称、未读消息数、最近一条消息等
TicketInfo
这张表在我这里有百余条数据,但是我实在没搞明白它是什么
四、FTSMSG
FTS 这一前缀了——这代表的是搜索时所需的索引。
其内主要的内容是这样的两张表:
- FTSChatMsg2_content:内有三个字段
- docid:从1开始递增的数字,相当于当前条目的 ID
- c0content:搜索关键字(在微信搜索框输入的关键字被这个字段包含的内容可以被搜索到)
- c1entityId:尚不明确用途,可能是校验相关
- FTSChatMsg2_MetaData
- docid:与FTSChatMsg2_content表中的 docid 对应
- msgId:与MSG数据库中的内容对应
- entityId:与FTSChatMsg2_content表中的 c1entityId 对应
- type:可能是该消息的类型
- 其余字段尚不明确
特别地,表名中的这个数字2,个人猜测可能是当前数据库格式的版本号。
五、MediaMSG (语音消息)
这里存储了所有的语音消息。数据库中有且仅有Media一张表,内含三个有效字段:
- Key
- Reserved0 与MSG数据库中消息的MsgSvrID一一对应
- Buf silk格式的语音数据
六、MSG(聊天记录核心数据库)
内部主要的两个表是MSG
和Name2ID
Name2ID
Name2ID
这张表只有一列,内容格式是微信号或群聊ID@chatroom- 作用是使MSG中的某些字段与之对应。虽然表中没有 ID 这一列,但事实上微信默认了第几行 ID 就是几(从1开始编号)。
MSG
- localId:字面意思消息在本地的 ID,暂未发现其功用
- TalkerId:消息所在房间的 ID(该信息为猜测,猜测原因见 StrTalker 字段),与Name2ID对应。
- MsgSvrID:猜测 Srv 可能是 Server 的缩写,代指服务器端存储的消息 ID
- Type:消息类型,具体对照见表1
- SubType:消息类型子分类,暂时未见其实际用途
- IsSender:是否是自己发出的消息,也就是标记消息展示在对话页左边还是右边,取值0或1
- CreateTime:消息创建时间的秒级时间戳。此处需要进一步实验来确认该时间具体标记的是哪个时间节点,个人猜测的规则如下:
- 从这台电脑上发出的消息:标记代表的是每个消息点下发送按钮的那一刻
- 从其它设备上发出的/收到的来自其它用户的消息:标记的是本地从服务器接收到这一消息的时间
- Sequence:次序,虽然看起来像一个毫秒级时间戳但其实不是。这是
CreateTime
字段末尾接上三位数字组成的,通常情况下为000,如果在出现两条CreateTime
相同的消息则最后三位依次递增。需要进一步确认不重复范围是在一个会话内还是所有会话。CreateTime
相同的消息则最后三位依次递增。需要进一步确认不重复范围是在一个会话内还是所有会话。 - StatusEx、FlagEx、Status、MsgServerSeq、MsgSequence:这五个字段个人暂时没有分析出有效信息
- StrTalker:消息发送者的微信号。特别说明,从这里来看的话,上面的
TalkerId
字段大概率是指的消息所在的房间ID,而非发送者ID,当然也可能和TalkerId
属于重复内容,这一点待确认。 - StrContent:字符串格式的数据。特别说明的是,除了文本类型的消息外,别的大多类型这一字段都会是一段 XML
数据标记一些相关信息。通过解析xml可以得到更多的信息,例如图片的宽高、语音的时长等等。 - DisplayContent:对于拍一拍,保存拍者和被拍者账号信息
- Reserved0~6:这些字段也还没有分析出有效信息,也有的字段恒为空
- CompressContent:字面意思是压缩的数据,实际上也就是微信任性不想存在 StrContent
里的数据在这里(例如带有引用的文本消息等;采用lz4压缩算法压缩) - BytesExtra:额外的二进制格式数据
- BytesTrans:目前看这是一个恒为空的字段
表1:MSG.Type字段数值与含义对照表(可能可以扩展到其它数据库中同样标记消息类型这一信息的字段)
分类Type | 子分类SubType | 对应类型 |
---|---|---|
1 | 0 | 文本 |
3 | 0 | 图片 |
34 | 0 | 语音 |
43 | 0 | 视频 |
47 | 0 | 动画表情(第三方开发的表情包) |
49 | 1 | 类似文字消息而不一样的消息,目前只见到一个阿里云盘的邀请注册是这样的。估计和57子类的情况一样 |
49 | 5 | 卡片式链接,CompressContent 中有标题、简介等,BytesExtra 中有本地缓存的封面路径 |
49 | 6 | 文件,CompressContent 中有文件名和下载链接(但不会读),BytesExtra 中有本地保存的路径 |
49 | 8 | 用户上传的 GIF 表情,CompressContent 中有CDN链接,不过似乎不能直接访问下载 |
49 | 19 | 合并转发的聊天记录,CompressContent 中有详细聊天记录,BytesExtra 中有图片视频等的缓存 |
49 | 33/36 | 分享的小程序,CompressContent 中有卡片信息,BytesExtra 中有封面缓存位置 |
49 | 57 | 带有引用的文本消息(这种类型下 StrContent 为空,发送和引用的内容均在 CompressContent 中) |
49 | 63 | 视频号直播或直播回放等 |
49 | 87 | 群公告 |
49 | 88 | 视频号直播或直播回放等 |
49 | 2000 | 转账消息(包括发出、接收、主动退还) |
49 | 2003 | 赠送红包封面 |
10000 | 0 | 系统通知(居中出现的那种灰色文字) |
10000 | 4 | 拍一拍 |
10000 | 8000 | 系统通知(特别包含你邀请别人加入群聊) |
仓库目录功能介绍
├─app
│ ├─analysis # 聊天数据分析、画图的实现
│ ├─components # PyQt写的一些自定义UI组件
│ ├─data # 存储程序用到的必要数据文件
│ ├─DataBase # 有关数据库的操作和聊天记录导出
│ ├─decrypt # 数据库解密
│ ├─log # 日志存储
│ ├─resources # 必要的资源文件
│ ├─ui # ui界面实现
│ │ ├─chat # 聊天界面
│ │ ├─contact # 联系人界面
│ │ │ ├─export # 联系人聊天记录导出
│ │ │ └─userinfo # 联系人详细信息
│ │ ├─menu # 菜单栏功能的实现
│ │ ├─QSS # 样式表
│ │ └─tool # 工具界面
│ │ ├─get_bias_addr # 获取微信基址
│ │ ├─pc_decrypt # 数据库解密
│ │ └─setting # 设置
│ ├─util # 用到的一些通用工具(聊天数据解析、音视频处理)
│ │ └─protocbuf
│ └─web_ui # 年度报告等网页的实现(flask)
│ └─templates # HTML模板
├─doc # 文档
└─resource # pyecharts资源文件,供打包使用
大模型训练指南
一、导出聊天记录
导出json格式的聊天记录。
如果你想合并多个联系人的数据,可以直接运行下面的代码合并
import json
import os
data_dir = r'E:\Project\Python\MemoTrace\data\聊天记录'
dev_res = []
train_res = []
for filepath, dirnames, filenames in os.walk(data_dir):
for filename in filenames:
if filename.endswith('.json'):
print(filename, filepath)
filepath_ = os.path.join(filepath, filename)
with open(filepath_, 'r', encoding='utf-8') as f:
data = json.load(f)
if data:
if filename.endswith('train.json'):
train_res += data
else:
dev_res += data
with open('train.json', 'w', encoding='utf-8') as f:
json.dump(train_res, f, ensure_ascii=False, indent=4)
with open('dev.json', 'w', encoding='utf-8') as f:
json.dump(dev_res, f, ensure_ascii=False, indent=4)
你现在应该有两个文件,dev.json(验证集)和train.json(训练集)
二、下载ChatGLM3-6B模型
下载地址:https://github.com/THUDM/ChatGLM3
使用方式
环境安装
首先需要下载本仓库:
git clone https://github.com/THUDM/ChatGLM3
cd ChatGLM3
然后使用 pip 安装依赖:
pip install -r requirements.txt
- 为了保证
torch
的版本正确,请严格按照 官方文档 的说明安装。 - 如果遇到问题,请参照ChatGLM3项目的解决方案,不要在本项目中提问
三、ChatGLM3-6B 微调
本目录提供 ChatGLM3-6B 模型的微调示例,包括全量微调和 P-Tuning v2。格式上,提供多轮对话微调样例和输入输出格式微调样例。
如果将模型下载到了本地,本文和代码中的 THUDM/chatglm3-6b
字段均应替换为相应地址以从本地加载模型。
运行示例需要 python>=3.10
,除基础的 torch
依赖外,示例代码运行还需要依赖。
pip install -r requirements.txt
测试硬件标准
我们仅提供了单机多卡/多机多卡的运行示例,因此您需要至少一台具有多个 GPU 的机器。本仓库中的默认配置文件中,我们记录了显存的占用情况:
- SFT 全量微调: 4张显卡平均分配,每张显卡占用
48346MiB
显存。 - P-TuningV2 微调: 1张显卡,占用
18426MiB
显存。 - LORA 微调: 1张显卡,占用
14082MiB
显存。
请注意,该结果仅供参考,对于不同的参数,显存占用可能会有所不同。请结合你的硬件情况进行调整。
请注意,我们仅仅使用英伟达 Hopper(代表显卡:H100) 和 Ampère(代表显卡:A100) 架构和系列显卡做过测试。如果您使用其他架构的显卡,可能会出现
- 未知的训练问题 / 显存占用与上述有误差。
- 架构过低而不支持某些特性。
- 推理效果问题。
以上三种情况为社区曾经遇到过的问题,虽然概率极地,如果您遇到了以上问题,可以尝试在社区中解决。
多轮对话格式
多轮对话微调示例采用 ChatGLM3 对话格式约定,对不同角色添加不同 loss_mask
从而在一遍计算中为多轮回复计算 loss
。
对于数据文件,样例采用如下格式
如果您仅希望微调模型的对话能力,而非工具能力,您应该按照以下格式整理数据。
[
{
"conversations": [
{
"role": "system",
"content": "<system prompt text>"
},
{
"role": "user",
"content": "<user prompt text>"
},
{
"role": "assistant",
"content": "<assistant response text>"
},
// ... Muti Turn
{
"role": "user",
"content": "<user prompt text>"
},
{
"role": "assistant",
"content": "<assistant response text>"
}
]
}
// ...
]
请注意,这种方法在微调的step较多的情况下会影响到模型的工具调用功能
system
角色为可选角色,但若存在system
角色,其必须出现在user
角色之前,且一个完整的对话数据(无论单轮或者多轮对话)只能出现一次system
角色。
数据集格式示例
这里以 AdvertiseGen 数据集为例,
您可以从 Google Drive
或者 Tsinghua Cloud 下载 AdvertiseGen 数据集。
将解压后的 AdvertiseGen 目录放到 data
目录下并自行转换为如下格式数据集。
请注意,现在的微调代码中加入了验证集,因此,对于一组完整的微调数据集,必须包含训练数据集和验证数据集,测试数据集可以不填写。或者直接用验证数据集代替。
{"conversations": [{"role": "user", "content": "类型#裙*裙长#半身裙"}, {"role": "assistant", "content": "这款百搭时尚的仙女半身裙,整体设计非常的飘逸随性,穿上之后每个女孩子都能瞬间变成小仙女啦。料子非常的轻盈,透气性也很好,穿到夏天也很舒适。"}]}
配置文件
微调配置文件位于 config
目录下,包括以下文件:
ds_zereo_2 / ds_zereo_3.json
: deepspeed 配置文件。lora.yaml / ptuning.yaml / sft.yaml
: 模型不同方式的配置文件,包括模型参数、优化器参数、训练参数等。 部分重要参数解释如下:- data_config 部分
- train_file: 训练数据集的文件路径。
- val_file: 验证数据集的文件路径。
- test_file: 测试数据集的文件路径。
- num_proc: 在加载数据时使用的进程数量。
- max_input_length: 输入序列的最大长度。
- max_output_length: 输出序列的最大长度。
- training_args 部分
- output_dir: 用于保存模型和其他输出的目录。
- max_steps: 训练的最大步数。
- per_device_train_batch_size: 每个设备(如 GPU)的训练批次大小。
- dataloader_num_workers: 加载数据时使用的工作线程数量。
- remove_unused_columns: 是否移除数据中未使用的列。
- save_strategy: 模型保存策略(例如,每隔多少步保存一次)。
- save_steps: 每隔多少步保存一次模型。
- log_level: 日志级别(如 info)。
- logging_strategy: 日志记录策略。
- logging_steps: 每隔多少步记录一次日志。
- per_device_eval_batch_size: 每个设备的评估批次大小。
- evaluation_strategy: 评估策略(例如,每隔多少步进行一次评估)。
- eval_steps: 每隔多少步进行一次评估。
- predict_with_generate: 是否使用生成模式进行预测。
- generation_config 部分
- max_new_tokens: 生成的最大新 token 数量。
- peft_config 部分
- peft_type: 使用的参数有效调整类型(如 LORA)。
- task_type: 任务类型,这里是因果语言模型(CAUSAL_LM)。
- Lora 参数:
- r: LoRA 的秩。
- lora_alpha: LoRA 的缩放因子。
- lora_dropout: 在 LoRA 层使用的 dropout 概率
- P-TuningV2 参数:
- num_virtual_tokens: 虚拟 token 的数量。
- data_config 部分
开始微调
通过以下代码执行 单机多卡/多机多卡 运行,这是使用 deepspeed
作为加速方案的,您需要安装 deepspeed
。
cd finetune_demo
OMP_NUM_THREADS=1 torchrun --standalone --nnodes=1 --nproc_per_node=8 finetune_hf.py data/AdvertiseGen/ THUDM/chatglm3-6b configs/lora.yaml configs/ds_zero_2.json
通过以下代码执行 单机单卡 运行。
cd finetune_demo
python finetune_hf.py data/AdvertiseGen/ THUDM/chatglm3-6b configs/lora.yaml
从保存点进行微调
如果按照上述方式进行训练,每次微调都会从头开始,如果你想从训练一半的模型开始微调,你可以加入第四个参数,这个参数有两种传入方式:
yes
, 自动从最后一个保存的 Checkpoint开始训练XX
, 断点号数字 例600
则从序号600 Checkpoint开始训练
例如,这就是一个从最后一个保存点继续微调的示例代码
cd finetune_demo
python finetune_hf.py data/AdvertiseGen/ THUDM/chatglm3-6b configs/lora.yaml yes
使用微调后的模型
在 inference_hf.py 中验证微调后的模型
您可以在 finetune_demo/inference_hf.py
中使用我们的微调后的模型,仅需要一行代码就能简单的进行测试。
python inference_hf.py your_finetune_path --prompt your prompt
这样,得到的回答就微调后的回答了。
在本仓库的其他 demo 或者外部仓库使用微调后的模型
您可以在任何一个 demo 内使用我们的 lora
和 全参微调的模型。这需要你自己按照以下教程进行修改代码。
- 使用
finetune_demo/inference_hf.py
中读入模型的方式替换 demo 中读入模型的方式。
请注意,对于 LORA 和 P-TuningV2 我们没有合并训练后的模型,而是在
adapter_config.json
中记录了微调型的路径,如果你的原始模型位置发生更改,则你应该修改adapter_config.json
中base_model_name_or_path
的路径。
def load_model_and_tokenizer(
model_dir: Union[str, Path], trust_remote_code: bool = True
) -> tuple[ModelType, TokenizerType]:
model_dir = _resolve_path(model_dir)
if (model_dir / 'adapter_config.json').exists():
model = AutoPeftModelForCausalLM.from_pretrained(
model_dir, trust_remote_code=trust_remote_code, device_map='auto'
)
tokenizer_dir = model.peft_config['default'].base_model_name_or_path
else:
model = AutoModelForCausalLM.from_pretrained(
model_dir, trust_remote_code=trust_remote_code, device_map='auto'
)
tokenizer_dir = model_dir
tokenizer = AutoTokenizer.from_pretrained(
tokenizer_dir, trust_remote_code=trust_remote_code
)
return model, tokenizer
- 读取微调的模型,请注意,你应该使用微调模型的位置,例如,若你的模型位置为
/path/to/finetune_adapter_model
,原始模型地址为path/to/base_model
,则你应该使用/path/to/finetune_adapter_model
作为model_dir
。 - 完成上述操作后,就能正常使用微调的模型了,其他的调用方式没有变化。
提示
- 微调代码在开始训练前,会先打印首条训练数据的预处理信息(默认已经注释,可以解除注释),显示为
Sanity
Check >> >> >> >> >> >> >
'[gMASK]': 64790 -> -100
'sop': 64792 -> -100
'<|system|>': 64794 -> -100
'': 30910 -> -100
'\n': 13 -> -100
'Answer': 20115 -> -100
'the': 267 -> -100
'following': 1762 -> -100
...
'know': 683 -> -100
'the': 267 -> -100
'response': 3010 -> -100
'details': 3296 -> -100
'.': 30930 -> -100
'<|assistant|>': 64796 -> -100
'': 30910 -> 30910
'\n': 13 -> 13
'I': 307 -> 307
'need': 720 -> 720
'to': 289 -> 289
'use': 792 -> 792
...
<< << << << << << < Sanity
Check
字样,每行依次表示一个 detokenized string, token_id 和 target_id。其中,target_id
为token_id
在模型词表中的索引,-100
表示该
token 不参与 loss
计算。
_prepare_model_for_training
的作用是遍历模型的所有可训练参数,并确保它们的数据类型为torch.float32
。
这在某些情况下是必要的,因为混合精度训练或其他操作可能会更改模型参数的数据类型。该代码默打开,可以注释,但是如果使用
half
格式训练出现问题,可以切换回这个代码,显存可能增加。- 在我们的Huggingface模型代码中,有以下内容:
这可能导致训练的时候显存增加,因此,如果您的显存不足,可以尝试将if self.gradient_checkpointing and self.training: layer_ret = torch.utils.checkpoint.checkpoint( layer, hidden_states, attention_mask, rotary_pos_emb, kv_caches[index], use_cache, use_reentrant=False )
use_reentrant
修改为True
。 - 微调后的模型可以使用任何支持
peft
载入的模型加速框架,在这里,我们没有提供demo。 - 本仓库的微调数据集格式与 API 微调数据集格式有一定区别
- ZhipuAI API 微调数据集中的
messages
字段在本仓库为conversation
字段。 - ZhipuAI API 中的微调文件为
jsonl
, 在本仓库,需要简单的将文件名改为json
。
- ZhipuAI API 微调数据集中的
以上内容来自ChatGLM3项目
微调示例
配置文件
config/lora.yaml
data_config:
train_file: train.json
val_file: dev.json
test_file: dev.json
num_proc: 10
max_input_length: 512
max_output_length: 128
training_args:
# see `transformers.Seq2SeqTrainingArguments`
output_dir: ./output03-24
max_steps: 100000
# settings for data loading
per_device_train_batch_size: 4
dataloader_num_workers: 10
remove_unused_columns: false
# settings for saving checkpoints
save_strategy: steps
save_steps: 2000
# settings for logging
log_level: info
logging_strategy: steps
logging_steps: 10
# settings for evaluation
per_device_eval_batch_size: 4
evaluation_strategy: steps
eval_steps: 5200
# settings for optimizer
# adam_epsilon: 1e-6
# uncomment the following line to detect nan or inf values
# debug: underflow_overflow
predict_with_generate: yes
# see `transformers.GenerationConfig`
generation_config:
max_new_tokens: 256
# set your absolute deepspeed path here
#deepspeed: ds_zero_2.json
# set to true if train with cpu.
use_cpu: false
peft_config:
peft_type: LORA
task_type: CAUSAL_LM
r: 8
lora_alpha: 32
lora_dropout: 0.1
硬件配置:4090 24G、64G内存、CPU 14700KF 20核28线程
你需要根据你的硬件配置修改上述参数,各个参数含义上面有说
微调命令(需要指定数据集路径和ChatGLM3基础大模型的路径)
python finetune_hf.py data/ E:\\Project\\Python\\Langchain-Chatchat\\chatglm3-6b configs/lora.yaml yes
部署
在api_server.py修改微调保存路径
model, tokenizer = load_model_and_tokenizer(
r'E:\Project\Python\ChatGLM3\finetune_demo\output03-24\checkpoint-224000'
)
直接运行即可
python api_server.py
调用示例(你可以在任意一个支持ChatGPT的应用中使用它):
from openai import OpenAI
base_url = "http://127.0.0.1:8002/v1/"
client = OpenAI(api_key="EMPTY", base_url=base_url)
def simple_chat(use_stream=True):
messages = [
{
"role": "user",
"content": "你好啊"
}
]
response = client.chat.completions.create(
model="chatglm3-6b",
messages=messages,
stream=use_stream,
max_tokens=256,
temperature=0.8,
presence_penalty=1.1,
top_p=0.8)
if response:
if use_stream:
for chunk in response:
print(chunk.choices[0].delta.content, end='')
else:
content = response.choices[0].message.content
print(content)
else:
print("Error:", response.status_code)
if __name__ == "__main__":
simple_chat(use_stream=True)
体验地址
https://chat.memotrace.cn/
安装程序及源码下载地址:
链接: https://pan.baidu.com/s/1iWr71ubGqCRT4HxFgD_fOA 提取码: 6q6t 复制这段内容后打开百度网盘手机App,操作更方便哦