优化 调试工作流1的AI分析流程(知识点权重,来源,AI复查复检...)
This commit is contained in:
parent
b4b02cfbd3
commit
a2d14487cb
|
|
@ -42,7 +42,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
|
|||
/// <param name="max_tokens">最大token <para>不设置默认最大值 16000/8000</para></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public override async Task<T> ChatAsync<T>(string task, string postMessages, string title, string model =null, int max_tokens = 16000)
|
||||
public override async Task<T> ChatAsync<T>(string task, string postMessages, string title, string model =null, int max_tokens = 32000)
|
||||
{
|
||||
Message[] messageArr = [
|
||||
new Message(postMessages,"user"),
|
||||
|
|
@ -53,7 +53,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
|
|||
taskId = task,
|
||||
title = title,
|
||||
model = model ?? ChatGPTType.Deepseek_Reasoner,
|
||||
max_tokens = model == ChatGPTType.Deepseek_Reasoner ? 16000 : max_tokens,
|
||||
max_tokens = model == ChatGPTType.Deepseek_Reasoner ? 32000 : max_tokens,
|
||||
stream = true,
|
||||
temperature = 0.2f,
|
||||
messages = messageArr
|
||||
|
|
|
|||
|
|
@ -34,9 +34,10 @@ namespace VideoAnalysisCore.AICore.GPT.Dto
|
|||
}
|
||||
public class VideoKnowPointDto
|
||||
{
|
||||
public float KnowPointWeight { get; set; }
|
||||
public string KnowPoint { get; set; }
|
||||
public string KnowPointId { get; set; }
|
||||
public float KnowSourceTime { get; set; }
|
||||
public string KnowSource { get; set; }
|
||||
}
|
||||
public class VideoKnowRes
|
||||
{
|
||||
|
|
@ -64,6 +65,10 @@ namespace VideoAnalysisCore.AICore.GPT.Dto
|
|||
/// </summary>
|
||||
public virtual string? KnowPoint { get; set; }
|
||||
/// <summary>
|
||||
/// 知识点权重
|
||||
/// </summary>
|
||||
public virtual float? KnowPointWeight { get; set; }
|
||||
/// <summary>
|
||||
/// 知识点ID
|
||||
/// </summary>
|
||||
public virtual string? KnowPointId { get; set; }
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ using System.IO;
|
|||
using VideoAnalysisCore.AICore.GPT.ChatGPT;
|
||||
using System.Threading.Tasks;
|
||||
using System.Text.Json;
|
||||
using FFmpeg.NET.Services;
|
||||
using NetTaste;
|
||||
|
||||
namespace VideoAnalysisCore.AICore.GPT
|
||||
{
|
||||
|
|
@ -156,7 +158,7 @@ namespace VideoAnalysisCore.AICore.GPT
|
|||
/// <param name="max_tokens">最大token <para>不设置默认最大值 16000/8000</para></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task<T> ChatAsync<T>(ChatRequest chatRep)
|
||||
public async Task<T> ChatAsync<T>(ChatRequest chatRep) where T:class,new()
|
||||
{
|
||||
var tryCount = 10;
|
||||
while (tryCount-- > 0)
|
||||
|
|
@ -186,8 +188,14 @@ namespace VideoAnalysisCore.AICore.GPT
|
|||
|
||||
if (string.IsNullOrEmpty(chatResContent))
|
||||
throw new Exception($"GPT返回结果无有效JSON =>{chatResp?.res}");
|
||||
var startsStr = typeof(T).IsArray ? "[" : "{";
|
||||
var endStr = typeof(T).IsArray ? "]" : "}";
|
||||
var startsStr = "{";
|
||||
var endStr = "}";
|
||||
var resT = new T();
|
||||
if (resT is Array || resT is System.Collections.IList || resT is System.Collections.IList)
|
||||
{
|
||||
startsStr = "[";
|
||||
endStr = "]";
|
||||
}
|
||||
if (!chatResContent.StartsWith(startsStr))
|
||||
chatResContent = startsStr + chatResContent;
|
||||
if (!chatResContent.EndsWith(endStr))
|
||||
|
|
@ -271,7 +279,7 @@ namespace VideoAnalysisCore.AICore.GPT
|
|||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public virtual Task<T> ChatAsync<T>(string task, string postMessages, string title,
|
||||
string model = null, int max_tokens = 16000)
|
||||
string model = null, int max_tokens = 16000) where T : class, new()
|
||||
{
|
||||
throw new Exception("需要实现");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ using System.Collections.Generic;
|
|||
using UserCenter.Model.Enum;
|
||||
using Dm.filter;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||
{
|
||||
|
|
@ -81,28 +82,37 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
questionRes = questionRes.Where(s => s != null)
|
||||
.OrderBy(s => s.StartTime).ToList();
|
||||
var thems = questionRes.Adapt<VideoKnowQueryDto[]>().ToJson();
|
||||
var checkResFormat1 = """[{"StartTime":开始秒(number),"TextbookSource":教材来源(string),"KnowPoints":[{"KnowSourceTime":"知识点来源的开始秒(number)","KnowPoint":知识点名称(string),"KnowPointId":知识点Id(string)}]}]""";
|
||||
var checkResFormat1 = """[{"StartTime":12.3,"TextbookSource":"课本","KnowPoints":[{"KnowPointWeight":0.5,"KnowSource":"开始时间(秒),匹配的原因","KnowPoint":"知识点名称","KnowPointId":"123"}]}]""";
|
||||
var knowMessages =
|
||||
$"我针对{taskInfo.Subject}课堂授课视频分析出了视频的授课阶段片段。\n" +
|
||||
$"现在需要你通过每个片段的内容总结来分配正确的知识点(单个片段允许多个知识点)。\n" +
|
||||
$"KnowSourceTime字段 需要提供出知识点被匹配的字幕内容最开始的时间来源。\n" +
|
||||
$"TextbookSource字段 需要你分析出单个片段内讲述内容所属的教材范围 例如 (范围限定在 课本/试卷/挹青苑/其他)。\n" +
|
||||
$"这是我的分段 {thems}。\n" +
|
||||
$"课堂内容与{sections}章节相关\n" +
|
||||
$"最后请确保分配的知识点是用户提供的,并且一定正确合理!\n" +
|
||||
$"返回的片段数量与传入片段数量一致!(硬性条件)\n" +
|
||||
$"输出内容只返回json格式({checkResFormat1})\n" +
|
||||
$" 格式 (方法点Id|方法点名称) \n" +
|
||||
$"提供的`知识点名称({knows})。\n";
|
||||
$"""
|
||||
角色:你是一位{taskInfo.Subject}学科教研老师。
|
||||
任务:为每个【视频分段】分配对应的知识点(可多个),并补充来源信息。
|
||||
字段说明:
|
||||
- TextbookSource:该分段讲授内容所属教材来源,仅允许取值:课本/试卷/挹青苑/其他
|
||||
- KnowPoints:数组。每个元素代表一个知识点匹配结果
|
||||
- KnowPoint:知识点名称(必须来自我提供的列表)
|
||||
- KnowPointId:知识点ID(必须与 KnowPoint 对应)
|
||||
- KnowPointWeight:知识点在本分段的占比权重(最高为1,单个分段内的知识点权重之和必须等于1)
|
||||
- KnowSource:该知识点在字幕中被首次提及的“开始秒,为什么匹配的原因(最多50字)”
|
||||
强制约束(硬性条件):
|
||||
1) 输出数组长度必须与输入分段长度一致,且顺序一致;不得新增/删除/合并分段。
|
||||
2) 每个对象的 StartTime 必须与输入分段的 StartTime 完全一致(不得改动)。
|
||||
3) KnowPoints 允许为空数组(表示未能匹配任何知识点),但不要输出空字符串或用逗号拼接。
|
||||
4) 只输出 JSON(禁止 Markdown/解释/额外文本)。
|
||||
输入分段:{thems}
|
||||
章节:{sections}
|
||||
知识点列表(Id|Name):{knows}
|
||||
输出格式示例:{checkResFormat1}
|
||||
""";
|
||||
await redisManager.AddTaskLog(taskInfo.Id, "==>2.开始分析视频内容知识点");
|
||||
VideoKnowRes[] konwRes;
|
||||
List<VideoKnowRes> konwRes;
|
||||
var knowOK = false;
|
||||
var chatClentArr = new GPTClient[] { chatGPTClient, geminiClient, deepSeekClient };
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
konwRes = await chatClentArr[i].ChatAsync<VideoKnowRes[]>(taskInfo.Id.ToString(), knowMessages, "知识点");
|
||||
konwRes = await chatClentArr[i].ChatAsync<List<VideoKnowRes>>(taskInfo.Id.ToString(), knowMessages, "知识点");
|
||||
// 分析结果的片段数量与预期不匹配
|
||||
if (questionRes.Count() != konwRes.Length) continue;
|
||||
if (questionRes.Count() != konwRes.Count()) continue;
|
||||
for (int xi = 0; xi < konwRes.Count(); xi++)
|
||||
{
|
||||
questionRes[xi].KnowPoints = konwRes[xi].KnowPoints;
|
||||
|
|
@ -132,7 +142,9 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
EndTime = s.EndTime,
|
||||
StageId = StageId,
|
||||
KnowPoint = x.KnowPoint,
|
||||
KnowSourceTime = x.KnowSourceTime,
|
||||
KnowPointWeight=x.KnowPointWeight,
|
||||
TextbookSource = s.TextbookSource,
|
||||
KnowSource = x.KnowSource,
|
||||
KnowPointId = knowDic[x.KnowPoint].ToString(),
|
||||
TagId = taskInfo.TagId,
|
||||
VideoTaskId = taskInfo.Id,
|
||||
|
|
@ -197,7 +209,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
var pptFormat = taskInfo.VideoType == AttachmentsInfoType.复习
|
||||
? "这堂课是习题课,所讲解内容几乎都是试题。"
|
||||
: string.Empty;
|
||||
var checkResFormat = """{"Score":85.5,"MinusScore":"简洁的扣分原因","Suggestion":"改进建议"}""";
|
||||
var checkResFormat = """{"Score":65.5,"MinusScore":"简洁的扣分原因","Suggestion":"简洁的改进建议"}""";
|
||||
var checkMessage =
|
||||
$"""
|
||||
请你担任一位专业的视频内容分析教研老师,擅长评估视频内容的结构和逻辑流暢度。
|
||||
|
|
@ -209,8 +221,9 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
知识点分配:检查分段内的知识点是否与分段Conten有关联,知识点分配给这个分段是否合理(硬性指标)。
|
||||
逻辑过渡:评估分段之间的过渡是否自然流畅,后一段是否是前一段内容的合理延伸或转折。
|
||||
综合评分:
|
||||
请基于以上分析,提供一个0-100的综合得分(70分及格)。
|
||||
详细说明打分理由,并逐条对应到上述评估维度。
|
||||
请基于以上分析,提供一个0-100的综合得分(70分及格,打分一定要严谨,总分一定要准确)。
|
||||
MinusScore: 详细说明打分理由,并逐条对应到上述评估维度。
|
||||
Suggestion: 基于扣分原因提出针对分段方案的改进意见(请忽略掉分段没有结束时间的问题我会自己处理)。
|
||||
输入数据格式说明:
|
||||
分段方案: {thems}
|
||||
字幕文本: 格式为说话人:开始秒:结束秒:内容|下一段字幕。完整内容为:{captions.Captions}
|
||||
|
|
@ -257,8 +270,8 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
输出格式(仅 JSON):{resFormat}
|
||||
""";
|
||||
|
||||
var improved = await geminiClient.ChatAsync<VideoKnowRes[]>(taskInfo.Id.ToString(), message, "分段优化");
|
||||
if (improved is null || improved.Length != questionRes.Count())
|
||||
var improved = await geminiClient.ChatAsync<List<VideoKnowRes>>(taskInfo.Id.ToString(), message, "分段优化");
|
||||
if (improved is null || improved.Count() != questionRes.Count())
|
||||
return null;
|
||||
|
||||
return improved.OrderBy(s => s.StartTime ?? 0).ToList();
|
||||
|
|
@ -271,7 +284,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
private async Task<SenseVoiceRes[]> OptimizeSubtitles(VideoTask taskInfo,
|
||||
SenseVoiceRes[] captionsArr, string sections)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(taskInfo.CaptionsAI))
|
||||
if (!string.IsNullOrEmpty(taskInfo.CaptionsAI) && taskInfo.CaptionsAI!="[]")
|
||||
return JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.CaptionsAI);
|
||||
var subject = taskInfo.Subject.ToString();
|
||||
var newCaptionsList = new List<SenseVoiceRes>(captionsArr.Length);
|
||||
|
|
@ -306,10 +319,10 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
$"待优化字幕内容:\n" +
|
||||
$"{nowCaptionStr}\n" +
|
||||
$"最终核对:请确保输出 JSON 中包含的字幕条数与输入的字幕条数完全对应。";
|
||||
string[]? resData = null;
|
||||
List<string>? resData = null;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
resData = await chatClentArr[i].ChatAsync<string[]>(taskInfo.Id.ToString(), postMessages, "优化字幕", ChatGPTType.Deepseek_Chat, 8000);
|
||||
resData = await chatClentArr[i].ChatAsync<List<string>>(taskInfo.Id.ToString(), postMessages, "优化字幕", ChatGPTType.Deepseek_Chat, 8000);
|
||||
if (resData.Count() == cArr.Count())
|
||||
break;
|
||||
else
|
||||
|
|
@ -318,7 +331,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
|
||||
if (resData.Count() != cArr.Count())
|
||||
{
|
||||
resData = cStrArr.ToArray();
|
||||
resData = cStrArr.ToList();
|
||||
await redisManager.AddTaskLog(taskInfo.Id, $"==>字幕优化 分段{s} AI结果数量不匹配 采用原始值");
|
||||
}
|
||||
newCaptionsList.AddRange(resData.Select((text, i) => new SenseVoiceRes()
|
||||
|
|
@ -366,13 +379,12 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
$"完整的课堂标准流程包含以下5个阶段:课程引入/新知讲解/例题精讲/课堂练习/知识总结。\n" +
|
||||
reviewStr +
|
||||
$"讲解知识内容的阶段的细分程度到某个知识点的讲解/认识/例题/总结\n" +
|
||||
$"不分析课堂作业相关的内容我已经预处理了\n" +
|
||||
$"初步划分阶段:{keyFrameStr}\n" +
|
||||
$"\n" +
|
||||
$"内容分析:对每个时间段,提取主要讲解内容:识别关键词(如“例题”“证明”“练习”“总结”)和内容结构。\n" +
|
||||
$"判断阶段类型:如果内容以解题为主,归类为“例题精讲”;如果涉及新知识讲解,归类为“新知讲解”;以此类推。\n" +
|
||||
$"内容总结:简述该阶段的核心讲解内容40~150字, 必须完全基于字幕文本可推断的信息,禁止捏造不存在的内容(硬性条件)。\n" +
|
||||
$"阶段主题:基于内容总结,提炼一个恰当的主题(例如,“柯西不等式的基本应用”)。\n" +
|
||||
$"输出要求:确保阶段划分合理、无重叠\n" +
|
||||
$"Stage:判断阶段类型如果内容以解题为主,归类为“例题精讲”;如果涉及新知识讲解,归类为“新知讲解”;以此类推。\n" +
|
||||
$"Content:简述单个阶段的核心讲解内容40~150字(如“例题”“证明”“练习”“总结”...), 必须完全基于字幕文本可推断的信息,禁止捏造不存在的内容(硬性条件)。\n" +
|
||||
$"Theme:理解Content,提炼一个精确的主题(例如,“柯西不等式的基本应用”)。\n" +
|
||||
$"输出要求:确保阶段划分合理、无重叠、\n" +
|
||||
$"作业布置阶段一般出现在末尾如果有" +
|
||||
$"输出格式要求:内容只返回json格式({resFormat})\n" +
|
||||
$"字幕格式(开始秒:内容|下一段字幕).以下是包含时间的视频字幕文本。\n" +
|
||||
|
|
@ -424,7 +436,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
输出格式(仅 JSON):{resFormat}
|
||||
""";
|
||||
|
||||
var res = await deepSeekClient.ChatAsync<VideoKnowRes>(taskInfo.Id.ToString(), message, "作业布置识别");
|
||||
var res = await deepSeekClient.ChatAsync<VideoKnowRes>(taskInfo.Id.ToString(), message, "作业布置识别", ChatGPTType.Deepseek_Chat, 8000);
|
||||
if (res is null)
|
||||
return null;
|
||||
if (!string.Equals(res.Stage, "作业布置", StringComparison.OrdinalIgnoreCase))
|
||||
|
|
@ -575,7 +587,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
$"输出内容只返回json格式为({resFormat})" +
|
||||
$"以下是试题内容" +
|
||||
$"`{sRes.Result.res.value}`";
|
||||
var resData = await deepSeekClient.ChatAsync<VideoQuestionOSSDto[]>(taskInfo.Id.ToString(), postMessages, "提取试题");
|
||||
var resData = await deepSeekClient.ChatAsync<List<VideoQuestionOSSDto>>(taskInfo.Id.ToString(), postMessages, "提取试题");
|
||||
//var resData = await chatClient.ChatAsync<VideoQuestionOSSDto[]>(taskInfo.Id.ToString(), postMessages, "提取试题");
|
||||
if (resData is null || resData.Count() == 0)
|
||||
break;
|
||||
|
|
@ -704,8 +716,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
if (questionRes is null) continue;
|
||||
//处理分段 知识点
|
||||
List<VideoKonwPoint> insertData = await GetVideoKnow(questionRes, taskInfo, sections, knowledgeInfos);
|
||||
if (homework != null)
|
||||
questionRes.Add(homework);
|
||||
|
||||
//校验结果质量
|
||||
var checkRes = await VerifySpanQuality(questionRes, taskInfo, captions, sections, Course_Id);
|
||||
|
||||
|
|
@ -715,16 +726,19 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
// 质量复检
|
||||
if (checkRes != null)
|
||||
{
|
||||
var improved = await ImproveSpanBySuggestion(questionRes, taskInfo, captions, sections, checkRes.Suggestion);
|
||||
var improved = await ImproveSpanBySuggestion(questionRes, taskInfo, captions, sections, "扣分原因 {checkRes.MinusScore} \n 改进意见 {checkRes.Suggestion}");
|
||||
if (improved != null)
|
||||
{
|
||||
var improvedCheck = await VerifySpanQuality(improved, taskInfo, captions, sections, Course_Id);
|
||||
await redisManager.AddTaskLog(taskInfo.Id, $"==>优化后复检得分=>{improvedCheck.Score}");
|
||||
await redisManager.AddTaskLog(taskInfo.Id, $"==>优化后扣分原因 {improvedCheck.MinusScore}");
|
||||
|
||||
if (improvedCheck != null && improvedCheck.Score >= 90)
|
||||
if (improvedCheck != null && improvedCheck.Score >= 90 && improvedCheck.Score > checkRes.Score)
|
||||
{
|
||||
questionRes = improved;
|
||||
if (homework != null && (!questionRes.Any(s => s.Stage == StageEnum.作业布置.ToString())))
|
||||
questionRes.Add(homework);
|
||||
|
||||
insertData = await GetVideoKnow(questionRes, taskInfo, sections, knowledgeInfos);
|
||||
await videoKonwPointDB.DeleteAsync(s => s.VideoTaskId == taskInfo.Id);
|
||||
await videoTaskStageDB.DeleteAsync(s => s.VideoTaskId == taskInfo.Id);
|
||||
|
|
@ -733,9 +747,10 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
Id = s.Key,
|
||||
TagId = s.First().TagId,
|
||||
CloudSchoolId = s.First().CloudSchoolId,
|
||||
StartTime = s.Last().StartTime,
|
||||
EndTime =s.Last().EndTime,
|
||||
KnowSourceTime=s.Last().KnowSourceTime,
|
||||
StartTime = s.First().StartTime,
|
||||
EndTime = s.First().EndTime,
|
||||
Content = s.First().Content,
|
||||
TextbookSource = s.First().TextbookSource,
|
||||
Stage = s.First().Stage,
|
||||
Theme = s.First().Theme,
|
||||
VideoTaskId = taskInfo.Id,
|
||||
|
|
@ -744,6 +759,11 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
|||
await videoKonwPointDB.InsertRangeAsync(insertData);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
await redisManager.AddTaskLog(taskInfo.Id, $"==>优化之后的得分降低/得分过低");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
|
|||
stream = true,
|
||||
temperature = 0.2f,
|
||||
messages = messageArr,
|
||||
max_completion_tokens=16000,
|
||||
max_completion_tokens= 12288,
|
||||
};
|
||||
|
||||
chatReq.modalities = null;
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
|
|||
throw new Exception("task 音频路径未找到");
|
||||
if (OR is null) Init();
|
||||
serviceProvider.GetRequiredService<SherpaVad>()
|
||||
.TaskHandle(new WaveReader(filePath), null, SoundHandle, SherpaVadVersion.silero_vad_v5);
|
||||
.TaskHandle(new WaveReader(filePath), task, SoundHandle, SherpaVadVersion.silero_vad_v5);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ namespace VideoAnalysisCore.Controllers
|
|||
private readonly Repository<VideoTask> videoTaskDB;
|
||||
private readonly Repository<CourseInfo> courseInfoDB;
|
||||
private readonly Repository<VideoKonwPoint> videoKonwPointDB;
|
||||
private readonly Repository<VideoTaskStage> videoTaskStageDB;
|
||||
private readonly Repository<NodePackageInfo> nodePackageInfoDB;
|
||||
private readonly Repository<VideoQuestion> videoQuestionDB;
|
||||
private readonly Repository<VideoQuestionKonw> videoQuestionKonwDB;
|
||||
|
|
@ -42,7 +43,7 @@ namespace VideoAnalysisCore.Controllers
|
|||
|
||||
public LJZK_Controller(IMapper mp, Repository<NodeSubscription> nodesubscriptionDB,
|
||||
Repository<VideoTask> videoTaskDB = null, Repository<VideoKonwPoint> videoKonwPointDB = null
|
||||
, Repository<NodePackageInfo> nodePackageInfoDB = null, Repository<VideoQuestion> videoQuestionDB = null, Repository<VideoQuestionKonw> videoQuestionKonwDB = null, Repository<CourseInfo> courseInfoDB = null, RedisManager redisManager = null)
|
||||
, Repository<NodePackageInfo> nodePackageInfoDB = null, Repository<VideoQuestion> videoQuestionDB = null, Repository<VideoQuestionKonw> videoQuestionKonwDB = null, Repository<CourseInfo> courseInfoDB = null, RedisManager redisManager = null, Repository<VideoTaskStage> videoTaskStageDB = null)
|
||||
{
|
||||
this.mp = mp;
|
||||
this.nodesubscriptionDB = nodesubscriptionDB;
|
||||
|
|
@ -53,6 +54,7 @@ namespace VideoAnalysisCore.Controllers
|
|||
this.videoQuestionKonwDB = videoQuestionKonwDB;
|
||||
this.courseInfoDB = courseInfoDB;
|
||||
this.redisManager = redisManager;
|
||||
this.videoTaskStageDB = videoTaskStageDB;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -201,27 +203,49 @@ namespace VideoAnalysisCore.Controllers
|
|||
.ToArrayAsync();
|
||||
if (konwArr is null || konwArr.Length == 0)
|
||||
return BadRequest("ÎÞÓÐЧÈÎÎñ·Ö¶Î");
|
||||
|
||||
|
||||
var stageArr = await videoTaskStageDB.AsQueryable()
|
||||
.Where(s => s.VideoTaskId == task.Id)
|
||||
.ToArrayAsync();
|
||||
var videoKnowDic = konwArr
|
||||
.GroupBy(s => s.StageId)
|
||||
.ToDictionary(s => s.Key);
|
||||
var videoKnows = stageArr
|
||||
.Select(s => new VideoKnowRes()
|
||||
{
|
||||
Content = s.Content,
|
||||
StartTime = s.StartTime,
|
||||
EndTime = s.EndTime,
|
||||
Theme = s.Theme,
|
||||
StageId = s.Id,
|
||||
KnowPoint = videoKnowDic.ContainsKey(s.Id)
|
||||
? string.Join(',', videoKnowDic[s.Id].Select(x => x.KnowPoint))
|
||||
: string.Empty
|
||||
}).ToArray();
|
||||
|
||||
var res = new TaskKnowRes()
|
||||
{
|
||||
TagId = task.TagId,
|
||||
Status = task.LastEnum,
|
||||
VideoTaskId = task.Id,
|
||||
KnowBlockArr = konwArr
|
||||
.GroupBy(s => s.StartTime)
|
||||
KnowBlockArr = stageArr
|
||||
.Select(s => new TaskKnowBlock()
|
||||
{
|
||||
Id = s.First().Id,
|
||||
Content = s.First().Content,
|
||||
StartTime = s.First().StartTime,
|
||||
StageId = s.First().StageId,
|
||||
EndTime = s.First().EndTime,
|
||||
Theme = s.First().Theme,
|
||||
Know = s.Select(x => new TaskKnowInfo()
|
||||
Id = s.Id,
|
||||
Content = s.Content,
|
||||
StartTime = s.StartTime,
|
||||
StageId = s.Id,
|
||||
EndTime = s.EndTime,
|
||||
Theme = s.Theme,
|
||||
Know = videoKnowDic.ContainsKey(s.Id)
|
||||
? videoKnowDic[s.Id]?.Select(x => new TaskKnowInfo()
|
||||
{
|
||||
Id = x.Id,
|
||||
KnowPoint = x.KnowPoint,
|
||||
KnowPointId = x.KnowPointId
|
||||
}).ToArray()
|
||||
KnowPointId = x.KnowPointId,
|
||||
})?.ToArray()
|
||||
: null
|
||||
}).ToArray()
|
||||
};
|
||||
if (task.VideoType == AttachmentsInfoType.¸´Ï°)
|
||||
|
|
|
|||
|
|
@ -33,9 +33,11 @@ namespace VideoAnalysisCore.Controllers
|
|||
readonly Repository<VideoTask> baseService;
|
||||
readonly Repository<VideoQuestion> videoQuestionDB;
|
||||
readonly Repository<VideoKonwPoint> videoKonwPointDB;
|
||||
readonly Repository<VideoTaskStage> videoTaskStageDB;
|
||||
readonly Repository<VideoQuestionKonw> videoQuestionKonwDB;
|
||||
readonly Repository<TaskLog> taskLogDB;
|
||||
|
||||
|
||||
readonly RedisManager redisManager;
|
||||
public readonly SenseVoice senseVoice;
|
||||
public readonly FunASRNano funASRNano;
|
||||
|
|
@ -43,7 +45,7 @@ namespace VideoAnalysisCore.Controllers
|
|||
private readonly IMapper mp;
|
||||
public VideoTaskController(Repository<VideoTask> baseService, RedisManager redisManager,
|
||||
Repository<VideoQuestion> videoQuestionDB,
|
||||
Repository<VideoQuestionKonw> videoQuestionKonwDB, Repository<VideoKonwPoint> videoKonwPointDB, SenseVoice senseVoice, IMapper mp, Repository<TaskLog> taskLogDB, FunASRNano funASRNano) : base(baseService)
|
||||
Repository<VideoQuestionKonw> videoQuestionKonwDB, Repository<VideoKonwPoint> videoKonwPointDB, SenseVoice senseVoice, IMapper mp, Repository<TaskLog> taskLogDB, FunASRNano funASRNano, Repository<VideoTaskStage> videoTaskStageDB) : base(baseService)
|
||||
{
|
||||
this.baseService = baseService;
|
||||
this.redisManager = redisManager;
|
||||
|
|
@ -54,6 +56,7 @@ namespace VideoAnalysisCore.Controllers
|
|||
this.mp = mp;
|
||||
this.taskLogDB = taskLogDB;
|
||||
this.funASRNano = funASRNano;
|
||||
this.videoTaskStageDB = videoTaskStageDB;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -370,17 +373,23 @@ namespace VideoAnalysisCore.Controllers
|
|||
var konwArr = await videoKonwPointDB.AsQueryable()
|
||||
.Where(s => s.VideoTaskId == nowTask.Id)
|
||||
.ToArrayAsync();
|
||||
|
||||
var videoKnows = konwArr
|
||||
.GroupBy(s => s.StartTime)
|
||||
var stageArr = await videoTaskStageDB.AsQueryable()
|
||||
.Where(s => s.VideoTaskId == nowTask.Id)
|
||||
.ToArrayAsync();
|
||||
var videoKnowDic = konwArr
|
||||
.GroupBy(s => s.StageId)
|
||||
.ToDictionary(s => s.Key);
|
||||
var videoKnows = stageArr
|
||||
.Select(s => new VideoKnowRes()
|
||||
{
|
||||
Content = s.First().Content,
|
||||
StartTime = s.First().StartTime,
|
||||
EndTime = s.First().EndTime,
|
||||
Theme = s.First().Theme,
|
||||
StageId = s.First().StageId,
|
||||
KnowPoint = string.Join(',', s.Select(x => x.KnowPoint))
|
||||
Content = s.Content,
|
||||
StartTime = s.StartTime,
|
||||
EndTime = s.EndTime,
|
||||
Theme = s.Theme,
|
||||
StageId = s.Id,
|
||||
KnowPoint = videoKnowDic.ContainsKey(s.Id)
|
||||
? string.Join(',', videoKnowDic[s.Id].Select(x => x.KnowPoint))
|
||||
: string.Empty
|
||||
}).ToArray();
|
||||
if (nowTask.VideoType == AttachmentsInfoType.复习)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -65,9 +65,13 @@ namespace VideoAnalysisCore.Model
|
|||
/// </summary>
|
||||
public string? KnowPointId { get; set; }
|
||||
/// <summary>
|
||||
/// 知识点来源 视频秒
|
||||
/// 知识点占比权重
|
||||
/// </summary>
|
||||
public float KnowSourceTime { get; set; }
|
||||
public float? KnowPointWeight { get; set; }
|
||||
/// <summary>
|
||||
/// 知识点来源
|
||||
/// </summary>
|
||||
public string KnowSource { get; set; }
|
||||
/// <summary>
|
||||
/// 内容总结[不写入数据库]
|
||||
/// </summary>
|
||||
|
|
@ -84,5 +88,11 @@ namespace VideoAnalysisCore.Model
|
|||
/// </summary>
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public long? CloudSchoolId { get; set; }
|
||||
/// <summary>
|
||||
/// 教材来源
|
||||
/// <para> 课本/试卷/挹青苑 ...</para>
|
||||
/// </summary>
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
public virtual string? TextbookSource { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@ namespace VideoAnalysisCore.Model
|
|||
/// </summary>
|
||||
public string? Theme { get; set; }
|
||||
/// <summary>
|
||||
/// 知识点来源 视频秒
|
||||
/// 知识点来源 视频秒,来源原因
|
||||
/// </summary>
|
||||
public float KnowSourceTime { get; set; }
|
||||
public string Content { get; set; }
|
||||
/// <summary>
|
||||
/// 课程阶段
|
||||
/// </summary>
|
||||
|
|
@ -68,5 +68,11 @@ namespace VideoAnalysisCore.Model
|
|||
/// </summary>
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public long? CloudSchoolId { get; set; }
|
||||
/// <summary>
|
||||
/// 教材来源
|
||||
/// <para> 课本/试卷/挹青苑 ...</para>
|
||||
/// </summary>
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public virtual string? TextbookSource { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue