新增 AI分析视频课程类型流程

This commit is contained in:
小肥羊 2025-06-30 18:01:49 +08:00
parent d36fb2fc9f
commit 3d112773c9
9 changed files with 131 additions and 7 deletions

View File

@ -22,5 +22,11 @@ namespace VideoAnalysisCore.AICore.GPT
/// <param name="task">任务id</param>
/// <returns></returns>
public Task GetVideoQuestion(string task);
/// <summary>
/// 获取视频类型
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
public Task GetVideoType(string task);
}
}

View File

@ -423,5 +423,10 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
{
throw new NotImplementedException();
}
Task IBserGPT.GetVideoType(string task)
{
throw new NotImplementedException();
}
}
}

View File

@ -20,6 +20,7 @@ using Aliyun.OSS;
using Yitter.IdGenerator;
using VideoAnalysisCore.Common.Expand;
using System.Collections.Generic;
using UserCenter.Model.Enum;
namespace VideoAnalysisCore.AICore.GPT.DeepSeek
{
@ -346,7 +347,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
if (max_tokens != -1)
chatRep.max_tokens = max_tokens;
var tryCount = 10;
while (--tryCount > 0)
while (tryCount-- > 0)
{
try
{
@ -392,8 +393,8 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
}
catch (Exception ex)
{
Console.WriteLine(DateTime.Now + $"=>ChatGPT结果解析错误 重试剩余{tryCount}");
Console.WriteLine(ex.Message);
Console.WriteLine(DateTime.Now + $"=>ChatGPT结果解析错误 重试剩余{tryCount}");
}
}
throw new Exception(DateTime.Now + "=>ChatGPT请求失败次数过多!!!");
@ -616,7 +617,6 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
var subject = taskInfo.Subject.ToString();
var Course_Id = taskInfo.CourseId;
var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.Captions);
//处理视频授课章节
var sections = await GetSections(taskInfo, Course_Id);
var know = await knowledgeInfoDB.GetFirstAsync(s => s.Course_Id == Course_Id && s.Name == sections);
@ -630,5 +630,51 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
return;
}
/// <summary>
/// 分析视频是否为复习课
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
public async Task GetVideoType(string task)
{
var taskId = long.Parse(task);
var taskInfo = await videoTaskDB.AsQueryable()
.Where(s => s.Id == taskId)
.FirstAsync();
var subject = taskInfo.Subject.ToString();
var Course_Id = taskInfo.CourseId;
var videoTypeStr = string.Join(',', Enum.GetNames(typeof(AttachmentsInfoType)));
//处理视频授课章节
var sections = await GetSections(taskInfo, Course_Id);
var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.Captions);
captionsArr = await OptimizeSubtitles(taskInfo, captionsArr, sections);
//合并字幕
var captions = ExpandFunction.GetSpeakerCaptions(captionsArr);
var resFormat = """{ "VideoType":string(课程类型),"Reason":string(分析原因)}""";
var postMessages =
$"我将提供一段视频的字幕内容,请你帮我分析这堂课的课程类型是什么。" +
$"授课类型限定在我提供的范围内 [{videoTypeStr}]" +
$"其中如果是[复习/习题课/试题讲解课程]那么课程类型视为'复习'" +
$"请简介的说明分析出课程类型的原因,如果分析出的课程类型与限定条件不匹配则返回NULL" +
$"输出内容只返回json格式为({resFormat})" +
$"以下是字幕内容" +
$"`{captions.Captions}`";
var resData = await ChatAsync<AIVideoTypeDto?>(taskInfo.Id.ToString(), postMessages, "视频类型", "deepseek-chat");
var res = resData.VideoType.ToEnum<AttachmentsInfoType>();
if (res != null)
{
await videoTaskDB.AsUpdateable()
.SetColumns(it => it.VideoType == res)
.Where(it => it.Id == taskInfo.Id)
.ExecuteCommandAsync();
}
}
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VideoAnalysisCore.Model.Enum;
namespace VideoAnalysisCore.AICore.GPT.Dto
{
public class AIVideoTypeDto
{
public string? VideoType { get; set; }
/// <summary>
/// 分析结果原因
/// </summary>
public string Reason { get; set; }
}
}

