iT邦幫忙

2025 iThome 鐵人賽

DAY 7
0
生成式 AI

當 .NET 遇見 AI Agents:用 Semantic Kernel × MCP 打造智慧協作應用系列 第 7

Day 7: Semantic Kernel Plugins 複雜性參數支援度

  • 分享至 

  • xImage
  •  

在前面幾天的內容中,探討了 Function Calling 的基本概念,也實作了簡單的 Plugin 來讓 AI Agent 具備調用工具的能力。但隨著業務需求的複雜化,很快就會遇到一個問題:當 Plugin 的參數變得複雜時,Semantic Kernel 還能處理得好嗎?

例如:你需要設計一個人力資源管理的 AI Agent,它不只要能查詢單一員工資訊,還要能根據「部門、職級、技能組合、工作經驗年數、是否遠端工作」等多個維度進行複雜的員工搜尋。這時候,傳統的 string employee_name 這種簡單參數就不夠用了。今天就來深入探討 Semantic Kernel 對於複雜參數的支援能力,從最基本的原始型別開始,一路進展到自定義物件、陣列進階參數類型。

從簡單開始:基本參數類型

讓我們先回顧一下 Semantic Kernel 對基本參數類型的支援。在之前的訂單查詢範例中,我們使用了最簡單的參數定義:

[KernelFunction]
[Description("查詢訂單狀態")]
public string Get_Order_Status(
    [Description("訂單編號")] string order_id)
{
    // 實作邏輯
}

這種寫法清楚明瞭,AI 模型能夠輕易理解需要一個字串參數,並且知道這個參數代表什麼,但當我們的業務邏輯變得複雜時,這些基本型別就顯得力不從心了,我想應該很少開發者會喜歡有 10 個參數的函式。

挑戰來了:複雜的業務需求

假設我們要建立一個人力資源管理的 Plugin,需要支援以下這種複雜的查詢需求:

「幫我找出工程部門或銷售部門的資深員工,必須具備程式設計和專案管理技能,工作經驗在 3-8 年之間,並且是遠端工作者。」

這個需求包含了:

  • 多個部門選擇(工程部門、銷售部門)
  • 特定職級(資深員工)
  • 技能組合要求(程式設計 + 專案管理)
  • 經驗年數範圍(3-8 年)
  • 工作模式偏好(遠端工作)

如果我們試圖用基本參數來處理這個需求,函式簽名可能會變成這樣:

// 這樣的設計會讓人抓狂...
public string SearchEmployees(
    string department1, string department2, string department3,
    string level1, string level2,
    string skill1, string skill2, string skill3,
    int minExperience, int maxExperience,
    bool isRemoteWorker)

不僅參數過多,而且無法彈性處理不同數量的部門或技能要求。更糟糕的是,AI 模型也很難理解這些參數之間的關聯性。

進階武器:複雜參數類型支援

幸運的是,Semantic Kernel 支援複雜參數類型,讓我們能夠設計出更優雅、更具表達力的 Plugin API。

陣列參數支援

當我們需要處理多選情況時,陣列是最自然的選擇,這樣的設計讓我們可以靈活傳入多個部門、職級和技能,並且對經驗年數和工作模式進行篩選。AI 模型也能夠理解這些參數的意義,並且根據使用者的需求來填寫。

[KernelFunction]
[Description("根據複雜條件搜尋員工,支援多維度篩選")]
public async Task<string> SearchEmployees(
    [Description("要搜尋的部門陣列")] Department[]? departments = null,
    [Description("員工職級陣列")] EmployeeLevel[]? levels = null,
    [Description("必備技能陣列")] SkillCategory[]? requiredSkills = null,
    [Description("最少工作經驗年數")] int minExperience = 0,
    [Description("最多工作經驗年數,不限制則輸入-1")] int maxExperience = -1,
    [Description("是否限定遠端工作者,true=僅遠端,false=僅非遠端,空白=不限制")] string remoteOnly = "")

複雜物件參數支援

