paint-brush
私はテレグラムのチャット履歴を使ってLLMを微調整しました。そこで学んだことは次のとおりです@furiousteabag
1,613 測定値
1,613 測定値

私はテレグラムのチャット履歴を使ってLLMを微調整しました。そこで学んだことは次のとおりです

Alex7m2024/06/13
Read on Terminal Reader

長すぎる; 読むには

私は自分の Telegram メッセージを使用して言語モデルを微調整し、自分の文章スタイルと会話パターンを再現できるかどうかを確認しました。パフォーマンスの観点から Mistral 7B モデルを選択し、LoRA (低ランク適応) と完全な微調整アプローチの両方を試しました。5 年間で合計 15,789 セッションに及ぶすべての Telegram メッセージを抽出し、最初は一般的な会話を微調整した Mistral モデルでテストしました。LoRA の場合、RTX 3090 でのトレーニングには 5.5 時間かかり、費用は 2 ドルでした。スタイルの模倣は改善されましたが、コンテキストと文法には苦労しました。8 つの A100 GPU を使用した完全な微調整により、言語パフォーマンスとコンテキスト保持は改善されましたが、まだいくつかのエラーがありました。全体として、モデルは会話スタイルと一般的なトピックをうまく捉えましたが、応答のコンテキストが欠けていることがよくありました。
featured image - 私はテレグラムのチャット履歴を使ってLLMを微調整しました。そこで学んだことは次のとおりです
Alex HackerNoon profile picture
0-item
1-item

私が交流するほとんどの人にとって、私はほとんどの場合、単なるテキストベースのプログラムです。入力と出力がそれほど単純なら、モデルで私を置き換えることはできるでしょうか? これが機能するには、モデルは私の文章スタイルを理解するだけでなく、私について多くのことを知る必要があります。そのための最適なソースは、私が毎日使用しているTelegramメッセンジャーです。そこには、チャット履歴の形で私の考えや行動に関するほぼすべての情報が含まれています。

アプローチ

最も簡単な方法は、すべてのメッセージを抽出し、ChatGPT のコンテキストにロードして、新しいメッセージに返信するときにこの情報を使用して私のスタイルを模倣するように指示することです。ただし、この方法はコンテキスト ウィンドウのサイズによって制限されるため、重要なポイントを抽出するためにメッセージを前処理する必要があります。この面倒を避けたいので、必要なときに必要な情報を取得するために、検索拡張生成 (RAG) を使用できるかもしれません。ただし、私の経験では、チャット セッションなどのさまざまなデータから取得するには、通常、検索モデルの教師付き微調整が必要であり、そのようなデータセットを作成することには乗り気ではありません。したがって、微調整が最善のオプションのようです。これはいくつかの理由で理想的です。重要なものを選択しなくても、私の文章スタイルをキャプチャし、すべてのメッセージから知識を蓄積できる可能性があります。


OpenAIは微調整機能を提供していますが、私はプライベートメッセージを使用するので、サードパーティの微調整サービスは使用したくありません。そのため、ベースモデルを選択する必要があります。Hugging Face Open LLM Leaderboardによると、上位の小型モデル(≤13Bパラメータ)の1つはMistral 7Bです。これは、 Llama 2 13Bよりも優れています。ここで問題となるのは、 LoRAで十分か、完全な微調整が必要かどうかです。さまざまな比較[1] [2]によると、LoRAは完全な微調整よりも少し劣りますが、ほとんどの場合それでも問題ないことが示唆されています。ただし、私のような特定のタスク(ロシア語+チャット)については、研究者が私の目標と複雑さの点で同様の中国語でLlama命令の微調整を行った論文を見つけました。彼らは、事前の命令チューニングなしのベースモデルでのLoRAベースのチューニングは、完全な微調整よりも効果が低いことを発見しました。しかし、すでに命令が微調整されたモデルでのLoRAベースのチューニングは、同等の結果をもたらす可能性があります。私の場合、これはベースモデルを完全に微調整するか、ロシア語でのチャット用にすでに微調整されているモデルで LoRA を実行することを意味します。ロシア語チャット用に微調整されたモデルが見つからなかったため、微調整された Mistral モデルDolphinのように、英語チャット用に微調整されたモデルで LoRA を試してみます。


したがって、計画は次のとおりです。

  1. Dolphin の上に LoRA を搭載し、英語チャットを微調整した Mistral から始める
  2. 品質が十分でない場合は、Mistralで完全な微調整を試してください。

データ準備

メールと比較した場合、Telegram などのアプリでのメッセージングのユニークな点は、会話の流れです。通常、メッセージはあなたと連絡先の間で 1 つずつ交互に送信されることはありません。代わりに、多くの場合、2、3 通のメッセージを続けて送信し、その後、相手からいくつかの返信が届きます。これらのメッセージも通常は短いです。私は、この自然な会話スタイルをデータに保存したいと考えました。


Telegram には、すべてのチャットを JSON にエクスポートする組み込み機能があります。メッセージをフィルタリングしてセッションにグループ化した後、過去 5 年間の 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|>


私のデータ コレータは、損失が誰かの応答に基づいてのみ計算されることを保証します。次に誰が話すかを予測するのは比較的簡単なので、モデルがそれを学習することに集中しないようにします。そのため、損失が計算される会話の部分は太字で強調表示されます。


損失の計算には、私の応答だけでなく他の人の応答も使用されていることに気付くかもしれません。これは意図的なものです。これにより、モデルは私としてだけでなく、私の頻繁な会話のパートナーとしてもロールプレイできるようになります。

