こんにちは、CCCMKホールディングスTECH LABの三浦です。
今週のお題「急に休みになったら」。はてなブログの今週のお題ですが、私は急に休みになったら電車に乗って行ったことがない場所に行ってみたいです。特に普段乗っている電車の終点の駅には行ったことがないので、のんびり電車に揺られながら、どんな街なのか見に行ってみたいです。
さて、現在Large Language Models(LLMs)の活用方法でよく取り上げられるのがRetrieval-Augmented Generation(RAG)ではないかと思っています。自然な会話が出来るLLMsはChatGPTをはじめ様々なものがありますが、各自が保有するデータについて正確に回答させるためにはRAGのようなテクニックが必要になります。
RAGによって得られる回答の品質向上について、現在様々な研究が進められています。私も自身が関わっているプロジェクトの中でRAGを使ったシステムを構築することがあり、その精度をどうやって向上させたらよいか悩むことが多いのですが、RAG周りの手法は本当に様々で、どこから手を付けたらよいのか困っています。
今回はRAGに関するサーベイ論文や、LangChainのブログを参考にどんな手法があるのかを調べてみました。
参考にした情報
参考にさせて頂いたサーベイ論文です。
Title: Retrieval-Augmented Generation for Large Language Models: A Survey
Authors: Yunfan Gao, Yun Xiong, Xinyu Gao, Kangxiang Jia, Jinliu Pan, Yuxi Bi, Yi Dai, Jiawei Sun, Qianyu Guo, Meng Wang, Haofen Wang
Submitted: 8 Dec 2023 (v1), last revised 5 Jan 2024
arXiv: https://arxiv.org/abs/2312.10997
そしてLangChainのこちらのブログも参考にさせて頂きました。
RAGを使っていて個人的に感じている課題
最初に私自身がRAGを使っていて感じている課題について、挙げたいと思います
間違った回答が生成されることがある
質問に対し、事実と異なる回答が生成されることがあります。内容は確かに与えられたドキュメントを参照しているのですが、それを間違った内容で解釈してしまっているケースです。
間違っていないが、回答の内容が浅く不十分なことがある
与えたドキュメントに含まれているはずの情報にもかかわらずそれには触れず、参照先のURLだけが提示される場合などがあります。
回答内容の粒度が安定しないことがある
質問内容やスタイルで返ってくる回答が詳細な場合や簡潔な場合があり、回答の粒度が安定しないと感じることがあります。
考えられる要因はいくつもあると思います。与えるドキュメントが適切な形になっていない、関連する情報が上手く検索出来ていない、検索結果の文章のスタイルなどが質問によって変わってしまう、などです。
RAGを改善するアプローチ
RAGを改善するアプローチとして、Fine-Tuningを必要とするもの、必要としないものに分類してまとめていこうと思います。
Fine-Tuningを必要とするもの
RAGにおいてFine-Tuningの対象は埋め込み表現を生成するEmbedding Modelと回答を生成するLLMs(Generator)が挙げられます。また、別のAdapterモジュールを追加し、そのモジュールを学習させる方法もあります。Fine-Tuningを必要としないもの
RAGではユーザーの質問文をクエリとして関連情報を検索するのが基本ですが、ユーザーの質問がクエリとして不適切な場合もあります。より望ましい検索が得られるように質問文を変換するテクニックが挙げられます。 さらに検索された結果について、関連度合いが高い順に並べ替えたり、重複を除外してLLMsに渡す方が良い回答が得られるそうです。このように検索された結果を加工するテクニックも考えられます。 また、参照させたドキュメントをDBに格納する際(Indexing)、細かく分割するChunk処理のサイズなども適切に選択する必要があります。さらにKnowledge Graphのような形でデータを格納する方法をあります。
Fine-Tuningだけでなく、LLMsそのものをRAGを適用するドメインに特化したデータで事前学習させる方法も考えられます。論文でもこの方法に触れられており、多大なコストが必要なものの、成功した場合は高い精度を持ちながらGPTなどの標準モデルを使用するよりも効率的な処理が実現できます。
Fine-Tuningを必要とするもの
Fine-Tuningの対象としてEmbedding Model(Retriever)とLLMs(Generator)が挙げられます。
Embedding ModelのFine-Tuning
論文ではEmbedding ModelをFine-TuningすることでRetrieverの性能向上につながり、結果質問に対するより潜在的に意味が近い情報が検索できる点がメリットとして挙げられています。
具体的なテクニックとして、たとえば検索結果に対しLLMsがその内容をどれだけ好むのかを評価したスコアを用いて学習させる方法などがあります。
論文では、AAR, REPLUG, UPRISEといった手法が触れられていました。
また、Embedding Modelには修正を加えず、Adapterモジュールを導入する方法もあります。OpenAIではEmbedding ModelをAPIとして提供していますが、それらのEmbedding Modelに対しても低コストで導入できる方法です。AdapterはRetrieverによって検索された結果を要約したり、よりGeneratorにとって望ましい形式に変換する用途で使用されるようです。
論文で触れられている手法はPRCA, RECOMP, PKGがあります。
GeneratorのFine-Tuning
GeneratorのFine-Tuningによってテキストのスタイルを自然に保ちながら検索された情報を効率的に活用し、ユーザーの質問により適した内容の回答を生成することが可能になります。Fine-Tuningの方法としては質問と検索情報を入力し、望ましいと定義された回答を出力出来るよう学習させる教師あり学習の手法があります。
論文ではSelf-Memという手法が挙げられています。
教師あり学習では入力に対して望ましい回答を1つ与えて学習させるため、特定の回答に過学習してしまう課題があります。その解決策として、Contrastive Learningを用いる方法が考えられます。論文で触れられている具体的な手法として、SURGE, SANTAが挙げられていました。
Fine-Tuningを必要としないもの
0からモデルを学習させる方法に比べ、Fine-Tuningは低コストでモデルのカスタマイズが可能ですが、それでも学習には多大なリソースが必要になります。Fine-Tuningを必要としない方法は、細かいデータ処理や最適化技術、使用するモデルに影響を受けるなどの制約がありますが、少ないコストで対応が可能である点がメリットと言えます。
論文でもいくつも方法が挙げられていますが、ここからはLangChainのブログを主に参考にしてまとめています。ここではユーザーの質問文の補正に関する方法と、検索結果の補正に関する方法について、調べてまとめました。
ユーザーの質問文の補正
主にRetrieverがより適した情報を検索出来るようにするため、ユーザーの質問文をより検索に適した文章に補正する方法です。
Query expansion
ユーザーの質問を異なる視点で書きなおした文章をLLMsに複数生成させ、それぞれの文章でRetrieverに検索をさせます。返ってきた検索結果から重複を省き統合したものを検索結果としてLLMsに与え、回答を生成させる方法です。重複を省いて統合する際には後程触れる"Re-rank"や"Clustering"といったテクニックが使われます。HyDE(Hypothetical Document Embeddings)
この方法では、まずユーザーの質問に外部データを用いずにLLMs自身に仮の回答を生成させます。そしてRetrieverにはこの仮の回答文を与えて関連情報を検索させます。この仮の回答文は正しい内容とは限りませんが、より検索に適した情報が含まれていることを想定した方法と考えられます。Step back prompting
ユーザーの質問をより広い視野(Step back)で捉えた文章に変換してRetrieverに渡す方法です。「たとえば○○の誕生日を教えて」という質問に対し、「○○のこれまでの人生を教えて」といったように書き換えます。Rewrite-Retrieve-Read ユーザーの質問を検索に適した文章に書き換える方法です。例えばユーザーの質問に対し、「この質問をWeb検索に適した文章に書きなおして」といったプロンプトをLLMsに与え、書き換えてRetrieverに渡します。
検索結果の補正
Retrieverが出力した検索結果を、続くGeneratorによる回答生成に適した形に補正する方法です。
Re-rank Retrieverによる複数の検索結果に対し、Reciprocal Rank Fusionという処理で重要度の順位付けを行い、順位の高い順に並べ替える方法です。先ほど記述した"Query expansion"など、複数のクエリやデータに対して検索を行い、最後にそれらを統合するようなシーンで使うことが出来ます。
Classification 検索された結果それぞれを分類し、タグ付けをします。そしてそのタグに基づいて適切な検索結果を選択し、回答を生成するという方法です。
Clustering 複数の検索処理から取得した検索結果に対し、重複したものを省く方法です。検索結果のテキストを埋め込み表現化し、クラスタリングを行います。生成されたクラスタからテキストをサンプリングすることで、似たような結果を除外しつつ、幅広い内容の検索結果を得ることが出来ます。
また、検索処理自体にも改善方法があります。これは使用するVectorDBがその機能を提供していることもあります。
- max-marginal-relevance search(MMR) クエリに関連しているかどうかに加え、結果の多様性も加味して検索する方法です。
まとめ
ということで、今回Retrieval-Augmented Generation(RAG)に関する手法について調べてまとめてみました。RAGの分野は思っていた以上に様々な研究が進んでおり、一筋縄ではいかないな、と感じました。今回はあまり調べられなかったのですが、データの持ち方としてグラフ構造を使う(Knowledge Graph)方法もあり、こちらも試してみたいと思います。