LlamaIndex v0.10.1を試す
サラッとColaboratoryで流してみる。
インストール
!pip install llama-index
新しいパッケージの構成を確認してみる。
!pip freeze | grep "llama-"
llama-index==0.10.6
llama-index-agent-openai==0.1.1
llama-index-core==0.10.6.post1
llama-index-embeddings-openai==0.1.1
llama-index-legacy==0.9.48
llama-index-llms-openai==0.1.2
llama-index-multi-modal-llms-openai==0.1.1
llama-index-program-openai==0.1.2
llama-index-question-gen-openai==0.1.1
llama-index-readers-file==0.1.3
んー、なるほど、この感じだとLLMにCohere使いたい、ベクトルDBにQdrant使いたい、みたいな場合は追加でパッケージのインストールが必要になりそう。
今のところのパッケージ構成は一時的にNotionに記載されているけど、最終的にはインテグレーション系はLlamaHubに集約されるのかな?
PyPIを見てみると山ほどあるな。でもまあ必要なパッケージだけ追加できるほうがイメージ作ったりする場合には極力コンパクトにできそう
例えばこんな感じでカスタムに必要なものだけインストールできるみたい。
!pip install llama-index-core llama-index-llms-cohere llama-index-embeddings-cohere llama-index postprocessor-cohere-rerank llama-index-vector-stores-qdrant
チュートリアル
OpenAI APIキーをセット
import os
from google.colab import userdata
os.environ["OPENAI_API_KEY"] = userdata.get("OPENAI_API_KEY")
ファイルを用意する。
from pathlib import Path
import requests
# Wikipediaからのデータ読み込み
wiki_titles = ["イクイノックス", "ドウデュース"]
for title in wiki_titles:
response = requests.get(
"https://ja.wikipedia.org/w/api.php",
params={
"action": "query",
"format": "json",
"titles": title,
"prop": "extracts",
# 'exintro': True,
"explaintext": True,
},
).json()
page = next(iter(response["query"]["pages"].values()))
wiki_text = page["extract"]
data_path = Path("data")
if not data_path.exists():
Path.mkdir(data_path)
with open(data_path / f"{title}.txt", "w") as fp:
fp.write(wiki_text)
ファイルからインデックス作成してクエリまで。
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query("ドウデュースの主な勝ち鞍は?")
print(response)
GIを含む重賞3勝目、日本ダービー、京都記念
ここまではそんなに違いは感じない。
変更点を見ている中でコード的に影響ありそうなのはここ
LlamaIndex v0.10 contains some major updates:
(snip)
- ServiceContext is deprecated: Every LlamaIndex user is familiar with ServiceContext, which over time has become a clunky, unneeded abstraction for managing LLMs, embeddings, chunk sizes, callbacks, and more. As a result we are completely deprecating it; you can now either directly specify arguments or set a default.
DeepL訳
LlamaIndex v0.10にはいくつかの大きなアップデートが含まれています:
(snip)
- ServiceContextは廃止されました: LlamaIndexのユーザーなら誰もがServiceContextを使い慣れていると思いますが、LLMやエンベッディング、チャンクサイズ、コールバックなどを管理するための抽象化された不要なものでした。現在では、引数を直接指定するか、デフォルトを設定することができます。
Service Contextのマイグレーションガイドがあった。
今までだとこんな感じになってたと思う。実際にこれで動くかはおいといて適当。
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core.node_parser import SentenceSplitter
from llama_index.llms.openai import OpenAI
from llama_index.core import ServiceContext, set_global_service_context
service_context = ServiceContext.from_defaults(
llm=OpenAI(model="gpt-3.5-turbo"),
embed_model=OpenAIEmbedding(model="text-embedding-3-small"),
node_parser=SentenceSplitter(chunk_size=512, chunk_overlap=20),
num_output=512,
context_window=3900,
)
set_global_service_context(service_context)
documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query("ドウデュースの主な勝ち鞍は?")
print(response)
自分はset_global_service_context
をあまり使わない、というかなんかうまく動かなかった印象を持っているので、いろんなモジュールの初期化時にservice contextを個別に設定することが多かった気がする。
今後はこんな感じ?
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core.node_parser import SentenceSplitter
from llama_index.llms.openai import OpenAI
from llama_index.core import Settings
Settings.llm = OpenAI(model="gpt-3.5-turbo-0125")
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
Settings.node_parser = SentenceSplitter()
Settings.num_output = 512
Settings.chunk_size = 400
Settings.chunk_overlap = 100
Settings.context_window = 4096
Settings.num_output = 256
documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query("ドウデュースの主な勝ち鞍は?")
print(response)
もしくは個別に設定する。
んー、Service ContextがSettingsになって劇的に変わったって感じはあまりしないかなぁ。
個人的に思うのは、上記のようにLLMモジュールとかEmbeddingモジュールというようなモジュールレベルのものとチャンクサイズとみたいなモジュールのパラメータレベルのものが同列に並んでいるというのがわかりにくさを生んでいるような気がするのだよね。。。
自分が使う場合はモジュールだけ設定して、パラメータはモジュール側に設定することにしそう。デフォルトのモジュール設定だけしておいて、変えたい場合は都度引数で指定する、もしくは、全部都度指定する、かな。
とりあえずコードを書く上では、
- 必要なパッケージを必要に応じて追加する
- Service Context/Settingsあたりは少し使ってみて考える
かな。それ以外はそんなに気にしなくて良さそう。
まあLangChainもパッケージ分割されているし、これ自体は正しい流れじゃないかな。