LlamaIndex on Vertex AI for RAGを試す
ドキュメント斜め読みした感じだと、LlamaIndexからVertex AIを使う、というよりは、Vertex AIにLlamaIndexが組み込まれている、という感じに読める。
LangChainについても、LlamaIndexとは少しやり方は異なるようだけど、どうやらSDKに組み込まれているような感がある。
フレームワークにロックインされるか、プラットフォームにロックインされるか、の違いかな。個人的には今の状況だとフレームワークにロックインされるほうがマシかなぁという感を持っているのだけど、それはそれとしてフレームワークを組み込むというアプローチはちょっと新鮮ではある。
少し触ってみる。
Colaboratoryでざっと試してみた。結論から言うと、今回のお試しでは以下がうまく行かなかった。
- retrieval単体で動かした場合に検索でチャンクが得られない
- よって、最終回答もおそらくコンテキストがない状態での回答(つまりLLM単体の回答)だと思われる
原因はわからない。何かが足りないのか、間違っているのかもしれないけど、一旦やったことだけまとめておく。途中でつまづきまくっていろいろやっていたので、もしかすると不要なものがあるかもしれない。
事前準備
- プロジェクトでVertex AI APIを有効にする
- コンテキストとなるドキュメントはCloud StorageもしくはGoogleドライブ
- Cloud Storage
- バケットを作成してドキュメントをアップロードしておく
- サービスアカウント"Vertex AI RAG データ サービス エージェント"にバケットへの参照権を付与しておく
- Googleドライブ
- 該当のファイル(フォルダでもいいかもしれない)の共有設定で、上記サービスアカウントからの参照を許可しておく
- Cloud Storage
Colaboratory
Cloud SDKをインストール。Colaboratoryには予めCloud SDKが入っているけども、最初うまくいかなかったので、バージョンが古いのかも、ということで、入れ直した。ただ、ここは本当にそうなのかは不明。
!apt-get update
!apt-get install apt-transport-https ca
!curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
!echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
!apt-get update
!apt-get install google-cloud-cli
gcloudコマンドのパスを確認
!which gcloud
デフォルトのものは/toolsみたいなところに入っていたはず。以下のように/usr/binになっていれば上記でインストールしたものが使用される。
/usr/bin/gcloud
Vertex AI SDKのインストール
!pip install --upgrade google-cloud-aiplatform
GCPの認証。以下は予めGCPアカウントとプロジェクトをColaboratoryのSecretに登録している前提。認証するとURLが表示されるので、アクセスしてトークンをコピー、Colaboratory側に入力する。
from google.colab import userdata
GCP_ACCOUNT = userdata.get('GCP_ACCOUNT')
GCP_PROJECT = userdata.get('GCP_PROJECT')
!gcloud config set account {GCP_ACCOUNT} --quiet
!gcloud config set project {GCP_PROJECT} --quiet
!gcloud auth application-default login
Quota project "XXXXXX" was added to ADC which can be used by Google client libraries for billing and quota. Note that some services may still bill the project owning the resource.
みたいになればOKだと思う。
ではサンプルコードを動かす。設定が必要なのは以下。
- プロジェクトID
- RagCopus(Vertex AI上ではRAGのインデックスのことをこう呼ぶみたい)につける名前
- ドキュメントへのパス(Cloud Storage and/or Googleドライブ)
project_id="XXXXXXXXXX" # プロジェクトID
display_name="doduece" # RAGのコンテキストに付ける名前、何でも良さそう
paths = ["https://drive.google.com/file/d/XXXXXXXXXXXXXXXXXX", "gs://XXXXXXX"]
まずRagCorpusを作成してドキュメントをインポート。
from vertexai.preview import rag
from vertexai.preview.generative_models import GenerativeModel, Tool
import vertexai
# Vertex AI API初期化、なお東京は非対応だった
vertexai.init(project=project_id, location="us-central1")
# RagCorpusの作成
rag_corpus = rag.create_corpus(display_name=display_name,)
この作成でまず躓いた。なぜかエラーになる。で色々調べて、冒頭のCloudSDKのインストールに至った次第。ただそれが原因だったかは不明。
RagCorpusが作成できたらドキュメントをインポート
# RagCorpusにドキュメントをインポート
response = rag.import_files(
rag_corpus.name,
paths,
chunk_size=512, # Optional
chunk_overlap=100, # Optional
)
reponseを見るとファイルはインポートされた模様
response
imported_rag_files_count: 1
retrieval単体で実施するも回答なし。。。
response = rag.retrieval_query(
text="名前の由来は?",
rag_corpora=[rag_corpus.name]
)
response
登録されていないのかな?ということで、いろいろインタフェース調べてると以下の様なものがあった。
rag.list_files(
corpus_name=rag_corpus.name
)
ListRagFilesPager<rag_files {
name: "projects/XXXXXXXXXX/locations/us-central1/ragCorpora/XXXXXXXXXXXXXXXXXXXX/ragFiles/XXXXXXXXXXXXXXXXXXXX"
display_name: "XXXXX.txt"
create_time {
seconds: 1715888362
nanos: 380013000
}
update_time {
seconds: 1715888362
nanos: 380013000
}
gcs_source {
uris: "gs://XXXXXXXXX/XXXXX.txt"
}
}
rag_files {
name: "projects/XXXXXXXXXX/locations/us-central1/ragCorpora/XXXXXXXXXXXXXXXXXXXX/ragFiles/XXXXXXXXXXXXXXXXXXXX"
display_name: "XXXXX.txt"
create_time {
seconds: 1715888660
nanos: 291426000
}
update_time {
seconds: 1715888660
nanos: 291426000
}
google_drive_source {
resource_ids {
resource_type: RESOURCE_TYPE_FILE
resource_id: "XXXXXXXXXXXXXXXXXXXX"
}
}
}
これを見る限りは登録されているように見えるんだけどな。。。
LLMで呼び出し。色々つまづいてたので気づいてなかったけど、今これを改めて見ると、ツール呼び出しっぽい感じだな。そもそもツールとして呼び出されていないという気もする(とはいえretrieval単体でアレなので、、、)
rag_retrieval_tool = Tool.from_retrieval(
retrieval=rag.Retrieval(
source=rag.VertexRagStore(
rag_corpora=[rag_corpus.name], # Currently only 1 corpus is allowed.
similarity_top_k=3, # Optional
),
)
)
rag_model = GenerativeModel(
model_name="gemini-1.0-pro-002", tools=[rag_retrieval_tool]
)
response = rag_model.generate_content("ドウデュースの主な勝ち鞍は?")
print(response)
結果
candidates {
content {
role: "model"
parts {
text: "Doudice\'s main wins are the Prix du Muguet, Prix Greffulhe, Prix Jean-Luc Lagard\303\250re, Poule d\'Essai des Poulains, Prix d\'Ispahan."
}
}
finish_reason: STOP
safety_ratings {
category: HARM_CATEGORY_HATE_SPEECH
probability: NEGLIGIBLE
probability_score: 0.08035746961832047
severity: HARM_SEVERITY_NEGLIGIBLE
severity_score: 0.07668380439281464
}
safety_ratings {
category: HARM_CATEGORY_DANGEROUS_CONTENT
probability: NEGLIGIBLE
probability_score: 0.10894504189491272
severity: HARM_SEVERITY_NEGLIGIBLE
severity_score: 0.07185126841068268
}
safety_ratings {
category: HARM_CATEGORY_HARASSMENT
probability: NEGLIGIBLE
probability_score: 0.08632347732782364
severity: HARM_SEVERITY_NEGLIGIBLE
severity_score: 0.08756384253501892
}
safety_ratings {
category: HARM_CATEGORY_SEXUALLY_EXPLICIT
probability: NEGLIGIBLE
probability_score: 0.07640768587589264
severity: HARM_SEVERITY_NEGLIGIBLE
severity_score: 0.04208773002028465
}
grounding_metadata {
}
}
usage_metadata {
prompt_token_count: 9
candidates_token_count: 45
total_token_count: 54
}
なるほど、コンテンツフィルタ的なものがあるっぽい。
んでもって回答は間違っているのだけど、それはまあ置いといて、おそらくRAGが正しく動くならば、grounding_metadataってのに何かしら入ってきそうではある。
とりあえずGCP久々すぎてつまづきまくったのだけど、個人的には、慣れたLlamaIndexの書き方をあえてVertex AIに合わせて変えるまでのモチベーションはあまりないかな。他のモデル使えないし。メリットとしては、
- GCPの各リソースと連携・管理ができる
- コンテンツフィルタが使える
あたりになるんだろうか。
参考
今ならちゃんと動くのかもしれない。ただ、上にも書いたのだけど、LlamaIndexである意味があるのかどうか。