初めての「LangChain」
はじめに
LLM(Large Language Model)を効率的に使うには、「LangChain」なるものを使うといいらしい、、、とよく耳にするものの、LangChainってそもそも何なのか、LangChainを使うと何ができるのか、正直よくわかっていない。そこで、10月の3連休を利用して、素人ながら調べて、少し勉強してみることにした。
尚、本記述は私の数日の理解を元に記載したものであり、誤りや正確でない内容が含まれる可能性があること、予めご了承頂きたい。
LangChainって何?
そもそも、LangChainとは何か?LangChianのドキュメントサイト(※1)やWikipedia(※2)を見てみると「LLMをつかったアプリケーション開発を簡単にするようにデザインされたパッケージフレームワーク」と書かれている。
ただ、これだけではちょっと抽象的なので、どんなモジュールがあってどのようなことができるか調べてみた。
LangChainで何ができる?
公式ドキュメントによると、主に1~6に分類されるようなモジュール群があり、それぞれざっくり以下のようなことができそう。
Model I/O LLMへのインターフェースを以下3段階で提供
①前処理 プロンプトを効率的に作る(langchainのPromptTemplate)
②呼出 異なるLLMに共通仕様でアクセス(langchain.llmsのOpenAI、langchainのHuggingFaceHub等)
③後処理 アウトプットを整える
Retrieval LLMモデルの訓練対象以外の独自ドキュメント・データを検索対象に加えられるようにする為、以下のような一連の機能を提供
①Document loaders 対象となるドキュメントを読み込む(langchain.document_loaders の TextLoader等)
②Document transformersドキュメントを小単位(単語等)に変換(langchain.text_splitter の RecursiveCharacterTextSplitter等)
③Text embedding models 変換した小単位を以下④のベクトルデータベースに組み込む(langchain.embeddings.openai の OpenAIEmbeddings等)
④Vector stores 提供されるベクトルデータベース(langchain.vectorstores のChroma等)
⑤Retrievers 上記組み込まれたデータを検索する
Chains LLM同士や別のコンポーネントとつなぐ機能(langchain.chains のLLMChain、SimpleSequentialChain、RetrievalQA等)
Agents 応答時等にwikipedia等効果的な外部ツールを利用できるようにする機能(langchain.agents のload_tools等)
Memory 会話履歴などを保持しておく機能(langchain.memoryのChatMessageHistory、ConversationBufferMemory等)
Callbacks 監視やログに活用できるコールバック機能
例えば、PaLM2でもGPTでも、APIを呼び出すだけでは一問一答のような答えしか返らない為、ChatGPTのように質問の応答履歴も踏まえて回答できるようにするにはどうするんだろう、、、と思っていたが、上記5のMemoryを使えば実現できそうだ。👍
また、LLMの学習データ以外の最近のネット情報やデータや固有ドキュメントを検索対象にして回答させるにはどうしたよいのだろう、、、と思っていたが、こちらも上記2のRetrievalを使えばできそう。クラウドサービス(GCPならVertexAISearch、MSAzureならCognitiveSearchが近い?)でも提供しているようだが、元となる技術はこれで抑えられそう。🙌
また、上記4のAgentsを使えば、wikipediaやGoogleSearchなど外部機能もアドオンして回答の精度を高められそうだ。😊
LangChainを使ってやってみたこと
LangChainでできることはたくさんありそうであるが、ここではこの3日間で私が試してみたことを書いてみる。
前準備
前準備としては、以下を実施した。
API取得関連(一部課金)(APIキー、APIトークンは環境変数に設定)
OpenAIのAPIキー取得 https://openai.com/product
Hugging FaceのAPIトークン取得 https://huggingface.co/
Google SearchのAPIキー(SerpAPI)取得 https://serpapi.com/
必要なPythonモデュールのインストール
pip install langchain
pip install huggingface_hub
pip install openai
pip install wikipedia
pip install tiktoken
pip install chromadb
やってみたのは、以下3つ。それぞれについて解説する。
プロンプトテンプレートを使ってLLMに共通仕様でアクセス
具体期には、以下のように、
プロンプトテンプレートを使って、質問をmath、english、scienceと変え
呼び出すモデルも共通仕様のHuggingFaceからモデルをgoogle/flan-t5-base、mistralai/Mistral-7B-v0.1に変えて
簡単にQAを実行することができる😊
(コード)
from langchain import HuggingFaceHub
from langchain import PromptTemplate
LLM_list={"google/flan-t5-base","mistralai/Mistral-7B-v0.1"}
subject_list={"math","english","science"}
template = "what is the best way to study {subject}?"
prompt_template = PromptTemplate.from_template(template)
for no, each_subject in enumerate(subject_list):
prompt=prompt_template.format(subject=each_subject)
print(f"Q{no+1} {prompt}")
for each_LLM in LLM_list:
llm = HuggingFaceHub(repo_id=each_LLM,
model_kwargs={
"temperature": 0.9,
"max_length": 64
})
ans=llm(prompt)
print(f"A{no+1}:({each_LLM}){ans}")
(実行結果)
Q1 what is the best way to study english?
A1:(google/flan-t5-base)study in a classroom
A1:(mistralai/Mistral-7B-v0.1)The best way to study English is by communicating with native English speakers like me.
Q2 what is the best way to study science?
A2:(google/flan-t5-base)study in a laboratory
A2:(mistralai/Mistral-7B-v0.1)Study during the day
Q3 what is the best way to study math?
A3:(google/flan-t5-base)study in a classroom
A3:(mistralai/Mistral-7B-v0.1)There is no substitute for hard work. Always be humble and kind.
Wikipediaなどのツールを使って応答を高度化
具体期には、以下のように、2023年の米国のGDPが日本のGDPをそれぞれwikipediaから参照し、GDPが何倍になっているかllm-mathを使って算出してみる。
(コード)
from langchain.llms import OpenAI
from langchain.agents import load_tools, initialize_agent
prompt = "How many times greater is the GDP of the U.S. in 2023 than the GDP of Japan?"
llm = OpenAI(temperature=0)
tools = load_tools(["wikipedia", "llm-math"], llm=llm)
agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)
agent.run(prompt)
(実行結果)
> Entering new AgentExecutor chain...
I need to find the GDP of both countries in 2023
Action: Wikipedia
Action Input: GDP of the United States in 2023
Observation: Page: List of U.S. states and territories by GDP
Summary: This is a list・・・・(中略)
Thought: I need to find the GDP of Japan in 2023
Action: Wikipedia
Action Input: GDP of Japan in 2023
Observation: Page: List of countries by GDP (nominal)
Summary: Gross domestic product (GDP) is the market value of all・・・(中略)
Thought: I need to compare the GDP of the U.S. and Japan in 2023
Action: Calculator
Action Input: 25.463 trillion / 5.7 trillion
Observation: Answer: 4.46719298245614
Thought: I now know the final answer
Final Answer: The GDP of the U.S. in 2023 is 4.47 times greater than the GDP of Japan.
> Finished chain.
このように、それぞれのGDPから4.47倍と算出してくれた。(但し、wikipediaを参照するとそれぞれのGDPの値を正しく抜き出していない模様でどうやら間違っている。。。😔でも、仕組みとしては動いることは確認できたこと、GPTのAPIの課金が気になるので今回は深追いせず)尚、「verbose=True」とすると上記のように途中経過も詳しく出力してくれようだ。
検索対象ドキュメントを追加し、会話履歴を考慮した応答にする
具体期には、以下のように、https://python.langchain.com/docs/get_started/introduction の内容をコピーしてテキストファイル(LangChain_introduction.txt)に保存し、その内容をロードし、変換し、エンベディングしChromaのベクタースペースに保存。RetrievalQAのChainを使いOpenAIのllmと上記ベクタースペースを連結し、「LangChainを使って何ができるか?」を上記追加したデータを使って回答させる。さらに、その会話履歴を保存させ、「何を話していたか?」という質問に答えさせる。
(コード)
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.schema import messages_from_dict, messages_to_dict
from langchain import OpenAI, ConversationChain
from langchain.memory import ChatMessageHistory, ConversationBufferMemory
loader = TextLoader("./LangChain_introduction.txt")
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
texts = text_splitter.split_documents(documents)
embeddings = OpenAIEmbeddings()
store = Chroma.from_documents(texts, embeddings, collection_name="introduction")
llm = OpenAI(temperature=0)
chain = RetrievalQA.from_chain_type(llm, retriever=store.as_retriever())
history = ChatMessageHistory()
history.add_user_message("What can we do by using LangChain?")
history.add_ai_message(chain.run("What can you do by using LangChain?"))
dicts = messages_to_dict(history.messages)
new_messages = messages_from_dict(dicts)
history = ChatMessageHistory(messages=new_messages)
buffer = ConversationBufferMemory(chat_memory=history)
conversation = ConversationChain(llm=llm, memory=buffer, verbose=True)
print(conversation.predict(input="what did you talk about?"))
(実行結果)
> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.
Current conversation:
Human: What can you do by using LangChain?
AI: You can develop applications that are context-aware and can reason using a language model, as well as use off-the-shelf chains, log and stream intermediate steps of any chain, use cases, guides, and resources, and construct sequences of calls.
Human: what did you talk about?
AI:
> Finished chain.
We were discussing LangChain, which is a platform for developing applications that are context-aware and can reason using a language model. We discussed the features of LangChain, such as the ability to use off-the-shelf chains, log and stream intermediate steps of any chain, use cases, guides, and resources, and construct sequences of calls.
上記のように、ちゃんと追加したtxtを踏まえた回答をAIがし、何を話していたかも会話を記憶して正しく答えている。🙌
今後やってみたいこと
なんとなくさわりだけでも、LangChainがわかってきたが、今後色々なUI(GoogleChatやLINEなど)から様々なモデルを呼び出し、会話履歴を考慮してドキュメント検索しながら応答するようなものを直接、またはクラウド上で作っていけたらと思う。
三連休のうち二日間はなんだかんだプログラムいじっていたが、明日10月10日は私の誕生日。昔は体育の日は祝日だったんだけどな。。。でも、明日生まれて半世紀の記念すべき?日を前に、新しい技術を理解できてちょっと嬉しい、充実した三連休だった😂
参考文献
この記事が気に入ったらサポートをしてみませんか?