View File

@ -249,6 +249,16 @@ namespace VideoAnalysisCore.Common
async (msg) => await TouchChannel(RedisChannelEnum., msg, SenseVoice.RunTask));
//SubscribeList.Add(RedisChannelEnum.解析说话人,
// async (msg) => await TouchChannel(RedisChannelEnum.解析说话人, msg, Speaker.Run));
SubscribeList.Add(RedisChannelEnum.AI课程类型,
async (msg) => await TouchChannel(RedisChannelEnum.AI课程类型, msg,
(task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetVideoType(task) ?? Task.CompletedTask;
}));
SubscribeList.Add(RedisChannelEnum.AI模型分析,
async (msg) => await TouchChannel(RedisChannelEnum.AI模型分析, msg,
(task) =>

View File

@ -16,6 +16,8 @@ using Microsoft.AspNetCore.Http;
using VideoAnalysisCore.Model.Dto;
using VideoAnalysisCore.Controllers.Dto;
using VideoAnalysisCore.Common.Expand;
using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
namespace VideoAnalysisCore.Controllers
{
@ -68,6 +70,22 @@ namespace VideoAnalysisCore.Controllers
#endif
/// <summary>
/// 初始化主库表
/// </summary>
/// <param name="url">文件流</param>
/// <returns></returns>
[HttpGet(Name = "tets1")]
public IActionResult tets1(string task)
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
scope.ServiceProvider.GetService<IBserGPT>()?.GetVideoType(task);
return Ok();
}
/// <summary>
/// ÓïÒôʶ±ð
/// </summary>

View File

@ -47,10 +47,19 @@ namespace VideoAnalysisCore.Job
var taskArr = await nodePackageInfoDB.AsQueryable()
.Where(s => s.SuccessTime == null)
.ToArrayAsync();
var videoIdArr = await videoTaskDB.AsQueryable()
var videoArr = await videoTaskDB.AsQueryable()
.Where(s => s.EndTime != null)
.Select(s => s.TagId)
.Select(s =>new VideoTask {
Id = s.Id,
TagId = s.TagId,
VideoType=s.VideoType
})
.ToArrayAsync();
var videoDic = videoArr
.Where(s=>s.TagId != null)
.GroupBy(s => s.TagId!)
.ToDictionary(s => s.Key,s=>s.First());
var videoIdArr = videoArr.Select(s => s.TagId).ToArray();
var videoPPTArr = await videoTaskDB.AsQueryable()
.Where(s => s.EndTime != null)
@ -59,8 +68,15 @@ namespace VideoAnalysisCore.Job
var postData = new List<NodePackageInfo>();
foreach (var item in taskArr)
{
if (videoIdArr.Contains(item.VideoCode)|| videoPPTArr.Contains(item.VideoCode))
if (videoIdArr.Contains(item.VideoCode) || videoPPTArr.Contains(item.VideoCode))
{
if (videoDic.ContainsKey(item.VideoCode))
{
var v = videoDic[item.VideoCode];
if (v.VideoType!=null && v.VideoType != item.CourseType)
item.CourseType = v.VideoType.Value;//额外同步课程类型[新课 复习课]
}
postData.Add(item);
item.SuccessTime = DateTime.Now;
}

View File

@ -25,6 +25,11 @@
///// 解析说话人
///// </summary>
//解析说话人 = 30,
/// <summary>
/// AI课程类型
/// </summary>
AI课程类型 = 31,
/// <summary>
/// Chat模型分析
/// </summary>

View File

@ -75,7 +75,7 @@ namespace VideoAnalysisCore.Model
/// <summary>
/// 通知回调地址
/// </summary>
[SugarColumn(Length = 500)]
[SugarColumn(IsNullable = true,Length = 500)]
public string CallBackUrl { get; set; }
/// <summary>
/// 请求区域