微信导出聊天记录清洗为数据集微调Qwen2.5-7B

2026年10月24日星期六·#AI技术·3756 字 19 分钟·
-浏览量
·

微信导出聊天记录清洗为数据集微调Qwen2.5-7B#


1. 起点:把微信聊天记录炼成数据集#

之前就用过一个项目是能把大模型对接微信,而且我发现可以用本地llama接口直接跑大模型。只不过回复很生硬,所以我就想拿数据集微调大模型把他更偏向口吻像人。所以就拿alpha这个开源项目导出了json格式的微信数据集,给ai让他帮我转成llamafactory可读的数据集。

1.1 提取:开源工具 alpha 把聊天记录拉成 JSON#

第一步解决”数据从哪来”。用开源项目 alpha 从微信提取聊天记录,导出为 JSON:225,627 条原始消息、21 个私聊会话、全部文本。

这一步的意义在于:模型的口吻不需要虚构,直接从真人对话里学。每个人说话的节奏、口头禅、话题跳跃方式,都原样躺在原始记录里。

1.2 注册:让 LLaMA-Factory 认识这份数据#

微信导出的 JSON 有自己的结构(每条消息带 direction:1 = 好友,2 = 号主本人),LLaMA-Factory 当然不认识。转换目标是最通用的 sharegpt / messages 风格:

{"messages":[{"role":"user","content":"问句"},{"role":"assistant","content":"回答"}]}

再配一个 dataset_info.json 条目放进 data/ 目录,数据集就被注册识别;Qwen 模板由 LLaMA-Factory 依据模型名自动套用

1.3 清洗:八条#

注册只是让框架”认得”,清洗才决定数据”干不干净”。执行口径:

  1. 格式固定:每条样本都是 {"messages":[{"role":"user",…},{"role":"assistant",…}]},user 永远是提问方、assistant 永远是回复方,不翻转角色。
  2. 极简短句尽量减少:单轮样本要求 user ≥ 3 字、assistant ≥ 3 字且合计 ≥ 8 字——「吃饭了吗 / 嗯」这类直接剔除;多轮样本要求合计 ≥ 24 字,且至少一轮两边都有实义。
  3. 剔除空回答 / 纯符号:内容去掉 emoji 占位 [xx]、标点、空白后,若无任何中英文,整条丢弃。
  4. 长度硬上限:用 Qwen2.5 官方 tokenizer 精确计数,单样本 ≤ 768 token(实测最大 767);多轮最多 4 轮,超长对话按 ≤ 4 轮切片。
  5. 文本清洗:去除 \r、控制字符、特殊空白(\xa0 \u3000 \u200b \ufeff 等),3+ 连续换行压缩为 2、多余空格压缩;不编造任何对话,只使用原始文本。
  6. 分段与合并:同一会话内按 15 分钟间隔切分对话;同一人连续发出的多条消息用换行合并为一条;开头多余的 assistant、结尾没有回复的 user,一律裁掉。
  7. 去重:整样本完全相同的去掉。
  8. 直接可用:不做任何模板层 hack。

1.4 关键设计:双向样本#

这份数据最有意思的设计是双向生成:

  • 正向(好友问 / 你答):好友是 user,号主本人是 assistant → 模型学”以你的口吻回复”,这是”数字分身代聊”的核心;
  • 反向(你问 / 好友答):号主是 user,好友是 assistant → 模型同时学 21 位好友的口吻,对话风格更多样、更像真人在聊。

两个方向用完全相同的清洗 / 分段 / 轮数 / token 规则生成,再全局去重合并:14,831 + 14,207 − 1 = 29,037 条。

代价也说清楚:反向集里 assistant 是 21 个人语气的混合体,风格不如正向一致。只想要”纯数字分身”的话,删掉反向样本重新生成即可。

1.5 产出与一条刻意的设计#

最终产出 wechat_sft.jsonl:29,037 条、13.4MB,token 分布均值 90、p99 312、最大 767。清洗的代价也记账:无意义短句丢了 12,757 条、超长刷屏 420 条、单轮过短约 3,641 条、多轮无实义约 2,335 条、token 超限收缩 56 条,外加双向各约 20,815 次的会话头尾裁剪。