評価計画

2 通りの方法でチャットしてモデルをテストします。まず、モデルが私のふりをして、私がさまざまな友人の視点から自分自身とチャットします。次に、モデルが私の友人のふりをして、私が自分自身としてチャットします。会話のきっかけは常に同じ 2 つのメッセージ、「hey」と「what's up?」です (ロシア語では、「прив」と「как дела?」)。モデルが演じるフレーズと人物は、生成されたフレーズと人物がハイライト表示されます。テストには、 oobabooga/text-generation-webuiを使用します。


まず最初に、一般的な会話を微調整した Mistral モデルが、私からの事前のトレーニングなしでそのタスクをどのように処理するかを調べたいと思います。


フレンド 1 vsアレクサンダー・スミルノフ


アレクサンダー・スミルノフ vsフレンド 1


まあ、まとまった文章を作れることはできる。最も目立つ問題は、会話の文脈に関する認識が欠如しており、当たり障りのないありきたりな返信になってしまうことだ。メッセージには明確なスタイルがなく、非常に基本的な感じがする。もう 1 つの問題は、モデルのロシア語が下手だということ。これは予想通りで、モデルは小さすぎて、主要言語である英語以外の言語にうまく一般化できない。さらに、モデルは過度に積極的になりがちで、ほとんどすべての文を疑問で終わらせる傾向があり、これは実際の人がメッセンジャーでコミュニケーションをとる一般的な方法ではない。


これらすべてを修正してみましょう!

ローラ

LoRA は、トレーニング パイプラインとハードウェア要件の両方の点で、労力のかからないアプローチを提供します。全体の重みの約 1% をトレーニングします。私は 1024 シーケンス長と 8 のバッチ サイズを選択しました。RTX 3090 で 20 GB の VRAM を消費したトレーニングには、3 エポックかかり、5.5 時間かかりました。これには、実験とバグ修正に費やされた時間を除いて、GPU コストが 1 時間あたり 0.362 ドルで、トレーニング全体で合計 2 ドルだった、 vast.aiを使用しました。


結果は次のとおりです。


フレンド 1 vsアレクサンダー・スミルノフ


フレンド2 vsアレクサンダー・スミルノフ


アレクサンダー・スミルノフ vsフレンド 1


アレクサンダー・スミルノフ vsフレンド2


これはずっと良くなりました。これは、応答する相手のスタイルを確実に捉えています。また、特定の 2 人の間で話し合われる最も一般的なトピックも特定しています。たとえば、友人 2 の場合、焦点は明らかに仕事にあります。ただし、文法はまだ間違っており、会話の文脈がすぐに失われます。LoRA は英語で妥当な品質で機能すると確信しており、完全な微調整は必要ないかもしれません。ただし、ロシア語はモデルの母国語ではないため、完全な微調整を試してみましょう。

完全な微調整

完全な微調整は、マルチGPUトレーニングが必要なため、より困難です。人気のある方法には、ZeROとDeepSpeed [3]またはFSDP [4]があり、FSDPは基本的にZeRO3 [5]です。私はFSDPを選択することにしました。


トレーニング パイプラインを実装する際には、 Stanford Alpaca の微調整コードAnton Bacaj の Mistral の微調整コードを参照しました。


シーケンス長が 1024、マイクロ バッチ サイズが 2 の半精度 FSDP フル シャードを使用するには、8 つの A100 80 GB GPU のそれぞれに 63 GB の VRAM が必要でした。3 エポックのトレーニングにはわずか 20 分かかりました。VM の合計コストは 1 時間あたり 8.88 ドルで、実験とバグ修正の時間は含まれず、合計 3 ドルでした。


会話:


フレンド 1 vsアレクサンダー・スミルノフ


フレンド2 vsアレクサンダー・スミルノフ


アレクサンダー・スミルノフ vsフレンド 1


アレクサンダー・スミルノフ vsフレンド2


会話はより面白く魅力的になりましたが、文脈が失われるリスクはまだあります。ロシア語のパフォーマンスは向上しましたが、エラーはまだ発生します。私のように限られたデータで特定のタスクを微調整する前に、まずロシア語のテキストの大規模なコーパスでモデルを教師なしで微調整することが有益であると思います。さらに、一般的な会話相手の名前を別のトークンとして組み込むと、品質が向上する可能性があります。


LoRA より大幅に優れているとは言えません。会話の相手を一人一人学習しようとするのではなく、1 人の人物だけに焦点を当て、自分の応答 (または他の誰かの応答) のみに基づいて損失を計算する方が効果的かもしれません。

最後に

確かに、モデルの返答のほとんどが不十分だったからではなく、会話で自然に頻繁に使用される「後で電話する」「忙しい」「OK」などの単純な返答が多かったため、結果を厳選する必要がありました。それにもかかわらず、モデルが、なりすましている人物のスタイルを模倣することに優れていることは明らかです。また、2人の間でよく話し合われるトピックも捉えています。ただし、会話のコンテキストが大幅に欠けています。完全なコンテキストがなければ、「やあ、それで?」や「週末の予定は?」などの質問に応答するのは困難です。おそらく、ユーザーがコンピューター上で行うすべての操作をキャプチャするRewindなどのシステムを利用すると効果的でしょう。

コード

このプロジェクトのコードと、自分の Telegram ダンプでそれを自分で複製する方法の説明は、私の github リポジトリにあります。トレーニング ログはWandBでアクセスできます。