LangChainでは、LLMに問いを投げるだけではなくWeb検索や独自のツールなどLLM以外の外部機能を使って回答のサポートを得ることもできる。
LangChainについては以下の記事などを参考にしてください。
ツール呼び出しの流れを図で表す

ツール呼び出しの流れは以下の通り。
- まずLLMを呼び出す
- LLMは問い合わせの内容と認識しているツールの内容を元にツールを呼び出すかどうかを決める
- ツールを呼び出さない場合はそのままLLMが回答して終了
- ツールを呼び出す場合はツールを呼び出し、得た回答を元にLLMが最終的な回答をまとめる
実装について
全体を一度に載せると細かいので少しずつ説明していく。
全体フロー
上に載せた図の全体フローの表現にはLangGraphを使用する。(LangGraphの説明は割愛)
from langgraph.graph import StateGraph, START, MessagesState
workflow = StateGraph(MessagesState)
workflow.add_node("llm", call_model)
workflow.add_node("tools", tool_node)
workflow.add_edge(START, "llm")
workflow.add_conditional_edges(
"llm",
decide_tool_route,
)
workflow.add_edge("tools", "llm")
app = workflow.compile()
コードの説明
- ノードについて
- llm
- 「LLM呼出」にあたるところ
- call_model関数が実行されLLMが呼び出される
(まずは全体フローのみに焦点を絞るために省略していますがcall_model関数を始め各説明に出てくる関数は自作の関数です)
- tools
- 「ツール呼出」にあたるところ
- tool_nodeに定義されてるツールの中から必要なものが呼び出される
- llm
- 処理の流れ(図と同じですが改めて)
- スタート後「LLM呼出」が呼ばれる
- その後、LLMからの回答を元にdecide_tool_route関数によってツールを呼び出すかどうかを決める
- 「ツール呼出」を行ったらその後は再度「LLM呼出」が呼ばれる
- decide_tool_route関数内での実装となるが「ツール呼出」を行わない場合は終了となる
ツールを呼び出すかどうかの分岐
decide_tool_route関数の実装
from langgraph.graph import END, MessagesState
def decide_tool_route(state: MessagesState):
""" 最新メッセージ(LLMからの返答)が「tool_calls」になっていたらツールを使用する """
messages = state['messages']
last_message = messages[-1]
if last_message.tool_calls:
return "tools"
return END
- LLMからの戻り値に「finish_reason」という項目があるのだが、ここが「tool_calls」になっていたらLLMがツールを呼び出した方が良さそう、と判断したということになる。なお、ツールを呼ばなくても大丈夫そうな時は「stop」になる
- ツールを呼び出した方が良さそうなら「tools(ツール呼出)」を返し、ツールを呼ばないときは「END」を返す
ツールの定義
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_core.tools import tool
from langchain_openai import init_chat_model
from langgraph.prebuilt import ToolNode
@tool
def support(query: str):
""" サポートツール """
return ["雨"]
tools = [support]
model = init_chat_model("gpt-4o-mini", model_provider="openai").bind_tools(tools)
tool_node = ToolNode(tools)
# LLMにはモデルが学習された以降の情報が含まれていないため、天気のようなリアルタイム情報は取得できない
# そのため、利用できるツールがあるならツールを使用しようとする
messages = [
SystemMessage("あなたはLLMとツールを使いこなしユーザーからの問いに答えます"),
HumanMessage("東京の天気を教えてください"),
]
- 「@tool」というデコレータを関数につけるとツールとして扱うことができる
- LLMモデルを定義するときに「.bind_tools(tools)」と書くことでそのツールが使用可能になる
- 「ToolNode(tools)」によりLangGraphでツール利用として使用するノードの定義が行える
(少し離れてしまったが「全体フロー」に実際使用しているコードがある)
LLMがツールを判断する仕組み
- 「@tool」をつければツールとして使用はできるが、どのツールをどんなふうに使えば良いかをLLMが知るにはその関数の「名前」「引数の型」「説明文(ドックストリング)」が頼りとなる
- なので上の例では「サポートツール」としか書いていないが、実際使う時には、どのようなツールで、どのような型を受け取り、どのような情報を返すのか、をきちんと書いたほうが良い
- また、この情報を元に判定するので「サポートツール」のところを「翻訳ツール」など天気とは関係ない説明に変更した場合はツールを使わずに終了となる


コメント