还有一条刻意的设计:这份数据不含 system prompt。因为 system 是”助手味”最大的来源,而数字分身要的是”无 AI 味”的口语风格。

有意思的是,后来做女生语气数据集时,在同一条注册 / 清洗流水线上做出了完全相反的系统设计——那边把 system prompt 当”人格开关”用。同样的地基,两种相反的设计,服务两个不同的目标,这个对照留到第 3 章展开。

数字分身跑通之后,野心自然变大:换成公开的大规模中文聊天数据,效果会不会更好?——于是有了第二章那次”越训越傻”的事故。


2. 事故现场:500 轮之后,模型傻了#

一切始于一句抱怨:“我用 LCCC 训练了 500 轮,回复变得傻傻的。”

第一反应是打开日志,而日志给出的答案和”玄学”完全无关:

  • “500 轮”其实是 500 步。按训练配置算,总共需要 11,876 步才够一个 epoch——500 步只跑了 4.2%,模型连一遍数据都没见完。
  • eval loss 从 3.820 只降到 3.758。这个降幅约等于没降,证明这批数据里几乎没有可学的有效信号(或者说,以当时的配置,信号没被学到)。
  • 学习率 1e-4,且没有 system prompt。对 instruct 基座来说这个 lr 偏冲动,又没有对话格式约束,指令能力被平推冲掉了。

还有个插曲:回收站里那个”导出的 adapter”,经核对其实是另一条 run(高情商 170 条、5 epoch)的产物,跟这次 LCCC run 没关系。日志和产物对不上,是微调翻车现场最常见的一坑。

诊断结论一句话:不是模型笨,是数据没选对、训练没跑够、格式没管住,三件事叠加。


3. 选型:什么数据能”塑造语气”?#

需求很明确:要一个”像女生一样聊天”的模型。语气这种属性,靠的是稠密的示范信号——每一句回复都在告诉模型”这种情况下,她会这么说”。

候选方案里最有吸引力的是某个繁体角色卡数据集(社区里流传较广的 RP 语料),但下载后做了一次内容安全扫描:2,109 张角色卡全部命中成人向关键词,无一例外。直接弃用,并把源文件清掉了。

最终选了一条更稳的路线:

来源角色条数
BelleGroup generated_chat_0.4M(39.6 万条通用角色扮演底料)过滤出女生向对话1,555
「中文高情商可爱聊天数据集」人格锚点170
同底料 reservoir 随机抽样通用压舱石19,992
合计21,717

3.1 关键一步:女性换位#

从底料过滤女生向对话时有个细节:原始对话里女性角色常常出现在 user 侧(第一说话人)。如果直接拿去训练,模型学到的是”捧哏”而不是”主侃”。

处理办法是整体反转对话顺序:只要女性原本在 user 侧,就把整段对话翻过来,保证模型要生成的回复永远出自女性之口。最终 500 条经过反转、572 条天然如此,其余为散文式或缺人名等形态。

3.2 人格只占 7.9%,是刻意压低的#

人格样本(1,555 + 170)加起来只占 7.9%。这不是抠门——语气是稠密信号,每句话都在示范风格,不靠堆量;真正怕的是人格数据占比过高,把通用对话能力挤掉,模型变成”只会撒娇,别的都不会”。

剩下 92% 的通用数据 system 为空串,是压舱石,专门防”变傻”——这也是对第二章那次事故的直接回应。

3.3 system prompt:整套设计的核心开关#

人格样本统一带这样一段 system prompt:

你是一个22岁的女生,性格温柔自然,说话亲切俏皮,擅长共情和安慰人。
回复像身边的女生朋友一样,简短、口语化。

训练时两种样本混在一起喂:带 system 的是人格样本,不带的是通用样本。模型学到的不是”把自己变成一个女生”,而是——“看到这个 system 就切换成女生语气,看不到就保持正常助手”。

这就是 LCCC 失败的反面:那次训练没有任何”开关”可抓,模型只能把各项能力一起平均冲淡。推理部署时必须原样带上这段 system prompt,一个字都别改,否则人格效果大打折扣。


