对于我接触的大多数人来说,我大部分时间都只是另一个基于文本的程序。如果输入和输出如此简单,我能被模型取代吗?要做到这一点,模型不仅需要了解我的写作风格,还需要对我有很深入的了解。最好的信息来源是我的 信息,因为我每天都会使用它,它以聊天记录的形式记录了我几乎所有的想法和行动。 Telegram 方法 最直接的方法是提取我的所有消息,将它们加载到 ChatGPT 的上下文中,并指示它使用这些信息来模仿我回复新消息时的风格。但是,这种方法受到上下文窗口大小的限制,需要我预处理消息以提取关键点。由于我想避免这种麻烦,也许可以使用检索增强生成 (RAG) 在需要时提取必要的信息。但是根据我的经验,从聊天会话等不同数据中检索通常需要对检索模型进行监督微调,而我并不热衷于创建这样的数据集。因此,微调似乎是最好的选择。它之所以理想,有几个原因:它应该捕捉我的写作风格,并可能从我的所有消息中积累知识,而无需选择重要内容。 OpenAI 提供了 ,但由于我将使用我的私人消息,所以我不想使用任何第三方微调服务。因此,我需要选择一个基础模型。根据 ,排名靠前的小型模型(≤13B 个参数)之一是 。它甚至优于 。现在,问题是 是否足够或者是否需要完全微调。各种比较 表明 LoRA 比完全微调差一点,但大多数时候仍然很好。然而,对于像我这样的特定任务(俄语 + 聊天),我发现了一篇 ,研究人员在其中进行了 Llama 中文指令微调,其复杂程度与我的目标相似。他们发现,在没有事先进行指令调整的基础模型上进行基于 LoRA 的调整不如完全微调有效。然而,在已经针对指令进行微调的模型上进行基于 LoRA 的调整可以产生相当的结果。就我而言,这意味着要么在基础模型上进行全面微调,要么在已经针对俄语聊天进行微调的模型上使用 LoRA。由于我找不到针对俄语聊天进行微调的模型,所以我将尝试在针对英语聊天进行微调的模型上使用 LoRA,例如经过微调的 Mistral 模型 。 微调功能 Hugging Face Open LLM 排行榜 Mistral 7B Llama 2 13B LoRA [1] [2] 论文 Dolphin 因此,计划是: 从 Dolphin 上的 LoRA 开始,英语聊天微调 Mistral 如果质量不够好,请尝试对 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 小时。为此,我使用了 ,其中 GPU 成本为每小时 0.362 美元,整个训练总计 2 美元,不包括花在实验和错误修复上的时间。 vast.ai 结果如下: 朋友 1 vs 亚历山大·斯米尔诺夫 朋友 2 vs 亚历山大·斯米尔诺夫 亚历山大·斯米尔诺夫 vs 朋友 1 亚历山大·斯米尔诺夫 vs 朋友 2 这样就好多了。它确实捕捉到了它所代表的人的风格。它还识别了特定人对之间讨论的最常见话题。例如,对于朋友 2,重点显然更多地放在工作上。然而,语法仍然不正确,它很快就失去了对话的背景。我非常有信心 LoRA 可以在英语中以合理的质量运行,并且可能不需要完全微调。但是,由于俄语不是该模型的母语,让我们尝试完全微调。 全面微调 由于需要多 GPU 训练,因此完全微调更具挑战性。流行的方法包括 或 ,其中 FSDP 本质上是 ZeRO3 。我决定采用 FSDP。 ZeRO 和 DeepSpeed [3] FSDP [4] [5] 在实施训练流程时,我参考了 和 。 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 代码 您可以在 中找到该项目的代码以及如何在您自己的 Telegram 转储中自行复制它的说明。 可以在 上访问训练日志。 我的 github repo WandB 主图由 提供 Unsplash 上的 Christian Wiediger