前回作成したAI Searchを使用し、Copilot StudioでNaive RAG(Retrieval-Augmented Generation)を組んでみた。
Naive RAG
『Naive RAG』は、情報検索と生成モデルを組み合わせたシンプルな(最も基礎的な)RAG手法。
- ユーザーのクエリに基づき、外部データベースやドキュメントから関連する情報を取得
- 検索で得られた情報をもとに、生成モデル(例: GPTなど)が回答を生成
最近は『Advanced RAG』や、RAGを使用した『Agentic Workflow/Agentic Design Pattern』が主流だけど、ひとまず練習もかねて基本的な『Naive RAG』から開始。
Tips:公式ではナレッジを推奨
ちなみにAI Searchの公式ドキュメントには、「CopilotにSharePointをデータソースとしたRAGを入れる場合は、Copilot Studioの機能(ナレッジ)を使うこと」を推奨している旨書いている。
SharePoint データとチャットするためにカスタム Copilot/RAG (取得拡張生成) アプリケーションを作成する必要がある場合は、このプレビュー機能ではなく Microsoft Copilot Studio を使用することをお勧めします。
公式から抜粋。
今回は実験なので自分で作るけど、本稼働の場合は「ナレッジを試す → 精度がいまいちな場合は自分で組む」くらいがちょうどよいかも。
SharePointをナレッジにする方法についてはこちら


Copilot Studio トピックからナレッジ(SharePoint)を使用してRAGで回答を生成する
Copilo Studioについて勉強を始めたので、その内容をメモ。今回はトピックからナレッジ「SharePoint」を使用して、RAGで回答を生成する。前回はトピック「Conversational boosting」を使用前回の記事ではS...
構築
全体的なイメージはこんな感じ。


SPOには、ほどよく新しい情報をWikiから抽出し、事前にチャンク化して保存。
※古い情報だとLLM自体の知識で回答できちゃっておもしろくないため。
※古い情報だとLLM自体の知識で回答できちゃっておもしろくないため。

構築は以下の手順で行う。
- トピックの作成 → 検索ワードの生成
- 検索(AI Search呼び出し)
- 回答生成 → メッセージの送信
- 任意:Conversational boostingから呼び出し
手順1 : トピックの作成 → 検索ワードの生成
まずは新しくトピックを作成して、検索ワードの生成を「プロンプトアクション」で実施する。


プロンプトにはFew-shotを使用し、応答を後のノードで使いやすいようJSON出力を定義。
※今回はNaive RAGを組むこと自体が目的なので、精度は未考慮。
※今回はNaive RAGを組むこと自体が目的なので、精度は未考慮。

Here are examples of user questions and their corresponding search queries. Use these examples to guide your transformation of the input question." Example Input 1: "Pythonでデータベースに接続する方法は?" Example Output: "Python データベース 雪像方法" Example Input 2: "気候変動が生態系に与える影響は?" Example Output: "気候変動 生態系 影響" Example Input 3: "AIの倫理的課題は何か?" Example Output: "AI 倫理 課題" Now, based on these examples, transform the following user question into an effective search query. Input : {input}
手順2 : 検索(AI Search呼び出し)
続いてAI Searchの呼び出し。今回はPower Automateを噛ませず、直接HTTPを投げる。

// 以下のURLにPOST https://【AI Searchリソース名】.search.windows.net/indexes/【インデックス名】/docs/search?api-version=2024-11-01-preview
ヘッダはAPIキーとContent-type。
※サンプルなのでAPIキーを雑に扱ってます。

※サンプルなのでAPIキーを雑に扱ってます。

ボディは「生コンテンツ」を選んで、JSON関数で本文を作成。
※ひとまず検索結果の上位3件から回答を生成する。
※ひとまず検索結果の上位3件から回答を生成する。

JSON({ search:Topic.queryOutput.structuredOutput.query, count:true, top:Topic.Top // 変数「Top」に3を代入済み })
最後に受信スキーマを定義。定義しておくと後ろのノードで簡単に使えて便利。
※定義はAI Searchのインデックスによって変わるので、サンプルから生成するのが楽。
※定義はAI Searchのインデックスによって変わるので、サンプルから生成するのが楽。

kind: Record properties: @odata.context: String @odata.count: Number value: type: kind: Table properties: @search.score: Number content: String id: String metadata_spo_item_content_type: String metadata_spo_item_last_modified: String metadata_spo_item_name: String metadata_spo_item_path: String metadata_spo_item_size: Number
手順3 : 回答生成 → メッセージの送信
「ユーザーの質問」と「検索結果」を「プロンプトアクション」に渡し、回答を生成する。

// 今回は検索結果として「ファイル名」と「ファイルの中身」を渡す。 JSON(ForAll( Topic.search_result.value, {fileName:metadata_spo_item_name,content:content} ))
プロンプトアクションの中身はこんな感じ。こちらも応答を簡単に扱えるよう、JSON出力を利用する。

If the query cannot be answered based on the provided context, respond with '提供された情報ではこの質問に答えることができません。' . Otherwise, generate a complete and accurate answer, and as an annotation, output the name of the referenced files at the end. # query {query} # information {information}
以上で「Naive RAG」のトピックの作成は完了。
手順4(任意):Conversational boostingから呼び出し
最後に、今後色々なRAG手法を試す予定なので、ユーザーのメッセージを「Conversational boosting」で受けるようにする。
メッセージを受け取ったら、「RAGの手法」を選ばせて、


選択に応じてリダイレクトする。


以上で構築は完了。
動作確認
こんな感じで質問してみると、正しい回答を返してくれる。


※ちなみに4oに聞くと普通に嘘をぶっこんでくる(おしいけど)。


ただ、本当に単純な構築なので、答えられない質問もたくさんある。


ということで、次回以降Advanced RAGをいくつか作って、性能の向上を試してみる。
コメント