星点匠心建站 星点匠心建站XD JIANXIN STUDIO
400-883-9527 免费定制方案
ARTICLE DETAIL

资讯详情

深耕新锐建站与运营推广的一线实战洞察。

AI 对话太长怎么办?用“记忆汇总”给上下文瘦身

AI 对话太长怎么办?用“记忆汇总”给上下文瘦身 目录什么是记忆汇总整体思路完整代码运行效果写在最后AI 聊天一开始通常很顺畅但对话越来越长以后问题也会慢慢出现输入 Token 越来越多调用成本不断上涨模型的响应速度也可能受到影响。更麻烦的是我们又不能简单地删除旧消息。用户前面提到的预算、偏好和产品信息后面可能还会用到。这时候可以给 AI 加一个“记忆汇总”机制。什么是记忆汇总说白了就是当聊天记录超过一定长度时让另一个模型把前面的对话整理成一份简短摘要。原始聊天记录可以被压缩但里面的重要信息会继续保留下来。后面的对话不再携带全部历史消息而是携带摘要和最近几轮消息。这样既能控制上下文长度也能让 AI 继续记住关键内容。整体思路下面的示例使用 Azure OpenAI 作为主对话模型负责正常回答用户问题。本地 Ollama 模型负责整理历史对话。总结任务相对简单没有必要全部交给主模型处理用本地模型还能减少调用成本。当上下文超过 300 个 Token 时SummarizationCompactionStrategy 会自动触发汇总。这里把 300 设置得比较小主要是为了方便演示。实际项目中可以根据模型的上下文窗口和业务成本调整。minimumPreservedGroups 设置为 2表示压缩历史消息时至少保留最近两个消息组。这样既能留下短期上下文又能避免历史记录无限增长。真正决定 AI“记住什么”的是 summarizationPrompt。示例里明确要求保留第一个产品、所有价格、用户预算、用户偏好以及后续可能用到的信息。总结模型不需要记住每句话只需要留下真正有价值的内容。完整代码​​​​​​​using Azure.AI.OpenAI; using Microsoft.Agents.AI; using Microsoft.Agents.AI.Compaction; using Microsoft.Extensions.AI; using OllamaSharp; using OllamaSharp.Models; using System.ClientModel; using System.Text.Json; #pragma warning disable var aiConfig new AIConfig.AzureOpenAIConfig(gpt-5.6-luna); var credential new ApiKeyCredential(aiConfig.Key); var options new JsonSerializerOptions() { WriteIndented true, Encoder System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; // 主对话模型负责响应用户输入。 var agentChatClient new AzureOpenAIClient(new Uri(aiConfig.Endpoint), credential) .GetChatClient(aiConfig.DeploymentName) .AsIChatClient(); var aiConfigOllama new AIConfig.OllamaConfig(qwen); // 总结模型专门用于在上下文压缩时生成摘要。 var summarizerChatClient new ThinkDisabledChatClient( new OllamaApiClient(aiConfigOllama.Endpoint, aiConfigOllama.Model) ); // 也可以使用 Azure OpenAI 完成总结。 // var summarizerChatClient new AzureOpenAIClient( // new Uri(aiConfig.Endpoint), // credential // ) // .GetChatClient(aiConfig.DeploymentName) // .AsIChatClient(); var compactionStrategy new SummarizationCompactionStrategy( chatClient: summarizerChatClient, trigger: CompactionTriggers.TokensExceed(300), minimumPreservedGroups: 2, summarizationPrompt: 为购物助手总结之前的对话内容。 保留以下信息 - 用户询问的第一个产品 - 所有产品价格 - 用户的预算 - 用户偏好 - 后续对话所需的重要信息 务必简洁明了内容真实可靠。 ); // 为智能体接入上下文压缩能力避免长对话导致上下文膨胀。 var agent agentChatClient .AsBuilder() .UseAIContextProviders(new CompactionProvider(compactionStrategy)) .BuildAIAgent( new ChatClientAgentOptions { Name Assistant, ChatOptions new() { // 通过系统提示词约束智能体角色和记忆重点。 Instructions 您是一位得力的购物助手。请记住用户偏好和产品信息。, }, } ); var session await agent.CreateSessionAsync(); // 使用多轮输入模拟一段会触发上下文压缩的购物对话。 var list new Liststring { 我想买一台1000美元以下的笔记本电脑。, 我主要用它来编程和视频通话。, 我找到的那台笔记本电脑售价999.99美元。, 我还需要一个键盘。键盘售价79.99美元。, 我不喜欢RGB背光。我更喜欢静音键盘。, 我还需要一个鼠标。鼠标售价29.99美元。, 请记住便携性对我来说很重要。, 我问的第一个产品是什么 }; foreach (var input in list) { Console.WriteLine(您说 input); var response await agent.RunAsync(input, session); Console.WriteLine(助手说); Console.WriteLine(response.Text); Console.ForegroundColor ConsoleColor.Yellow; Console.WriteLine( $总Token数:{response.Usage.TotalTokenCount}\n $输入Token数{response.Usage.InputTokenCount}\n $输出Token数{response.Usage.OutputTokenCount}\n $缓存输入Token数{response.Usage.CachedInputTokenCount}\n $推理Token数{response.Usage.ReasoningTokenCount} ); Console.ResetColor(); } var serializedSession await agent.SerializeSessionAsync(session); PrintMessageGroups( serializedSession, options, SummarizationCompactionStrategy ); void PrintMessageGroups( JsonElement serializedSession, JsonSerializerOptions options, string propertyName) { if (serializedSession.TryGetProperty(stateBag, out var stateBag) stateBag.TryGetProperty(propertyName, out var strategy) strategy.TryGetProperty(messagegroups, out var messageGroups) messageGroups.ValueKind JsonValueKind.Array) { foreach (var item in messageGroups.EnumerateArray()) { if (item.TryGetProperty(isExcluded, out var isExcluded) isExcluded.GetBoolean()) { Console.ForegroundColor ConsoleColor.Red; } else { Console.ForegroundColor ConsoleColor.Green; } Console.WriteLine(JsonSerializer.Serialize(item, options)); } } Console.ResetColor(); } // 对 Ollama 客户端进行简单封装统一关闭 think 模式 // 避免总结时输出额外推理内容。 sealed class ThinkDisabledChatClient(IChatClient inner) : IChatClient { public TaskChatResponse GetResponseAsync( IEnumerableChatMessage messages, ChatOptions? options null, CancellationToken cancellationToken default) { options ?? new ChatOptions(); options.AddOllamaOption(OllamaOption.Think, false); Console.ForegroundColor ConsoleColor.Red; Console.WriteLine(开始汇总了……); Console.ResetColor(); return inner.GetResponseAsync( messages, options, cancellationToken ); } public IAsyncEnumerableChatResponseUpdate GetStreamingResponseAsync( IEnumerableChatMessage messages, ChatOptions? options null, CancellationToken cancellationToken default) { options ?? new ChatOptions(); options.AddOllamaOption(OllamaOption.Think, false); Console.ForegroundColor ConsoleColor.Red; Console.WriteLine(开始汇总了……); Console.ResetColor(); return inner.GetStreamingResponseAsync( messages, options, cancellationToken ); } public object? GetService( Type serviceType, object? serviceKey null) inner.GetService(serviceType, serviceKey); public void Dispose() inner.Dispose(); }运行效果程序会模拟一段购物对话。用户先后提到了笔记本电脑、键盘、鼠标、预算和使用偏好。当 Token 数量超过限制后本地模型会开始汇总旧对话。最后即使早期消息已经被压缩用户再问“我问的第一个产品是什么”主模型仍然能够回答“笔记本电脑”。程序最后还会输出会话里的消息组。红色表示已经被排除出活动上下文的旧消息绿色表示当前仍然保留的内容方便我们观察压缩结果。写在最后AI 记忆并不等于把所有聊天记录一直塞进上下文。更实用的做法是保留最近的对话再把更早的内容整理成摘要。主模型负责聊天小模型负责整理记忆。上下文更短了重要信息还在这就是“记忆汇总”的核心。引入地址
返回列表