4. 让 LLaMA-Factory 认识这份数据#

数据做成 jsonl,每条一个 conversations 字段 + 一个 system 字段,注册文件只有一条:

{
"girl_persona_mix": {
"file_name": "girl_persona_mix.jsonl",
"formatting": "sharegpt",
"columns": { "messages": "conversations", "system": "system" }
}
}

踩过的坑值得单独说:

  • sharegpt 格式的硬规则:角色必须奇偶位严格交替(偶数 human、奇数 gpt),SFT 场景 messages 长度必须是偶数。入库前做了一次全量校验,21,717 条零违规。
  • columns 映射的键必须每条记录都存在。这个版本里每条都带 system 键(通用样本为空串),少一个 key,转换器直接 KeyError。
  • 冒烟测试:注册后随机抽 300 条走完整转换链路,全过;带 system 的比例和人格组占比吻合,说明配比没在转换环节被破坏。

数据分布也对齐了训练参数:长度 p50 为 297 字、p99 为 585 字——这直接决定了 cutoff_len 选 1024(覆盖 99.8% 的样本,再大纯属浪费显存)。


5. 训练参数:每个数字在解决什么问题#

配置走 QLoRA(4bit 量化 + LoRA),目标是在 12GB 显存的卡上把 7B 模型训动。逐组解释:

显存与精度

参数值为什么
quantization_bit47B bf16 权重约 15GB,压到 4bit 约 5.5GB,QLoRA 标准玩法
upcast_layernormtrueLayerNorm 对量化误差最敏感,留在 bf16 防止误差逐层累积(QLoRA 论文原始建议)
cutoff_len1024照着数据 p99=585 字定的,覆盖 99.8%

LoRA 结构

参数值为什么
lora_rank16学”说话风格”这种低维属性,16 足够;再大容易背样本
lora_alpha32α = 2×r 的经验缩放
lora_targetall语气体现在每一层线性变换里,只调 attention 学不全
lora_dropout0.05轻量正则,配合只跑 1 epoch

优化策略(这组是全章的教训)

参数值为什么
learning_rate5e-5LoRA 标准区间中低段。事故那次用的是 1e-4,对 instruct 模型偏冲动,这次保守一半
num_train_epochs1全场最关键:人格样本只有 1,725 条,跑第二遍必然过拟合、顺带冲掉通用能力
lr_scheduler_typecosine平滑退火
warmup_ratio0.03约 80 步热身,让适配器开局稳一点

数据与评估:template: qwen 必须和 Qwen2.5 对话格式对齐(错了整个训练白跑);验证集留 2% 盯过拟合;eval 每 200 步、存档每 500 步。


6. 整理:627MB 的断舍离#

跑通之后工作区惨不忍睹:77MB 的废弃数据集、524MB 的底料源文件、两份副本、十几个草稿脚本。收敛规则只有一条——新数据集文件夹里只留主数据集和注册集:

D:\数据集\女生语气混合数据集\
├── girl_persona_mix.jsonl # 21,717 条,25.8MB
└── dataset_info.json # 单条目注册

训练配置的 dataset_dir 同步指向新文件夹,原来的注册表(true_chinesechat)恢复成原始的 lccc + high_eq_cute 两条。共释放约 627MB。

收敛后做了完整回归:注册表从新目录 resolve 成功、转换冒烟 100/100 通过、YAML 384 个键全部解析正确。


7. 复盘:从日志里读出”哪百步最好”#

训练是从 LLaMA-Factory WebUI 启动的(数据 md5 核对过,就是收敛那份)。日志分析有一个清晰的结论——eval loss 全程单调下降,零过拟合:

检查点步数段eval_loss较上一段
checkpoint-1001–1001.9723—
checkpoint-200101–2001.9587-0.0136
checkpoint-300201–3001.9522-0.0065
checkpoint-400301–4001.9476-0.0046
checkpoint-500401–5001.9464-0.0012
checkpoint-600501–6001.9433-0.0031
checkpoint-700601–7001.9409-0.0024
checkpoint-800701–8001.9399**-0.0010

