全6章20節 · テキスト講義

LangChain 基礎から応用まで

モデル、プロンプト、会話、検索、ツール、エージェントの役割と組み合わせを理解し、用途に合うLangChainの構成を判断できるようになる。

目次へ戻る

第1章 LangChainの概要

1. LangChainとは?

LangChainは何をするものか

LangChainは、大規模言語モデル(LLM)を利用するアプリケーションを組み立てるための、オープンソースのフレームワークです。LLMは、入力された文章などをもとに応答を生成するモデルです。LangChainは、そのモデルに何を渡し、どの情報や機能と組み合わせ、返ってきた結果をどう扱うかを、プログラムから組み立てるために使います。

アプリケーションとは、質問に答える画面や申請を受け付けるサービスなど、ある目的のために動くソフトウェアです。プログラムは、コンピューターへ処理の手順を伝えるものです。この教材ではプログラムを書かずに、LangChainがその手順の中で何を担うかを学びます。オープンソースとは、その仕組みを記したソースコードが公開され、定められた利用条件(ライセンス)のもとで利用・変更などができる形を指します。

LLMの「学習」と「利用」も分けておきます。学習は、大量の文章などから言葉の関係や応答の傾向を身につける準備の段階です。利用する段階では、与えられた入力をもとに続きを作ります。これを生成と呼びます。質問するたびにモデル全体を学習し直しているわけではありません。

新しい文章や画像などを作る仕組みの総称が生成AIです。LLMは、その中で主に言葉を扱うモデルです。この教材では文章のやり取りを中心に学ぶので、まず「文章を作るモデルを、アプリケーションの一つの部品として使う」と捉えてください。

たとえば「この文章を要約してください」と一度依頼するだけなら、モデル提供会社のAPI(プログラムからモデルを利用する入口)を直接呼び出しても実現できます。一方、「社内資料を探す」「見つかった箇所を渡す」「根拠がなければ回答を保留する」「前の会話を踏まえて追加の質問に答える」となると、生成以外の処理が増えます。LangChainが役立つのは、このような処理をモデルとつなぎ、アプリケーションとして扱いたいときです。

ここでいうフレームワークとは、開発によく使う部品や、それらの組み合わせ方を提供する仕組みです。LangChain自体が社内規程を知っているわけではありません。規程を検索できる仕組みや生成モデルを用意し、それらをつなぐ役割を受け持ちます。

チャット画面でAIを使う場合との違い

チャットサービスでは、人が画面に入力し、返ってきた文章を読みます。資料を渡す、追加の質問をする、結果を別の場所へ転記する、といった操作も人が行えます。LangChainを使う場合は、それらの一部をプログラム側の処理として組み立てます。利用者が毎回同じ指示を入力しなくても、アプリケーション側で回答方針や資料の渡し方をそろえられます。

社内規程の案内を例にすると、利用者は「出張の交通費はどう申請しますか」と質問します。アプリケーションは、関連する規程を取得し、その文章と質問をモデルへ渡して、回答を利用者に返します。利用者に見えるのは一つの応答ですが、内部には検索、情報の受け渡し、生成、表示という複数の段階があります。

LangChainを使えば、こうした部品を共通した扱い方で接続できます。ただし、質問を受けるWeb画面や利用者のログイン、規程そのものの管理まで、すべてが自動的に完成するわけではありません。LangChainはアプリケーション全体の中で、主にモデルを利用する処理を担当します。

理解の中心になる四つの要素

最初は、モデル、メッセージ、外部の情報、ツールの四つを分けると理解しやすくなります。モデルは応答を生成するものです。メッセージは、モデルへ渡す指示や質問、会話の記録です。外部の情報は、社内資料など、モデルにその場で参照させたい内容です。ツールは、資料検索やデータ照会など、アプリケーションが実行できる機能です。

モデルに「残りの有給休暇を教えて」と頼んでも、モデルだけでは本人の残日数を確定できません。実際の勤怠情報を取得するツールを用意し、その結果を受け取って説明文を作る必要があります。この場合、事実を取得するのは勤怠システムにつながる処理で、文章にして伝えるのがモデルの仕事です。LangChainはその受け渡しを組み立てます。

この区別をせずに「AIが調べた」「AIが実行した」とひとまとめにすると、どこで間違いが起きたのか分からなくなります。本教材では、何をモデルに任せ、何をプログラムやデータ側で決めるのかを、繰り返し説明します。

何が作れて、何が保証されないのか

LangChainを使うと、文章の要約や分類、必要項目の抽出、会話の継続、資料に基づく回答、外部ツールを使うエージェントなどを構成できます。これらは、モデルの呼び出しに情報や処理を組み合わせた使い方です。機能の名前を増やすよりも、「どの入力を、どの部品へ渡し、どんな結果として受け取るか」を押さえることが基本です。

LangChainを導入しても、モデルが常に正しい答えを返すわけではありません。検索対象が古ければ古い情報に基づく回答になりますし、質問に合う箇所を取得できなければ、必要な根拠を渡せません。モデルが作った文章を業務上そのまま利用できるかどうかは、別途確認する必要があります。

モデルが、根拠の無い内容をもっともらしい文章として作ることは、ハルシネーションと呼ばれます。たとえば資料を渡していないのに、存在しない社内規程の条番号を答えるような場合です。「自然に読める文章」と「根拠を確認できる回答」を分けることが、LangChainを学ぶ上でも大切です。

また、LangChainの公開された部品を利用することと、接続する生成APIや外部サービスの費用は別です。このテキストを読むためのAPI契約や環境構築は必要ありません。まず仕組みを理解し、実装するときに利用するモデルやサービスを選ぶ、という順序で学べます。実装とは、考えた仕組みを実際に動くプログラムなどにすることです。

この後の学習で扱うこと

この教材では、モデルへの入力と出力を理解した後、構造化出力、会話、RAG、ツール、エージェントへ進みます。RAGは資料を参照して回答する構成、エージェントは状況に応じてモデルがツールの利用を選ぶ構成です。応用では、LangGraphを使った処理の制御や、動作の評価・改善も扱います。

どの話題も、土台は「モデルを部品として利用し、必要な情報や処理につなぐ」という考え方です。次の節では、APIを直接使う方法や、名前の似た関連製品と比較しながら、LangChainを選ぶ意味をもう少し具体的に整理します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第1章 LangChainの概要

2. できること・使いどころ・関連する仕組み

モデルを使う方法は一つではない

前の節では、LangChainを「モデルと情報・機能をつなぐ仕組み」と説明しました。この節では、その仕組みを使う理由を、ほかの選択肢と比べて整理します。まず「生成モデルを使うこと」と「LangChainを使うこと」を分けて考えます。

ライブラリは、再利用できるプログラムの部品をまとめたものです。モデル提供会社のAPIを扱いやすくする専用の部品集は、SDKと呼ばれます。提供会社のSDKからモデルを直接利用する方法も、LangChainを通して利用する方法もあります。LangChainは、異なるモデルや周辺の処理を共通の考え方で組み合わせるための選択肢です。

たとえば、決まったモデルに一種類の文章を渡して要約を得るだけなら、直接APIを使う小さな処理で十分なことがあります。LangChainを使うと部品の整理や拡張がしやすくなる一方、LangChain自体の概念や、組み合わせる部品も学ぶ必要があります。どのアプリケーションにも無条件に必要なもの、という位置づけではありません。

複数のモデルを比較したい、資料検索を組み込みたい、会話やツールを同じ枠組みで扱いたい、といった場面では、共通の部品が役立ちます。「モデルの生成能力を増やすため」ではなく、「モデルを使う処理を組み立て、変更しやすくするため」と理解すると、導入の理由が明確になります。

LangChainが共通化する範囲

モデル提供会社ごとに、接続方法や応答の形式、追加機能は異なります。LangChainはモデルの呼び出し方やメッセージの表現などをそろえ、アプリケーション側が同じ考え方で扱えるようにします。このような部品の使い方や情報の受け渡しの取り決めを、インターフェースと呼びます。入力は部品へ渡す情報、出力はその部品から受け取る結果です。

ただし、共通の呼び方があることと、すべてのモデルが同じ能力を持つことは別です。あるモデルで使えるツール呼び出しや構造化出力が、別のモデルでは同じように動かない場合があります。入力できる量、応答速度、料金、対応するデータ形式も変わります。モデルを差し替える際には、接続だけでなく、利用している機能と回答の品質も確認します。

共通化は、差異を消す魔法ではありません。共通部分をそろえることで、何が差し替え可能で、何が提供会社固有なのかを見分けやすくする仕組みです。

LangChain・LangGraph・LangSmithの違い

LangChainは、モデルに指示を渡し、資料やツールと組み合わせるための中心の部品を提供します。モデルに次のツールの選択を任せる構成は、エージェントと呼ばれます。今は「どの機能を使うかをモデルが選べる」と捉え、詳しい動きは第5章で学びます。

LangGraphは、「資料があれば回答し、足りなければ追加の確認へ進む」など、処理の手順や途中の情報を細かく管理するための関連フレームワークです。LangChainのエージェントを動かす土台にも使われています。最初はLangChainから利用でき、独自の複雑な手順が必要になった段階で、LangGraphを直接扱う選択肢があります。

LangSmithは、モデルを使った処理の記録を観察したり、テスト用データで品質を比較したりするための関連サービスです。何をモデルへ渡したか、どのツールを利用したか、どこで時間や費用がかかったかを調べる役割があります。LangChainを使うための必須契約ではなく、評価や運用の際に組み合わせられます。

名前この教材での捉え方
LangChainモデルと情報・ツールを組み合わせる中心の部品
LangGraph複雑な状態と実行経路を明示的に制御する仕組み
LangSmith処理を観察し、品質を評価・比較する仕組み

周辺技術は、必要になってから関連づける

検索に使う保存先や、外部の機能を接続する仕組みなど、周辺の技術もあります。まずは、何を解決するために必要になるかを理解してから、その名前を覚えれば十分です。LangChainで何かを作るために、関連する製品を一度にすべて用意する必要はありません。

周辺技術を先に大量に学ぶより、必要になる場面に沿って学びます。検索を扱う第4章では資料の保存・取得の部品を、ツールを扱う第5〜6章では外部の機能とのつなぎ方を説明します。まずは、この節のLangChain・LangGraph・LangSmithの三つの役割を押さえてください。

古い教材を読むときの注意

LangChainは更新が続いており、古い教材と現在の公式資料で、部品の名前や組み合わせ方が違うことがあります。バージョンは、ソフトウェアの版を示す番号です。本教材は、確認時点の1.x系の公式資料に沿って説明します。古い名前を最初から覚える必要はありません。

一方、指示を渡す、会話を入力に含める、関連資料を検索する、ツールの結果を受け取る、という考え方は、名前が変わっても理解の土台になります。最初はAPI名の暗記よりも、各部品の役割を理解することを優先します。次の章では、その土台になる生成APIの入出力を説明します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第2章 生成APIとLangChainの基本部品

3. 生成API・トークン・ツール呼び出しの基本

APIは、アプリケーションからモデルを利用する入口

APIは、プログラム同士が決まった形式で情報をやり取りするための入口です。生成AIのAPIでは、アプリケーションが指示や質問を送り、モデルが生成した応答を受け取ります。チャット画面で手入力する代わりに、アプリケーションの処理から利用できるようにしたもの、と考えると分かりやすくなります。

APIという言葉は、外部のサービスを呼ぶ窓口にも、ライブラリの部品を使う窓口にも使われます。たとえばLangChainの部品へ「質問を渡す」操作と、その部品が外部の生成サービスへ通信することは、別の段階です。部品を使うたびに、必ず外部へ通信するわけではありません。

モデルへの一回の呼び出しには、入力となるメッセージ、利用するモデル、生成に関する設定などが含まれます。返ってくるのは文章だけとは限りません。ツールを呼び出す要求や、項目ごとに整理されたデータ、利用量などの付随情報が含まれることもあります。LangChainでは、こうした入出力をモデルやメッセージの部品として扱います。

社内規程について回答させたい場合、質問文を送るだけでは、未公開の規程はモデルの入力に入りません。「モデルが社内のことを分かっているはず」と考えず、必要な情報をアプリケーションから渡すことが出発点です。

トークンは、入力と出力の量を数える単位

