🌴
【LangChain】複数処理をつなげる「Chains」読解メモ
LangChainでLLMやツール使用、データの前処理など、さまざまな処理をラクにつなげることができる「Chains」のドキュメントを読み解いたメモです。
pip install -U openai langchain langchain-openai
「Chains」とは
LLM、ツール、データ前処理ステップなどへの一連の呼び出しを簡単に行うためのLangChainのモジュールの一つです。これによって特定タスクを効率的に実行できるようになります。
現在「LCEL Chains」と「Legacy Chains」の2種類のチェーンがサポートされています。(2024年2月12日時点)
1. LCEL Chains
LCEL(LangChain Composition Expression Language)を用いて構築された、よりモダンで柔軟性の高いチェーン。
「独自の処理フローを持つチェーンを構築したい場合」や「特定のタスクに合わせて細かいカスタマイズが必要な場合」に適しています。
GitHub)
1-1. create_stuff_documents_chain (- 「Documentオブジェクトのリスト」を一つのプロンプトにまとめてLLMに渡すチェーン。
コード例&出力プロンプト
- コード例
from langchain_openai import ChatOpenAI
from langchain_core.documents import Document
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains.combine_documents import create_stuff_documents_chain
prompt = ChatPromptTemplate.from_messages(
[("system", "みんなの好きな色は何ですか?:\n\n{context}")]
)
llm = ChatOpenAI(model_name="gpt-4-0125-preview")
chain = create_stuff_documents_chain(llm, prompt)
docs = [
Document(page_content="ジェシーは赤が好きだけど黄色は好きではない"),
Document(page_content="ジャマールは緑が好きだけど、オレンジの方がもっと好き")
]
res = chain.invoke({"context": docs})
res
# ジェシーの好きな色は赤で、ジャマールの好きな色はオレンジです。
- 生成されるプロンプト
# SYSTEM PROMPT
みんなの好きな色は何ですか?:
ジェシーは赤が好きだけど黄色は好きではない
ジャマールは緑が好きだけど、オレンジの方がもっと好き
GitHub)
1-2. create_openai_fn_runnable (- OpenAIのFunction Callingを使用して、「構造化された出力応答を生成したい場合」に使用。
- 複数の関数を渡せるけれど、必ずしもそれらを呼び出す必要はない。
コード例&出力プロンプト
- コード例
from langchain_openai import ChatOpenAI
from langchain.chains.openai_functions import create_openai_fn_runnable
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field
from typing import Optional
class RecordPerson(BaseModel):
"""ある人物の識別情報を記録する。"""
name: str = Field(..., description="名前")
age: int = Field(..., description="年齢")
fav_food: Optional[str] = Field(None, description="好きな食べ物")
class RecordDog(BaseModel):
"""ある犬の識別情報を記録する。"""
name: str = Field(..., description="犬の名前")
color: str = Field(..., description="犬の色")
fav_food: Optional[str] = Field(None, description="犬の好きな食べ物")
llm = ChatOpenAI(model="gpt-4-0125-preview")
prompt = ChatPromptTemplate.from_messages(
[
("system", "エンティティを記録するための世界クラスのアルゴリズムです。"),
("human", "以下の入力にあるエンティティを記録するために、関連する関数を呼び出してください: {input}"),
("human", "ヒント: 正しいフォーマットで回答してください"),
]
)
chain = create_openai_fn_runnable([RecordPerson, RecordDog], llm, prompt)
res = chain.invoke({"input": "ハリーはチキンが大好きなふくよかな茶色のビーグル犬でした"})
res
# RecordDog(name='ハリー', color='茶色', fav_food='チキン')
- 生成されるプロンプト
# SYSTEM PROMPT
エンティティを記録するための世界クラスのアルゴリズムです。
# HUMAN PROMPT
以下の入力にあるエンティティを記録するために、関連する関数を呼び出してください: ハリーはチキンが大好きなふくよかな茶色のビーグル犬でした
# HUMAN PROMPT
ヒント: 正しいフォーマットで回答してください
GitHub)
1-3. create_structured_output_runnable (- OpenAIのFunction Callingを使用して、「LLMに特定の関数で応答させることを強制したい場合」に使用。
- 一つの関数のみを渡し、常にこの応答を返します。
コード例&出力プロンプト
- コード例
from langchain_openai import ChatOpenAI
from langchain.chains.openai_functions import create_structured_output_runnable
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field
from typing import Optional
class Dog(BaseModel):
"""犬に関する識別情報。"""
name: str = Field(..., description="犬の名前")
color: str = Field(..., description="犬の色")
fav_food: Optional[str] = Field(None, description="犬の好きな食べ物")
llm = ChatOpenAI(model="gpt-4-0125-preview")
prompt = ChatPromptTemplate.from_messages(
[
("system", "構造化されたフォーマットで情報を抽出するための世界クラスのアルゴリズムです。"),
("human", "与えられたフォーマットを使用して、以下の入力から情報を抽出してください: {input}"),
("human", "ヒント: 正しいフォーマットで回答してください"),
]
)
chain = create_structured_output_runnable(Dog, llm, prompt)
res = chain.invoke({"input": "ハリーはチキンが大好きなふくよかな茶色のビーグル犬でした"})
res
# Dog(name='Harry', color='茶色', fav_food='チキン')
- 生成されるプロンプト
# SYSTEM PROMPT
エンティティを記録するための世界クラスのアルゴリズムです。
# HUMAN PROMPT
以下の入力にあるエンティティを記録するために、関連する関数を呼び出してください: ハリーはチキンが大好きなふくよかな茶色のビーグル犬でした
# HUMAN PROMPT
ヒント: 正しいフォーマットで回答してください
GitHub)
1-4. load_query_constructor_runnable (- クエリを生成するために使用できます。許可された操作のリストを指定する必要があり、自然言語クエリをこれらの許可された操作に変換するrunnableを返します。
コード例&出力プロンプト(※まだ未確認)
- コード例
# 今後更新
- 生成されるプロンプト
# 今後更新
GitHub)
1-5. create_sql_query_chain (- 自然言語からSQLデータベースのクエリを構築したい場合に使用します。
- SQLデータベース
コード例&出力プロンプト(※まだ未確認)
- コード例
# 今後更新
- 生成されるプロンプト
# 今後更新
GitHub)
1-6. create_history_aware_retriever (- 会話履歴を取り込み、それを使用して検索クエリを生成し、基礎となるリトリーバーに渡すチェーンです。
コード例&出力プロンプト(※まだ未確認)
- コード例
# 今後更新
- 生成されるプロンプト
# 今後更新
GitHub)
1-7. create_retrieval_chain (- ユーザーの問い合わせを受け取り、関連文書をフェッチするためにリトリーバーに渡し、その文書(および元の入力)をLLMに渡して応答を生成するチェーンです。
コード例&出力プロンプト(※まだ未確認)
- コード例
# 今後更新
- 生成されるプロンプト
# 今後更新
2. Legacy Chains
以前のバージョンのLangChainで使用されていた、サブクラス化によって構築されたチェーン。
今後LCELベースのチェーンに置き換えられる予定で、新たにチェーンを構築する際にはLCELの使用が推奨されています。
その他のコード
LLMChain
指定のモデル+プロンプトの組み合わせをChainとして作り、簡単に実行できるものです。
コード例
from langchain.chains import LLMChain
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
# --- 指定: 使用モデル ---
chat_gpt_4 = ChatOpenAI(model='gpt-4-0125-preview')
# --- プロンプトのテンプレート ---
prompt_template = "ランダムに{theme}選んでください。"
prompt = PromptTemplate(
input_variables=["theme"], # プロンプトの変数名
template=prompt_template # プロンプト
)
# --- チェーン生成 ---
llm = LLMChain(
llm=chat_gpt_4, # 使用モデル
prompt=prompt # プロンプト
)
# --- チェーン実行 ---
result = llm.invoke("動物") # プロンプトの変数「動物」を代入して実行
print(result)
# {'theme': '動物', 'text': '\nライオン'}
(複数の変数を使う場合)
from langchain.chains import LLMChain
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
# --- 指定: 使用モデル ---
chat_gpt_4 = ChatOpenAI(model='gpt-4-0125-preview')
# --- プロンプトのテンプレート ---
prompt_template = "ランダムに{theme_1}と{theme_2}選んでください。"
prompt = PromptTemplate(
input_variables=["theme_1", "theme_2"], # プロンプトの変数名
template=prompt_template # プロンプト
)
# --- チェーン生成 ---
llm = LLMChain(
llm=chat_gpt_4, # 使用モデル
prompt=prompt # プロンプト
)
# --- チェーン実行 ---
result = llm.invoke({"theme_1": "動物", "theme_2": "数字"})
print(result)
# {'theme_1': '動物', 'theme_2': '数字', 'text': 'カワウソ、7'}
まとめ
主要な用途ではそれぞれチェーンが用意されているような印象でした!
Discussion