paint-brush
我利用 Telegram 聊天记录对 LLM 进行了微调。以下是我学到的东西经过@furiousteabag
1,351 讀數
1,351 讀數

我利用 Telegram 聊天记录对 LLM 进行了微调。以下是我学到的东西

经过 Alex7m2024/06/13
Read on Terminal Reader

太長; 讀書

我使用我的 Telegram 消息微调了一个语言模型,看看它是否可以复制我的写作风格和对话模式。我选择了 Mistral 7B 模型,因为它的性能很好,并尝试了 LoRA(低秩自适应)和完全微调方法。我提取了所有 Telegram 消息,五年内总共 15,789 个会话,并首先使用通用对话微调的 Mistral 模型进行测试。对于 LoRA,在 RTX 3090 上进行训练需要 5.5 小时,费用为 2 美元,改进了风格模仿,但在上下文和语法方面遇到了困难。使用八个 A100 GPU 进行完全微调,提高了语言性能和上下文保留,但仍然有一些错误。总体而言,虽然该模型很好地捕捉了对话风格和常见主题,但它在响应中往往缺乏上下文。
featured image - 我利用 Telegram 聊天记录对 LLM 进行了微调。以下是我学到的东西
Alex HackerNoon profile picture
0-item
1-item

对于我接触的大多数人来说,我大部分时间都只是另一个基于文本的程序。如果输入和输出如此简单,我能被模型取代吗?要做到这一点,模型不仅需要了解我的写作风格,还需要对我有很深入的了解。最好的信息来源是我的Telegram信息,因为我每天都会使用它,它以聊天记录的形式记录了我几乎所有的想法和行动。

方法

最直接的方法是提取我的所有消息,将它们加载到 ChatGPT 的上下文中,并指示它使用这些信息来模仿我回复新消息时的风格。但是,这种方法受到上下文窗口大小的限制,需要我预处理消息以提取关键点。由于我想避免这种麻烦,也许可以使用检索增强生成 (RAG) 在需要时提取必要的信息。但是根据我的经验,从聊天会话等不同数据中检索通常需要对检索模型进行监督微调,而我并不热衷于创建这样的数据集。因此,微调似乎是最好的选择。它之所以理想,有几个原因:它应该捕捉我的写作风格,并可能从我的所有消息中积累知识,而无需选择重要内容。


OpenAI 提供了微调功能,但由于我将使用我的私人消息,所以我不想使用任何第三方微调服务。因此,我需要选择一个基础模型。根据Hugging Face Open LLM 排行榜,排名靠前的小型模型(≤13B 个参数)之一是Mistral 7B 。它甚至优于Llama 2 13B 。现在,问题是LoRA是否足够或者是否需要完全微调。各种比较[1] [2]表明 LoRA 比完全微调差一点,但大多数时候仍然很好。然而,对于像我这样的特定任务(俄语 + 聊天),我发现了一篇论文,研究人员在其中进行了 Llama 中文指令微调,其复杂程度与我的目标相似。他们发现,在没有事先进行指令调整的基础模型上进行基于 LoRA 的调整不如完全微调有效。然而,在已经针对指令进行微调的模型上进行基于 LoRA 的调整可以产生相当的结果。就我而言,这意味着要么在基础模型上进行全面微调,要么在已经针对俄语聊天进行微调的模型上使用 LoRA。由于我找不到针对俄语聊天进行微调的模型,所以我将尝试在针对英语聊天进行微调的模型上使用 LoRA,例如经过微调的 Mistral 模型Dolphin


因此,计划是:

  1. 从 Dolphin 上的 LoRA 开始,英语聊天微调 Mistral
  2. 如果质量不够好,请尝试对 Mistral 进行全面微调

数据准备

与电子邮件相比,Telegram 等应用中的消息传递的一个独特之处是对话流。消息通常不会在您和您的联系人之间逐条交替发送。相反,您经常会发现自己连续发送几条消息,然后对方会做出几次回复。这些消息通常也很短。我希望在我的数据中保留这种自然的对话风格。


Telegram 提供了一项内置功能,可以将所有聊天导出为 JSON。经过一些筛选并将消息分组到会话中后,我整理了过去五年使用 Telegram 的数据。结果显示,466 个聊天中有 15,789 个会话,平均会话长度为 8.51 条消息。为了构造数据,我选择了ChatML提示格式。以下是示例会话(从俄语翻译而来):


<|im_start|>约翰·史密斯
>>> 该死,无法绕过 135 的时间限制

>>> 尝试以最优方式完成所有工作,但没有成功<|im_end|>

<|im_start|>亚历山大·斯米尔诺夫
>>> 是的,一样

>>> 你还坚持同样的想法吗?<|im_end|>

<|im_start|>约翰·史密斯
>>> 不知道,我想我们的想法一致

>>>正如你所说

>>> 尝试使用反转的字符串并尝试在那里找到一些东西

>>> 看起来很糟糕,因为 z 函数毁了一切……………………<|im_end|>

<|im_start|>亚历山大·斯米尔诺夫
>>> 不明白 z 是怎么进入这个的<|im_end|>

<|im_start|>约翰·史密斯
>>> 不管怎样,我好像都在迭代地做所有事情,但是是的,必须反转一些字符串才能构建 z 函数