两个不同问题的答案:

  • 哪百步”效果最好”?701–800 段(checkpoint-800,eval_loss 1.9399),而且它既是历史最优也是最终存档。
  • 哪百步”学得最多”?101–200 段——训练 loss 从 2.42 骤降 0.447,真正的模式学习发生在这一小段,之后就在 1.96 附近平台震荡做精细打磨。

还有个情况:这次 run 在 803/1290 步(62%)静默停止,日志里没有任何报错(无 Traceback、无 OOM),进程是被手动终止或窗口关闭带走的。考虑到增量已收敛到 -0.001 量级,剩余 490 步收益极小,checkpoint-800 可以直接用,也可以加载它续训。

附注:这次 run 的超参是 WebUI 默认那套(rank 32/alpha 64、只调 q/k/v/o、cutoff 2048),和第 5 节那份 YAML 不完全一样——上面的指标对应 WebUI 配置。想复现”设计值”,跑 YAML 即可。


8. 踩坑清单(全部真实发生)#

  1. HuggingFace 直连被墙:换 hf-mirror.com,curl 记得 -L 跟随 302 到 CDN。
  2. generated_chat_0.4M 是 JSONL 不是 JSON 数组:按数组写的流式解析器只捞出 62,551 个对象,而字节扫描有 396,002 个 "instruction"——差 5/6。必须逐行 json.loads。解析器的假设要用文件头尾验证,别想当然。
  3. get_train_args([yaml路径]) 不加载 YAML:LLaMA-Factory 只在 args=None 且 sys.argv[1] 以 .yaml 结尾时才读配置文件;传列表会被当成普通 argv,YAML 被静默忽略,最后报一句极具误导性的 Please provide model_name_or_path。验证配置必须模拟 CLI:设 sys.argv 再调。
  4. 验证环境要用对 Python:LLaMA-Factory 相关验证一律用训练环境那个 Python(transformers 4.57.1 + torch + CUDA),受管的干净环境连 numpy 都没有。
  5. shell 里的反引号是命令替换:一次把含代码的说明文字直接写进 shell 命令,反引号内的 llamafactory-cli train ... 被真实执行了一遍(在沙箱里跑到预处理阶段失败,无文件损害)。教训:含反引号/代码的文本,先落成脚本文件再执行。
  6. Windows 控制台是 GBK:tasklist 输出用 utf-8 解会崩,要 decode('gbk')。

9. 结语#

回头看,从微信聊天记录到 29,037 条数字分身数据,再到那次”变傻”事故和 21,717 条语气数据,最有价值的产出不是任何一个模型,而是一套可复用的方法论:

  • 数据工程先于训练调参:提取、注册、清洗、校验,每一步都有明确规则和记账(丢了多少、为什么丢),训练只是最后一环。
  • 语气类微调,配方比数量重要:少量高密度人格样本(7.9%)+ 大量通用压舱石 + system prompt 开关,三者缺一不可。
  • 参数为数据服务:cutoff 照着 p99 定、epoch 照着人格样本量定、lr 照着基座类型定——每个数字都应该能回答”为什么不改成别的”。
  • 日志是唯一的事实来源:最优 checkpoint、停止原因、配置差异,全在日志里,别靠感觉。

模型接下来还有迭代空间(剩余 490 步、或者换回设计值超参重训),但数据工程这一层——提取、配方、注册、验证、收敛——已经是可以复用的资产了。


评论区

看板娘
公告
欢迎关于我的介绍

欢迎来到奇怪的博客,我是一名热爱JAVA,C++,AI等技术的偏执学家

查看详情
音乐
封面

音乐

暂未播放

0:00
0:00
暂无歌词
标签
# 技术7# 日常6# 博客1
目录
工具

隐私政策

更新日期: 2026 年 7 月 15 日
生效日期: 2026 年 7 月 15 日

适用范围#

本政策适用于 Qiguai的博客(以下简称“本站”)。本站是个人博客,用于发布和分享内容;不提供账户注册、支付、定位或广告投放服务。访问本站、发表文章评论或在留言板留言前,请阅读本政策。

信息收集与使用#

