🤖

【技術解説】LangChainとLangGraphでAIエージェント開発に入門してみた【初心者】

2025/03/12に公開

最初に結論: LangChainとLangGraphを活用すると、AIエージェント構築・拡張がしやすいっぽい!

↑そんなの知っとるわいと言う人はこの記事をスルーしてください!
LLMアプリやAIエージェント・RAGに興味があって、LangChainって結局なんだ?と思っている人はもしかしたら役立つかも!

今回は、LangChainとLangGraphによるRAG・AIエージェント[実践]入門を最後まで読んだので、結局LangChainって何だったんだ?ってのを軽くまとめようと思って備忘録的に書いてみました。

LLM・AIエージェント実装初心者の方向けにLangChainとLangGraphの基本的な内容を理解し、活用イメージを持てることを目標に書いてみます!

  • 本当に簡単な技術説明:
    • LangChain: LLMアプリケーション開発を簡単にするフレームワーク
    • LangGraph: LangChainを拡張。マルチステップ・並列処理を効率的に構築できるワークフロー管理ツール

なぜLangChainが必要なのか

1. LangChainが必要になる瞬間って?

  • LLM APIを直接叩くのは簡単ですが、LLMを「アプリ」として動かすには課題があります。
    • 毎回プロンプトを作るのが面倒(テンプレート化したい)
    • 会話の流れが記憶されない(履歴を管理したい)
    • 外部データ(DB・API・検索エンジン)を参照できない(ナレッジ活用したい)
    • ユーザーの質問に応じて柔軟に処理を変えたい(動的フロー制御したい)
  • 例えば
    • ユーザーが何度も問い合わせてくるサポートチャットボットを作りたいが、API直叩きでは会話履歴が保持できない
    • こういう時に LangChain が役立ちます!

2. LangChainの概要

  • LangChainとは?
    • LLMの活用・アプリ開発を簡単にするフレームワーク
    • 代表的なモジュール(参考サイトはこちら):
      • Models(いわゆる学習モデル、LLMなど)
      • Prompts(入力を組み立てる。プロンプトをテンプレート化できる)
      • Memory(会話の履歴を保持)
      • Indexes(RAG的な処理。VectorStoreを活用して必要な情報のみを取ってくる)
      • Agents(動的にタスクを処理。必要なツールを選択したり。)
      • Chains(モジュールを連結する)
      • 詳しいコンポーネントは公式ドキュメントのこちらをご覧ください!

それではひとまず簡単な例を見てもらいます。

from langchain.schema import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4", openai_api_key="your_api_key")
messages = [
   SystemMessage(content="あなたは親切なアシスタントです")
   HumanMessage(content="こんにちは!")
]
response = llm.invoke(messages)
print(response.content)
 "こんにちは!今日はどんなことをお手伝いできますか?"

…APIを叩くのと変わらないと思いましたか?まぁシンプルな実装例だとそうなります。
では続きましてMemoryモジュールを使ってみましょうか

# 会話を保持してくれるMemoryを使った実装例
from langchain.chains import ConversationChain
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory()
llm = ChatOpenAI(model="gpt-4", openai_api_key="your_api_key")
chain = ConversationChain(llm=llm, memory=memory)

print(chain.invoke("おすすめの本を教えて"))
print("\n\n")
print(chain.invoke("前におすすめされた本は?"))

関数を書けばもちろん何も使わなくても実装はできますが、行数が桁違いですね(参考: [Azure] OpenAI Service で AI チャットボットを作ってみよう)。

3. LangChainの「Chain」とLCEL(LangChain Expression Language)

  • LangChainのChainが分かりやすく実装されているLCEL
    • LCELは、パイプ | を使って処理をシンプルに連結できる記法[1]
    • 複数の処理を直感的につなげる仕組み→Chain(チェーン)
    • これなら「データ取得 → 変換 → LLMで解釈」 を簡潔に記述可能!
  • LCEL(LangChain Expression Language)を使ったデモ
    • 例えば以下のコードでは、以下の 3ステップの処理 を | を使ってつなげています。
    1. retriever → TavilySearchResults[2]
      • 「今日の東京の天気」の検索結果を取得
    2. データ変換 → lambda x: f"今日の東京の天気の情報: {x}"
      • 検索結果を LLM が理解しやすいフォーマットに変換
    3. LLM に渡す → llm
      • ChatGPT (AzureOpenAPI)に渡して解釈させる