モデルは文章を内部で細かな単位へ分けて扱います。この単位をトークンと呼びます。トークン数は文字数や単語数と同じではなく、言語やモデルの分割方法によって変わります。「日本語一文字が必ず一トークン」のような換算はできません。

入力には、利用者の今回の質問だけでなく、回答方針、過去の会話、参照資料、ツールの説明や結果なども含まれます。質問が一行でも、そのほかに長い資料を渡せば、入力全体のトークン数は大きくなります。出力も利用量の対象になり、提供会社やモデルによって数え方や料金体系が異なります。

コンテキストウィンドウは、モデルが一度の処理で扱える情報量の上限です。入力と出力にそれぞれ制約があるため、「大きな資料を渡せるモデルなら、いくらでも長く回答させられる」とは限りません。会話や資料の量を管理する理由は、費用だけでなく、この上限にもあります。

コンテキストは、モデルがその呼び出しで参照する指示や情報の全体を指します。今回の質問に加えて、方針・履歴・資料などがその中身です。コンテキストウィンドウは、それらを扱う量の上限です。入力と出力で枠を共有するモデルでは、入力を増やすと出力に残せる枠も変わります。具体的な上限と数え方は、使うモデルで確認します。

同じ指示でも応答が変わることがある

生成モデルの応答は、一般的な計算機の四則演算のように、いつでも同じ結果になるものではありません。同じ質問でも表現が変わったり、含まれる項目が変わったりすることがあります。生成の設定を調整して変動を抑えられる場合もありますが、それだけで内容の正しさが保証されるわけではありません。

このため、アプリケーションでは「文章として自然か」と「必要な条件を満たすか」を分けて考えます。規程の回答なら、読める日本語であることに加え、根拠の資料が合っているか、適用条件を落としていないかが必要です。LangChainの構造化出力や評価は、このような確認を組み立てるために使えます。

Function Callingで返るのは、実行の要求

プログラムの中で、名前を付けてまとめた処理を関数と呼びます。関数へ渡す条件や材料が引数、処理から受け取る結果が戻り値です。「規程を検索する」という関数へ「交通費」という引数を渡し、該当する文章を戻り値として受け取る、と考えてください。ここでは関数の書き方を知る必要はありません。

Function Calling、またはツール呼び出しは、モデルが利用したい機能の名前と引数を、決まった形式で返す仕組みです。たとえばモデルが「規程を検索する機能へ、交通費という語を渡したい」と判断したとき、検索するための要求を返します。

要求が返った時点で、検索が実行済みとは限りません。アプリケーションが、その機能を実行してよいか、引数が妥当かを確かめ、実際に検索を行います。検索結果をモデルへ返すことで、その内容に基づいた説明を生成させられます。LangChainではこの流れをツールやエージェントとして扱います。

この節では、APIには「文章を受け取る呼び出し」だけでなく、「次に実行する機能の要求を受け取る呼び出し」もあると押さえておけば十分です。ツールの詳細は第5章で説明します。

LangChainを挟んでも、API側の条件は残る

LangChainは接続を扱いやすくしますが、APIの認証、利用回数の制限、対応機能、通信障害まで無くすものではありません。応答が返らなかった場合は、入力の作り方の問題なのか、認証や利用制限の問題なのか、外部サービスの一時的な問題なのかを分けて考えます。

外部サービスでは、利用を許可された接続かを確かめるためにAPIキーなどを使う場合があります。APIキーは、サービスを利用するための秘密の認証情報です。また、短時間に送れる要求の数を制限する仕組みをレート制限と呼びます。この教材では取得作業は行いませんが、接続時の問題が回答内容の問題とは別であることを理解するために、これらの言葉を知っておくと役立ちます。

一つの質問が一回のAPI呼び出しで終わるとも限りません。ツールの結果を受けてモデルへ再度問い合わせたり、検索用の質問を作り直したりすると、呼び出し回数は増えます。利用者から見える一往復と、内部のモデル呼び出し回数を分けることが、後のエージェント理解にもつながります。

ここまでで、モデルへ依頼を送り、応答を受け取る全体像を確認しました。次の節では、このやり取りをLangChainのモデル、メッセージ、プロンプトという部品でどう表すかを学びます。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第2章 生成APIとLangChainの基本部品

4. モデル・メッセージ・プロンプト

モデル・メッセージ・プロンプトの関係

前の節では、APIを通してモデルへ入力を送り、結果を受け取る流れを学びました。この節では、その入力と結果をLangChainで扱うための部品を整理します。

モデルは応答を生成する部品で、メッセージはモデルとやり取りする情報の単位です。プロンプトは、モデルへ渡す指示や文脈を含む入力の構成を指します。これらを区別すると、「モデルを選ぶこと」と「どの情報を渡すかを決めること」を別々に考えられます。

LangChainでは、init_chat_modelなどを通して会話モデルを用意し、invokeで入力を渡して応答を受け取れます。ここでモデルを用意するとは、学習を一から行うことではなく、既存のモデルを呼び出すための部品を設定することです。接続先は外部APIの場合も、ローカルのモデル提供サービスの場合もあります。

等幅の文字で示した名前は、LangChainの部品や操作を指す目印です。init_chat_modelは「使うモデルを準備する」、invokeは「入力を渡して実行する」と読めば、Pythonを知らなくても説明を追えます。会話モデルは、役割付きのメッセージを受け取って応答するモデルです。この教材では、名前の綴りの暗記より、準備と実行の違いを押さえます。

メッセージには内容だけでなく役割がある

会話の入力は、単に文章を連結したものとしてではなく、役割付きのメッセージとして表現できます。代表的な役割は、全体の振る舞いを示すsystem、利用者の発言を示すhumanまたはuser、モデルの応答を示すaiまたはassistantです。ツールから返った情報は、toolの役割で扱います。

LangChainには、方針を表すSystemMessage、利用者の発言を表すHumanMessage、モデルの応答を表すAIMessage、ツールの結果を表すToolMessageなどがあります。同じ「交通費」という文字が含まれていても、それが利用者の質問なのか、資料の一部なのか、ツールが返した結果なのかで意味が異なります。役割を保つことは、その区別をモデルへ伝えるために役立ちます。

systemに書いた方針も、アクセス権限を強制するプログラムそのものではありません。「社外秘を答えない」と指示するだけで機密保護が完成するわけではなく、そもそも見せてよい資料だけを渡す制御が別途必要です。

プロンプトは、方針と今回の入力を整理する

社内規程の案内なら、共通の方針は「提示した資料の範囲で答える」「根拠がなければ不明と伝える」、今回の入力は「出張の交通費はどう申請するか」という質問です。これらを一つの長い文章に混在させるより、共通の方針と毎回変わる内容を分けて構成すると、どこを変更したかが明確になります。

ChatPromptTemplateは、役割付きメッセージや差し込む値を、再利用できるひな型として表す部品です。「質問」という差し込み先へ今回の質問を入れ、「参考資料」という差し込み先へ検索した文章を入れる、といった組み立てに使います。ひな型を作ること自体は、モデルへの送信や生成ではありません。

ひな型の目的は、指示を長くすることではなく、入力の構造を一定にすることです。同じ仕事の質問でも、あるときだけ根拠資料を渡し忘れる、回答形式の指示が抜ける、といったばらつきを減らせます。ただし、ひな型へ入れる情報が誤っていれば、その誤りまで修正してくれるわけではありません。

入力の構成を、文章で示すと次のようになります。これは仕組みを説明するための例で、実際のAPIへ送信した記録ではありません。

入力の役割内容の例
共通の方針提示した資料だけを根拠に、申請方法を説明する。確認できない条件は不明と伝える。
今回の資料検索で取得した規程の本文と、その出典。
今回の質問日帰り出張の交通費は、どのように申請しますか。

質問だけを変えても、回答方針と資料の受け渡し方をそろえられることが、ひな型を使う意味です。資料の内容を変更すること、方針を変更すること、モデルを変更することは、それぞれ異なる変更として比較できます。

応答は文章以外の情報も持つ

会話モデルから返るAIMessageには、生成した本文に加え、ツールの要求や利用量などが含まれる場合があります。本文は常に単純な文字列とは限らず、画像などを含む形式では複数の内容ブロックになることもあります。画面へ表示する文章と、処理に必要な元のメッセージを分けて扱うことが大切です。

とくにツールを使う会話では、応答を文章だけにして保存すると、要求のIDや付随情報が失われることがあります。IDは、対象を識別するための番号や文字列です。LangChainのメッセージを使う意味は、見える文章だけでなく、モデルとのやり取りに必要な構造を保つことにもあります。

設定の変更と、指示の変更は分けて考える

モデルには、出力の長さや生成の変動に関する設定があり、利用できる項目は接続先によって異なります。一方、プロンプトは、何を答えるか、何を根拠にするか、どの形で返すかという仕事の条件を伝えます。長さの上限を変えることと、要約の観点を変えることは、別の操作です。

思った応答にならない場合は、「必要な情報が入力に入っているか」「指示が曖昧でないか」「選んだモデルが必要な機能に対応しているか」を順に考えます。次の節では、自然な文章として受け取るだけでなく、アプリケーションが使える項目として結果を受け取る方法を説明します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第2章 生成APIとLangChainの基本部品

5. 構造化出力とスキーマ

文章として読む結果と、プログラムが利用する結果

前の節では、モデルからメッセージを受け取る流れを説明しました。回答を人が読むだけなら、自然な文章で返せば十分な場合があります。しかし、問い合わせの分類や申請項目の抽出では、後続の処理が使える形で受け取りたくなります。そこで利用するのが構造化出力です。

たとえば「来週大阪へ出張します。交通費の申請方法を知りたいです」という入力から、分類、行き先、質問内容を取り出すとします。文章で「これは出張に関する問い合わせで……」と返されるより、分類は「出張」、行き先は「大阪」、質問内容は「交通費の申請方法」と分かれている方が、振り分けや保存に利用しやすくなります。

構造化出力は、このように項目と形式を決めて結果を受け取る方法です。生成モデルを使う範囲は同じですが、自由な文章を返す場合よりも、アプリケーションとの接続を明確にできます。

スキーマは、結果に求める形の定義

どんな項目があり、どんな値を入れるかを定義したものをスキーマと呼びます。項目名だけでなく、文字列なのか数値なのか、値が無いことを許すのか、選べる分類は何か、といった条件を表せます。文字列は「大阪」のような文字の並び、数値は計算に使える数です。こうした値の種類を型と呼びます。

JSONは、「項目名と値」の組などを使ってデータを表す書式です。たとえば{"行き先": "大阪", "出張日": null}は、行き先が大阪で、具体的な出張日は値が無いと表した例です。nullは値が無いことを表します。JSON Schemaは、そのJSONにどんな項目や型を求めるかを書くための規格です。データ本体と、その形の定義を区別してください。

ここで大切なのは、不明な項目も表現できるようにすることです。入力に具体的な出張日が書かれていないのに、必ず日付を埋めることを求めると、推測が混ざるおそれがあります。「入力にない場合は未確定として扱う」という設計なら、不明なことを不明なまま次の処理へ渡せます。

スキーマは項目の説明書でもあります。「分類」という名前だけでは、人事・経理・その他なのか、出張・休暇・給与なのか分かりません。選択肢や説明を具体化することで、モデルへの要求と受け取る側の期待をそろえます。

先ほどの問い合わせを、説明用の項目へ整理した例が次の表です。入力には「来週」という範囲だけが書かれており、具体的な日付は未確定としています。

項目求める値の形整理した結果の例
分類決めた分類から一つ出張
行き先文字列、または未確定大阪
出張日日付、または未確定未確定
質問内容文字列交通費の申請方法

後続の処理は「分類が出張なら担当窓口を選ぶ」「日付が必要な手続きなら追加確認する」といった判断ができます。自由な文章の言い回しを毎回読み取るより、何を条件として処理を進めるかを明示しやすくなります。

JSONに見えること、形式が合うこと、正しいこと

モデルに「JSONで返してください」と文章で指示するだけの方法と、スキーマを指定して結果を検証する方法は同じではありません。JSONらしい文字列でも、必須の項目が抜けていたり、数値の項目へ文章が入っていたりすれば、後続の処理で扱えません。

さらに、形式の検証に通っても、内容が正しいとは限りません。行き先が文字列として「京都」になっていれば、型は正しくても、元の文章が大阪への出張なら抽出内容は誤っています。構造の検証と、入力や根拠に照らした意味の確認を分ける必要があります。

