当前位置: 首页 > news >正文

从QQ聊天记录到AI训练数据:高效格式转换实战指南

1. 为什么需要将QQ聊天记录转为AI训练数据

最近两年AI对话模型火得一塌糊涂,很多开发者都想训练自己的个性化AI助手。但最大的难题就是找不到合适的训练数据——总不能直接用网上公开的语料库吧?那训练出来的模型完全没有个人特色。

其实我们每天都在生产大量自然对话数据,比如微信、QQ聊天记录。特别是QQ,它的消息管理器可以直接导出历史聊天记录为txt文件。这些真实对话包含了我们最自然的语言习惯、用词偏好和表达方式,简直是训练个性化AI的绝佳原料。

不过直接使用这些原始数据会遇到几个问题:

  • 格式混乱:包含时间戳、昵称、系统消息等干扰信息
  • 无效内容:图片、表情、撤回消息等需要过滤
  • 隐私风险:可能暴露真实姓名、联系方式等敏感信息
  • 结构不符:AI训练需要特定的jsonl格式,包含明确的角色区分

我去年帮朋友训练一个模仿他说话风格的AI时,就花了整整两周时间手工处理聊天记录。后来痛定思痛,开发了一套自动化转换工具,现在只需要3分钟就能完成原来手动2天的工作量。

2. 准备工作:获取原始聊天记录

2.1 使用QQ消息管理器导出数据

首先确保你使用的是Windows版QQ(Mac版导出格式不太一样)。操作步骤很简单:

  1. 打开QQ主面板,点击底部"消息管理器"图标(长得像个时钟)
  2. 在左侧联系人列表中找到目标对话
  3. 右键点击 → "导出消息记录"
  4. 选择"文本文件(*.txt)"格式保存

建议为每个重要联系人都单独导出一次,存放在不同文件夹中。比如:

my_chats/ ├── mom/ │ └── chat_mom.txt ├── best_friend/ │ └── chat_friend.txt └── work_group/ └── chat_work.txt

2.2 原始数据格式解析

导出的txt文件结构大致如下:

消息对象:张三 2023-05-20 10:00:00 老李 周末打球去吗? 2023-05-20 10:02:00 我 好啊,老地方? 2023-05-20 10:02:30 老李 [图片] 2023-05-20 10:03:00 老李 就这个球场

关键特征:

  • 前8行是元数据(可以忽略)
  • 每条消息以时间戳+昵称开头
  • 空行分隔不同消息块
  • 图片/表情会显示为[图片][表情]
  • 系统消息如"撤回了一条消息"也会被记录

3. 数据清洗与转换核心逻辑

3.1 过滤无效内容

不是所有消息都有训练价值,我们需要过滤掉:

invalid_set = { "[自动回复]", "撤回了一条消息", "对方已成功接收了你发送的离线文件", "[戳一戳]", "[图片]", "[表情]" } def is_valid_msg(msg): # 检查是否是纯图片/表情 if re.sub(r'\[图片\]|\[表情\]', '', msg).strip() == '': return False # 检查是否包含无效关键词 return not any(word in msg for word in invalid_set)

3.2 角色识别与区分

AI训练需要明确区分对话双方。在QQ数据中:

  • "我"发送的消息 → 对应AI助手的输出
  • 对方发送的消息 → 对应用户的输入

但有个坑:QQ记录的昵称可能是备注名或QQ昵称。我的解决方案是让用户自己确认哪些昵称属于"我":

# 从所有消息中提取出现的昵称 nicknames = set() for msg in messages: if msg.sender not in contacts: nicknames.add(msg.sender) # 用户手动过滤非本人昵称 my_names = {"小明", "明明"} # 用户自己确认

3.3 话题分割策略

连续对话应该保持话题连贯性。我通过两个指标自动分割话题:

  1. 时间间隔 >6小时
  2. 对话轮次 >10轮

实现代码:

def should_split(last_msg, current_msg): time_gap = current_msg.time - last_msg.time return time_gap.total_seconds() > 6*3600

4. 完整转换流程实现

4.1 核心数据结构

使用namedtuple来组织消息数据:

from collections import namedtuple from datetime import datetime Msg = namedtuple('Msg', ['time', 'role', 'content']) # 示例 msg = Msg( time=datetime(2023,5,20,10,0,0), role="user", content="你好啊" )

4.2 转换主流程

def convert_to_jsonl(input_txt, output_jsonl): with open(input_txt, 'r', encoding='utf-8') as f_in, \ open(output_jsonl, 'w', encoding='utf-8') as f_out: buffer = [] last_role = None for line in f_in: if is_msg_start(line): # 检测消息开头 time, role, content = parse_msg(line) if not is_valid(content): continue if role != last_role and buffer: write_buffer(buffer, f_out) buffer = [] buffer.append((role, content)) last_role = role if buffer: # 写入剩余内容 write_buffer(buffer, f_out) def write_buffer(buffer, file): # 确保是user和assistant交替 for i in range(0, len(buffer)-1, 2): user_msg = buffer[i] bot_msg = buffer[i+1] if user_msg[0] != "user": user_msg, bot_msg = bot_msg, user_msg json.dump({ "conversations": [ {"role": "user", "content": user_msg[1]}, {"role": "assistant", "content": bot_msg[1]} ] }, file, ensure_ascii=False) file.write("\n")