# デモ
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage
from langchain_community.tools.tavily_search import TavilySearchResults

# LLM & 検索ツールの準備
# llm = ChatOpenAI(model_name="gpt-4")
llm = azureai
retriever = TavilySearchResults()

# LCEL (LangChain Expression Language) を使ってシンプルに処理を定義
workflow = retriever | (lambda x: f"今日の東京の天気の情報: {x}") | llm

# 実行
result = workflow.invoke("今日の東京の天気")
print(result.content)
今日の東京の天気は以下の通りです。

- **日付**: 2025年2月8日(土)
- **天気**: 晴れ時々曇り
- **最高気温**: 9℃
- **最低気温**: 1℃
- **降水確率**: 10%(昼間は降水なし)
- **風**: 北西の風、日中はやや強く吹く
- **湿度**: 約58%

明日、2月9日(日)の予報は以下の通りです。

- **天気**: 晴れ
- **最高気温**: 11℃
- **最低気温**: 2℃
- **降水確率**: 0%(降水の可能性は低い)

注意点として、強い冬型の気圧配置が続いており、寒気の影響を受ける見込みです。特に、山沿いでは雪が降る可能性があるため、交通機関への影響に注意が必要です。

詳しい情報は以下のリンクから確認できます:
- [東進の天気情報](https://www.toshin.com/weather/detail?id=66124)
- [Yahoo!天気](https://weather.yahoo.co.jp/weather/jp/13/4410.html)
- [tenki.jp](https://tenki.jp/live/3/16/)
- [NHK天気情報](https://www.nhk.or.jp/kishou-saigai/pref/weather/tokyo/)

4.LangChainを使うメリットを比較

API直叩き LangChain
プロンプト管理 手動で書く必要あり PromptTemplateで再利用可能
会話履歴の保持 なし Memoryで文脈を理解
外部データの参照 APIを個別に呼ぶ必要あり RetrievalQAで簡単に実装
動的な意思決定 if 文だらけの処理 Agentsで自動的に適切なツールを選択
  • 例えば、「カスタマーサポートの問い合わせAIを作る」場合
    • ユーザー:「注文履歴を教えて!」
    • LangChain:「外部データベースにアクセス」
    • LangChain:「あなたの注文履歴はこちらです!」
    • → API直叩きではできない「データ検索+履歴保持+動的応答」が可能になります!

ではLangGraphとは?

LangGraphの概要

  • LangGraphとは?

    • LangChainを拡張し、複雑なワークフローを「グラフ構造」で直感的に管理・構築するフレームワーク
    • 特徴:
      • グラフベースのノード処理
      • 並列処理・条件分岐が可能
      • LLMの推論ステップを整理しやすい
  • LangGraphを使うメリット

    • 逐次処理ではなく、複雑なワークフローを整理
    • デバッグがしやすく、再利用可能
    • あとLangSmith[3]が便利
  • 例えば、「FAQの問い合わせ対応AI」を作る場合

    • LangChain だけ → if 文だらけで管理が大変[4]
    • LangGraph → 「質問の種類」に応じて適切なノードへ分岐
  • 参考になりそうなサイト

  • 以下デモ

ここでは、基本的なチャットボットのワークフローをLangChainとLangGraphで構築してみます!
LangGraphのサンプルコードをAnthropicからAzure OpenAIモデルにしたものです。
以下の構成で実装します:

from_part3
from typing import Annotated

- from langchain_anthropic import ChatAnthropic
+ from langchain_openai import AzureChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.messages import BaseMessage
from typing_extensions import TypedDict

from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode, tools_condition


class State(TypedDict):
    messages: Annotated[list, add_messages]


graph_builder = StateGraph(State)


tool = TavilySearchResults(max_results=2)
tools = [tool]
- llm = ChatAnthropic(model="claude-3-5-sonnet-20240620")
+ llm = AzureChatOpenAI(api_key="your_api_key", azure_endpoint="your_endpoint", azure_deployment="gpt-4")
llm_with_tools = llm.bind_tools(tools)


def chatbot(state: State):
    return {"messages": [llm_with_tools.invoke(state["messages"])]}


graph_builder.add_node("chatbot", chatbot)

tool_node = ToolNode(tools=[tool])
graph_builder.add_node("tools", tool_node)

graph_builder.add_conditional_edges(
    "chatbot",
    tools_condition,
)
graph_builder.add_edge("tools", "chatbot")
graph_builder.set_entry_point("chatbot")
memory = MemorySaver()
graph = graph_builder.compile(checkpointer=memory)

こちらでコンパイルしたグラフ構成を見るには以下のコードで確認できます!

from IPython.display import Image, display

try:
    display(Image(graph.get_graph().draw_mermaid_png()))
except Exception:
    # This requires some extra dependencies and is optional
    pass


ワークフローがどうなっているのか、とても理解しやすいと思います。
こちらを実行すると、記憶機能のあるチャットボットが確認できます!

config = {"configurable": {"thread_id": "1"}}
user_input = "こんにちは、元気ですか?私はジョンです。"
events = graph.stream(
    {"messages": [{"role": "user", "content": user_input}]},
    config,
    stream_mode="values",
)
for event in events:
    event["messages"][-1].pretty_print()
出力
================================ Human Message =================================

こんにちは、元気ですか?私はジョンです。
================================== Ai Message ==================================

こんにちは、ジョンさん!お会いできて嬉しいです。元気ですか?何かお話ししたいことや質問があれば、どうぞお気軽にお知らせください。
user_input = "私の名前を覚えていますか?"

# The config is the **second positional argument** to stream() or invoke()!
events = graph.stream(
    {"messages": [{"role": "user", "content": user_input}]},
    config,
    stream_mode="values",
)
for event in events:
    event["messages"][-1].pretty_print()
出力
================================ Human Message =================================

私の名前を覚えていますか?
================================== Ai Message ==================================

はい、ジョンさんという名前を覚えています。何か特別なことについてお話ししたいですか?

しっかりと動作することが確認できました!
公式のチュートリアルでは基本のチャットノードからノード・機能を追加していく体験ができます。
ここからさらに、Human in the roopの実装も解説されていました!
ぜひ皆さんも触ってみてはいかがでしょうか?

まとめ: LangChainとLangGraphを活用すると、AIエージェント構築・拡張がしやすい!

  • 今回の目標:

    • LangChainとLangGraphの基本的な内容を理解し、活用イメージを持つ
  • 簡単な技術説明:

    • LangChain: LLMアプリケーション開発を簡単にするフレームワーク
    • LangGraph: LangChainを拡張。マルチステップ・並列処理を効率的に構築できるワークフロー管理ツール
  • 個人の感想

LangChain LangGraph
シンプルな処理 得意 可能
分岐処理 if 文で実装が大変 グラフで簡単に整理
並列処理 できなくはない ネイティブサポート
複雑なワークフロー 状態管理が大変 グラフで自然に設計可能

こちらのサイトのLangGraphとLangChainを比較する図がわかりやすかったのでもしよければ参考にどうぞ!

最後に

なかなかLLMアプリ開発よく分からないと思っていましたが、LangChainとLangGraphの本やチュートリアルを見ていると、なんだか自分でも実装できそうとイメージがついてきて妄想が膨らみました!
今後はもう少し凝ったものの開発に挑戦したいです。
本当に初めて記事掲載ですが、良かったよって方・少しでも参考になったという方は「いいね/like」、また「ここ違うんじゃない?」とかありましたら気軽にコメントをいただけると励みになります!
最後までお読みいただきありがとうございました!!

脚注
  1. 通常のコードだと、関数を定義して順番に呼び出す必要がありますが、LCELを使うと「|(パイプ)」を使って直感的に記述できますね!他にも追加の処理を挟むのが簡単というメリットもあります。 ↩︎

  2. Tavily」は、AIエージェント専用に構築された検索エンジンです。クレジットカードの登録なしで、毎月最大1,000回まで無料利用が可能みたいなので使いやすいですね! ↩︎

  3. ここでの解説は省きますが、エージェントの中でどのような処理が行われているかトレースできる便利なサイト・機能です! ↩︎

  4. この表現は語弊を生むかもしれないですね。LangChainでもRunnableParallelという関数が標準でありますが、複雑なフローを管理するにはLangGraphがオススメというお話です! ↩︎

Discussion