From ed8387dea3377a646efef50bf22241679f06320b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=82=A5=E7=BE=8A?= <1048382248@qq.com> Date: Fri, 10 Apr 2026 15:07:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AICore/GPT/ChatGPT/ChatGPTClient.cs | 2 +- VideoAnalysisCore/AICore/GPT/ChatGPTType.cs | 13 ++- .../GPT/DeepSeek/BSET_DeepSeekGPTClient.cs | 1 + .../AICore/GPT/GTP_Analysis_1.cs | 14 +-- .../AICore/GPT/Gemini/GeminiGPTClient.cs | 2 +- VideoAnalysisCore/Controllers/Dto/ApiDto.cs | 102 +++++++++++++++++- .../Controllers/LJZK_Controller.cs | 83 +++++++++++++- VideoAnalysisCore/Model/VideoTaskStage.cs | 2 +- 8 files changed, 202 insertions(+), 17 deletions(-) diff --git a/VideoAnalysisCore/AICore/GPT/ChatGPT/ChatGPTClient.cs b/VideoAnalysisCore/AICore/GPT/ChatGPT/ChatGPTClient.cs index 3e54927..8bd5811 100644 --- a/VideoAnalysisCore/AICore/GPT/ChatGPT/ChatGPTClient.cs +++ b/VideoAnalysisCore/AICore/GPT/ChatGPT/ChatGPTClient.cs @@ -49,7 +49,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT Message[] messageArr = [ new Message(postMessages,"user"), ]; - model = model ?? ChatGPTType.GPT5_mini; + model = model ?? ChatGPTType.GPT54_mini; messageArr = messageArr.Where(s => s != null).ToArray(); var chatReq = new ChatRequest { diff --git a/VideoAnalysisCore/AICore/GPT/ChatGPTType.cs b/VideoAnalysisCore/AICore/GPT/ChatGPTType.cs index 4e34c31..9354423 100644 --- a/VideoAnalysisCore/AICore/GPT/ChatGPTType.cs +++ b/VideoAnalysisCore/AICore/GPT/ChatGPTType.cs @@ -8,18 +8,23 @@ namespace VideoAnalysisCore.AICore.GPT { public class ChatGPTType { - public const string GPT5_mini = "gpt-5-mini"; - public const string GPT5 = "gpt-5-2025-08-07"; + //public const string GPT5_mini = "gpt-5-mini"; + //public const string GPT5 = "gpt-5-2025-08-07"; + + public const string GPT54_mini = "gpt-5.4-mini"; + public const string GPT54 = "gpt-5.4"; public const string Deepseek_Reasoner = "deepseek-reasoner"; public const string Deepseek_Chat = "deepseek-chat"; + public const string Deepseek_v32 = "deepseek-v3.2"; public const string Deepseek_v32_thinking = "deepseek-v3.2-thinking"; //渠道限制没有并发 //public const string Gemini_3_Chat_thinking = "gemini-3-pro-preview-thinking"; - public const string Gemini_3_Chat = "gemini-3-pro-preview"; - public const string Gemini_3_Chat_flash = "gemini-3-flash-preview"; + public const string Gemini_3_Chat = "gemini-3.1-pro-preview"; + //public const string Gemini_3_Chat_flash = "gemini-3-flash-preview"; + public const string Gemini_31_Chat_flash = "gemini-3.1-flash-preview"; } diff --git a/VideoAnalysisCore/AICore/GPT/DeepSeek/BSET_DeepSeekGPTClient.cs b/VideoAnalysisCore/AICore/GPT/DeepSeek/BSET_DeepSeekGPTClient.cs index fa8f0a2..663b80c 100644 --- a/VideoAnalysisCore/AICore/GPT/DeepSeek/BSET_DeepSeekGPTClient.cs +++ b/VideoAnalysisCore/AICore/GPT/DeepSeek/BSET_DeepSeekGPTClient.cs @@ -57,6 +57,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek messages = messageArr }; chatReq.modalities = null; + chatReq.max_completion_tokens = null; return await ChatAsync(chatReq); } diff --git a/VideoAnalysisCore/AICore/GPT/GTP_Analysis_1.cs b/VideoAnalysisCore/AICore/GPT/GTP_Analysis_1.cs index abb56d5..4d2ab10 100644 --- a/VideoAnalysisCore/AICore/GPT/GTP_Analysis_1.cs +++ b/VideoAnalysisCore/AICore/GPT/GTP_Analysis_1.cs @@ -36,7 +36,7 @@ namespace VideoAnalysisCore.AICore.GPT public class GTP_Analysis_1 : IBaseGPTWorkflow { private readonly GeminiGPTClient geminiClient; - private readonly DeepSeekGPTClient deepSeekClient; + //private readonly DeepSeekGPTClient deepSeekClient; private readonly BSET_DeepSeekGPTClient bset_deepSeekClient; private readonly BestAIClient chatGPTClient; private readonly Repository criteriaDB; @@ -59,7 +59,7 @@ namespace VideoAnalysisCore.AICore.GPT Repository knowledgeInfoDB, Repository videoKonwPointDB, SimpLetexClient simpLetexClient, Repository videoQuestionDB, OssClient ossClient, Repository videoQuestionKonwDB, RedisManager redisManager, VideoSliceWorkflowManager workflowManager, BestAIClient chatGPTClient, GeminiGPTClient geminiClient, Repository videoTaskStageDB, BSET_DeepSeekGPTClient bset_deepSeekClient) { - deepSeekClient = moonshotClient; + //deepSeekClient = moonshotClient; criteriaDB = criteria; this.videoTaskDB = videoTaskDB; this.knowledgeInfoDB = knowledgeInfoDB; @@ -115,7 +115,7 @@ namespace VideoAnalysisCore.AICore.GPT await _workflowManager.AddTaskLog(taskInfo.Id, "==>2.开始分析视频内容知识点"); List konwRes; var knowOK = false; - var chatClentArr = new GPTClient[] { chatGPTClient, geminiClient, deepSeekClient }; + var chatClentArr = new GPTClient[] { chatGPTClient, geminiClient, bset_deepSeekClient }; for (int i = 0; i < 3; i++) { konwRes = await chatClentArr[i].ChatAsync>(taskInfo.Id.ToString(), knowMessages, "知识点"); @@ -307,10 +307,10 @@ namespace VideoAnalysisCore.AICore.GPT [ async (m)=>await bset_deepSeekClient .ChatAsync>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.Deepseek_v32,8_000), - async (m)=>await deepSeekClient + async (m)=>await bset_deepSeekClient .ChatAsync>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.Deepseek_Chat,8_000), async (m)=>await chatGPTClient - .ChatAsync>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.GPT5,16_000), + .ChatAsync>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.GPT54_mini,16_000), async (m)=>await geminiClient .ChatAsync>(taskInfo.Id.ToString(), m, "优化字幕",ChatGPTType.Gemini_3_Chat,16_000), ]; await Parallel.ForAsync(0, totalCount, @@ -482,7 +482,7 @@ namespace VideoAnalysisCore.AICore.GPT 输出格式(仅 JSON):{resFormat} """; - var res = await deepSeekClient.ChatAsync(taskInfo.Id.ToString(), message, "作业布置识别", ChatGPTType.Deepseek_Chat, 8000); + var res = await bset_deepSeekClient.ChatAsync(taskInfo.Id.ToString(), message, "作业布置识别", ChatGPTType.Deepseek_Chat, 8000); if (res is null) return null; if (!string.Equals(res.Stage, "作业布置", StringComparison.OrdinalIgnoreCase)) @@ -635,7 +635,7 @@ namespace VideoAnalysisCore.AICore.GPT $"输出内容只返回json格式为({resFormat})" + $"以下是试题内容" + $"`{sRes.Result.res.value}`"; - var resData = await deepSeekClient.ChatAsync>(taskInfo.Id.ToString(), postMessages, "提取试题"); + var resData = await bset_deepSeekClient.ChatAsync>(taskInfo.Id.ToString(), postMessages, "提取试题"); //var resData = await chatClient.ChatAsync(taskInfo.Id.ToString(), postMessages, "提取试题"); if (resData is null || resData.Count() == 0) break; diff --git a/VideoAnalysisCore/AICore/GPT/Gemini/GeminiGPTClient.cs b/VideoAnalysisCore/AICore/GPT/Gemini/GeminiGPTClient.cs index 4c459e8..0bfe55f 100644 --- a/VideoAnalysisCore/AICore/GPT/Gemini/GeminiGPTClient.cs +++ b/VideoAnalysisCore/AICore/GPT/Gemini/GeminiGPTClient.cs @@ -46,7 +46,7 @@ namespace VideoAnalysisCore.AICore.GPT.Gemini Message[] messageArr = [ new Message(postMessages,"user"), ]; - model = model ?? ChatGPTType.Gemini_3_Chat_flash; + model = model ?? ChatGPTType.Gemini_31_Chat_flash; messageArr = messageArr.Where(s => s != null).ToArray(); var chatReq = new ChatRequest { diff --git a/VideoAnalysisCore/Controllers/Dto/ApiDto.cs b/VideoAnalysisCore/Controllers/Dto/ApiDto.cs index 786e24a..15ccfe1 100644 --- a/VideoAnalysisCore/Controllers/Dto/ApiDto.cs +++ b/VideoAnalysisCore/Controllers/Dto/ApiDto.cs @@ -1,9 +1,11 @@ -using SqlSugar; +using SqlSugar; using System.ComponentModel.DataAnnotations; using UserCenter.Model.Enum; using VideoAnalysisCore.AICore.GPT.Dto; +using VideoAnalysisCore.Model; using VideoAnalysisCore.Model.Dto; using VideoAnalysisCore.Model.Enum; +using Yitter.IdGenerator; namespace VideoAnalysisCore.Controllers.Dto { @@ -340,4 +342,102 @@ namespace VideoAnalysisCore.Controllers.Dto // TimeBase?.GroupBy(s => s.TimeBaseType??TimeBaseTypeEnum.教师讲授)? // .ToDictionary(s => s.Key, s => new TextValue(s.Sum(x => x.End - x.Start))); } + + public class VideoKonwPointQueryReq + { + public long? CloudSchoolId { get; set; } + public CourselevelTypeEnum? CourseLevel { get; set; } + public GradeEnum? GradeId { get; set; } + public GradeSemesterEnum? GradeSemester { get; set; } + public long? TextBookVersionId { get; set; } + public string[]? KnowPointIdArr { get; set; } + public string? Theme { get; set; } + public string? Content { get; set; } + public int PageIndex { get; set; } = 0; + public int PageSize { get; set; } = 200; + } + + public class VideoTaskInfoRes + { + /// + /// 视频vid + /// + public long VideoTaskId { get; set; } + /// + /// 分段 + /// + public VideoTaskStageRes[] Stages { get; set; } + + } + public class VideoTaskStageRes + { + + /// + /// id + /// + [SugarColumn(IsPrimaryKey = true)] + public long Id { get; set; } = YitIdHelper.NextId(); + /// + /// 视频任务id + /// + /// + public long VideoTaskId { get; set; } + /// + /// 自定义Id [任务视频自定义id] + /// + /// + [SugarColumn(Length = 500, IsNullable = true)] + public string? TagId { get; set; } + + /// + /// 开始时间 + /// + [SugarColumn(IsNullable = true)] + public float? StartTime { get; set; } + /// + /// 结束时间 + /// + [SugarColumn(IsNullable = true)] + public float? EndTime { get; set; } + /// + /// 持续时间 + /// + [SugarColumn(IsIgnore = true)] + public float? KeepTime => (EndTime ?? 0) - StartTime ?? 0; + /// + /// 主题 + /// + public string? Theme { get; set; } + /// + /// 课程阶段 + /// + [SugarColumn(IsIgnore = true)] + public virtual StageEnum? Stage { get; set; } + /// + /// 视频所属云校ID + /// 用户中心的云校id + /// + [SugarColumn(IsNullable = true)] + public long? CloudSchoolId { get; set; } + /// + /// 知识点 + /// + public string[] KnowPoints { get; set; } = []; + } + public class VideoTaskStageQueryRes + { + + public VideoTaskStageQueryRes() + { + Data = []; + Total = 0; + } + public VideoTaskStageQueryRes(VideoTaskInfoRes[] data, int total = 0) + { + Data = data; + Total = total; + } + public int Total { get; set; } + public VideoTaskInfoRes[] Data { get; set; } + } } diff --git a/VideoAnalysisCore/Controllers/LJZK_Controller.cs b/VideoAnalysisCore/Controllers/LJZK_Controller.cs index 0059a6b..261304d 100644 --- a/VideoAnalysisCore/Controllers/LJZK_Controller.cs +++ b/VideoAnalysisCore/Controllers/LJZK_Controller.cs @@ -12,13 +12,12 @@ using System.Text.Json; using Microsoft.AspNetCore.Authorization; using VideoAnalysisCore.Model.Enum; using FFmpeg.NET.Services; -using static FFmpeg.NET.MetaData; -using static System.Runtime.InteropServices.JavaScript.JSType; using Yitter.IdGenerator; using VideoAnalysisCore.AICore.GPT.Dto; using VideoAnalysisCore.Model; using VideoAnalysisCore.Controllers.Dto; using VideoAnalysisCore.Model.Dto; +using SqlSugar; using VideoAnalysisCore.Model.ǿ; namespace VideoAnalysisCore.Controllers @@ -285,6 +284,86 @@ namespace VideoAnalysisCore.Controllers return Ok(res); } + /// + /// ѯ ƵƬ + /// + /// + /// + [HttpPost(Name = "QueryVideoStage")] + public async Task QueryVideoStage([FromBody] VideoKonwPointQueryReq req) + { + if (req is null) + return BadRequest("Ϊ"); + + var stageQuery = videoTaskStageDB.AsQueryable(); + stageQuery = stageQuery.WhereIF(req.CloudSchoolId.HasValue, s => s.CloudSchoolId == req.CloudSchoolId); + stageQuery = stageQuery.WhereIF(req.CourseLevel.HasValue, s => s.CourseLevel == req.CourseLevel); + stageQuery = stageQuery.WhereIF(req.GradeId.HasValue, s => s.GradeId == req.GradeId); + stageQuery = stageQuery.WhereIF(req.GradeSemester.HasValue, s => s.GradeSemester == req.GradeSemester); + stageQuery = stageQuery.WhereIF(req.TextBookVersionId.HasValue, s => s.TextBookVersionId == req.TextBookVersionId.Value); + stageQuery = stageQuery.WhereIF(!string.IsNullOrWhiteSpace(req.Theme), s => s.Theme.Contains(req.Theme)); + stageQuery = stageQuery.WhereIF(!string.IsNullOrWhiteSpace(req.Content), s => s.Content.Contains(req.Content)); + + var pageIndex = req.PageIndex < 0 ? 0 : req.PageIndex; + var pageSize = req.PageSize <= 0 ? 200 : req.PageSize > 500 ? 500 : req.PageSize; + + if (req.KnowPointIdArr is not null && req.KnowPointIdArr.Length > 0) + { + var knowArr = req.KnowPointIdArr.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToArray(); + if (knowArr.Length > 0) + { + stageQuery = stageQuery.Where(s => SqlFunc.Subqueryable() + .Where(k => k.StageId == s.Id && k.KnowPointId != null && knowArr.Contains(k.KnowPointId)) + .Any()); + } + } + + RefAsync total = 0; + var stagePageArr = await stageQuery.ToPageListAsync(pageIndex + 1, pageSize, total); + if (stagePageArr is null || stagePageArr.Count == 0) + return Ok(new VideoTaskStageQueryRes()); + + var taskIdArr = stagePageArr.Select(s => s.VideoTaskId).ToArray(); + var kpQuery = videoKonwPointDB.AsQueryable() + .Where(s => taskIdArr.Contains(s.VideoTaskId) && s.KnowPointId != null); + if (req.KnowPointIdArr is not null && req.KnowPointIdArr.Length > 0) + { + var knowArr = req.KnowPointIdArr.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToArray(); + if (knowArr.Length > 0) + kpQuery = kpQuery.Where(s => knowArr.Contains(s.KnowPointId)); + } + + var kpArr = await kpQuery + .Select(s => new { s.StageId, s.KnowPoint }) + .ToArrayAsync(); + var kpDic = (kpArr ?? []) + .GroupBy(s => s.StageId) + .ToDictionary(s => s.Key, s => s.Select(x => x.KnowPoint!).Distinct().ToArray()); + + var data = stagePageArr.Select(s => new VideoTaskStageRes() + { + Id = s.Id, + VideoTaskId = s.VideoTaskId, + TagId = s.TagId, + StartTime = s.StartTime, + EndTime = s.EndTime, + Theme = s.Theme, + CloudSchoolId = s.CloudSchoolId, + KnowPoints = kpDic.ContainsKey(s.Id) ? kpDic[s.Id] : [] + }).ToArray(); + + return Ok(new VideoTaskStageQueryRes() + { + Total = total, + Data = data.GroupBy(s=>s.VideoTaskId) + .Select(s=>new VideoTaskInfoRes() + { + Stages = s.ToArray(), + VideoTaskId =s.Key + }).ToArray() + }); + } + diff --git a/VideoAnalysisCore/Model/VideoTaskStage.cs b/VideoAnalysisCore/Model/VideoTaskStage.cs index 2c57c41..d46dc92 100644 --- a/VideoAnalysisCore/Model/VideoTaskStage.cs +++ b/VideoAnalysisCore/Model/VideoTaskStage.cs @@ -55,7 +55,7 @@ namespace VideoAnalysisCore.Model /// public string? Theme { get; set; } /// - /// 知识点来源 视频秒,来源原因 + /// 切片内容 /// [SugarColumn(Length = 500, IsNullable = true)] public string Content { get; set; }