using Edu.Common.API; using Edu.Common.Plugin; using Edu.Model.ViewModel.AI; using Edu.Module.User; using Edu.WebApi.Filter; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Org.BouncyCastle.Asn1.Cmp; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Ubiety.Dns.Core; using OpenAI_API; using OpenAI_API.Completions; using Microsoft.AspNetCore.Authorization; using System.IO; using Spire.Pdf.Exporting.XPS.Schema; using Edu.Common.YouDao; using Newtonsoft.Json.Linq; using System.Net; using System.Security.Policy; using Polly.Caching; using System.IO.Compression; using SharpCompress.Common; using System.Collections; using System.Reflection; using System.Text; namespace Edu.WebApi.Controllers.AI { [Route("api/[controller]/[action]")] [ApiExceptionFilter] [ApiController] [EnableCors("AllowCors")] public class AIStudentController : AppletBaseController { private static readonly string postUrl = "https://api.zhizengzeng.com/v1/chat/completions"; private const string user = "user"; private const string messages = "messages"; /// /// AI供应商处理类 /// private readonly AIModule aiModule = new AIModule(); /// /// 根据学生id获取对应的应用 /// /// [HttpPost] public ApiResult GetAuthorizeStudentBySIdList() { var query = new RB_AI_PresetsApplication_ViewModel();// Common.Plugin.JsonHelper.DeserializeObject(RequestParm.Msg.ToString()); query.Group_Id = base.AppletUserInfo.Group_Id; // query.School_Id = base.AppletUserInfo.School_Id; query.StudentId = this.AppletUserInfo.AccountId; query.Enable = 1; query.IsEffective = 1; if (this.AppletUserInfo.AccountType != Common.Enum.User.AccountTypeEnum.Student) { return ApiResult.Failed("请用正确的账号登录"); } var list = aiModule.GetStuPresetsApplicationList(query); var result = list.Select(extModel => new { ID = extModel?.ID ?? 0, Logo = extModel?.Logo ?? "", PresetsApplicationName = extModel?.Name ?? "", SupplierId = extModel?.SupplierId ?? 0, SupplierName = extModel?.SupplierName ?? "", Content = extModel?.Content ?? "", Range = extModel?.RangeName ?? "", Area = extModel?.Area ?? "", Describe = extModel?.DescribeName ?? "", DateType = extModel?.DateType ?? 0, StartDate = StringHelper.FormatDateTimeStr(extModel.StuStartDate), EndDate = StringHelper.FormatDateTimeStr(extModel.StuEndDate), CreateTime = StringHelper.FormatDateTimeStr(extModel.CreateTime), LanguageType = extModel?.LanguageType ?? 0, Enable = extModel?.Enable ?? 0, SupplierType = extModel?.SupplierType ?? 0, }); return ApiResult.Success(data: result); } /// /// 根据学生id获取对应的应用 /// /// [HttpPost] public ApiResult GetAuthorizeStudentBySIdList_V2() { var query = new RB_AI_AuthorizeStudent_ViewModel();// Common.Plugin.JsonHelper.DeserializeObject(RequestParm.Msg.ToString()); query.Group_Id = base.AppletUserInfo.Group_Id; query.School_Id = base.AppletUserInfo.School_Id; query.StudentId = this.AppletUserInfo.AccountId; query.Enable = 1; query.IsEffective = 1; if (this.AppletUserInfo.AccountType != Common.Enum.User.AccountTypeEnum.Student) { return ApiResult.Failed("请用正确的账号登录"); } var list = aiModule.GetAuthorizeStudentListModule(query); var result = list.Select(extModel => new { ID = extModel?.ID ?? 0, StuName = extModel?.StuName ?? "", PresetsApplicationName = extModel?.PresetsApplicationName ?? "", ApplicationId = extModel?.ApplicationId ?? 0, StudentId = extModel?.StudentId ?? 0, DateType = extModel?.DateType ?? 0, SupplierId = extModel?.SupplierId ?? 0, StartDate = StringHelper.FormatDateTimeStr(extModel.StartDate), EndDate = StringHelper.FormatDateTimeStr(extModel.EndDate), CreateTime = StringHelper.FormatDateTimeStr(extModel.CreateTime), }); return ApiResult.Success(data: result); } /// /// 根据内容以及供应商获取ai内容 /// /// [HttpPost] public ApiResult GetAIContentByKeyWord() { string keyWord = base.ParmJObj.GetStringValue("KeyWord"); keyWord = StringHelper.UrlDecode(keyWord); //int supplierId = base.ParmJObj.GetInt("SupplierId", 0); int applicationId = base.ParmJObj.GetInt("ApplicationId", 0); if (applicationId == 0) { return ApiResult.ParamIsNull(); } var applocationModel = aiModule.GetAI_PresetsApplicationEntity(applicationId); if ((applocationModel?.ID ?? 0) == 0 || applocationModel.Status == Common.Enum.DateStateEnum.Delete || applocationModel.Enable == 2) { return ApiResult.Failed("应用信息不存在"); } if ((applocationModel?.SupplierId ?? 0) == 0) { return ApiResult.Failed("应用信息供应商不存在"); } string grade = base.ParmJObj.GetStringValue("Grade"); int Type = base.ParmJObj.GetInt("Type", 0);//1-英语作文批改(图像识别),2-英语作文批改(文本输入),3-中文作文批改(图像识别),4-中文作文批改(文本输入) var supplierModel = aiModule.GetAI_SupplierEntity(applocationModel.SupplierId); string imgUrl = base.ParmJObj.GetStringValue("ImgUrl"); RB_AI_UseLog_ViewModel userLogModel = new RB_AI_UseLog_ViewModel(); userLogModel.CreateBy = base.AppletUserInfo.Id; userLogModel.Group_Id = base.AppletUserInfo.Group_Id; userLogModel.School_Id = base.AppletUserInfo.School_Id; userLogModel.CreateTime = DateTime.Now; userLogModel.StudentId = this.AppletUserInfo.AccountId; userLogModel.ApplicationId = applicationId; userLogModel.SupplierId = applocationModel.SupplierId; userLogModel.TokenNum = ""; userLogModel.Charging = ""; userLogModel.KeyWord = keyWord; userLogModel.KeyWordType = Type; userLogModel.Status = Common.Enum.DateStateEnum.Normal; if ((supplierModel?.ID ?? 0) == 0) { return ApiResult.Failed("请选择应用"); } if (supplierModel.Enable != 1) { return ApiResult.Failed("当前应用供应商未启用"); } if ((Type == 1 || Type == 3) && string.IsNullOrWhiteSpace(imgUrl)) { return ApiResult.Failed("请上传图片信息"); } else if ((Type == 2 || Type == 4) && string.IsNullOrWhiteSpace(keyWord)) { return ApiResult.Failed("请输入关键字"); } var basicConfigureModel = new BasicConfigureModel(); if (!string.IsNullOrWhiteSpace(supplierModel.BasicConfigure)) { var info = JObject.Parse(supplierModel.BasicConfigure); basicConfigureModel.ApiKey = info.GetStringValue("ApiKey"); } if (supplierModel.SupplierType == Common.Enum.AI.SupplierTypeEnum.YouDaoNote) { if (!string.IsNullOrWhiteSpace(basicConfigureModel.ApiKey)) { string postUrl = ""; if (Type == 1 || Type == 3)//1-英语作文批改(图像识别) { userLogModel.KeyWord = imgUrl; userLogModel.Charging = "0.13(元/次)"; postUrl = (Type == 1 ? "https://openapi.youdao.com/v2/correct_writing_image" : "https://openapi.youdao.com/correct_writing_cn_image"); if (YouDaoHelper.RemoteFileExists(imgUrl)) { keyWord = YouDaoHelper.readFileAsBaes64_V2(imgUrl); } else { return ApiResult.Failed("图片获取失败,请稍后再试"); } } else if (Type == 2 || Type == 4) { userLogModel.Charging = "0.08(元/次)"; postUrl = (Type == 2 ? "https://openapi.youdao.com/v2/correct_writing_text" : "https://openapi.youdao.com/correct_writing_cn_text"); } // 添加请求参数 Dictionary paramsMap = YouDaoHelper.createRequestParams(keyWord: keyWord, Grade: grade); // 添加鉴权相关参数 AuthV4Util.addAuthParams("4427e2bed8595678", basicConfigureModel.ApiKey, paramsMap); Dictionary header = new Dictionary() { { "Content-Type", new String[] { "application/x-www-form-urlencoded" } } }; // 请求api服务 byte[] result = HttpUtil.doPost(postUrl, header, paramsMap, "application/json"); // 打印返回结果 if (result != null) { string resStr = System.Text.Encoding.UTF8.GetString(result); JObject jsonObject = JObject.Parse(resStr); if (jsonObject.GetStringValue("errorCode") == "0") { userLogModel.ResultInfo = resStr; int addId = aiModule.SetAIUseLogModule(userLogModel); // Task.Run(() => { }); return ApiResult.Success(data: new { result = resStr, Id = addId }); } else { return ApiResult.Failed(jsonObject.GetStringValue("msg")); } } } return ApiResult.Failed("解析失败!"); } else if (supplierModel.SupplierType == Common.Enum.AI.SupplierTypeEnum.OpenAI) { int addId = aiModule.SetAIUseLogModule(userLogModel); if (addId > 0) { var resultModel = new OpenAIModel { AccountId = this.AppletUserInfo.AccountId, ApplicationId = applicationId, KeyWord = keyWord, LogId = addId, Status = 0, CompletionResultModel = "", }; Cache.User.UserReidsCache.Set(this.AppletUserInfo.AccountId + "_" + "LogId_" + addId, resultModel, Common.Config.JwtExpirTime); PostAsync("sk-zk2ad4c7483a167ffcbb7246c4b551b02e967777cb2744fc", keyWord, addId); return ApiResult.Success(data: new { result = resultModel, Id = addId }); } } return ApiResult.Failed("解析失败!"); } static string ExtractContent(string jsonResponse) { string returnStr = ""; JObject json = JObject.Parse(jsonResponse); returnStr = json["choices"][0]["message"]["content"].ToString(); return returnStr; } /// /// 根据内容以及供应商获取ai内容 /// /// [HttpPost] public ApiResult GettestAIContentByKeyWord() { // PostAsync(); return ApiResult.Success(); } public async Task PostAsync(string apiSecretKey, string keyWord, int addId) { var data = new JObject(); data[user] = "测试者"; // messages var messageDatas = new JArray(); // 单个 message var messageData = new JObject { ["role"] = "user", ["content"] = keyWord }; // 存入 message messageDatas.Add(messageData); // 配置内容 data[messages] = messageDatas; // 编码 JSON var jsonData = data.ToString(); var dataBytes = Encoding.UTF8.GetBytes(jsonData); string cacheKey = this.AppletUserInfo.AccountId + "_" + "LogId_" + addId; Console.WriteLine("PostAsync:CacheKey:{0}", cacheKey); var returnModel = Cache.User.UserReidsCache.OpenAIGet(cacheKey); Console.WriteLine("PostAsync:returnModel_1:{0}", Common.Plugin.JsonHelper.Serialize(returnModel)); if (returnModel != null) { Console.WriteLine("PostAsync:returnModel_2:{0}", Common.Plugin.JsonHelper.Serialize(returnModel)); using (HttpClient client = new HttpClient()) { var requestContent = new ByteArrayContent(dataBytes); requestContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", apiSecretKey); HttpResponseMessage response = await client.PostAsync(postUrl, requestContent); if (response.IsSuccessStatusCode) { string receiveContent = await response.Content.ReadAsStringAsync(); returnModel.Status = 1; returnModel.CompletionResultModel = receiveContent; //更新数据库信息 var oldModel = aiModule.GetAIUseLogEntity(addId); if ((oldModel?.ID ?? 0) > 0) { oldModel.ResultInfo = receiveContent; try { JObject json = JObject.Parse(receiveContent); string prompt_tokens = json["usage"]["prompt_tokens"].ToString(); string completion_tokens = json["usage"]["completion_tokens"].ToString(); var tokenNum = new { prompt_tokens, completion_tokens, }; oldModel.TokenNum = JsonHelper.Serialize(tokenNum); } catch (Exception ex) { } aiModule.SetAIUseLogModule(oldModel); } Cache.User.UserReidsCache.SetOpenAIModelCache(cacheKey, returnModel, Common.Config.JwtExpirTime); } else { returnModel.Status = 3;//失败了 Cache.User.UserReidsCache.SetOpenAIModelCache(cacheKey, returnModel, Common.Config.JwtExpirTime); LogHelper.WriteInfo($"Error: {response.StatusCode}, {response.ReasonPhrase}"); } } } } /// /// 获取openAi的调用结果 /// /// [HttpPost] public ApiResult GetOpenAIResult() { //string dateStr = base.ParmJObj.GetStringValue("TimeUtc"); int Id = base.ParmJObj.GetInt("Id", 0); if (Id <= 0) { return ApiResult.ParamIsNull(); } var returnModel = Cache.User.UserReidsCache.OpenAIGet(this.AppletUserInfo.AccountId + "_" + "LogId_" + Id); if (returnModel == null) { return ApiResult.Failed("获取失败请重新调用"); } return ApiResult.Success(data: returnModel); } /// /// 根据id获取详情信息 /// /// [HttpPost] public ApiResult GetUserLog() { int Id = base.ParmJObj.GetInt("Id", 0); if (Id <= 0) { return ApiResult.ParamIsNull(); } var model = aiModule.GetAIUseLogEntity(Id); var result = new { model.ID, model.ApplicationId, model.SupplierId, model.Charging, model.TokenNum, model.KeyWordType, model.KeyWord, model.ResultInfo, SupplierType = model?.SupplierType ?? 0, PresetsApplicationName = model?.ApplicationName ?? "", SupplierName = model?.SupplierName ?? "", CreateTime = StringHelper.FormatDateTimeStr(model.CreateTime), }; return ApiResult.Success(data: result); } /// /// 获取AI调用记录分页列表 /// /// [HttpPost] public ApiResult GetAIUseLogPageList() { var pageModel = Common.Plugin.JsonHelper.DeserializeObject(RequestParm.Msg.ToString()); var query = new RB_AI_UseLog_ViewModel { StudentId = base.AppletUserInfo.AccountId, EndDate = base.ParmJObj.GetStringValue("EndDate"), StartDate = base.ParmJObj.GetStringValue("StartDate"), Group_Id = base.AppletUserInfo.Group_Id, }; if (string.IsNullOrWhiteSpace(query.StartDate) && string.IsNullOrWhiteSpace(query.EndDate)) { query.StartDate = StringHelper.FormatDate(DateTime.Now.AddMonths(-3)); } var list = aiModule.GetAIUseLogPageListModule(pageModel.PageIndex, pageModel.PageSize, out long rowsCount, query); pageModel.Count = rowsCount; pageModel.PageData = list.Select(x => new { x.ID, x.ApplicationId, x.SupplierId, x.Charging, x.TokenNum, x.KeyWordType, x.KeyWord, x.ResultInfo, SupplierType = x?.SupplierType ?? 0, PresetsApplicationName = x?.ApplicationName ?? "", SupplierName = x?.SupplierName ?? "", CreateTime = StringHelper.FormatDateTimeStr(x.CreateTime), }); return ApiResult.Success(data: pageModel); } /// /// grade 级别 /// /// [HttpPost] [HttpGet] [AllowAnonymous] public ApiResult GetYouDaoGrade() { List listChina = new List(); listChina.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "一年级", Content = "g1" }); listChina.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "二年级", Content = "g2" }); listChina.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "三年级", Content = "g3" }); listChina.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "四年级", Content = "g4" }); listChina.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "五年级", Content = "g5" }); listChina.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "六年级", Content = "g6" }); listChina.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "七年级", Content = "g7" }); listChina.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "八年级", Content = "g8" }); listChina.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "九年级", Content = "g9" }); listChina.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "高一", Content = "g10" }); listChina.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "高二", Content = "g11" }); listChina.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "高三", Content = "g12" }); List listEnglish = new List(); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "默认", Content = "default", RangeName = "100" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "小学", Content = "elementary", RangeName = "100" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "初中", Content = "junior", RangeName = "100" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "高中", Content = "high", RangeName = "25" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "四级", Content = "cet4", RangeName = "106.5" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "六级", Content = "cet6", RangeName = "106.5" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "考研", Content = "graduate", RangeName = "20" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "考研英语(一)大作文", Content = "graduate_b1", RangeName = "20" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "考研英语(一)小作文", Content = "graduate_a1", RangeName = "10" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "考研英语(二)小作文", Content = "graduate_a2", RangeName = "10" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "考研英语(二)大作文", Content = "graduate_b2", RangeName = "15" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "托福", Content = "toefl", RangeName = "30" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "托福-独立写作", Content = "toefl_independent", RangeName = "30" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "托福-综合写作", Content = "toefl_comprehensive", RangeName = "30" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "GRE", Content = "gre", RangeName = "6" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "雅思", Content = "ielts", RangeName = "9" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "雅思-task1", Content = "ielts_task1", RangeName = "9" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "雅思-task2", Content = "ielts_task2", RangeName = "9" }); listEnglish.Add(new RB_AI_PresetsApplication_ViewModel { DescribeName = "学术写作", Content = "academic", RangeName = "100" }); return ApiResult.Success(data: new { ChinaGradeList = listChina.Select(x => new { Name = x.DescribeName, Value = x.Content }), EnglishGradeList = listEnglish.Select(x => new { Name = x.DescribeName, Value = x.Content, Score = x.RangeName }) }); } } }