申請の可否も同様です。結果に「承認可能」という項目が入ったからといって、業務上の承認が行われたことにはなりません。モデルの分類結果、業務ルールによる判定、人による承認は、それぞれ別の段階です。

LangChainでは、どこで構造化するのか

LangChainでは、with_structured_outputでスキーマを指定し、モデルの応答を項目として受け取る構成を作れます。Pydanticという、データの形や値を検査するライブラリも利用できます。「Pydanticのモデル」はデータの項目を定義するもので、文章を生成するLLMとは別の意味の「モデル」です。

内部では、提供会社の構造化出力機能を利用する方法や、ツール呼び出しの形式を利用する方法があります。使える方法や検査のされ方は、スキーマの表し方と接続先によって異なります。ここでは「形を指定する」「結果を検査する」「意味を確認する」という役割を押さえます。エージェントで最終出力の形を指定する方法は、第14節で、その仕組みを学んでから扱います。

失敗を扱えることも、構造化の利点

応答を解釈できない場合や、必要な項目がそろわない場合は、その結果を無理に利用せず、追加の確認や保留へ進めます。再度モデルへ依頼する方法もありますが、繰返せば必ず正しくなるわけではありません。回数の上限と、失敗した場合の扱いを決めておきます。

構造化出力を学ぶ意味は、モデルにきれいなJSONを書かせることだけではありません。何を受け取れると処理を進められ、何が不足すると止めるべきかを明確にすることにあります。次の節では、このような部品を順に組み合わせるChainとRunnableを説明します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第2章 生成APIとLangChainの基本部品

6. Chain・Runnable・LCEL

Chainは、複数の処理をつないだ流れ

これまでに、入力を作るプロンプト、応答を生成するモデル、結果を項目に整理する構造化出力を学びました。この節では、それらを一つの処理の流れとしてつなぐ考え方へ進みます。入力と出力の種類が曖昧なら、第5節の型とスキーマが土台になります。

Chainは、ある処理の出力を次の処理の入力へ渡す、一連の流れです。たとえば、質問を受け取り、プロンプトを組み立て、モデルへ送り、応答から表示用の文章を取り出す処理が考えられます。ひとつのモデルを呼ぶだけでも、前後には入力と出力を整える段階があります。

この場合、どの順で処理するかは開発者が決めています。モデルは与えられた入力に応答しますが、プロンプト作成の前に出力整形を行う、といった順序変更を自分で決めるわけではありません。この決まった流れと、後に扱うエージェントの動的なツール選択を区別しておきます。

Runnableは、部品を共通の扱い方で実行するための仕組み

LangChainには、Runnable(ランナブル)という共通の実行インターフェースがあります。第2節で説明した、部品を使うための取り決めの一種です。モデルやプロンプトなど、Runnableの約束に対応した部品を、「入力を渡し、出力を受け取るもの」として共通の方法で扱えます。

ただし、共通なのは呼び方であり、入力や出力の種類がすべて同じになるわけではありません。プロンプトの部品は差し込む値を受け取り、モデルへ渡す入力を返します。会話モデルはメッセージを受け取り、応答のメッセージを返します。出力を整える部品は、そのメッセージから文章などを取り出します。

つなぐときには、前の部品が返すものを、次の部品が受け取れることが必要です。文章を想定する場所へ、複数の項目をまとめたデータをそのまま渡すなど、入出力がかみ合わなければ、流れは成立しません。前の節で学んだ型の違いも、つなげるかどうかに関わります。

部品受け取るもの次へ渡すもの
プロンプト質問、参考資料などの値役割付きメッセージとして組み立てた入力
会話モデル組み立てた入力AIMessageなどの応答
出力の変換モデルの応答表示に使う文字列など

この表の右側を、次の行の左側へ渡すのが基本の接続です。たとえば最後に文章を取り出した後、その文字列に対してさらに別の分類を行うなら、分類する部品がその形式を受け取れるかを確認します。

LCELは、組み合わせを表す記法

LCELはLangChain Expression Languageの略で、Runnableを組み合わせて処理の流れを表すための記法です。たとえばprompt | model | parserという形は、プロンプトを作り、モデルで生成し、その結果を整える順序を表します。縦棒は、前の出力を次へ渡す組み合わせとして読みます。

この式のpromptは入力のひな型、modelは会話モデル、parserは結果を読み取って変換する部品の名前です。parser(パーサー)は、モデルの応答から文章を取り出すなどの役割を持ちます。回答の事実確認まで自動的に済ませるものではありません。

式は部品をつなぐ順序を表します。実際に処理を動かすには、組み立てた流れへ入力を渡します。LCELは、決まった入出力の処理を組み合わせる方法です。後の第5章では、次のツールをモデルが選ぶエージェントや、処理の経路を細かく決めるLangGraphへ学習を広げます。

invoke・batch・streamは、結果の受け取り方の違い

invokeは、一つの入力について実行し、結果を受け取る基本の方法です。batchは、複数の入力をまとめて扱うための方法です。たとえば複数の問い合わせを分類するとき、それぞれに同じ処理を適用できます。batchを使うことが、外部APIの一回の課金や一回の通信を意味するわけではありません。

streamは、結果を途中から順次受け取るために使います。文章が少しずつ画面に現れるチャットの動作が一例です。最初の表示を早くできる場合がありますが、生成する情報が減るわけではなく、すべての処理時間や費用が必ず減るわけでもありません。途中の部品が結果をまとめてから返す場合は、その段階で待ち時間が生じます。

途中で受け取る情報は、まだ完成していない場合があります。文章を少しずつ画面へ出すことと、構造化した項目やツールの引数が確定したと判断することは別です。後続の処理に使う値は、必要な情報を受け取り、形や内容を確かめてから利用します。

非同期の実行にはainvokeなどがあります。これは、通信などを待つ間にほかの処理を進められるようにする仕組みです。モデルの回答能力を変える機能ではなく、アプリケーション側の実行方法を変えます。

固定の流れを理解することが、応用の土台になる

固定の流れには、どの処理が行われたかを追いやすい利点があります。入力の差し込みで失敗したのか、モデルとの通信で失敗したのか、結果の変換で失敗したのかを、部品ごとに考えられます。検索や生成を組み合わせるRAGでも、まず固定の流れを理解すると、どこで品質が変わるかを調べやすくなります。

ここまでで、入力を作り、モデルへ渡し、結果を受け取る基本がつながりました。次の章では、この一回の流れを会話の中で利用するために、過去の情報をどのように保持して渡すのかを説明します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第3章 会話とメモリ

7. 会話履歴と短期メモリ

会話を続けるには、前の発言が入力に必要になる

第2章では、一回の入力から応答を受け取る流れを学びました。会話では、その流れを繰り返し、過去のやり取りも必要に応じて入力へ加えます。記録の基本の形には、第4節の役割付きメッセージを使います。

利用者が「大阪出張の申請方法を教えて」と聞き、回答の後に「日帰りの場合は?」と質問したとします。二つ目の質問だけでは、何の日帰りなのかが分かりません。人は直前の会話から補えますが、モデルにも、その会話を入力として与える必要があります。

同じモデルを繰り返し呼ぶだけで、以前のやり取りを自動的にすべて覚えてくれると考えてはいけません。会話を継続するための情報は、アプリケーション側で保持し、利用する仕組みに応じて次の入力へ含めます。画面に過去の発言が表示されていることと、その発言がモデルの入力に入っていることも別です。

会話履歴は、役割と順序を持つデータ

会話履歴には、利用者の質問とモデルの応答を、役割付きメッセージとして順に保持します。ツールを利用した場合は、その要求と結果も含めて扱います。単に「前に出張について話した」という一文を保存する場合と、やり取りを元の構造で保存する場合では、保持できる情報が異なります。

モデルへの入力は、共通の回答方針、必要な履歴、今回の質問などから構成されます。過去の応答は、会話の文脈としては有用ですが、事実として常に正しいとは限りません。以前の回答が誤っていた場合、その誤りを繰り返さないよう、現在の資料や訂正情報を踏まえて扱う必要があります。

LangChainの短期メモリとthread

状態は、処理を続けるために持っておく情報のまとまりです。ここでは、過去のメッセージや、今どんな相談をしているかが当てはまります。メモリは、過去のやり取りに関する情報を保持し、次の処理で使う仕組みです。モデル本体を追加学習することとは分けて考えます。

LangChainのエージェントでは、会話履歴などを状態として管理し、checkpointer(チェックポインター)を組み合わせて会話単位で保持できます。checkpointerは、処理の途中や終了時の状態を記録する仕組みです。前回の状態を復元することで、次のやり取りへつなげます。エージェントの動作自体は第14節で扱いますが、ここでは会話の状態を扱う仕組みに注目します。

この会話のまとまりをthread(スレッド)と呼び、thread_idという識別子で区別します。同じ利用者でも、出張申請の相談と採用に関する相談を別のthreadにすれば、それぞれの会話を分けて扱えます。逆に、会話を続けたいのに毎回別のIDを付けると、過去の状態とつながりません。

threadのIDは、本人確認そのものではありません。IDを知っているだけで別の人の履歴を読める設計にしてはいけません。アプリケーション側で、その利用者がその会話を参照してよいかを確認する必要があります。LangChainによる状態管理と、利用者の認証・権限管理を区別します。

認証は「その人が誰か」を確認すること、認可は「その人が何をしてよいか」を決めて確認することです。ログインできた利用者でも、ほかの人の会話を読めるとは限りません。この違いは、後に資料検索やツールを利用するときにも必要になります。

保存先によって、保持できる期間が変わる

起動して動いているプログラムの実行単位を、プロセスと呼びます。実行中だけ使う記憶領域に情報を置く場合と、ファイルやデータベースへ書き残す場合では、終了・再起動した後の扱いが違います。データベースは、情報を整理して保存・取得するための仕組みです。

メモリ上に状態を置く方法では、同じプロセスが動いている間は会話を継続できても、再起動すると失われることがあります。データベースなどへ保存するcheckpointerを使うと、プロセスを越えた再開を構成できます。短期メモリという名前は、必ず短時間で消えるという意味ではなく、主に一つのthreadの範囲で使う情報であることを指します。

「アプリケーションを再起動したら会話を忘れた」という問題は、モデルの知能の問題ではなく、状態の保存先や復元方法の問題かもしれません。会話の仕組みを、生成、状態、保存の三つに分けて考えると、原因を見つけやすくなります。

たとえば一回目の質問と回答を「出張相談の状態」として保存し、二回目の「日帰りの場合は?」で同じ状態を取り出します。その履歴を今回の入力に含めることで、何の相談が続いているかをモデルへ伝えられます。保存しただけでモデルへ自動的に伝わるのではなく、保存・復元・入力への反映がつながって会話になります。

履歴は多ければよいとは限らない

会話が長くなるほど、モデルへ渡す情報の量も増えます。入力の上限に近づくだけでなく、関係の薄い過去の話題が混ざり、今回の質問に必要な条件が埋もれることがあります。また、モデルへ渡す情報が増えることで、時間や費用にも影響します。

そのため、履歴を保存することと、保存した履歴を毎回すべて渡すことは分けて設計します。直近のやり取りだけを使う、古い部分を要約する、必要な条件だけを残す、といった方法があります。ただし、要約で日付や例外条件を失う可能性もあります。次の節では、保存と入力の範囲をもう少し広く整理します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第3章 会話とメモリ

8. 長期メモリとコンテキストの管理

保存されている情報と、モデルが今見ている情報

前の節では、一つの会話の状態を保存する仕組みを学びました。ここでは、保存した情報のうち何を今回の入力へ渡すかと、別の会話でも使う情報をどこへ置くかを分けて考えます。

モデルが一回の生成で参照する入力全体を、ここではコンテキストと呼びます。回答方針、今回の質問、会話履歴、検索した資料、ツールの結果などが含まれます。アプリケーションのどこかにデータを保存していても、その情報を今回のモデル入力へ渡さなければ、モデルはその内容を参照できません。

このため、「覚えている」という言葉には二つの意味が混ざります。一つは、アプリケーションが情報を保存していること。もう一つは、今回のモデル呼び出しでその情報を参照できることです。メモリの設計では、何を残すかだけでなく、いつ取り出し、どの範囲を渡すかも決めます。

