見出し画像

LlamaIndex v0.10のIndexingをやってみた

2024/02/20

こちらの公式ドキュメントを参考にインデックス作成についてあれこれ試してみました.

私が試した時のLlamaIndexの最新バージョンはv0.10.7です.


なお,私の実行環境はこちらです.

!pip install -q openai==1.12.0
!pip install -q pypdf==4.0.1
!pip install -q langchain==0.1.7
!pip install -q llama-index==0.10.5

インデックスとは


RAGのステージ

インデックスとは,Documentオブジェクトから構成されるデータ構造であり,LLMによってクエリができるように設計されています.また,クエリ戦略を補完するように設計されています.

LlamaIndexではさまざまな種類がありますが,代表的な2つを試します.


VectorStoreIndex

VectorStoreIndexは,最もよく使用されているインデックスのタイプです.ドキュメントを取得してノードに分割します.

次に,すべてのノードのテキストのベクトル埋め込みを作成して,LLMによってクエリできるようにします.

ドキュメントと取得方法やノードへの分割方法はこちらの記事を参考にしてください.


埋め込みとは

Vector embeddingsは,LLMアプリケーションの機能の中枢を担います.

単に埋め込み(embeddings)と呼ばれることも多いベクトル埋め込みは,テキストの意味を数値的に表現したものです.同様の意味を持つ2つのテキストは,実際のテキストがまったく異なっていたとしても,数学的に同様の埋め込みを持っています.

このことは,ある単語とある単語の類似度を算出することで確かめられそうです.

この関係から,ユーザがクエリ用語を指定すると,LlamaIndexが単純なキーワードの一致ではなくクエリ用語の意味に関連するテキストを検索できる意味的な検索が可能になります.

埋め込みには多くの種類があり,効率,有効性,計算コストが異なります.デフォルトではtext-embedding-ada-002 が使用されます.異なるLLMを使用する場合は異なる埋め込みを使用することもよくあります


Vector Store Index はドキュメントを埋め込む

Vector Store IndexはLLMのAPIを利用してすべてのテキストを埋め込みに変換します.そのため,インデックス作成時にAPI料金が発生します.

このテキストを埋め込みに変換する工程が「テキストを埋め込む」というときの意味になります.

テキストが多い場合,埋め込みの生成には多くの往復API呼び出しが含まれるため時間がかかります.

埋め込みを検索する場合,クエリ自体がベクトル埋め込みに変換され,VectorStoreIndexによって数学的な演算が実行されてクエリとの意味的な類似度に基づいてすべての埋め込みがランク付けされます.


上位K検索

ランク付けが完了すると,VectorStoreIndexは最も類似した埋め込みを対応するテキストのチャンクとして返します.返される埋め込みの数はkを使用されるため,その返される埋め込みの数を制御するパラメータはtop_kが良く使用されます.このような理由からこの類の検索は「top-kセマンティック検索」と呼ばれることが多いです.

top-k検索はベクトルインデックスをクエリするもっとも単純な形式です.公式ドキュメントの「クエリ」のセクションではより複雑な戦略を紹介しています.


Vector Store Index の使用

使用するには,作成したドキュメントのリストをVectore Store Indexに渡せばよいです.

from llama_index.core import VectorStoreIndex

index = VectorStoreIndex.from_documents(documents)

from_documentsのオプション引数として,show_progressをTrueにすると,インデックスの構築中に進行状況のバーを表示できるので,ドキュメントのサイズが大きい場合は利用するとよいでしょう.

試してみたコードはこちらから

Node オブジェクトのリストに対してインデックスを直接構築することもできます.

from llama_index.core import VectorStoreIndex

index = VectorStoreIndex(nodes)

任意のノードだけを使用してインデックスを作成するなんてこともできますし,大きなデータを一つずつノードに分割して,最後にまとめてインデックスにするといったこともできますね.

nodeを直接インデックスに変換する例はこちらです


テキストにインデックスが付けられると,クエリを実行できるようになります.作成したインデックスは保存することができ,インデックス作成にかかる時間とAPI料金のコストを削減することができます.


SummaryIndex

SummaryIndexは名前の通りドキュメント内のテキストの概要を生成しようとするクエリに最適なよりシンプルな形式のインデックスです.すべてのドキュメントを保存してすべてをクエリエンジンに返すだけの仕組みになっています.

VectorStoreIndexとSummaryIndexで要約力や,意味的な情報をとらえる力について比較してみました.

結構面白い結果が出たのでこちらで紹介させていただきます.

まず,使用するデータ(ドキュメント)はカローラスポーツ前期の諸元表,カローラスポーツおよびカローラツーリング後期の諸元表と簡潔なスペック比較表です.

これらをVector Store Indexでインデックス化したものと,Summary Indexでインデックス化したもので応答を生成し比較を行いました.

質問は,要約力を問う質問と意味的な理解力を問う質問を用意しました.

結果を以下の表にまとめます.

Vector Store IndexとSummary Indexの異なる力を要する質問に対する応答の比較

見ていただくとわかるように,Vector Store Indexは意味的な質問に強く,Summary Indexは要約力を問う質問に的確に回答ができていることが分かります.

左上から順番に見ていきます.
かっこいいグレードは何?という質問に対して「かっこいい」に関連するグレード特有の装備について説明されており理想的な回答が得られています.

対して,右上のSummary IndexではG"Z"グレードがおしゃれなグレードということは回答できていますが,グレード依存ではないハイブリッド車であることに言及していたり,「かっこいい」要素と関係ない安全装備について回答しています.ここから,全体的な把握力はあるものの特定のことを詳しく説明する能力は不足する傾向にありそうです.

左下の要約質問に対するVector Store Indexを用いた応答では,「カローラスポーツがどんな車か」を聞いているにもかかわらず,与えられたドキュメントについての要約を行っています.「~の表が記載されている車種です」と言われても聞きたいことと違うのは人間の感覚だと自然ですよね.

右下の要約質問に対するSummaryIndexの応答は,カローラスポーツがどんな車種であるかを具体的な装備をあげて「装備が充実した車」ですと回答できています.
ほかの車種と比較した場合のカローラスポーツの立ち位置が「装備が充実した車」といえるかは微妙ですが,与えたドキュメントから得られる情報としてはばっちりです.

このように,どのような質問をしたいかによってIndex作成のえらびかたが変わってくる可能性があります.


注意点として,今回の実験ではVector Store Indexによるインデックスを用いた応答は10秒ほどで終了したのに対し,Summary Indexでは2分ほどかかりました.

効率という面では,Vector Store Indexがかなり優れていると思われます.

またIndexについてくわしく勉強するときが来た場合は追記していく予定です.

長くなりましたが,閲覧いただきありがとうございました.

まとめ

  • インデックスとはDocumentをLLMが解釈しクエリできるようにしたデータ構造である

  • 代表的なインデックスの種類はVectorStoreIndexとSummaryIndexである

  • Vector Embeddingはテキストの意味を数値的に表現したものであり,意味的に同じテキストは同様のEmbeddingを持つ

  • Summary Indexはテキストの要約を生成する際に有用なシンプルなIndex

  • 質問内容によって最適なIndexが異なる可能性がある

次のおすすめ

次の読むべきは,インデックス保存に関するこちらの公式ドキュメントがおすすめです.

https://docs.llamaindex.ai/en/stable/understanding/storing/storing.html

この記事が気に入ったらサポートをしてみませんか?