优化 调试工作流1的AI分析流程(知识点权重,来源,AI复查复检...)

This commit is contained in:
小肥羊 2026-01-19 18:17:58 +08:00
parent b4b02cfbd3
commit a2d14487cb
10 changed files with 168 additions and 86 deletions

View File

@ -42,7 +42,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
/// <param name="max_tokens">最大token <para>不设置默认最大值 16000/8000</para></param> /// <param name="max_tokens">最大token <para>不设置默认最大值 16000/8000</para></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="Exception"></exception> /// <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 = [ Message[] messageArr = [
new Message(postMessages,"user"), new Message(postMessages,"user"),
@ -53,7 +53,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
taskId = task, taskId = task,
title = title, title = title,
model = model ?? ChatGPTType.Deepseek_Reasoner, 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, stream = true,
temperature = 0.2f, temperature = 0.2f,
messages = messageArr messages = messageArr

View File

@ -34,9 +34,10 @@ namespace VideoAnalysisCore.AICore.GPT.Dto
} }
public class VideoKnowPointDto public class VideoKnowPointDto
{ {
public float KnowPointWeight { get; set; }
public string KnowPoint { get; set; } public string KnowPoint { get; set; }
public string KnowPointId { get; set; } public string KnowPointId { get; set; }
public float KnowSourceTime { get; set; } public string KnowSource { get; set; }
} }
public class VideoKnowRes public class VideoKnowRes
{ {
@ -64,6 +65,10 @@ namespace VideoAnalysisCore.AICore.GPT.Dto
/// </summary> /// </summary>
public virtual string? KnowPoint { get; set; } public virtual string? KnowPoint { get; set; }
/// <summary> /// <summary>
/// 知识点权重
/// </summary>
public virtual float? KnowPointWeight { get; set; }
/// <summary>
/// 知识点ID /// 知识点ID
/// </summary> /// </summary>
public virtual string? KnowPointId { get; set; } public virtual string? KnowPointId { get; set; }

View File

@ -13,6 +13,8 @@ using System.IO;
using VideoAnalysisCore.AICore.GPT.ChatGPT; using VideoAnalysisCore.AICore.GPT.ChatGPT;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Text.Json; using System.Text.Json;
using FFmpeg.NET.Services;
using NetTaste;
namespace VideoAnalysisCore.AICore.GPT namespace VideoAnalysisCore.AICore.GPT
{ {
@ -76,7 +78,7 @@ namespace VideoAnalysisCore.AICore.GPT
{ {
throw new Exception("请求GPT服务器失败次数过多"); throw new Exception("请求GPT服务器失败次数过多");
} }
goto PostJsonStream; goto PostJsonStream;
} }
using var stream = chatResp.Content.ReadAsStream(); using var stream = chatResp.Content.ReadAsStream();
using var reader = new StreamReader(stream, Encoding.UTF8); using var reader = new StreamReader(stream, Encoding.UTF8);
@ -87,7 +89,7 @@ namespace VideoAnalysisCore.AICore.GPT
var splitCount = "data:".Length; var splitCount = "data:".Length;
var maxLoop = 50 * 200; var maxLoop = 50 * 200;
int threshold = 0; int threshold = 0;
var startTime= DateTime.Now; var startTime = DateTime.Now;
var endTime = startTime.AddHours(1.5); var endTime = startTime.AddHours(1.5);
//最长分析分析时间1.5小时 或者重试读取 1w次 //最长分析分析时间1.5小时 或者重试读取 1w次
while (maxLoop > 0 && DateTime.Now < endTime) while (maxLoop > 0 && DateTime.Now < endTime)
@ -156,7 +158,7 @@ namespace VideoAnalysisCore.AICore.GPT
/// <param name="max_tokens">最大token <para>不设置默认最大值 16000/8000</para></param> /// <param name="max_tokens">最大token <para>不设置默认最大值 16000/8000</para></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="Exception"></exception> /// <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; var tryCount = 10;
while (tryCount-- > 0) while (tryCount-- > 0)
@ -180,14 +182,20 @@ namespace VideoAnalysisCore.AICore.GPT
chatResContent = chatResContent?.Replace("```", ""); chatResContent = chatResContent?.Replace("```", "");
chatResContent = chatResContent?.Replace("}{", "},{"); chatResContent = chatResContent?.Replace("}{", "},{");
chatResContent = chatResContent?.Replace("}|{", "},{"); chatResContent = chatResContent?.Replace("}|{", "},{");
chatResContent = chatResContent?.Trim(); chatResContent = chatResContent?.Trim();
chatResContent = chatResContent?.ExtractJsonStrings()?.FirstOrDefault(); chatResContent = chatResContent?.ExtractJsonStrings()?.FirstOrDefault();
if (string.IsNullOrEmpty(chatResContent)) if (string.IsNullOrEmpty(chatResContent))
throw new Exception($"GPT返回结果无有效JSON =>{chatResp?.res}"); throw new Exception($"GPT返回结果无有效JSON =>{chatResp?.res}");
var startsStr = typeof(T).IsArray ? "[" : "{"; var startsStr = "{";
var endStr = typeof(T).IsArray ? "]" : "}"; 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)) if (!chatResContent.StartsWith(startsStr))
chatResContent = startsStr + chatResContent; chatResContent = startsStr + chatResContent;
if (!chatResContent.EndsWith(endStr)) if (!chatResContent.EndsWith(endStr))
@ -271,7 +279,7 @@ namespace VideoAnalysisCore.AICore.GPT
/// <returns></returns> /// <returns></returns>
/// <exception cref="Exception"></exception> /// <exception cref="Exception"></exception>
public virtual Task<T> ChatAsync<T>(string task, string postMessages, string title, 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("需要实现"); throw new Exception("需要实现");
} }