短期メモリと長期メモリは、使う範囲が違う

短期メモリは、主に一つの会話や処理のまとまりに属する状態です。「今は大阪出張の交通費について相談している」という文脈が当てはまります。前の節で説明したcheckpointerは、このthreadに属する状態を保存・復元するために利用します。

長期メモリは、別の会話でも再利用したい情報です。たとえば「回答は簡潔にしてほしい」という利用者の希望は、会話が変わっても使いたいかもしれません。LangChainの関連基盤では、Store(ストア)という保存・取得の仕組みを利用できます。利用者や組織ごとの区画に当たる「名前空間」と、その区画内で項目を見つけるための「キー」などで情報を整理します。

ここでのキーは、保存した項目を見つけるための名前です。第3節のAPIキーはサービスへ接続するための秘密の認証情報で、役割が異なります。同じ言葉が出てきても、何を識別し、何のために使うかを見ると区別できます。

短期・長期という名前は、主に情報を使う範囲の違いです。長期メモリでも、保存先が実行中だけの記憶領域なら再起動で失われます。会話をまたぐことと、アプリケーションの再起動をまたいで保存できることは、別々に確認します。

長期メモリを作ることは、モデル本体を追加学習することとは異なります。情報を外部に保存し、必要なときに取り出して入力へ含める構成です。保存内容を更新したり削除したりできるのは、この外部データとしての性質によります。

情報の例使う範囲と役割
いま大阪出張について相談している今回の会話の状態。短期メモリとして会話を続ける。
回答は簡潔にしてほしいという本人の希望別の会話でも使う情報。長期メモリとして必要時に取り出す。
現在有効な出張規程回答の根拠となる組織の資料。次章で学ぶ資料検索の対象。

何でも保存すると、誤りも長く残る

会話中にモデルが「この人は営業部だろう」と推測しただけなのに、それを本人の確定情報として保存すると、次の会話でも誤った前提が使われます。利用者が明示した事実、システムから確認できた事実、モデルの推測は区別する必要があります。

長期的に残す情報には、確認した時点、根拠、更新の可否が重要です。部署や勤務形態のように変わる情報を、一度保存したから永久に正しいと扱うことはできません。記憶を増やす機能だけでなく、訂正する、期限を設ける、不要になったものを消すという扱いも必要です。

コンテキストの選択には、目的がある

「日帰りの場合は?」という追加質問では、直前の出張相談を渡す必要があります。しかし、昨日の別件の相談全文まで渡す必要はありません。一方、申請の例外条件が前の会話で確定しているなら、その条件を落とすと誤った回答になります。単純に古い順で切るだけでは、必要な情報が欠ける場合があります。

直近の会話を残す方法は単純ですが、以前に決まった条件を失いやすい面があります。要約は入力を短くできますが、要約自体に省略や誤りが入り得ます。重要な条件を項目として状態へ保持する方法は、内容を明示しやすい一方、どの項目を残すかの設計が必要です。これらは目的に応じて組み合わせます。

会話の記憶と、資料の検索は役割が違う

利用者が何を相談しているかを保つことと、最新の社内規程を調べることは同じではありません。会話の記憶は質問の文脈を補い、規程の検索は回答の根拠を補います。以前の会話に出てきた規程の説明が、現在も有効だとは限らないため、根拠資料の更新は別に扱います。

長期メモリに保存した情報を探す際にも、資料検索と似た方法を使う場合があります。仕組みが一部重なっていても、「利用者の希望を思い出すためか」「規程の根拠を取得するためか」という目的を分けると、保存や更新の方針を決めやすくなります。

次の章のRAGは、この「必要な外部情報を検索して入力へ加える」構成です。短期メモリ、長期メモリ、RAGは同時に使えますが、それぞれ何を保存・検索し、何のためにモデルへ渡すのかを分けて理解すると、混乱せずに組み合わせられます。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第4章 RAGによる資料の活用

9. RAGとは? 検索してから回答する仕組み

RAGは、検索した情報を使って回答する構成

第3章では、過去の会話を入力に含めて、相談の文脈を保つ方法を学びました。この章では、モデルへ渡す情報を、会話以外の社内資料などへ広げます。

RAGはRetrieval Augmented Generationの略で、必要な情報を検索し、その結果をモデルの入力へ加えて回答を生成する構成です。Retrievalは情報の取得、Generationは生成を意味します。LangChainの機能名一つを指すのではなく、検索と生成を組み合わせるアプリケーションの作り方です。

たとえば、出張の交通費に関する質問を受けたとき、まず社内規程から関連する箇所を検索します。その文章を質問と一緒にモデルへ渡し、「この資料に基づいて説明してください」と依頼します。モデルの一般知識だけに頼らず、今回渡した資料を回答の根拠として使うことを目指します。

このとき、モデルが社内規程を恒久的に学習したわけではありません。今回の呼び出しの入力として参照しています。次の質問で別の資料を渡せば、その資料を参照する構成になります。

資料を用意する段階と、質問へ答える段階

RAGには、質問が来る前に資料を検索できる形へ整える段階と、質問が来てから関連箇所を取り出して回答する段階があります。ここを分けると、次の節から学ぶ部品が、どの場面で働くか分かりやすくなります。

段階行うこと次の段階へ渡すもの
事前の準備資料を読み、検索しやすいまとまりに分け、検索用に登録する。検索できる資料と、出典などの情報。
質問時の検索今回の質問に関連する箇所を取得する。回答の参考にする文章と出典。
質問時の生成質問、取得した文章、回答方針をモデルへ渡す。資料を根拠に作成した回答。

同じ資料を使う質問が来るたびに、全資料の読み込みや登録からやり直す必要はありません。資料の内容が更新されたときには、事前に用意した検索対象へ、その変更を反映します。

検索することと、回答を作ることは別の段階

質問時の基本的な流れは、質問を受ける、関連する資料を取得する、取得した資料と質問で入力を作る、モデルが回答する、という順序です。LangChainでは、資料の読み込みや検索の部品に、これまで学んだプロンプトとモデルを組み合わせます。資料の表し方は第10節、検索の仕組みは第11節で詳しく説明します。

検索だけなら、資料の候補一覧を返す検索システムです。RAGでは、取得した情報をモデルへ渡し、利用者の質問に合わせた説明へ変換する段階が加わります。検索で正しい資料を取得できなければ、モデルの文章が自然でも回答に必要な根拠が不足します。

反対に、正しい資料を取得していても、モデルが条件を読み落とすことがあります。このため、RAGの品質は「検索がうまくいったか」と「資料から適切に回答したか」に分けて考えます。

説明用の架空の規程に「交通費は精算システムから申請する。領収書がある場合は添付する」とだけ書かれているとします。この文章を検索できたなら、申請先と添付については説明できます。しかし、申請期限はこの記述からは確認できません。

この場合の回答は、「精算システムから申請し、領収書がある場合は添付します。期限は提示資料に記載がないため確認が必要です」のように、資料で分かることと、分からないことを分けた形になります。「通常は一週間以内だろう」と補うと、検索した根拠から離れてしまいます。

なぜ資料を全部渡さずに検索するのか

資料が短く少数であれば、全文を直接モデルへ渡す方法もあります。しかし、多くの文書を毎回すべて渡すと、入力の上限や時間、費用の問題が生じます。無関係な説明が増えることで、必要な条件が埋もれる場合もあります。質問に関係する部分を絞って渡すことが、検索を組み込む理由です。

ただし、絞り込みは必要な情報を落とす危険も伴います。「交通費の通常ルール」は取得できても、「特定の勤務区分の例外」が別の場所にあり、取得できないかもしれません。RAGは情報を選ぶ構成であるため、何を残し何を落としたかが品質に直結します。

RAGとファインチューニングの違い

RAGは、外部にある情報を取得してモデルの入力へ含める方法です。ファインチューニングは、学習を通してモデルのパラメーターを調整する方法です。資料を更新して検索対象に反映したい場合と、特定の応答傾向や仕事の振る舞いを学習させたい場合では、目的が異なります。

ここでのパラメーターは、学習によって調整されるモデル内部の数値です。質問ごとに渡す資料や、出力の長さなどの利用時の設定とは別です。RAGは今回参照する資料を変え、ファインチューニングは学習によってモデル内部を調整する、と捉えると、第1節の「学習と利用」の違いにつながります。

両者は排他的ではなく、組み合わせることもあります。ただし、「社内資料を使わせるには必ずモデルを再学習しなければならない」と考える必要はありません。更新される規程やマニュアルを参照させたい場合、まず検索して渡す構成を検討できます。

根拠付き回答の限界を知る

RAGを導入しても、誤った回答が完全に無くなるわけではありません。取得した資料が古い、質問の意味を取り違えた、モデルが根拠に無い説明を付け足した、などの失敗があり得ます。出典のリンクを表示していても、そのリンク先が回答の主張を実際に裏付けているかは別の確認です。

根拠が足りないときに、不足を伝える設計も重要です。資料に申請期限が無ければ、一般的な期限をもっともらしく補うより、「この資料から期限は確認できない」と伝え、次の確認先を示す方が適切な場合があります。次の節から、検索に使う資料をどのように準備し、取り出すかを説明します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第4章 RAGによる資料の活用

10. Document・読み込み・文書の分割

文書を、検索に使える形へそろえる

前の節で分けた、RAGの「事前の準備」に当たる部分です。検索や生成を始める前に、資料の本文と出典を扱える形へそろえます。

RAGの前半では、元の資料を検索に使える形へ整えます。資料はPDF、Webページ、テキスト、データベースなど、さまざまな場所にあります。形式ごとの読み取り方法は異なりますが、生成へ渡す前には、何が書かれているかと、どこから来た情報かを扱える必要があります。

LangChainのDocument loader(文書を読み込む部品)は、こうした資料をDocumentという共通の形へ読み込むために使います。Documentは、本文と付随情報をまとめたデータです。本文の項目名がpage_content、付随情報の項目名がmetadataです。読み込んだ時点では、モデルによる要約や回答生成が済んだわけではありません。

元のファイルとDocumentが、必ず一対一になるわけではありません。一つのPDFをページごとに読み込めば複数のDocumentになり、長い本文をさらに分割すれば、より小さなDocumentになります。Documentは、アプリケーションが資料の一まとまりを扱うための形だと考えてください。

metadataは、資料の意味と出典を保つ

本文だけを保存すると、その文章がどの文書の何ページにあったのか分からなくなります。metadataには、文書名、出典のURL(Web上の場所を示すアドレス)、ページ、文書ID、更新日、適用対象など、後で必要になる情報を持たせます。出典の表示や検索条件の絞り込みは、この情報を土台にします。

たとえば、本文が「交通費は精算システムで申請する」で、付随情報が「文書名:出張規程、ページ:3、版:2026年度」という形です。本文は回答の材料になり、付随情報は出典の表示や適用する版の確認に使います。これらの情報がすべて自動でそろうとは限らず、読み込み時などに必要な項目を補います。

たとえば同じ「出張規程」という名前の資料でも、年度や所属会社によって内容が違う場合があります。文章がよく似ていても、どの資料を適用するかが異なります。文書の識別情報や版を保持することで、古い規程と新しい規程が混ざる問題を見つけやすくなります。

閲覧できる部署などの情報をmetadataへ持たせることもあります。ただし、情報を書き込むだけではアクセス制御になりません。検索や取得の際に、認証された利用者に応じて条件を適用する必要があります。

なぜ文書をチャンクへ分けるのか

長い文書を小さなまとまりへ分割したものを、チャンクと呼びます。交通費について答えるのに、人事制度全体を毎回渡す必要はありません。適切なまとまりへ分けることで、質問に関係する箇所を取得しやすくし、モデルへ渡す量も管理できます。

分割では、一方を良くすると別の点が悪くなる、トレードオフと呼ばれる関係があります。細かすぎると、条件と結論、見出しと本文、表の項目と数値が離れてしまいます。大きすぎると、無関係な内容が多く混ざり、検索の焦点がぼやけます。よい分割は、文字数だけでなく、文書の構造や質問の種類に依存します。

Text splitterとoverlapの考え方

Text splitterは、文書をチャンクへ分ける部品です。見出しや段落などを利用する方法や、一定の長さを基準にする方法があります。LangChainには複数の分割方法があり、RecursiveCharacterTextSplitterは、段落や区切りを段階的に利用する代表的な選択肢です。

