-
Notifications
You must be signed in to change notification settings - Fork 0
DNET_LlamaIndex
-
RAGのIndexing、Searchingインフラを実装するライブラリ。
-
テキストをある単位でChunk分割してIndexing、コレらを永続化する。
-
プロンプトによりChunk(RAWデータ、NoSQL)をSearchingし、LLMと接続するためのI/Fを提供
-
インデックスには様々なタイプがあり、必ずしも、チャンク分割、Indexing、Searchingを前提としない。
-
以下のような処理も追加されつつある模様。
テキストデータを読み込む
テキストデータからインデックスを作成する。
テキストデータとインデックスを永続化する。
インデックスを使用してテキストデータを検索する。
検索のリクエストレスポンスを客観的に評価。
各ステージを処理する基本的なライブラリ
各ステージを処理するライブラリ
-
データ取得:LlamaHubに様々なデータコネクタが提供されている。
-
ベクトル化、ストア
- NoSQLデータベース:MongoDBやElasticsearchなどのNoSQLデータベースを使用してデータを保存および検索できる。
- クラウドストレージ: AWS S3やCloudflare R2などのクラウドストレージサービスを利用してデータを保存できる。
- Vectorストア: DeepLakeやFAISSなどを使用して、効率的なベクトル化、ベクトル検索を実現する。
斯々然々(OSSのLLMの該当節を参照)で公式を読む事をオススメする。
データの取得
-
生のテキストデータだけでなく、
- ファイル (PDF、ePub、Word、PowerPoint、Audioなど) や
- Webサービス (Notion、Slack、Wikipediaなど) を
データソースとして利用できる。
-
Reader
- SimpleDirectoryReaderと言う汎用的なライブラリを利用できる他、
- Readerを使用する代わりに、ドキュメントを直接使用することもできる。
- また、数百のデータ コネクタをLlamaHubレジストリをダウンロードして使用できる。
- LlamaCloudのコネクタは、LlamaIndex純正IaaSストレージということだろう。
- ストレージによっては、インデックス化処理がオフロードされているものもあり、その場合、Indexingのプロセスは不要になる。
インデックスの作成
-
テキストデータをチャンクに分割し、チャンクからインデックスを作成する。
-
さまざまなインデックス化の方法がある(キーワード、ベクトル、グラフ)。
-
インデックス化の結果、チャンクに対応して実際取得されるデータはノードと呼ばれる。
-
クエリでインデックスを検索し、対応するノードを取得する。
-
node_parser
- API的には、Indexingと同じタイミングで実行されるが、
- 概念的には、Loading、Readerの後に実行されるもの。
- SplitterでChunkに分割する(APIはNodeを返す)。
- Splitterのインスタンスがnode_parserらしい。
- node_parserの単独実行も可能で、show_progressと言ったオプションもある。
- パイプライン(IngestionPipeline)に組み込んで、複雑なパースを実装することもできる。
- IngestionPipeline()には、Splitter、Extractor、Embeddingなどを指定できる模様。
-
基本的には、キーワード、ベクトル、グラフなどの検索を使用する。
-
ベクトル:VectorStoreIndex
-
グラフ:Graph RAG(LLMのRAGの該当節を参照)
- KnowledgeGraphIndex:RDF、トリプレット
- PropertyGraphIndex:プロパティグラフ
-
その他の検索
-
その他
-
-
参考:https://docs.llamaindex.ai/en/stable/module_guides/indexing/index_guide/
データのストア
-
Vector Store、Document Store、Index Storeなどのストアにデータを保存。
- Vector Store
- Document Store
- Index Store
-
Document Store、Vector Store、Index Storeに、Storage Contextを設定する。
- Document Store:既出の、Loadingの所で、Document Storeから読み出している。
- Indexingで、Vector Store と Index Storeに書き出し(永続化し)ている。
- DBにストア機能とサーチ機能が実装されているような場合、
- Vector Store、Index Storeには同じDBのStorage Contextを設定する。
- 一部のIndex機能では、NoSQL的ストアを使用しないと使用できないSearchオプションがある。
| 区分 | インデックス | 特性 | 適合する NoSQL |
|---|---|---|---|
| ベクトル | VectorStoreIndex | ベクトルデータ管理 | ANN Pinecone, Weaviate, Milvus, Qdrant, Redis |
| グラフ | KnowledgeGraphIndex、PropertyGraphIndex | グラフデータ(ノードとエッジ)管理 | Neo4j, ArangoDB, Amazon Neptune, TigerGraph, JanusGraph |
データの検索
- インデックスを使用してデータを検索
- キーワード検索:キーワードを使用し、文書ベクトルを検索し結果を得る。
- ベクトル検索:クエリもベクトルに変換し、文書ベクトルと 近似最近傍探索(ANN)
- グラフ検索:全文検索後、ノードとエッジから関連文書を検索し結果を得る。
人手に依らない、マシンによるインデックスの評価機能を持つ。
Semantic Search(LLMのRAGの該当節を参照)で説明済み。
GraphRAG(LLMのRAGの該当節を参照)で説明した処理に近いが、
-
Indexing
コチラはノードからナレッジグラフ(トリプレット)と言うGraphにする。 -
Searching
Graph検索、+オプショナルなVector検索を使用する。-
Graph検索:クエリからキーワードを抽出してナレッジグラフ(トリプレット)を検索
-
Vector検索:ノードを直接検索しているもよう
- keyword: keywordで検索
- embedding: embeddingで検索
- hybrid: keywordとembeddingのハイブリッドで検索
-
プロンプトとノード(トリプレット(+オプショナルなチャンク))から回答を生成する。
-
-
特徴
- 初手のキーワード抽出に依存してる。
- ナレッジグラフの主語をプロンプトに含めそれがキーワード抽出される必要がある。
- ナレッジグラフのノードとなるキーワードが良くないと上手く辿れない事がある。
-
概要はGraphRAG(LLMのRAGの該当節を参照)で説明済み。
-
KnowledgeGraphIndexのトリプレットの表現力の課題を解決すると言われている。
- ノードと(ノード間の)関係性にラベルとプロパティを割り当てれない
- ノードをベクトル埋め込みとして表現できない。
- ベクトル検索と記号検索の両方を実行できない。
-
Indexing
- グラフ抽出に3つのオプションがある。
- SimpleLLMPathExtractorは、KnowledgeGraphIndex的トリプレットのグラフを作成
- ImplicitPathExtractorは、LlamaIndexのnode.relationshiopsを使って、グラフを作成
- SchemaLLMPathExtractorは、指定したスキーマに従い、グラフを作成
- グラフ抽出に3つのオプションがある。
-
Searching
-
複数のretrieverを組み合わせることができる。
retrieverの機能をフルに使おうと思うと、Neo4jやNebulaGraphを使う必要がある。- LLMSynonymRetriever:LLMを使って、クエリからキーワード・シノニムを生成して、ノードを検索
- VectorContextRetriever:ノードのベクトル類似度から、ノードを検索
- TextToCypherRetriever:PropertyGraphStoreが対応している場合のみ、LLMを使って、CypherというGraphDB用クエリ言語に変換して検索
- CypherTemplateRetriever:TextToCypherRetrieverと同じくCypherを使うが、Cypherの定義をテンプレートで渡す限定版的なもの
-
-
特徴
- なんとなく期待値が高すぎて使うとがっかりするらしい。
- KnowledgeGraphIndexの課題を解決と言う程でもなさそうな感じ。
- 複雑な割に効果が薄い、なにか特定のユースケースで効果的なのか?
キーワード検索
-
Indexing
- チャンクからキーワードを抽出してIndexを作成しておく。
- キーワード抽出に3つのオプションがある。
- default:LLMを使用
- simple:正規表現を使用
- rake:RAKEを使用
-
Searching
- キーワードでフィルタしたノードをリストする。
- プロンプトとノードのリストから回答を生成する。
-
特徴:キーワード検索なので
- キーワードが含まれていれば漏れることはない。
- セマンティックさが薄れることが予想される。
- キーワード≒セマンティック(固有名詞の説明を求める)のようなシーンでは活用できる。
リーフ・ノード(チャンク)から木構造のサマリ・ノードを作成する。
-
Indexing
- 親ノードは子ノードのテキストをLLMでサマリしたテキストを保持する。
- 親ノードは指定数の子ノードを持つ。
- 根ノードは複数になることがある。
-
Searching
- 根から葉へコンテキストに対応する件が含まれるノードを辿り、
- 最期に葉ノ-ドを取得する(葉の数はパラメタで指定可能)
- プロンプトと葉ノ-ド(チャンク)から回答を生成する。
-
特長
- SummaryIndexよりも処理要求数が少なくて済むので、完了までのリソース消費を節約できる。
- ルートからリーフへ正しく辿れる必要があり、かつ、リーフを元に回答する。
- 根ノードは複数になる≒いくらかコンテキストを変えてインデックス化しているものと思われる。
- しかし、サマリを使う時点である程度のコンテキストが失われる。
概要は Pandas Dataframe、TextToSQL(LLMのRAGの該当節を参照)で説明済み。
-
Indexing
- 自然言語のテキストではなく、RDBの2次元表形式データの検索機能を活用
- 自然言語のテキストではないのでチャンクはない。ノードはレコードに対応する。
-
Searching
クエリは3つの方法がある。-
NLSQLTableQueryEngine
- NLSQLTableQueryEngineはテーブルを指定しプロンプトで検索
- LLMがプロンプトの指示をSQLのクエリに変換して結果を得る。
- それを、LLMに入力して結果を説明させる。
-
SQLTableRetrieverQueryEngine
- DBのスキーマ情報を読ませ、プロンプトからテーブルを選択させる。
- 以降の部分は、NLSQLTableQueryEngineと同じ。
-
NLSQLRetriever
- Retrieverのみを行う。
- RetrieverQueryEngineでラップすれば、回答の生成が行える。
-
チャンク自体がIndexで、検索ではQA、Refineテンプレートを繰り返しサマリをする。
-
Indexing
事前にチャンクのリストを作成しておく。 -
Searching
- 順番、キーワードでフィルタ、embeddingsを使ったtop-k近似検索などでノードをリストする。
- シーケンシャルなノードのリストにQA、Refineテンプレートを繰り返しサマリをする。
- 初回は、QAテンプレートを使用し、クエリとコンテキストでサマリを得る。
- 以降は、Refineテンプレートを使用し、前回の回答とクエリとコンテキストでサマリを改善する。
-
特徴
- ノードを話題によってシーケンシャルにサマリするので、
- 件が漏れることを回避できる可能性がある。
- KeywordTableIndexと比べると、SummaryIndexは、セマンティックさを保持できる。
- 最初と最後では、最後のほうが重要になりそう。つまり、コンテキストの並び順にも影響されそう。
- 全チャンクを処理させると、LLMに対する処理要求数が大きくなり、完了までに多くのリソースを消費する。
- ノードを話題によってシーケンシャルにサマリするので、
HyDE(LLMのRAGの該当節を参照)そのものではないが似ている。
-
Indexing
- 先ずチャンクをサマリする。
- これらのサマリのEmbeddingを作成する。
- 「サマリのEmbedding」と「チャンクのノード」を紐付ける。
-
Searching
-
サマリを検索して該当するノードを選択
- LLMベース:LLMが「チャンクのノード」を選択する。
- Embeddingベース:Embeddingの類似検索で紐付いたノードを選択する。
-
プロンプトとノ-ド(チャンク)から回答を生成する。
-
-
Loading、Indexing、Storing、Querying、Evaluationプロセスの設計・実装をカスタマイズする。
-
様々なpipeline
-
Ingestion Pipeline、Data Transformation Pipeline
- データの加工や変換に特化したパイプライン。
- データ取得、データ正規化、トークン化、保存
-
Index Pipeline
- データをインデックス化するための処理パイプライン。
- データソースからデータ取得、前処理、インデックス構築
-
Query Pipeline
- クエリ処理を複数のステージで行うパイプライン。
- クエリ解析、インデックス検索、フィルタリング、応答生成
-
RAG Pipeline
- 外部データを活用して生成的な応答を行うパイプライン。
- 情報検索(Retrieval)、文脈強化(Context Augmentation)、応答生成
-
Multi-Index Query Pipeline
- 複数のインデックスを統合してクエリ処理を行うパイプライン。
- クエリ分割、個別検索、結果統合、最終応答生成
-
Custom Workflow Pipelines
- ユーザーが独自の処理フローを設計可能なカスタムパイプライン。
- 特定業界向けの独自ソリューション、複雑なビジネスプロセスに対応するカスタムシステム。
-
-
Pipeline は、データ処理やインデックス構築のためのシンプルかつ直線的なフローを構築するのに適しているが、
Workflow は、より、複雑なタスクや動的な処理を管理し、条件に応じた柔軟な操作を実現するのに適している。 -
LangFlow(LangChainの該当節を参照)とか Azure の プロンプトフロー(Azure AI 資格(AI-900)の該当節を参照)とかソレ系統の機能。
-
ただし、RAGに特化した仕様で、非構造化データや外部データベースを利用した情報取得とプロンプト設計に強みがある。
-
かつ、LangFlow や Azure の プロンプトフローにあるGUIのデザイナ機能は提供されていない。
- 非構造化テキストから表形式やJSON、キー・バリュー形式などの構造化された情報を自動的に取り出す技術
- LLMは自然言語理解能力が高いため、従来のルールベース手法や単純なNLP手法よりも柔軟かつ高精度に抽出できる。
- OpenAIの最新APIでは、JSONスキーマだけでなく型情報(例:PydanticやZod)を活用するアプローチも可能。
最近では、システムによる自動化されたプロンプトエンジニアリング、プロンプトフローを
ReAct(LLMのPEの該当節を参照)的プロンプトエンジニアリングを用い更にファジー化した、エージェント・システムが注目されている。
LLMツールは、高度に抽象化されていることから内部でどのような処理がされているか通常は見えないことが多い。
| 特徴 | VectorStoreIndex | PropertyGraphIndex |
|---|---|---|
| データ構造 | ベクトル | プロパティグラフ |
| 検索方法 | ベクトル検索 | グラフクエリ言語(例:Cypher) |
| ノードの管理 | ドキュメントをノードに分割しベクトル化 | ノード(エンティティ)とエッジ(関係) |
| クエリの複雑さ | シンプルな意味的類似性検索 | 複雑なCypherクエリをサポート |
| ハイブリッド検索 | なし | ベクトル検索とグラフを用いた検索をサポート |
| 用途 | 意味的な類似性に基づく検索 | データの関係性を重視した検索 |
- 「シンプルな意味的類似性検索」だが強力と言えば強力、主要な用途にRAGが含まれる。
- 初回のEmbeddingさえ終われば、以降、Indexing、Searchingに大きなコストがかからない。
- 通常、類似度スコアの上位数件のチャンクを取得するので、KB全体からの要約はできない。
-
ベクトル検索とグラフ検索(シンボリック検索)を併用
- グラフ検索:ノード間のパスを探索し、関連するデータを検索します。
- シンボリック検索:データのシンボル(名前、属性、関係など)を使用して検索を行います。
-
ベクトル検索に比べて強力と言う触れ込みがあったが、実はそれほどではない。
-
主要な用途は、KB構築で、RAGが含まれない。RAGに応用されたイメージ。
-
大規模データには向かない。
- Indexingのグラフ作成に多くのコスト(LLMへの要求)が発生する。
- LLMにはチャンクと、チャンクから抽出したグラフ情報が追加されて渡される。
- 同様にグラフ検索(シンボリック検索)は全チャンク要約には対応しない。
-
ランク上位のチャンクしか抜かないVectorStoreIndex、PropertyGraphIndexと異なり全体要約が可能。
-
全体要約するので、Indexingは、ただのチャンクで、Searchingは、全チャンクの要約になる。
-
大規模データには向かない。
- Searchingの度に発生する全チャンク要約に多くのコスト(LLMへの要求)が発生する。
- QA、Refineテンプレートを繰り返しの中で、誤りや、欠落が発生すると全体が破綻する(評価中に実際に発生)。
-
SummaryIndexの仕組みなどを確認すれば、全体要約は、一種のプロンプトフローに過ぎない事が解る。
-
そのため、以下のような独自のプロンプトフローで実装が可能と考えられる。
-
VectorStoreIndexを使用しTOPではなく、類似度スコアの閾値を超えるチャンクを収集して要約する。
※ 実際に網羅性が今ひとつだったが、比較的、上手く機能した。類似度スコアの閾値をチューニングすると、結果は更に良くなりそうではある。 -
QA、Refineのような直列の要約ではなく並列で要約し、プロンプトに適合した要約が含まれる場合、コレを次の入力に統合する。
※ 実際に検証していないが「全チャンク要約」と「要約結果検証」が発生するため、多くのコスト(LLMへの要求)が発生する。
-
-
RAGフレームワーク LlamaIndex の概要を整理してみる
https://zenn.dev/nomhiro/articles/llama-index-abstract -
LlamaIndexを使ってローカル環境でRAGを実行する方法 - 電通総研 テックブログ
https://tech.dentsusoken.com/entry/2024/01/22/LlamaIndex%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E7%92%B0%E5%A2%83%E3%81%A7RAG%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95
LlamaIndex - LlamaIndex
https://docs.llamaindex.ai/en/stable/
https://docs.llamaindex.ai/en/stable/
- High-Level Concepts
- Installation and Setup
- How to read these docs
- Starter Examples
- Starter Tutorial (OpenAI) - LlamaIndex
https://docs.llamaindex.ai/en/stable/getting_started/starter_example/ - Starter Tutorial (Local Models) - LlamaIndex
https://docs.llamaindex.ai/en/stable/getting_started/starter_example_local/
- Starter Tutorial (OpenAI) - LlamaIndex
- Discover LlamaIndex Video Series
- Frequently Asked Questions (FAQ)
- Starter Tools
https://docs.llamaindex.ai/en/stable/understanding/
-
Using LLMs
https://docs.llamaindex.ai/en/stable/understanding/rag/ -
Building a RAG pipeline
-
Loading & Ingestion
- Loading Data (Ingestion)
https://docs.llamaindex.ai/en/stable/understanding/loading/loading/ - LlamaHub
https://docs.llamaindex.ai/en/stable/understanding/loading/llamahub/ - Loading from LlamaCloud
https://docs.llamaindex.ai/en/stable/understanding/loading/llamacloud/
- Loading Data (Ingestion)
-
Indexing & Embedding
https://docs.llamaindex.ai/en/stable/understanding/indexing/indexing/ -
Storing
https://docs.llamaindex.ai/en/stable/understanding/storing/storing/ -
Querying
https://docs.llamaindex.ai/en/stable/understanding/querying/querying/
-
-
Building an agent
https://docs.llamaindex.ai/en/stable/understanding/agent/ -
Building Workflows
https://docs.llamaindex.ai/en/stable/understanding/workflows/ -
Structured Data Extraction
-
Tracing and Debugging
-
Evaluating
https://docs.llamaindex.ai/en/stable/understanding/evaluating/evaluating/ -
Putting it all Together
https://docs.llamaindex.ai/en/stable/use_cases/
- Prompting
- Question-Answering (RAG)
- Chatbots
- Structured Data Extraction
https://docs.llamaindex.ai/en/stable/examples/
https://docs.llamaindex.ai/en/stable/module_guides/
- Models
- Prompts
- Loading
- Indexing
https://docs.llamaindex.ai/en/stable/module_guides/indexing/
-
LlamaIndex の DocumentSummaryIndex を試す
https://note.com/npaka/n/n78a1184706d7
- ① Data Loding
https://note.com/rhe/n/ndf6d42efe273 - ② Indexing
https://note.com/rhe/n/n27b4ad617226 - ③ StoringStoring
https://note.com/rhe/n/n852087f2d905 - ④ Querying
https://note.com/rhe/n/n665a9a24ae17
- その1:処理の概念や流れを理解する基礎編(v0.6.8対応)
https://dev.classmethod.jp/articles/llamaindex-tutorial-001-overview/ - その1:処理の概念や流れを理解する基礎編(v0.7.9対応)
https://dev.classmethod.jp/articles/llamaindex-tutorial-001-overview-v0-7-9/ - その2:テキスト分割のカスタマイズ
https://dev.classmethod.jp/articles/llamaindex-tutorial-002-text-splitter/ - その3:CallbackManagerで内部動作の把握やデバッグを可能にする
https://dev.classmethod.jp/articles/llamaindex-tutorial-003-callback-manager/ - その4:ListIndex(今のSummaryIndexの事らしい)で埋め込みベクトルを使用する方法
https://dev.classmethod.jp/articles/llamaindex-tutorial-004-listindex-use-embedding-vector/ - その5:TreeIndexを使ってその動作を確認してみる
https://dev.classmethod.jp/articles/llamaindex-tutorial-005-treeindex/
- LlamaIndexモジュールガイドを試してみる: Indexing
https://zenn.dev/kun432/scraps/189e19674125ce
- kun432
- LlamaIndexモジュールガイドを試してみる: Indexing > Knowledge Graph Index
https://zenn.dev/kun432/scraps/189e19674125ce#comment-4265fb2ee007b4 - LlamaIndexのProperty Graph Indexを試す
https://zenn.dev/kun432/scraps/b2a363020a79e2
- LlamaIndexモジュールガイドを試してみる: Indexing > Knowledge Graph Index
- Local-LLM+Knowledge Graph+RAG, RAG series 2/n|Pes Cafe
https://note.com/pescafe/n/n1759b5f4d41b
https://github.com/OpenTouryoProject/DxCommon/blob/master/Notebook/path/TableOfContents.ipynb
- https://github.com/OpenTouryoProject/DxCommon/blob/master/Notebook/path/LLM_LlamaIndex1.ipynb
- https://github.com/OpenTouryoProject/DxCommon/blob/master/Notebook/path/LLM_LlamaIndex2.ipynb
- https://github.com/OpenTouryoProject/DxCommon/blob/master/Notebook/path/LLM_LlamaIndex3.ipynb
- https://github.com/OpenTouryoProject/DxCommon/blob/master/Notebook/path/LLM_LlamaIndex4.ipynb
移行メモ
- 「インデックス評価」の表と本文で、VectorStoreIndex のリンクが KnowledgeGraphIndex のアンカ(
#w9b9cec0)を指していたため、 同節の VectorStoreIndex を指すよう修正した。- 「以上期以降の部分は、NLSQLTableQueryEngineと同じ。」の「以上期」は衍字のため除去した。 また「Retreiver」→「Retriever」、「NeburaGraph」→「NebulaGraph」に修正した。
- 元 Wiki で HTML 実体参照(
VectorStoreIndexなど)で書かれていた インデックス名は、PukiWiki のページ内リンク自動生成を避けるための記法と 思われるため、通常の文字列に戻した。- 同名の見出し(「Loading」「Indexing」「Storing」「Querying」「Evaluation」 「VectorStoreIndex」「PropertyGraphIndex」「SummaryIndex」)が ステージ・主要機能・Index・インデックス評価で重複し GitHub Wiki でアンカが衝突するため、括弧で文脈を補って一意にした。
- マイクロソフト系技術情報 Wiki(techinfoofmicrosofttech.osscons.jp)への URL リンクは、移行済みの Azure AI 資格(AI-900) に張り替えた。
- PukiWiki のページ内アンカ(
#xxxxxxxx)は GitHub Wiki では再現できないため、 同一ページ内のアンカは見出しから生成されるアンカに張り替え、 他ページのアンカを指すリンクは「〜(ページ名の該当節を参照)」の形に置き換えた。
Tags: 移行, LlamaIndex, RAG, インデックス, VectorStoreIndex, PropertyGraphIndex, SummaryIndex, LLM, パイプライン
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。