View File

@ -22,6 +22,7 @@ using System.Collections.Generic;
using UserCenter.Model.Enum; using UserCenter.Model.Enum;
using Dm.filter; using Dm.filter;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Diagnostics;
namespace VideoAnalysisCore.AICore.GPT.DeepSeek namespace VideoAnalysisCore.AICore.GPT.DeepSeek
{ {
@ -81,28 +82,37 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
questionRes = questionRes.Where(s => s != null) questionRes = questionRes.Where(s => s != null)
.OrderBy(s => s.StartTime).ToList(); .OrderBy(s => s.StartTime).ToList();
var thems = questionRes.Adapt<VideoKnowQueryDto[]>().ToJson(); 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 = var knowMessages =
$"我针对{taskInfo.Subject}课堂授课视频分析出了视频的授课阶段片段。\n" + $"""
$"现在需要你通过每个片段的内容总结来分配正确的知识点(单个片段允许多个知识点)。\n" + {taskInfo.Subject}
$"KnowSourceTime字段 需要提供出知识点被匹配的字幕内容最开始的时间来源。\n" +
$"TextbookSource字段 需要你分析出单个片段内讲述内容所属的教材范围 例如 (范围限定在 课本/试卷/挹青苑/其他)。\n" +
$"这是我的分段 {thems}。\n" + - TextbookSource///
$"课堂内容与{sections}章节相关\n" + - KnowPoints
$"最后请确保分配的知识点是用户提供的,并且一定正确合理!\n" + - KnowPoint
$"返回的片段数量与传入片段数量一致!(硬性条件)\n" + - KnowPointIdID KnowPoint
$"输出内容只返回json格式({checkResFormat1})\n" + - KnowPointWeight(1,1)
$" 格式 (方法点Id|方法点名称) \n" + - KnowSource,(50)
$"提供的`知识点名称({knows})。\n";
1) //
2) StartTime StartTime
3) KnowPoints
4) JSON Markdown//
{thems}
{sections}
Id|Name{knows}
{checkResFormat1}
""";
await redisManager.AddTaskLog(taskInfo.Id, "==>2.开始分析视频内容知识点"); await redisManager.AddTaskLog(taskInfo.Id, "==>2.开始分析视频内容知识点");
VideoKnowRes[] konwRes; List<VideoKnowRes> konwRes;
var knowOK = false; var knowOK = false;
var chatClentArr = new GPTClient[] { chatGPTClient, geminiClient, deepSeekClient }; var chatClentArr = new GPTClient[] { chatGPTClient, geminiClient, deepSeekClient };
for (int i = 0; i < 3; i++) 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++) for (int xi = 0; xi < konwRes.Count(); xi++)
{ {
questionRes[xi].KnowPoints = konwRes[xi].KnowPoints; questionRes[xi].KnowPoints = konwRes[xi].KnowPoints;
@ -132,7 +142,9 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
EndTime = s.EndTime, EndTime = s.EndTime,
StageId = StageId, StageId = StageId,
KnowPoint = x.KnowPoint, KnowPoint = x.KnowPoint,
KnowSourceTime = x.KnowSourceTime, KnowPointWeight=x.KnowPointWeight,
TextbookSource = s.TextbookSource,
KnowSource = x.KnowSource,
KnowPointId = knowDic[x.KnowPoint].ToString(), KnowPointId = knowDic[x.KnowPoint].ToString(),
TagId = taskInfo.TagId, TagId = taskInfo.TagId,
VideoTaskId = taskInfo.Id, VideoTaskId = taskInfo.Id,
@ -197,7 +209,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
var pptFormat = taskInfo.VideoType == AttachmentsInfoType. var pptFormat = taskInfo.VideoType == AttachmentsInfoType.
? "这堂课是习题课,所讲解内容几乎都是试题。" ? "这堂课是习题课,所讲解内容几乎都是试题。"
: string.Empty; : string.Empty;
var checkResFormat = """{"Score":85.5,"MinusScore":"","Suggestion":""}"""; var checkResFormat = """{"Score":65.5,"MinusScore":"","Suggestion":""}""";
var checkMessage = var checkMessage =
$""" $"""
@ -209,8 +221,9 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
Conten有关联() Conten有关联()
0-10070 0-10070,,
MinusScore:
Suggestion: ()
{thems} {thems}
:::|{captions.Captions} :::|{captions.Captions}
@ -257,8 +270,8 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
JSON{resFormat} JSON{resFormat}
"""; """;
var improved = await geminiClient.ChatAsync<VideoKnowRes[]>(taskInfo.Id.ToString(), message, "分段优化"); var improved = await geminiClient.ChatAsync<List<VideoKnowRes>>(taskInfo.Id.ToString(), message, "分段优化");
if (improved is null || improved.Length != questionRes.Count()) if (improved is null || improved.Count() != questionRes.Count())
return null; return null;
return improved.OrderBy(s => s.StartTime ?? 0).ToList(); return improved.OrderBy(s => s.StartTime ?? 0).ToList();
@ -271,7 +284,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
private async Task<SenseVoiceRes[]> OptimizeSubtitles(VideoTask taskInfo, private async Task<SenseVoiceRes[]> OptimizeSubtitles(VideoTask taskInfo,
SenseVoiceRes[] captionsArr, string sections) SenseVoiceRes[] captionsArr, string sections)
{ {
if (!string.IsNullOrEmpty(taskInfo.CaptionsAI)) if (!string.IsNullOrEmpty(taskInfo.CaptionsAI) && taskInfo.CaptionsAI!="[]")
return JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.CaptionsAI); return JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.CaptionsAI);
var subject = taskInfo.Subject.ToString(); var subject = taskInfo.Subject.ToString();
var newCaptionsList = new List<SenseVoiceRes>(captionsArr.Length); var newCaptionsList = new List<SenseVoiceRes>(captionsArr.Length);
@ -306,10 +319,10 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
$"待优化字幕内容:\n" + $"待优化字幕内容:\n" +
$"{nowCaptionStr}\n" + $"{nowCaptionStr}\n" +
$"最终核对:请确保输出 JSON 中包含的字幕条数与输入的字幕条数完全对应。"; $"最终核对:请确保输出 JSON 中包含的字幕条数与输入的字幕条数完全对应。";
string[]? resData = null; List<string>? resData = null;
for (int i = 0; i < 3; i++) 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()) if (resData.Count() == cArr.Count())
break; break;
else else
@ -318,7 +331,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
if (resData.Count() != cArr.Count()) if (resData.Count() != cArr.Count())
{ {
resData = cStrArr.ToArray(); resData = cStrArr.ToList();
await redisManager.AddTaskLog(taskInfo.Id, $"==>字幕优化 分段{s} AI结果数量不匹配 采用原始值"); await redisManager.AddTaskLog(taskInfo.Id, $"==>字幕优化 分段{s} AI结果数量不匹配 采用原始值");
} }
newCaptionsList.AddRange(resData.Select((text, i) => new SenseVoiceRes() newCaptionsList.AddRange(resData.Select((text, i) => new SenseVoiceRes()
@ -366,13 +379,12 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
$"完整的课堂标准流程包含以下5个阶段课程引入/新知讲解/例题精讲/课堂练习/知识总结。\n" + $"完整的课堂标准流程包含以下5个阶段课程引入/新知讲解/例题精讲/课堂练习/知识总结。\n" +
reviewStr + reviewStr +
$"讲解知识内容的阶段的细分程度到某个知识点的讲解/认识/例题/总结\n" + $"讲解知识内容的阶段的细分程度到某个知识点的讲解/认识/例题/总结\n" +
$"不分析课堂作业相关的内容我已经预处理了\n" +
$"初步划分阶段:{keyFrameStr}\n" + $"初步划分阶段:{keyFrameStr}\n" +
$"\n" + $"Stage判断阶段类型如果内容以解题为主归类为“例题精讲”如果涉及新知识讲解归类为“新知讲解”以此类推。\n" +
$"内容分析:对每个时间段,提取主要讲解内容:识别关键词(如“例题”“证明”“练习”“总结”)和内容结构。\n" + $"Content简述单个阶段的核心讲解内容40~150字如“例题”“证明”“练习”“总结”..., 必须完全基于字幕文本可推断的信息,禁止捏造不存在的内容(硬性条件)。\n" +
$"判断阶段类型:如果内容以解题为主,归类为“例题精讲”;如果涉及新知识讲解,归类为“新知讲解”;以此类推。\n" + $"Theme理解Content提炼一个精确的主题例如“柯西不等式的基本应用”。\n" +
$"内容总结简述该阶段的核心讲解内容40~150字, 必须完全基于字幕文本可推断的信息,禁止捏造不存在的内容(硬性条件)。\n" + $"输出要求:确保阶段划分合理、无重叠、\n" +
$"阶段主题:基于内容总结,提炼一个恰当的主题(例如,“柯西不等式的基本应用”)。\n" +
$"输出要求:确保阶段划分合理、无重叠\n" +
$"作业布置阶段一般出现在末尾如果有" + $"作业布置阶段一般出现在末尾如果有" +
$"输出格式要求内容只返回json格式({resFormat})\n" + $"输出格式要求内容只返回json格式({resFormat})\n" +
$"字幕格式(开始秒:内容|下一段字幕).以下是包含时间的视频字幕文本。\n" + $"字幕格式(开始秒:内容|下一段字幕).以下是包含时间的视频字幕文本。\n" +
@ -424,7 +436,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
JSON{resFormat} 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) if (res is null)
return null; return null;
if (!string.Equals(res.Stage, "作业布置", StringComparison.OrdinalIgnoreCase)) if (!string.Equals(res.Stage, "作业布置", StringComparison.OrdinalIgnoreCase))
@ -575,7 +587,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
$"输出内容只返回json格式为({resFormat})" + $"输出内容只返回json格式为({resFormat})" +
$"以下是试题内容" + $"以下是试题内容" +
$"`{sRes.Result.res.value}`"; $"`{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, "提取试题"); //var resData = await chatClient.ChatAsync<VideoQuestionOSSDto[]>(taskInfo.Id.ToString(), postMessages, "提取试题");
if (resData is null || resData.Count() == 0) if (resData is null || resData.Count() == 0)
break; break;
@ -704,8 +716,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
if (questionRes is null) continue; if (questionRes is null) continue;
//处理分段 知识点 //处理分段 知识点
List<VideoKonwPoint> insertData = await GetVideoKnow(questionRes, taskInfo, sections, knowledgeInfos); 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); var checkRes = await VerifySpanQuality(questionRes, taskInfo, captions, sections, Course_Id);
@ -715,35 +726,44 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
// 质量复检 // 质量复检
if (checkRes != null) 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) if (improved != null)
{ {
var improvedCheck = await VerifySpanQuality(improved, taskInfo, captions, sections, Course_Id); var improvedCheck = await VerifySpanQuality(improved, taskInfo, captions, sections, Course_Id);
await redisManager.AddTaskLog(taskInfo.Id, $"==>优化后复检得分=>{improvedCheck.Score}"); await redisManager.AddTaskLog(taskInfo.Id, $"==>优化后复检得分=>{improvedCheck.Score}");
await redisManager.AddTaskLog(taskInfo.Id, $"==>优化后扣分原因 {improvedCheck.MinusScore}"); 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; questionRes = improved;
if (homework != null && (!questionRes.Any(s => s.Stage == StageEnum..ToString())))
questionRes.Add(homework);
insertData = await GetVideoKnow(questionRes, taskInfo, sections, knowledgeInfos); insertData = await GetVideoKnow(questionRes, taskInfo, sections, knowledgeInfos);
await videoKonwPointDB.DeleteAsync(s => s.VideoTaskId == taskInfo.Id); await videoKonwPointDB.DeleteAsync(s => s.VideoTaskId == taskInfo.Id);
await videoTaskStageDB.DeleteAsync(s => s.VideoTaskId == taskInfo.Id); await videoTaskStageDB.DeleteAsync(s => s.VideoTaskId == taskInfo.Id);
var tStage = insertData.GroupBy(s => s.StageId).Select(s => new VideoTaskStage var tStage = insertData.GroupBy(s => s.StageId).Select(s => new VideoTaskStage
{ {
Id=s.Key, Id = s.Key,
TagId = s.First().TagId, TagId = s.First().TagId,
CloudSchoolId =s.First().CloudSchoolId, CloudSchoolId = s.First().CloudSchoolId,
StartTime = s.Last().StartTime, StartTime = s.First().StartTime,
EndTime =s.Last().EndTime, EndTime = s.First().EndTime,
KnowSourceTime=s.Last().KnowSourceTime, Content = s.First().Content,
Stage=s.First().Stage, TextbookSource = s.First().TextbookSource,
Theme=s.First().Theme, Stage = s.First().Stage,
VideoTaskId=taskInfo.Id, Theme = s.First().Theme,
VideoTaskId = taskInfo.Id,
}).ToArray(); }).ToArray();
await videoTaskStageDB.InsertRangeAsync(tStage); await videoTaskStageDB.InsertRangeAsync(tStage);
await videoKonwPointDB.InsertRangeAsync(insertData); await videoKonwPointDB.InsertRangeAsync(insertData);
break; break;
} }
else
{
await redisManager.AddTaskLog(taskInfo.Id, $"==>优化之后的得分降低/得分过低");
continue;
}
} }
} }

