取得拡張生成 (RAG) にプラグインを使用する
多くの場合、AI エージェントは外部ソースからデータを取得して、根拠のある応答を生成する必要があります。 この追加のコンテキストがないと、AI エージェントが誤った情報を確認したり、提供したりする可能性があります。 これに対処するには、プラグインを使用して外部ソースからデータを取得できます。
取得拡張生成 (RAG) 用のプラグインを検討する場合は、次の 2 つの質問を自問する必要があります。
- 必要なデータを "検索" する方法 (または AI エージェント) semantic 検索またはクラス検索が必要ですか?
- AI エージェントが事前に必要とするデータ (プリフェッチされたデータ) を既に把握しているか、または AI エージェントが動的にデータを取得する必要があるか。
- データのセキュリティを確保し、機密情報の過剰な共有を防止 する方法。
セマンティック検索とクラシック検索
取得拡張生成 (RAG) 用のプラグインを開発するときは、セマンティック検索とクラシック検索の 2 種類の検索を使用できます。
セマンティック検索
セマンティック検索では、ベクター データベースを使用して、単に一致するキーワードではなく、クエリの意味とコンテキストに基づいて情報を理解および取得します。 このメソッドを使用すると、検索エンジンは、シノニム、関連する概念、クエリの背後にある全体的な意図など、言語の微妙な違いを把握できます。
セマンティック検索は、ユーザー クエリが複雑、オープン エンド、またはコンテンツをより深く理解する必要がある環境で優れています。 たとえば、"写真に最適なスマートフォン" を検索すると、"best"、"smartphones"、"photography" という単語に一致するのではなく、スマートフォンの写真機能のコンテキストを考慮した結果が得られます。
セマンティック検索機能を LLM に提供する場合、通常は 1 つの検索クエリで関数を定義するだけで済みます。 その後、LLM はこの関数を使用して必要な情報を取得します。 Azure AI Search を使用して特定のクエリに似たドキュメントを検索するセマンティック検索機能の例を次に示します。
using System.ComponentModel;
using System.Text.Json.Serialization;
using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Models;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Embeddings;
public class InternalDocumentsPlugin
{
private readonly ITextEmbeddingGenerationService _textEmbeddingGenerationService;
private readonly SearchIndexClient _indexClient;
public AzureAISearchPlugin(ITextEmbeddingGenerationService textEmbeddingGenerationService, SearchIndexClient indexClient)
{
_textEmbeddingGenerationService = textEmbeddingGenerationService;
_indexClient = indexClient;
}
[KernelFunction("Search")]
[Description("Search for a document similar to the given query.")]
public async Task<string> SearchAsync(string query)
{
// Convert string query to vector
ReadOnlyMemory<float> embedding = await _textEmbeddingGenerationService.GenerateEmbeddingAsync(query);
// Get client for search operations
SearchClient searchClient = _indexClient.GetSearchClient("default-collection");
// Configure request parameters
VectorizedQuery vectorQuery = new(embedding);
vectorQuery.Fields.Add("vector");
SearchOptions searchOptions = new() { VectorSearch = new() { Queries = { vectorQuery } } };
// Perform search request
Response<SearchResults<IndexSchema>> response = await searchClient.SearchAsync<IndexSchema>(searchOptions);
// Collect search results
await foreach (SearchResult<IndexSchema> result in response.Value.GetResultsAsync())
{
return result.Document.Chunk; // Return text from first result
}
return string.Empty;
}
private sealed class IndexSchema
{
[JsonPropertyName("chunk")]
public string Chunk { get; set; }
[JsonPropertyName("vector")]
public ReadOnlyMemory<float> Vector { get; set; }
}
}
クラシック検索
従来の検索 (属性ベースまたは条件ベースの検索とも呼ばれます) は、データセット内の正確な用語または値のフィルター処理と照合に依存します。 これは、データベース クエリ、インベントリ検索、および特定の属性によるフィルター処理が必要な状況に特に有効です。
たとえば、ユーザーが特定の顧客 ID によって行われたすべての注文を検索したり、特定の価格範囲内とカテゴリ内の製品を取得したりする場合、従来の検索では正確で信頼性の高い結果が得られます。 ただし、従来の検索は、言語のコンテキストやバリエーションを理解できないことによって制限されます。
ヒント
ほとんどの場合、既存のサービスはクラシック検索を既にサポートしています。 セマンティック検索を実装する前に、既存のサービスが AI エージェントに必要なコンテキストを提供できるかどうかを検討してください。
たとえば、従来の検索を使用して CRM システムから顧客情報を取得するプラグインがあるとします。 ここでは、AI は顧客 ID を使用して GetCustomerInfoAsync
関数を呼び出して、必要な情報を取得する必要があります。
using System.ComponentModel;
using Microsoft.SemanticKernel;
public class CRMPlugin
{
private readonly CRMService _crmService;
public CRMPlugin(CRMService crmService)
{
_crmService = crmService;
}
[KernelFunction("GetCustomerInfo")]
[Description("Retrieve customer information based on the given customer ID.")]
public async Task<Customer> GetCustomerInfoAsync(string customerId)
{
return await _crmService.GetCustomerInfoAsync(customerId);
}
}
セマンティック検索で同じ検索機能を実現することは、セマンティック クエリの非決定論的な性質のため、不可能または実用的ではない可能性があります。
それぞれを使用する場合
セマンティック検索とクラシック検索のどちらを選択するかは、クエリの性質によって異なります。 これは、ユーザーが自然言語を使用して質問したり製品を探したりする可能性がある、サポート情報やカスタマー サポートなどのコンテンツが多い環境に最適です。 一方、精度と完全一致が重要な場合は、従来の検索を使用する必要があります。
一部のシナリオでは、両方のアプローチを組み合わせて包括的な検索機能を提供する必要がある場合があります。 たとえば、eコマース ストアの顧客を支援するチャットボットは、セマンティック検索を使用してユーザー クエリとクラシック検索を理解し、価格、ブランド、可用性などの特定の属性に基づいて製品をフィルター処理する場合があります。
セマンティック検索とクラシック検索を組み合わせて eコマース データベースから製品情報を取得するプラグインの例を次に示します。
using System.ComponentModel;
using Microsoft.SemanticKernel;
public class ECommercePlugin
{
[KernelFunction("search_products")]
[Description("Search for products based on the given query.")]
public async Task<IEnumerable<Product>> SearchProductsAsync(string query, ProductCategories category = null, decimal? minPrice = null, decimal? maxPrice = null)
{
// Perform semantic and classic search with the given parameters
}
}
動的なデータ取得とプリフェッチされたデータの取得
取得拡張生成 (RAG) 用のプラグインを開発する場合は、データ取得プロセスが静的か動的かを考慮する必要もあります。 これにより、必要な場合にのみデータを取得することで、AI エージェントのパフォーマンスを最適化できます。
動的データ取得
ほとんどの場合、ユーザー クエリによって、AI エージェントが取得する必要があるデータが決定されます。 たとえば、ユーザーが 2 つの異なる製品の違いを求める場合があります。 その後、AI エージェントは、データベースまたは API から製品情報を動的に取得し、 関数呼び出しを使用して応答を生成する必要があります。 考えられるすべての製品情報を事前にフェッチして AI エージェントに渡すのは現実的ではありません。
動的なデータ取得が必要なユーザーと AI エージェントの間の行き来チャットの例を次に示します。
ロール | メッセージ |
---|---|
🔵User | あなたは最高のマットレスについて教えていただけますか? |
🔴アシスタント (関数呼び出し) | Products.Search("mattresses") |
🟢ツール | [{"id": 25323, "name": "Cloud Nine"},{"id": 63633, "name": "Best Sleep"}] |
🔴アシスタント | もちろんです。 クラウド ナインとベスト スリープの両方があります |
🔵User | 両者の相違点とは何ですか? |
🔴アシスタント (関数呼び出し) | Products.GetDetails(25323) Products.GetDetails(63633) |
🟢ツール | { "id": 25323, "name": "Cloud Nine", "price": 1000, "material": "Memory foam" } |
🟢ツール | { "id": 63633, "name": "Best Sleep", "price": 1200, "material": "Latex" } |
🔴アシスタント | クラウドナインはメモリフォームで作られており、コストは1000ドルです。 ベストスリープはラテックスで作られており、費用は$ 1200です。 |
プリフェッチされたデータの取得
静的データの取得には、外部ソースと からデータをフェッチし それを AI エージェントに提供する必要があります。 これは、すべての要求にデータが必要な場合、またはデータが比較的安定していて頻繁に変更されない場合に便利です。
たとえば、現地の天気に関する質問に常に回答するエージェントがあるとします。 WeatherPlugin
があると仮定すると、気象 API から気象データを事前にフェッチし、チャット履歴に提供することができます。 これにより、エージェントは API からデータを要求する時間を無駄にすることなく、天気に関する応答を生成できます。
using System.Text.Json;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
IKernelBuilder builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey);
builder.Plugins.AddFromType<WeatherPlugin>();
Kernel kernel = builder.Build();
// Get the weather
var weather = await kernel.Plugins.GetFunction("WeatherPlugin", "get_weather").InvokeAsync(kernel);
// Initialize the chat history with the weather
ChatHistory chatHistory = new ChatHistory("The weather is:\n" + JsonSerializer.Serialize(weather));
// Simulate a user message
chatHistory.AddUserMessage("What is the weather like today?");
// Get the answer from the AI agent
IChatCompletionService chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
var result = await chatCompletionService.GetChatMessageContentAsync(chatHistory);
データのセキュリティ保護
外部ソースからデータを取得する場合は、データが安全であり、機密情報が公開されていないことを確認することが重要です。 機密情報の過剰な共有を防ぐには、次の方法を使用できます。
戦略 | 説明 |
---|---|
ユーザーの認証トークンを使用する | AI エージェントがユーザーの情報を取得するために使用するサービス プリンシパルは作成しないでください。 これにより、取得した情報にユーザーがアクセス権を持っていることを確認するのが困難になります。 |
検索サービスの再作成を回避する | ベクター DB を使用して新しい検索サービスを作成する前に、必要なデータを持つサービスに対して検索サービスが既に存在するかどうかを確認します。 既存のサービスを再利用することで、機密性の高いコンテンツの複製を回避し、既存のアクセス制御を活用し、ユーザーがアクセスできるデータのみを返す既存のフィルターメカニズムを使用できます。 |
コンテンツの代わりにベクター DB に参照を格納する | 機密コンテンツをベクター DB に複製する代わりに、実際のデータへの参照を格納できます。 ユーザーがこの情報にアクセスするには、最初に認証トークンを使用して実際のデータを取得する必要があります。 |
次のステップ
これで、AI エージェントを外部ソースからのデータで固定する方法が説明されました。AI エージェントを使用してビジネス プロセスを自動化する方法を学習できるようになりました。 詳細については、「タスク自動化関数の使用を参照してください。