在 C# 中调用千问(Qwen)、DS(通义千问)和智谱(如 GLM)等大模型时,记忆机制(Memory) 和 Token 消耗优化 是提升交互体验和降低成本的关键。本文将从技术实现、代码示例、优化策略等方面详细解析如何在 C# 中实现记忆功能并节省 Token。
这是最基础的记忆形式,适用于对话长度较短的场景。它会将所有对话消息按顺序存储,并在每次调用时以字符串或消息列表的形式返回。
示例代码:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
using LangChain.Memory; using LangChain.ChatModels;
// 初始化记忆 var memory = new ConversationBufferMemory();
// 保存上下文 memory.SaveContext(new Dictionary<string, object> { { "input", "你好" } }, new Dictionary<string, object> { { "output", "您好!有什么需要帮助的?" } });
// 加载记忆 var history = memory.LoadMemoryVariables(new Dictionary<string, object>()); Console.WriteLine(history["history"]); |
说明:此方法适合简单的多轮对话,但不适用于长对话或需要摘要的场景。
对于长对话,可以使用 ConversationSummaryMemory 来减少 Token 消耗。该模块通过生成摘要的方式,保留关键信息,同时丢弃冗余内容。
示例代码:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
using LangChain.Memory; using LangChain.ChatModels;
// 初始化摘要记忆 var summaryMemory = new ConversationSummaryMemory( llm: new ChatTongyi(), // 使用通义千问模型 maxTokenLimit: 2000 // 设置最大 Token 限制 );
// 保存上下文 summaryMemory.SaveContext(new Dictionary<string, object> { { "input", "你好" } }, new Dictionary<string, object> { { "output", "您好!有什么需要帮助的?" } });
// 加载记忆 var history = summaryMemory.LoadMemoryVariables(new Dictionary<string, object>()); Console.WriteLine(history["summary"]); |
说明:通过设置 maxTokenLimit,可以控制 Token 消耗,避免超出模型限制。
Kernel Memory 是微软开源的跨语言记忆框架,支持非结构化数据(如 PDF、网页、Markdown 等)的自动切块、向量化、索引,并支持语义检索。
示例代码:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
using Microsoft.KernelMemory;
// 初始化 Kernel Memory var memory = new KernelMemoryBuilder() .WithVectorDatabase(new QdrantClient("http://localhost:6333")) .Build();
// 导入文档 await memory.ImportDocumentAsync("docs/report.pdf");
// 查询记忆 var results = await memory.SearchAsync("项目背景"); foreach (var result in results) { Console.WriteLine(result.Content); } |
说明:Kernel Memory 不依赖数据库,而是通过向量数据库(如 Qdrant、Azure AI Search)进行语义检索,适合长期记忆和复杂查询。
通过 ConversationSummaryMemory 或 ConversationBufferMemory,将长对话压缩为摘要,减少 Token 消耗。
示例代码:
|
1 2 3 4 5 6 7 |
var summaryMemory = new ConversationSummaryMemory( llm: new ChatTongyi(), maxTokenLimit: 2000 );
// 保存上下文 summaryMemory.SaveContext(new Dictionary<string, object> { { "input", "你好" } }, new Dictionary<string, object> { { "output", "您好!有什么需要帮助的?" } }); |
说明:通过设置 maxTokenLimit,可以控制 Token 消耗,避免超出模型限制。
对常见问题或重复请求进行缓存,避免重复调用 LLM。
示例代码:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
using System.Collections.Generic;
public class CacheManager { private readonly Dictionary<string, string> _cache = new Dictionary<string, string>();
public string Get(string key) { return _cache.ContainsKey(key) ? _cache[key] : null; }
public void Set(string key, string value) { _cache[key] = value; } }
// 使用缓存 var cache = new CacheManager(); if (cache.Get("user_query") == null) { var response = await CallLLM("用户问题"); cache.Set("user_query", response); } else { Console.WriteLine("从缓存中获取结果:" + cache.Get("user_query")); } |
说明:缓存机制可以显著减少 Token 消耗,尤其适用于重复性高的任务。
对于简单任务,使用小模型(如 7B 参数级)进行路由判断,只有复杂任务才调用大模型。
示例代码:
|
1 2 3 4 5 6 7 8 |
var smallModel = new ChatTongyi(model: "qwen-turbo"); var largeModel = new ChatTongyi(model: "qwen-plus");
var response = await smallModel.InvokeAsync("用户问题"); if (response.Contains("需要进一步分析")) { response = await largeModel.InvokeAsync("用户问题"); } |
说明:通过分层模型调用,可以有效降低 Token 消耗。
|
1 2 3 |
dotnet add package Microsoft.KernelMemory --version 7.0.0 dotnet add package LangChain --version 0.1.17 dotnet add package dashscope --version 1.0.0 |
|
1 |
Environment.SetEnvironmentVariable("DASHSCOPE_API_KEY", "your-api-key-here"); |
|
1 2 3 4 5 6 7 8 |
using LangChain.ChatModels; using LangChain.Agents;
var llm = new ChatTongyi( model: "qwen-turbo", temperature: 0.7, maxTokens: 1024 ); |
|
1 2 3 4 5 6 7 8 9 10 11 |
var memory = new ConversationSummaryMemory( llm: llm, maxTokenLimit: 2000 );
// 保存上下文 memory.SaveContext(new Dictionary<string, object> { { "input", "你好" } }, new Dictionary<string, object> { { "output", "您好!有什么需要帮助的?" } });
// 加载记忆 var history = memory.LoadMemoryVariables(new Dictionary<string, object>()); Console.WriteLine(history["summary"]); |
|
1 2 3 4 5 6 7 8 9 |
var agent = initialize_agent( tools: new List<Tool>(), llm: llm, agentType: AgentType.ZeroShotReActDescription, verbose: true );
var response = await agent.RunAsync("用户问题"); Console.WriteLine(response); |
在 C# 中调用千问、DS、智谱等 AI 时,记忆机制 和 Token 消耗优化 是提升交互体验和降低成本的关键。通过以下方式可以实现:
这些方法不仅能够提升 AI 的智能水平,还能显著降低 Token 消耗,提高系统的稳定性和效率。