diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs index 651c27f..813214e 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs @@ -1,587 +1,557 @@ -using HuanMeng.DotNetCore.Base; -using HuanMeng.MiaoYu.Code.Cache; -using HuanMeng.MiaoYu.Code.Chat.Claude; -using HuanMeng.MiaoYu.Code.Chat.Claude.Model; -using HuanMeng.MiaoYu.Code.Chat.Contract; -using HuanMeng.MiaoYu.Code.Chat.Minimax; -using HuanMeng.MiaoYu.Code.Users; -using HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; -using HuanMeng.MiaoYu.Model.Dto.Character; -using HuanMeng.MiaoYu.Model.Dto.Chat; -using HuanMeng.MiaoYu.Model.EnumModel.Chat; -using HuanMeng.MiaoYu.Model.EnumModel.User; +namespace HuanMeng.MiaoYu.Code.Chat; - -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; - -using Newtonsoft.Json.Linq; - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace HuanMeng.MiaoYu.Code.Chat +/// +/// 聊天类 +/// +public class ChatBLL : MiaoYuBase { - /// - /// 聊天类 - /// - public class ChatBLL : MiaoYuBase + public ChatBLL(IServiceProvider serviceProvider) : base(serviceProvider) { - public ChatBLL(IServiceProvider serviceProvider) : base(serviceProvider) + //logger.i + } + + /// + /// 获取用户和角色的聊天记录 + /// + /// + /// + /// + public async Task>> GetChatMessage(int characterId) + { + + + var charact = MiaoYuCache.CharacterList.FirstOrDefault(it => it.Id == characterId); + if (charact == null) { - //logger.i + throw new ArgumentException("角色不存在"); } - - /// - /// 获取用户和角色的聊天记录 - /// - /// - /// - /// - public async Task>> GetChatMessage(int characterId) + var list = new List(); + ChatMessageDto chatMessageDto2 = new ChatMessageDto() + { + ClaudeType = ChatMessageType.text.ToString(), + Content = charact.Biography ?? "", + Role = ChatRole.profile.ToString(), + Timestamp = DateTime.Now, + UserIcon = "", + Id = 0 + }; + list.Add(chatMessageDto2); + if (_UserId == 0) { - var charact = MiaoYuCache.CharacterList.FirstOrDefault(it => it.Id == characterId); - if (charact == null) + var chat = new ChatMessageDto() { - throw new ArgumentException("角色不存在"); - } - var list = new List(); - ChatMessageDto chatMessageDto2 = new ChatMessageDto() - { - ClaudeType = ChatMessageType.text.ToString(), - Content = charact.Biography ?? "", - Role = ChatRole.profile.ToString(), + Id = 0, + Role = ChatRole.assistant.ToString(), + ClaudeType = "text", + Content = charact.Prologue, Timestamp = DateTime.Now, - UserIcon = "", - Id = 0 + UserIcon = charact.IconImage }; - list.Add(chatMessageDto2); - if (_UserId == 0) - { - - var chat = new ChatMessageDto() - { - Id = 0, - Role = ChatRole.assistant.ToString(), - ClaudeType = "text", - Content = charact.Prologue, - Timestamp = DateTime.Now, - UserIcon = charact.IconImage - }; - - list.Add(chat); - return new BaseResponse>(ResonseCode.Success, "", list); - } - var userChatSession = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(it => it.CharacterId == characterId && it.UserId == _UserId && !it.IsDelete).FirstOrDefaultAsync(); - if (userChatSession == null) - { - userChatSession = new T_User_Chat() - { - SessionId = Guid.NewGuid(), - CharacterId = characterId, - CreateAt = DateTime.Now, - IsDelete = false, - SessionName = "新会话", - UpdateAt = DateTime.Now, - ModelConfigId = charact.ModelConfigId, - TenantId = charact.TenantId, - UserId = _UserId, - }; - Dao.daoDbMiaoYu.context.T_User_Chat.Add(userChatSession); - Dao.daoDbMiaoYu.context.SaveChanges(); - } - var chatList = await Dao.daoDbMiaoYu.context.T_Chat.Where(it => it.SessionId == userChatSession.SessionId && it.UserId == _UserId && it.Type == (int)ChatType.正常).OrderByDescending(it => it.SendMessageDay).ToListAsync(); - if (chatList == null || chatList.Count == 0) - { - //添加第一句 - var chat = new T_Chat() - { - Role = ChatRole.initialization.ToString(), - CharacterId = characterId, - ClaudeId = "", - ClaudeType = "text", - CreateTime = DateTime.Now, - Content = charact.Prologue, - Input_tokens = 0, - Output_tokens = 0, - SendDateDay = int.Parse(DateTime.Now.ToString("yyyyMMdd")), - TimeStamp = DateTime.Now,//DateTimeExtensions.ToUnixTimestamp(),.ToUnixTimestamp() - SendMessageDay = DateTime.Now.ToUnixTimestamp(), - SessionId = userChatSession.SessionId, - TenantId = userChatSession.TenantId, - Type = 0, - UpdateTime = DateTime.Now, - UserId = userChatSession.UserId, - ClaudeModel = "" - }; - Dao.daoDbMiaoYu.context.T_Chat.Add(chat); - Dao.daoDbMiaoYu.context.SaveChanges(); - chatList = new List(); - chatList.Add(chat); - } - var message = Mapper.Map>(chatList); - //设置头像 - message.Where(it => - it.Role == ChatRole.assistant.ToString() || - it.Role == ChatRole.initialization.ToString() - ).ToList() - .ForEach(it => it.UserIcon = charact.IconImage); - //用户头像 - var userData = await Dao.daoDbMiaoYu.context.T_User_Data.FirstOrDefaultAsync(it => it.UserId == _UserId); - var userIconUrl = userData?.UserIconUrl ?? ""; - message.Where(it => it.Role == ChatRole.user.ToString()).ToList().ForEach(it => it.UserIcon = userIconUrl); - - //将第一句修改角色 - var initia = message.FirstOrDefault(it => it.Role == ChatRole.initialization.ToString()); - if (initia != null) - { - initia.Role = ChatRole.assistant.ToString(); - } - message.Insert(0, chatMessageDto2); - return new BaseResponse>(ResonseCode.Success, "", message); + list.Add(chat); + return new BaseResponse>(ResonseCode.Success, "", list); } - - - /// - /// 发送消息接口 - /// - /// 角色Id - /// 消息内容 - /// - /// - public async Task> Message(int characterId, string message) + var userChatSession = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(it => it.CharacterId == characterId && it.UserId == _UserId && !it.IsDelete).FirstOrDefaultAsync(); + if (userChatSession == null) { - ChatMessageDataDto chatListDto = new ChatMessageDataDto(); - List chatMessageDtos = new List(); - if (TextCensor.TextCensor(message)) + userChatSession = new T_User_Chat() { - var chatMessage = new ChatMessageDto() - { - Id = 0, - Role = ChatRole.tips.ToString(), - ClaudeType = "text", - Content = "输入内容违规", - Timestamp = DateTime.Now, - UserIcon = "" - }; - chatMessageDtos.Add(chatMessage); - chatListDto.ChatList = chatMessageDtos; - return new BaseResponse(ResonseCode.Success, "", chatListDto); - } - - - var charact = MiaoYuCache.CharacterList.FirstOrDefault(it => it.Id == characterId); - if (charact == null) + SessionId = Guid.NewGuid(), + CharacterId = characterId, + CreateAt = DateTime.Now, + IsDelete = false, + SessionName = "新会话", + UpdateAt = DateTime.Now, + ModelConfigId = charact.ModelConfigId, + TenantId = charact.TenantId, + UserId = _UserId, + }; + Dao.daoDbMiaoYu.context.T_User_Chat.Add(userChatSession); + Dao.daoDbMiaoYu.context.SaveChanges(); + } + var chatList = await Dao.daoDbMiaoYu.context.T_Chat.Where(it => it.SessionId == userChatSession.SessionId && it.UserId == _UserId && it.Type == (int)ChatType.正常).OrderByDescending(it => it.SendMessageDay).ToListAsync(); + if (chatList == null || chatList.Count == 0) + { + //添加第一句 + var chat = new T_Chat() { - throw new ArgumentException("角色不存在"); - } - - if (_UserId == 0) - { - - var chatMessage = new ChatMessageDto() - { - Id = 0, - Role = ChatRole.assistant.ToString(), - ClaudeType = "text", - Content = charact.Prologue, - Timestamp = DateTime.Now, - UserIcon = charact.IconImage - }; - chatMessageDtos.Add(chatMessage); - - chatListDto.ChatList = chatMessageDtos; - return new BaseResponse(ResonseCode.Success, "", chatListDto); - } - //if(timeStamp.) - UserInfoBLL userInfoBLL = new UserInfoBLL(Dao, _UserId); - if (!userInfoBLL.IsCheckingSufficient(UserCurrencyType.聊天次数)) - { - throw new Exception("聊天次数不足"); - } - //userInfoBLL.User.GetUserCurrency(Model.EnumModel.User.UserCurrencyType.聊天次数); - var userChatSession = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(it => it.CharacterId == characterId && it.UserId == _UserId && !it.IsDelete).FirstOrDefaultAsync(); - if (userChatSession == null) - { - userChatSession = new T_User_Chat() - { - SessionId = Guid.NewGuid(), - CharacterId = characterId, - CreateAt = DateTime.Now, - IsDelete = false, - SessionName = $"{charact.Name}-{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}", - UpdateAt = DateTime.Now, - ModelConfigId = charact.ModelConfigId, - TenantId = charact.TenantId, - UserId = _UserId, - TotalToken = 0, - }; - Dao.daoDbMiaoYu.context.T_User_Chat.Add(userChatSession); - Dao.daoDbMiaoYu.context.SaveChanges(); - } - List mess = new List(); - int maxToken = 7000; - // var _memoryCardType = userInfoBLL[Model.EnumModel.UserMemoryCardType.记忆卡, charact.Id]; - (maxToken, var isMemoryCard) = userInfoBLL.GetMemoryCardMaxToken(charact.Id); - //await AddMessage(userChatSession, mess); - //递归获取聊天记录 - var _token = await AddMessage(userChatSession.SessionId, _UserId, 1, 0, maxToken, mess); - //将聊天数据反转 - // mess.Reverse(); - mess = mess.OrderBy(it => it.MessageDay).ToList(); - mess.Add(new ClaudeChatMessage - { - Role = ChatRole.user.ToString(), - Content = message, - }); - #region 添加数据库 - T_Chat t_Chat1 = new T_Chat - { - CharacterId = charact.Id, - ClaudeModel = "", + Role = ChatRole.initialization.ToString(), + CharacterId = characterId, ClaudeId = "", ClaudeType = "text", - Content = message, CreateTime = DateTime.Now, + Content = charact.Prologue, Input_tokens = 0, Output_tokens = 0, - Role = ChatRole.user.ToString(), SendDateDay = int.Parse(DateTime.Now.ToString("yyyyMMdd")), + TimeStamp = DateTime.Now,//DateTimeExtensions.ToUnixTimestamp(),.ToUnixTimestamp() SendMessageDay = DateTime.Now.ToUnixTimestamp(), SessionId = userChatSession.SessionId, TenantId = userChatSession.TenantId, - TimeStamp = DateTime.Now, Type = 0, UpdateTime = DateTime.Now, - UserId = _UserId, + UserId = userChatSession.UserId, + ClaudeModel = "" }; + Dao.daoDbMiaoYu.context.T_Chat.Add(chat); + Dao.daoDbMiaoYu.context.SaveChanges(); + chatList = new List(); + chatList.Add(chat); + } + var message = Mapper.Map>(chatList); + //设置头像 + message.Where(it => + it.Role == ChatRole.assistant.ToString() || + it.Role == ChatRole.initialization.ToString() + ).ToList() + .ForEach(it => it.UserIcon = charact.IconImage); + //用户头像 + var userData = await Dao.daoDbMiaoYu.context.T_User_Data.FirstOrDefaultAsync(it => it.UserId == _UserId); + var userIconUrl = userData?.UserIconUrl ?? ""; + message.Where(it => it.Role == ChatRole.user.ToString()).ToList().ForEach(it => it.UserIcon = userIconUrl); + + //将第一句修改角色 + var initia = message.FirstOrDefault(it => it.Role == ChatRole.initialization.ToString()); + if (initia != null) + { + initia.Role = ChatRole.assistant.ToString(); + } + message.Insert(0, chatMessageDto2); + return new BaseResponse>(ResonseCode.Success, "", message); + } - #endregion - - var claudeChatResponse = await Chat(charact, mess); - var t_Chat = new T_Chat + /// + /// 发送消息接口 + /// + /// 角色Id + /// 消息内容 + /// + /// + public async Task> Message(int characterId, string message) + { + ChatMessageDataDto chatListDto = new ChatMessageDataDto(); + List chatMessageDtos = new List(); + if (TextCensor.TextCensor(message)) + { + var chatMessage = new ChatMessageDto() { - CharacterId = charact.Id, - ClaudeModel = claudeChatResponse.Model, - ClaudeId = claudeChatResponse.Id, + Id = 0, + Role = ChatRole.tips.ToString(), ClaudeType = "text", - Content = claudeChatResponse.Message, - CreateTime = DateTime.Now, - Input_tokens = claudeChatResponse.InputTokens, - Output_tokens = claudeChatResponse.OutputTokens, - Role = ChatRole.assistant.ToString(), - SendDateDay = int.Parse(DateTime.Now.ToString("yyyyMMdd")), - SendMessageDay = DateTime.Now.ToUnixTimestamp(), - SessionId = userChatSession.SessionId, - TenantId = userChatSession.TenantId, - TimeStamp = DateTime.Now, - Type = 0, - UpdateTime = DateTime.Now, - UserId = _UserId, - Tokens = claudeChatResponse.OutputTokens - }; - #region 开启事务 - using (IDbContextTransaction transaction = Dao.daoDbMiaoYu.context.Database.BeginTransaction()) - { - try - { - if (charact.Token == null || charact.Token == 0) - { - charact.Token = (int)(claudeChatResponse.InputTokens - (message.Length * 2)); - if (charact.Token <= 0) - { - charact.Token = claudeChatResponse.Message.Length * 2; - } - var t_Character = await Dao.daoDbMiaoYu.context.T_Character.FirstOrDefaultAsync(it => it.Id == charact.Id); - if (t_Character != null) - { - t_Character.Token = charact.Token; - } - } - t_Chat1.Tokens = claudeChatResponse.InputTokens - charact.Token; - t_Chat1.Input_tokens = claudeChatResponse.InputTokens; - //设置消耗的总token - userChatSession.TotalToken += claudeChatResponse.InputTokens + claudeChatResponse.OutputTokens; - Dao.daoDbMiaoYu.context.Add(t_Chat1); - Dao.daoDbMiaoYu.context.Add(t_Chat); - //最后一次聊天时间 - userChatSession.UpdateAt = DateTime.Now; - //最后一次聊天记录 - userChatSession.LastMessage = t_Chat.Content; - if (userChatSession.LastMessage.Length > 10) - { - userChatSession.LastMessage = userChatSession.LastMessage.Substring(0, 10) + "..."; - } - await Dao.daoDbMiaoYu.context.SaveChangesAsync(); - //扣除货币 - userInfoBLL[UserCurrencyType.聊天次数].ConsumeMoneyNoWork(-1, Dao); - if (isMemoryCard) - { - //扣除记忆卡 - userInfoBLL[Model.EnumModel.UserMemoryCardType.记忆卡, charact.Id].ConsumeMemoryCard(-1, Dao); - } - - transaction.Commit(); - } - catch (Exception ex) - { - transaction.Rollback(); - throw ex; - } - } - #endregion - //claudeChatResponse. - ChatMessageDto chatMessageDto = new ChatMessageDto() - { - ClaudeType = ChatMessageType.text.ToString(), - Content = claudeChatResponse.Message, - Role = ChatRole.assistant.ToString(), + Content = "输入内容违规", Timestamp = DateTime.Now, - UserIcon = charact.IconImage, - Id = t_Chat.Id + UserIcon = "" }; - chatMessageDtos.Add(chatMessageDto); - #region 添加返回次数 - var cishu = userInfoBLL[UserCurrencyType.聊天次数].CurrencyMoney; - if (cishu <= 3) - { - ChatMessageDto chatMessageDto1 = new ChatMessageDto() - { - ClaudeType = ChatMessageType.text.ToString(), - Content = $"您还剩余{cishu:F0}次聊天次数", - Role = ChatRole.tips.ToString(), - Timestamp = DateTime.Now, - Id = 0 - }; - chatMessageDtos.Add(chatMessageDto1); - } - #endregion + chatMessageDtos.Add(chatMessage); chatListDto.ChatList = chatMessageDtos; - chatListDto.LastMessageId = t_Chat1.Id; - chatListDto.RemainingChatCount = (int)cishu; return new BaseResponse(ResonseCode.Success, "", chatListDto); } - public async Task Chat(CharacterCache? charact, List mess) + + var charact = MiaoYuCache.CharacterList.FirstOrDefault(it => it.Id == characterId); + if (charact == null) { - if (charact.ModelConfig.ModelName.Contains("minimaxi")) - { - var chat = new MinimaxChat(HttpClientFactory); - MinimaxChatParams minimaxChatParams = new MinimaxChatParams(mess, charact, charact.Name); - return await chat.MessagesAsync(minimaxChatParams); - } - else - { - return await ClaudeChat(charact, mess); - } + throw new ArgumentException("角色不存在"); } - /// - /// - /// - /// - /// - /// - /// - /// - /// - private async Task ClaudeChat(CharacterCache? charact, List mess) + if (_UserId == 0) { - #region 调用api - ClaudeChatChatParams baseChatParams = new ClaudeChatChatParams(); - baseChatParams.Messages = mess.ToArray(); - baseChatParams.System = charact.System; - baseChatParams.MaxTokens = charact.ModelConfig.MaxTokens; - var claude = charact.ModelConfig.GetClaudeChatConfig(); - IChat chat = new ClaudeChat(claude, HttpClientFactory); - var response = await chat.MessagesAsync(baseChatParams); - if (response == null) - { - throw new Exception("ai出现错误"); - } - var claudeChatResponse = response as ClaudeChatResponse; - if (claudeChatResponse == null) - { - throw new Exception("ai返回出现错误"); - } - #endregion - claudeChatResponse.TotalTokens = claudeChatResponse.Usage.OutputTokens + claudeChatResponse.Usage.InputTokens; - claudeChatResponse.InputTokens = claudeChatResponse.Usage.InputTokens; - claudeChatResponse.OutputTokens = claudeChatResponse.Usage.OutputTokens; - claudeChatResponse.Message = claudeChatResponse.Content[0].Text; + var chatMessage = new ChatMessageDto() + { + Id = 0, + Role = ChatRole.assistant.ToString(), + ClaudeType = "text", + Content = charact.Prologue, + Timestamp = DateTime.Now, + UserIcon = charact.IconImage + }; + chatMessageDtos.Add(chatMessage); - return claudeChatResponse; + chatListDto.ChatList = chatMessageDtos; + return new BaseResponse(ResonseCode.Success, "", chatListDto); } - - /// - /// 通过递归判断聊天是否满足 - /// - /// - /// - /// - /// - /// - /// - /// - private async Task AddMessage(Guid sessionId, int userId, int index, int tokens, int maxTokens, List mess) + //if(timeStamp.) + UserInfoBLL userInfoBLL = new UserInfoBLL(Dao, _UserId); + if (!userInfoBLL.IsCheckingSufficient(UserCurrencyType.聊天次数)) { - int size = 50; - var role = new List(); - role.Add(ChatRole.assistant.ToString()); - role.Add(ChatRole.user.ToString()); - - var chatList = await Dao.daoDbMiaoYu.context.T_Chat.AsNoTracking().Where(it => it.SessionId == sessionId && it.UserId == userId && role.Contains(it.Role)).OrderByDescending(it => it.SendMessageDay).Skip((index - 1) * size).Take(size) - .Select(it => new { it.Role, it.Content, it.Tokens, it.SendMessageDay }).ToListAsync(); - if (chatList != null || chatList.Count == 0) + throw new Exception("聊天次数不足"); + } + //userInfoBLL.User.GetUserCurrency(Model.EnumModel.User.UserCurrencyType.聊天次数); + var userChatSession = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(it => it.CharacterId == characterId && it.UserId == _UserId && !it.IsDelete).FirstOrDefaultAsync(); + if (userChatSession == null) + { + userChatSession = new T_User_Chat() { - for (int i = 0; i < chatList.Count; i++) + SessionId = Guid.NewGuid(), + CharacterId = characterId, + CreateAt = DateTime.Now, + IsDelete = false, + SessionName = $"{charact.Name}-{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}", + UpdateAt = DateTime.Now, + ModelConfigId = charact.ModelConfigId, + TenantId = charact.TenantId, + UserId = _UserId, + TotalToken = 0, + }; + Dao.daoDbMiaoYu.context.T_User_Chat.Add(userChatSession); + Dao.daoDbMiaoYu.context.SaveChanges(); + } + List mess = new List(); + int maxToken = 7000; + // var _memoryCardType = userInfoBLL[Model.EnumModel.UserMemoryCardType.记忆卡, charact.Id]; + (maxToken, var isMemoryCard) = userInfoBLL.GetMemoryCardMaxToken(charact.Id); + //await AddMessage(userChatSession, mess); + //递归获取聊天记录 + var _token = await AddMessage(userChatSession.SessionId, _UserId, 1, 0, maxToken, mess); + //将聊天数据反转 + // mess.Reverse(); + mess = mess.OrderBy(it => it.MessageDay).ToList(); + mess.Add(new ClaudeChatMessage + { + Role = ChatRole.user.ToString(), + Content = message, + }); + #region 添加数据库 + T_Chat t_Chat1 = new T_Chat + { + CharacterId = charact.Id, + ClaudeModel = "", + ClaudeId = "", + ClaudeType = "text", + Content = message, + CreateTime = DateTime.Now, + Input_tokens = 0, + Output_tokens = 0, + Role = ChatRole.user.ToString(), + SendDateDay = int.Parse(DateTime.Now.ToString("yyyyMMdd")), + SendMessageDay = DateTime.Now.ToUnixTimestamp(), + SessionId = userChatSession.SessionId, + TenantId = userChatSession.TenantId, + TimeStamp = DateTime.Now, + Type = 0, + UpdateTime = DateTime.Now, + UserId = _UserId, + }; + + + #endregion + + var claudeChatResponse = await Chat(charact, mess); + var t_Chat = new T_Chat + { + CharacterId = charact.Id, + ClaudeModel = claudeChatResponse.Model, + ClaudeId = claudeChatResponse.Id, + ClaudeType = "text", + Content = claudeChatResponse.Message, + CreateTime = DateTime.Now, + Input_tokens = claudeChatResponse.InputTokens, + Output_tokens = claudeChatResponse.OutputTokens, + Role = ChatRole.assistant.ToString(), + SendDateDay = int.Parse(DateTime.Now.ToString("yyyyMMdd")), + SendMessageDay = DateTime.Now.ToUnixTimestamp(), + SessionId = userChatSession.SessionId, + TenantId = userChatSession.TenantId, + TimeStamp = DateTime.Now, + Type = 0, + UpdateTime = DateTime.Now, + UserId = _UserId, + Tokens = claudeChatResponse.OutputTokens + }; + #region 开启事务 + using (IDbContextTransaction transaction = Dao.daoDbMiaoYu.context.Database.BeginTransaction()) + { + try + { + if (charact.Token == null || charact.Token == 0) { - var chat = chatList[i]; - if ((tokens + chat.Tokens) > maxTokens) + charact.Token = (int)(claudeChatResponse.InputTokens - (message.Length * 2)); + if (charact.Token <= 0) { - return tokens; + charact.Token = claudeChatResponse.Message.Length * 2; } - mess.Add(new ClaudeChatMessage + var t_Character = await Dao.daoDbMiaoYu.context.T_Character.FirstOrDefaultAsync(it => it.Id == charact.Id); + if (t_Character != null) { - Role = chat.Role, - Content = chat.Content, - MessageDay = chat.SendMessageDay - }); - tokens += chat.Tokens ?? 0; + t_Character.Token = charact.Token; + } } - //数据不够 - if (chatList.Count < size) + t_Chat1.Tokens = claudeChatResponse.InputTokens - charact.Token; + t_Chat1.Input_tokens = claudeChatResponse.InputTokens; + //设置消耗的总token + userChatSession.TotalToken += claudeChatResponse.InputTokens + claudeChatResponse.OutputTokens; + Dao.daoDbMiaoYu.context.Add(t_Chat1); + Dao.daoDbMiaoYu.context.Add(t_Chat); + //最后一次聊天时间 + userChatSession.UpdateAt = DateTime.Now; + //最后一次聊天记录 + userChatSession.LastMessage = t_Chat.Content; + if (userChatSession.LastMessage.Length > 10) + { + userChatSession.LastMessage = userChatSession.LastMessage.Substring(0, 10) + "..."; + } + await Dao.daoDbMiaoYu.context.SaveChangesAsync(); + //扣除货币 + userInfoBLL[UserCurrencyType.聊天次数].ConsumeMoneyNoWork(-1, Dao); + if (isMemoryCard) + { + //扣除记忆卡 + userInfoBLL[Model.EnumModel.UserMemoryCardType.记忆卡, charact.Id].ConsumeMemoryCard(-1, Dao); + } + + transaction.Commit(); + } + catch (Exception ex) + { + transaction.Rollback(); + throw ex; + } + } + #endregion + //claudeChatResponse. + ChatMessageDto chatMessageDto = new ChatMessageDto() + { + ClaudeType = ChatMessageType.text.ToString(), + Content = claudeChatResponse.Message, + Role = ChatRole.assistant.ToString(), + Timestamp = DateTime.Now, + UserIcon = charact.IconImage, + Id = t_Chat.Id + }; + chatMessageDtos.Add(chatMessageDto); + #region 添加返回次数 + var cishu = userInfoBLL[UserCurrencyType.聊天次数].CurrencyMoney; + if (cishu <= 3) + { + ChatMessageDto chatMessageDto1 = new ChatMessageDto() + { + ClaudeType = ChatMessageType.text.ToString(), + Content = $"您还剩余{cishu:F0}次聊天次数", + Role = ChatRole.tips.ToString(), + Timestamp = DateTime.Now, + Id = 0 + }; + chatMessageDtos.Add(chatMessageDto1); + } + #endregion + chatListDto.ChatList = chatMessageDtos; + chatListDto.LastMessageId = t_Chat1.Id; + chatListDto.RemainingChatCount = (int)cishu; + return new BaseResponse(ResonseCode.Success, "", chatListDto); + } + + public async Task Chat(CharacterCache? charact, List mess) + { + if (charact.ModelConfig.ModelName.Contains("minimaxi")) + { + var chat = new MinimaxChat(HttpClientFactory); + MinimaxChatParams minimaxChatParams = new MinimaxChatParams(mess, charact, charact.Name); + return await chat.MessagesAsync(minimaxChatParams); + } + else + { + return await ClaudeChat(charact, mess); + } + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + private async Task ClaudeChat(CharacterCache? charact, List mess) + { + #region 调用api + ClaudeChatChatParams baseChatParams = new ClaudeChatChatParams(); + baseChatParams.Messages = mess.ToArray(); + baseChatParams.System = charact.System; + baseChatParams.MaxTokens = charact.ModelConfig.MaxTokens; + var claude = charact.ModelConfig.GetClaudeChatConfig(); + IChat chat = new ClaudeChat(claude, HttpClientFactory); + var response = await chat.MessagesAsync(baseChatParams); + if (response == null) + { + throw new Exception("ai出现错误"); + } + var claudeChatResponse = response as ClaudeChatResponse; + if (claudeChatResponse == null) + { + throw new Exception("ai返回出现错误"); + } + #endregion + claudeChatResponse.TotalTokens = claudeChatResponse.Usage.OutputTokens + claudeChatResponse.Usage.InputTokens; + claudeChatResponse.InputTokens = claudeChatResponse.Usage.InputTokens; + claudeChatResponse.OutputTokens = claudeChatResponse.Usage.OutputTokens; + claudeChatResponse.Message = claudeChatResponse.Content[0].Text; + + + return claudeChatResponse; + } + + /// + /// 通过递归判断聊天是否满足 + /// + /// + /// + /// + /// + /// + /// + /// + private async Task AddMessage(Guid sessionId, int userId, int index, int tokens, int maxTokens, List mess) + { + int size = 50; + var role = new List(); + role.Add(ChatRole.assistant.ToString()); + role.Add(ChatRole.user.ToString()); + + var chatList = await Dao.daoDbMiaoYu.context.T_Chat.AsNoTracking().Where(it => it.SessionId == sessionId && it.UserId == userId && role.Contains(it.Role)).OrderByDescending(it => it.SendMessageDay).Skip((index - 1) * size).Take(size) + .Select(it => new { it.Role, it.Content, it.Tokens, it.SendMessageDay }).ToListAsync(); + if (chatList != null || chatList.Count == 0) + { + for (int i = 0; i < chatList.Count; i++) + { + var chat = chatList[i]; + if ((tokens + chat.Tokens) > maxTokens) { return tokens; } - if (tokens < maxTokens) + mess.Add(new ClaudeChatMessage { - index++; - await AddMessage(sessionId, userId, index, tokens, maxTokens, mess); - } + Role = chat.Role, + Content = chat.Content, + MessageDay = chat.SendMessageDay + }); + tokens += chat.Tokens ?? 0; + } + //数据不够 + if (chatList.Count < size) + { + return tokens; + } + if (tokens < maxTokens) + { + index++; + await AddMessage(sessionId, userId, index, tokens, maxTokens, mess); } - return tokens; } + return tokens; + } - /// - /// 删除聊天记录 - /// - /// 聊天id - /// - /// - public async Task DelChatByIds(List id, int characterId) + /// + /// 删除聊天记录 + /// + /// 聊天id + /// + /// + public async Task DelChatByIds(List id, int characterId) + { + var chatsToDelete = await Dao.daoDbMiaoYu.context.T_Chat.Where(t => id.Contains(t.Id)).ToListAsync(); + if (chatsToDelete.Count <= 0) { - var chatsToDelete = await Dao.daoDbMiaoYu.context.T_Chat.Where(t => id.Contains(t.Id)).ToListAsync(); - if (chatsToDelete.Count <= 0) - { - throw new Exception("删除失败"); - } - var chatList = chatsToDelete.Where(t => t.UserId == _UserId && t.CharacterId == characterId && (t.Type == (int)ChatType.正常 || t.Type == (int)ChatType.重新生成)).ToList(); - if (chatList.Count > 0) - { - chatList.ForEach(t => t.Type = 2); - } - Dao.daoDbMiaoYu.context.SaveChanges(); - return true; + throw new Exception("删除失败"); } - - /// - /// 清空聊天记录 - /// - /// - /// - public async Task DelChat(int characterId) + var chatList = chatsToDelete.Where(t => t.UserId == _UserId && t.CharacterId == characterId && (t.Type == (int)ChatType.正常 || t.Type == (int)ChatType.重新生成)).ToList(); + if (chatList.Count > 0) { - var tempList = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(t => t.UserId == _UserId && t.CharacterId == characterId && t.IsDelete == false).FirstOrDefaultAsync(); - if (tempList != null) - { - tempList.IsDelete = true; - } - Dao.daoDbMiaoYu.context.SaveChanges(); - return true; + chatList.ForEach(t => t.Type = 2); } + Dao.daoDbMiaoYu.context.SaveChanges(); + return true; + } - /// - /// 获取消息聊天记录列表 - /// - /// - //public async Task>> GetChatHistoryList() - //{ - // var userChatSessions = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(it => it.UserId == _UserId && !it.IsDelete).ToListAsync(); - // List chatHistoryInfos = new List(); - // var charactersIds = MiaoYuCache.CharacterList.ToList(); - // userChatSessions.ForEach(it => - // { - // var model = charactersIds.FirstOrDefault(item => item.Id == it.CharacterId); - // if (model != null) - // { - // var info = Mapper.Map(model); - // info.LastContactTime = it.UpdateAt; - // chatHistoryInfos.Add(info); - // } - - // }); - // chatHistoryInfos = chatHistoryInfos.OrderByDescending(it => it.LastContactTime).ToList(); - // return new BaseResponse>(ResonseCode.Success, "", chatHistoryInfos) { }; - //} - - /// - /// 获取消息聊天记录列表 - /// - /// - public async Task>> GetChatHistoryList() + /// + /// 清空聊天记录 + /// + /// + /// + public async Task DelChat(int characterId) + { + var tempList = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(t => t.UserId == _UserId && t.CharacterId == characterId && t.IsDelete == false).FirstOrDefaultAsync(); + if (tempList != null) { - var userChatSessions = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(it => it.UserId == _UserId && !it.IsDelete).ToListAsync(); + tempList.IsDelete = true; + } + Dao.daoDbMiaoYu.context.SaveChanges(); + return true; + } + + /// + /// 获取消息聊天记录列表 + /// + /// + //public async Task>> GetChatHistoryList() + //{ + // var userChatSessions = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(it => it.UserId == _UserId && !it.IsDelete).ToListAsync(); + // List chatHistoryInfos = new List(); + // var charactersIds = MiaoYuCache.CharacterList.ToList(); + // userChatSessions.ForEach(it => + // { + // var model = charactersIds.FirstOrDefault(item => item.Id == it.CharacterId); + // if (model != null) + // { + // var info = Mapper.Map(model); + // info.LastContactTime = it.UpdateAt; + // chatHistoryInfos.Add(info); + // } + + // }); + // chatHistoryInfos = chatHistoryInfos.OrderByDescending(it => it.LastContactTime).ToList(); + // return new BaseResponse>(ResonseCode.Success, "", chatHistoryInfos) { }; + //} + + /// + /// 获取消息聊天记录列表 + /// + /// + public async Task>> GetChatHistoryList() + { + var userChatSessions = await Dao.daoDbMiaoYu.context.T_User_Chat.Where(it => it.UserId == _UserId && !it.IsDelete).ToListAsync(); - List chatHistoryInfos = new List(); - var charactersIds = MiaoYuCache.CharacterList.ToList(); - userChatSessions.ForEach(it => + List chatHistoryInfos = new List(); + var charactersIds = MiaoYuCache.CharacterList.ToList(); + userChatSessions.ForEach(it => + { + var model = charactersIds.FirstOrDefault(item => item.Id == it.CharacterId); + if (model != null) { - var model = charactersIds.FirstOrDefault(item => item.Id == it.CharacterId); - if (model != null) + + var info = Mapper.Map(model); + //获取最新的聊天记录 + //var c = Dao.daoDbMiaoYu.context.T_Chat.Where(it => it.SessionId == it.SessionId).OrderByDescending(it => it.SendMessageDay).FirstOrDefault(); + info.LastContactTime = it.UpdateAt; + info.LastMessage = it.LastMessage; + if (string.IsNullOrEmpty(info.LastMessage)) { - - var info = Mapper.Map(model); - //获取最新的聊天记录 - //var c = Dao.daoDbMiaoYu.context.T_Chat.Where(it => it.SessionId == it.SessionId).OrderByDescending(it => it.SendMessageDay).FirstOrDefault(); - info.LastContactTime = it.UpdateAt; - info.LastMessage = it.LastMessage; - if (string.IsNullOrEmpty(info.LastMessage)) + info.LastMessage = model.Prologue; + if (info.LastMessage.IndexOf("*") > -1) { - info.LastMessage = model.Prologue; - if (info.LastMessage.IndexOf("*") > -1) - { - // 定义正则表达式模式来匹配*号之间的文本 - string pattern = @"\*.*?\*"; + // 定义正则表达式模式来匹配*号之间的文本 + string pattern = @"\*.*?\*"; - // 使用正则表达式替换*号之间的文本为空 - info.LastMessage = Regex.Replace(info.LastMessage, pattern, ""); - } + // 使用正则表达式替换*号之间的文本为空 + info.LastMessage = Regex.Replace(info.LastMessage, pattern, ""); } - - //if (c != null) - //{ - // info.LastMessage = c.Content; - //} - chatHistoryInfos.Add(info); } - }); - chatHistoryInfos = chatHistoryInfos.OrderByDescending(it => it.LastContactTime).ToList(); - return new BaseResponse>(ResonseCode.Success, "", chatHistoryInfos) { }; - } + + //if (c != null) + //{ + // info.LastMessage = c.Content; + //} + chatHistoryInfos.Add(info); + } + }); + chatHistoryInfos = chatHistoryInfos.OrderByDescending(it => it.LastContactTime).ToList(); + return new BaseResponse>(ResonseCode.Success, "", chatHistoryInfos) { }; } } + diff --git a/src/0-core/HuanMeng.MiaoYu.Code/GlobalUsings.cs b/src/0-core/HuanMeng.MiaoYu.Code/GlobalUsings.cs index ab2d6b2..c1f6c60 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/GlobalUsings.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/GlobalUsings.cs @@ -1,14 +1,37 @@ +global using HuanMeng.DotNetCore.Base; +global using HuanMeng.DotNetCore.TextCensor; +global using HuanMeng.DotNetCore.Utility; global using HuanMeng.MiaoYu.Code.Base; +global using HuanMeng.MiaoYu.Code.Cache; +global using HuanMeng.MiaoYu.Code.Chat.Claude; +global using HuanMeng.MiaoYu.Code.Chat.Claude.Model; +global using HuanMeng.MiaoYu.Code.Chat.Contract; +global using HuanMeng.MiaoYu.Code.Chat.Minimax; global using HuanMeng.MiaoYu.Code.DataAccess; -global using HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; global using HuanMeng.MiaoYu.Code.Other; +global using HuanMeng.MiaoYu.Code.SysDictionary.Contract; +global using HuanMeng.MiaoYu.Code.SysDictionary.DictionaryNetwork; +global using HuanMeng.MiaoYu.Code.Users; +global using HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; +global using HuanMeng.MiaoYu.Model.Dto.Character; +global using HuanMeng.MiaoYu.Model.Dto.Chat; +global using HuanMeng.MiaoYu.Model.EnumModel; +global using HuanMeng.MiaoYu.Model.EnumModel.Chat; +global using HuanMeng.MiaoYu.Model.EnumModel.User; + +global using Microsoft.EntityFrameworkCore; +global using Microsoft.EntityFrameworkCore.Storage; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Logging; + +global using Newtonsoft.Json.Linq; + +global using System; +global using System.Collections.Concurrent; +global using System.Collections.Generic; +global using System.Linq; +global using System.Text; global using System.Text.Json; global using System.Text.Json.Serialization; -global using HuanMeng.MiaoYu.Model.EnumModel; -global using HuanMeng.MiaoYu.Model.EnumModel.User; -global using System.Collections.Concurrent; -global using HuanMeng.MiaoYu.Code.SysDictionary.Contract; -global using HuanMeng.MiaoYu.Code.SysDictionary; -global using HuanMeng.MiaoYu.Code.SysDictionary.DictionaryNetwork; -global using HuanMeng.DotNetCore.TextCensor; -global using HuanMeng.DotNetCore.Utility; \ No newline at end of file +global using System.Text.RegularExpressions; +global using System.Threading.Tasks; \ No newline at end of file diff --git a/src/2-api/HuanMeng.MiaoYu.WebApi/Pay-config/wxpay.json b/src/2-api/HuanMeng.MiaoYu.WebApi/Pay-config/wxpay.json deleted file mode 100644 index 58efb04..0000000 --- a/src/2-api/HuanMeng.MiaoYu.WebApi/Pay-config/wxpay.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "AppID": "", //网站的唯一标识 - "MchID": "", //商户ID - "Key": "" -}