ASP.NET Core 6 MVC Ajax调用中如何维持OpenAI对话上下文?
解决ASP.NET Core 6 MVC中OpenAI聊天机器人无法维持对话上下文的问题
问题根源
每次Ajax调用GetAnswerFromOpenAI方法时,都会创建新的OpenAIHelper实例,而对话历史ChatMessages是该类的实例变量,导致每次请求的上下文都是全新的,AI无法获取之前的对话内容,因此后续问题会被当作独立的新请求处理。
解决方案
核心思路是将对话上下文持久化存储,利用ASP.NET Core的Session来保存每个用户的对话历史(HTTP是无状态协议,Session可在多次请求间保留用户数据),具体步骤如下:
1. 启用Session支持
在Program.cs中添加Session配置:
// 添加Session服务 builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); // 设置会话超时时间 options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); // 在路由后启用Session app.UseRouting(); app.UseSession(); // 必须放在UseRouting之后,UseAuthorization之前 app.UseAuthorization();
2. 添加Session扩展方法
为了方便在Session中序列化/反序列化对话历史,添加扩展方法:
public static class SessionExtensions { public static void SetObjectAsJson(this ISession session, string key, object value) { session.SetString(key, JsonSerializer.Serialize(value)); } public static T GetObjectFromJson<T>(this ISession session, string key) { var value = session.GetString(key); return value == null ? default(T) : JsonSerializer.Deserialize<T>(value); } }
3. 修改控制器方法,复用对话上下文
修改GenAIController的GetAnswerFromOpenAI方法,从Session加载对话历史,调用OpenAI后更新并保存回Session:
[HttpGet] public JsonResult GetAnswerFromOpenAI(string simulationName = "", string userMessage = "") { // 从Session获取对话历史,无则初始化 var chatMessages = HttpContext.Session.GetObjectFromJson<List<ChatMessage>>("ChatHistory") ?? new List<ChatMessage>(); // 首次对话时添加系统提示 if (!chatMessages.Any(m => m is SystemChatMessage)) { var systemMsg = new SystemChatMessage("Act as a Chemistry teacher. Don't reply to non educational or unrelated queries and avoid giving answers on Biology and Physics. Strictly make the answer under 500 characters."); chatMessages.Add(systemMsg); } // 创建OpenAI客户端 var openAIClient = new ChatClient(model: "gpt-3.5-turbo", apiKey: "your-api-key"); // 添加当前用户消息到对话历史 chatMessages.Add(new UserChatMessage(userMessage)); // 调用OpenAI获取回复 var completionResponse = openAIClient.CompleteChat(chatMessages); var contentResponse = new List<string>(); if (completionResponse.Content != null && completionResponse.Content.Count > 0) { var assistantReply = completionResponse.Content[0].Text.Trim(); contentResponse.Add(assistantReply); // 将AI的回复也存入对话历史,维持上下文 chatMessages.Add(new AssistantChatMessage(assistantReply)); } // 将更新后的对话历史保存回Session HttpContext.Session.SetObjectAsJson("ChatHistory", chatMessages); return Json(contentResponse); }
4. 调整OpenAIHelper(可选)
如果不需要保留原OpenAIHelper的封装,可以简化该类,让它专注于OpenAI调用逻辑,或者直接将调用逻辑整合到控制器中(如上述代码所示)。
关键说明
- Session是用户隔离的,每个用户的对话历史独立存储,不会互相干扰。
- 如果需要跨设备持久化对话,可将Session替换为数据库存储(如用用户ID关联对话记录)。
- 必须将AI的回复也添加到对话历史中,否则后续请求只会包含用户的问题,AI仍无法理解上下文。
内容的提问来源于stack exchange,提问作者Oxygen
相关产品推荐
相关产品推荐

