diff --git a/VideoAnalysis/Components/Pages/VideoTaskShow.razor b/VideoAnalysis/Components/Pages/VideoTaskShow.razor index 581d25d..3626de3 100644 --- a/VideoAnalysis/Components/Pages/VideoTaskShow.razor +++ b/VideoAnalysis/Components/Pages/VideoTaskShow.razor @@ -3,8 +3,11 @@
@if (videoKnows != null) { -
-

@nowTask.MediaName

+
+ +

+ + @nowTask.MediaName

@for (int i = 0; i < videoKnows.Length; i++) { var item = videoKnows[i]; @@ -63,11 +66,21 @@ window.subtitles = a window.b = b const videoPlayer = document.getElementById('videoPlayer'); - videoPlayer.src=c + videoPlayer.src = c init() } //点击时间片时 function spClick(i, button) { videoPlayer.currentTime = displayButton[i].startTime; } + function gd(btn) { + let e = btn.parentElement.parentElement + if (e.style.right == "0px") { + btn.innerHTML = "🔒" + e.style.right = "-300px" + } else { + e.style.right = "0px" + btn.innerHTML = "🔓" + } + } diff --git a/VideoAnalysis/Components/Pages/VideoTaskShow.razor.cs b/VideoAnalysis/Components/Pages/VideoTaskShow.razor.cs index c41e07d..318a073 100644 --- a/VideoAnalysis/Components/Pages/VideoTaskShow.razor.cs +++ b/VideoAnalysis/Components/Pages/VideoTaskShow.razor.cs @@ -57,10 +57,10 @@ namespace Learn.VideoAnalysis.Components.Pages } public string getF(VideoKnowRes segment) { - var sf = (int)((segment.StartTime ?? 0) / 60); - var sm = (int)((segment.StartTime ?? 0) % 60); - var ef = (int)((segment.EndTime ?? 0) / 60); - var em = (int)((segment.EndTime ?? 0) % 60); + var sf = ((int)((segment.StartTime ?? 0) / 60)).ToString().PadLeft(2,'0'); + var sm = ((int)((segment.StartTime ?? 0) % 60)).ToString().PadLeft(2, '0'); + var ef = ((int)((segment.EndTime ?? 0) / 60)).ToString().PadLeft(2, '0'); + var em = ((int)((segment.EndTime ?? 0) % 60)).ToString().PadLeft(2, '0'); return $"{sf}:{sm} - {ef}: {em}"; } /// diff --git a/VideoAnalysis/Components/Pages/VideoTaskShow.razor.css b/VideoAnalysis/Components/Pages/VideoTaskShow.razor.css index cd3fe16..eddbc0e 100644 --- a/VideoAnalysis/Components/Pages/VideoTaskShow.razor.css +++ b/VideoAnalysis/Components/Pages/VideoTaskShow.razor.css @@ -16,7 +16,13 @@ video { width: 94%; height: 85%; } - +.gudingBtn { + width: 32px; + height: 32px; + /* border-radius: 16px; */ + line-height: 27px; + text-align: center; +} .subtitles { position: absolute; bottom: 200px; @@ -28,18 +34,18 @@ video { } #segmentsContainer:is(:hover) { width: 400px; - right: 0px; + right: 0px!important; } #segmentsContainer { - transition:right 0.7s; - z-index:999; + transition: right 0.7s; + z-index: 999; overflow-x: hidden; background-color: #e3e3e3c2; position: absolute; - right: -180px; + right: -300px; display: flex; flex-direction: column; - width: 265px; + width: 400px; height: 850px; gap: 10px; overflow: hidden; @@ -52,18 +58,18 @@ video { align-items: center; } - #segmentsContainer button { - width: 100%; - height: 60px; - font-size: 1.3rem; - text-align: left; - cursor: pointer; - color: rgb(103, 194, 58); - background-color: rgb(240, 249, 235); - border: 1px solid rgb(179, 225, 157); - } +.kBtn { + width: 100%; + height: 60px; + font-size: 1.3rem; + text-align: left; + cursor: pointer; + color: rgb(103, 194, 58); + background-color: rgb(240, 249, 235); + border: 1px solid rgb(179, 225, 157); +} - #segmentsContainer button:hover { - background-color: rgb(248, 230, 191) !important; - border: 1px solid rgb(206, 187, 81); - } +.kBtn:hover { + background-color: rgb(248, 230, 191) !important; + border: 1px solid rgb(206, 187, 81); +} diff --git a/VideoAnalysisCore/AICore/GPT/ChatGPT/ChatGPTModel.cs b/VideoAnalysisCore/AICore/GPT/ChatGPT/ChatGPTModel.cs index 8279331..c4f9b6d 100644 --- a/VideoAnalysisCore/AICore/GPT/ChatGPT/ChatGPTModel.cs +++ b/VideoAnalysisCore/AICore/GPT/ChatGPT/ChatGPTModel.cs @@ -16,7 +16,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT /// public Message[] messages { get; set; } public string model { get; set; } = "gpt-4o"; - public float temperature { get; set; } = 0.3f; + public float temperature { get; set; } = 0.2f; public float max_tokens { get; set; } = 4000; public object response_format = new { type = "json_object" }; // 指定结构化输出格式 } diff --git a/VideoAnalysisCore/AICore/GPT/ChatGPT/Chat_GPT.cs b/VideoAnalysisCore/AICore/GPT/ChatGPT/Chat_GPT.cs index a828c38..8e786e8 100644 --- a/VideoAnalysisCore/AICore/GPT/ChatGPT/Chat_GPT.cs +++ b/VideoAnalysisCore/AICore/GPT/ChatGPT/Chat_GPT.cs @@ -77,7 +77,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT .FirstAsync(); var subject = "数学"; var xkwKnows = await knowledgeInfoDB.AsQueryable() - .Where(s => s.Course_Id == 27 + .Where(s => s.Course_Id == 27 && s.Depth == 2) .Select(s => s.Name).ToArrayAsync(); string title = taskInfo.MediaName; @@ -87,47 +87,55 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT $"1.分析出高中{subject}课堂授课的主要章节(例如 章节: 数列),章节范围限定在[{string.Join(',', xkwKnows)}]范围." + $"2.分析出这堂课的主要授课内容." + $"输出格式 json字符串 对象格式{fileNameResFormat}"; - var fileNameInfoRes = await ChatAsync(task, fileNamePostMessages, fileNameResFormat); + var fileNameInfoRes = await ChatAsync(task, fileNamePostMessages,null, fileNameResFormat); - var captions = ExpandFunction.GetSpeakerCaptions(task); + var captions = ExpandFunction.GetSpeakerCaptions(task); var criteriaBuilder = new StringBuilder(); - var resFormat = """[{"StartTime":开始秒(number),"EndTime":结束秒(number),"Section":章节(string),"Theme":主题(string),"NewTheme":新主题(string),"Content":内容总结(string)}]"""; + var resFormat = """[{"StartTime":开始秒(number),"EndTime":结束秒(number),"Section":章节(string),"Theme":主题(string),"ThemeDetalis":主题详情(string),"Content":内容总结(string)}]"""; var know = await knowledgeInfoDB.GetFirstAsync(s => s.Name == fileNameInfoRes.授课章节); var knowledgeInfos = await knowledgeInfoDB.AsQueryable().ToChildListAsync(s => s.Parent_Id, know.Id); var knows = "数列的概念,数列的定义,项的表示,数列的表示方法,通项公式,递推公式,图像表示,数列的类型,等差数列,等比数列,其他特殊数列,数列的性质,单调性,有限性,数列的求和,等差数列求和公式,等比数列求和公式,数列极限,递推关系"; knows = string.Join(',', knowledgeInfos.Select(s => s.Name)); + var postMessages = $"你的任务是分析视频字幕内容并提取出中国高考考试试题方法点,然后根据步骤分析出内容片段" + $"按以下步骤完成:" + - $"1.识别方法点:提取字幕内容中与{subject}考试相关的方法点。" + - $"2.分类方法点:按学科方法点,细化到具体章节与主题(例如“章节:数列 主题:数列的基本概念”)。" + - $"3.分析总结:基于提取出的方法点名称来匹配我提供的方法点名称" + - $"提供的方法点名称(基本概念,课堂练习,{knows},例题讲解)。" + - $"4.关联合并相似的知识点来合并为内容片段。" + + $"1.识别方法点:提取字幕内容中与{subject}考试属于{fileNameInfoRes.授课章节}章节相关的方法点。" + + $"2.分析总结:基于提取出的方法点名称来匹配我提供的方法点名称" + + $"提供的方法点名称(基本概念,课堂练习,例题讲解,{knows})。" + + $"3.关联合并相似的知识点来合并为内容片段。" + $"内容片段使用关联知识点中的最小(开始秒)和(最大)结束秒,主题为关联知识点的主题分析,内容总结为关联知识点的内容总结分析。" + - $"延长内容片段时间区间来获取更加详细的上下文。" + - $"基于内容片段的内容总结加上主题来分析这个片段对主题的讲解内容为新的主题 例(数列的基本概念)。" + + $"4.基于内容片段的内容总结加上主题来分析这个片段对主题的讲解内容为新的主题 例(数列的基本概念)。" + + $"5.分配空余未使用的时间段到内容相近的内容片段时间区间来获取更加详细的上下文,但是请避免内容片段之间时间重合。" + $"输入:包含时间戳的视频字幕文本。" + $"以下是包含时间的视频字幕文本。" + $"字幕格式(说话人:开始秒:结束秒:内容|下一段字幕).字幕列表 {captions.Captions}" + $"输出格式({resFormat})"; + var questionRes = await ChatAsync(task, postMessages, null, resFormat); //var postMessages = - // $"你是一名专业的教育视频内容分析助手,主要任务是分析视频字幕内容,精准提取出与中国高考数学考试相关的试题方法点。" + + // $"你的任务是分析视频字幕内容,精准提取出与中国高考数学考试相关的试题方法点。" + // $"按以下步骤完成:" + - // $"1.准确识别方法点:从字幕中提取与{subject}考试紧密相关的方法点,尤其关注与给定方法点类别相关的内容" + + // $"1.准确识别方法点:从字幕中提取与考试紧密相关的方法点,尤其关注与给定方法点类别相关的内容" + // $"2.深入分析总结:依据给定的方法点类别进行约束,确定提取出的方法点所属类别。" + - // $"给定方法点包括(基本概念,课堂练习,例题讲解,解题技巧,{gjz})。" + + // $"给定方法点包括(基本概念,课堂练习,例题讲解,解题技巧...)。" + // $"3.细致分类方法点:按照学科方法点进行分类,具体细化到特定章节与主题,格式为 “章节:具体章节名称 主题:具体主题名称" + // $"4.合理合并相似方法点为内容片段,确保内容的连贯性和逻辑性" + // $"5.关联每个内容片段的方法点所有的时间并结构化输出。" + + // $"6.基于内容片段的内容总结加上主题来分析这个片段对主题的讲解内容为新的主题 例(数列的基本概念)。" + // $"尽可能延内容片段时间区间,以获取详细的方法点上下文。" + - // $"输入:包含时间戳的视频字幕文本。输出格式:开始秒,结束秒,主题,内容总结" + - // $"以下是包含时间的视频字幕文本。" + + // $"输入:包含时间戳的视频字幕文本。输出格式:开始秒,结束秒,主题,内容总结" ; + //var postM2 = $"以下是包含时间的视频字幕文本。" + // $"字幕格式(说话人:开始秒:结束秒:内容|下一段字幕).字幕列表 {captions.Captions}" + // $"返回固定的JSON格式({resFormat})"; - var questionRes =await ChatAsync(task, postMessages, resFormat); + //var questionRes = await ChatAsync(task, postMessages, postM2, resFormat); + if (questionRes.Length <= 3) + throw new Exception("视频分段数量过低 =>"+ questionRes.Length); + + if (questionRes.Count(s=>s.ThemeDetalis == questionRes.First().ThemeDetalis) >= 3) + throw new Exception("视频分段主题重复 =>" + questionRes.First().ThemeDetalis); + await RedisExpand.Redis .HMSetAsync(RedisExpandKey.Task(task), "VideoKnows", questionRes); @@ -141,7 +149,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT // $"以下是包含json内容的文本。" + // $" {JsonSerializer.Serialize(questionRes)}" + // $"返回固定的JSON格式({resFormat})"; - + //var questionRes1 = await ChatAsync(task, postMessages1, resFormat); ////questionRes1 = MergeRes(questionRes1).ToArray(); @@ -152,17 +160,20 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT RedisExpand.InsertChannel(RedisChannelEnum.EndTask, task); return gptRes; } - public async Task ChatAsync(string task,string postMessages,string resFormat) + public async Task ChatAsync(string task, string postMessages,string postMessages1, string resFormat) { var maxTokens = 4000; + Message[] messageArr = [ + new Message(postMessages,"system"), + string.IsNullOrEmpty(postMessages1)?null:new Message(postMessages1,"user"), + new Message(resFormat,"assistant"), + ]; + messageArr = messageArr.Where(s => s != null).ToArray(); var chatRep = new ChatRequest { max_tokens = maxTokens, - temperature = 0.3f, - messages = [ - new Message(postMessages,"system"), - new Message(resFormat,"assistant"), - ] + temperature = 0.2f, + messages = messageArr }; RedisExpand.SetTaskGPTReqCached(task, chatRep); @@ -180,8 +191,8 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT chatResContent = chatResContent?.Replace("}{", "},{"); chatResContent = chatResContent?.Replace("}|{", "},{"); chatResContent = chatResContent?.Trim(); - var startsStr = typeof(T).IsArray? "[" :"{"; - var endStr = typeof(T).IsArray? "]" : "}"; + var startsStr = typeof(T).IsArray ? "[" : "{"; + var endStr = typeof(T).IsArray ? "]" : "}"; if (!chatResContent.StartsWith(startsStr)) chatResContent = startsStr + chatResContent; if (!chatResContent.EndsWith(endStr)) @@ -334,7 +345,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT Merit = ccArr.Where(s => s.Score >= s.PassScore).ToArray(), }; //高频词汇 - gptRes.Hotwords = + gptRes.Hotwords = arr2[(int)QuestionTypeEnum.高频词].ToObject() ?? ["暂无数据"]; //时间段概览 gptRes.TimeOverview = arr2[(int)QuestionTypeEnum.时间段概览] diff --git a/VideoAnalysisCore/AICore/GPT/Dto/QuestionRes.cs b/VideoAnalysisCore/AICore/GPT/Dto/QuestionRes.cs index 2db7867..5a6854b 100644 --- a/VideoAnalysisCore/AICore/GPT/Dto/QuestionRes.cs +++ b/VideoAnalysisCore/AICore/GPT/Dto/QuestionRes.cs @@ -26,9 +26,9 @@ namespace VideoAnalysisCore.AICore.GPT.Dto /// public string? Theme { get; set; } /// - /// 新主题 + /// 主题详情 /// - public string? NewTheme { get; set; } + public string? ThemeDetalis { get; set; } /// /// 章节 ///