本記事は
2022年度 新人卒業記念Week
2日目の記事です。
🌸
1日目
▶▶ 本記事 ▶▶
3日目
📚
はじめに
こんにちは。新人の堤です。この1年はAWSを中心としたサービスの開発や運用を行っていました。最近はChatGPTなどのLLMを使って遊ぶのにはまってます。 今回は最近自分が色々試しているLangChainというライブラリについてご紹介したいと思います!
LangChainについて
LangChainとはChatGPTなどの大規模言語モデル(LLM)を使ったサービスの開発を支援するためのライブラリです。LangChainを使用することで、LLM単独ではできないような他の計算や知識のソースと組み合わせたより高度なアプリケーションを開発することができます。
LangChainの機能
LangChainには以下のような機能があります。今回はこれらのMemoryとChats以外の機能を試していきたいと思います。
- LLMs
- Prompt Template
- Document Loaders
- Indexes
- Chains
- Agent
- Memory
- Chats
LLMs
LLMsはLLMをLangChainで使用するためのモジュールです。 LangChainを介することで異なるLLMを統一したインターフェースで利用する事ができます。
以下はChatGPTを使用したコード例です。環境変数OPENAI_API_KEY
にOpenAIのAPIキーを設定してきましょう。
from langchain.llms import OpenAI llm = OpenAI(model_name="gpt-3.5-turbo") print(llm("面白い冗談を1つ言ってください。"))
「なぜ猫がコンピューターを使えないか知ってる? キーボードが『にゃんにゃんにゃん』しか打てないからだよ!」
Prompt Template
Prompt Templateはプロンプトを共通化したり,変数を用いることでプロンプトの取り扱いを便利にするモジュールです。
以下のようにテンプレートを定義することができます。
from langchain import PromptTemplate template = """与えられた料理名の レシピを出力してください。ただし必ず以下の情報を含めること。 ・ 材料 ・ 調理の手順 ・ コツ,注意点 ・ 費用目安 ・ 所要時間 料理名: {dish_name}""" prompt = PromptTemplate( input_variables=["dish_name"], template=template, )
Document LoadersとIndexes
Document Loadersは独自のテキストデータを読み込み,それをLLMと組み合わせて使用するためのライブラリです。
テキストファイルはもちろん,パワーポイントやPDFなど様々なフォーマットのファイルを読み込むことができます。
IndexesはLLMがドキュメントとやり取りできるようにするためにドキュメントを構造化するモジュールです。例えば社内のChatBotを作りたいとなったときは,documents Loadersで社内情報を取り込み,Indexesで構造化してLLMが利用できるようにするといった流れになります。
実際にDocument LoadersとIndexesを使って独自データを読み込んでみましょう...と言いたいところですがこのあたりは別ライブラリのLlammaIndexというライブラリを使った方が簡単なためそちらを試していこうかと思います。
LlamaIndexもLangChainと同じようなライブラリでLLM周りのサービスの開発で使われるライブラリになります。
今回は大谷翔平選手のWikipediaのページを読み込んで質問に答えてもらいましょう。実際のコードは以下のようになります。
from llama_index.readers import BeautifulSoupWebReader documents = BeautifulSoupWebReader().load_data(urls=["https://ja.wikipedia.org/wiki/%E5%A4%A7%E8%B0%B7%E7%BF%94%E5%B9%B3"])
ページが読み込めました!
次はLLMがこのドキュメントを読み込めるようにindexを作成します。
from llama_index import GPTSimpleVectorIndex index = GPTSimpleVectorIndex(documents=documents)
indexが作成できました。indexに対してqueryを入力することで質問できます。
print(index.query("2023年のWBCでの打者成績"))
2023年のWBCでの打者成績は、23打数10安打で打率.435、1本塁打、8打点となった。
正しい情報が取得できています!
内部的にはOpenAIのEmbeddings APIを使ってEmbeddingを取得して...みたいなことをやってます。
このあたりのソースつきで質問に回答してもらう仕組みについては今回は詳しく踏み込みませんが、以下のブログなどが分かりやすかったので参考にしてみてください。
Chains
話をLangChainに戻します。Chainsはその名の通りLLMを連鎖的につなげていくことのできるモジュールです。例えばあるLLMの出力をまた別のLLMの入力として使用したいときなどにChainsを使うことができます。
例えばある事象について説明してもらうLLMと入力された文章を要約するLLMの2つのLLMがあったとします。
from langchain import PromptTemplate from langchain import LLMChain # LLMの定義 explain_llm = OpenAI(model_name="gpt-3.5-turbo") summarize_llm = OpenAI(model_name="gpt-3.5-turbo") # テンプレートの定義 explain_template = """与えられた入力について詳細に説明してください。 入力: {input} """ summarize_template = """以下の入力について端的に要約してください。 入力: {input} """ explain_prompt_template = PromptTemplate( input_variables=["input"], template=explain_template, ) summarize_prompt_template = PromptTemplate( input_variables=["input"], template=explain_template, )
この2つのLLMをチェーンでつないでみます。
from langchain.chains import SimpleSequentialChain explain_chain = LLMChain(llm=explain_llm, prompt=explain_prompt_template) summarize_chain = LLMChain(llm=summarize_llm, prompt=summarize_prompt_template) explain_summarize_chain = SimpleSequentialChain(chains=[explain_chain, summarize_chain], verbose=True)
それぞれのLLMのチェーンを定義して、それをSimpleSequentialChain
というもので繋いでいます。
このチェーンについてクエリを実行してみます。
print(explain_summarize_chain.run("野球"))
> Entering new SimpleSequentialChain chain... 野球は、球技の一つで、2チームに分かれて行う競技です。目的は、ボールを打って相手チームの守備を翻弄し、得点を獲得することです。 野球には「ピッチャー」と呼ばれる投手が投げるボールを打とうとする「バッター」というポジションがあります。バッターが打ったボールを、相手チームの選手が走りながら追いかけてキャッチする「アウトフィールド」と呼ばれるエリアや、内野で守備を行う選手たちには「セカンド」「サード」などの名称があります。打ったボールがフェアかファウルか、また、ランナーの走塁がセーフかアウトかは、審判員が判断します。 野球は、ルールが複雑であるため、試合の長さが長くなります。また、「甲子園」と呼ばれる高校野球の全国大会や、「日米野球」など国際大会も開催されます。野球は、日本の国民的スポーツであり、多くの人々に愛されています。 この文章は、野球についての概要を説明しています。野球は2チームに分かれて行う球技で、ボールを打って相手チームの守備を翻弄し、得点を獲得することが目的です。投手やバッター、アウトフィールドや内野で守備を行う選手たちにはそれぞれ役割があり、審判員がフェアかファウル、セーフかアウトかを判断します。ルールが複雑で試合の長さが長くなるため、高校野球の全国大会や国際大会も開催されます。野球は日本の国民的スポーツであり、多くの人々に愛されています。 > Finished chain.
最初に野球という単語について説明があった後、その説明が要約されていることが確認できます!
今回はシンプルに2つのLLMの入出力をつないだだけですが、他にもPython Shellを実行するチェーンやSQLクエリを実行するチェーンなどもあり、これらをつないでいくことで1つのLLMだけでは実現できない処理を行うことができます。
Agent
次はAgentです。Chainsと似ていますが、Agentはツールというものを使用でき、それらを使用して回答することができます。
ツールは以下のようなものが用意されています
- google-search
- Google検索を行い、その結果を含めた回答ができるツール
- llm-math
- 数学の問題を解くツール
- python_repl
- phthon shellを実行するツール
このほかにも色々なツールが定義されており、自分で独自のツールを定義することもできます。
Agentは、与えられたツールからどのツールを実行し、どういう順序で使用するかを決定し、回答を導きます。 Chainsは順番通りにチェーンをつないでいくだけですが、Agentはどのツールをどういう順番で使用するかというところまで決めてくれるのが大きな違いでしょう。
実際に使ってみましょう
llm = OpenAI(model_name="gpt-3.5-turbo") tools = load_tools(["google-search"], llm=llm) agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)
toolsでどのような種類のツールを使用するかを定義しています。 今回はgoogle-searchのツールを使用するようにしています。
最近の出来事を質問してみましょう
agent.run("2023年wbcの日本対アメリカのスコア")
> Entering new AgentExecutor chain... I need to search for the score of the Japan vs. USA game in the 2023 WBC. Action: Google Search Action Input: "2023 WBC Japan vs. USA score" Observation: 1 day ago ... Japan finished the tournament 7-0, the second ever team to finish the WBC undefeated, joining the 2013 Dominican Republic squad. It was a ... 2 days ago ... The 2023 World Baseball Classic champion will be crowned Tuesday night in Miami · Japan up 3-1 in the fifth · Takahashi K's Goldschmidt · 3-1 Japan ... 1 day ago ... USA 2 - 3 Japan. ...以下略 Thought:I found the score - now I need to note it down. Final Answer: Japan won 3-2 against the USA in the 2023 WBC championship game. > Finished chain. 'Japan won 3-2 against the USA in the 2023 WBC championship game.'
Japan won 3-2 against the USA in the 2023 WBC championship game.
と正しい回答をしていることがわかります!
流れとしてはまず最初にエージェントがI need to search for the score of the Japan vs. USA game in the 2023 WBC.
と判断しており、2023 WBC Japan vs. USA score
というキーワードでGoogle検索をしています。その結果をもとに判断をし、最終的な回答を導き出しています。足りない情報をググって正しい回答を導き出しているのはすごいですね!今回は1つのツールしか使っていませんが色々なツールを組み合わせていくのも面白そうです。
まとめ
今回LangChainやLlmaIndexを触ってみて、ChatGPTなどのLLM単体ではできないような機能がこれらのライブラリで実現できるということが分かりました。今回はライブラリを軽く触ってみる程度でしたが、今後これらのライブラリを活用したアプリケーションも作ってみたいです!