QEUR23_LMABYS5: GPT4ALLでLangChain(Vector Store)を使う
~ 応用は「∞(無限大)」 ~
・・・ 前回のつづきです ・・・
D先生 : “プロンプトにCONTEXTを入れるのは、とても効果がありますね。あっ、そうだ!!この考え方を使えば、我々が適切な情報をCONTEXT経由でLLMに注入して、GPTに回答させることができますね。”
QEU:FOUNDER : “それがLangChainというシステムが提案しているVector Storeの考え方です。つまり、ユーザが提供した膨大なCONTEXTを細かく分割しDB(データベース)にします。それを、質問に応じて適当な情報を取り出してプロンプトに渡せばいいわけです。”
D先生 : “そうすれば、GPTのパフォーマンス(回答レスポンス)を悪くすることなく、よりよい品質の回答を出すことができます。”
D先生 : “現在LLM界で流行しているLangChain技術の本質を理解するには、良いケーススタディになりますよね。あのAI界のレジェンドの一人であるAndrew NgがLangChainの使い方を教えていますので、このレクチャーを受ける前に我々のプロジェクトをやると、より理解が深まると思います。”
QEU:FOUNDER : “それでは、LangChain技術で最も有用といわれている「Vector Store」の機能を前回のプログラムに注入しましょう。質問は10種類で前回と同じものを使います。CONTEXTとして使うデータも前回通りです。ただし、Vector Storeを使うのでこれらの長文データは分割されChunkとなります。そして、それはEmbeddingにより特徴ベクトルに変換されます。”
D先生 : “LangChainでよく出てくる「Chunk」って、よくわからないんですよね・・・。”
QEU:FOUNDER : “英単語としては、このシチュエーションで使うのは意味が「?」となるんだけどね。何はともあれ、Chunkってのは「文(Sentence)」以上、「文章・段落(Paragraph)」以下として考えればいいんじゃないでしょうか。それでは、プログラムをドン!!”
# -----
import pandas as pd
import numpy as np
from langchain.chains import RetrievalQA
from langchain.document_loaders import DirectoryLoader
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.llms import GPT4All
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
#Load all the .txt files from docs directory
loader = DirectoryLoader('./LCdocs/',glob = "**/*.txt")
documents = loader.load()
len(documents)
# -----
print(documents[0].page_content)
# -----
# 言語情報をChunk分割する
splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=64)
texts = splitter.split_documents(documents)
len(texts)
# -----
print(texts[0].page_content)
QEU:FOUNDER : “今回は前半の前処理部分が最も重要なので、一旦ストップして解説です。LangChainにはいろいろメソッドはあるんですが、文書をロードしてLangChainで使う型式に変換することができます。”
D先生 : “ほう・・・。このメソッドでは「LCdoc」というディレクトリの中のすべてのtxtファイルを一括して読み込むんですね。”
QEU:FOUNDER : “だから、次の命令の「len(documents)」の値が1になっているでしょ?”
D先生 : “なるほどね・・・。そして、その読み込んだdocumentsをChunkに分割するわけですね。”
QEU:FOUNDER : “それでは、Chunkに分割するコード周辺を見てみましょう。Chunkするには、サイズとオーバーラップを決める必要があります。”
D先生 : “オーバーラップっていうパラメタがあるんですね。単純にぶった切ると意味がない文章になる可能性があるからしようがないですが・・・。質問数は10件でしたよね。”
QEU:FOUNDER : “だから、Chunkの数が10個付近になるように調整しました。最後に、オマケですが、つづけてEmbedding をしていますね。”
D先生 : “TokenizerのモデルをHuggingFace(HF)から読み込んでますね・・・。”
QEU:FOUNDER : “興味があったらこのTokenizerのHFページを見てください。どのようなデータベースから学習されたモデルかが出ています。どうやら、東アジア圏の言語は苦手なんでしょうね。”
D先生 : “欧米様は東アジアには関心がないから・・・(笑)。実際のところ、東アジアの言語は「分かち書き」がないのでトークン化が難しいんです。”
# -----
# Create Embeddings
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
db = Chroma.from_documents(texts, embeddings, persist_directory="db")
# -----
#Create Chain
model_path = "D:./ggml-gpt4all-j-v1.3-groovy.bin"
#llm = GPT4All(model=model_path, n_ctx=300, backend="gptj", verbose=False)
llm = GPT4All(model=model_path, backend="gptj", verbose=False)
qa = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=db.as_retriever(search_kwargs={"k": 2}),
return_source_documents=True,
verbose=False,
)
# -----
#Ask Questions
res = qa(
"What is the capital of Japan?"
)
print(res)
# -----
print(res["result"])
# -----
# 質問の文字列リストを定義する
question_list = [
"What is the capital of Japan?",
"Who is the author of Harry Potter?",
"What is the name of the largest bone in the human body?",
"How many planets are there in the solar system?",
"What is the chemical formula of water?",
"Who painted the Mona Lisa?",
"What is the most spoken language in the world?",
"Who is the current president of the United States?",
"What is the square root of 81?",
"What is the name of the first artificial satellite launched by the Soviet Union?"
]
# -----
# 個別の質問応答のタスクを実行する関数を定義する
def repeat_qa(question):
# 質問に回答する
print(f"No.{i}: Question: {question}")
#Ask Questions
res = qa( question )
answer = res["result"]
# 答えを表示する
print(f"Answer: {answer}")
return answer
# 繰り返し質問する
mx_output = []
for i in range(3): # range(len(question_list))
# 今回の質問を抽出する
question = question_list[i]
# 質問に回答する
answer = repeat_qa(question)
# 質問と回答のマトリックス(リスト)を生成する
mx_output.append([question, answer])
# -----
# リストを出力する
print("--------")
print("generate output matrix")
print(np.array(mx_output))
# -----
import pandas as pd
import numpy as np
# Create DataFrame
mx_out = np.array(mx_output)
columns1 = ["Question", "Answer"]
df_out = pd.DataFrame(data=mx_out, columns=columns1)
print(df_out)
# CSV ファイル (result_gpt4all.csv) として出力
df_out.to_csv("result_gpt4all(vector_store).csv")
D先生 : “あとは結果だけを見ればいいですね。ここでは、CSV出力されています。”
QEU:FOUNDER : “じゃあ、結果を見てみましょう。う~ん、惜しい・・・。”
D先生 : “なんか、GPTがイレギュラーな終わり方をしたのかな?しかし、81の平方根が9であるという答えをしっかり出しています。・・・そういえば、スピードは速くなりましたか?”
QEU:FOUNDER : “うん、前回の長文のCONTEXTをプロンプトに入れたときよりも圧倒的に速いですよ。ホントに、VectorStoreっていいわぁ・・・。いろいろ使えそうですね。「LCdocs」フォルダにもっとたくさんの情報を入れてみたいですね。”
D先生 : “GPT4Allは基本は英語しか使えないですが、英語の学習用のシステムを作るには十分だと思います。学習(英語)塾の先生は、英語教育のノウハウがあるんで、是非自分で「バーチャル講師」を作ってみてほしいですね。”
QEU:FOUNDER : “今はGradioという手軽なUI(User Interface)もあるので、Webサーバーを立ち上げれば、オンライン学習もできるようになります。ただし、もうちょっとPCにパワーがあったほうがいい。”
D先生 : “以上、教育対策、経済対策の提案でした。”
~ まとめ ~
・・・ 前回のつづきです ・・・
QEU:FOUNDER : “さっき見ていたのだが、どうやらペット系列の製品には力を入れていないようだ。たぶん、どうしても「これを作りたい」という気持ちがないんでしょうね。”
C部長 : “「お客タマ」という方向性は正しいと思うんだけど・・・。そういえば、最近、新卒社員の面接をやりまして、そのセリフに思わずのけ反りました。”
学生:「御社の社風が私に合っていると考えました。」
QEU:FOUNDER : “(爆)いや、笑っちゃいかん・・・・。そういえば、小生は昔面接で同じセリフを吐いたはずです。でも、なんで、今、この令和の世の中で同じセリフを吐くとこういうふうになるのでしょうか・・・。”
C部長 : “やっぱり、「自分はココに入って何をしたい!」と言ってほしいですね。もしSteve Jobsとの面接で「御社の社風」といったら、1秒で「帰れ!」と言われますよ。”
QEU:FOUNDER : “「お前はiPhoneで何をしたいのか?」、もっといえば今までの自社製品群を否定してくれてもいいですね。俺ならこうすると・・・。多分、彼は大喜びします。”
C部長 : “天下のG社では、仕事の20%は目下のプロジェクト以外に使わなければならないですからね。常にやりたいことを自分で探さなければならない。”
QEU:FOUNDER : “人生で初めて「自分のやりたいことを決める」のは学校なんですよね。今では・・・。ああ・・・、大変な時代になったもんだ。”
コメント
コメントを投稿