本站只在提供内容、评论和留言功能,以及维护站点安全所需的范围内处理信息。

  • 访问与统计信息:访问页面时,统计服务可能处理访问时间、页面地址、来源页、浏览器和设备相关信息,用于了解内容访问情况、排查故障和改进站点。
  • 评论信息:使用文章评论功能时,Waline 可能处理您主动提交的昵称、邮箱、站点链接和评论内容;还可能处理 IP 地址等必要信息,用于防止垃圾评论、滥用和维护服务安全。评论内容、昵称和站点链接(如填写)可能公开展示在文章下方;邮箱不会公开展示。
  • 留言信息:留言板使用 Waline /guestbook/ 频道。Waline 可能处理您主动提交的昵称、可选邮箱、站点链接、留言内容和图片,以及浏览器、操作系统、IP 地址等必要的反滥用信息。默认情况下,留言图片以内嵌数据随留言提交;如站点维护者配置了远程图片上传接口,图片会先发送至该接口并在留言中保存返回的图片地址。留言内容、昵称、图片和站点链接(如填写)可能公开展示;邮箱和 IP 地址不会在留言板公开展示。
  • AI 对话信息:使用 AI 搜索时,本站会处理您提交的问题以及最近 6 条对话历史,用于检索博客内容并生成回答。问题和对话历史会发送至 ModelScope,或在第三方接口不可用时由 Cloudflare Workers AI 处理。请勿在 AI 对话中提交密码、Token、身份证件、联系方式或其他敏感信息。

请不要在评论或留言中提交身份证件、银行卡、住址、密码或其他不必要的敏感个人信息。

第三方服务#

为实现本站功能,以下第三方会在各自服务范围内处理相关数据:

  • Umami:用于匿名化的网站访问统计和出站链接点击统计,帮助我了解本站的使用情况。
  • Waline:用于文章评论、留言板及访问量统计。服务会按照其自身规则处理您在评论或留言时提交的信息及必要的反滥用信息。
  • Cloudflare:为本站提供静态资源分发、AI Worker、Vectorize 和相关基础设施。留言板不使用项目 Worker 或 KV 存储。
  • ModelScope:为 AI 搜索提供文本向量和对话模型服务,会处理您提交的问题及发送给模型的最近对话历史。
  • Cloudflare Workers AI:在未配置第三方 AI 接口时提供文本向量和对话模型服务,并处理相同的 AI 请求数据。
  • unpkg:用于加载 Waline 的前端脚本、样式和表情资源;请求这些资源时,您的浏览器会与该服务建立连接。

第三方服务可能有独立的隐私政策和数据保存规则。请在使用相关功能前查阅其规则;本站无法控制其独立的数据处理活动。

本站主要使用浏览器本地存储(Local Storage 或 Session Storage)保存使用偏好,例如主题颜色、明暗模式、文章列表视图和音乐播放设置。留言板会在本地保存匿名资料、未发送草稿和登录状态,以便恢复输入与会话;管理员登录状态仅保存在当前会话。AI 搜索的会话标题和完整对话也会保存在当前浏览器的 Local Storage 中,最长保存 7 天;您可以在 AI 面板中使用“清空全部会话”立即删除这些数据。

本站不主动设置用于广告定向的第一方 Cookie。评论、统计或资源服务可能按照其自身规则使用 Cookie 或类似技术。您可以通过浏览器设置查看、删除或限制 Cookie 和本地存储;清除后,部分偏好或互动状态可能会恢复为默认值,评论功能也可能受到影响。

信息公开、保存与安全#

评论和留言属于公开互动内容,提交后可能被搜索引擎收录、被他人引用或在缓存中短暂保留。请谨慎决定发布内容。除非您提出删除请求、内容违反规则或法律法规另有要求,公开内容会持续保留以维持讨论上下文。

本站会采取合理措施保护数据安全,包括使用 HTTPS、输入校验、内容转义和访问频率限制。但互联网传输和第三方服务均无法保证绝对安全,请理解并自行承担公开发布信息的相应风险。

你的权利#

你可以通过 3530002633@qq.com 联系我,申请查询、更正或删除由本站直接保存的评论、留言或相关公开内容。为保护他人权益,请在请求中提供足以定位内容的信息,并说明你与该内容的关系;必要时可能需要进行合理核验。

