LlamaIndexを動かしていきます。最近名前がGPTIndexから変わったみたい。
LlamaIndexとは、LLMのPromptの作成などを外部のデータソースと連携して行えるようにしたツールキット。
https://gpt-index.readthedocs.io/en/latest/guides/primer.html
データソースにはGoogle DocsやSlackなどが使えるらしい。
メインの機能は、DocsやSlack、Webの情報を体系化したIndexとして保持して、抽出できる機能でしょう。
OpenAIのAPIを使うことが多いと思いますが、今回はHugging faceのモデルを使ってみます。
LangChainをwrapしている部分がいくつかあるので、LangChainについても知っておくと良いと思う。
Install
doc通り
pip install llama-index
このあたりも使うので入れておく。
pip install transformers sentencepiece torch langchain
とりあえず動かす
大まかな流れは、ドキュメントからIndexを作成、Indexに対してqueryを投げ、抽出する、といった感じ。
ドキュメントからIndexを作成する際に、以下の4つを使う。
- llm_predictor
- embed_model
- prompt_helper
- template
llm_predictorの作成
llm_predictorは最終的な文章生成の際に使われる。インデックスの構築、挿入、クエリの走査中にも使用される場合がある。
Huggingfaceにあるmodelを使う例。モデルは好きなものを使ってください。
transformersのpipelineをlangchainのHuggingFacePipelineでwrap、
langchainのHuggingFacePipelineをllama_indexのLLMPredictorでwrapする。
model_name = "facebook/xglm-564M"
tokenizer = XGLMTokenizer.from_pretrained(model_name)
model = XGLMForCausalLM.from_pretrained(model_name)
pipe = pipeline("text2text-generation",
model=model,
tokenizer=tokenizer,
torch_dtype=torch.float16)
llm = HuggingFacePipeline(pipeline=pipe)
llm_predictor = LLMPredictor(llm=llm)
embed_modelの作成
embed_modelはdocumentをsentense vectorにしindexを作成する際に使われる。 (queryによる抽出の方法がいくつかあるが、vectorの類似度から抽出する方法があるので、そこのembeddingでも使ってそう)
model_name = "sonoisa/sentence-bert-base-ja-en-mean-tokens"
embeddings = HuggingFaceEmbeddings(model_name = model_name)
embed_model = LangchainEmbedding(embeddings)
prompt helperの作成
tokenの制限に使われる。OpenAIのモデルを使う場合に設定するものだと思う。
prompt_helper=PromptHelper.from_llm_predictor(
llm_predictor=llm_predictor,
max_chunk_overlap=0,
chunk_size_limit=512,
embedding_limit=1023,
)
promptの作成
日本語のpromptが欲しかったので作成。
QA_PROMPT_TMPL = (
"以下は文脈情報です。\n"
"---------------------\n"
"{context_str}"
"\n---------------------\n"
"予備知識ではなく、文脈情報が与えられます。"
"質問: {query_str}\n"
"回答:\n"
)
QA_PROMPT = QuestionAnswerPrompt(QA_PROMPT_TMPL)
indexの作成
これまでに作成した4つをあわせてindexを作成
- llm_predictor
- embed_model
- prompt_helper
- template
index = GPTSimpleVectorIndex(documents,
llm_predictor=llm_predictor,
embed_model=embed_model,
prompt_helper=prompt_helper,
text_qa_template=QA_PROMPT,
)
query
GPTSimpleVectorIndexに渡すtext_qa_templateと同じものを、queryにも渡します。
query_str = "podについて教えてください。"
response = index.query(query_str, text_qa_template=QA_PROMPT)
print("response:", response.response, "\n")
print("source_nodes:", response.source_nodes, "\n")
Indexについて
documentを読み込み、チャンクに分割、embeddingしたものNodeと呼ぶ。
このNode郡をIndexと呼ぶ
Nodeの束ね方はには種類がいくつかあり、sequentialに並べただけのList Indexや階層構造を持つTree Indexがある。
Indexの種類ごとにqueryの走査が異なる。
https://gpt-index.readthedocs.io/en/latest/guides/index_guide.html
とりあえず動かす場合、vector store使うのがおすすめらしい
https://gpt-index.readthedocs.io/en/latest/guides/use_cases.html#use-case-just-starting-out
vector storeは、いろいろなinmemory dbに対応してそう
https://github.com/jerryjliu/gpt_index/blob/v0.4.20/gpt_index/indices/vector_store/vector_indices.py
作成したindexに対し、追加/削除も可能
https://gpt-index.readthedocs.io/en/latest/how_to/update.html
query modeについて
色々試し中
https://gpt-index.readthedocs.io/en/latest/guides/usage_pattern.html#setting-response-mode
コードサンプル
https://github.com/jerryjliu/gpt_index/tree/v0.4.20/examples