前面的文章中,我們已經打造了強大的 AI Agent,他們會根據當前對話(ChatHistory
)來判斷是否需要呼叫工具(Function Calling)來完成任務。但各位有沒有發現一個問題?一旦你跟 Agent 說:「我喜歡吃辣,而且我的名字是王小明。」然後你結束對話,下次再來,Agent 就把這些細節忘得一乾二淨了!
這就好比你的專屬服務生,每接待你一次,腦袋就重啟一次。這樣怎麼能提供「滿漢全席」級的客製化服務呢?
為了讓我們的 Agent 成為真正有溫度的 AI 夥伴,我們需要一個專門的「外部記憶層」,這就是今天要介紹的明星食材:Mem0!
在 Semantic Kernel 中,Agent 的短期記憶主要由 ChatHistory
維護。這段記憶很寶貴,但有幾個限制:
AgentThread
時,之前的對話內容就消失了。Mem0 的出現就是為了解決這個痛點。它是一個開源的記憶層(Memory Layer),專門用於儲存和檢索長期、個人化、跨對話的上下文資訊。它不只是普通的資料庫,它能將你的偏好、人稱、甚至情緒狀態都轉化成向量,並在需要時精準地「提醒」Agent。
將 Mem0 整合進 Semantic Kernel Agent Framework 非常直覺。我們只需要引入 Mem0Provider
,並在建立 Agent 時將其注入即可。
假設我們希望 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 不再是每次都從零開始的「路人甲」,而是真正了解你的「老朋友」。它可以記住:
這項技術極大地提升了企業級應用中的使用者體驗和連續性,讓你的 AI 全餐不僅好吃,還能貼心入微!