diff --git a/src/0-core/HuanMeng.DotNetCore/Json/CustomDateTimeConverter.cs b/src/0-core/HuanMeng.DotNetCore/Json/CustomDateTimeConverter.cs new file mode 100644 index 0000000..d8897e6 --- /dev/null +++ b/src/0-core/HuanMeng.DotNetCore/Json/CustomDateTimeConverter.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace HuanMeng.DotNetCore.Json +{ + public class CustomDateTimeConverter : JsonConverter + { + private readonly string _format; + + public CustomDateTimeConverter(string format) + { + _format = format; + } + + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return DateTime.Parse(reader.GetString()); + } + + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + writer.WriteStringValue(value.ToString(_format)); + } + } +} diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Cache/Special/CharacterEntityCache.cs b/src/0-core/HuanMeng.MiaoYu.Code/Cache/Special/CharacterEntityCache.cs index d19b428..ee7b1eb 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Cache/Special/CharacterEntityCache.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Cache/Special/CharacterEntityCache.cs @@ -40,7 +40,7 @@ namespace HuanMeng.MiaoYu.Code.Cache.Special return characterCaches; } characterCaches = mapper.Map>(characters); - string sqlString = $"select TOP 100 CharacterId,count(DISTINCT UserId ) UserCount from T_User_Char where isdelete=0 and TenantId='{_dao.daoDbMiaoYu.context.TenantInfo?.TenantId}' GROUP BY CharacterId"; + string sqlString = $"select TOP 100 CharacterId,count(DISTINCT UserId ) UserCount from T_User_Chat where isdelete=0 and TenantId='{_dao.daoDbMiaoYu.context.TenantInfo?.TenantId}' GROUP BY CharacterId"; //获取查看次数 var characteChatCounts = _dao.daoDbMiaoYu.SqlQueryList(sqlString); //查询配置表 diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs index 57dd500..58432f2 100644 --- a/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs +++ b/src/0-core/HuanMeng.MiaoYu.Code/Chat/ChatBLL.cs @@ -2,6 +2,9 @@ using HuanMeng.DotNetCore.Base; using HuanMeng.MiaoYu.Code.Cache; using HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; using HuanMeng.MiaoYu.Model.Dto.Chat; +using HuanMeng.MiaoYu.Model.EnumModel.Chat; +using HuanMeng.Utility; + using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -23,26 +26,104 @@ namespace HuanMeng.MiaoYu.Code.Chat { } - public async Task>> GetChatMessage(int characterId, long timeStamp) + /// + /// 获取用户和角色的聊天记录 + /// + /// + /// + /// + public async Task>> GetChatMessage(int characterId) { + + var charact = MiaoYuCache.CharacterList.FirstOrDefault(it => it.Id == characterId); + if (charact == null) + { + throw new ArgumentException("角色不存在"); + } if (_UserId == 0) { - return new BaseResponse>(ResonseCode.Success, "", new List()); + + + var chat = new ChatMessageDto() + { + Id=0, + Role = ChatRole.assistant.ToString(), + ClaudeType = "text", + Content = charact.Prologue, + Timestamp = DateTime.Now, + UserIcon = charact.IconImage + }; + var list = new List(); + list.Add(chat); + return new BaseResponse>(ResonseCode.Success, "", list); } - var userChatSession = Dao.daoDbMiaoYu.context.T_User_Chat.Where(it => it.CharacterId == characterId && it.UserId == _UserId && !it.IsDelete).FirstOrDefault(); + //if(timeStamp.) + 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="现在", + 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(); } - //Dao.daoDbMiaoYu.context.T_Chat.Where(it=>it.CharacterId) - return null; + 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 = "", + 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(); + } + return new BaseResponse>(ResonseCode.Success, "", message); } /// diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/CharacterInfoDto.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/CharacterInfoDto.cs index 2929ac8..13fbc45 100644 --- a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/CharacterInfoDto.cs +++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/CharacterInfoDto.cs @@ -94,19 +94,7 @@ namespace HuanMeng.MiaoYu.Model.Dto.Chat // public string LabelName { get; set; } //} - /// - /// 聊天列表信息 - /// - public class ChatMessageDto - { - public string Id { get; set; } - public string Role { get; set; } - public string Content { get; set; } - public DateTime Timestamp { get; set; } - public int MessageType { get; set; } - public string UserIcon { get; set; } - } - + /// /// 聊天列表 /// @@ -145,43 +133,5 @@ namespace HuanMeng.MiaoYu.Model.Dto.Chat public int CharacterId { get; set; } } - /// - /// 聊天表信息状态 - /// - public enum ChatType - { - /// - /// 正常 - /// - 正常 = 0, - /// - /// 重新生成 - /// - 重新生成 = 1, - - /// - /// 删除 - /// - 删除 = 2 - } - - /// - /// 角色分类 - /// - public enum Role - { - /// - /// 用户 - /// - user, - /// - /// AI - /// - assistant, - /// - /// 提示 - /// - tips - } } diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/ChatMessageDto.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/ChatMessageDto.cs new file mode 100644 index 0000000..df112a5 --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Chat/ChatMessageDto.cs @@ -0,0 +1,61 @@ +using AutoMapper; +using AutoMapper.Configuration.Annotations; + +using HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; +using HuanMeng.MiaoYu.Model.EnumModel.Chat; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.MiaoYu.Model.Dto.Chat +{ + /// + /// 聊天列表信息 + /// + [AutoMap(typeof(T_Chat))] + public class ChatMessageDto + { + /// + /// 聊天记录Id + /// + public int Id { get; set; } + /// + /// 角色 + /// + public string Role { get; set; } + /// + /// 文本内容 + /// + public string Content { get; set; } + /// + /// 发送时间戳 + /// + public DateTime Timestamp { get; set; } + + /// + /// 消息类型 + /// + public string ClaudeType { get; set; } + /// + /// 消息类型 + /// + //[SourceMember(nameof(T_Chat.ClaudeType))] + public int MessageType + { + get + { + + var x = (ChatMessageType)Enum.Parse(typeof(ChatMessageType), ClaudeType); + return (int)x; + } + } + /// + /// 角色头像 + /// + public string UserIcon { get; set; } + } + +} diff --git a/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/Chat/ChatMessageType.cs b/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/Chat/ChatMessageType.cs new file mode 100644 index 0000000..3ebd77d --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/Chat/ChatMessageType.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.MiaoYu.Model.EnumModel.Chat +{ + /// + /// 消息类型 + /// + public enum ChatMessageType + { + /// + /// 文本消息 + /// + text = 0, + + } +} diff --git a/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/Chat/ChatRole.cs b/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/Chat/ChatRole.cs new file mode 100644 index 0000000..fde7b10 --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/Chat/ChatRole.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.MiaoYu.Model.EnumModel.Chat +{ + /// + /// 聊天角色 + /// + public enum ChatRole + { + /// + /// 第一次初始化语句 + /// + initialization, + /// + /// 用户 + /// + user, + /// + /// AI + /// + assistant, + /// + /// 提示 + /// + tips + } +} diff --git a/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/Chat/ChatType.cs b/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/Chat/ChatType.cs new file mode 100644 index 0000000..2b5734c --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/EnumModel/Chat/ChatType.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.MiaoYu.Model.EnumModel.Chat +{ + /// + /// 聊天记录类型 + /// + public enum ChatType + { + /// + /// 正常 + /// + 正常 = 0, + + /// + /// 重新生成 + /// + 重新生成 = 1, + + /// + /// 删除 + /// + 删除 = 2 + } +} diff --git a/src/0-core/HuanMeng.Utility/DateTimeExtensions.cs b/src/0-core/HuanMeng.Utility/DateTimeExtensions.cs new file mode 100644 index 0000000..0710e31 --- /dev/null +++ b/src/0-core/HuanMeng.Utility/DateTimeExtensions.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace HuanMeng.Utility +{ + /// + /// 时间扩展 + /// + public static class DateTimeExtensions + { + /// + /// 获取时间戳,秒 + /// + /// + /// + public static long ToUnixTimestamp(this DateTime dateTime) + { + return (long)(dateTime.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalSeconds; + } + + /// + /// 获取是时间戳,毫秒 + /// + /// + /// + public static long ToUnixTimestampMilliseconds(this DateTime dateTime) + { + return (long)(dateTime.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalMilliseconds; + } + } +} diff --git a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/ChatController.cs b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/ChatController.cs index 2e00dc8..1f45660 100644 --- a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/ChatController.cs +++ b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/ChatController.cs @@ -62,7 +62,7 @@ namespace HuanMeng.MiaoYu.WebApi.Controllers } /// - /// 获取聊天列表信息 + /// 获取聊天记录 /// /// /// @@ -70,8 +70,11 @@ namespace HuanMeng.MiaoYu.WebApi.Controllers [AllowAnonymous] public async Task> GetChatInfo(int characterId) { - var obj = JsonConvert.DeserializeObject("{\"ChatList\":[{\"Id\":\"1\",\"Role\":\"user\",\"Content\":\"Hello, how are you?\",\"Timestamp\":\"2022-03-01 12:00:00 \",\"MessageType\":0,\"UserIcon\":\"\"},{\"Id\":\"2\",\"Role\":\"assistant\",\"Content\":\"I'm fine, thanks!\",\"Timestamp\":\"2022-03-01 12:05:00 \",\"UserIcon\":\"\"}]}"); - return new BaseResponse(ResonseCode.Success, "", obj); + ChatListDto chatListDto = new ChatListDto(); + ChatBLL chatBLL = new ChatBLL(ServiceProvider); + var list = await chatBLL.GetChatMessage(characterId); + chatListDto.ChatList = list.Data; + return new BaseResponse(ResonseCode.Success, "", chatListDto); } /// diff --git a/src/2-api/HuanMeng.MiaoYu.WebApi/Program.cs b/src/2-api/HuanMeng.MiaoYu.WebApi/Program.cs index 5f71777..042f040 100644 --- a/src/2-api/HuanMeng.MiaoYu.WebApi/Program.cs +++ b/src/2-api/HuanMeng.MiaoYu.WebApi/Program.cs @@ -14,6 +14,8 @@ using HuanMeng.MiaoYu.Code.Cache; using HuanMeng.MiaoYu.Code.Chat; using Serilog; using HuanMeng.MiaoYu.Model.Dto; +using System.Text.Json.Serialization; +using HuanMeng.DotNetCore.Json; var builder = WebApplication.CreateBuilder(args); //Log.Logger = new LoggerConfiguration() // .WriteTo.Console() @@ -45,7 +47,12 @@ if (type != null) builder.Services.AddAutoMapper(mapperDomain); #endregion -builder.Services.AddControllers(); +builder.Services.AddControllers().AddJsonOptions(options => +{ + options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); + options.JsonSerializerOptions.PropertyNamingPolicy = null; + options.JsonSerializerOptions.Converters.Add(new CustomDateTimeConverter("yyyy-MM-dd HH:mm:ss")); +}); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c =>