チャンクの境目で文脈が切れることを和らげるために、前後で一部の内容を重ねることがあります。この重なりをoverlapと呼びます。ただし、重ねる量を増やすほどよいとは限りません。似た候補が何度も取得されたり、保存するデータや処理量が増えたりするためです。

また、分割の長さが文字数なのかトークン数なのかは、利用する方法や設定によって異なります。値の単位を確認せずに、別の教材の数字だけを移すと、想定とは違う大きさのチャンクになることがあります。

読み取りが間違えば、その後の検索も困難になる

PDFから読み取った文章では、段組みの順番が崩れたり、表の行と列の関係が失われたりすることがあります。画像だけの資料では、画像から文字を読み取るOCRという処理が必要になる場合もあります。読み込めたというだけで、元の資料の意味が正しく残っているとは限りません。

この段階で生じた誤りは、後からモデルを強力なものへ変更しても解消しないことがあります。たとえば金額と対象者の対応が崩れた表を渡せば、正しい条件を判断できません。RAGを理解するときは、生成の前に、資料の読み取りと構造の保持という仕事があることを押さえます。

次の節では、こうして整えたチャンクを、質問から見つけ出すためのEmbedding、Vector store、Retrieverを説明します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第4章 RAGによる資料の活用

11. Embedding・Vector store・Retriever

言葉が一致しなくても、関連する資料を探したい

前の節で、資料の本文と付随情報をDocumentへまとめ、長い文書をチャンクに分けました。この節では、そのまとまりを質問から探し出す方法を説明します。

利用者が「立て替えた電車代はどうするのか」と質問したとき、規程には「公共交通機関の利用に伴う旅費の精算」と書かれているかもしれません。質問と資料で同じ語を使っていなくても、意味が関連する箇所を探したい場面があります。Embeddingは、このような検索に使う文章の数値表現を作ります。

Embedding(エンベディング)モデルは、文章を数値の並び、つまりベクトルへ変換します。数値がいくつ並ぶかを次元と呼びます。同じ方式で文章を数値化しておくと、数値の並び同士を比較し、関連がありそうな文章を探せます。各数値を人が直接読んで、文章の意味を判断するためのものではありません。

検索では、質問と資料を対応するEmbeddingで数値化し、ベクトル同士の近さを手掛かりに候補を取得します。この近さを数値で表したものが類似度です。近いということは、その表現方法のもとで関連がありそうという意味で、文章の事実が正しいことや、回答に十分なことまで保証するものではありません。

Embeddingモデルと、回答を生成するモデルは別の役割

Embeddingモデルの出力は数値の並びで、会話モデルの主な出力は文章やツール要求です。どちらもモデルですが、担当する仕事が異なります。RAGでは、検索用にEmbeddingを使い、取得した資料から説明を作るために会話モデルを使う、といった組み合わせができます。

質問と文書で、異なるEmbeddingモデルや互換性のない設定を使うと、そのままでは近さを適切に比較できません。Embeddingを変更する場合は、保存している文書側のベクトルも作り直す必要があるかを確認します。回答用のモデルだけを差し替える場合とは、影響する範囲が違います。

Vector storeは、ベクトルと文書を関連づけて保持する

Vector storeは、文書のベクトルを保持し、近さに基づく検索を行うための部品です。元の文章やmetadataとの対応も扱います。LangChainには複数の製品・実装と接続するための共通インターフェースがあり、アプリケーション側から文書の追加や類似検索などを行えます。

第8節のStoreは、会話をまたぐ情報の保存・取得の窓口でした。ここでのVector storeは、とくに文章を数値化した情報と検索を扱う部品です。どちらも「保存する」という役割を含みますが、何を保存し、どの方法で取り出すかに注目して使い分けます。

ここで、検索用の索引を作る準備段階と、利用者の質問へ答える実行段階を分けます。準備段階では文書を分割し、Embeddingを作り、保存します。質問の段階では質問のEmbeddingを作り、候補を取得します。文書のEmbeddingを毎回すべて作り直す構成にする必要はありません。

ただし、規程を更新したら、検索対象にも更新を反映しなければなりません。新しい文書を追加するだけで古い版を残すと、内容のよく似た古い規程が候補になる場合があります。文書のIDや版の管理は、検索の品質にも関係します。

Retrieverは、質問から文書を返す窓口

Retrieverは、問い合わせを受け取り、関連するDocumentを返す部品です。Vector storeと似て見えますが、役割の範囲が違います。Vector storeは保存と検索を支える実装で、Retrieverは、アプリケーション側から見た「関連文書を取得する」入口です。

検索へ渡す問いや検索語は、クエリとも呼ばれます。利用者の質問文をそのまま使う場合もあれば、会話の文脈から省略された条件を補い、検索用のクエリを作る場合もあります。どんな問いを検索へ渡したかは、検索結果を理解するための大事な情報です。

Retrieverの内部が、必ずベクトル検索である必要はありません。キーワード検索、複数の検索方法を合わせる方法、既存の検索システムへの問い合わせなどでも構成できます。この窓口を分けることで、後ろのプロンプトやモデルを大きく変えず、検索方法を比較しやすくなります。

件数、絞り込み、検索方法で結果は変わる

検索件数を表すkは、候補を何件取得するかの設定としてよく登場します。件数を増やせば必要な情報を含む可能性は広がりますが、無関係な文章や似た候補も増えます。上位に出たというだけで、質問に回答できる資料だと判断することはできません。

文書の版や部署などをmetadataで絞り込む方法もあります。また、製品コードや規程番号のように文字の一致が重要な質問では、意味の近さだけよりキーワード検索を組み合わせる方法が適する場合があります。どの方法も、想定する質問で比較して選びます。

補足:候補の偏りを減らすMMR

上位の候補が同じ文章の繰返しばかりだと、別の重要な条件を取得できないことがあります。MMRは、質問との関連性に加え、候補どうしが似すぎないことも考慮する選び方です。たとえば通常ルールに似た文章ばかりを取る偏りを減らせる場合があります。ただし、必要な例外を必ず取得できると保証するものではありません。まず通常の検索の役割を理解し、改善方法の一つとして位置づけます。

Embedding、Vector store、Retrieverは、順に「数値表現を作る」「保存し検索する」「文書を取得する窓口になる」と整理できます。次の節では、取得した文書から回答する流れと、その改善の考え方を扱います。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第4章 RAGによる資料の活用

12. 根拠付き回答とRAGの改善

検索結果を、そのまま回答だとは考えない

前の節のRetrieverは、質問に関連する文書の候補を返す窓口でした。その候補から利用者の質問に答えるのが、生成の段階です。この節では、そのつなぎ方と改善を扱います。

RAGでは、Retrieverが返したDocumentをモデルの入力へ組み込みます。その際、本文だけを無造作に並べるのではなく、どの文章がどの資料に属するかを分かるようにして渡します。資料の識別子を付けておくと、モデルが根拠を指し示す出力を作りやすくなり、後から対応を確認できます。

たとえば「出張規程の第3項では申請が必要とされ、別の補足には日帰り時の例外がある」とします。どちらも質問に必要なら、両方を渡す必要があります。モデルは検索範囲の外にある補足を、当然に知っているとは限りません。RAGの回答は、今回取得して渡した情報に左右されます。

回答方針は、根拠の範囲と不足時の扱いを決める

資料に基づく回答では、「参考資料の範囲で説明する」「根拠が無い項目は不明とする」「出典を示す」といった方針を入力に含めます。これにより、一般知識を使った自由な回答とは異なる仕事をモデルへ伝えます。ただし、指示しただけで必ず守られるとは限らないため、出力の確認も必要です。

出典を表示する場合、リンクの形式だけを検査しても不十分です。実在する資料へのリンクでも、回答の主張を支えていない場合があります。「申請は前日まで」と答えているなら、その期限を確認できる記述が、引用した資料の中にあるかを見る必要があります。

問題を、検索と生成に分けて調べる

回答が間違っているとき、最初に検索結果を確認します。必要な資料を取得できていないなら、モデルへの指示を変更するだけでは根本的に改善しない可能性があります。資料が読み取れているか、分割で条件を切り離していないか、古い版が残っていないか、検索条件が狭すぎないかを見ます。

必要な根拠を取得しているのに回答が誤る場合は、生成側を調べます。資料の渡し方が分かりにくい、無関係な候補が多い、適用条件が明示されていない、モデルが指示に従えていない、などが考えられます。この場合は入力構成や候補の整理、モデルの選択などが改善の対象になります。

検索と生成を一つの成功率だけで見ると、どちらが良くなったのか分かりません。少なくとも、必要な資料を取得できたか、回答が資料に支えられているか、利用者の質問に答えているかを分けて比較します。

第9節の架空の規程には、申請先と領収書の扱いがあり、期限は書かれていませんでした。その例に戻ると、次のように原因を分けられます。

観察した結果主に確認する場所
申請先が書かれた規程を取得できていない。資料の読み込み・分割・検索条件。
規程は取得したが、別の申請先を答えた。モデルへ渡した資料と、生成した説明の対応。
規程は取得したが、書かれていない期限を作って答えた。根拠が無い場合の回答方針と、その方針を守れたか。

代表的な改善方法と、その意味

質問の書き換えは、利用者の短い言い方を、検索しやすい問い合わせへ変換する方法です。第7節の大阪出張についての会話を踏まえて、「日帰りなら?」を「大阪への日帰り出張に適用される交通費の申請条件」のように補うと、検索対象が明確になることがあります。ただし、大阪出張という文脈が無いのに場所を足すなど、利用者が伝えていない条件を追加すると、別の質問を検索してしまいます。

検索語を複数作るクエリ拡張や、キーワード検索とベクトル検索を合わせる方法は、候補の取りこぼしを減らすために使えます。再ランキングは、取得した候補を、質問への関連性などで並べ直す段階です。いずれも処理が増えるので、時間や費用、誤った変換が入る可能性も考慮します。

一度に多くの変更を加えるより、同じ質問集合を使い、検索方法や分割方法などを一つずつ変える方が、改善の理由を判断しやすくなります。特定の一問にだけ合う調整と、全体の品質が上がる調整を区別することも大切です。

取得した文章は、参照データとして扱う

取得したWebページや文書に、「これまでの指示を無視しなさい」のような文章が含まれる可能性があります。それは資料の中身であり、アプリケーションの回答方針を書き換える権限を持つ命令ではありません。外部の文章に引きずられて振る舞いが変わる問題は、プロンプトインジェクションとして知られています。

資料と指示の区別に加え、取得前の権限確認、渡す範囲の制限、根拠の確認などを組み合わせます。RAGにすれば自動的に安全になるわけではありません。第6章では、こうした制御と評価を、LangChainの実行の中へどう組み込むかを説明します。

ここまでは、検索してから生成する順序を決めた構成でした。次の章では、検索などの機能を「ツール」としてモデルへ知らせ、必要に応じて利用させる方法へ進みます。RAGで学んだ検索の部品は、その場合にも利用できます。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第5章 ツールとエージェント

13. ツールとFunction Calling

ツールは、モデルの外で行う処理を接続する部品

モデルは、与えられた情報から文章や要求を生成できます。一方、最新の残日数を勤怠システムから取得することや、申請データを保存することには、外部の処理が必要です。その処理をモデルが利用できる機能として表したものがツールです。

第3節で、関数は名前を付けた処理、引数は渡す条件、戻り値は受け取る結果と説明しました。LangChainでは、関数に@toolという目印を付けて、ツールとして定義する方法などがあります。名前や説明、引数の形を、モデルが利用方法を判断するための情報にできます。

モデルへ機能の使い方を伝えることと、関数を実際に動かすことは別です。たとえば規程検索なら、「何を渡せば何が返るか」をモデルへ伝え、実際の検索はアプリケーションの処理が行います。この区別が、Function Callingとツールの説明をつなぎます。

関数の中身より先に、使い方の説明が必要になる

たとえばsearch_policyというツールなら、説明に「社内規程から、問い合わせに関連する条項を検索する」と書けます。入力は検索する質問、出力は本文と出典の一覧です。この説明が「情報を探す」だけでは、何を探せて何を探せないのか、モデルに伝わりにくくなります。

