はじめに

どうも、カヌです。
最近は趣味としてLLMを使ってチャットボットを作る傍ら、会社でもLLMに触れ始めています。いずれ、RAG+HyDEを使ったチャットボットの実装についてもここで触れてみたいなとは思っていますが、プライベートとの切り分けが大変難しく悩んでおります。(プライベートでも記事を書いているためです)
でも思い切って今回は最近流行ってるな!って思ったことを会社から書いてみようと思います!

MCPというプロトコル、ご存じでしょうか?LLMに情報連携する際に有用かなと思いましたので、今回は概要を、次回は使い方や実装について書いていこうと思っています。

AIとの会話はステートレス

最近の対話型AIはとても便利になってきています。しかし、少し使い込んでくると「昨日の会話を覚えていない」「プロジェクトの内容を何度も説明する必要がある」といった、 記憶喪失っぽさに不便を感じることがあると思います。

これは、今の大半のAIが会話のたびに記憶を初期化して動いているためです。もっというと、AIとの会話はステートレスであるからです。本当はもっと「継続的にやりとりできる賢い相棒」になってほしいんですが、そうは問屋が卸しません。世知辛い話です。では、AIに文脈を持たせるには、どうすればいいのか?ということについて触れていきましょう。

モデルは記憶を持たない

大規模言語モデル(LLM)は、会話の前後関係を理解しているように見えますが、実際には「1回のプロンプト入力で与えられた情報」しか処理していません。この入力の上限は「コンテキストウィンドウ」と呼ばれるトークン数(単語より細かい単位)で決まっており、GPT-4でも128k(4万~約12万字)程度が限界です。

つまり、過去の会話を「記憶している」わけではなく「毎回、文脈を含めて渡している」だけなので、長期的なやりとりや複数日をまたいだ会話を自然に続けるのは難しいというわけです。
私たち人間が長いお付き合いの中で会話するとき、こんな場面は割と頻繁にあると思います。

Aさん
「こんにちは!」
Bさん
「あ、こんにちは!お久しぶりです!あの件はどうもありがとうございました」
Aさん
「いえいえこちらこそ~」

このように会話が進んでいくと思いますが、これはAさんもBさんも文脈を理解しているからです。

例えば、AさんBさんがとあるお仕事(案件)でやり取りをしている仲であるとしたら「あの件」はお仕事かもしれませんし、趣味仲間であれば趣味の話かもしれません。

ですが、LLMはそういう文脈を理解するために次のような形のとてもストロングなスタイルをとっています。まずLLMが会話をするなど、何か動作をするときには必ず「指示」となるシステムプロンプトという物あります。
この指示に「すべきこと(アシスタントとして動いてほしい)」「しちゃダメなこと(人格否定や差別的な発言などはしない)」「人格(あなたはAIです)」などが書いてあります。

また、AI自身が発言した内容をアシスタントプロンプト(AIMessage)、ユーザーが発言した内容をユーザープロンプト(HumanMessage)として保持しています。
Bさん役のシステムプロンプト・アシスタントプロンプト・ユーザープロンプトの例は以下のような形です。

私はBさんであり、Bさんという人格は~である。(システムプロンプト)
Aさん
「趣味は~で」
AI
「なるほど、そういうことでしたら~~がおすすめですよ」
・・・
・・・
Aさん
「なるほどいいですね、これでいきましょう」
AI
「ありがとうございます!ぜひよろしくお願いします!」

というようなやり取りを、「こんにちは!」とか「今何時?」というリクエストがあるたび毎回全部頭から読んで推論するということをLLMはやってのけています。非常にストロングスタイルですね。こんな仕組みであるので、128kトークンを扱えます!といっても要約するなり、「この間の案件ですが~」というキーワードでDBから情報を引っ張ってきて文脈を理解する方法しかないわけです。(1回の問い合わせにフルフル128kトークンを投げて処理してくれるわけではありません)

話をまとめながら人間に例えていくと、人間でいう海馬の役割をしているのがLLMのコンテキストウィンドウになります。それでは、長期記憶をするためにどうしていたのか?という話をしたいと思います。

外部で文脈を保持するという発想

ここまではあたかも長期記憶は存在しないかのように書いていましたが、実際にはこの問題に対処するため、AIアプリケーションの開発者は以前からさまざまな工夫をしてきました。
言い方を変えれば、短期記憶しかできないなら外部のリソースを使えばいいじゃんという発想です。

  • 会話履歴をサーバー側に保存して、次回以降に再注入する
  • 重要なトピックを要約して、モデルに毎回渡すようにする
  • 知識の文脈を外部から与えるRAG(Retrieval Augmented Generation:検索拡張生成)

