State / Node / Edgeの3概念でグラフを組み立て、全パーツを統合してRAGシステムを完成させる。午前の部の集大成。
05_langgraph_basics.py
グラフ全体で共有するデータ。辞書に型を付けたもの
処理の単位。普通のPython関数。Stateを受け取り、更新したい値を辞書で返す
処理の順番を定義。add_edgeで繋ぐ
Session 02-03で書いたコードは「上から順に実行するだけ」のスクリプトだった。しかし実際のAIシステムでは「検索結果が不十分なら再検索する」「エラーが出たら別の処理に分岐する」といった条件分岐が必要になる。LangGraphはこうした複雑な処理フローを、State(データ)+ Node(処理)+ Edge(順序)の3要素だけで見通しよく定義できる。
class SimpleState(TypedDict): は「SimpleStateという名前の辞書で、question(文字列)とanswer(文字列)のキーを持つ」と定義しているdef greet(name): と同じlog_node は return {} で空辞書を返している。これは「Stateを何も変更しない」という意味。printで質問を表示するだけのノードanswer_node は return {"answer": response.content} で、Stateのanswerキーを更新しているStateGraph(SimpleState): 「SimpleStateを共有データとして使うグラフ」を新規作成add_node("log", log_node): "log"という名前でlog_node関数をグラフに登録add_node("answer", answer_node): "answer"という名前でanswer_node関数を登録set_entry_point("log"): 「最初に実行するノードはlogです」と指定add_edge("log", "answer"): 「logの次はanswerを実行」と接続add_edge("answer", END): 「answerの次は終了」と接続。ENDはLangGraphが提供する特殊な終了マーカーcompile(): 上の設定を確定し、実行可能なアプリケーションにする。コンパイル後に app.invoke() で実行できる06_rag_with_langgraph.py
このコードには Session 01 で確認したAPI接続、Session 02 で学んだChatOpenAI/Prompt Template/LCEL、Session 03 で体験した5つのRAGコンポーネント、そしてこのSession 04のLangGraphが全て含まれている。新しい要素は一つもない。既に学んだパーツを組み合わせているだけ。
retrieve_node: Stateからquestion(質問文)を取り出し → Retriever(Session 03のStep 5)に渡して検索 → 検索結果をdocumentsとしてStateに書き込むgenerate_node: Stateからdocuments(検索結果)とquestion(質問)を取り出す → documentsを改行で連結してcontextを作る → ChatPromptTemplate(Session 02のStep 2)でsystemメッセージに文書を埋め込む → LCEL(Session 02のStep 3)でLLMに渡す → 回答をanswerとしてStateに書き込む| コード | 学んだ場所 |
|---|---|
| PyPDFLoader, TextSplitter, FAISS, Retriever | Session 03 |
| ChatPromptTemplate, LCEL | Session 02 |
| StateGraph, add_node, add_edge | この演習の前半 |
PDFの内容に基づいた回答が返ってくれば成功。
SystemMessageを書き換えて、丁寧語やフランクな口調など異なるトーンで回答させてみる
generate_nodeの出力にdocumentsを含め、回答の根拠となった文書チャンクも表示する
質問リストをループで回し、同じグラフに複数回invokeする処理を書いてみる
午前の部はここで終了。午後はAI駆動開発(Claude Code)に入ります。