调整 部分文件代码命名

This commit is contained in:
小肥羊 2025-12-19 17:41:24 +08:00
parent 929d6f8a98
commit deb7f80bce
7 changed files with 112 additions and 53 deletions

View File

@ -15,7 +15,7 @@ using System.Text.Json.Serialization;
namespace VideoAnalysisCore.AICore.GPT
{
public interface IBserGPT
public interface IBserGPTWorkflow
{
/// <summary>
/// 访问GPT
@ -190,8 +190,8 @@ namespace VideoAnalysisCore.AICore.GPT
public static void AddGPTService(this IServiceCollection services)
{
services.AddSingleton<DeepSeekGPTClient>();
services.AddSingleton<ChatGPTClient>();
services.AddSingleton<IBserGPT, DeepSeek_GPT>();
services.AddSingleton<BestAIClient>();
services.AddSingleton<IBserGPTWorkflow, GTP_Analysis_1>();
}

View File

@ -15,7 +15,10 @@ using System.Text.Json;
namespace VideoAnalysisCore.AICore.GPT.ChatGPT
{
public class ChatGPTClient : GPTClient
/// <summary>
/// 接入oaibest
/// </summary>
public class BestAIClient : GPTClient
{
public override GptConfig Config { get; set; } = AppCommon.Config.ChatGpt.ChatGpt;
@ -23,7 +26,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
private readonly IHttpClientFactory _httpClientFactory;
private readonly RedisManager redisManager;
public ChatGPTClient(IHttpClientFactory httpClientFactory, RedisManager redisManager) : base(httpClientFactory, redisManager)
public BestAIClient(IHttpClientFactory httpClientFactory, RedisManager redisManager) : base(httpClientFactory, redisManager)
{
_httpClientFactory = httpClientFactory;
this.redisManager = redisManager;

View File

@ -16,5 +16,9 @@ namespace VideoAnalysisCore.AICore.GPT
public static string Deepseek_Chat = "deepseek-chat";
public static string Gemini_3_Chat_thinking = "gemini-3-pro-preview-thinking";
public static string Gemini_3_Chat = "gemini-3-pro-preview";
}
}

View File

@ -167,7 +167,7 @@ namespace VideoAnalysisCore.AICore.GPT
var chatResp = await Chat(chatRep);
var chatResContent = chatResp?.res;
if (string.IsNullOrEmpty(chatResContent))
throw new Exception("GPT返回message无效结果");
throw new Exception($"GPT返回message无效结果 => res:{chatResp?.res} reasoning:{chatResp?.reasoning}");
if (chatResp != null)
{
redisCached[1] = new object[] { chatResp.Value.res, chatResp.Value.u, chatResp.Value.reasoning };

View File

@ -26,12 +26,13 @@ using System.Text.RegularExpressions;
namespace VideoAnalysisCore.AICore.GPT.DeepSeek
{
/// <summary>
/// chatgpt 文本模型
/// 视频分析工作流1
/// </summary>
public class DeepSeek_GPT : IBserGPT
public class GTP_Analysis_1 : IBserGPTWorkflow
{
private readonly GeminiGPTClient geminiClient;
private readonly DeepSeekGPTClient chatClient;
private readonly ChatGPTClient chatGPTClient;
private readonly BestAIClient chatGPTClient;
private readonly Repository<CourseGradingCriteria> criteriaDB;
private readonly RedisManager redisManager;
private readonly Repository<VideoTask> videoTaskDB;
@ -46,9 +47,9 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
/// </summary>
/// <param name="moonshotClient"></param>
/// <param name="logger"></param>
public DeepSeek_GPT(DeepSeekGPTClient moonshotClient, Repository<CourseGradingCriteria> criteria, Repository<VideoTask> videoTaskDB,
public GTP_Analysis_1(DeepSeekGPTClient moonshotClient, Repository<CourseGradingCriteria> criteria, Repository<VideoTask> videoTaskDB,
Repository<KnowledgeInfo> knowledgeInfoDB, Repository<VideoKonwPoint> videoKonwPointDB, SimpLetexClient simpLetexClient,
Repository<VideoQuestion> videoQuestionDB, OssClient ossClient, Repository<VideoQuestionKonw> videoQuestionKonwDB, RedisManager redisManager, ChatGPTClient chatGPTClient)
Repository<VideoQuestion> videoQuestionDB, OssClient ossClient, Repository<VideoQuestionKonw> videoQuestionKonwDB, RedisManager redisManager, BestAIClient chatGPTClient, GeminiGPTClient geminiClient)
{
chatClient = moonshotClient;
criteriaDB = criteria;
@ -61,6 +62,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
this.videoQuestionKonwDB = videoQuestionKonwDB;
this.redisManager = redisManager;
this.chatGPTClient = chatGPTClient;
this.geminiClient = geminiClient;
}
/// <summary>
/// 获取分段内容对应的章节知识点
@ -297,8 +299,8 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
try
{
var keyFrameArr = string.IsNullOrEmpty(taskInfo?.PPTVideoCode) || string.IsNullOrEmpty(taskInfo?.PPTKeyFrame)
? string.Empty
: $"授课PPT发生了变化的时间是{taskInfo.PPTKeyFrame},所以在这些时间段附近应该发生了授课内容得变化,授课阶段结果尽量参考这些时间节点(PPT与字幕有一定的延时)。";
? $""
: $"授课PPT发生了变化的时间是{taskInfo.PPTKeyFrame},基于PPT变化时间点将字幕内容分割成时间段。每个时间段的起始和结束应接近这些时间点例如以时间点为中心扩展至内容自然过渡处。";
var resFormat = """[{"StartTime":开始秒(number),"EndTime":结束秒(number),"Stage":阶段(string),"Theme":主题(string),"Content":内容总结(string)}]""";
var postMessages = string.Empty;
@ -306,46 +308,27 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
{
case AttachmentsInfoType.:
case AttachmentsInfoType.:
postMessages =
$"请通过视频字幕内容分析出视频中课堂的授课阶段。" +
$"课堂内容与{taskInfo.Subject}学科下的{sections}章节相关。" +
$"{keyFrameArr}" +
$"完整的课堂标准流程包含以下5个阶段课程引入/新知讲解/例题精讲/课堂练习/知识总结。" +
$"每个类型的授课阶段允许有多个 例如 多个新知讲解/例题精讲..." +
$"1.初步划分阶段基于PPT变化时间点将字幕内容分割成时间段。每个时间段的起始和结束应接近这些时间点例如以时间点为中心扩展至内容自然过渡处。" +
$"2.内容分析:对每个时间段,提取主要讲解内容:识别关键词(如“例题”“证明”“练习”“总结”)和内容结构。" +
$"3.判断阶段类型:如果内容以解题为主,归类为“例题精讲”;如果涉及新知识讲解,归类为“新知讲解”;以此类推。" +
$"4.生成内容总结与主题内容总结用1-2句话简述该阶段的核心讲解内容例如“通过例题演示柯西不等式在求最值中的应用”。" +
$"5.阶段主题:基于内容总结,提炼一个具体主题(例如,“柯西不等式的基本应用”)。" +
$"6.时长检查与调整计算每个阶段的时长结束时间减开始时间。如果阶段时长低于50秒则合并相邻的类似内容阶段例如将两个连续的例题讲解合并为一个阶段或扩展时间段以确保最低50秒。调整时需保持内容连贯性。" +
$"7.输出要求:最终分析结果应列出每个阶段的开始时间、结束时间、阶段类型、主题和详细的内容总结(50~100字不包含提示词内容),确保划分合理、无重叠,且时长符合要求。" +
$"输出内容只返回json格式({resFormat})" +
$"字幕格式(开始秒:内容|下一段字幕).以下是包含时间的视频字幕文本。" +
$"字幕列表 {captions.Captions} 字幕结束!";
break;
case AttachmentsInfoType.:
postMessages =
$"请通过视频字幕内容分析出视频中课堂的授课阶段。" +
$"课堂内容与{taskInfo.Subject}学科下的{sections}章节相关。" +
$"{keyFrameArr}" +
$"完整的课堂标准流程包含以下5个阶段课程引入/新知讲解/例题精讲/课堂练习/知识总结。" +
$"但本堂课是习题课,所以大部分阶段是不同的例题讲解内容。" +
$"1.初步划分阶段基于PPT变化时间点将字幕内容分割成时间段。每个时间段的起始和结束应接近这些时间点例如以时间点为中心扩展至内容自然过渡处。" +
$"2.内容分析:对每个时间段,提取主要讲解内容:识别关键词(如“例题”“证明”“练习”“总结”)和内容结构。" +
$"3.判断阶段类型:如果内容以解题为主,归类为“例题精讲”;如果涉及新知识讲解,归类为“新知讲解”;以此类推。" +
$"4.生成内容总结与主题内容总结用1-2句话简述该阶段的核心讲解内容例如“通过例题演示柯西不等式在求最值中的应用”。" +
$"5.阶段主题:基于内容总结,提炼一个具体主题(例如,“柯西不等式的基本应用”)。" +
$"6.时长检查与调整计算每个阶段的时长结束时间减开始时间。如果阶段时长低于50秒则合并相邻的类似内容阶段例如将两个连续的例题讲解合并为一个阶段或扩展时间段以确保最低50秒。调整时需保持内容连贯性。" +
$"7.输出要求:最终分析结果应列出每个阶段的开始时间、结束时间、阶段类型、主题和详细的内容总结(50~100字不包含提示词内容),确保划分合理、无重叠,且时长符合要求。" +
$"输出格式要求内容只返回json格式({resFormat})" +
$"字幕格式(开始秒:内容|下一段字幕).以下是包含时间的视频字幕文本。" +
$"字幕列表 {captions.Captions} 字幕结束!";
break;
case AttachmentsInfoType.:
case AttachmentsInfoType.:
break;
default:
throw new Exception("无效的课程类型");
}
postMessages =
$"请通过视频字幕内容分析出视频中课堂的授课阶段。" +
$"课堂内容与{taskInfo.Subject}学科下的{sections}章节相关。" +
$"完整的课堂标准流程包含以下5个阶段课程引入/新知讲解/例题精讲/课堂练习/知识总结。" +
(taskInfo?.VideoType == AttachmentsInfoType. ? $"但本堂课是习题课,所以大部分阶段是不同的例题讲解内容。" : string.Empty) +
$"初步划分阶段:{keyFrameArr}" +
$"内容分析:对每个时间段,提取主要讲解内容:识别关键词(如“例题”“证明”“练习”“总结”)和内容结构。" +
$"判断阶段类型:如果内容以解题为主,归类为“例题精讲”;如果涉及新知识讲解,归类为“新知讲解”;以此类推。" +
$"内容总结简述该阶段的核心讲解内容70~200字,确保内容与阶段时间内授课内容符合。" +
$"阶段主题:基于内容总结,提炼一个恰当的主题(例如,“柯西不等式的基本应用”)。" +
$"输出要求:确保阶段划分合理、无重叠,且时长符合要求" +
$"输出格式要求内容只返回json格式({resFormat})" +
$"字幕格式(开始秒:内容|下一段字幕).以下是包含时间的视频字幕文本。" +
$"字幕列表 {captions.Captions} 字幕结束!";
await redisManager.AddTaskLog(taskInfo.Id, $"开始分析视频内容 {tryCount}");
//return await chatGPTClient.ChatAsync<VideoKnowRes[]>(taskInfo.Id.ToString(), postMessages, "分析字幕");

View File

@ -0,0 +1,69 @@
using VideoAnalysisCore.Common;
using System.Net.Http.Headers;
using System.Text;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using System.Net.Http;
using Newtonsoft.Json;
using System.Net.Http.Json;
using System.Net;
using VideoAnalysisCore.AICore.GPT.DeepSeek;
using VideoAnalysisCore.AICore.GPT;
using System.Text.Json;
namespace VideoAnalysisCore.AICore.GPT.ChatGPT
{
public class GeminiGPTClient : GPTClient
{
public override GptConfig Config { get; set; } = AppCommon.Config.ChatGpt.ChatGpt;
private readonly IHttpClientFactory _httpClientFactory;
private readonly RedisManager redisManager;
public GeminiGPTClient(IHttpClientFactory httpClientFactory, RedisManager redisManager) : base(httpClientFactory, redisManager)
{
_httpClientFactory = httpClientFactory;
this.redisManager = redisManager;
}
/// <summary>
/// 请求AI
/// </summary>
/// <typeparam name="T">返回JSON类型</typeparam>
/// <param name="task">任务id</param>
/// <param name="postMessages">提示词</param>
/// <param name="title">任务类型</param>
/// <param name="model">GPT版本</param>
/// <param name="max_tokens">最大token <para>不设置默认最大值 16000/8000</para></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async Task<T> ChatAsync<T>(string task, string postMessages, string title, string model = null, int max_tokens = 8000)
{
Message[] messageArr = [
new Message(postMessages,"user"),
];
model = model ?? ChatGPTType.Gemini_3_Chat;
messageArr = messageArr.Where(s => s != null).ToArray();
var chatReq = new ChatRequest
{
taskId = task,
model = model,
max_tokens =12000,
stream = true,
temperature = 0.2f,
messages = messageArr
};
chatReq.modalities = null;
chatReq.max_tokens = null;
chatReq.top_p = null;
return await base.ChatAsync<T>(chatReq);
}
}
}

View File

@ -137,26 +137,26 @@ namespace VideoAnalysisCore.Common
SubscribeList.Add(RedisChannelEnum.AI课程类型, async (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
if (scope is null || scope.ServiceProvider.GetService<IBserGPTWorkflow>() is null)
throw new Exception("IBserGPT 未注入");
else
await scope.ServiceProvider.GetService<IBserGPT>()?.GetVideoType(task);
await scope.ServiceProvider.GetService<IBserGPTWorkflow>()?.GetVideoType(task);
});
SubscribeList.Add(RedisChannelEnum.AI模型分析, async (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
if (scope is null || scope.ServiceProvider.GetService<IBserGPTWorkflow>() is null)
throw new Exception("IBserGPT 未注入");
else
await scope.ServiceProvider?.GetService<IBserGPT>()?.GetKnow(task);
await scope.ServiceProvider?.GetService<IBserGPTWorkflow>()?.GetKnow(task);
});
SubscribeList.Add(RedisChannelEnum.AI分析试题, async (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
if (scope is null || scope.ServiceProvider.GetService<IBserGPTWorkflow>() is null)
throw new Exception("IBserGPT 未注入");
else
await scope.ServiceProvider?.GetService<IBserGPT>()?.GetVideoQuestion(task);
await scope.ServiceProvider?.GetService<IBserGPTWorkflow>()?.GetVideoQuestion(task);
});
SubscribeList.Add(RedisChannelEnum., redisManager.TaskEnd);