对于由 Waline、Umami、Cloudflare 或 unpkg 独立处理的数据,你也可以直接向对应服务提供方行使相关权利。删除公开评论或留言后,第三方缓存、搜索引擎索引或他人转载的副本可能无法立即同步删除。

未成年人条款#

未满 14 周岁的未成年人应在监护人同意和指导下使用本站的评论、留言等互动功能。监护人如发现未成年人未经同意提交了个人信息,可通过上述联系方式与我联系,我会在合理范围内协助处理。

政策更新与联系#

我可能因本站功能或适用规则变化更新本政策,更新后的版本将在本站公布并标明日期。继续使用相关功能即表示你已阅读并理解更新后的政策。

如对本政策或数据处理有疑问,请联系 3530002633@qq.com。

用户协议

更新日期: 2026 年 5 月 19 日
生效日期: 2026 年 5 月 19 日

适用范围#

本协议适用于你访问 Qiguai的博客,以及使用文章评论、留言板等互动功能的行为。继续浏览本站或提交评论、留言,即表示你已阅读、理解并同意遵守本协议及本站的隐私政策。

评论及留言规则#

请在交流中保持友善、理性和尊重。你不得利用本站发布、传播或实施以下行为:

  • 发布任何违反中华人民共和国法律法规的内容。
  • 发布任何侵犯他人合法权益的内容,包括但不限于隐私、名誉、肖像、著作权、商标权和其他知识产权。
  • 恶意攻击、辱骂、骚扰、威胁、歧视其他用户或任何第三方。
  • 发布垃圾广告、恶意推广、刷屏、灌水,或与讨论主题明显无关的重复内容。
  • 利用本站进行网络诈骗、钓鱼、传播恶意软件,或发布可能危害网络和信息安全的内容。
  • 绕越或试图绕越本站的审核、限流、封禁等管理措施。
  • 冒充他人、伪造身份,或收集、公开他人的个人信息。

内容与访问管理#

你应对自己发布的评论和留言负责,并保证拥有发布该等内容所需的合法权利。论坛管理员有权在不另行通知的情况下删除违规内容、限制或封禁违规账号,或限制其继续使用本站互动功能。

如发现涉嫌违法犯罪、严重侵权或危及本站安全的内容,本站可保留相关记录,并在法律法规要求或必要时向有关部门提供协助。对管理措施有疑问时,可通过文末联系方式说明情况;本站会结合实际情况处理,但不承诺恢复已删除内容或访问权限。

知识产权与内容授权#

本站原创文章、页面设计和其他受保护内容的权利归作者或权利人所有。未经授权,请勿复制、转载、镜像或用于商业用途;法律法规允许的合理使用除外。

你发布评论或留言时,授予本站为展示、存储、备份、审核、删除和维护互动功能所必需的非独占、免费的使用许可。该许可不改变你对原创内容依法享有的权利。

免责声明#

本站内容仅用于个人记录、学习交流和一般信息参考,不构成任何专业意见、承诺或担保。你应结合自身情况独立判断,并对据此采取的行动负责。

评论、留言和外部链接中的内容由其发布者或运营者负责,不代表本站立场。本站会在合理范围内处理明显违规内容,但不保证所有内容均及时发现,也不对第三方网站的可用性、内容、安全性或隐私实践承担责任。

因网络故障、不可抗力、第三方服务异常、维护升级或超出合理控制范围的原因导致本站暂时无法访问、内容延迟或数据丢失的,本站会尽力恢复,但不承担由此产生的间接损失。

未成年人条款#

未满 14 周岁的未成年人应在监护人同意和指导下使用评论、留言等互动功能。监护人应协助未成年人理解本协议,并对其使用行为进行必要的引导。

其他条款#

我可以根据本站功能、管理需要或法律法规变化更新本协议,更新后的版本将在本站公布并标明日期。继续使用本站即视为接受更新后的协议。

本协议的订立、执行和解释适用中华人民共和国法律。因本协议或使用本站产生争议时,双方应先友好协商;协商不成的,依法向有管辖权的人民法院解决。

如对本协议或内容管理有疑问,请联系 3530002633@qq.com。