このように、「LLMの外で文脈を管理し、必要なときにモデルに再構築して渡す」という設計はすでに存在していました。
しかし問題は、それらが各自でバラバラに実装されていたという点です。構造や命名、文脈の再挿入方法に統一性がなく、ツールやモデルごとの連携も難しい状況でした。

RAGの活用と情報取得の課題

ここまでは「会話の文脈保持」という観点からLLMの特性(主にステートレス性)を見てきましたが、同じ「文脈(コンテキスト)」という言葉でも、もうひとつ重要な使い方があります。それが「知識の文脈」つまり、AIが背景知識や外部情報を参照してより賢く振る舞うための情報のことです。

この段落では、そうした「情報取得」と「文脈注入」の仕組みであるRAG(Retrieval Augmented Generation:検索拡張生成)について見ていきましょう。繰り返しとなりますが、背景情報(文脈)に特定の専門的な領域の情報を与えて回答精度を強化する方法をRAGと言います。RAGを活用することで、外部情報源を活用してAIの出力を強化できます。

RAGを実装するためには、必要な情報を外部(例えばインターネット)から取得し、その情報を適切な文脈としてモデルに渡す必要があります。しかし、情報の取得自体にはかなりの手間がかかることがしばしばです。特に、HTTPリクエストやデータベースアクセスを用いて必要な情報を収集するプロセスにはいくつかの障壁が存在します。

インターネットから情報を得るための方法としてHTTP通信を行いスクレイピングする例を挙げます。

例:HTTPリクエストによる情報取得

例えば、ユーザーが今日の天気について尋ねてきたとしましょう。LLMはリアルタイム性のある情報に弱いため、基本的に天気予報のデータは外部のAPI(例えば、OpenWeatherMapやWeatherAPI)から取得することになります。この場合、次のような手順が必要です。

  1. HTTPリクエストの送信: ユーザーからの質問に基づいて、適切なエンドポイントにリクエストを送信します。これには、URLの組み立て、パラメータの指定、APIキーの管理などが含まれます。
  2. レスポンスの解析: APIから返されるデータ(通常はJSON形式)を適切に解析し、必要な情報(例:現在の天気、気温、風速など)を抽出します。
  3. モデルに情報を与えるためMarkdownやJSONなどのフォーマットを用いて構造化してプロンプトに文脈情報として与えます。

そのほか、エラー処理もそれぞれ固有の処理を書く必要があります。外部サービスに依存しているため、APIのレスポンスが遅延したり、エラーが発生したりする可能性があります。これに対するエラーハンドリングが不可欠です。
外部APIへのアクセスは単純なようでいて、リクエスト・レスポンス処理を含む多くの手間がかかります。また、異なるAPIを使用する場合は、それぞれに特有の仕様(認証方法やデータ形式)に対応する必要があり、コードの保守性が低くなる可能性もあります。

もちろん、HTTP APIは非常に便利で、LLMの知識を拡張するために欠かせない手段です。ですが、開発や運用の観点では「各APIごとの仕様対応」や「エラーハンドリングの複雑さ」など、スムーズに使いこなすための工夫が必要です。

Model Context Protocol(MCP)の登場

そこで登場するのが、Model Context Protocol(MCP)です。MCPは、これらの情報取得プロセスを統一的に扱うための枠組みを提供します。MCPを使うことで、異なるデータソース(HTTP API、データベース、外部サービスなど)から情報を取得する際に、統一されたプロトコルを使用してアクセスすることができます。

これにより、情報を「どこから」「どのように」取得するかに関するコードが簡素化され、整合性を保ちやすくなりました。つまり、RAG(情報の取得)に限らず外部ツールの活用プロンプトへの情報の差し込みも今まで以上により実装しやすくなると言えるでしょう。

まとめ

  • AIとの会話は基本的にはステートレスです
  • 状態を持つには今までの文脈情報を持たせなければなりません
  • MCPが登場するまでは独自の実装方法を考えて実装するしかありませんでした
  • MCPが登場したことで、共通の実装方法でステートや外部情報を持たせることが可能になったため、プラグインなどの互換性が上がることが期待されます

次回は、実際の使い方としてLLMアプリ構築ソフトウェアのDifyとMCP Fetch Serverを使ってインターネットにある情報を要約する方法、LLM特有のセキュリティ観点について解説していきます。