この記事では、LlamaIndexでベクトル検索を行うVectorStoreについて解説しています。
ChromaDB、Faiss、Qdrantといったオープンソースのベクトルストアの違いや使用方法について詳しく説明しています。
ざっくり言うと
- LlamaIndexのVectorStoreとは
- ChromaDB、Faiss、Qdrantの違いが分かる
- ベクトルストアをローカルで構築する方法を解説
LlamaIndexのVectorStoreとは
LlamaIndexのベクトルストアは、RAGにおいてベクトル検索を活用した効率的な類似性検索を提供します。
これにより、膨大なデータの中から関連性の高い情報を素早く見つけ出すことが可能です。
LlamaIndexは、以下のようなオープンソースのベクトルストアに対応しています。
- ChromaDB
- Faiss
- Qdrant
ChromaDB・Faiss・Qdrantの違い
ChromaDB
ChromaDBは、RAG 向けのオープンソース埋め込みデータベースであり、LLMアプリケーションの開発を簡素化するために設計されています。特に音声関連のユースケースで人気があります。
メリット
- 柔軟性とスケーラビリティが強みで、クラウド環境やオンプレミスでのデプロイが可能です。
- 複数のデータ形式やタイプに対応でき、幅広いアプリケーションに適しています。
- ローカルでの運用が可能で、クラウドやオンプレミスのどちらでも利用可能です。
デメリット
- 他のデータベースと比べると、特定のケースでパフォーマンスの差が生じることがある。
Faiss
FaissDBは、類似度検索やクラスタリングに特化したオープンソースのベクトル検索ライブラリです。
Facebook AI Researchによって開発され、非常に高速な検索性能が特徴です。
メリット
- 大規模なデータセットに対して高速な検索が可能で、特に高効率な類似度検索やクラスタリングが必要なタスクに適しています。
- 研究やプロダクション環境で使われることが多く、さまざまなベクトルベースのアプリケーションで利用されています。
デメリット
- セットアップやデプロイがやや複雑で、他のベクトルストアと比べて利用には技術的な知識が求められる。
- ローカルでの運用が前提となっており、クラウドでの使用に関しては他の選択肢と比較して制約がある
Qdrant
Qdrantは、スケーラブルなベクトルデータベースで、ハイブリッド検索(ベクトルとスパースデータを組み合わせた検索)をサポートしています。特に類似検索に強みがあります。
クライアントとサーバーサイドの両方で利用でき、ローカルクラウドやでの展開も可能です。
メリット
- ハイブリッド検索機能をサポートしており、複雑な検索クエリにも対応可能です。
- スケーラビリティが高く、大規模なデータセットにも対応でき、クラウドやローカルの両方で運用可能です。
- APIを通じて簡単に利用でき、モダンなベクトルデータベースの一つとして注目されています。
デメリット
- ハイブリッド検索が有効でない場合や、特定のユースケースでは他のデータベースに対してパフォーマンスが劣る場合があります。
LlamaIndex VectorStoreの実行環境
この記事で用意した実行環境は以下のとおりです。
- GPU:NVIDIA A100 80GB
- GPUメモリ(VRAM):80GB
- OS :Ubuntu 22.04
- Docker
Dockerで環境構築
Dockerを使用してLlamaIndexの環境構築をします
Dockerの使い方は以下の記事をご覧ください。
Ubuntuのコマンドラインで、Dockerfileを作成します。
mkdir llamaindex_vectorstore
cd llamaindex_vectorstore
nano Dockerfile
Dockerfileに以下の記述を貼り付けます。
# ベースイメージ(CUDA)の指定
FROM nvidia/cuda:12.1.0-cudnn8-devel-ubuntu22.04
# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y python3-pip python3-venv git nano curl
RUN curl -fsSL https://ollama.com/install.sh | sh
# 作業ディレクトリを設定
WORKDIR /app
# アプリケーションコードをコピー
COPY . /app
# Python仮想環境の作成
RUN python3 -m venv /app/.venv
# 仮想環境をアクティベートするコマンドを.bashrcに追加
RUN echo "source /app/.venv/bin/activate" >> /root/.bashrc
# JupyterLabのインストール
RUN /app/.venv/bin/pip install Jupyter jupyterlab
# LlamaIndex関連のインストール
RUN /app/.venv/bin/pip install ollama llama-index llama-index-core llama-index-llms-ollama llama-index-embeddings-huggingface llama-index-readers-web llama-index-readers-file chromadb llama-index-vector-stores-chroma llama-index-vector-stores-faiss faiss-gpu llama-index-vector-stores-qdrant qdrant_client
# コンテナの起動時にbashを実行
CMD ["/bin/bash"]
FROM nvidia/cuda:12.1.0-cudnn8-devel-ubuntu22.04
CUDA12.1のベースイメージを指定しています。
RUN apt-get update && apt-get install -y python3-pip python3-venv git nano curl
必要なパッケージをインストールしています。
RUN curl -fsSL https://ollama.com/install.sh | sh
Linux版のOllamaをインストールしています。PythonでOllamaを動かす際にもLinux版Ollamaのインストールが必要になりますのでご注意ください。
RUN /app/.venv/bin/pip install Jupyter jupyterlab
JupyterLabをインストールしています。
RUN /app/.venv/bin/pip install ollama llama-index llama-index-core llama-index-readers-file llama-index-llms-ollama llama-index-embeddings-huggingface llama-index-readers-web
LlamaIndexとOllama関連のパッケージをインストールしています。
LLMはOllamaのライブラリを使って動かしますので、PyTorchやTransformerは別途インストール不要です。
docker-compose.ymlでDockerコンテナの設定をします。
docker-compose.ymlのYAMLファイルを作成して開きます。
nano docker-compose.yml
以下のコードをコピーして、YAMLファイルに貼り付けます。
services:
llamaindex_vectorstore:
build:
context: .
dockerfile: Dockerfile
image: llamaindex_vectorstore
runtime: nvidia
container_name: llamaindex_vectorstore
ports:
- "8888:8888"
volumes:
- .:/app/llamaindex_vectorstore
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
command: >
bash -c '/usr/local/bin/ollama serve & /app/.venv/bin/jupyter lab --ip="*" --port=8888 --NotebookApp.token="" --NotebookApp.password="" --no-browser --allow-root'
bash -c ‘/usr/local/bin/ollama serve & /app/.venv/bin/jupyter lab –ip=”*” –port=8888 –NotebookApp.token=”” –NotebookApp.password=”” –no-browser –allow-root’
bash -c '/usr/local/bin/ollama serve
Ollama Serverを起動しています。PythonのOllamaを使用する際に、Ollama Serverを起動しておく必要がありますので、ご注意ください。
& /app/.venv/bin/jupyter lab --ip="*" --port=8888 --NotebookApp.token="" --NotebookApp.password="" --no-browser --allow-root'
JupyterLabを8888番ポートで起動しています。
Dockerfileからビルドしてコンテナを起動します。
docker compose up
Dockerの起動後にブラウザの検索窓に”localhost:8888″を入力すると、Jupyter Labをブラウザで表示できます。
localhost:8888
事前準備
Dockerコンテナで起動したJupyter Lab上でRAGの実装をします。
日本語LLMモデル「Llama-3-ELYZA-JP-8B-q4_k_m.gguf」をダウンロードします。
!curl -L -o Llama-3-ELYZA-JP-8B-q4_k_m.gguf "https://huggingface.co/elyza/Llama-3-ELYZA-JP-8B-GGUF/resolve/main/Llama-3-ELYZA-JP-8B-q4_k_m.gguf?download=true"
Llama-3-ELYZA-JPについては、別記事で詳しく解説しています。
LLMの実行にはOllamaを使用します。
LLMのモデルがOllama使えるようにプロンプトテンプレートを指定して、モデルを作成します。
import ollama
from llama_index.core import Settings
from llama_index.llms.ollama import Ollama
modelfile='''
FROM ./Llama-3-ELYZA-JP-8B-q4_k_m.gguf
TEMPLATE """{{ if .System }}<|start_header_id|>system<|end_header_id|>
{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>
{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>
{{ .Response }}<|eot_id|>"""
PARAMETER stop "<|start_header_id|>"
PARAMETER stop "<|end_header_id|>"
PARAMETER stop "<|eot_id|>"
PARAMETER stop "<|reserved_special_token"
'''
ollama.create(model='elyza8b', modelfile=modelfile)
Settings.llm = Ollama(model="elyza8b", request_timeout=360.0)
FROM ./Llama-3-ELYZA-JP-8B-q4_k_m.gguf
ダウンロードしたモデルのパスが入ります。
TEMPLATE “””{{ if .System }}<|start_header_id|>system<|end_header_id|>…
モデルで使用するプロンプトテンプレートが入ります。
ollama.create(model=’elyza8b’, modelfile=modelfile)
モデルとプロンプトテンプレートを使ってOllama用のモデルを作成します。model
にはOllamaで呼び出す際に使用する名前をつけられます。
Settings.llm = Ollama(model=”elyza8b”, request_timeout=360.0)
Settings.llm
は、LlamaIndexにおけるLLMをグローバルに設定しています。LlamaIndexでLLMを使用する際に、自動的にグローバルに設定したLLMが使用されます。
Ollama(model="elyza8b", request_timeout=360.0)
Ollamaのモデルを指定しています。またリクエストのタイムアウト時間を360秒に設定しています。
Ollamaの詳しい使い方は、別の記事で解説しています。
テキストをベクトル表現に変換する埋め込みモデルを読み込みます。
日本語性能が高く、無料で使える埋め込みモデル「intfloat/multilingual-e5-large」を指定しています。
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
Settings.embed_model = HuggingFaceEmbedding(model_name="intfloat/multilingual-e5-large")
Settings.embed_model
埋め込みモデルをグローバルに設定しています。LlamaIndexでインデックス作成時に埋め込みモデルが自動的に使用されます。
Wikipediaからテキストデータを抽出して、読み込みます。
Wikipediaの『宮部みゆきの小説』に関するページを指定しています。
from llama_index.readers.web import SimpleWebPageReader
documents = SimpleWebPageReader(html_to_text=True).load_data(
["https://ja.wikipedia.org/wiki/%E7%81%AB%E8%BB%8A_(%E5%B0%8F%E8%AA%AC)",
"https://ja.wikipedia.org/wiki/%E7%90%86%E7%94%B1_(%E5%B0%8F%E8%AA%AC)",
"https://ja.wikipedia.org/wiki/%E5%90%8D%E3%82%82%E3%81%AA%E3%81%8D%E6%AF%92",
"https://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%AD%E3%83%A2%E3%83%B3%E3%81%AE%E5%81%BD%E8%A8%BC"]
)
SimpleWebPageReader(html_to_text=True).load_data()
指定したWebページから取得したHTMLデータをテキスト形式で読み込みます。
読み込んだデータをチャンクに分割し、各チャンクをノードとして処理します。
ノードは効率的な検索やクエリ処理をサポートするため、メタデータや関係情報を含む単位です。
from llama_index.core.node_parser import TokenTextSplitter
splitter = TokenTextSplitter(
chunk_size=1000,
chunk_overlap=100,
separator=" ",
)
nodes = splitter.get_nodes_from_documents(documents)
nodes[10:13]
splitter = TokenTextSplitter(…
chunk_size=1000
: 1つのチャンクに含まれるトークンの最大数を1000トークンに設定しています。これにより、テキストが1000トークンずつ分割されます。chunk_overlap=100
: 隣接するチャンク間で100トークンの重複が設定されています。これにより、文脈の連続性を保つことができ、モデルがより意味を理解しやすくなります。separator=" "
: トークンを分割する際の区切り文字として、スペース(" "
)を使用しています。これは、一般的に単語の区切りを意味します。
nodes = splitter.get_nodes_from_documents(documents)
指定したdocuments
をトークン単位で分割し、それぞれをノードに変換します。ノードはテキストの一部分を保持し、後でモデルに入力するためのチャンクとなります。
確認のため、分割したノードを3つ表示しています。
[TextNode(id_='20bcf4cd-92fc-42a8-9757-f5cbd6d4777c', embedding=None, metadata={}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={<NodeRelationship.SOURCE: '1'>: RelatedNodeInfo(node_id='https://ja.wikipedia.org/wiki/%E7%81%AB%E8%BB%8A_(%E5%B0%8F%E8%AA%AC)', node_type=<ObjectType.DOCUMENT: '4'>, metadata={}, hash='956de29d6407704bc945d1ff9f843ad814ca357e032b0d19e2b86c40d6754fe9'), <NodeRelationship.PREVIOUS: '2'>: RelatedNodeInfo(node_id='2caab499-b5e6-4d7c-97fd-a758b7182667', node_type=<ObjectType.TEXT: '1'>, metadata={}, hash='b1e3b12cf2dec27dee38ac9f925d7110a4cd9213fb3584c076fd00010c3c533d'), <NodeRelationship.NEXT: '3'>: RelatedNodeInfo(node_id='46f36a51-8730-445d-9510-1ef7a5834351', node_type=<ObjectType.TEXT: '1'>, metadata={}, hash='0b109e7390b9935d93de686a7ca2c39197f64842a4b6d3cd4741e1a0002ed341')}, text='## あらすじ\n\n[[編集](/w/index.php?title=%E7%81%AB%E8%BB%8A_\\(%E5%B0%8F%E8%AA%AC\\)&action=edit§ion=2\n"節を編集: あらすじ")]\n\n刑事・本間俊介は、犯人確保時に負った傷のために休職していた。そんな彼に、亡くなった妻・千鶴子の親戚で銀行員の栗坂和也が意外な事を頼み込む。謎の失踪を遂げた和也の婚約者・関根彰子を探し出して欲しいという。\n\n和也の話によれば、クレジットカードを持っていないという彰子にカード作成を薦めたところ、審査の段階で彼女が自己破産経験者だということが判明した。事の真偽を問い詰められた彰子は、翌日には職場からも住まいからも姿を消していたとの事だった。\n\n休職中で警察手帳も使えない本間は、彰子の親戚や雑誌記者を装って捜査を開始する。最初に彰子の勤め先を訪ね、社長から彰子の履歴書を見せられた本間は、写真を見て彼女の美貌に驚く。美しいながら、夜の仕事には染まらない清楚な雰囲気が漂っていた。次に、彰子の自己破産手続きに関わった弁護士を訪ねたところ、「関根彰子」は会社勤めの傍ら水商売に手を出しており、容貌の特徴は大きな八重歯だという。勤め先での関根彰子と自己破産した関根彰子は、名前が同じながら容貌も性格も素行も一致しないのだ。\n\n本間は和也の婚約者だった「関根彰子」は、本物の関根彰子に成りすました偽者ではないのかと言う疑念がわく。\n\n調べを進める本間は、都会での1人暮らしの夢からカード破産に陥る女性や、無理なマイホーム購入で離散に陥った一家、実家の借金が原因で追い詰められ、婚家を去らざるを得なかった女性など、借金に翻弄される人生を目の当たりにする。\n\n## 登場人物\n\n[[編集](/w/index.php?title=%E7%81%AB%E8%BB%8A_\\(%E5%B0%8F%E8%AA%AC\\)&action=edit§ion=3\n"節を編集: 登場人物")]\n\n本間 俊介\n\n 42歳。捜査一課刑事。休職中\n本間 智\n\n 10歳。俊介の息子\n本間 千鶴子\n\n 俊介の妻。故人\n井坂 恒男\n\n 本間家の隣人\nカッちゃん', mimetype='text/plain', start_char_idx=11862, end_char_idx=12802, text_template='{metadata_str}\n\n{content}', metadata_template='{key}: {value}', metadata_seperator='\n'),
TextNode(id_='46f36a51-8730-445d-9510-1ef7a5834351', embedding=None, metadata={}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={<NodeRelationship.SOURCE: '1'>: RelatedNodeInfo(node_id='https://ja.wikipedia.org/wiki/%E7%81%AB%E8%BB%8A_(%E5%B0%8F%E8%AA%AC)', node_type=<ObjectType.DOCUMENT: '4'>, metadata={}, hash='956de29d6407704bc945d1ff9f843ad814ca357e032b0d19e2b86c40d6754fe9'), <NodeRelationship.PREVIOUS: '2'>: RelatedNodeInfo(node_id='20bcf4cd-92fc-42a8-9757-f5cbd6d4777c', node_type=<ObjectType.TEXT: '1'>, metadata={}, hash='a5977d98668d2593e22ab29fb494a46132835e241159732d9418462574bdd54f'), <NodeRelationship.NEXT: '3'>: RelatedNodeInfo(node_id='f96c3089-226f-4a13-a706-2a5e86b5a923', node_type=<ObjectType.TEXT: '1'>, metadata={}, hash='db5e608fed56cc45a77a1f7149021b786a8964035fcdcdf17e618e99300facd9')}, text='42歳。捜査一課刑事。休職中\n本間 智\n\n 10歳。俊介の息子\n本間 千鶴子\n\n 俊介の妻。故人\n井坂 恒男\n\n 本間家の隣人\nカッちゃん\n\n 智の同級生\n栗坂 和也\n\n 29歳。千鶴子のいとこの息子。銀行員\n碇 貞夫\n\n 42歳。俊介の同僚\n関根 彰子\n\n 本物の関根彰子。スナックに勤務したことがあり、自己破産した経歴があった。\n新城 喬子\n\n 偽の関根彰子。婚約者を残し失踪した。自身は父親が遺した借金によって取り立て屋に苦しめられ、売春の強要をされた。悪状況から脱却するため自分と近い境遇の人間に成りすまそうとしていた。\n野村 一恵\n\n 本物の彰子の同級生\n本多 保\n\n 本物の彰子の幼なじみ\n本多 郁美\n\n 保の妻\n関根 淑子\n\n 彰子の母、故人。宇都宮市に在住していたが転落死した。\n溝口 悟郎\n\n 関根彰子の破産手続きをした弁護士\n今井 四郎\n\n 今井事務機の社長\nみっちゃん\n\n 今井事務機の事務員\n澤木\n\n 溝口・高田弁護士事務所の事務員\n青年\n\n 溝口・高田弁護士事務所の事務員\n井坂 久恵\n\n 43歳、恒男の妻、デザイナー\n片瀬 秀樹\n\n 下着通販会社ローズライン管理課課長補佐。新城喬子と交際していたが、新城喬子の他人に成りすますという野望のため体よく利用されていただけだった。\n須藤 薫\n\n 喬子の友人\n木村 こずえ\n\n 22歳。フリーター\n倉田 康司\n\n 喬子の別れた夫\n市木 かおり\n\n 喬子の元同居人\n雑誌記者\n\n 本間の知人\n宮城 富美江\n\n 彰子の知人\n紺野\n\n 喫茶バッカスの店主\n紺野 明美\n\n 紺野の娘\n紺野 信子\n\n 紺野の妻。コーポ川口の大家\n宮田 かなえ\n\n 美容室ロレアルサロンの従業員\nママ\n\n ライハマのママ\n菊池\n\n ライハマのバーテン\nマキ', mimetype='text/plain', start_char_idx=12724, end_char_idx=13566, text_template='{metadata_str}\n\n{content}', metadata_template='{key}: {value}', metadata_seperator='\n'),
TextNode(id_='f96c3089-226f-4a13-a706-2a5e86b5a923', embedding=None, metadata={}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={<NodeRelationship.SOURCE: '1'>: RelatedNodeInfo(node_id='https://ja.wikipedia.org/wiki/%E7%81%AB%E8%BB%8A_(%E5%B0%8F%E8%AA%AC)', node_type=<ObjectType.DOCUMENT: '4'>, metadata={}, hash='956de29d6407704bc945d1ff9f843ad814ca357e032b0d19e2b86c40d6754fe9'), <NodeRelationship.PREVIOUS: '2'>: RelatedNodeInfo(node_id='46f36a51-8730-445d-9510-1ef7a5834351', node_type=<ObjectType.TEXT: '1'>, metadata={}, hash='0b109e7390b9935d93de686a7ca2c39197f64842a4b6d3cd4741e1a0002ed341'), <NodeRelationship.NEXT: '3'>: RelatedNodeInfo(node_id='3ec6b5c7-5d2a-4598-84ad-eadb436669fc', node_type=<ObjectType.TEXT: '1'>, metadata={}, hash='4508fa37c97fe2b086c790e51f4c45f23d99e5bee0de3f253c363501e0d92b17')}, text='紺野の妻。コーポ川口の大家\n宮田 かなえ\n\n 美容室ロレアルサロンの従業員\nママ\n\n ライハマのママ\n菊池\n\n ライハマのバーテン\nマキ\n\n ライハマの店員\n北村 真知子\n\n 理学療法士\n境\n\n 宇都宮署の刑事\n加藤\n\n 倉田不動産社員\n\n## 書誌情報\n\n[[編集](/w/index.php?title=%E7%81%AB%E8%BB%8A_\\(%E5%B0%8F%E8%AA%AC\\)&action=edit§ion=4\n"節を編集: 書誌情報")]\n\n * 単行本:1992年7月1日発売、[双葉社](/wiki/%E5%8F%8C%E8%91%89%E7%A4%BE "双葉社")、[ISBN 978-4-5752-3117-5](/wiki/%E7%89%B9%E5%88%A5:%E6%96%87%E7%8C%AE%E8%B3%87%E6%96%99/9784575231175)\n * 文庫本:1998年1月30日発売、[新潮文庫](/wiki/%E6%96%B0%E6%BD%AE%E6%96%87%E5%BA%AB "新潮文庫")、[ISBN 978-4-1013-6918-1](/wiki/%E7%89%B9%E5%88%A5:%E6%96%87%E7%8C%AE%E8%B3%87%E6%96%99/9784101369181)\n * Audible版: 2019年8月15日配信、朗読:[三浦友和](/wiki/%E4%B8%89%E6%B5%A6%E5%8F%8B%E5%92%8C "三浦友和") 15時間35分\n\n## テレビドラマ\n\n[[編集](/w/index.php?title=%E7%81%AB%E8%BB%8A_\\(%E5%B0%8F%E8%AA%AC\\)&action=edit§ion=5\n"節を編集: テレビドラマ")]\n\n### 1994年版\n\n[[編集](/w/index.php?title=%E7%81%AB%E8%BB%8A_\\(%E5%B0%8F%E8%AA%AC\\)&action=edit§ion=6\n"節を編集: 1994年版")]\n\n[1994年](/wiki/1994%E5%B9%B4 "1994年")(平成6年)[2月5日](/wiki/2%E6%9C%885%E6%97%A5\n"2月5日")に[土曜ワイド劇場](/wiki/%E5%9C%9F%E6%9B%9C%E3%83%AF%E3%82%A4%E3%83%89%E5%8A%87%E5%A0%B4\n"土曜ワイド劇場")枠で『**火車 カード破産の女!** 』というタイトルでドラマ化された。\n\n映画でも高い実績を持つベテラン池広一夫が演出し、クライマックス一場面だけのために大きな喫茶店セットを組むなどの特徴がある。\n\n####', mimetype='text/plain', start_char_idx=13489, end_char_idx=14707, text_template='{metadata_str}\n\n{content}', metadata_template='{key}: {value}', metadata_seperator='\n')]
LlamaIndexのVectorStoreの構築
LlamaIndexで用意されているシンプルなVectorStoreの構築について解説していきます。
必要なパッケージをインストールします。
pip install llama-index llama-index-core
VectorStoreIndexクラスを使って、ベクトルストアのインデックスを作成します。
from llama_index.core import VectorStoreIndex
index = VectorStoreIndex(nodes, show_progress=True)
インデックスをもとにクエリエンジンを作成します。
query_engine = index.as_query_engine(similarity_top_k=3)
response = query_engine.query("火車の概要を教えて下さい")
print(response)
火車は、宮部みゆきによるミステリー小説であり、社会問題としての消費者金融のありかたをテーマに、サラリーマン金融やカード破産などの借財と多重債務をめぐる取り立てに翻弄される女の生き様を、彼女のことを追い求める刑事の視点から描く。
query_engine = index.as_query_engine(similarity_top_k=3)
as_query_engine
:インデックスもとにユーザーの質問に対して回答を生成するクエリエンジンを構築します。similarity_top_k=3
:類似度に基づいて上位3つの関連性の高い結果を取得するように指定しています。
インデックスのIDを設定し、指定したディレクトリに保存します。
index.set_index_id("miyabe_miyuki")
index.storage_context.persist("./storage/simple_vs")
index.set_index_id(“miyabe_miyuki”)
index
に対して、IDとして"miyabe_miyuki"
を設定しています。インデックスIDは、インデックスを一意に識別するためのもので、後でインデックスをロードしたり、クエリを実行したりする際に役立ちます。
index.storage_context.persist(“./storage/simple_vs”)
データの保存や管理を行う部分(storage_context)を指定されたディレクトリ("./storage/simple_vs"
)に保存しています。このディレクトリにインデックスのデータが保存され、次回以降の使用時に再インデックスすることなく、同じデータをすぐに利用できるようになります。
保存されたインデックスをストレージからロードして再利用します。
from llama_index.core import StorageContext, load_index_from_storage
storage_context = StorageContext.from_defaults(persist_dir="./storage/simple_vs")
simple_vc_index = load_index_from_storage(storage_context, index_id="miyabe_miyuki")
storage_context = StorageContext.from_defaults(persist_dir=”./storage/simple_vs”)
- ここでは、
"./storage/simple_vs"
というディレクトリにある保存済みデータを扱うためのStorageContext
を作成しています。
simple_vc_index = load_index_from_storage(storage_context, index_id=”miyabe_miyuki”)
storage_context
とindex_id="miyabe_miyuki"
を使って、ストレージからインデックスをロードしています。index_id="miyabe_miyuki"
は、保存したインデックスに設定された一意のIDです。このIDを指定することで、その特定のインデックスをロードしています。これにより、以前に保存したインデックスを再構築することなく、再度使用できるようになります。
ChromaDBの構築
ChromaDBを使用してベクトルストアを保存および再利用する方法を示しています。
必要なパッケージをインストールします。
pip install chromadb llama-index-vector-stores-chroma
ChromaDBを使用してベクトルストアのインデックスを作成します。
import chromadb
from llama_index.core import VectorStoreIndex
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core import StorageContext
chroma_client = chromadb.EphemeralClient()
chroma_collection = chroma_client.create_collection("miyabe_miyuki")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
chroma_index = VectorStoreIndex(nodes, storage_context=storage_context)
chroma_client = chromadb.EphemeralClient()
ChromaDBのエフェメラル(短期間の)クライアントを作成します。これは、データを一時的に保存し、サーバーが終了すると削除されるメモリ内のデータベースを意味します。
chroma_collection = chroma_client.create_collection(“miyabe_miyuki”)
chroma_client
を使用して、新しいコレクション(データのコンテナ)を作成しています。ここではコレクション名を"miyabe_miyuki"
として指定しています。
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
ChromaVectorStore
を使って、ChromaDB
内のコレクション(chroma_collection
)をベクトルストアとして扱うためのオブジェクトを作成しています。これにより、コレクション内のデータに対してベクトル検索を行えるようになります。
storage_context = StorageContext.from_defaults(vector_store=vector_store)
StorageContext
は、データの保存や管理を行うためのオブジェクトです。ここでは、先に作成したvector_store
(ChromaDBベースのベクトルストア)をStorageContext
にセットして、データ管理を行えるようにしています。
chroma_index = VectorStoreIndex(nodes, storage_context=storage_context)
VectorStoreIndex
クラスを使って、nodes
をベクトル検索用のインデックスとして作成しています。storage_context
を指定しているため、このインデックスはChromaDBをバックエンドとして使って検索が行われます。
インデックスをもとにクエリエンジンを作成します。
query_engine = chroma_index.as_query_engine()
response = query_engine.query("『理由』で事件のあったマンション名を教えて下さい。")
print(response)
ヴァンダール千住北ニューシティ
query_engine = chroma_index.as_query_engine()
as_query_engine
:インデックスもとにユーザーの質問に対して回答を生成するクエリエンジンを構築します。
インデックスのIDを設定し、指定したディレクトリに保存します。
db = chromadb.PersistentClient(path="./storage/chroma")
chroma_collection = db.get_or_create_collection("miyabe_miyuki")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
chroma_index = VectorStoreIndex(nodes, storage_context=storage_context, show_progress=True)
db = chromadb.PersistentClient(path=”./storage/chroma”)
- PersistentClientを作成し、
path="./storage/chroma"
という指定されたディレクトリにデータを永続化します。
chroma_collection = db.get_or_create_collection(“miyabe_miyuki”)
- get_or_create_collectionメソッドは、”miyabe_miyuki”という名前のコレクションを取得するか、存在しない場合は新しく作成します。
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
- ChromaVectorStoreを作成し、先ほど作成した
chroma_collection
をベクトルストアとして使用します。
storage_context = StorageContext.from_defaults(vector_store=vector_store)
- StorageContextを作成し、
vector_store
をその一部として設定します。
chroma_index = VectorStoreIndex(nodes, storage_context=storage_context, show_progress=True)
- VectorStoreIndexを作成し、
nodes
とstorage_context
をもとにインデックスを構築します。 - VectorStoreIndexは、ベクトル検索用のインデックスを作成し、指定された
nodes
をインデックス化します。 show_progress=True
は、インデックス作成中に進行状況を表示するオプションで、インデックスの構築が進んでいるかを確認できます。
保存されたインデックスをストレージからロードして再利用します。
db = chromadb.PersistentClient(path="./storage/chroma")
chroma_collection = db.get_or_create_collection("miyabe_miyuki")
chroma_vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
chroma_index = VectorStoreIndex.from_vector_store(vector_store=chroma_vector_store)
chroma_collection = db.get_or_create_collection(“miyabe_miyuki”)
PersistentClient
を使って、以前保存したChromaDBのデータベースを再利用するための接続を行います。path
で指定したディレクトリ (./storage/chroma
) に保存されたデータベースを読み込み、再利用します。
chroma_vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
すでに保存されている "miyabe_miyuki"
という名前のコレクションを取得します。get_or_create_collection
は、もしコレクションが存在しない場合に新たに作成しますが、ここでは既存のコレクションを再利用しています。
chroma_index = VectorStoreIndex.from_vector_store(vector_store=chroma_vector_store)
取得したコレクションを元にChromaVectorStore
を読み込み、保存されたベクトルストアを再利用します。これにより、新規にベクトルストアを構築することなく、保存済みのベクトルデータをそのまま利用することができます。
chroma_index = VectorStoreIndex.from_vector_store(vector_store=chroma_vector_store)
from_vector_store
メソッドを使って、保存されたベクトルストア (chroma_vector_store
) を元にVectorStoreIndex
を再利用します。
FaissDBの構築
FaissDBを使用してベクトルストアを保存および再利用する方法を示しています。
必要なパッケージをインストールします。
pip install llama-index-vector-stores-faiss faiss-gpu
ベクトル検索に使用する次元数を設定します。
import faiss
d = 1024
faiss_index = faiss.IndexFlatL2(d)
d = 1024
ベクトル検索に使用する次元数(d)を設定しています。ここでは、1024次元のベクトルを扱うことを示しています。
ベクトル検索に使用する次元数は、埋め込みベクトル(この記事では、intfloat/multilingual-e5-large)の次元数と合わせる必要があります。
faiss_index = faiss.IndexFlatL2(d)
1024次元のベクトルに対して、L2距離を使ったインデックスを作成しています。このインデックスは、類似検索(例えば、与えられたベクトルに最も近いベクトルを見つける)に使用されます。
ChromaDBを使用してベクトルストアのインデックスを作成します。
from llama_index.core import (VectorStoreIndex,StorageContext,)
from llama_index.vector_stores.faiss import FaissVectorStore
faiss_vector_store = FaissVectorStore(faiss_index=faiss_index)
storage_context = StorageContext.from_defaults(vector_store=faiss_vector_store)
faiss_index = VectorStoreIndex(nodes, storage_context=storage_context, show_progress=True)
faiss_vector_store = FaissVectorStore(faiss_index=faiss_index)
事前に作成したFaissインデックス(faiss_index
)を使用して、FaissVectorStore を初期化しています。
storage_context = StorageContext.from_defaults(vector_store=faiss_vector_store)
デフォルト設定でストレージコンテキストを作成しています。このコンテキストは、ベクトルデータを保存・管理するために使用します。
faiss_index = VectorStoreIndex(nodes, storage_context=storage_context, show_progress=True)
VectorStoreIndex
を使って、ベクトルインデックスを作成しています。
インデックスをもとにクエリエンジンを作成します。
query_engine = faiss_index.as_query_engine()
response = query_engine.query("杉村三郎の所属を教えて下さい")
print(response)
杉村三郎は今多コンツェルン会長の娘婿で、同コンツェルングループ広報室に所属しています。
query_engine = faiss_index.as_query_engine()
as_query_engine
:インデックスもとにユーザーの質問に対して回答を生成するクエリエンジンを構築します。
インデックスのIDを設定し、指定したディレクトリに保存します。
faiss_index.storage_context.persist(persist_dir="./storage/faiss")
faiss_index.storage_context.persist(persist_dir=”./storage/faiss”)
persist()
は、faiss_index
内で使用されているストレージコンテキストをディスクに保存するためのメソッドです。これにより、次回の使用時に同じインデックスを読み込むことができます。faiss_index.storage_context
は、faiss_index
のストレージに関する設定やコンテキストを保持しています。
保存されたインデックスをストレージからロードして再利用します。
vector_store = FaissVectorStore.from_persist_dir("./storage/faiss")
storage_context = StorageContext.from_defaults(
vector_store=vector_store, persist_dir="./storage/faiss"
)
faiss_index = load_index_from_storage(storage_context=storage_context)
vector_store = FaissVectorStore.from_persist_dir(“./storage/faiss”)
指定したディレクトリに保存されているFaissのベクトルストアをロードしています。
storage_context = StorageContext.from_defaults(vector_store=vector_store,persist_dir=”./storage/faiss”)
StorageContext.from_defaults()
は、ベクトルストアを基にして、ストレージコンテキストを構築するためのメソッドです。persist_dir="./storage/faiss"
では、永続化ディレクトリとして./storage/faiss
を指定しています。これにより、今後の保存や読み込みで同じディレクトリが使用されます。vector_store=vector_store
では、上で読み込んだFaissのベクトルストアを使用して、ストレージコンテキストを作成しています。
faiss_index = load_index_from_storage(storage_context=storage_context)
load_index_from_storage()
は、ストレージコンテキストからベクトルインデックスをロードするための関数です。storage_context=storage_context
では、前のステップで作成したstorage_context
を指定し、その中に含まれるベクトルストアや関連情報を使用してインデックスを読み込みます。- これにより、保存されていたFaissのベクトルインデックスが再度ロードされ、使用可能な状態になります。
Qdrant VectorStoreの構築
Qdrantを使用してベクトルストアを保存および再利用する方法を示しています。
必要なパッケージをインストールします。
pip install llama-index-vector-stores-qdrant qdrant_client
Qdrantを使用してベクトルストアのインデックスを作成します。
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.qdrant import QdrantVectorStore
from qdrant_client import QdrantClient
client = QdrantClient(path="./storage/qdrant")
qdrant_vector_store = QdrantVectorStore(
client=client,
collection_name="miyabe_miyuki",
enable_hybrid=False,
)
storage_context = StorageContext.from_defaults(vector_store=qdrant_vector_store)
qdrant_index = VectorStoreIndex(nodes, storage_context=storage_context)
client = QdrantClient(path=”./storage/qdrant”)
QdrantClient
を初期化して、./storage/qdrant
パスに保存されたQdrantのデータに接続します。このクライアントを通して、Qdrantの操作が行われます。
qdrant_vector_store = QdrantVectorStore()
QdrantVectorStore
は、QdrantClient
を使用して Qdrant 内にコレクション(データの集合体)を管理するクラスです。client=client
では、先ほど初期化したQdrantClient
を使います。collection_name="miyabe_miyuki"
では、コレクションを指定しています。これは、ベクトル検索を行う際のデータの分類や管理に使われます。enable_hybrid=False
は、ハイブリッド検索(ベクトル検索とメタデータフィルタリングを組み合わせた検索)を無効にしています。必要に応じて、True
にすることで有効化も可能です。
storage_context = StorageContext.from_defaults(vector_store=qdrant_vector_store)
StorageContext
は、ベクトルストアや他のストレージに関連する情報を管理します。from_defaults(vector_store=qdrant_vector_store)
で、先ほど作成したqdrant_vector_store
を使ってStorageContext
を初期化します。- これにより、
QdrantVectorStore
がこのストレージコンテキストの一部となり、データの永続化やインデックス作成に利用されます。
qdrant_index = VectorStoreIndex(nodes, storage_context=storage_context)
VectorStoreIndex
は、ベクトルストアに基づくドキュメントインデックスを作成します。nodes
はインデックスに追加するデータで、ドキュメントや記事などの情報をベクトル化して保存するものです。storage_context=storage_context
では、先ほど作成したStorageContext
を指定します。これにより、ベクトルデータがQdrantに保存され、ベクトル検索や類似度検索ができるようになります。
インデックスをもとにクエリエンジンを作成します。
query_engine = qdrant_index.as_query_engine()
response = query_engine.query("『ソロモンの偽証』は何部作ですか?")
print(response)
『ソロモンの偽証』は3部作です。
query_engine = qdrant_index.as_query_engine()
as_query_engine
:インデックスもとにユーザーの質問に対して回答を生成するクエリエンジンを構築します。
保存されたインデックスをストレージからロードして再利用します。
client = QdrantClient(path="./storage/qdrant")
qdrant_vector_store = QdrantVectorStore(client=client, collection_name="miyabe_miyuki")
qdrant_index = VectorStoreIndex.from_vector_store(vector_store=qdrant_vector_store)
client = QdrantClient(path=”./storage/qdrant”)
ローカルストレージに保存されているQdrantデータベースを読み込んでいます。ここでは新しいデータを追加するのではなく、既存のデータベースを再利用しています。
qdrant_vector_store = QdrantVectorStore(client=client, collection_name=”miyabe_miyuki”)
Qdrant内の既存のmiyabe_miyuki
コレクションを指定しています。これにより、このコレクションに既に保存されているベクトルデータを再利用する形で、検索インデックスを作成します。
qdrant_index = VectorStoreIndex.from_vector_store(vector_store=qdrant_vector_store)qdrant_vector_store
の既存データを基にしてインデックスを作成しています。
生成AI・LLMのコストでお困りなら
GPUのスペック不足で生成AIの開発が思うように進まないことはありませんか?
そんなときには、高性能なGPUをリーズナブルな価格で使えるGPUクラウドサービスがおすすめです!
GPUSOROBANは、生成AI・LLM向けの高速GPUを業界最安級の料金で使用することができます。
インターネット環境さえあれば、クラウド環境のGPUサーバーをすぐに利用可能です。
大規模な設備投資の必要がなく、煩雑なサーバー管理からも解放されます。