Compare commits

...

9 Commits

15 changed files with 200 additions and 108 deletions

View File

@ -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 = "确定",

View File

@ -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();

View File

@ -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>

View File

@ -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>
/// 在渲染页面之后

View File

@ -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()
{

View File

@ -49,7 +49,8 @@ namespace Learn.VideoAnalysis.Controllers.Dto
}
public TextValue(string t,object v)
{
Text = t;
Value = v;
}
public TextValue()
{

View File

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>1.0.0.0</Version>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>false</InvariantGlobalization>

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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)

View File

@ -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}");
}

View File

@ -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;

View File

@ -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>
/// 转化本地缓存目录

View File

@ -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
{

View File

@ -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 = "统计授课中教师回答类型的次数 回答类型" +
"[重复回答,老师追问,简单性表扬,老师补充答案,表扬并补充答案] 结果类型{回答类型:次数}")]