🔥開発動機
僕はとある普通科高校の「科学部Robotics班」の部長兼「Noa.h」というこの部活動に所属する3年生によるチームのプログラマとしてロボットサッカーの大会に出場していました。この部活動の創設者でもある元顧問の先生が今年度他校へ異動となり、他にロボットに関する技術を指導できる先生がいなくなってしまったため、技術継承をどう行うかが課題となりました。これを受けて部活動継承のためのAIバーチャルマネージャーによるチャットアプリを作成することになり、このプロジェクトにおいて僕が担当するタスクの一つとしてRAG検索システムを担当しました。
なお、プロジェクトのフロントエンドなど他の要素については同じくNoa.hのmilktearが記事にしており、本人の気が向けば今後も更新されると思いますので良ければどうぞ。
💡基礎情報
⚪︎使用モデル
ベクトル計算にはcl-nagoya/ruri-small-v2を採用しました。このモデルの採用理由としては
・比較的モデルサイズが小さく、手元の開発環境(Mac mini M2 Pro 16GB RAM)で実行可能
・日本語の検索能力が高い
といったことが挙げられます。
⚪︎ベクトル検索
ベクトル検索にはfaissを用いました。RAG検索においておそらく定番であろう高速な検索が可能な検索システムです。
🔍Discordを検索対象にした理由
今回のプロジェクトは部活動の技術継承を目的と設定していたので最初は部活動に関する技術をドキュメントにまとめてそれを参照する形を考えていました。しかしながらこの手法には
・ドキュメントを書くのが手間である
・2年間かけて培った技術を全てドキュメントに起こすことは無理がある
・新しい情報を追加するためにドキュメントを追加し続けなければならない
といった問題がありました。そこで「普段開発のやりとりに使ってるDiscordの情報を参照すれば良いのでは」と考えました。Discordは僕たちが入部して約1ヶ月後から運用を行なっており、部活動に関するすべての連絡や自宅で開発する際のやりとり、他チームを分析する際の議論などをすべて一つのdiscordサーバーで行っていたのでそれを参照することで
・ドキュメントを書く手間が省ける
・Discordでやり取りを続ける限り情報が更新され続ける
というメリットが期待できると考え、この方法を取ることにしました。
⚠️チャットアプリをRAG検索する際の問題点
ドキュメントではなくDiscordといったチャットアプリの履歴をRAG検索する際の最大の問題点として「メッセージ単体の情報量が少ない」という問題があります。例えばチャット履歴の一部として以下のようなものがあったとします。
A : UARTを正しく設定してるはずなのに通信結果が文字化けしてる
B : なんでだろ
A : 2時間格闘してる😭
C : 通信レート合ってる?
A : あ...😇
A : 私の2時間はなんだったんだろう
B : 草
これをそれぞれのメッセージごとに言語ベクトルを計算して「UARTの不具合」というクエリでRAG検索を実行した場合、最初の「UARTを正しく設定...」のメッセージは検索結果の上位になることが考えられますが、それ以降の解決策を示す直接の情報源になるはずの「通信レート合ってる?」や本当にそれが原因であったことを示す「 あ...😇」はヒットせず、代わりに他のチャンネルのUARTについてのメッセージがより上位にヒットすることが考えられます。これではDiscord内に問題解決の方法が存在するにも関わらず、それを参照して解答を生成できないという非常に勿体無い現象が起きてしまいます。このようにチャットアプリのメッセージ単体 を関連度に基づいて検索し、参照するだけでは問題解決のための十分な情報を提供できない可能性があるという問題点があります。
🗣️前後の文脈を踏まえるために
チャットアプリの会話内容は前後の文脈を踏まえて参照することで初めて情報として有用なものになると考えます。そこで僕は次の方法を取りました。
・メッセージをチャンネル、スレッドごとに分割
・その上で送信された日付ごとに分割
このように分割したメッセージのブロックに対して言語ベクトルを計算し、RAG検索を行うことで前後の文脈を踏まえた検索を実現しました。
✅最後に
今回は部活動の技術継承のためのAIバーチャルマネージャープロジェクトの一環としてDiscordのRAG検索を行いましたが、今回の手法はDiscord以外であってもチャットアプリの履歴を用いたアプリケーション作りなどでも有用かと思いますので一つの実装例として参考になれば幸いです。