Compare commits
3 Commits
2bdd77380c
...
d433d84d46
| Author | SHA1 | Date |
|---|---|---|
|
|
d433d84d46 | |
|
|
02518a1c4f | |
|
|
dd7e217bb2 |
|
|
@ -11,19 +11,24 @@
|
||||||
@for (int i = 0; i < videoKnows.Length; i++)
|
@for (int i = 0; i < videoKnows.Length; i++)
|
||||||
{
|
{
|
||||||
var item = videoKnows[i];
|
var item = videoKnows[i];
|
||||||
<div class="knowDiv" onclick="spClick(@i,this)">
|
<div class="knowDiv">
|
||||||
|
|
||||||
<div class="knowTtile">
|
<div class="knowTtile">
|
||||||
<div class="knowTtileTheme">@getF(item) @item.Theme</div>
|
<div style="cursor: pointer" onclick="spClick(@i,this)">
|
||||||
<span class="kSpan">#@item.KnowPointId @item.KnowPoint</span>
|
<div class="knowTtileTheme">@getF(item) @item.Theme</div>
|
||||||
|
<span class="kSpan">#@item.KnowPointId @item.KnowPoint</span>
|
||||||
|
</div>
|
||||||
<div>概览: @item.Content</div>
|
<div>概览: @item.Content</div>
|
||||||
<br />
|
<br />
|
||||||
@foreach (var q in item.QuestionArr)
|
@foreach (var q in item.QuestionArr)
|
||||||
{
|
{
|
||||||
<h3>问题: </h3>
|
|
||||||
<div class="knowQuestion">@q.Question</div>
|
<div class="knowQuestion" onclick="spClickTime(@q.StartTime)">
|
||||||
<img style="text-align:center" src="@q.ImageUrl" width="320" height="180" />
|
<h3>问题: <span class="kSpan">@q.StartTime 秒</span></h3>
|
||||||
<br />
|
<div class="kSpan">@q.TopicStem</div>
|
||||||
|
<div >@q.Question</div>
|
||||||
|
<img style="text-align:center" src="@q.ImageUrl" width="320" height="180" />
|
||||||
|
</div>
|
||||||
<br />
|
<br />
|
||||||
}
|
}
|
||||||
<br />
|
<br />
|
||||||
|
|
@ -112,6 +117,9 @@
|
||||||
function spClick(i, button) {
|
function spClick(i, button) {
|
||||||
videoPlayer.currentTime = displayButton[i].startTime;
|
videoPlayer.currentTime = displayButton[i].startTime;
|
||||||
}
|
}
|
||||||
|
function spClickTime(startTime) {
|
||||||
|
videoPlayer.currentTime = startTime;
|
||||||
|
}
|
||||||
function gd(btn) {
|
function gd(btn) {
|
||||||
let e = btn.parentElement.parentElement
|
let e = btn.parentElement.parentElement
|
||||||
if (e.style.right == "0px") {
|
if (e.style.right == "0px") {
|
||||||
|
|
|
||||||
|
|
@ -11,20 +11,24 @@
|
||||||
float: left;
|
float: left;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kSpan {
|
.kSpan {
|
||||||
color: rgba(120, 120, 120,0.66);
|
color: rgba(120, 120, 120,0.66);
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
width: 330px;
|
width: 330px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.textEllipsis {
|
.textEllipsis {
|
||||||
white-space: nowrap; /* 禁止换行 */
|
white-space: nowrap; /* 禁止换行 */
|
||||||
overflow: hidden; /* 隐藏溢出内容 */
|
overflow: hidden; /* 隐藏溢出内容 */
|
||||||
text-overflow: ellipsis; /* 显示省略号 */
|
text-overflow: ellipsis; /* 显示省略号 */
|
||||||
}
|
}
|
||||||
|
|
||||||
video {
|
video {
|
||||||
width: 94%;
|
width: 94%;
|
||||||
height: 85%;
|
height: 85%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gudingBtn {
|
.gudingBtn {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
|
@ -32,6 +36,7 @@ video {
|
||||||
line-height: 27px;
|
line-height: 27px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitles {
|
.subtitles {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 200px;
|
bottom: 200px;
|
||||||
|
|
@ -41,9 +46,11 @@ video {
|
||||||
background-color: rgba(0, 0, 0, 0.7);
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#segmentsContainer:is(:hover) {
|
#segmentsContainer:is(:hover) {
|
||||||
right: 0px!important;
|
right: 0px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#segmentsContainer {
|
#segmentsContainer {
|
||||||
transition: right 0.7s;
|
transition: right 0.7s;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
|
|
@ -62,7 +69,7 @@ video {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: flex-end
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kBtn {
|
.kBtn {
|
||||||
|
|
@ -75,8 +82,9 @@ video {
|
||||||
background-color: rgb(240, 249, 235);
|
background-color: rgb(240, 249, 235);
|
||||||
border: 1px solid rgb(179, 225, 157);
|
border: 1px solid rgb(179, 225, 157);
|
||||||
}
|
}
|
||||||
|
|
||||||
.knowTtileTheme {
|
.knowTtileTheme {
|
||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: rgb(103, 194, 58);
|
color: rgb(103, 194, 58);
|
||||||
}
|
}
|
||||||
|
|
@ -85,20 +93,26 @@ video {
|
||||||
background-color: rgb(248, 230, 191) !important;
|
background-color: rgb(248, 230, 191) !important;
|
||||||
border: 1px solid rgb(206, 187, 81);
|
border: 1px solid rgb(206, 187, 81);
|
||||||
}
|
}
|
||||||
|
|
||||||
.knowDiv {
|
.knowDiv {
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.knowQuestion {
|
.knowQuestion {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
border: 2px solid #ff000059;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #cddc393d;
|
||||||
}
|
}
|
||||||
.knowDiv:hover .knowTtile {
|
|
||||||
width: 340px;
|
.knowDiv:hover .knowTtile {
|
||||||
display:block;
|
width: 340px;
|
||||||
background-color: rgb(240, 249, 235);
|
display: block;
|
||||||
border: 1px solid rgb(179, 225, 157);
|
background-color: rgb(240, 249, 235);
|
||||||
}
|
border: 1px solid rgb(179, 225, 157);
|
||||||
|
}
|
||||||
|
|
||||||
.knowTtile {
|
.knowTtile {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ using Microsoft.AspNetCore.Mvc.Formatters;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using VideoAnalysisCore.AICore.FFMPGE;
|
using VideoAnalysisCore.AICore.FFMPGE;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
using System.Text.Unicode;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -39,7 +41,11 @@ namespace Learn.VideoAnalysis
|
||||||
loggingBuilder.SetMinimumLevel(LogLevel.Warning); // 设置最小日志级别为 Warning
|
loggingBuilder.SetMinimumLevel(LogLevel.Warning); // 设置最小日志级别为 Warning
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers()
|
||||||
|
.AddJsonOptions(options =>
|
||||||
|
{
|
||||||
|
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
|
||||||
|
});
|
||||||
|
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen(c =>
|
builder.Services.AddSwaggerGen(c =>
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
var messageBuilder1 = new StringBuilder();
|
var messageBuilder1 = new StringBuilder();
|
||||||
var lastChat = new ChatResSSE();
|
var lastChat = new ChatResSSE();
|
||||||
var splitCount = "data:".Length;
|
var splitCount = "data:".Length;
|
||||||
var maxLoop = 60*1000;
|
var maxLoop = 60*10000;
|
||||||
int threshold = 0;
|
int threshold = 0;
|
||||||
while (maxLoop>0)
|
while (maxLoop>0)
|
||||||
{
|
{
|
||||||
|
|
@ -205,6 +205,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Console.WriteLine(DateTime.Now + "=>AI请求超时 " + chatReq.taskId);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string model { get; set; } = "deepseek-reasoner";
|
public string model { get; set; } = "deepseek-reasoner";
|
||||||
|
|
||||||
public float max_tokens { get; set; } = 4000;
|
public float max_tokens { get; set; } = 8000;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 要使用的采样温度,介于 0 和 2 之间。较高的值(如 0.8)将使输出更加随机,而较低的值(如 0.2)将使其更加集中和确定。 我们通常建议更改此项或同时更改两者。top_p
|
/// 要使用的采样温度,介于 0 和 2 之间。较高的值(如 0.8)将使输出更加随机,而较低的值(如 0.2)将使其更加集中和确定。 我们通常建议更改此项或同时更改两者。top_p
|
||||||
/// <para> 默认为 1</para>
|
/// <para> 默认为 1</para>
|
||||||
|
|
@ -38,7 +38,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
/// 一种替代温度采样的方法,称为原子核采样, 其中,模型考虑具有top_p概率的标记的结果 质量。所以 0.1 表示仅包含前 10% 概率质量的代币 被考
|
/// 一种替代温度采样的方法,称为原子核采样, 其中,模型考虑具有top_p概率的标记的结果 质量。所以 0.1 表示仅包含前 10% 概率质量的代币 被考
|
||||||
/// <para>建议与<see cref="ChatRequest.temperature"/>联动</para>
|
/// <para>建议与<see cref="ChatRequest.temperature"/>联动</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float top_p { get; set; } = 0.5f;
|
public float top_p { get; set; } = 0.1f;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 一个对象,用于指定模型必须输出的格式。设置为 enable 结构化输出,确保模型与您提供的 JSON 匹配 图式。
|
/// 一个对象,用于指定模型必须输出的格式。设置为 enable 结构化输出,确保模型与您提供的 JSON 匹配 图式。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ using static System.Collections.Specialized.BitVector32;
|
||||||
using FFmpeg.NET.Services;
|
using FFmpeg.NET.Services;
|
||||||
using Aliyun.OSS;
|
using Aliyun.OSS;
|
||||||
using Yitter.IdGenerator;
|
using Yitter.IdGenerator;
|
||||||
|
using VideoAnalysisCore.Common.Expand;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
{
|
{
|
||||||
|
|
@ -172,10 +173,14 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
{
|
{
|
||||||
//校验结果质量
|
//校验结果质量
|
||||||
var thems = JsonSerializer.Serialize(questionRes.Adapt<VideoKnowQueryDto[]>());
|
var thems = JsonSerializer.Serialize(questionRes.Adapt<VideoKnowQueryDto[]>());
|
||||||
|
var pptFormat = taskInfo.VideoType==AttachmentsInfoType.PPT
|
||||||
|
? "这堂课是习题课,所讲解内容都是试题。"
|
||||||
|
: string.Empty;
|
||||||
var checkResFormat = """{"Score":打分(number),"Evaluation":评价(string)""";//,"Data":优化后的分段(array)}""";
|
var checkResFormat = """{"Score":打分(number),"Evaluation":评价(string)""";//,"Data":优化后的分段(array)}""";
|
||||||
var checkMessage = "我为视频的讲解内容做了一些分段,希望你能通读字幕内容后检查下的分段是否符合我的要求?" +
|
var checkMessage = "我为视频的讲解内容做了一些分段,希望你能通读字幕内容后检查下的分段是否符合我的要求?" +
|
||||||
$"检查这些分段的时间是否合理 与相邻的时间段间隔是否处于合理区间30~900秒之间?" +
|
$"检查这些分段的时间是否合理 与相邻的时间段间隔是否大于30秒?" +
|
||||||
$"分段的主题内容,知识点分配是否合理符合实际吗?" +
|
$"分段的主题内容,知识点分配是否合理符合实际吗?" +
|
||||||
|
$"{pptFormat}" +
|
||||||
$"请给出你的打分(0-100,70分及格)以及打分原因。" +
|
$"请给出你的打分(0-100,70分及格)以及打分原因。" +
|
||||||
$"这是我的分段 {thems}。" +
|
$"这是我的分段 {thems}。" +
|
||||||
$"后续的内容是包含时间戳的视频字幕的固定格式文本。" +
|
$"后续的内容是包含时间戳的视频字幕的固定格式文本。" +
|
||||||
|
|
@ -254,50 +259,48 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task Analytics(List<VideoKnowRes> questionRes, VideoTask taskInfo,
|
private async Task Analytics(List<VideoKnowRes> questionRes, VideoTask taskInfo,
|
||||||
SenseVoiceRes[] captionsArr, string sections)
|
TotalCaptionsDto captions, string sections)
|
||||||
{
|
{
|
||||||
var lastTime = 0;
|
var tryCount = 10;
|
||||||
var endTime = 0;
|
while (tryCount-->0)
|
||||||
var maxVideoTime = captionsArr?.LastOrDefault()?.End ?? 0;
|
|
||||||
var subject = taskInfo.Subject.ToString();
|
|
||||||
var timeSpan = (int)(maxVideoTime * 0.5);
|
|
||||||
while (endTime + 60 < maxVideoTime)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
endTime = lastTime + timeSpan;
|
|
||||||
var nowCaptionStr = string.Join('|', captionsArr
|
|
||||||
.Where(s => s.Text != "。")
|
|
||||||
.Where((s, i) => s.Start > lastTime && s.End < endTime)
|
|
||||||
.Select(s => s.Start + ":" + s.Text));
|
|
||||||
var keyFrameArr = string.IsNullOrEmpty(taskInfo?.PPTVideoCode)
|
var keyFrameArr = string.IsNullOrEmpty(taskInfo?.PPTVideoCode)
|
||||||
? string.Empty
|
? string.Empty
|
||||||
: $"视频授课内容发生了变化的时间节点{taskInfo.PPTKeyFrame},授课阶段应当在附近时间发生变化。";
|
: $"图像视频中授课内容PPT发生了变化的时间节点是{taskInfo.PPTKeyFrame},授课阶段结果可以参考这些时间节点。";
|
||||||
var resFormat = """[{"StartTime":开始秒(number),"EndTime":结束秒(number),"Stage":阶段(string),"Theme":主题(string),"Content":内容总结(string)}]""";
|
var resFormat = """[{"StartTime":开始秒(number),"EndTime":结束秒(number),"Stage":阶段(string),"Theme":主题(string),"Content":内容总结(string)}]""";
|
||||||
|
|
||||||
|
var exerciseClass = taskInfo?.VideoType == AttachmentsInfoType.Review
|
||||||
|
? $"但是本堂课是习题课,所以每个阶段是不同的例题讲解内容。"
|
||||||
|
: string.Empty;
|
||||||
|
//$"请注意 本次分析的视频字幕只是其中一部分 不需要分析出所有类型的授课阶段。";
|
||||||
var postMessages =
|
var postMessages =
|
||||||
$"请通过视频字幕内容分析出视频中{subject}课堂的授课阶段。" +
|
$"请通过视频字幕内容分析出视频中课堂的授课阶段。" +
|
||||||
$"课堂内容与{sections}章节相关。" +
|
$"课堂内容与{taskInfo.Subject}学科下的{sections}章节相关。" +
|
||||||
$"{keyFrameArr}" +
|
$"{keyFrameArr}" +
|
||||||
$"完整的课堂标准流程包含以下5个阶段:课程引入/新知讲解/例题精讲/课堂练习/知识总结。" +
|
$"完整的课堂标准流程包含以下5个阶段:课程引入/新知讲解/例题精讲/课堂练习/知识总结。"+
|
||||||
|
$"{exerciseClass}" +
|
||||||
$"通过授课阶段的主要讲解内容分析出对应的授课阶段内容总结。" +
|
$"通过授课阶段的主要讲解内容分析出对应的授课阶段内容总结。" +
|
||||||
$"通过生成的内容总结分析出对应的授课阶段主题。 " +
|
$"通过生成的内容总结分析出对应的授课阶段主题。 "+
|
||||||
$"请注意 本次分析的视频字幕只是其中一部分 不需要分析出所有类型的授课阶段。" +
|
$"最后请检查每个授课阶段的时长,不允许出现低于50秒的阶段。" +
|
||||||
$"最后请检查每个授课阶段的时长,不允许出现超出800秒或者低于50秒的授课阶段。" +
|
|
||||||
$"输出内容只返回json格式({resFormat})" +
|
$"输出内容只返回json格式({resFormat})" +
|
||||||
$"字幕格式(开始秒:内容|下一段字幕).以下是包含时间的视频字幕文本。" +
|
$"字幕格式(开始秒:内容|下一段字幕).以下是包含时间的视频字幕文本。" +
|
||||||
$"字幕列表 {nowCaptionStr} 字幕结束!";
|
$"字幕列表 {captions.Captions} 字幕结束!";
|
||||||
|
|
||||||
Console.WriteLine(DateTime.Now + $"=>{taskInfo.Id.ToString()}.开始分析视频内容 {lastTime}~{endTime}");
|
Console.WriteLine(DateTime.Now + $"=>{taskInfo.Id.ToString()}.开始分析视频内容 {tryCount}");
|
||||||
questionRes.AddRange(await ChatAsync<VideoKnowRes[]>(taskInfo.Id.ToString(), postMessages, "分析字幕"));
|
var resData = await ChatAsync<VideoKnowRes[]>(taskInfo.Id.ToString(), postMessages, "分析字幕");
|
||||||
lastTime = (int)questionRes.Last().EndTime.Value - (lastTime == 0 ? 0 : 30);
|
if (taskInfo?.VideoType == AttachmentsInfoType.Review)
|
||||||
|
foreach (var item in resData)
|
||||||
|
item.Stage = StageEnum.例题精讲.ToString();
|
||||||
|
questionRes.AddRange(resData);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine(DateTime.Now + $"=>分析视频内容失败 {lastTime}~{endTime}");
|
Console.WriteLine(DateTime.Now + $"=>{taskInfo.Id.ToString()}分析视频内容失败 {tryCount}");
|
||||||
Console.WriteLine(DateTime.Now + ex.Message);
|
Console.WriteLine(DateTime.Now + ex.Message);
|
||||||
Console.WriteLine(DateTime.Now + ex.StackTrace);
|
Console.WriteLine(DateTime.Now + ex.StackTrace);
|
||||||
endTime = lastTime - timeSpan;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -313,6 +316,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
{
|
{
|
||||||
taskId = task,
|
taskId = task,
|
||||||
model = model,
|
model = model,
|
||||||
|
max_tokens= model== "deepseek-reasoner"?16000:8000,
|
||||||
stream = true,
|
stream = true,
|
||||||
temperature = 0.2f,
|
temperature = 0.2f,
|
||||||
messages = messageArr
|
messages = messageArr
|
||||||
|
|
@ -333,13 +337,13 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
redisCached[1] = new object[] { chatResp.Value.res, chatResp.Value.u, chatResp.Value.reasoning };
|
redisCached[1] = new object[] { chatResp.Value.res, chatResp.Value.u, chatResp.Value.reasoning };
|
||||||
RedisExpand.SetTaskGPTCached(task, time, redisCached);
|
RedisExpand.SetTaskGPTCached(task, time, redisCached);
|
||||||
}
|
}
|
||||||
chatResContent = chatResContent?.Replace("字幕内容", "课堂情况");
|
chatResContent = chatResContent?.ExtractJsonStrings()?.FirstOrDefault();
|
||||||
chatResContent = chatResContent?.Replace("\n", "");
|
chatResContent = chatResContent?.Replace("\n", "");
|
||||||
chatResContent = chatResContent?.Replace("```json", "");
|
chatResContent = chatResContent?.Replace("```json", "");
|
||||||
chatResContent = chatResContent?.Replace("```", "");
|
chatResContent = chatResContent?.Replace("```", "");
|
||||||
chatResContent = chatResContent?.Replace("}{", "},{");
|
chatResContent = chatResContent?.Replace("}{", "},{");
|
||||||
chatResContent = chatResContent?.Replace("}|{", "},{");
|
chatResContent = chatResContent?.Replace("}|{", "},{");
|
||||||
chatResContent = chatResContent?.Trim().ExtractJson().FirstOrDefault();
|
chatResContent = chatResContent?.Trim();
|
||||||
|
|
||||||
var startsStr = typeof(T).IsArray ? "[" : "{";
|
var startsStr = typeof(T).IsArray ? "[" : "{";
|
||||||
var endStr = typeof(T).IsArray ? "]" : "}";
|
var endStr = typeof(T).IsArray ? "]" : "}";
|
||||||
|
|
@ -401,37 +405,51 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
.ProcessImageAsync(new SimpleTexOcrRequest(filePath));
|
.ProcessImageAsync(new SimpleTexOcrRequest(filePath));
|
||||||
if (!sRes.Success)
|
if (!sRes.Success)
|
||||||
continue;
|
continue;
|
||||||
var knowArr=string.Join(',', knowInfoArr.Select(s => s.KnowPointId + "|" + s.KnowPoint ));
|
if(sRes.Result.res.value.Trim().Length<10)//总试题内容长度小于10 视为无效题目
|
||||||
var resFormat = """[{"TopicStem":string(试题题干),"Question:string(问题)","KnowPointId":(string)知识点ID}]""";
|
break;
|
||||||
|
Console.WriteLine(DateTime.Now + $"=>{taskInfo.Id} 提取{knowInfoArr.First().StartTime}秒试题的试题内容");
|
||||||
|
Console.WriteLine( sRes.Result.res.value);
|
||||||
|
var knowArr=JsonSerializer.Serialize(knowInfoArr.Select(s => new { s.KnowPointId, s.KnowPoint }));
|
||||||
|
var resFormat = """[{"Type":string(试题类型),"TopicStem":string(试题题干),"QuestionArr":[{"Question":string(子问题),"KnowPointId":(string)知识点ID}]}]""";
|
||||||
var postMessages =
|
var postMessages =
|
||||||
$"提供一段内容是md格式的试题内容字符串。" +
|
$"我将提供一段内容是md格式的试题内容字符串。" +
|
||||||
$"请提取出其中的试题内容。并且为每个试题关联上在我限定范围内的知识点(多个则用逗号分割)。" +
|
$"请提取出其中的试题内容试,题干以及每个试题的问题。并且为每个试题关联上在我限定范围内的知识点(多个则用逗号分割)。" +
|
||||||
$"知识点格式(知识点ID|知识点名称)范围[{knowArr}]。" +
|
$"知识点格式(json格式)范围[{knowArr}]。" +
|
||||||
$"排除不是试题内容的文字,优化公式排版并且去除题号。" +
|
$"排除不是试题内容的文字,优化公式排版并且去除题号,但不要修改latex数学公式。" +
|
||||||
$"如果存在多道大题,请帮忙拆分开!" +
|
$"如果存在多道题,则需要拆分成为多个试题对象!" +
|
||||||
|
$"试题的类型约束在 填空题/判断题/选择题/解答题 范围内。" +
|
||||||
|
$"请检查我提供的字符串内容,如不包含问题试题则返回`[]`" +
|
||||||
$"输出内容只返回json格式为({resFormat})" +
|
$"输出内容只返回json格式为({resFormat})" +
|
||||||
$"以下是试题内容" +
|
$"以下是试题内容" +
|
||||||
$"`{sRes.Result.res.info.markdown}`";
|
$"`{sRes.Result.res.value}`";
|
||||||
var resData = await ChatAsync<VideoQuestionOSSDto[]>(taskInfo.Id.ToString(), postMessages, "提取试题", "deepseek-chat");
|
var resData = await ChatAsync<VideoQuestionOSSDto[]>(taskInfo.Id.ToString(), postMessages, "提取试题", "deepseek-chat");
|
||||||
foreach (var q in resData)
|
foreach (var q in resData)
|
||||||
{
|
{
|
||||||
q.Id = YitIdHelper.NextId();
|
var TopicId = YitIdHelper.NextId();
|
||||||
q.FilePath = filePath;
|
foreach (var qt in q.QuestionArr)
|
||||||
q.VideoTaskId = taskInfo.Id;
|
|
||||||
q.StageId = knowInfoArr.First().StageId;
|
|
||||||
foreach (var kid in q.KnowPointId.Split(","))
|
|
||||||
{
|
{
|
||||||
insertQuestionKonw.Add(new VideoQuestionKonw()
|
var vq = q.Adapt<VideoQuestionOSSDto>();
|
||||||
|
vq.Id = YitIdHelper.NextId();
|
||||||
|
vq.StartTime = item;
|
||||||
|
vq.FilePath = filePath;
|
||||||
|
vq.VideoTaskId = taskInfo.Id;
|
||||||
|
vq.StageId = knowInfoArr.First().StageId;
|
||||||
|
vq.Question = qt.Question;
|
||||||
|
vq.TopicId = TopicId;
|
||||||
|
insertData.Add(vq);
|
||||||
|
foreach (var kid in qt.KnowPointId.Split(","))
|
||||||
{
|
{
|
||||||
KnowPoint = knowInfoArr.First(s => s.KnowPointId == kid).KnowPoint,
|
insertQuestionKonw.Add(new VideoQuestionKonw()
|
||||||
KnowPointId= kid,
|
{
|
||||||
StageId =q.StageId,
|
KnowPoint = knowInfoArr.First(s => s.KnowPointId == kid).KnowPoint,
|
||||||
VideoTaskId = q.VideoTaskId,
|
KnowPointId = kid,
|
||||||
VideoQuestionId = q.Id,
|
StageId = q.StageId,
|
||||||
});
|
VideoTaskId = q.VideoTaskId,
|
||||||
|
VideoQuestionId = q.Id,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
insertData.AddRange(resData);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -440,13 +458,6 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//分组共同题干试题ID
|
|
||||||
foreach (var item in insertData.GroupBy(x => x.TopicStem))
|
|
||||||
{
|
|
||||||
var keyId=YitIdHelper.NextId();
|
|
||||||
foreach (var s in item)
|
|
||||||
s.TopicId = keyId;
|
|
||||||
}
|
|
||||||
//上传oss 并更新imageUrl
|
//上传oss 并更新imageUrl
|
||||||
ossClient.AddVideoQuestionUrl(insertData);
|
ossClient.AddVideoQuestionUrl(insertData);
|
||||||
|
|
||||||
|
|
@ -501,7 +512,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
{
|
{
|
||||||
questionRes = new List<VideoKnowRes>();
|
questionRes = new List<VideoKnowRes>();
|
||||||
//视频字幕分析
|
//视频字幕分析
|
||||||
await Analytics(questionRes, taskInfo, captionsArr, sections);
|
await Analytics(questionRes, taskInfo, captions, sections);
|
||||||
|
|
||||||
if (questionRes.Count == 0) continue;
|
if (questionRes.Count == 0) continue;
|
||||||
//处理分段 知识点
|
//处理分段 知识点
|
||||||
|
|
|
||||||
|
|
@ -102,50 +102,6 @@ namespace VideoAnalysisCore.Common
|
||||||
return Path.Combine(task.Id.ToString().LocalPath(), $"{FrameName}{(fTime / 5).ToString().PadLeft(3,'0')}.jpg");
|
return Path.Combine(task.Id.ToString().LocalPath(), $"{FrameName}{(fTime / 5).ToString().PadLeft(3,'0')}.jpg");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 识别字符串中的json字符串
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static List<string> ExtractJson(this string input)
|
|
||||||
{
|
|
||||||
List<string> jsonList = new List<string>();
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
while (index < input.Length)
|
|
||||||
{
|
|
||||||
if (input[index] == '{' || input[index] == '[')
|
|
||||||
{
|
|
||||||
int startIndex = index;
|
|
||||||
int openCount = 1;
|
|
||||||
index++;
|
|
||||||
|
|
||||||
while (index < input.Length && openCount > 0)
|
|
||||||
{
|
|
||||||
if (input[index] == '{' || input[index] == '[')
|
|
||||||
{
|
|
||||||
openCount++;
|
|
||||||
}
|
|
||||||
else if (input[index] == '}' || input[index] == ']')
|
|
||||||
{
|
|
||||||
openCount--;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (openCount == 0)
|
|
||||||
{
|
|
||||||
string json = input.Substring(startIndex, index - startIndex);
|
|
||||||
jsonList.Add(json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return jsonList;
|
|
||||||
}
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 处理数学公式
|
/// 处理数学公式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -246,8 +202,8 @@ namespace VideoAnalysisCore.Common
|
||||||
//stringBuilder.Append(":");
|
//stringBuilder.Append(":");
|
||||||
stringBuilder.Append((int)item.Key.Start);
|
stringBuilder.Append((int)item.Key.Start);
|
||||||
stringBuilder.Append(":");
|
stringBuilder.Append(":");
|
||||||
stringBuilder.Append((int)item.Key.End);
|
//stringBuilder.Append((int)item.Key.End);
|
||||||
stringBuilder.Append(":");
|
//stringBuilder.Append(":");
|
||||||
stringBuilder.Append(item.Key.Text);
|
stringBuilder.Append(item.Key.Text);
|
||||||
stringBuilder.Append("|");
|
stringBuilder.Append("|");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using VideoAnalysisCore.Common.Expand;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.Common
|
namespace VideoAnalysisCore.Common
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@ using AlibabaCloud.TeaUtil.Models;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using VideoAnalysisCore.Job;
|
using VideoAnalysisCore.Job;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.Common
|
namespace VideoAnalysisCore.Common.Expand
|
||||||
{
|
{
|
||||||
public class AlibabaCloudVodConfig
|
public class AlibabaCloudVodConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// id
|
/// id
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ using Aliyun.Credentials.Models;
|
||||||
using VideoAnalysisCore.Model.Dto;
|
using VideoAnalysisCore.Model.Dto;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.Common
|
namespace VideoAnalysisCore.Common.Expand
|
||||||
{
|
{
|
||||||
public class AliyunOSSConfig
|
public class AliyunOSSConfig
|
||||||
{
|
{
|
||||||
|
|
@ -65,13 +65,13 @@ namespace VideoAnalysisCore.Common
|
||||||
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
|
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
|
||||||
AccessKeySecret = AppCommon.Config.AliyunOSS.AccessKeySecret,
|
AccessKeySecret = AppCommon.Config.AliyunOSS.AccessKeySecret,
|
||||||
Endpoint = AppCommon.Config.AliyunOSS.Endpoint,
|
Endpoint = AppCommon.Config.AliyunOSS.Endpoint,
|
||||||
Region= AppCommon.Config.AliyunOSS.Region,
|
Region = AppCommon.Config.AliyunOSS.Region,
|
||||||
};// 创建ClientConfiguration实例,按照您的需要修改默认参数。
|
};// 创建ClientConfiguration实例,按照您的需要修改默认参数。
|
||||||
var conf = new ClientConfiguration();
|
var conf = new ClientConfiguration();
|
||||||
// 设置v4签名。
|
// 设置v4签名。
|
||||||
conf.SignatureVersion = SignatureVersion.V4;
|
conf.SignatureVersion = SignatureVersion.V4;
|
||||||
// 创建OssClient实例。
|
// 创建OssClient实例。
|
||||||
var oss = new OssClient(config.Endpoint, config.AccessKeyId, config.AccessKeySecret, conf);
|
var oss = new OssClient(config.Endpoint, config.AccessKeyId, config.AccessKeySecret, conf);
|
||||||
oss.SetRegion(config.Region);
|
oss.SetRegion(config.Region);
|
||||||
|
|
||||||
service.AddSingleton(oss);
|
service.AddSingleton(oss);
|
||||||
|
|
@ -81,7 +81,7 @@ namespace VideoAnalysisCore.Common
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="oss"></param>
|
/// <param name="oss"></param>
|
||||||
/// <param name="fileArr">视频实体片段</param>
|
/// <param name="fileArr">视频实体片段</param>
|
||||||
public static void AddVideoQuestionUrl(this OssClient oss, List<VideoQuestionOSSDto> fileArr )
|
public static void AddVideoQuestionUrl(this OssClient oss, List<VideoQuestionOSSDto> fileArr)
|
||||||
{
|
{
|
||||||
var cached = new HashSet<string>();
|
var cached = new HashSet<string>();
|
||||||
foreach (var item in fileArr)
|
foreach (var item in fileArr)
|
||||||
|
|
@ -89,7 +89,7 @@ namespace VideoAnalysisCore.Common
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var path = item.VideoTaskId.ToString() + "/" + Path.GetFileName(item.FilePath);
|
var path = item.VideoTaskId.ToString() + "/" + Path.GetFileName(item.FilePath);
|
||||||
if (cached.Contains(item.FilePath))
|
if (cached.Contains(item.FilePath))
|
||||||
{
|
{
|
||||||
item.ImageUrl = AppCommon.Config.AliyunOSS.BucketDomain + "/" + path;
|
item.ImageUrl = AppCommon.Config.AliyunOSS.BucketDomain + "/" + path;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ using System.Net.Http.Json;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AlibabaCloud.OpenApiClient.Models;
|
using AlibabaCloud.OpenApiClient.Models;
|
||||||
using AlibabaCloud.SDK.Vod20170321;
|
using AlibabaCloud.SDK.Vod20170321;
|
||||||
|
|
@ -15,10 +17,9 @@ using AlibabaCloud.TeaUtil.Models;
|
||||||
using Azure;
|
using Azure;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using VideoAnalysisCore.Job;
|
using VideoAnalysisCore.Job;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.Common
|
namespace VideoAnalysisCore.Common.Expand
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -32,7 +33,10 @@ namespace VideoAnalysisCore.Common
|
||||||
public class SimpleTexOcrResponseDataRes
|
public class SimpleTexOcrResponseDataRes
|
||||||
{
|
{
|
||||||
public string type { get; set; }
|
public string type { get; set; }
|
||||||
public SimpleTexOcrResponseDataInfo info { get; set; }
|
|
||||||
|
[JsonPropertyName("info")] // 替换为实际字段名
|
||||||
|
public JsonElement DataInfo { get; set; } // 使用JsonElement接收未知类型
|
||||||
|
public string value { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SimpleTexOcrResponseDataInfo
|
public class SimpleTexOcrResponseDataInfo
|
||||||
|
|
@ -81,6 +85,7 @@ namespace VideoAnalysisCore.Common
|
||||||
{
|
{
|
||||||
public bool Success { get; set; }
|
public bool Success { get; set; }
|
||||||
public SimpleTexOcrResponseData Result { get; set; }
|
public SimpleTexOcrResponseData Result { get; set; }
|
||||||
|
public string ResultStr { get; set; }
|
||||||
public string Error { get; set; }
|
public string Error { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,7 +128,7 @@ namespace VideoAnalysisCore.Common
|
||||||
|
|
||||||
if (request.isolated_formula_wrapper != null)
|
if (request.isolated_formula_wrapper != null)
|
||||||
{
|
{
|
||||||
var isolatedWrapper = JsonConvert.SerializeObject(request.isolated_formula_wrapper);
|
var isolatedWrapper = JsonSerializer.Serialize(request.isolated_formula_wrapper);
|
||||||
content.Add(new StringContent(isolatedWrapper), nameof(request.isolated_formula_wrapper));
|
content.Add(new StringContent(isolatedWrapper), nameof(request.isolated_formula_wrapper));
|
||||||
parameters[nameof(request.isolated_formula_wrapper)] = isolatedWrapper;
|
parameters[nameof(request.isolated_formula_wrapper)] = isolatedWrapper;
|
||||||
}
|
}
|
||||||
|
|
@ -161,11 +166,25 @@ namespace VideoAnalysisCore.Common
|
||||||
var response = await client.SendAsync(requestMessage);
|
var response = await client.SendAsync(requestMessage);
|
||||||
var resStr = await response.Content.ReadAsStringAsync();
|
var resStr = await response.Content.ReadAsStringAsync();
|
||||||
var responseContent = await response.Content.ReadFromJsonAsync<SimpleTexOcrResponseData>();
|
var responseContent = await response.Content.ReadFromJsonAsync<SimpleTexOcrResponseData>();
|
||||||
|
if (responseContent.res.DataInfo.ValueKind == JsonValueKind.Object)
|
||||||
|
{
|
||||||
|
responseContent.res.value = JsonSerializer.Deserialize<SimpleTexOcrResponseDataInfo>(
|
||||||
|
responseContent.res.DataInfo.GetRawText(),
|
||||||
|
new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
|
||||||
|
)?.markdown??string.Empty;
|
||||||
|
// 处理字符串
|
||||||
|
}
|
||||||
|
else if (responseContent.res.DataInfo.ValueKind == JsonValueKind.String)
|
||||||
|
{
|
||||||
|
responseContent.res.value = responseContent.res.DataInfo.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
request.file.Dispose();
|
request.file.Dispose();
|
||||||
return new SimpleTexOcrResponse
|
return new SimpleTexOcrResponse
|
||||||
{
|
{
|
||||||
Success = response.IsSuccessStatusCode,
|
Success = response.IsSuccessStatusCode,
|
||||||
Result = responseContent,
|
Result = responseContent,
|
||||||
|
ResultStr= resStr,
|
||||||
Error = response.IsSuccessStatusCode ? null : $"HTTP Error: {response.StatusCode}"
|
Error = response.IsSuccessStatusCode ? null : $"HTTP Error: {response.StatusCode}"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace VideoAnalysisCore.Common
|
||||||
|
{
|
||||||
|
public static class JsonExtractor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 提取json字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static List<string> ExtractJsonStrings(this string input)
|
||||||
|
{
|
||||||
|
List<string> jsonList = new List<string>();
|
||||||
|
int index = 0;
|
||||||
|
while (index < input.Length)
|
||||||
|
{
|
||||||
|
if (input[index] == '{' || input[index] == '[')
|
||||||
|
{
|
||||||
|
int? endIndex = FindMatchingBracket(input, index);
|
||||||
|
if (endIndex.HasValue)
|
||||||
|
{
|
||||||
|
string candidate = input.Substring(index, endIndex.Value - index + 1);
|
||||||
|
if (IsValidJson(candidate))
|
||||||
|
{
|
||||||
|
jsonList.Add(candidate);
|
||||||
|
index = endIndex.Value + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return jsonList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int? FindMatchingBracket(string str, int start)
|
||||||
|
{
|
||||||
|
Stack<char> stack = new Stack<char>();
|
||||||
|
bool inString = false;
|
||||||
|
bool inEscape = false;
|
||||||
|
|
||||||
|
for (int i = start; i < str.Length; i++)
|
||||||
|
{
|
||||||
|
char c = str[i];
|
||||||
|
|
||||||
|
if (inEscape)
|
||||||
|
{
|
||||||
|
inEscape = false;
|
||||||
|
}
|
||||||
|
else if (inString)
|
||||||
|
{
|
||||||
|
if (c == '\\')
|
||||||
|
inEscape = true;
|
||||||
|
else if (c == '"')
|
||||||
|
inString = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '{':
|
||||||
|
case '[':
|
||||||
|
stack.Push(c);
|
||||||
|
break;
|
||||||
|
case '}':
|
||||||
|
if (stack.Count == 0 || stack.Peek() != '{')
|
||||||
|
return null;
|
||||||
|
stack.Pop();
|
||||||
|
break;
|
||||||
|
case ']':
|
||||||
|
if (stack.Count == 0 || stack.Peek() != '[')
|
||||||
|
return null;
|
||||||
|
stack.Pop();
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
inString = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack.Count == 0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return null; // 括号未完全匹配
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsValidJson(string candidate)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(candidate))
|
||||||
|
return false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
JsonDocument.Parse(candidate);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,7 @@ using VideoAnalysisCore.Model;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using VideoAnalysisCore.Model.Dto;
|
using VideoAnalysisCore.Model.Dto;
|
||||||
using VideoAnalysisCore.Controllers.Dto;
|
using VideoAnalysisCore.Controllers.Dto;
|
||||||
|
using VideoAnalysisCore.Common.Expand;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.Controllers
|
namespace VideoAnalysisCore.Controllers
|
||||||
{
|
{
|
||||||
|
|
@ -44,6 +45,29 @@ namespace VideoAnalysisCore.Controllers
|
||||||
throw new Exception("未能获取到客户端ip地址");
|
throw new Exception("未能获取到客户端ip地址");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ³õʼ»¯Ö÷¿â±í
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">ÎļþÁ÷</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet(Name = "InitDbTable")]
|
||||||
|
public IActionResult InitDbTable()
|
||||||
|
{
|
||||||
|
var b = AppCommon.Config.DB.UpdateTable;
|
||||||
|
AppCommon.Config.DB.UpdateTable= true;
|
||||||
|
SqlSugarExpand.InitDbTable();
|
||||||
|
AppCommon.Config.DB.UpdateTable = b;
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 语音识别
|
/// 语音识别
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using SqlSugar;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
@ -6,9 +7,26 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.Model.Dto
|
namespace VideoAnalysisCore.Model.Dto
|
||||||
{
|
{
|
||||||
|
public class AIQuestionDto
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 问题
|
||||||
|
/// </summary>
|
||||||
|
public string Question { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 知识点id
|
||||||
|
/// </summary>
|
||||||
|
public string KnowPointId { get; set; }
|
||||||
|
}
|
||||||
public class VideoQuestionOSSDto: VideoQuestion
|
public class VideoQuestionOSSDto: VideoQuestion
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 问题
|
||||||
|
/// </summary>
|
||||||
|
public AIQuestionDto[]? QuestionArr { get; set; }
|
||||||
public string FilePath { get; set; }
|
public string FilePath { get; set; }
|
||||||
|
public string Type { get; set; }
|
||||||
public string KnowPointId { get; set; }
|
public string KnowPointId { get; set; }
|
||||||
}
|
}
|
||||||
public class VideoQuestionShowDto : VideoQuestion
|
public class VideoQuestionShowDto : VideoQuestion
|
||||||
|
|
|
||||||
|
|
@ -52,5 +52,9 @@ namespace VideoAnalysisCore.Model
|
||||||
/// 问题(设问)
|
/// 问题(设问)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Question { get; set; }
|
public string? Question { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 试题开始时间
|
||||||
|
/// </summary>
|
||||||
|
public int StartTime { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue