如何让AI拥有记忆
AI是个很笨的东西,做什么是需要我们教的
AI可以帮我们聚焦需要的信息,但是无法凭空产生,所以怎么让AI记住我们的信息呢?
先举一个小例子,我们简单调用一下
using Microsoft.Extensions.AI; using OpenAI.Chat; using System; using System.ClientModel; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace StudyAI { public static class AIHelper { static string apiKey = ""; static string url = "";//专属 public static async Task ChatSimple() { IChatClient client = new ChatClient("qwen3-vl-plus", new ApiKeyCredential(apiKey), new OpenAI.OpenAIClientOptions() { Endpoint = new Uri(url) } ).AsIChatClient(); while (true) { Console.Write(">>>>>>"); var question = Console.ReadLine(); if (question == null) continue; try { //同步输出 var res = await client.GetResponseAsync(question); Console.WriteLine(res.Text); Console.WriteLine("单次token总消耗" + res.Usage?.TotalTokenCount); //流式输出 //await foreach (var update in client.GetStreamingResponseAsync(question)) //{ // Console.Write(update.Text); //} //Console.WriteLine(); } catch (Exception ex) { Console.WriteLine($"发生异常: {ex.Message}"); } } } } }
运行:
>>>>>>我96年出生的 你好!96年出生的话,2025年你就是 **29周岁**(虚岁30岁)?? 这个年纪正处于人生很关键又充满可能性的阶段——事业可能刚站稳脚跟,感情、生活、自我成长都在快速变化中。 你最近在关注什么方向呢?比如: - 职业发展/转行/副业探索? - 感情状态或人生规划? - 健康、理财、学习新技能? - 或者单纯想聊聊“96年这代人”的共同记忆/困惑? 我很乐意陪你一起梳理、分析,或者就当个树洞~ ?? 单次token总消耗162
>>>>>>我今年多大了 你好!要确定你今年多大,我需要知道你的出生年份(或者具体出生日期),以及当前的年份。 不过,如果你是在2025年提问(比如今天是2025年4月5日),而你知道自己的出生年份,可以这样简单计算: **年龄 = 当前年份 ? 出生年份** (如果生日还没过,就减1) 例如: - 如果你出生于2000年,且今天已过生日 → 2025 ? 2000 = 25岁 - 如果你出生于2000年,但生日还没到 → 24岁 ?? 注意:我无法直接获取你的个人信息(如出生日期),所以请告诉我你的出生年份或生日,我可以帮你准确计算 ?? 你愿意分享一下吗? 单次token总消耗196
可以看出,第二次请求到大模型的时候,第一次的信息并没法保留,所以AI并不知道我今年多大了
如何在第二次请求的时候,把第一次信息作为一个“事实”发给AI
逻辑是:录入记忆 -> 查询前先查找数据库的相似记忆 -> 带着相似记忆一起发送到大模型
using Microsoft.Extensions.AI; using OpenAI; using OpenAI.Chat; using OpenAI.Embeddings; using Qdrant.Client; using Qdrant.Client.Grpc; using System; using System.ClientModel; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ChatMessage = Microsoft.Extensions.AI.ChatMessage; using EmbeddingGenerationOptions = OpenAI.Embeddings.EmbeddingGenerationOptions; namespace StudyAI { public static class AIHelper { static string apiKey = ""; static string url = "";//专属public static async Task ChatWithMemory() { IChatClient client = new ChatClient("qwen3-vl-plus", new ApiKeyCredential(apiKey), new OpenAI.OpenAIClientOptions() { Endpoint = new Uri(url) } ).AsIChatClient(); while (true) { Console.Write(">>>>>>"); var txt = Console.ReadLine(); if (txt == null) continue; try { List<ChatMessage> messages = new List<ChatMessage>(); var points = await GetRelevantMemory(txt); foreach (var point in points) { messages.Add(new ChatMessage(ChatRole.User, point.Payload["txt"].StringValue)); } messages.Add(new ChatMessage(ChatRole.User, txt)); var res = await client.GetResponseAsync(messages); Console.WriteLine(res.Text); } catch (Exception ex) { Console.WriteLine($"发生异常: {ex.Message}"); } } } /// <summary> /// 获取信息向量 /// </summary> /// <param name="txt"></param> /// <returns></returns> private static async Task<float[]> GetVector(string txt) { const string modelId = "text-embedding-v4"; // 推荐使用 v4 模型 var openAiEmbeddingClient = new EmbeddingClient( model: modelId, credential: new ApiKeyCredential(apiKey), options: new OpenAIClientOptions { Endpoint = new Uri(url) } ); // 调用百炼 Embedding 接口生成向量 var embeddingResponse = await openAiEmbeddingClient.GenerateEmbeddingAsync(txt, new EmbeddingGenerationOptions { Dimensions = 1536 }); ReadOnlyMemory<float> vectorMemory = embeddingResponse.Value.ToFloats(); float[] vector = vectorMemory.ToArray(); Console.WriteLine($"向量维度: {vector.Length}"); //Console.WriteLine($"{string.Join(",",vector)}"); return vector; } /// <summary> /// 录入记忆 /// </summary> /// <param name="txt"></param> /// <returns></returns> public static async Task RememberMe(string txt) { var vector = await GetVector(txt); //写入向量数据库 var client = new QdrantClient("192.168.232.133", 6334); //await client.CreateCollectionAsync(//写之前可以手动创建,也可以代码创建 // collectionName: "firstCollection", // vectorsConfig: new VectorParams { Size = 1536, Distance = Distance.Cosine } //); var points = new List<PointStruct> { new PointStruct { Id = Guid.NewGuid(), Vectors = vector, Payload = { ["txt"] = txt } }, }; await client.UpsertAsync("firstCollection", points); Console.WriteLine("成功写入Qdrant"); } /// <summary> /// 获取相关记忆 /// </summary> /// <param name="txt"></param> /// <returns></returns> public static async Task<IReadOnlyList<ScoredPoint>> GetRelevantMemory(string txt) { var vector = await GetVector(txt); //在向量数据库找到最相似的三条数据 var client = new QdrantClient("192.168.232.133", 6334); var results = await client.SearchAsync( collectionName: "firstCollection", vector: vector, limit: 3, // 最多返回3条 scoreThreshold: 0.5f // 相似度阈值 > 50% ); foreach (var point in results) { Console.WriteLine($"ID: {point.Id}, Score: {point.Score},txt:{point.Payload["txt"].StringValue}"); } return results; } } }
运行ChatWithMemory,在询问AI之前,会先从Qdrant中查找相关记忆
输入1=记录信息,2=读取记忆,3=对话 1 >>>>>>我是96年出生的 向量维度: 1536 成功写入Qdrant 输入1=记录信息,2=读取记忆,3=对话 3>>>>>>我今年多大了 向量维度: 1536 ID: { "uuid": "0f784446-9c2d-4c4d-a01c-05656d24f781" }, Score: 0.6475532,txt:我是96年出生的 你好!你是1996年出生的,现在是2025年(当前时间为2025年4月),那么: - 如果你的生日**已经过了**(比如1月1日到4月之前出生),你今年是 **29周岁**; - 如果你的生日**还没过**(比如4月之后出生),你今年是 **28周岁**。 ?? 举个例子: - 如果你出生于1996年3月15日 → 到2025年3月15日已满29岁 → 现在29岁; - 如果你出生于1996年5月20日 → 要到2025年5月20日才满29岁 → 现在还是28岁。 你可以告诉我你的具体出生月份和日期,我帮你精确计算 ?? >>>>>>现在是26年 向量维度: 1536 ID: { "uuid": "0f784446-9c2d-4c4d-a01c-05656d24f781" }, Score: 0.6133094,txt:我是96年出生的 你好!你提到你是1996年出生的,现在是2026年,那么你的年龄是: **2026 ? 1996 = 30岁** 所以你现在 **30周岁**(如果已经过了生日),或者即将满30岁(如果还没过生日)。 ?? 30岁是一个很特别的里程碑——人生进入更成熟、更有力量的阶段,很多人在这个年纪事业稳步上升、生活逐渐稳定,也有人开始规划家庭或追求新的梦想。无论你现在处于什么状态,都值得为自己感到骄傲! 如果你愿意分享更多(比如职业、兴趣、近况),我很乐意陪你聊聊~ ??
(大模型秀逗了,以为现在是25年,小问题)
后续可以继续优化,在Chat的过程中,筛选出更多事实加以记忆

浙公网安备 33010602011771号