iT邦幫忙

2025 iThome 鐵人賽

DAY 23
0

前面的文章中,我們已經打造了強大的 AI Agent,他們會根據當前對話(ChatHistory)來判斷是否需要呼叫工具(Function Calling)來完成任務。但各位有沒有發現一個問題?一旦你跟 Agent 說:「我喜歡吃辣,而且我的名字是王小明。」然後你結束對話,下次再來,Agent 就把這些細節忘得一乾二淨了!

這就好比你的專屬服務生,每接待你一次,腦袋就重啟一次。這樣怎麼能提供「滿漢全席」級的客製化服務呢?

為了讓我們的 Agent 成為真正有溫度的 AI 夥伴,我們需要一個專門的「外部記憶層」,這就是今天要介紹的明星食材:Mem0

Agent 的短期記憶 vs. Mem0 的長期記憶

Semantic Kernel 中,Agent 的短期記憶主要由 ChatHistory 維護。這段記憶很寶貴,但有幾個限制:

  1. Token 限制: 歷史對話紀錄會隨著時間拉長而佔用大量的 Token,最終會被截斷,導致遺忘。
  2. 跨對話遺忘: 當你開一個新的 AgentThread 時,之前的對話內容就消失了。

Mem0 的出現就是為了解決這個痛點。它是一個開源的記憶層(Memory Layer),專門用於儲存和檢索長期、個人化、跨對話的上下文資訊。它不只是普通的資料庫,它能將你的偏好、人稱、甚至情緒狀態都轉化成向量,並在需要時精準地「提醒」Agent。

整合 Mem0:讓 Agent 成為你的老朋友

將 Mem0 整合進 Semantic Kernel Agent Framework 非常直覺。我們只需要引入 Mem0Provider,並在建立 Agent 時將其注入即可。

假設我們希望 Agent 記住使用者在專案中習慣使用的程式語言。

建立具備 Mem0 長期記憶的 Agent

我們透過 KernelBuilder 註冊服務並建立 ChatCompletionAgent。關鍵在於來注入記憶服務。

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using System;
using System.Threading.Tasks;
using Microsoft.SemanticKernel.Memory;
using Microsoft.Extensions.Configuration;
using System.Net.Http.Headers;

// 1. 建立 Kernel 核心
var config = new ConfigurationBuilder()
    .AddUserSecrets<Program>()
    .Build();
var builder = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion(
        modelId: "gpt-5-nano",
        apiKey: config["OpenAI:ApiKey"]!);

var kernel = builder.Build();

// 2. 建立 Mem0 Provider
// Mem0 Provider 會將 Agent 的對話內容智能地提煉出關鍵事實 (Fact) 並儲存。
using var httpClient = new HttpClient()
{
    BaseAddress = new Uri("https://api.mem0.ai")
};
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", config["mem0:ApiKey"]!);

var mem0Provider = new Mem0Provider(httpClient, options: new()
{
    UserId = Guid.NewGuid().ToString()
});
await mem0Provider.ClearStoredMemoriesAsync();
// 3. 建立並配置 Agent,注入 Mem0 Provider
var agent = new ChatCompletionAgent
{
    Kernel = kernel,
    // 賦予 Agent 一個角色指令
    Instructions = "你是一個專業的軟體工程師助手,你應該記得我的偏好並以此來提供幫助。",
};

// 建立 Agent 執行緒
// 每次執行緒建立,都是一個「新的會話」
var thread = new ChatHistoryAgentThread();
// 關鍵步驟:將 Mem0 Provider 注入 Agent
thread.AIContextProviders.Add(mem0Provider);
// --- 第一次會話 (建立記憶) ---
Console.WriteLine($"--- 會話 1 開始:建立偏好 ---");
await foreach (ChatMessageContent response in agent.InvokeAsync("我的工作主要使用 C# 語言來開發 Web API,請記住這個偏好。", thread))
{
    Console.WriteLine($"Agent: {response.Content}");
}

// 模擬 Mem0 儲存:Mem0Provider 在此步驟的背後,已經將「使用者偏好:C# 語言」儲存起來。
Console.WriteLine("\n*Agent已將偏好存入Mem0記憶庫*\n");

// --- 第二次會話 (測試記憶) ---
// 模擬使用者過了一段時間回來,建立一個全新的執行緒
thread = new ChatHistoryAgentThread();
thread.AIContextProviders.Add(mem0Provider);

Console.WriteLine($"--- 會話 2 開始:重新連接,測試記憶 ---");
await foreach (ChatMessageContent response in agent.InvokeAsync("請幫我寫一個簡單的 Log 檔案清理程式的範例。", thread))
{
    Console.WriteLine($"Agent: {response.Content}");
}
// 即使是新的執行緒,Agent 也會先從 Mem0 提取記憶(「使用者偏好:C#」),然後生成 C# 語言的 Log 清理範例。

在第二次會話的 thread.InvokeAsync 之前,Mem0Provider 會自動執行一個 檢索(Retrieval) 步驟。它會根據你當前的問題(「寫一個 Log 檔案清理程式」),去 Mem0 記憶庫裡尋找相關的「事實」和「偏好」(例如「使用者主要使用 C#」)。這些檢索到的記憶會被作為額外的 System Prompt 或 Context 注入到模型中,從而讓 Agent 表現出「記得」你的樣子。

記憶的魔力:跨越時間的客製化

透過 Mem0,我們的 Agent 不再是每次都從零開始的「路人甲」,而是真正了解你的「老朋友」。它可以記住:

  • 技術偏好: 喜歡 C# 或 Python?偏好 NoSQL 或關聯式資料庫?
  • 個人資訊: 你的職位、你上次問的問題的進度。
  • 服務歷史: 上次點了什麼菜?下次可能會想點什麼?

這項技術極大地提升了企業級應用中的使用者體驗和連續性,讓你的 AI 全餐不僅好吃,還能貼心入微!


完整程式碼範例


上一篇
Day 22: 最強大腦會議:Magentic Orchestration 深度解析
下一篇
Day 24: 會議白板:使用 WhiteboardProvider 捕捉短期關鍵資訊
系列文
AI 全餐,好吃嗎?用 Semantic Kernel 打造你的客製化滿漢全席!24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言