iT邦幫忙

2025 iThome 鐵人賽

DAY 13
0

昨天我們學會了如何使用 VectorStore 來製作 RAG 的美味湯底,並手動進行資料注入與搜尋。不過,有沒有覺得這個過程還是有點「手動」呢?想像一下,你是一位餐廳經理,你希望你的 AI 服務生能夠根據客人的需求,自己決定要去「內部知識庫」還是「外部搜尋引擎」找資料,而不是每次都由你來下達指令。

這就是我們今天要探討的重點:Text Search 抽象化。Semantic Kernel 為我們提供了一個更高層次的抽象介面 ITextSearch,它就像一個萬能的「食材供應商」介面。無論你的食材是來自於內部的 VectorStore,還是來自於外部的 Bing 搜尋,我們都可以用同一個介面來操作。

統一介面:將 Vector Store 包裝成 ITextSearch 服務

回想一下我們昨天的 VectorStore 範例,它其實已經具備了搜尋的能力。Semantic Kernel 讓我們可以非常簡單地將它包裝成一個 ITextSearch 服務。

C#

using Microsoft.SemanticKernel.Text;
using Microsoft.SemanticKernel.Connectors.OpenAI; // 或其他 AI 服務
using Microsoft.SemanticKernel.Memory;

// 1. 建立一個 InMemoryVectorStore
var EmbeddingGenerator = new OpenAIClient(config["OpenAI:ApiKey"]!)
            .GetEmbeddingClient("text-embedding-ada-002")
            .AsIEmbeddingGenerator();

var vectorStore = new InMemoryVectorStore(new() { EmbeddingGenerator = EmbeddingGenerator });

var collection = vectorStore.GetCollection<string, Recipe>("Recipe");

var recipes = new List<Recipe>
{
    new() { Name = "麻婆豆腐", Cuisine = "川菜", Type = "主菜", Description = "麻、辣、燙、嫩、酥、香,這六個字完美地詮釋了麻婆豆腐的精髓。一道極具代表性的川菜,吃起來溫暖又過癮。" },
    new() { Name = "宮保雞丁", Cuisine = "川菜", Type = "主菜", Description = "以雞丁、乾辣椒、花生米、花椒粒等材料烹炒而成,鹹甜微辣,醬汁濃郁,是道經典的家常菜。" },
    new() { Name = "三杯雞", Cuisine = "台菜", Type = "主菜", Description = "以一杯麻油、一杯醬油、一杯米酒烹調的台式經典名菜,香氣四溢,配飯一流。" },
};
await collection.EnsureCollectionExistsAsync();
await collection.UpsertAsync(recipes);

Console.WriteLine("食譜搜尋服務已準備就緒!");

ITextSearch recipeTextSearch = new VectorStoreTextSearch<Recipe>(collection);

現在,我們的 recipeTextSearch 就可以用 ITextSearch 這個統一的介面來呼叫,無論底層是 InMemory 還是 Qdrant,對上層程式碼來說都毫無差別。

整合外部搜尋引擎:Bing 的加入

如果我們需要最新的時事新聞或外部資訊,光靠內部知識庫是不夠的。這時,我們可以請出外部的「食材供應商」——例如 Bing 搜尋引擎。

Semantic Kernel 也為我們提供了 Bing 的 ITextSearch 實作。

C#

using Microsoft.SemanticKernel.Plugins.Core; // 包含 Bing 搜尋 Plugin

// 1. 建立 Bing 搜尋服務,需要設定你的 Bing Search API key
// (注意:請將你的 API key 存放在安全的地方,例如 User Secrets)
var textSearch = new BingTextSearch(apiKey: "<Your Bing API Key>");

Console.WriteLine("Bing 搜尋服務已準備就緒!");

透過這種方式,我們就有了兩種不同來源的 ITextSearch 服務,一個是我們的內部食譜資料庫,一個是外部的 Bing 搜尋。

讓 AI 成為「食材採購員」:建立 Plugin

現在是整個流程中最神奇的部分!我們將這兩種 ITextSearch 服務包裝成一個 Plugin,並讓 AI 服務生可以透過 Function Calling 來自主決定要使用哪個服務。

public class SearchPlugin(ITextSearch recipeSearch, ITextSearch bingSearch)
{
    [KernelFunction]
    [Description("搜尋內部食譜資料庫。")]
    public async IAsyncEnumerable<string> SearchRecipesAsync(
        [Description("要搜尋的食譜關鍵字。")] string query)
    {
        await foreach (var result in recipeSearch.SearchAsync(query, 5))
        {
            yield return $"食譜: {result.Text}";
        }
    }

    [KernelFunction]
    [Description("使用 Bing 搜尋引擎進行網路搜尋。")]
    public async IAsyncEnumerable<string> SearchWebAsync(
        [Description("要搜尋的網路關鍵字。")] string query)
    {
        await foreach (var result in bingSearch.SearchAsync(query, 5))
        {
            yield return $"網頁搜尋結果: {result.Text}";
        }
    }
}

kernel.Plugins.AddFromObject(new SearchPlugin(recipeTextSearch, textSearch));

var executionSettings = new OpenAIPromptExecutionSettings
{
    FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};

Console.WriteLine("客人點餐:請推薦一道暖心又過癮的菜色。");
var result1 = await kernel.InvokePromptAsync("請推薦一道暖心又過癮的菜色。", new(executionSettings));
Console.WriteLine($"\nAI 服務生回應:\n{result1}");
Console.WriteLine("------------------------------------------");

// 測試外部搜尋
Console.WriteLine("客人點餐:請問 2022 年世界盃足球賽冠軍是誰?");
var result2 = await kernel.InvokePromptAsync("請問 2022 年世界盃足球賽冠軍是誰?", new(executionSettings));
Console.WriteLine($"\nAI 服務生回應:\n{result2}");
Console.WriteLine("------------------------------------------");

當客人問:「如何做一道三杯雞?」時,AI 會根據 Description 判斷,這是一個內部知識庫就能回答的問題,因此會自動呼叫 SearchRecipesAsync

但如果客人問:「請問 2024 年的世界盃足球賽冠軍是誰?」AI 則會判斷這個問題需要最新的外部資訊,因此會自主地呼叫 SearchWebAsync

透過 ITextSearch 介面的抽象化和 Function Calling 的整合,我們讓 AI 不再是被動的,而是能夠根據情境主動地選擇合適的工具來解決問題。這就好像我們為 AI 服務生賦予了「自主採購」的能力,大大提升了它的工作效率和精準度!

明天,我們將把眼界放得更寬,探索 AI 如何處理文字之外的資訊,也就是多模態 (Multi-modal) 輸入,敬請期待!

完整程式碼範例


上一篇
Day 12: 精準撈料:Vector Stores 的資料注入與搜尋 (Part 2 - 應用)
下一篇
Day 14: 多感官饗宴:處理圖片等多模態輸入
系列文
AI 全餐,好吃嗎?用 Semantic Kernel 打造你的客製化滿漢全席!21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言