>>>这只是一个随机解决方案

>>> 来自讨论<|im_end|>

<|im_start|>亚历山大·斯米尔诺夫
>>> 明白了<|im_end|>


我的数据整理器确保损失仅根据某人的回答来计算。预测谁将接下来发言相对简单,我们不希望模型专注于学习这一点。因此,对话中计算损失的部分以粗体突出显示。


您可能会注意到,不仅我的回答,而且其他人的回答也用于计算损失。这是故意的。通过这样做,模型不仅可以扮演我的角色,还可以扮演我经常交谈的伙伴的角色!

评估计划

我将通过两种聊天方式测试模型。首先,模型将假装是我,我将从不同朋友的角度与自己聊天。然后,我将以自己身份聊天,而模型则充当我的朋友。我的对话开场白将始终是相同的两条消息:“嘿”和“怎么了?”(俄语中为“прив”和“как дела?”)。生成的短语和模型扮演的人将突出显示。为了进行测试,我将使用oobabooga/text-generation-webui


首先,我想探索通用对话微调的 Mistral 模型如何在我未进行任何事先训练的情况下处理该任务。


朋友 1 vs亚历山大·斯米尔诺夫


亚历山大·斯米尔诺夫 vs朋友 1


好吧,它能够形成连贯的句子。最明显的问题是它缺乏对对话背景的认识,这导致回复平淡无奇。这些信息缺乏独特的风格,感觉很基础。另一个问题是该模型的俄语很差。这是意料之中的,因为该模型太小,无法很好地推广到除其主要语言英语以外的其他语言。此外,该模型往往过于主动,几乎每句话都以问题结尾,而这并不是真人在即时通讯中通常交流的方式


让我们尝试解决所有这些问题!

洛拉

LoRA 在训练流程和硬件要求方面都提供了一种省力的方法。它训练了大约 1% 的总权重。我选择了 1024 序列长度和 8 的批处理大小。训练在 RTX 3090 上消耗了 20GB 的 VRAM,耗时 3 个 epoch,持续了 5.5 小时。为此,我使用了vast.ai ,其中 GPU 成本为每小时 0.362 美元,整个训练总计 2 美元,不包括花在实验和错误修复上的时间。


结果如下:


朋友 1 vs亚历山大·斯米尔诺夫


朋友 2 vs亚历山大·斯米尔诺夫


亚历山大·斯米尔诺夫 vs朋友 1


亚历山大·斯米尔诺夫 vs朋友 2


这样就好多了。它确实捕捉到了它所代表的人的风格。它还识别了特定人对之间讨论的最常见话题。例如,对于朋友 2,重点显然更多地放在工作上。然而,语法仍然不正确,它很快就失去了对话的背景。我非常有信心 LoRA 可以在英语中以合理的质量运行,并且可能不需要完全微调。但是,由于俄语不是该模型的母语,让我们尝试完全微调。

全面微调

由于需要多 GPU 训练,因此完全微调更具挑战性。流行的方法包括ZeRO 和 DeepSpeed [3]FSDP [4] ,其中 FSDP 本质上是 ZeRO3 [5] 。我决定采用 FSDP。


在实施训练流程时,我参考了Stanford Alpaca 微调代码Anton Bacaj 的 Mistral 微调代码


使用序列长度为 1024 且微批次大小为 2 的半精度 FSDP 全分片,需要八个 A100 80 GB GPU 上每个 GPU 配备 63GB VRAM。训练持续三个时期,仅需 20 分钟。虚拟机的总成本为每小时 8.88 美元,最终为 3 美元,不包括实验和错误修复的时间。


对话:


朋友 1 vs亚历山大·斯米尔诺夫


朋友 2 vs亚历山大·斯米尔诺夫


亚历山大·斯米尔诺夫 vs朋友 1


亚历山大·斯米尔诺夫 vs朋友 2


对话变得更有趣、更吸引人了,尽管仍然有丢失上下文的风险。俄语能力有所提高,但错误仍然会出现。我认为,在针对数据有限的特定任务(如我的任务)进行微调之前,首先在大量俄语文本上对模型进行无监督微调会很有帮助。此外,将常见对话伙伴的姓名作为单独的标记可能会提高质量。


我不会说它比 LoRA 好很多。专注于一个人并仅根据我的回答(或其他人的反应)计算损失可能更有效,而不是试图了解每一个对话伙伴。

结束语

当然,我必须对结果进行精挑细选,这并不是因为模型的大多数回复都不够充分,而是因为许多回复都是简单的回复,例如“我稍后会给你打电话”、“忙”和“好的”,这些回复在对话中很常见。尽管如此,很明显该模型在模仿其扮演的人的风格方面表现出色。它还捕捉了两个人之间经常讨论的话题。然而,它严重缺乏对话中的上下文。如果没有完整的上下文,回答“你好吗?”或“你周末有什么计划”等问题是很有挑战性的。也许使用像Rewind这样的系统可能会有所帮助,它可以捕捉用户在计算机上所做的一切。

代码

您可以在我的 github repo中找到该项目的代码以及如何在您自己的 Telegram 转储中自行复制它的说明。 可以在WandB上访问训练日志。