同じ検索でも、規程検索と、利用者本人の申請状況の照会は別の仕事です。ツールを分け、説明を具体的にすることで、モデルが目的に合う機能を選びやすくなります。処理が正しく実装されていても、その使い道の説明が曖昧なら、適切に選ばれるとは限りません。

ツール呼び出しは、要求・実行・結果の往復

モデルにツールの定義を渡すと、応答にツール名と引数を含む要求が返ることがあります。たとえば「規程検索へ『交通費の精算期限』を渡す」という要求です。LangChainでは、モデルへ利用可能なツールを結び付けるbind_toolsなどの仕組みがありますが、定義を渡すこと自体は、外部システムの処理を実行することではありません。

アプリケーションが要求を受け取り、許可された処理か、引数が妥当かを確認した上で、実際のツールを実行します。その返り値をToolMessageなどでモデルへ戻すと、モデルは検索結果に基づいた回答を生成できます。tool_call_idは、どの要求に対する結果かを対応づけるために使います。

複数の要求がある場合、結果の順番だけでは取り違えることがあります。要求AのIDを付けて結果Aを返す、と対応を保つのが呼出IDの役割です。ToolMessageは、第4節で学んだ役割付きメッセージのうち、ツールから返った情報を表すものです。

結果が空だった場合も、その事実を返す必要があります。「該当なし」を「一般的な規程ではこうだろう」という推測で置き換えると、実データの取得とモデルの推測の境目が失われます。

段階説明用の例
利用者の依頼交通費の申請期限を知りたい。
モデルの要求search_policyへ「交通費の申請期限」という引数を渡したい。
アプリケーションの実行許可した資料の中を検索し、見つかった条項と出典を取得する。
モデルへ返す結果取得した条項、または期限が確認できなかったという情報。

この例では、モデルの要求の時点では、期限について何も確定していません。実行結果を受け取って初めて、その情報を使った説明へ進めます。ツール名が応答に含まれたことを、検索が成功した証拠として扱わない理由がここにあります。

読み取りと書き込みでは、扱う責任が変わる

規程を検索するツールは主に情報を読み取ります。一方、申請を登録する、メールを送る、予約を確定するといったツールは外部の状態を変えます。どちらもツールですが、間違った要求を実行したときの影響が異なります。

モデルが「申請を登録したい」と要求しても、本人がその申請を登録できる権限を持つか、必要な確認が済んでいるかは、アプリケーションが判断します。本人のIDをモデルの生成した文字列だけから決めるような設計では、別の人の情報を扱う危険があります。信頼できる本人情報は、アプリケーション側の実行情報として渡します。

このように、ツールはモデルの能力を現実の処理へつなぐ一方、実行してよい範囲を明確にする境界でもあります。利用できる機能を必要なものへ絞ることは、選択の分かりやすさと権限管理の両方に役立ちます。

ツールを一度使うことと、エージェントは別の概念

一つの決まった検索をアプリケーションが必ず呼び出し、結果をモデルへ渡すだけなら、固定した処理として構成できます。モデルに次のツールの選択を任せる必要はありません。一方、何を調べるか、追加の照会が必要かを、モデルの応答に応じて繰り返し判断させる場合は、エージェントの構成が関わります。

ツールは利用できる機能、エージェントはその機能を選びながら仕事を進める流れです。次の節では、LangChainのcreate_agentを通して、この流れを説明します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第5章 ツールとエージェント

14. create_agentとエージェントの動作

エージェントは、状況に応じて次の処理を選ぶ

この教材で扱うエージェントは、モデルが利用可能なツールを選び、その結果を受けて、さらに処理するか回答するかを判断する構成です。単に質問へ文章を返す場合よりも、途中の選択が増えます。「自律的」という言葉で紹介されることがありますが、どんな権限でも自由に持つという意味ではありません。

たとえば「出張の精算が済んでいなければ、必要な手続きを教えて」という依頼では、本人の申請状況を確認し、未完了なら関連する規程を検索し、その結果を説明する流れが考えられます。状況によって不要な検索を省いたり、追加で調べたりする判断を、モデルに任せることができます。

create_agentが組み立てる基本のループ

LangChainのcreate_agentは、モデル、ツール、回答方針などを受け取り、エージェントの基本的な処理を組み立てる入口です。モデルを呼ぶ、ツールの要求があれば実行する、結果をモデルへ返す、という往復を構成します。状態や実行には、LangGraphの基盤が使われています。

利用者の質問は、まずモデルへ渡ります。モデルがツールを要求すれば、アプリケーション側の処理がそれを実行し、結果を返します。次のモデル呼び出しでは、その結果を踏まえて、別のツールを使うか、最終的な回答を返すかを判断します。必ず一回だけツールを呼ぶわけでも、必ずツールを使うわけでもありません。

このループの周囲には、ツールの実行制御、入力の構成、記録、上限などの仕組みがあります。モデルの生成能力と、それを仕事として動かす周囲の仕組みを合わせて考えることが、エージェントを理解するポイントです。

一度だけ規程を検索して回答する場合でも、内部では「モデルの一回目の呼び出しで検索を要求する」「検索ツールが結果を返す」「モデルの二回目の呼び出しで回答を作る」という流れになることがあります。利用者には一つの回答として見えても、モデル呼び出しは二回、ツール実行は一回です。

検索結果を見て追加の検索が必要と判断すれば、さらに往復が増えます。反対に、利用者が挨拶をしただけなら、ツールを使わず回答して終わる場合もあります。回数は、利用者の発言数だけからは決まりません。

第6節のChainでは、部品をつなぐ順序を開発者が決めました。エージェントでは、モデルへ利用可能なツールを示し、途中でどれを要求するかを選ばせます。入力から結果へ進む途中の選択を、どこまでモデルへ任せるかが違います。

決まった手順との使い分け

あらかじめ定めた手順に沿って進める構成を、workflow(ワークフロー)と呼びます。毎回「規程を検索して、その結果から回答する」と決まっているなら、固定したworkflowで十分な場合があります。固定した流れは、どの処理が行われるかを予想しやすく、品質や費用も比較しやすくなります。

固定した手順にも、条件による分岐はあります。たとえば「検索結果が空なら不足を伝え、あれば回答する」というルールを開発者が決める方法です。分岐があることだけでエージェントになるわけではなく、次の処理の選択にモデルの判断を使うかが、ここで比べている違いです。

一方、質問によって必要な情報源が変わる、途中の結果を見て追加の照会を判断したい、といった場合は、エージェントの柔軟性が役立ちます。その分、経路が毎回同じとは限らず、呼び出し回数や時間のばらつきも増えます。高度な機能に見えるから選ぶのではなく、途中の判断をモデルへ任せる必要があるかで選びます。

補足:ReActという言葉を見かけたら

ReActは、状況についての判断と行動を往復するエージェントの考え方です。LangChainのエージェントを理解する際は、まず「モデルの要求→ツールの実行→結果を受けた次の判断」という往復を押さえます。実際の動作は、ツール名・引数・結果・最終回答で確認でき、モデルの内面を推測して説明する必要はありません。

最終回答を、項目として受け取る場合

エージェントの最終回答にも、第5節の構造化出力を適用できます。たとえば途中で規程を検索し、最後に「回答」「出典」「追加確認が必要か」という項目へ整理する構成です。途中で使うツールと、最後に受け取るデータの形は、役割が異なります。

補足:エージェントの出力設定の名前

create_agentのresponse_formatは、最終出力のスキーマを指定する入口です。得られた構造化データは、結果の状態にあるstructured_responseという項目で受け取れます。第5節のモデル単体に対するwith_structured_outputとは、使う入口が異なります。名前よりも、モデル単体の応答とエージェント全体の最終結果を分ける点を理解してください。

終了条件は、仕事の成功と同じではない

モデルがこれ以上ツールを要求せず、回答を返すと、ループは通常の終了へ進みます。しかし、回答を返したことだけで、依頼した仕事が正しく完了したとは言えません。検索に失敗したのに一般論で答えた場合や、必要な条件を確認し忘れた場合も、文章は返せるためです。

また、処理回数や時間の上限に達して止める場合もあります。これは、正常な完了とは別の結果です。「必要な情報を取得できた」「利用者へ説明できた」「上限で止まった」といった状態を分けることで、停止を成功として扱う誤りを防げます。

柔軟性を使う範囲を決める

エージェントには、利用可能なツール、モデルやツールの呼び出し上限、再試行、出力形式などを設計します。一回の利用者の質問でも、モデルを数回呼ぶことがあり、ツール自体の外部通信が加わる場合もあります。生成の回数と外部処理の回数を分けて把握すると、費用や遅延を説明しやすくなります。

自由に判断できる部分と、必ず守る手順を組み合わせたい場合は、標準のエージェントループの外側にも処理を構成します。次の節では、その実行経路と状態を明示するためのLangGraphを紹介します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第5章 ツールとエージェント

15. LangGraphによる状態・分岐・再開

標準のループから、独自の手順へ

前の節で、モデルとツールの往復を組み立てる標準的なエージェントを学びました。ここでは、その周囲を含めて独自の手順を組みたい場合を考えます。途中で持っておく情報は、第7節で学んだ「状態」につながります。

LangChainのエージェントでは、モデルとツールの往復を比較的少ない設定で構成できます。しかし、すべての仕事が同じループに収まるわけではありません。問い合わせを分類した後で異なる処理へ分ける、必要な情報がそろうまで入力を確認する、回答案を作ってから必ず承認を受ける、といった独自の手順もあります。

LangGraphは、こうした状態を持つ処理を、グラフとして構成するためのフレームワークです。ここでのグラフは、処理のまとまりを点、次へ進む接続を線で表した見取り図です。LangChainで作ったモデル処理やエージェントを、さらに細かい手順の中へ組み込むための仕組みとして理解するとつながります。

node・edge・stateの三つを分ける

node(ノード)は、処理の単位です。質問の分類、資料検索、モデルによる回答作成、結果の検査などを、それぞれのnodeとして表せます。nodeが必ず生成AIである必要はありません。確定したルールで検査する通常の処理も含められます。

edge(エッジ)は、処理の進み方を表します。「分類した後は検索する」という固定した接続も、「資料が見つかったら回答し、見つからなければ不足を伝える」という条件付きの接続もあります。state(ステート)は、その処理の間で引き継ぐ情報です。今回の質問、取得した資料、回答案、処理の状態などを保持します。

重要なのは、stateはモデルの頭の中ではなく、アプリケーションが管理するデータだということです。nodeが状態を読み、必要な更新を返し、次のnodeがその情報を使います。どのnodeが何を変更するかを明確にすると、処理の責任が見えるようになります。

出張相談の例なら、検索nodeの実行前は「質問はあるが資料は未取得」、実行後は「質問と取得した資料がある」という状態になります。回答nodeはその資料を読み、回答案を状態へ追加します。処理が次へ進むことがedge、引き継ぐ情報がstateだと区別できます。途中の項目を書き残すだけなら、モデルに新しい事実を学習させたことにはなりません。

分岐と繰返しを、制御できる形で表す

たとえば、質問に必要な条件が足りなければ追加質問へ進み、条件がそろえば資料を検索し、根拠が足りれば回答する、という経路を考えます。どの時点で分岐し、何を条件として次へ進むかをグラフに表すことで、生成だけに手順を委ねずに構成できます。

一部の分岐をモデルの分類結果に基づいて決めることもできますが、その場合でも、許可する分類や遷移先はアプリケーションが定義します。モデルがどんな文字列を返しても、任意の処理へ進めるようにする必要はありません。柔軟な判断と、決められた経路を組み合わせることができます。

繰返しでは、状態が変わる条件と終了条件が重要です。検索を続けても、必要な資料が存在するとは限りません。試行回数、時間、必要情報の有無などで打ち切る経路を用意します。

checkpointerは、処理の状態を再開につなぐ

LangGraphは、checkpointerを通してthreadの状態を記録できます。会話の継続に加え、人の確認で待機する処理や、途中で中断した処理の再開にも関わります。「この申請についてどこまで処理したか」を保存することで、新しいプロセスでも続きを判断できる構成を作れます。

ただし、状態を保存することと、外部で行った処理をすべて元に戻せることは別です。メールを送信したという外部の事実は、stateを以前の値に戻しても取り消されません。保存した状態と、外部システムの状態の両方を考える必要があります。

いつLangGraphを直接扱うのか