View File

@ -58,7 +58,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
stream = true, stream = true,
temperature = 0.2f, temperature = 0.2f,
messages = messageArr, messages = messageArr,
max_completion_tokens=16000, max_completion_tokens= 12288,
}; };
chatReq.modalities = null; chatReq.modalities = null;

View File

@ -143,7 +143,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
throw new Exception("task 音频路径未找到"); throw new Exception("task 音频路径未找到");
if (OR is null) Init(); if (OR is null) Init();
serviceProvider.GetRequiredService<SherpaVad>() 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; return Task.CompletedTask;
} }

View File

@ -35,6 +35,7 @@ namespace VideoAnalysisCore.Controllers
private readonly Repository<VideoTask> videoTaskDB; private readonly Repository<VideoTask> videoTaskDB;
private readonly Repository<CourseInfo> courseInfoDB; private readonly Repository<CourseInfo> courseInfoDB;
private readonly Repository<VideoKonwPoint> videoKonwPointDB; private readonly Repository<VideoKonwPoint> videoKonwPointDB;
private readonly Repository<VideoTaskStage> videoTaskStageDB;
private readonly Repository<NodePackageInfo> nodePackageInfoDB; private readonly Repository<NodePackageInfo> nodePackageInfoDB;
private readonly Repository<VideoQuestion> videoQuestionDB; private readonly Repository<VideoQuestion> videoQuestionDB;
private readonly Repository<VideoQuestionKonw> videoQuestionKonwDB; private readonly Repository<VideoQuestionKonw> videoQuestionKonwDB;
@ -42,7 +43,7 @@ namespace VideoAnalysisCore.Controllers
public LJZK_Controller(IMapper mp, Repository<NodeSubscription> nodesubscriptionDB, public LJZK_Controller(IMapper mp, Repository<NodeSubscription> nodesubscriptionDB,
Repository<VideoTask> videoTaskDB = null, Repository<VideoKonwPoint> videoKonwPointDB = null 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.mp = mp;
this.nodesubscriptionDB = nodesubscriptionDB; this.nodesubscriptionDB = nodesubscriptionDB;
@ -53,6 +54,7 @@ namespace VideoAnalysisCore.Controllers
this.videoQuestionKonwDB = videoQuestionKonwDB; this.videoQuestionKonwDB = videoQuestionKonwDB;
this.courseInfoDB = courseInfoDB; this.courseInfoDB = courseInfoDB;
this.redisManager = redisManager; this.redisManager = redisManager;
this.videoTaskStageDB = videoTaskStageDB;
} }
@ -201,27 +203,49 @@ namespace VideoAnalysisCore.Controllers
.ToArrayAsync(); .ToArrayAsync();
if (konwArr is null || konwArr.Length == 0) if (konwArr is null || konwArr.Length == 0)
return BadRequest("ÎÞÓÐЧÈÎÎñ·Ö¶Î"); 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() var res = new TaskKnowRes()
{ {
TagId = task.TagId, TagId = task.TagId,
Status = task.LastEnum, Status = task.LastEnum,
VideoTaskId = task.Id, VideoTaskId = task.Id,
KnowBlockArr = konwArr KnowBlockArr = stageArr
.GroupBy(s => s.StartTime)
.Select(s => new TaskKnowBlock() .Select(s => new TaskKnowBlock()
{ {
Id = s.First().Id, Id = s.Id,
Content = s.First().Content, Content = s.Content,
StartTime = s.First().StartTime, StartTime = s.StartTime,
StageId = s.First().StageId, StageId = s.Id,
EndTime = s.First().EndTime, EndTime = s.EndTime,
Theme = s.First().Theme, Theme = s.Theme,
Know = s.Select(x => new TaskKnowInfo() Know = videoKnowDic.ContainsKey(s.Id)
{ ? videoKnowDic[s.Id]?.Select(x => new TaskKnowInfo()
Id = x.Id, {
KnowPoint = x.KnowPoint, Id = x.Id,
KnowPointId = x.KnowPointId KnowPoint = x.KnowPoint,
}).ToArray() KnowPointId = x.KnowPointId,
})?.ToArray()
: null
}).ToArray() }).ToArray()
}; };
if (task.VideoType == AttachmentsInfoType.¸´Ï°) if (task.VideoType == AttachmentsInfoType.¸´Ï°)

