Compare commits
9 Commits
935c6a9eb1
...
dd6878210f
| Author | SHA1 | Date |
|---|---|---|
|
|
dd6878210f | |
|
|
01af735d62 | |
|
|
fe45448b81 | |
|
|
68056e17d3 | |
|
|
b332fa742c | |
|
|
8f4f48fd66 | |
|
|
d3cf043e09 | |
|
|
a2c9831a0a | |
|
|
90cf56efec |
|
|
@ -5,7 +5,7 @@
|
|||
@using SqlSugar
|
||||
@using VideoAnalysisCore.Model
|
||||
|
||||
<Table @ref="_table" Loading="tableLoading" TItem="CourseGradingCriteria" PageSize="15" Total="_total" DataSource="_dataSource" @bind-SelectedRows="_selectedRows" OnChange="OnChange">
|
||||
<Table @ref="_table" Loading="tableLoading" TItem="CourseGradingCriteria" ScrollY="600px" PageSize="15" Total="_total" DataSource="_dataSource" @bind-SelectedRows="_selectedRows" OnChange="OnChange">
|
||||
<TitleTemplate>
|
||||
<Flex Justify="end" Gap="10">
|
||||
<Button Type="primary" @onclick="()=> StartEdit(default)">新增</Button>
|
||||
|
|
@ -13,13 +13,13 @@
|
|||
</Flex>
|
||||
</TitleTemplate>
|
||||
<ColumnDefinitions Context="row">
|
||||
<Selection />
|
||||
<ActionColumn Title="操作列">
|
||||
<ActionColumn Title="操作列" Width ="230px">
|
||||
<a @onclick="() => StartEdit(row)">修改</a>
|
||||
<Button Type="@ButtonType.Link" Danger @onclick="() => Delete(row)">
|
||||
删除</Button>
|
||||
</ActionColumn>
|
||||
<GenerateColumns Definitions="@((n,c) => { c.Filterable = true; c.Sortable = true; })" />
|
||||
<PropertyColumn Property="c=>c.Id" Width="130px" Filterable="true" Sortable="true" />
|
||||
<PropertyColumn Property="c=>c.NamePrompt" />
|
||||
</ColumnDefinitions>
|
||||
</Table>
|
||||
|
||||
|
|
@ -41,7 +41,9 @@
|
|||
Content =
|
||||
@<Form @ref="form" Model="data" OnFinish="()=> modalRef.OkAsync(true)"
|
||||
LabelColSpan="6" WrapperColSpan="18">
|
||||
<GenerateFormItem NotGenerate="@(x=> x == "Id")" />
|
||||
<FormItem Label="标准提问词" >
|
||||
<TextArea Rows="4" @bind-Value="@context.NamePrompt" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
,
|
||||
OkText = "确定",
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace Learn.VideoAnalysis.Components.Pages
|
|||
}
|
||||
_dataSource = await criteria.AsQueryable()
|
||||
.Where(where)
|
||||
.ToPageListAsync(query.PageIndex - 1, query.PageSize, _total);
|
||||
.ToPageListAsync(query.PageIndex, query.PageSize, _total);
|
||||
tableLoading = false;
|
||||
StateHasChanged();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,15 @@
|
|||
@using AntDesign
|
||||
@using AntDesign.TableModels
|
||||
@using System.ComponentModel.DataAnnotations
|
||||
@using Learn.VideoAnalysis.Controllers.Dto
|
||||
@using SqlSugar
|
||||
@using VideoAnalysisCore.Model
|
||||
@using VideoAnalysisCore.Model.Dto
|
||||
@using VideoAnalysisCore.Enum
|
||||
|
||||
<Table @ref="_table" Loading="tableLoading" TItem="VideoTaskDto" PageSize="15" Total="_total" DataSource="_dataSource" @bind-SelectedRows="_selectedRows" OnChange="OnChange"
|
||||
<Table @ref="_table" Loading="tableLoading" TItem="VideoTaskDto" ScrollY="600px" PageSize="10" Total="_total" DataSource="_dataSource"
|
||||
OnRowClick="(r)=>r.Expanded = !r.Expanded"
|
||||
@bind-SelectedRows="_selectedRows" OnChange="OnChange"
|
||||
OnExpand="OnExpand">
|
||||
<TitleTemplate>
|
||||
<Flex Justify="end" Gap="10">
|
||||
|
|
@ -16,16 +19,16 @@
|
|||
</TitleTemplate>
|
||||
<ColumnDefinitions Context="row">
|
||||
<Selection />
|
||||
<PropertyColumn Property="c=>c.Id" Width="100" Filterable="true" Sortable="true"/>
|
||||
<PropertyColumn Property="c=>c.TagId" Width="100" />
|
||||
<PropertyColumn Property="c=>c.LastEnum" Width="120" />
|
||||
<PropertyColumn Property="c=>c.ApiToken" Width="120" />
|
||||
<PropertyColumn Property="c=>c.ComeFrom" Width="120" />
|
||||
<PropertyColumn Property="c=>c.MediaUrl" Width="300" />
|
||||
<PropertyColumn Property="c=>c.TotalTokens" Width="100" />
|
||||
<PropertyColumn Property="c=>c.Id" Width="130px" Filterable="true" Sortable="true" />
|
||||
<PropertyColumn Property="c=>c.TagId" Width="160px" />
|
||||
<PropertyColumn Property="c=>c.LastEnum" Width="150px" />
|
||||
<PropertyColumn Property="c=>c.ApiToken" Width="150px" />
|
||||
<PropertyColumn Property="c=>c.ComeFrom" Width="100px" />
|
||||
<PropertyColumn Property="c=>c.MediaUrl" Width="320px" />
|
||||
<PropertyColumn Property="c=>c.TotalTokens" Width="100px" />
|
||||
<PropertyColumn Property="c=>c.CreateTime" />
|
||||
</ColumnDefinitions>
|
||||
<ExpandTemplate Context="rowData" >
|
||||
<ExpandTemplate Context="rowData">
|
||||
<Descriptions Title="任务详情" Bordered>
|
||||
|
||||
<DescriptionsItem Title="@rowData.Data.LastEnum.ToString()">
|
||||
|
|
@ -35,10 +38,10 @@
|
|||
<DescriptionsItem Title="操作" Span="2">
|
||||
<Button Type="@ButtonType.Primary"
|
||||
Loading="rowRestartLoading"
|
||||
OnClick="()=>RowRestart(rowData)">
|
||||
OnClick="()=>RowRload(rowData)">
|
||||
刷新数据
|
||||
</Button>
|
||||
<Button Type="@ButtonType.Primary" Danger @onclick="() => ReStart(rowData.Data)">
|
||||
<Button Type="@ButtonType.Primary" Danger @onclick="() => ReStartClick(rowData.Data)">
|
||||
重试
|
||||
</Button>
|
||||
</DescriptionsItem>
|
||||
|
|
@ -46,26 +49,26 @@
|
|||
<DescriptionsItem Title="任务时间轴" Span="5">
|
||||
<Steps Current="@RowSTIndex(rowData)" Status="@RowSTStatus(rowData)">
|
||||
<Step Title="下载文件"
|
||||
Description="@RowST(rowData,RedisChannelEnum.DownloadFile)" />
|
||||
Description="@RowST(rowData,RedisChannelEnum.DownloadFile)" />
|
||||
|
||||
<Step Title="分离音频"
|
||||
Description="@RowST(rowData,RedisChannelEnum.SeparateAudio)" />
|
||||
Description="@RowST(rowData,RedisChannelEnum.SeparateAudio)" />
|
||||
|
||||
<Step Title="解析字幕"
|
||||
Description="@RowST(rowData,RedisChannelEnum.ParsingCaptions)" />
|
||||
Description="@RowST(rowData,RedisChannelEnum.ParsingCaptions)" />
|
||||
|
||||
<Step Title="解析说话人"
|
||||
Description="@RowST(rowData,RedisChannelEnum.ParsingSpeaker)" />
|
||||
Description="@RowST(rowData,RedisChannelEnum.ParsingSpeaker)" />
|
||||
|
||||
<Step Title="Chat模型分析"
|
||||
Description="@RowST(rowData,RedisChannelEnum.ChatModelAnalysis)" />
|
||||
Description="@RowST(rowData,RedisChannelEnum.ChatModelAnalysis)" />
|
||||
|
||||
<Step Title="结束任务"
|
||||
Description="@RowST(rowData,RedisChannelEnum.EndTask)" />
|
||||
Description="@RowST(rowData,RedisChannelEnum.EndTask)" />
|
||||
</Steps>
|
||||
</DescriptionsItem>
|
||||
|
||||
@if (!string.IsNullOrEmpty( @rowData.Data.ErrorMessage))
|
||||
@if (!string.IsNullOrEmpty(@rowData.Data.ErrorMessage))
|
||||
{
|
||||
<DescriptionsItem Title="任务异常" Span="3">
|
||||
@rowData.Data.ErrorMessage
|
||||
|
|
@ -73,6 +76,25 @@
|
|||
}
|
||||
|
||||
</Descriptions>
|
||||
|
||||
|
||||
</ExpandTemplate>
|
||||
</Table>
|
||||
|
||||
<Modal Title="重试任务"
|
||||
Width="400"
|
||||
OnOk="ReStart"
|
||||
@bind-Visible="@modalShow">
|
||||
|
||||
<Title Level="3">ID : @reStartTask.Id</Title>
|
||||
<p></p>
|
||||
<p>将从哪个步骤重试?</p>
|
||||
|
||||
<Select Style="width:220px;"
|
||||
DataSource="SelectDataSource"
|
||||
LabelName="@nameof(TextValue.Text)"
|
||||
ValueName="@nameof(TextValue.Value)"
|
||||
@bind-Value="@selectEnum">
|
||||
</Select>
|
||||
<br />
|
||||
<br />
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using AntDesign;
|
||||
using AntDesign.TableModels;
|
||||
using FFmpeg.NET.Services;
|
||||
using Learn.VideoAnalysis.Controllers.Dto;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.DataProtection.KeyManagement;
|
||||
|
|
@ -28,19 +29,42 @@ namespace Learn.VideoAnalysis.Components.Pages
|
|||
List<VideoTaskDto> _dataSource = null;
|
||||
RefAsync<int> _total = 0;
|
||||
|
||||
bool modalShow = false;
|
||||
|
||||
bool tableLoading = false;
|
||||
private VideoTaskDto selectData;
|
||||
private bool rowRestartLoading=false;
|
||||
private bool rowRestartLoading = false;
|
||||
private VideoTaskDto reStartTask ;
|
||||
|
||||
static TextValue[] SelectDataSource =
|
||||
Enum.GetValues(typeof(RedisChannelEnum))
|
||||
.Cast<RedisChannelEnum>()
|
||||
.Select(s => new TextValue(s.ToString(), (int)s))
|
||||
.ToArray();
|
||||
int selectEnum = 1;
|
||||
int selectDefaultValue =1;
|
||||
|
||||
/// <summary>
|
||||
/// 点击重试
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
async void ReStartClick(VideoTaskDto query)
|
||||
{
|
||||
selectDefaultValue =
|
||||
(await RedisExpand.Redis.HMGetAsync<int>(RedisExpandKey.Task(query.Id), "LastEnum")).FirstOrDefault();
|
||||
selectEnum = selectDefaultValue;
|
||||
reStartTask = query;
|
||||
modalShow = true;
|
||||
}
|
||||
/// <summary>
|
||||
/// 重试
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
async void ReStart(VideoTaskDto query)
|
||||
async void ReStart()
|
||||
{
|
||||
var lastEnum = (await RedisExpand.Redis.HMGetAsync<RedisChannelEnum>(RedisExpandKey.Task(query.Id), "LastEnum")).FirstOrDefault() ;
|
||||
await RedisExpand.SetTaskErrorMessage(query.Id, null);
|
||||
RedisExpand.InsertChannel(lastEnum, query.Id);
|
||||
await RedisExpand.SetTaskErrorMessage(reStartTask.Id, null);
|
||||
RedisExpand.InsertChannel((RedisChannelEnum)selectEnum, reStartTask.Id);
|
||||
modalShow = false;
|
||||
}
|
||||
private QueryModel<VideoTaskDto> lastQuery = null;
|
||||
/// <summary>
|
||||
|
|
@ -51,7 +75,7 @@ namespace Learn.VideoAnalysis.Components.Pages
|
|||
async void ShowErrorTask(MouseEventArgs e)
|
||||
{
|
||||
_dataSource = await taskDB.AsQueryable()
|
||||
.Where(s=>s.ErrorMessage != null &&s.ErrorMessage!=string.Empty)
|
||||
.Where(s => s.ErrorMessage != null && s.ErrorMessage != string.Empty)
|
||||
.Select<VideoTaskDto>()
|
||||
.ToListAsync();
|
||||
_total = _dataSource.Count();
|
||||
|
|
@ -66,7 +90,7 @@ namespace Learn.VideoAnalysis.Components.Pages
|
|||
/// <param name="changed"></param>
|
||||
async void OnChange(QueryModel<VideoTaskDto> query)
|
||||
{
|
||||
lastQuery= query;
|
||||
lastQuery = query;
|
||||
tableLoading = true;
|
||||
List<IConditionalModel> where = default!;
|
||||
if (query.FilterModel != null && ((query.FilterModel?.Count() ?? 0) > 0))
|
||||
|
|
@ -76,13 +100,18 @@ namespace Learn.VideoAnalysis.Components.Pages
|
|||
_dataSource = await taskDB.AsQueryable()
|
||||
.Where(where)
|
||||
.Select<VideoTaskDto>()
|
||||
.ToPageListAsync(query.PageIndex - 1, query.PageSize, _total);
|
||||
.OrderByDescending(s => s.Id)
|
||||
.ToPageListAsync(query.PageIndex , query.PageSize, _total);
|
||||
|
||||
tableLoading = false;
|
||||
StateHasChanged();
|
||||
|
||||
}
|
||||
public void RowRestart(RowData<VideoTaskDto> rowData)
|
||||
/// <summary>
|
||||
/// 刷新数据
|
||||
/// </summary>
|
||||
/// <param name="rowData"></param>
|
||||
public void RowRload(RowData<VideoTaskDto> rowData)
|
||||
{
|
||||
rowRestartLoading = true;
|
||||
var item = rowData.Data;
|
||||
|
|
@ -101,7 +130,7 @@ namespace Learn.VideoAnalysis.Components.Pages
|
|||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private string RowST(RowData<VideoTaskDto> rowData, RedisChannelEnum e)
|
||||
private string RowST(RowData<VideoTaskDto> rowData, RedisChannelEnum e)
|
||||
{
|
||||
var dic = rowData.Data.StartTimeDic;
|
||||
if (dic is null || !dic.ContainsKey(e))
|
||||
|
|
@ -113,22 +142,19 @@ namespace Learn.VideoAnalysis.Components.Pages
|
|||
var dic = rowData.Data.StartTimeDic;
|
||||
if (dic is null)
|
||||
return "wait";
|
||||
if(!string.IsNullOrEmpty(rowData.Data.ErrorMessage))
|
||||
if (!string.IsNullOrEmpty(rowData.Data.ErrorMessage))
|
||||
return "error";
|
||||
if(dic.ContainsKey(RedisChannelEnum.EndTask))
|
||||
if (dic.ContainsKey(RedisChannelEnum.EndTask))
|
||||
return "finish";
|
||||
return "wait";
|
||||
}
|
||||
private int RowSTIndex(RowData<VideoTaskDto> rowData)
|
||||
private int RowSTIndex(RowData<VideoTaskDto> rowData)
|
||||
{
|
||||
var dic = rowData.Data.StartTimeDic;
|
||||
if (dic is null )
|
||||
return 0;
|
||||
return (int)dic.LastOrDefault().Key;
|
||||
return (int)rowData.Data.LastEnum;
|
||||
}
|
||||
private void OnExpand(RowData<VideoTaskDto> rowData)
|
||||
private void OnExpand(RowData<VideoTaskDto> rowData)
|
||||
{
|
||||
RowRestart(rowData);
|
||||
RowRload(rowData);
|
||||
}
|
||||
/// <summary>
|
||||
/// 在渲染页面之后
|
||||
|
|
|
|||
|
|
@ -157,6 +157,8 @@ namespace Learn.VideoAnalysis.Controllers
|
|||
{
|
||||
if (!ModelState.IsValid) return BadRequest(ModelState);
|
||||
|
||||
if(await videoTaskDB.IsAnyAsync(s=>s.TagId == req.TagId) )
|
||||
return BadRequest("重复添加");
|
||||
// 自动映射属性到哈希
|
||||
var task = new VideoTask()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ namespace Learn.VideoAnalysis.Controllers.Dto
|
|||
}
|
||||
public TextValue(string t,object v)
|
||||
{
|
||||
|
||||
Text = t;
|
||||
Value = v;
|
||||
}
|
||||
public TextValue()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Version>1.0.0.0</Version>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<InvariantGlobalization>false</InvariantGlobalization>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,11 @@
|
|||
using VideoAnalysisCore.Common;
|
||||
using VideoAnalysisRazor;
|
||||
using Learn.VideoAnalysis.Components;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using AntDesign.ProLayout;
|
||||
using VideoAnalysisCore.AICore.ChatGPT;
|
||||
using VideoAnalysisCore.AICore.ChatGPT.KIMI;
|
||||
using VideoAnalysisCore.AICore.SherpaOnnx;
|
||||
using SqlSugar;
|
||||
using Mapster;
|
||||
using VideoAnalysisCore.AICore.ChatGPT.Dto;
|
||||
using System.Text.Json;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
|
@ -18,7 +19,34 @@ namespace VideoAnalysisCore.AICore.ChatGPT.Dto
|
|||
/// <summary>
|
||||
/// 结果
|
||||
/// </summary>
|
||||
public JToken 结果 { get; set; }
|
||||
public JsonDocument 结果 { get; set; }
|
||||
|
||||
private object? _cached = null;
|
||||
/// <summary>
|
||||
/// 转换结果为对象
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public T? ToObject<T>()
|
||||
{
|
||||
try
|
||||
{
|
||||
if(_cached != null)
|
||||
return (T)_cached;
|
||||
var r = 结果.RootElement.GetRawText();
|
||||
if (r is null)
|
||||
return default;
|
||||
_cached = System.Text.Json.JsonSerializer.Deserialize<T>(r);
|
||||
|
||||
if (_cached is null)
|
||||
return default;
|
||||
return (T)_cached;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 问题解释
|
||||
/// </summary>
|
||||
|
|
@ -69,8 +97,9 @@ namespace VideoAnalysisCore.AICore.ChatGPT.Dto
|
|||
/// <summary>
|
||||
/// 改进意见
|
||||
/// </summary>
|
||||
public string[]? BadImprovedMethods =>
|
||||
Bad?.Select(s => s.ImprovedMethods??string.Empty)?.ToArray();
|
||||
public string[]? BadImprovedMethods =>
|
||||
(Merit?.Select(s => s.ImprovedMethods??string.Empty)?.ToArray()??[])
|
||||
.Concat(Bad?.Select(s => s.ImprovedMethods ?? string.Empty)?.ToArray() ?? []).ToArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ using VideoAnalysisCore.Enum;
|
|||
using System.Reflection;
|
||||
using FreeRedis;
|
||||
using VideoAnalysisCore.Model.Dto;
|
||||
using Newtonsoft.Json;
|
||||
using AntDesign;
|
||||
using SqlSugar.IOC;
|
||||
|
||||
|
|
@ -57,7 +56,8 @@ namespace VideoAnalysisCore.AICore.ChatGPT.KIMI
|
|||
criteriaBuilder.Append(item.Id);
|
||||
criteriaBuilder.Append(":");
|
||||
criteriaBuilder.Append(item.NamePrompt);
|
||||
criteriaBuilder.Append("请基于解释打分(0-10分 6分为及格) 结果类型 int |");
|
||||
criteriaBuilder.Append("? 请基于解释打分(0-10分 6分为及格) 结果类型 array=[得分,简明的提问的回答,对于问题的详细改进意见,详细的列举出主要扣分原因] |");
|
||||
|
||||
}
|
||||
//拼接枚举提问
|
||||
foreach (var value in System.Enum.GetValues(typeof(QuestionTypeEnum)))
|
||||
|
|
@ -75,6 +75,9 @@ namespace VideoAnalysisCore.AICore.ChatGPT.KIMI
|
|||
|
||||
var resFormat = "[{问题编号:int,结果:array|bool|object,问题解释:string}]";
|
||||
var postMessages =
|
||||
$"你是一个教学经验老道老师对教学工作有着深入的理解和丰富的经验,能够准确把握教学大纲的要求和教学重点。" +
|
||||
$"熟练掌握各种教学管理方法和手段,能够制定科学合理的教学计划和教学评估体系。" +
|
||||
$"善于发现教学中的问题,并能迅速提出有效的解决方案,确保教学工作的顺利进行。" +
|
||||
$"以下是一段音频的字幕,分析这段字幕(格式 说话人:开始秒:结束秒:内容|下一段字幕)." +
|
||||
$"来简明的回答提出的问题 问题列表 {criteriaBuilder} " +
|
||||
$"字幕列表 {captions.Captions} " +
|
||||
|
|
@ -83,10 +86,11 @@ namespace VideoAnalysisCore.AICore.ChatGPT.KIMI
|
|||
if (modelsResp is null || modelsResp.data.Count == 0)
|
||||
throw new Exception("未获取KIMI模型类型");
|
||||
var reqTokenCount = await moonshotClient.GetAsTiMateTokenCount(postMessages);
|
||||
var modelId = reqTokenCount > 32 * 1000 ? "moonshot-v1-128k" : "moonshot-v1-32k";
|
||||
var maxTokens = 4000;
|
||||
var modelId = reqTokenCount > 32 * 1000 - maxTokens ? "moonshot-v1-128k" : "moonshot-v1-32k";
|
||||
var chatRep = new ChatReq
|
||||
{
|
||||
max_tokens = 32*1024 - (reqTokenCount + 20),
|
||||
max_tokens = maxTokens,
|
||||
temperature = 0.3f,
|
||||
frequency_penalty = 0,
|
||||
presence_penalty = 0,
|
||||
|
|
@ -100,14 +104,12 @@ namespace VideoAnalysisCore.AICore.ChatGPT.KIMI
|
|||
RedisExpand.SetTaskGPTCached(task, chatResp);
|
||||
if (chatResp is null || chatResp.error != null)
|
||||
throw new Exception($"KIMI模型返回异常 Chat 返回参数: " +
|
||||
$" {System.Text.Json.JsonSerializer.Serialize(chatResp)}");
|
||||
$" {JsonSerializer.Serialize(chatResp)}");
|
||||
var chatResContent = chatResp?.choices.FirstOrDefault()?.message.content;
|
||||
|
||||
|
||||
chatResContent = chatResContent?.Replace("字幕内容", "课堂");
|
||||
if (chatResContent is null)
|
||||
throw new Exception("KIMIGPT返回message无效结果");
|
||||
|
||||
var questionRes = JsonConvert.DeserializeObject<QuestionRes[]>(chatResContent);
|
||||
var questionRes = JsonSerializer.Deserialize<QuestionRes[]>(chatResContent);
|
||||
var gptRes = new TaskRes(captions);
|
||||
if (questionRes is null)
|
||||
throw new Exception("KIMIGPT返回无效结果");
|
||||
|
|
@ -117,52 +119,48 @@ namespace VideoAnalysisCore.AICore.ChatGPT.KIMI
|
|||
.ToDictionary(s => s.问题编号);
|
||||
//AI综合评估
|
||||
var criteriaDic = criteriaArr.ToDictionary(s => s.Id);
|
||||
|
||||
var ccArr = arr1.Select(s => new CourseCriteria()
|
||||
{
|
||||
Id = criteriaDic[s.问题编号].Id,
|
||||
Score = int.Parse(s.ToObject<object[]>()?[0].ToString() ?? string.Empty),
|
||||
Prompt = s.ToObject<object[]>()?[1].ToString() ?? string.Empty,
|
||||
ImprovedMethods = s.ToObject<object[]>()?[2].ToString() ?? string.Empty,
|
||||
Analyze = s.问题解释 + s.ToObject<object[]>()?[3].ToString() ?? string.Empty,
|
||||
//Analyze = s.问题解释 ?? string.Empty,
|
||||
}).ToArray();
|
||||
gptRes.Assessment = new AssessmentDto()
|
||||
{
|
||||
Bad = arr1.Where(s => s.结果.ToObject<int>() < 6)
|
||||
.Select(s => new CourseCriteria()
|
||||
{
|
||||
Id = criteriaDic[s.问题编号].Id,
|
||||
ImprovedMethods = criteriaDic[s.问题编号].ImprovedMethods,
|
||||
Analyze = s.问题解释 ?? string.Empty,
|
||||
Score = s.结果.ToObject<int>(),
|
||||
Prompt = criteriaDic[s.问题编号].Flaw,
|
||||
}).ToArray(),
|
||||
Merit = arr1.Where(s => s.结果.ToObject<int>() >= 6)
|
||||
.Select(s => new CourseCriteria()
|
||||
{
|
||||
Id = criteriaDic[s.问题编号].Id,
|
||||
Score = s.结果.ToObject<int>(),
|
||||
//ImprovedMethods = criteriaDic[s.问题编号].ImprovedMethods,
|
||||
Analyze = s.问题解释 ?? string.Empty,
|
||||
Prompt = criteriaDic[s.问题编号].Advantage,
|
||||
}).ToArray(),
|
||||
Bad = ccArr.Where(s => s.Score< 6 ).ToArray(),
|
||||
Merit = ccArr.Where(s => s.Score>= 6).ToArray(),
|
||||
};
|
||||
|
||||
//高频词汇
|
||||
gptRes.Hotwords = arr2[(int)QuestionTypeEnum.高频词].结果.ToObject<string[]>() ?? ["暂无数据"];
|
||||
gptRes.Hotwords = arr2[(int)QuestionTypeEnum.高频词].ToObject<string[]>() ?? ["暂无数据"];
|
||||
|
||||
//时间段概览
|
||||
gptRes.TimeOverview = arr2[(int)QuestionTypeEnum.时间段概览]
|
||||
.结果.ToObject<TimeBase[]>();
|
||||
.ToObject<TimeBase[]>();
|
||||
//提问类型
|
||||
gptRes.QuestionType = arr2[(int)QuestionTypeEnum.提问类型]
|
||||
.结果.ToObject<Dictionary<TeacherAnswerTypeEnum, int>>();
|
||||
.ToObject<Dictionary<TeacherAnswerTypeEnum, int>>();
|
||||
|
||||
//分析上课时间段情况 分析 独立学习 小组合作 随堂练习等情况
|
||||
var extraTimeBase = arr2[(int)QuestionTypeEnum.额外课堂情况]
|
||||
.结果.ToObject<TimeBase[]>();
|
||||
.ToObject<TimeBase[]>();
|
||||
if (extraTimeBase is not null)
|
||||
foreach (var item in extraTimeBase)
|
||||
{
|
||||
if (item is null)
|
||||
continue;
|
||||
var r = item.Content.ToEnum<TimeBaseTypeEnum>();
|
||||
if (r is null)
|
||||
continue;
|
||||
var arr = gptRes.TimeBase?
|
||||
.Where(s => s.Start >= item.Start && s.End <= item.End);
|
||||
if (arr is null)
|
||||
continue;
|
||||
foreach (var s in arr)
|
||||
s.TimeBaseType = item.Content.ToEnum<TimeBaseTypeEnum>();
|
||||
s.TimeBaseType = r;
|
||||
}
|
||||
var totalTokens = chatResp?.usage.total_tokens ?? 0;
|
||||
if (totalTokens > 1)
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ namespace VideoAnalysisCore.AICore.ChatGPT.KIMI
|
|||
/// <returns>Return HttpResponseMessage for SSE</returns>
|
||||
public async Task<ChatRes?> Chat(ChatReq chatReq)
|
||||
{
|
||||
var requestBody = Newtonsoft.Json.JsonConvert.SerializeObject(chatReq);
|
||||
var requestBody = System.Text.Json.JsonSerializer.Serialize(chatReq);
|
||||
var chatResp = await PostJsonStreamAsync("/v1/chat/completions", requestBody);
|
||||
return await chatResp.Content.ReadFromJsonAsync<ChatRes>();
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ namespace VideoAnalysisCore.AICore.ChatGPT.KIMI
|
|||
var responseObj = JToken.Parse(responseText);
|
||||
return responseObj?["data"]?["total_tokens"]?.ToObject<int>();
|
||||
}
|
||||
var error = Newtonsoft.Json.JsonConvert.DeserializeObject<ErrorResponse>(responseText);
|
||||
var error = JsonConvert.DeserializeObject<ErrorResponse>(responseText);
|
||||
_logger.LogError($"{error?.error?.type}: {error?.error?.message}");
|
||||
throw new Exception($"{error?.error.type}: {error?.error.message}");
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@ namespace VideoAnalysisCore.AICore.ChatGPT.KIMI
|
|||
/// <returns></returns>
|
||||
public async Task<int?> GetAsTiMateTokenCount(ChatReq chatReq)
|
||||
{
|
||||
var chatReqText = Newtonsoft.Json.JsonConvert.SerializeObject(chatReq);
|
||||
var chatReqText = JsonConvert.SerializeObject(chatReq);
|
||||
return await GetAsTiMateTokenCount(chatReqText);
|
||||
}
|
||||
|
||||
|
|
@ -183,15 +183,16 @@ namespace VideoAnalysisCore.AICore.ChatGPT.KIMI
|
|||
|
||||
private async Task<HttpResponseMessage> PostJsonStreamAsync(string path, string json)
|
||||
{
|
||||
var client = _httpClientFactory.CreateClient();
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ApiKey);
|
||||
var request = ToHttpRequest(path);
|
||||
var maxRestart = 4;
|
||||
var errorMSG = new Exception[maxRestart];
|
||||
for (int i = 0; i < maxRestart; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
var client = _httpClientFactory.CreateClient();
|
||||
client.Timeout = TimeSpan.FromSeconds(60 * 20);//超时时间20分钟
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ApiKey);
|
||||
var request = ToHttpRequest(path);
|
||||
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
return await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
|
||||
}
|
||||
|
|
@ -225,9 +226,9 @@ namespace VideoAnalysisCore.AICore.ChatGPT.KIMI
|
|||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(responseText) ?? default;
|
||||
return JsonConvert.DeserializeObject<T>(responseText) ?? default;
|
||||
}
|
||||
var error = Newtonsoft.Json.JsonConvert.DeserializeObject<ErrorResponse>(responseText);
|
||||
var error = JsonConvert.DeserializeObject<ErrorResponse>(responseText);
|
||||
_logger.LogError($"{error?.error.type}: {error?.error.message}");
|
||||
throw new Exception($"{error?.error.type}: {error?.error.message}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
|
|||
public class SenseVoice
|
||||
{
|
||||
static OfflineRecognizer OR =default!;
|
||||
static VoiceActivityDetector VAD = default!;
|
||||
//static VoiceActivityDetector VAD = default!;
|
||||
static VadModelConfig VADModelConfig = default!;
|
||||
/// <summary>
|
||||
/// 初始化 SenseVoice
|
||||
|
|
@ -71,8 +71,6 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
|
|||
VADModelConfig = new VadModelConfig();
|
||||
VADModelConfig.SileroVad.Model = Path.Combine(AppCommon.AIModelFile, "sherpa-onnx-sense-voice-24-07-17", "silero_vad.onnx");
|
||||
VADModelConfig.Debug = 0;
|
||||
//缓冲区大小
|
||||
VAD = new VoiceActivityDetector(VADModelConfig, 60);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -94,6 +92,9 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
|
|||
int numIter = numSamples / windowSize;
|
||||
var totalSecond = numSamples / (float)sampleRate;
|
||||
var res = new List<SenseVoiceRes>(500);
|
||||
|
||||
//缓冲区大小
|
||||
var VAD = new VoiceActivityDetector(VADModelConfig, 60);
|
||||
//var VAD = new VoiceActivityDetector(VADModelConfig, 60);
|
||||
for (int i = 0; i != numIter; ++i)
|
||||
{
|
||||
|
|
@ -173,7 +174,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
|
|||
int numIter = numSamples / windowSize;
|
||||
var totalSecond = numSamples / (float)sampleRate;
|
||||
var res = new List<SenseVoiceRes>(500);
|
||||
//var VAD = new VoiceActivityDetector(VADModelConfig, 60);
|
||||
var VAD = new VoiceActivityDetector(VADModelConfig, 60);
|
||||
for (int i = 0; i != numIter; ++i)
|
||||
{
|
||||
int start = i * windowSize;
|
||||
|
|
|
|||
|
|
@ -207,9 +207,16 @@ namespace VideoAnalysisCore.Common
|
|||
/// <returns></returns>
|
||||
public static T? ToEnum<T>(this object data) where T : struct, System.Enum
|
||||
{
|
||||
if (data is null || string.IsNullOrEmpty(data?.ToString()))
|
||||
try
|
||||
{
|
||||
if (data is null || string.IsNullOrEmpty(data?.ToString()))
|
||||
return null;
|
||||
return System.Enum.Parse<T>(data.ToString());
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
return System.Enum.Parse<T>(data.ToString());
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 转化本地缓存目录
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ namespace VideoAnalysisCore.Common
|
|||
Redis.Deserialize = (json, type) => System.Text.Json.JsonSerializer.Deserialize(json, type);
|
||||
Task.Run(() =>
|
||||
{
|
||||
Task.Delay(1000 * 5);
|
||||
Task.Delay(1000 * 10);
|
||||
InitChannel();
|
||||
});
|
||||
}
|
||||
|
|
@ -105,7 +105,7 @@ namespace VideoAnalysisCore.Common
|
|||
/// <param name="taskId"></param>
|
||||
public static void SetTaskGPTCached(object taskId, object? data)
|
||||
{
|
||||
Redis.Set(RedisExpandKey.TaskGPT(taskId), data, 3600);
|
||||
Redis.Set(RedisExpandKey.TaskGPT(taskId), data, 3600*24);
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取任务进度
|
||||
|
|
@ -230,14 +230,15 @@ namespace VideoAnalysisCore.Common
|
|||
InsertChannel(lastEnum, oldTask);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Subscribe?.IsUnsubscribed == false)//排除重试机制后 多次接收任务导致内存泄露
|
||||
return;
|
||||
Subscribe = Redis.SubscribeList(RedisExpandKey.ChannelKey, (taskId) =>
|
||||
{
|
||||
if (taskId is null) return;
|
||||
Subscribe?.Dispose();
|
||||
//存储当前机器的任务
|
||||
Redis.Set(RedisExpandKey.IDTask, taskId);
|
||||
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "-> 接收到任务 " + taskId);
|
||||
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "-------------> 接收到任务 " + taskId);
|
||||
InsertChannel(RedisChannelEnum.DownloadFile, taskId);
|
||||
});
|
||||
|
||||
|
|
@ -283,6 +284,7 @@ namespace VideoAnalysisCore.Common
|
|||
var tID = long.Parse(taskId);
|
||||
if (action is not null)
|
||||
{
|
||||
var errArr = new Exception[3];
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "-> 开始执行 " + key + " " + taskId);
|
||||
|
|
@ -299,11 +301,16 @@ namespace VideoAnalysisCore.Common
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errArr[i] = ex;
|
||||
Console.WriteLine("====================[出现异常]====================");
|
||||
Console.WriteLine(ex.Message);
|
||||
Console.WriteLine(ex.StackTrace);
|
||||
Console.WriteLine("==============================================");
|
||||
Thread.Sleep(1000);
|
||||
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "-> 稍后后重试." + key + " " + taskId );
|
||||
await SetTaskErrorMessage(tID, ex);
|
||||
}
|
||||
}
|
||||
await SetTaskErrorMessage(tID, errArr.First());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace VideoAnalysisCore.Enum
|
||||
{
|
||||
enum QuestionTypeEnum
|
||||
public enum QuestionTypeEnum
|
||||
{
|
||||
|
||||
[Display(Prompt = "分析授课中使用的高频词" +
|
||||
"10个频率从高到低 结果类型[]")]
|
||||
高频词 = 100,
|
||||
[Display(Prompt = "基于字幕内容知识点精准的划分成最多10个片段" +
|
||||
"提取片段的内容概览,字幕开始秒,结束秒 结果类型[{Start:开始秒,End:结束秒,Content:概览}]")]
|
||||
[Display(Prompt = "基于字幕描述内容精准的划分成时间片段" +
|
||||
",提取片段的内容概览,字幕开始秒,结束秒.作为返回结果.每个个片段不低于120秒 结果类型[{Start:开始秒,End:结束秒,Content:概览}]")]
|
||||
时间段概览 = 101,
|
||||
[Display(Prompt = "统计授课中教师回答类型的次数 回答类型" +
|
||||
"[重复回答,老师追问,简单性表扬,老师补充答案,表扬并补充答案] 结果类型{回答类型:次数}")]
|
||||
|
|
|
|||
Loading…
Reference in New Issue