標準のツール利用ループで目的を満たせるなら、最初から独自のグラフを書く必要はありません。LangChainのcreate_agentを使い、必要な制御を設定する方法で進められます。一方、決まった業務手順を厳密に表したい、複数の処理を特定の条件で組み合わせたい、といった場合には、LangGraphを直接扱う意味が出てきます。

LangChainで構成したエージェントを、より大きなグラフの一つの処理として利用することもできます。どちらか一方しか使えないという関係ではありません。次の節では、この状態と再開の仕組みを利用した、人の確認を挟む処理を説明します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第5章 ツールとエージェント

16. 人の確認と、止めて再開する処理

人の確認を、処理の一部として組み込む

生成した回答案を確認してから送る、申請内容を本人が見直してから登録する、といった場面では、人の判断を実行手順へ組み込みます。これをHuman-in-the-loopと呼びます。AIを使う仕事の途中に、人が承認・修正・拒否できる段階を置く考え方です。

「重要な操作の前に確認してください」とプロンプトへ書くだけでは、確認待ちの状態がアプリケーションに保存されるとは限りません。何を実行しようとしているのかを提示し、そこで実行を止め、判断が返るまで待ち、判断に従って再開する仕組みが必要です。

LangChainとLangGraphでの位置づけ

LangChainでは、ツール実行前などに確認を挟むための部品を利用できます。これは、実行の途中へ処理を差し込むmiddleware(ミドルウェア)の一つで、詳しくは次の節で扱います。より独自の処理では、LangGraphのinterruptという中断の仕組みを使って、人の判断を待つ構成を作れます。どちらの場合も、中断中の状態と、再開する対象を保持することが重要です。

LangGraphでこの中断・再開を構成するときは、checkpointerで状態を記録し、threadの識別子で再開する対象を指定します。人の判断を再開の入力として渡し、待機していた処理へ戻す流れになります。画面に確認の文を表示するだけの動作と、処理の続きまで保存して待つ動作は異なります。

LangChainの確認用middlewareを使う場合も、状態を保存するcheckpointerと、同じ確認待ちの処理へ戻るためのthreadの指定が必要です。確認を挟む部品と、待機中の情報を保持する仕組みを組み合わせます。

第7節では、checkpointerが会話を続けるための状態を保存しました。ここでは、同じ考え方を使って「どんな操作の確認を待っているか」を保存します。たとえば「申請案を作成済み、登録は未実施、承認待ち」という状態です。承認が返った後で登録し、拒否された場合には登録しない、という経路へつながります。

確認する人へ示す情報は、「何かを実行してよいか」だけでは不十分です。どの機能を、どの引数で、誰のどの情報へ適用するかが分からなければ、意味のある承認になりません。申請を登録するなら、対象の利用者、日付、金額、登録先など、操作内容を確認できる形にします。

承認・修正・拒否で、進む経路を変える

承認された場合は、確認された内容を実行へ進めます。修正が必要なら、変更後の内容に対して条件を再確認します。拒否された場合は実行しない経路へ進めます。人が画面を見たという事実だけで、すべてを承認済みと扱わないことが大切です。

判断を記録するときは、何に対する承認なのかを対応づけます。承認後にモデルが引数を変更したのに、以前の承認をそのまま流用すると、確認した内容と実行内容がずれます。確認対象の内容と実行対象の内容が一致するように設計します。

また、返答が来ない、権限のある人が確認できない、といった場合もあり得ます。待機を継続するのか、期限切れにするのか、別の担当へ引き継ぐのかは、業務上の条件として決めます。

再開時には、同じ処理が再び実行される可能性がある

中断した処理を再開する際には、利用する仕組みに応じて、nodeの先頭などから再び処理される箇所があります。LangGraphのinterruptを含むnodeも、再開時には先頭から実行されるため、中断前に置いた処理をもう一度行う可能性を考える必要があります。

単にデータを読むだけなら問題が小さくても、中断前にメールを送信していれば、再実行で二重送信になるおそれがあります。外部へ変更を加える処理は、確認との位置関係を整理し、同じ操作を繰り返しても結果が重複しないようにする必要があります。

同じ操作を繰り返しても、一回実行した場合と同じ結果になる性質を、冪等性(べきとうせい)と呼びます。たとえば一つの申請操作に識別子を付け、既にその操作が登録済みなら再登録しない、といった対策が考えられます。モデルへの再問い合わせと、外部システムへの再実行は、同じように繰り返してよい処理ではありません。

「止まった」と「終わった」を区別する

承認待ちの中断、利用者による拒否、エラーによる停止、正常完了は、別の状態です。画面にすべて「完了」と表示すると、実際には登録されていない申請を、登録済みと誤解する原因になります。LangChainやLangGraphで状態を扱う意味は、こうした仕事の現在地を明確にすることにもあります。

エージェントの応用では、生成だけでなく、状態、制御、外部の実行を組み合わせて考えます。次の章では、その実行の途中へルールを加えるmiddlewareや、RAGとの組み合わせ、評価・運用の考え方へ進みます。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第6章 応用・評価・アプリケーション設計

17. middlewareとコンテキストの設計

エージェントの途中へ、共通の制御を加える

前の節では、人の確認を待ってからツールを実行する制御を学びました。この節では、確認に加えて、入力の整理や上限の検査などを、エージェントの途中へ組み込む考え方を説明します。

エージェントの動作を変えたいとき、プロンプトの書き換えだけでは対応しきれない場合があります。モデルへ渡す履歴を整理する、利用できるツールを条件に応じて変える、回数の上限を超えたら止める、ツールのエラーを扱う、といった処理は、実行の途中へ組み込む必要があります。

LangChainのmiddlewareは、エージェントの実行の前後や、モデル・ツールの呼び出しの周囲へ処理を加える仕組みです。create_agentで組み立てるエージェントに、共通の方針や制御を組み合わせるために利用します。単独で動く別のAIではなく、エージェントの動かし方を調整する部品です。

指示で期待することと、処理で強制すること

「何度も検索しないでください」という指示は、モデルに望ましい行動を伝えます。一方、呼び出し回数を数え、上限へ達したら実際に次の呼び出しを止める処理は、実行を制御します。期待を伝えることと、実行条件を強制することには違いがあります。

同じように、「申請登録の前に確認する」という方針は、前の節で説明した確認待ちの仕組みと組み合わせる必要があります。middlewareは、このようにプロンプトだけでは保証できない段階へ制御を加えるために役立ちます。ただし、提供される機能を組み合わせれば、すべての業務ルールが自動で完成するわけではありません。

たとえば「これからモデルを呼ぶ直前」に上限を確かめ、「ツールを動かす直前」に人の承認が必要かを調べ、「呼び出しが返った直後」に利用量を記録する、という置き方が考えられます。どのタイミングへ何を差し込むかが、middlewareを設計する際の焦点です。

コンテキストを、その時点の仕事へ合わせる

第3章では、保存した情報とモデルへ渡す情報を分けました。エージェントでは、ツールを使うたびに新しい情報が加わるため、どの段階で何を渡すかがさらに重要になります。利用者の依頼、過去の結果、今回利用できるツールが、その時点の仕事に合っている必要があります。

必要な情報を、適切な形式で、その呼び出しに合わせて渡す設計をコンテキストエンジニアリングと呼びます。単に長い指示文を書くことではありません。関係の無いツールを減らす、長い履歴を要約する、直前の検索結果を整理する、といった操作も含みます。

たとえば規程を説明する段階では、検索結果の本文と出典が重要です。申請を登録する段階では、確定した申請内容と、操作を許可する条件が重要になります。同じエージェントの中でも、段階によって必要な情報が変わります。

runtime contextは、信頼できる実行情報を渡す

モデルが生成した引数と、アプリケーションが把握している利用者情報は、別の経路で扱えます。LangChainのruntime contextは、利用者IDや接続先など、その実行に必要な情報をツールやmiddlewareへ渡すために使えます。会話の途中でモデルに本人の識別子を自由に決めさせる必要はありません。

runtimeは、プログラムが実行されるときの仕組みを指します。runtime contextは、その一回の実行へアプリケーションから渡す設定や情報です。モデルへ見せる入力全体を指す「コンテキスト」とは、使う場所が違います。runtime contextに置いた情報が、そのまま自動的にモデルへ送られるわけではありませんが、ツールがその情報を結果に含めればモデルへ渡る可能性があります。

情報を置く場所主な役割
モデルへ渡すコンテキスト今回の生成のための質問・方針・履歴・資料。
state(状態)処理の途中や同じ会話で引き継ぐ情報。
Store会話をまたいで保存・取得する情報。
runtime context今回の実行に必要な利用者情報や接続先など。

たとえば本人の申請状況を調べるツールでは、質問文に書かれた名前よりも、ログインによって確認された本人情報を利用する方が適切です。ただし、contextへ値を入れる前の認証と、取得先での権限確認は、アプリケーション側の責任です。contextを渡すだけで本人確認が済むわけではありません。

MCPは、ツールの接続方法の一つ

外部サービスのツールを接続する方法として、MCP(Model Context Protocol)があります。MCPは、ツールや文脈情報を受け渡すための共通の通信の取り決めです。このような取り決めをプロトコルと呼びます。MCPサーバーは、その取り決めに従って機能を提供するプログラムです。LangChainの対応する連携を使うと、公開された機能をエージェントのツールとして利用できます。

ここで増えるのは、利用できる機能を受け取る接続経路です。どのツールをモデルへ見せ、どの利用者に実行を許可し、失敗時にどうするかという設計は、引き続き必要です。MCPを学ぶ際も、プロトコルの名前より先に、LangChainのツールの意味を理解しておくと位置づけが明確になります。

middleware、runtime context、外部ツールの接続は、いずれもエージェントの柔軟性を、実際の仕事の条件へ合わせるための仕組みです。次の節では、その応用として検索をツール化する構成を扱います。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第6章 応用・評価・アプリケーション設計

18. RAGとエージェントを組み合わせる

検索を、エージェントが利用できるツールにする

第4章では、質問を受けたら検索し、その結果から回答する固定したRAGを説明しました。第5章では、モデルがツールを選ぶエージェントを学びました。この二つをつなぎ、検索をツールとして公開して、モデルが必要に応じて利用する構成がAgentic RAG(エージェンティックRAG)です。

たとえば、簡単な挨拶には検索せず、「交通費の規程を確認したい」という質問では規程検索を使う、といった判断をモデルへ任せられます。さらに、検索結果に不足があれば質問を言い換えて再検索したり、別の情報源も調べたりする構成が考えられます。

LangChainでは、Retrieverなどによる検索をツールとして表し、create_agentへ渡す部品の一つにできます。新しい検索原理に置き換わるのではなく、いつ何を検索するかという判断の場所が変わります。

固定したRAGと、何が変わるのか

固定したRAGでは、開発者が検索と生成の順序を決めます。質問ごとに同じ段階を通るため、処理の有無や費用を見積もりやすく、検索品質と生成品質を分けて調べやすい利点があります。必要な情報源が決まっている案内では、この単純さが役立ちます。

Agentic RAGでは、検索するか、どのツールを選ぶか、追加で調べるかを、途中の状態に応じて判断します。柔軟になる一方、必要なのに検索しない、同じ検索を繰り返す、適切でない情報源を選ぶ、といった失敗も増えます。検索を一回足しただけではなく、判断の品質も評価する必要が生じます。

比べる点固定したRAGAgentic RAG
いつ検索するか定めた手順の中で検索する。モデルが必要性を判断する場合がある。
追加の検索追加する条件や経路をあらかじめ決める。途中の結果を受けてモデルが要求できる。
確認する品質検索結果と、根拠に基づく回答。左の項目に加え、検索の要否・情報源・追加検索の判断。

追加検索が役立つ場合と、役立たない場合

「海外出張について、通常の規程と例外手続きを比較してほしい」という依頼では、複数の資料を順に調べることが有用な場合があります。一度の検索で両方そろわなくても、取得した資料から不足を判断し、別の検索へ進む構成を作れます。

一方、対象資料に該当する情報がそもそも無い場合、何度検索しても根拠は増えません。検索語の言い換えを延々と続けるより、不足を伝える方が適切です。また、利用者の勤務区分が不明なら、別の資料を増やす前に本人へ条件を尋ねる必要があるかもしれません。