View File

@ -33,9 +33,11 @@ namespace VideoAnalysisCore.Controllers
readonly Repository<VideoTask> baseService; readonly Repository<VideoTask> baseService;
readonly Repository<VideoQuestion> videoQuestionDB; readonly Repository<VideoQuestion> videoQuestionDB;
readonly Repository<VideoKonwPoint> videoKonwPointDB; readonly Repository<VideoKonwPoint> videoKonwPointDB;
readonly Repository<VideoTaskStage> videoTaskStageDB;
readonly Repository<VideoQuestionKonw> videoQuestionKonwDB; readonly Repository<VideoQuestionKonw> videoQuestionKonwDB;
readonly Repository<TaskLog> taskLogDB; readonly Repository<TaskLog> taskLogDB;
readonly RedisManager redisManager; readonly RedisManager redisManager;
public readonly SenseVoice senseVoice; public readonly SenseVoice senseVoice;
public readonly FunASRNano funASRNano; public readonly FunASRNano funASRNano;
@ -43,7 +45,7 @@ namespace VideoAnalysisCore.Controllers
private readonly IMapper mp; private readonly IMapper mp;
public VideoTaskController(Repository<VideoTask> baseService, RedisManager redisManager, public VideoTaskController(Repository<VideoTask> baseService, RedisManager redisManager,
Repository<VideoQuestion> videoQuestionDB, 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.baseService = baseService;
this.redisManager = redisManager; this.redisManager = redisManager;
@ -54,6 +56,7 @@ namespace VideoAnalysisCore.Controllers
this.mp = mp; this.mp = mp;
this.taskLogDB = taskLogDB; this.taskLogDB = taskLogDB;
this.funASRNano = funASRNano; this.funASRNano = funASRNano;
this.videoTaskStageDB = videoTaskStageDB;
} }
@ -370,17 +373,23 @@ namespace VideoAnalysisCore.Controllers
var konwArr = await videoKonwPointDB.AsQueryable() var konwArr = await videoKonwPointDB.AsQueryable()
.Where(s => s.VideoTaskId == nowTask.Id) .Where(s => s.VideoTaskId == nowTask.Id)
.ToArrayAsync(); .ToArrayAsync();
var stageArr = await videoTaskStageDB.AsQueryable()
var videoKnows = konwArr .Where(s => s.VideoTaskId == nowTask.Id)
.GroupBy(s => s.StartTime) .ToArrayAsync();
var videoKnowDic = konwArr
.GroupBy(s => s.StageId)
.ToDictionary(s => s.Key);
var videoKnows = stageArr
.Select(s => new VideoKnowRes() .Select(s => new VideoKnowRes()
{ {
Content = s.First().Content, Content = s.Content,
StartTime = s.First().StartTime, StartTime = s.StartTime,
EndTime = s.First().EndTime, EndTime = s.EndTime,
Theme = s.First().Theme, Theme = s.Theme,
StageId = s.First().StageId, StageId = s.Id,
KnowPoint = string.Join(',', s.Select(x => x.KnowPoint)) KnowPoint = videoKnowDic.ContainsKey(s.Id)
? string.Join(',', videoKnowDic[s.Id].Select(x => x.KnowPoint))
: string.Empty
}).ToArray(); }).ToArray();
if (nowTask.VideoType == AttachmentsInfoType.) if (nowTask.VideoType == AttachmentsInfoType.)
{ {

View File

@ -65,9 +65,13 @@ namespace VideoAnalysisCore.Model
/// </summary> /// </summary>
public string? KnowPointId { get; set; } public string? KnowPointId { get; set; }
/// <summary> /// <summary>
/// 知识点来源 视频秒 /// 知识点占比权重
/// </summary> /// </summary>
public float KnowSourceTime { get; set; } public float? KnowPointWeight { get; set; }
/// <summary>
/// 知识点来源
/// </summary>
public string KnowSource { get; set; }
/// <summary> /// <summary>
/// 内容总结[不写入数据库] /// 内容总结[不写入数据库]
/// </summary> /// </summary>
@ -84,5 +88,11 @@ namespace VideoAnalysisCore.Model
/// </summary> /// </summary>
[SugarColumn(IsNullable = true)] [SugarColumn(IsNullable = true)]
public long? CloudSchoolId { get; set; } public long? CloudSchoolId { get; set; }
/// <summary>
/// 教材来源
/// <para> 课本/试卷/挹青苑 ...</para>
/// </summary>
[SugarColumn(IsIgnore = true)]
public virtual string? TextbookSource { get; set; }
} }
} }

View File

@ -54,9 +54,9 @@ namespace VideoAnalysisCore.Model
/// </summary> /// </summary>
public string? Theme { get; set; } public string? Theme { get; set; }
/// <summary> /// <summary>
/// 知识点来源 视频秒 /// 知识点来源 视频秒,来源原因
/// </summary> /// </summary>
public float KnowSourceTime { get; set; } public string Content { get; set; }
/// <summary> /// <summary>
/// 课程阶段 /// 课程阶段
/// </summary> /// </summary>
@ -68,5 +68,11 @@ namespace VideoAnalysisCore.Model
/// </summary> /// </summary>
[SugarColumn(IsNullable = true)] [SugarColumn(IsNullable = true)]
public long? CloudSchoolId { get; set; } public long? CloudSchoolId { get; set; }
/// <summary>
/// 教材来源
/// <para> 课本/试卷/挹青苑 ...</para>
/// </summary>
[SugarColumn(IsNullable = true)]
public virtual string? TextbookSource { get; set; }
} }
} }