但是,當參數數量持續增加時,即便是陣列也會讓函式簽名變得冗長。這時候,可以考慮使用自定義物件來封裝相關參數,這種方式的好處是:

  • 更清楚的語意:參數被邏輯性地組織在一起
  • 更好的可維護性:新增或修改參數只需要調整物件定義
  • 更強的可讀性:函式簽名變得簡潔明瞭
public class SearchEmployeesRequest
{
    [Description("要搜尋的部門陣列")]
    public Department[]? Departments { get; set; }

    [Description("員工職級陣列")]
    public EmployeeLevel[]? Levels { get; set; }

    [Description("必備技能陣列")]
    public SkillCategory[]? RequiredSkills { get; set; }

    [Description("最少工作經驗年數")]
    public int MinExperience { get; set; } = 0;

    [Description("最多工作經驗年數,不限制則輸入-1")]
    public int MaxExperience { get; set; } = -1;

    [Description("是否限定遠端工作者,true=僅遠端,false=僅非遠端,空白=不限制")]
    public string RemoteOnly { get; set; } = "";
}

然後函式就可以簡化為:

[KernelFunction]
[Description("根據複雜條件搜尋員工,支援多維度篩選")]
public async Task<string> SearchEmployees(
    [Description("員工搜尋條件")] SearchEmployeesRequest searchRequest)

實作細節:讓 AI 更好理解你的參數

描述的藝術

良好的參數描述是提升 AI 理解能力的關鍵。以下是一些實用的描述技巧:

// 描述過於簡潔
[Description("部門")]
public Department[]? Departments { get; set; }

// 描述清楚且具體
[Description("要搜尋的部門陣列,可多選,不指定則搜尋所有部門")]
public Department[]? Departments { get; set; }

// 沒有說明特殊值的含義
[Description("最大經驗年數")]
public int MaxExperience { get; set; }

// 說明特殊值和邊界條件
[Description("最多工作經驗年數,不限制則輸入-1")]
public int MaxExperience { get; set; } = -1;

預設值的策略

合理的預設值可以讓 AI 更容易使用你的函式:

// 為數值參數提供合理預設值
public int MinExperience { get; set; } = 0;  // 最小值通常是 0

// 為可選參數使用 null
public Department[]? Departments { get; set; }  // null 表示不篩選

// 為字串參數使用空字串表示「不指定」
public string RemoteOnly { get; set; } = "";

AI 互動測試

實際測試 AI 是否能正確理解和使用這些複雜參數,非常重要,應該測試各種不同的使用者輸入,包含複雜的條件組合,以確保 AI 能夠根據描述正確填寫參數:

使用者:「幫我找工程部門的資深員工,要有程式設計技能」
AI:正確調用 SearchEmployees(departments: [Engineering], levels: [Senior], requiredSkills: [Programming])

使用者:「找 5 年以上經驗的遠端工作者」
AI:正確調用 SearchEmployees(minExperience: 5, remoteOnly: "true")

性能考量:複雜參數的成本

雖然複雜參數帶來了更強的表達能力,但我們也需要考慮Token 使用量影響,複雜參數會增加 Function Calling 的 token 消耗:

  • 參數描述需要更多 token
  • 複雜物件的 JSON 序列化佔用更多 token
  • AI 生成複雜參數值需要更多推理 token

結語

Semantic Kernel 對複雜參數的支援為我們打開了建構精緻 AI Agent 的大門。從基本的字串、數值參數,到進階的陣列、自定義物件,有了充分的工具設計來應對各種複雜的業務場景。

但技術能力只是基礎,真正的挑戰在於如何設計出既能被 AI 正確理解,又能滿足業務需求的 Plugin API。開發者們需要意識到,撰寫這些 function 是給 AI 使用的,不是給人類開發者使用的,所以 function 讓 AI 模型可以理解,這件事很重要。


上一篇
Day 6: Semantic Kernel Function Choice Behavior 深度解析:精確控制 AI Agent 的函式呼叫行為
系列文
當 .NET 遇見 AI Agents:用 Semantic Kernel × MCP 打造智慧協作應用7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言