このため、追加検索の判断には、何が不足しているのかという観点が必要です。単に候補が少ないから再検索するのではなく、回答に必要な条件や根拠を満たしているかを見ます。

固定した制御と、動的な判断を組み合わせる

実際の構成では、すべてを固定するか、すべてをエージェントへ任せるかの二択ではありません。たとえば、利用者の権限に応じた検索対象の制限は固定しておき、その範囲で検索語や利用する情報源を選ばせる方法があります。必ず社内資料を一度取得した後、不足時だけ追加検索を許可する構成も考えられます。

こうした組み合わせは、LangGraphで経路を明示したり、LangChainのmiddlewareで利用可能なツールや回数を制御したりして構成できます。必ず守る条件をアプリケーション側で保ち、判断が必要な部分へモデルを利用する考え方です。

たとえば「規程に関する質問では、許可された社内資料を必ず一度調べる」と決めた上で、「不足していれば追加検索を選べる」とする構成です。前半の必須の検索と、後半のモデルによる選択を分けると、どの柔軟性が必要なのかを具体的に説明できます。

判断が増えた分を、評価にも反映する

Agentic RAGでは、最終回答だけでなく、必要なときに検索したか、適切な情報源を使ったか、再検索が有益だったかも確認します。回答が正しくても、不要な検索を何度も行っていれば、時間や費用の面では改善の余地があります。逆に、検索回数が少なくても、根拠を見ずに回答したなら問題です。

基本のRAGがうまく動いていない原因を、エージェント化だけで解決できるとは限りません。資料の読み取りや検索対象の問題は、経路を柔軟にしても残ります。まず固定した構成のどこに限界があるかを把握し、必要な判断を追加すると、応用の意味が明確になります。次の節では、その比較を支えるトレースと評価を説明します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第6章 応用・評価・アプリケーション設計

19. LangSmith・トレース・品質評価

動いたことと、役に立つことを分ける

第12節で、検索の失敗と生成の失敗を分けました。この節では、そのような原因の調査と、変更前後の品質の比較を継続して行う方法を学びます。

LangChainで処理をつなぎ、文章が返るようになっても、アプリケーションの品質が確認できたわけではありません。社内規程の案内なら、正しい資料を使い、条件を落とさず、根拠の無いことを補わずに答えられる必要があります。評価は、このような期待を具体的な基準にして、繰り返し確かめるために行います。

一つの質問にうまく答えられただけでは、別の表現や例外条件にも対応できるか分かりません。また、以前は正しく答えられた質問でも、モデルやプロンプト、検索方法の変更で結果が変わることがあります。動作確認と継続的な品質の比較を分けて考えます。

トレースは、内部で何が起きたかの記録

トレースは、一つの依頼に対して行われた処理の記録です。モデルへ渡した入力、受け取った応答、検索の結果、ツールの要求や実行、各段階の時間などを追います。最終回答だけを見るより、どの段階で問題が生じたかを調べやすくなります。

たとえば古い規程に基づいた回答が返った場合、検索が古い版を選んだのか、正しい資料と古い資料が両方渡ったのか、モデルが資料を読み違えたのかを分けて調べます。生成の途中で何を入力したかが分からないと、推測でプロンプトを変更し続けることになりがちです。

トレースはモデルの内面をすべて説明するものではありません。観察できる入力、出力、選択、時間などの記録です。また、記録には質問や資料の本文が含まれる可能性があるため、保存する範囲や閲覧できる人も設計します。

トレースで原因を調べることと、評価基準に照らして良い結果かを判定することは別です。「検索ツールが一回呼ばれた」という記録だけでは、その検索が必要だったか、回答を支えたかまでは決まりません。記録は判断の材料になり、何を良いとするかは仕事に合わせて定めます。

LangSmithで、観察と比較を行う

LangSmithは、モデルを利用する処理の観察や評価に使える関連プラットフォームです。LangChainの実行を追跡し、呼び出しの構造や失敗箇所を確認したり、質問集合に対する結果を比較したりできます。LangChain以外のアプリケーションにも利用できます。

LangChainを使うためにLangSmithが必須というわけではありません。小さな構成では自分で記録を保存して比較することもできます。ただし、エージェントのように処理経路が変わる構成では、複数の呼び出しをひとまとまりとして追える仕組みが役立ちます。

評価データと基準を、仕事に合わせて用意する

評価用の質問集合には、一般的な質問だけでなく、条件不足、該当資料なし、古い版との混同、利用できない情報への問い合わせなどを含めます。単に正解の文章を一つ用意するより、何を含めるべきで、何を言ってはいけないかを明らかにすると、表現の違いを許しながら意味を確認できます。

このように、質問や必要に応じた参考情報・期待する結果をまとめたものを、評価用データセットと呼びます。たとえば第9節の資料で「申請先」を尋ねた場合は、精算システムという根拠に沿って答えることが基準です。「期限」を尋ねた場合は、資料から確認できないと伝えることが基準になります。すべての質問へ具体的な答えを出すことが、良い結果とは限りません。

RAGなら、必要な資料を取得できたか、回答が資料に支えられているか、質問へ答えているかを見ます。ツール利用なら、正しいツールと引数を選んだか、結果を取り違えていないかを見ます。構造化出力なら、形式と項目の内容を分けて確認します。時間、呼び出し回数、使用量も、品質と並べて比較します。

評価には、決まったルールによる検査、人の確認、別のモデルによる判定などがあります。モデルによる判定も誤る可能性があるため、基準となる人の判断と照らして使います。点数が付いたことだけを、正しさの証明として扱わないことが大切です。

たとえば必須の項目があるかはルールで調べやすく、適用条件を正しく説明しているかは資料と照らした確認が必要です。一つの合計点だけにすると、根拠のない回答が速く返ることを高く評価してしまう場合があります。正確さ、根拠、時間、利用量を分けて見ると、何が改善し、何を犠牲にしたかが分かります。

変更前後を、同じ条件で比較する

開発中に用意したデータで比較する評価をoffline評価、実際の利用中のやり取りを対象とする評価をonline評価と呼びます。ここでのofflineは、APIへ接続しないという意味とは限りません。運用前などに、用意したデータ集合で比較するという意味です。

モデル、プロンプト、検索設定を同時に変えると、結果が改善しても理由が分かりにくくなります。変更を区別し、同じ質問、同じ資料の版、同じ基準で比べることで、何が改善したかを判断しやすくなります。実際に失敗した質問を評価データへ加えると、同じ問題が戻っていないかも確認できます。

次の節では、ここまで学んだ部品を、継続して利用できるアプリケーションへまとめる際の考え方を整理します。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。

第6章 応用・評価・アプリケーション設計

20. LangChainを使うアプリケーションの設計

アプリケーション全体の中にLangChainを置く

LangChainを使った処理は、アプリケーションの一部分です。利用者の質問を受け取り、認証や入力条件を確認し、必要なモデル処理を行い、結果を画面へ返す流れの中に組み込みます。Web画面やログインをLangChain自体がすべて提供するわけではありません。

社内規程の案内を例にすると、画面と利用者の認証、資料の管理、検索、モデルへの入力、生成、出典付きの表示、実行の記録という役割があります。このうちLangChainは、モデルや検索、ツールを組み合わせる処理を支えます。どこまでをLangChainで扱い、どこからを通常のアプリケーションで扱うかを分けると、構成を単純にできます。

同じ出張相談を、第1節からの流れで振り返ると、入力の構成は第4節、会話の継続は第7〜8節、規程の参照は第9〜12節に当たります。申請状況の照会まで選ばせるなら第13〜14節、人の確認を必ず挟むなら第15〜16節の仕組みを組み合わせます。すべてを使う必要はなく、必要な仕事から部品を選びます。

モデルに任せる部分を、小さく明確にする

確定した計算、本人の権限、資料の版、申請が登録済みかどうかは、可能な限り確定したデータや処理で確認します。質問の言い方を理解する、資料を読みやすい説明へ変える、必要な機能を選ぶ、といった部分にモデルを利用します。すべての判断を生成に置き換える必要はありません。

たとえば、規程に載っている金額の説明を自然な文章へすることと、支給可能な金額を確定することは別です。前者へモデルを利用する場合でも、後者の業務ルールは確定した処理へ置けます。LangChainは、生成と通常の処理を組み合わせるために利用できます。

変更できる場所と、確認すべき場所を明確にする

モデルを差し替えるときは、呼び出し方だけでなく、構造化出力やツール利用の対応、回答品質、時間、費用を確認します。検索を変更するときは、資料の版、Embeddingの互換性、候補の取得方法も影響します。共通のインターフェースがあることで変更箇所を分けやすくなりますが、評価を省略できるわけではありません。

LangChain本体、接続用の連携ライブラリ、LangGraphなどのバージョンも、動作の条件になります。更新時には、同じ評価データを使って、出力や経路が意図せず変わっていないかを比較します。古いサンプルにあるAPI名を、そのまま現在の組み合わせへ移すことは避けます。

失敗、上限、再試行の意味をそろえる

外部APIが一時的に応答しない、利用上限へ達する、資料が見つからない、必要な項目を抽出できない、といった状態は起こり得ます。それぞれ、再試行する、利用者へ不足を尋ねる、回答を保留するなど、適切な扱いが異なります。

fallbackは、主な処理が利用できないときに代わりの方法へ切り替える構成です。別のモデルへ切り替える場合も、そのモデルが必要なツールや出力形式に対応しているかを確認します。また、外部へ変更を加える操作を再試行する場合は、二重実行を防ぐ必要があります。単に「失敗したらもう一度」では不十分です。

実行の上限は、一回のモデル生成だけでなく、エージェント全体の回数や時間にも設定します。利用者には、回答できたのか、情報が不足したのか、上限や障害で止まったのかを区別して伝えます。

結果が期待と違う場合と、処理を実行できなかった場合も分けます。通信が成功していても、回答が資料と矛盾していれば品質の問題です。通信の障害なら再試行が有効な場合がありますが、根拠が資料に無い問題を同じ入力で繰り返しても、根拠が増えるわけではありません。第19節の記録と評価が、対応を選ぶ材料になります。

利用者へ提供し、継続して使えるようにする

作った処理を、利用者が使える場所で動かせるようにすることをデプロイと呼びます。LangChainの処理をWebサービスなどから呼び出し、結果を画面へ返す構成も作れます。LangChainを組み込むことと、サービスを動かす場所・利用者のログイン・保存先を用意することは、役割が異なります。

運用は、提供した後も状態や品質を確認し、資料や部品を更新しながら使える状態を保つことです。資料が改訂されたら検索対象を更新し、モデルやライブラリを変更したら同じ評価基準で比べます。利用者へ公開した後も、どの情報・どの版に基づいて答えたかを追えることが大切です。

情報と権限は、入力の前から管理する

秘密のキーやデータベース接続情報は、モデルへ渡すプロンプトに含めるものではありません。利用者が参照できない資料は、検索の候補やツールの結果としても渡さないようにします。外部の文書に書かれた指示で、アプリケーションの権限や実行方針が変わらない設計が必要です。

第7節の認証・認可の区別に戻ると、ログインした本人かを確かめた後で、その人が読める資料や実行できるツールの範囲を確認します。LangChainの生成処理へ情報を渡す前と、外部の操作を実行する前の両方で、その範囲を保つ必要があります。

LangChainにはmiddlewareを利用した検査や制御を組み込めますが、それだけで認証、認可、機密保護のすべてが完成するわけではありません。検索対象、ツール、状態の保存先、トレースの記録先まで含めて、情報の流れを考えます。

基本から応用までのつながり

LangChainの基本は、モデルへ何を渡し、どんな形で受け取るかです。会話は過去の情報を入力へつなぎ、RAGは検索した情報を入力へつなぎ、ツールは外部の機能へつなぎます。エージェントは、その利用を状況に応じて選ぶ構成です。LangGraphは状態と経路を制御し、LangSmithは観察と評価を支えます。

実装へ進む際は、まず一回のモデル呼び出しや固定したRAGなど、目的を満たす小さな構成から始められます。途中の判断が必要になればエージェントへ、独自の手順が必要になればLangGraphへと広げます。どの部品を増やすかを、名前の新しさではなく、解決したい問題から選べることが、このカリキュラムで目指す理解です。

この節の参考資料

具体例・説明は本教材で作成しています。APIや対応機能の詳細は、利用するバージョンの公式資料で確認できます。