現状のChatGPT の限界
チャット GPT は非常に便利ですが主に2つの課題があります。
1つめは学習されたデータが最新でない事です。2021年9月までのデータで学習しているため それ以降のデータについては 回答することができません。
2つめはプロンプトに含められるトークン数の制限です。GPT3.5では4,096トークンまで、GPT4は8,192トークンまでとなっています。ざっくりと日本語1文字で1トークンとなります。これよりも文字数の多い論文などについて要約したくてもプロンプトに含めることはできません。
このようなChatGPTが抱える課題を乗り越えるために開発されたライブラリが今回ご紹介するLangChainです。
LangChainとは
LangChainとは大規模言語モデルを効果的に使う為のライブラリです。現在、PythonとTypescriptに対応しています。(こちらの記事ではPythonを紹介)
このライブラリを使用することで 先ほどあげた ChatGPTの課題を克服することが可能になります。
つまり最新の情報をもとにGPTモデルと対話することやまた論文など文字数の多い資料をもとにGPTモデルと対話することも可能になります。
どのようなモジュールがあるのか?
LangChainはModels、Prompts、Memory、Indexes、Chains、Agentsの6つのカテゴリに分かれ、それぞれに複数のモジュールが属しています。
- Models
LLMs
、Chat Models
、Text Embeddings Models
- Prompts
Prompt Templates
、Chat Prompt Template
、Example Selectors
、Output Parsers
- Memory
- Indexes
Document Loaders
、Text Splitters
、Vectorstores
、Retrievers
- Chains
- Agents
Tools
、Agents
、Toolkits
、Agent Executors
それぞれ 概要を見ていきましょう。
Models
Modelsのカテゴリでは、
LLMs
、Chat Models
、Text Embeddings Models
というモジュールが用意されています。Text completion(単発のやり取り)やChat completion、EmbeddingsなどLLMのAPIを叩くのに便利なインターフェースを提供しています。下記のように連携可能なLLMをシンプルな記法で呼び出すことができます。
from langchain.llms import OpenAI llm = OpenAI(model_name="text-ada-001", n=2, best_of=2)
llm("Tell me a joke")
'\n\nWhy did the chicken cross the road?\n\nTo get to the other side.'
Prompts
Promptsのカテゴリでは
Prompt Templates
、Chat Prompt Template
、Example Selectors
、Output Parsers
というモジュールが用意されています。これらはプロンプトをデザインする上で便利な機能を提供しています。Prompt Template
, Chat Prompt Template
ではそれぞれプロンプトを共通化したり、変数を使って簡単にカスタマイズできるインターフェースを提供しています。同じような質問を繰り返し行う際に、手間を省くことができます。例えば以下の例ではプロンプトにproductという変数を持ったテンプレートを用意し、実行時に変数を代入できるようにしています。
from langchain import PromptTemplate template = """ I want you to act as a naming consultant for new companies. What is a good name for a company that makes {product}? """ prompt = PromptTemplate( input_variables=["product"], template=template, ) prompt.format(product="colorful socks") # -> I want you to act as a naming consultant for new companies. # -> What is a good name for a company that makes colorful socks?
これを後述する
Chains
を使って、Models
で定義したLLMと組み合わせることでLLMへカスタマイズしたプロンプトを投げることが出来ます。他にもFew shot Promptsなどのテクニックを実装する為の
Example Selectors
や出力結果のフォーマットを定義するOutput Parsers
などが用意されています。Memory
LLM とのやり取りを保持するために使用するモジュールです。
ChatGPT のように過去のやり取りを踏まえて回答するチャットサービスを実現するために必要な機能です。
以下の例では
ChatMessageHistory
クラスにユーザーとAIからのメッセージをそれぞれ格納している様子が分かるかと思います。from langchain.memory import ChatMessageHistory history = ChatMessageHistory() history.add_user_message("hi!") history.add_ai_message("whats up?")
history.messages
[HumanMessage(content='hi!', additional_kwargs={}), AIMessage(content='whats up?', additional_kwargs={})]
Indexes
Indexesのカテゴリでは、
Document Loaders
、Text Splitters
、Vectorstores
、Retrievers
というモジュールが用意されています。このカテゴリはEmbeddings
というLLMに任意の情報を追加する手法で用いられます。Embeddings
の手法は主に- テキストデータの読み込み
- テキストデータの分割
- 分割されたチャンクのベクトル化
- ベクトル化したデータの保存
- 保存したデータの取得
というステップで行われます。このステップの1,2,4,5に対応したモジュールが用意されているわけです。
テキストデータの読み込み: Document loader テキストデータの分割: Text Splitters ベクトル化データの保存: Vectorstores 保存したデータの取得: Retrievers
例えば以下のようにドキュメントを読み込み、
TextSplitter
というクラスを使ってそのドキュメントを指定したチャンクサイズに分割することができます。from langchain.text_splitter import CharacterTextSplitter documents = loader.load() text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0) texts = text_splitter.split_documents(documents)
Chains
Chains
は、LLM を連鎖的につなげていくことのできるモジュールです。前述のModels
とPrompts
を組み合わせて、鎖を作り、それを繋げていく様なイメージです。それを応用することで、ある LLM の出力を別の LLM の入力として使用することなども可能になります。最もシンプルなChainは以下の様に
Models
とPromptTemplate
を組み合わせて作ります。from langchain.prompts import PromptTemplate from langchain.llms import OpenAI llm = OpenAI(temperature=0.9) prompt = PromptTemplate( input_variables=["product"], template="What is a good name for a company that makes {product}?", )
from langchain.chains import LLMChain chain = LLMChain(llm=llm, prompt=prompt) # Run the chain only specifying the input variable. print(chain.run("colorful socks"))
また
SimpleSequentialChain
というクラスでChain
を複数繋げることもできます。from langchain.chains import SimpleSequentialChain overall_chain = SimpleSequentialChain(chains=[chain, chain_two], verbose=True) # Run the chain specifying only the input variable for the first chain. catchphrase = overall_chain.run("colorful socks") print(catchphrase)
Agents
Agentsカテゴリでは、
Tools
、Agents
、Toolkits
、Agent Executor
というモジュールがあります。これらはAutoGPTやBabyAGIといった最近話題となっている自律駆動型AIエージェントを作るベースとなっています。Tools
はLLMを使ってインターネット検索やZapierの操作など実際のアクションを実行するモジュールです。これをChain
と組み合わせることで一連の流れの中でLLMからの応答に応じて、ネット検索を行ったり、APIを実行したり実際のアクションを実行させることが出来ます。例えば以下の様な流れでGoogle検索を実行することが出来ます。
from langchain.tools import Tool from langchain.utilities import GoogleSearchAPIWrapper search = GoogleSearchAPIWrapper() tool = Tool( name = "Google Search", description="Search Google for recent results.", func=search.run )
tool.run("Obama's first name?")
そして中でも強力な機能が
Agents
モジュールです。このモジュールではユーザーの指示に基づいて、何をどのステップで行うかを自身で判断し、実行まで行ってくれるAgentを定義することができます。# Construct the agent. We will use the default agent type here agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
ここまででは凄さが伝わらないかと思いますが、詳細は別記事にて深堀りたいと思います。
まとめ
現在、LLMを使った様々なサービスがカンブリア爆発よろしく、日々大量に誕生していますが、その多くはGPTの様なLLM x LangChainの組み合わせで作られています。また今後も話題に登ってくるであろう自立駆動型AIエージェントでもLangChainが広く使われています。
この2点からもLLMを使ったアプリケーションを作る際には必ずと言って良いほど使われるライブラリとなっているので、各モジュールの中身を知ってアイデアを形にしていきましょう。
各カテゴリのより詳細な説明や使い方は別の記事で見ていきたいと思います。
今日はここまで!!👋