當前位置: 妍妍網 > 碼農

探索Semantic Kernel內建外掛程式:深入了解ConversationSummaryPlugin的套用

2024-06-19碼農

前言

經過前幾章的學習我們已經熟悉了 Semantic Kernel 外掛程式的概念,以及基於 Prompts 構造的 Semantic Plugins 和基於本地方法構建的 Native Plugins 。本章我們來講解一下在 Semantic Kernel 中內建的一些外掛程式,讓我們避免重復造輪子。

內建外掛程式

Semantic Kernel 有非常多的預定義外掛程式,作為解決通用業務的相關能力。 Plugins 地址 [1]

這裏面每一個類別庫都是一組相關功能的外掛程式 SDK ,其中 Plugins.Core 裏面提供的使我們高頻使用的外掛程式集合。

Plugins.Core

可以看到 Plugins.Core 內有以下幾個外掛程式:

  • ConversationSummaryPlugin :對話總結外掛程式

  • FileIOPlugin :讀寫檔外掛程式

  • HttpPlugin Http 請求功能的外掛程式

  • MathPlugin Math 計算外掛程式

  • TextPlugin :字串操作外掛程式

  • TimePlugin :獲取當前時間和日期外掛程式

  • WaitPlugin WaitPlugin 提供了一組函式,在進行其余操作之前等待。

  • 實戰

    我們來對 Semantic Kernel 中提供的內建外掛程式來做一個實戰練習

    第一步需要安裝 Nuget

    NuGet\Install-Package Microsoft.SemanticKernel.Plugins.Core -Version 1.14.1-alpha

    該包目前只有預覽版本,如果用 VS 的包管理器安裝,那需要勾選 包括預覽發行版

    ConversationSummaryPlugin

    這是一個對話總結外掛程式,以提示詞構造的 Semantic Plugins ,外掛程式內定義了三個 Kernel Function 分別是:

  • SummarizeConversation :給定一段長的對話記錄,總結談話內容

  • GetConversationActionItems :給定一段長的對話記錄,辨識出其中的行動項。

  • GetConversationTopics :給定一段長的對話記錄,辨識出值得記住的主題

  • unset unset SummarizeConversation unset unset

    我們先定義一個對話使用者我們測試的對話數據


    string chatTranscript = @"
    A: 你好,最近工作很忙碌,我們需要安排下周的會議時間,你覺得周幾比較合適?
    B: 嗯,我明白,工作確實很忙。周三或周四應該比較合適,因為那時候大家的日程相對空閑一些。
    A: 好的,周三或周四都可以,我們再確認一下其他同事的時間表。
    B: 對,最好再和大家核實一下,免得出現時間沖突。
    A: 我今天會發信件詢問大家的意見,然後我們再做最終決定。
    B: 好的,我也會在群裏提醒大家留意信件。
    A: 大家好,關於下周的會議安排,我建議定在周四下午兩點,在會議室A舉行,大家覺得怎麽樣?
    C: 周四下午兩點可以,我在行事曆上已經標註了。
    D: 對不起,周四下午我有其他安排,能否改到周三下午呢?
    A: 好的,我們盡量照顧大家的時間,那就改到周三下午兩點吧,地點仍然是會議室A。
    B: 沒問題,我會通知其他同事,讓大家知道時間的變動。
    "

    ;

    Kernel 註冊外掛程式:

    var conversationSummaryPlugin = kernel.ImportPluginFromType<ConversationSummaryPlugin>();

    總結會話內容

    Console.WriteLine("SamplePlugins - Conversation Summary Plugin - Summarize");
    {
    FunctionResult summary = await kernel.InvokeAsync(
    conversationSummaryPlugin["SummarizeConversation"], new() { ["input"] = chatTranscript });
    Console.WriteLine($"Generated Summary:{summary.ToString()}");
    }

    OutPut:

    Generated Summary:In the conversation, A and B discuss scheduling a meeting for the following week, considering Wednesday or Thursday as potential dates due to lighter schedules. A decides to send an email to confirm the availability of all colleagues. Later, A proposes holding the meeting on Thursday at 2 PM in Conference Room A, but D requests a change due to a scheduling conflict. A agrees to reschedule the meeting to Wednesday at 2 PM in the same room, and B confirms that they will inform the rest of the team about the change.

    Semantic Kernel 的這個外掛程式我用了 GPT-4o Kimi 都回復的是英文,我感覺這個內建的這個 Semantic Kernel 外掛程式還是不夠完善。

    我們可以看一下 SummarizeConversation 方法的 Prompts 定義

    BEGIN CONTENT TO SUMMARIZE:
    {{$INPUT}}
    END CONTENT TO SUMMARIZE.
    Summarize the conversation in 'CONTENT TO SUMMARIZE', identifying main points of discussion and any conclusions that were reached.
    Do not incorporate other general knowledge.
    Summary is in plain text, in complete sentences, with no markup or tags.
    BEGIN SUMMARY:

    簡要理解一下這個提示詞:

  • 開始標記: BEGIN CONTENT TO SUMMARIZE : 這個標記清晰地指示了摘要內容的開始。

  • 輸入占位符: {{$INPUT}} 這是一個占位符,用於插入需要被摘要的對話或文本內容。

  • 結束標記: END CONTENT TO SUMMARIZE . 這個標記同樣清晰地指示了摘要內容的結束。

  • 摘要指導:提供了對摘要的具體要求,包括辨識對話的主要討論點和結論,並且強調不要包含外部的一般知識。

  • 格式要求:指出摘要應該是純文本,用完整的句子表達,不包含任何標記或標簽。

  • 摘要開始標記: BEGIN SUMMARY : 這個標記指示了摘要部份的開始。

  • 針對上述我們發現的問題: 會話摘要全部是中文的問題 我覺得可以進行提示詞的最佳化

    最佳化的第一點內容是: 總結應選擇最切合內容的語言 in the language that best fits the content.

    @"BEGIN CONTENT TO SUMMARIZE:
    {{$INPUT}}
    END CONTENT TO SUMMARIZE.
    Please summarize the conversation, highlighting the main points and any conclusions reached, in the language that best fits the content. Do not incorporate any external general knowledge. The summary should be in plain text, in complete sentences, without any markup or tags.
    BEGIN SUMMARY:

    我們自訂一個外掛程式測試一下,建立一個 CustomConversationSummaryPlugin 的外掛程式,這個和原生 SummarizeConversation 外掛程式只有 Prompts 有區別

    privateconstint MaxTokens = 1024;
    privatereadonly KernelFunction _summarizeConversationFunction;
    publicCustomConversationSummaryPlugin()
    {

    PromptExecutionSettings settings = new()
    {
    ExtensionData = new Dictionary<stringobject>()
    {
    "Temperature"0.1 },
    "TopP"0.5 },
    "MaxTokens", MaxTokens }
    }
    };
    this._summarizeConversationFunction = KernelFunctionFactory.CreateFromPrompt(
    CustomConversationSummaryPlugin.SummarizeConversationDefinition,
    description: "Given a p of a conversation transcript, summarize the part of the conversation.",
    executionSettings: settings);
    }
    ///<summary>
    /// Given a long conversation transcript, summarize the conversation.
    ///</summary>
    ///<param name="input">A long conversation transcript.</param>
    ///<param name="kernel">The <see cref="Kernel"/> containing services, plugins, and other state for use throughout the operation.</param>
    [KernelFunction, Description("Given a long conversation transcript, summarize the conversation.")]
    public Task<stringSummarizeConversationAsync(
    [Description("A long conversation transcript."
    )] string input,
    Kernel kernel)
     =>
    ProcessAsync(this._summarizeConversationFunction, input, kernel);
    privatestaticasync Task<stringProcessAsync(KernelFunction func, string input, Kernel kernel)
    {
    List<string> lines = TextChunker.SplitPlainTextLines(input, MaxTokens);
    List<string> paragraphs = TextChunker.SplitPlainTextParagraphs(lines, MaxTokens);
    string[] results = newstring[paragraphs.Count];
    for (int i = 0; i < results.Length; i++)
    {
    // The first parameter is the input text.
    results[i] = (await func.InvokeAsync(kernel, new() { ["input"] = paragraphs[i] }).ConfigureAwait(false))
    .GetValue<string>() ?? string.Empty;
    }
    returnstring.Join("\n", results);
    }





    Kernel 物件註冊自訂外掛程式

    var customCustomConversationSummaryPlugin = kernel.ImportPluginFromType<CustomConversationSummaryPlugin>();

    新跑一邊測試一下:

    Generated Summary:在這段對話中,A和B討論了安排下周會議的時間。B建議周三或周四比較合適,因為那時大家的日程相對空閑。A決定透過信件詢問其他同事的意見,然後做出最終決定 。在信件中,A提議將會議安排在周四下午兩點,地點是會議室A。然而,D表示周四下午有其他安排,請求將會議改到周三下午。A同意了D的請求,將會議時間調整為周三下午兩點,地點仍然是會議室A。B表示會通知其他同事關於時間變動的情況。

    可以看到滿足我們的需求了,根據我們輸入生成的摘要資訊沒有問題了。

    這個外掛程式對於我們的聊天會話也是十分有用,對話歷史記錄隨著不斷聊天,訊息越來越多,那每次對話消耗的 token 也是不斷增加,此時 ConversationSummaryPlugin 外掛程式的就可以幫助我們對聊天記錄進行摘要總結,提高聊天效率。

    提取會話行動項

    辨識對話記錄中的動作項( action items )是一種重要的溝通技巧,它有助於提高效率、確保任務的完成和促進團隊協作。

    使用場景包括:

  • 會議記錄:在會議結束後,快速生成包含所有動作項的摘要,便於團隊成員執行和跟蹤。

  • 計畫管理:在計畫討論中,辨識和記錄關鍵的裏程碑和任務,確保計畫按時進展。

  • 客戶服務:在客戶溝通中,記錄客戶的請求和需要采取的行動,以提供更好的服務和支持。

  • 團隊協作工具:整合到團隊協作平台中,幫助團隊成員共享和協調任務。

  • 個人生產力:個人使用該外掛程式來管理自己的任務和待辦事項,提高個人效率。

  • 法律和合規性:在需要確保對話內容符合特定法規或標準的情況下,辨識必要的行動以確保合規。

  • 要完成這個需要用到 ConversationSummaryPlugin 外掛程式的 GetConversationActionItems 方法

    Console.WriteLine("======== SamplePlugins - Conversation Summary Plugin - Action Items ========");
    {
    FunctionResult summary = await kernel.InvokeAsync(
    conversationSummaryPlugin["GetConversationActionItems"], new() { ["input"] = chatTranscript });
    Console.WriteLine($"Generated Action Items:{summary.ToString()}");
    Console.WriteLine(summary.GetValue<string>());
    }

    輸出:

    {
    "actionItems": [
    {
    "owner""A",
    "actionItem""發信件詢問大家的意見",
    "dueDate""",
    "status""Open",
    "notes""今天會發"
    },
    {
    "owner""B",
    "actionItem""在群裏提醒大家留意信件",
    "dueDate""",
    "status""Open",
    "notes"""
    },
    {
    "owner""B",
    "actionItem""通知其他同事時間的變動",
    "dueDate""",
    "status""Open",
    "notes""讓大家知道時間的變動"
    }
    ]
    }

    提取會話的主題

    用於對話摘要的工具或外掛程式,它的作用是幫助使用者快速辨識和總結對話中的主要話題。

    使用場景可能包括但不限於:

  • 企業內部會議的快速摘要和資訊整理。

  • 客戶服務對話的分析,以辨識服務改進點。

  • 社交媒體或論壇討論的監控和摘要。

  • 教育環境中的課堂討論摘要。

  • 法律咨詢或案件討論的記錄和審查。

  • 要完成這個功能需要用到 ConversationSummaryPlugin 外掛程式的 GetConversationTopics 方法

    使用:

    Console.WriteLine("======== SamplePlugins - Conversation Summary Plugin - Topics ========");
    FunctionResult summary = await kernel.InvokeAsync(
    conversationSummaryPlugin["GetConversationTopics"], new() { ["input"] = chatTranscript });
    Console.WriteLine($"Generated Topics:{summary.ToString()}");

    輸出:

    Generated Topics:
    {
    "topics": [
    "Work busy",
    "Schedule meeting",
    "Wednesday or Thursday",
    "Confirm colleagues' availability",
    "Email for opinions",
    "Meeting reschedule",
    "Thursday 2 PM",
    "Change to Wednesday 2 PM",
    "Notify colleagues"
    ]
    }

    最後

    剩下的外掛程式我們後續章節在講解吧,本章重點講解了 ConversationSummaryPlugin 會話總結外掛程式的使用。

    範例程式碼

    本文原始碼 [2]

    參考資料

    [1]

    Plugins 地址: https://github.com/microsoft/semantic-kernel/tree/main/dotnet/src/Plugins

    [2]

    本文原始碼: https://github.com/Dong-Ruipeng/SK-WorkBook