4.3 隐私保护处理

在写入最终文件前,建议做敏感信息替换:

def sanitize_content(content): # 替换电话号码 content = re.sub(r'1[3-9]\d{9}', '<PHONE>', content) # 替换地址 content = re.sub(r'[省市县区].+?(路|街|号)', '<ADDRESS>', content) return content

5. 进阶优化技巧

5.1 处理连续多行消息

有些人习惯分段发消息,可以适当合并:

def merge_multi_line(msgs): merged = [] temp_msg = None for msg in msgs: if temp_msg and msg.role == temp_msg.role: # 相同发送者,合并内容 temp_msg = temp_msg._replace( content=temp_msg.content + " " + msg.content ) else: if temp_msg: merged.append(temp_msg) temp_msg = msg if temp_msg: merged.append(temp_msg) return merged

5.2 表情符号处理方案

两种可选方案:

  1. 完全删除:content = re.sub(r'\[.*?\]', '', content)
  2. 替换为文字描述:content = re.sub(r'\[图片\]', '[图片]', content)

推荐后者,可以保留更多语义信息。

5.3 批量处理工具开发

我用PyQt5做了个图形化工具,主要功能:

  • 选择文件夹批量处理
  • 可视化确认昵称
  • 进度显示
  • 错误日志

核心代码结构:

QQConverter/ ├── main.py # 主界面 ├── converter.py # 核心转换逻辑 └── utils.py # 辅助函数

6. 最终效果验证

转换后的jsonl文件示例:

{"conversations": [{"role": "user", "content": "周末去哪玩?"}, {"role": "assistant", "content": "去爬山怎么样?"}]} {"conversations": [{"role": "user", "content": "几点集合?"}, {"role": "assistant", "content": "早上8点地铁站见"}]}

适合直接用于主流AI框架训练:

from transformers import Trainer trainer = Trainer( model=model, train_dataset=load_dataset("json", data_files="converted.jsonl") ) trainer.train()

我在实际项目中用这种方法处理了超过10万条聊天记录,训练出的AI助手能很好地模仿个人语言风格。有个朋友甚至说他分不清哪个是真人回复,哪个是AI生成的。

http://www.jsqmd.com/news/535078/

相关文章:

  • 2026年AI Agent崛起:从知识库到智慧助手,收藏这份程序员必看指南!
  • 大模型时代,AI产品经理的转型指南:从入门到精通,你需要知道这些!
  • 探秘2026景区滑梯分析:趣味组合滑梯等你来玩,公园游乐设备/社区滑梯/幼儿园健身器材/非标游乐设施,滑梯品牌选哪家 - 品牌推荐师
  • 算法艺术创作与Canvas视觉开发:技术驱动的创意编程实践指南
  • ZYNQ实战:用FPGA驱动LCD显示RTC时钟的避坑指南
  • HunyuanVideo-Foley在Node.js环境下的集成:构建音效生成REST API服务
  • AGI 正在被商业大佬玩坏:当技术概念沦为营销幌子
  • 让工具秒变中文:axure-cn本地化方案全攻略
  • OpenClaw密码管理:Qwen3-32B加密存储与自动填充方案
  • Phi-4-Reasoning-VisionAI应用:金融财报截图解析+数字异常推理预警
  • nanomsg深度解析:高性能消息传递库的架构设计与实战应用
  • 避开这5个坑!用Ansys Workbench做冲压仿真时90%人会犯的错误
  • MATLAB图像处理新手避坑指南:fliplr、flipud、rot90和repmat的实战详解与常见错误
  • 从71.5%到87.5%:我是如何用PyTorch+ResNeXt101优化GTZAN音乐分类精度的(附完整代码)
  • 用Three.js模拟智慧园区交通流:手把手实现车辆自动寻路与泊车逻辑
  • Ubuntu 20.04忘记密码?3分钟搞定root和用户密码重置(附GRUB菜单截图)
  • League Akari:革新性游戏体验的智能辅助解决方案
  • LVGL8.1消息框避坑指南:ESP32上容易忽略的3个内存泄漏问题
  • 国内开发者必备:Nexus3最新版下载与安装全攻略(附百度网盘链接)
  • SkyWalking 9.7.0与Elasticsearch 8.17.4集成避坑指南:证书转换那些事儿
  • 如何用ESP32 NimBLE快速构建低功耗蓝牙HID设备:完整实战指南
  • 如何快速配置暗黑2智能刷宝脚本:3步实现游戏自动化
  • 论文降重太难?AI 工具实测对比,帮你快速通关
  • RWKV7-1.5B-G1A模型效果深度评测:多场景文本生成作品集
  • 4步掌握AI语音创作:零代码播客制作全流程指南
  • Mermaid完全指南:从文本到可视化的高效图表解决方案
  • CogVideoX-2b业务整合:嵌入现有工作流的API调用实践
  • HunyuanVideo-Foley开发者手册:自定义模型路径、输出格式与采样率设置
  • TPU 架构与 Pallas Kernel 编程入门:从内存层次结构到 FlashAttention
  • Linux软RAID实战:mdadm构建RAID5及故障磁盘热替换指南