parent
73d4fbd8c1
commit
d12839be20
|
|
@ -101,7 +101,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE
|
||||||
keyFrames[i] = -1;
|
keyFrames[i] = -1;
|
||||||
}
|
}
|
||||||
//写入数据库
|
//写入数据库
|
||||||
var keyFramStr = JsonSerializer.Serialize(keyFrames.Where(s=>s!=-1));
|
var keyFramStr = keyFrames.Where(s => s != -1).ToJson();
|
||||||
await DbScoped.Sugar
|
await DbScoped.Sugar
|
||||||
.Updateable<VideoTask>()
|
.Updateable<VideoTask>()
|
||||||
.SetColumns(it => it.PPTKeyFrame == keyFramStr)
|
.SetColumns(it => it.PPTKeyFrame == keyFramStr)
|
||||||
|
|
|
||||||
|
|
@ -32,47 +32,6 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
|
||||||
public async Task<(Usage u, string res)?> ChatSSE(ChatRequest chatReq)
|
public async Task<(Usage u, string res)?> ChatSSE(ChatRequest chatReq)
|
||||||
{
|
{
|
||||||
throw new Exception($"未实现");
|
throw new Exception($"未实现");
|
||||||
//chatReq.stream = true;
|
|
||||||
var requestBody = System.Text.Json.JsonSerializer.Serialize(chatReq);
|
|
||||||
var chatResp = await PostJsonStreamAsync("/v1/chat/completions", requestBody);
|
|
||||||
using var stream = await chatResp.Content.ReadAsStreamAsync();
|
|
||||||
using var reader = new StreamReader(stream, Encoding.UTF8);
|
|
||||||
string line;
|
|
||||||
StringBuilder messageBuilder = new StringBuilder();
|
|
||||||
ChatRes lastChat = new ChatRes();
|
|
||||||
|
|
||||||
//while ((line = await reader.ReadLineAsync()) != null)
|
|
||||||
//{
|
|
||||||
// if (line.EndsWith("[DONE]"))
|
|
||||||
// {
|
|
||||||
// // 表示一条消息结束
|
|
||||||
// string message = messageBuilder.ToString();
|
|
||||||
// messageBuilder.Clear();
|
|
||||||
// var u = lastChat?.choices?.FirstOrDefault()?.usage;
|
|
||||||
// if (u == null || string.IsNullOrEmpty(message))
|
|
||||||
// return null;
|
|
||||||
// return (u, message);
|
|
||||||
// }
|
|
||||||
// else if (line.StartsWith("data:"))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var data = System.Text.Json.JsonSerializer.Deserialize<ChatRes>(line.Substring("data:".Length).Trim());
|
|
||||||
// lastChat = data;
|
|
||||||
// var str = data?.choices.FirstOrDefault()?.delta.content;
|
|
||||||
// if (!string.IsNullOrEmpty(str))
|
|
||||||
// messageBuilder.Append(str);
|
|
||||||
// }
|
|
||||||
// catch (Exception e)
|
|
||||||
// {
|
|
||||||
// Console.WriteLine("异常 ChatSSE=>");
|
|
||||||
// Console.WriteLine(line);
|
|
||||||
// Console.WriteLine(e.Message);
|
|
||||||
// Console.WriteLine(e.StackTrace);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -82,14 +41,14 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
|
||||||
/// <returns>Return HttpResponseMessage for SSE</returns>
|
/// <returns>Return HttpResponseMessage for SSE</returns>
|
||||||
public async Task<(Usage u, string res)?> Chat(ChatRequest chatReq)
|
public async Task<(Usage u, string res)?> Chat(ChatRequest chatReq)
|
||||||
{
|
{
|
||||||
var requestBody = System.Text.Json.JsonSerializer.Serialize(chatReq);
|
var requestBody = chatReq.ToJson();
|
||||||
var chatResp = await PostJsonStreamAsync("v1/chat/completions", requestBody);
|
var chatResp = await PostJsonStreamAsync("v1/chat/completions", requestBody);
|
||||||
var res = await chatResp.Content.ReadFromJsonAsync<ChatRes>();
|
var res = await chatResp.Content.ReadFromJsonAsync<ChatRes>();
|
||||||
var chatResContent = res?.choices.FirstOrDefault()?.message.content.Trim();
|
var chatResContent = res?.choices.FirstOrDefault()?.message.content.Trim();
|
||||||
|
|
||||||
if (res is null || res.error != null)
|
if (res is null || res.error != null)
|
||||||
throw new Exception($" ChatGPT模型返回异常 返回参数: " +
|
throw new Exception($" ChatGPT模型返回异常 返回参数: " +
|
||||||
$" {System.Text.Json.JsonSerializer.Serialize(res)}");
|
$" {res?.ToJson()}");
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(chatResContent))
|
if (string.IsNullOrEmpty(chatResContent))
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
//chatReq.model = "deepseek-r1";
|
//chatReq.model = "deepseek-r1";
|
||||||
if (chatReq.stream) return await ChatSSE(chatReq);
|
if (chatReq.stream) return await ChatSSE(chatReq);
|
||||||
postStar:
|
postStar:
|
||||||
var requestBody = System.Text.Json.JsonSerializer.Serialize(chatReq);
|
var requestBody = chatReq.ToJson();
|
||||||
HttpResponseMessage chatResp = PostJsonStream(Path, requestBody);
|
HttpResponseMessage chatResp = PostJsonStream(Path, requestBody);
|
||||||
var res1 = await chatResp.Content.ReadAsStringAsync();
|
var res1 = await chatResp.Content.ReadAsStringAsync();
|
||||||
if (res1 == null || string.IsNullOrEmpty(res1)|| !chatResp.IsSuccessStatusCode)
|
if (res1 == null || string.IsNullOrEmpty(res1)|| !chatResp.IsSuccessStatusCode)
|
||||||
|
|
@ -65,7 +65,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
var res = await chatResp.Content.ReadFromJsonAsync<ChatRes>();
|
var res = await chatResp.Content.ReadFromJsonAsync<ChatRes>();
|
||||||
if (res is null || res.error != null)
|
if (res is null || res.error != null)
|
||||||
throw new Exception($" GPT模型返回异常 返回参数: " +
|
throw new Exception($" GPT模型返回异常 返回参数: " +
|
||||||
$" {System.Text.Json.JsonSerializer.Serialize(res)}");
|
$" {res.ToJson()}");
|
||||||
var d = thinkMSG(res?.choices.FirstOrDefault()?.message);
|
var d = thinkMSG(res?.choices.FirstOrDefault()?.message);
|
||||||
var chatResContent = d.m1;
|
var chatResContent = d.m1;
|
||||||
var chatResReasoning = d.m2;
|
var chatResReasoning = d.m2;
|
||||||
|
|
@ -136,7 +136,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
/// <returns>Return HttpResponseMessage for SSE</returns>
|
/// <returns>Return HttpResponseMessage for SSE</returns>
|
||||||
public async Task<(Usage u, string res, string reasoning)?> ChatSSE(ChatRequest chatReq)
|
public async Task<(Usage u, string res, string reasoning)?> ChatSSE(ChatRequest chatReq)
|
||||||
{
|
{
|
||||||
var requestBody = System.Text.Json.JsonSerializer.Serialize(chatReq);
|
var requestBody = chatReq.ToJson();
|
||||||
PostJsonStream:
|
PostJsonStream:
|
||||||
var chatResp = PostJsonStream(string.Empty, requestBody);
|
var chatResp = PostJsonStream(string.Empty, requestBody);
|
||||||
if (!chatResp.IsSuccessStatusCode)
|
if (!chatResp.IsSuccessStatusCode)
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
/// 获取内容对应的章节
|
/// 获取内容对应的章节
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task<List<VideoKonwPoint>> GetVideoKnow(List<VideoKnowRes> questionRes, VideoTask taskInfo,
|
private async Task<List<VideoKonwPoint>> GetVideoKnow(VideoKnowRes[] questionRes, VideoTask taskInfo,
|
||||||
string sections, List<KnowledgeInfo> knowledgeInfos)
|
string sections, List<KnowledgeInfo> knowledgeInfos)
|
||||||
{
|
{
|
||||||
var knows = string.Join(',', knowledgeInfos.Select(s => s.Id + "|" + s.Name));
|
var knows = string.Join(',', knowledgeInfos.Select(s => s.Id + "|" + s.Name));
|
||||||
|
|
@ -67,8 +67,8 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
.GroupBy(s => s.Name)
|
.GroupBy(s => s.Name)
|
||||||
.ToDictionary(s => s.First().Name, s => s.First().Id);
|
.ToDictionary(s => s.First().Name, s => s.First().Id);
|
||||||
questionRes = questionRes.Where(s => s != null)
|
questionRes = questionRes.Where(s => s != null)
|
||||||
.OrderBy(s => s.StartTime).ToList();
|
.OrderBy(s => s.StartTime).ToArray();
|
||||||
var thems = JsonSerializer.Serialize(questionRes.Adapt<VideoKnowQueryDto[]>());// string.Join(',', questionRes.Select(s => s.StartTime + "->" + s.Theme));
|
var thems = questionRes.Adapt<VideoKnowQueryDto[]>().ToJson();
|
||||||
var checkResFormat1 = """[{"StartTime":开始秒(number),"KnowPoint":知识点名称(string),"KnowPointId":知识点Id(string)}]""";
|
var checkResFormat1 = """[{"StartTime":开始秒(number),"KnowPoint":知识点名称(string),"KnowPointId":知识点Id(string)}]""";
|
||||||
var knowMessages =
|
var knowMessages =
|
||||||
$"我针对{taskInfo.Subject}课堂授课视频分析出了视频的授课阶段片段。" +
|
$"我针对{taskInfo.Subject}课堂授课视频分析出了视频的授课阶段片段。" +
|
||||||
|
|
@ -94,7 +94,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
s =>
|
s =>
|
||||||
{
|
{
|
||||||
var ks = s.KnowPoint.Split(",").Distinct();
|
var ks = s.KnowPoint.Split(",").Distinct();
|
||||||
var StageId=Yitter.IdGenerator.YitIdHelper.NextId();
|
var StageId = Yitter.IdGenerator.YitIdHelper.NextId();
|
||||||
return ks.Where(x => knowDic.ContainsKey(x))
|
return ks.Where(x => knowDic.ContainsKey(x))
|
||||||
.Select(x => new VideoKonwPoint()
|
.Select(x => new VideoKonwPoint()
|
||||||
{
|
{
|
||||||
|
|
@ -160,11 +160,11 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
/// 检查AI切片结果质量
|
/// 检查AI切片结果质量
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task<CheckMessageDto> VerifySpanQuality(List<VideoKnowRes> questionRes, VideoTask taskInfo, TotalCaptionsDto captions, string sections, int course_Id)
|
private async Task<CheckMessageDto> VerifySpanQuality(VideoKnowRes[] questionRes, VideoTask taskInfo, TotalCaptionsDto captions, string sections, int course_Id)
|
||||||
{
|
{
|
||||||
//校验结果质量
|
//校验结果质量
|
||||||
var thems = JsonSerializer.Serialize(questionRes.Adapt<VideoKnowQueryDto[]>());
|
var thems = questionRes.Adapt<VideoKnowQueryDto[]>().ToJson();
|
||||||
var pptFormat = taskInfo.VideoType==AttachmentsInfoType.复习
|
var pptFormat = taskInfo.VideoType == AttachmentsInfoType.复习
|
||||||
? "这堂课是习题课,所讲解内容都是试题。"
|
? "这堂课是习题课,所讲解内容都是试题。"
|
||||||
: string.Empty;
|
: string.Empty;
|
||||||
var checkResFormat = """{"Score":打分(number),"Evaluation":评价(string)""";//,"Data":优化后的分段(array)}""";
|
var checkResFormat = """{"Score":打分(number),"Evaluation":评价(string)""";//,"Data":优化后的分段(array)}""";
|
||||||
|
|
@ -206,7 +206,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
.Take(spanCount);
|
.Take(spanCount);
|
||||||
if (cArr.Count() == 0)
|
if (cArr.Count() == 0)
|
||||||
return;
|
return;
|
||||||
var nowCaptionStr =JsonSerializer.Serialize(cArr.Select(s =>s.Text));
|
var nowCaptionStr = cArr.Select(s => s.Text).ToJson();
|
||||||
var resFormat = """[string(修改结果)]""";
|
var resFormat = """[string(修改结果)]""";
|
||||||
var postMessages =
|
var postMessages =
|
||||||
$"这是一堂中国{subject}课堂的字幕,由结果是语音识别提供。" +
|
$"这是一堂中国{subject}课堂的字幕,由结果是语音识别提供。" +
|
||||||
|
|
@ -219,11 +219,11 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
$"`{nowCaptionStr}`" +
|
$"`{nowCaptionStr}`" +
|
||||||
$"字幕结束。" +
|
$"字幕结束。" +
|
||||||
$"最后请确保输出字幕条数与输入字幕条数一致!!! 如果不一致则重新优化并且确保字幕条数一致!!!!";
|
$"最后请确保输出字幕条数与输入字幕条数一致!!! 如果不一致则重新优化并且确保字幕条数一致!!!!";
|
||||||
Console.WriteLine(DateTime.Now + $"=>字幕优化 分段{s}/{totalCount}开始...");
|
Console.WriteLine(DateTime.Now + $"=>{taskInfo.Id}字幕优化 分段{s}开始...");
|
||||||
var resData = await ChatAsync<string[]>(taskInfo.Id.ToString(), postMessages, "优化字幕", "deepseek-chat");
|
var resData = await ChatAsync<string[]>(taskInfo.Id.ToString(), postMessages, "优化字幕", "deepseek-chat", 3000);
|
||||||
if (resData.Count() != cArr.Count())
|
if (resData.Count() != cArr.Count())
|
||||||
{
|
{
|
||||||
Console.WriteLine(DateTime.Now + $"=>字幕优化 分段{s}/{totalCount} AI结果数量不匹配,重试");
|
Console.WriteLine(DateTime.Now + $"=>{taskInfo.Id}字幕优化 分段{s} AI结果数量不匹配,重试×");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
newCaptionsList.AddRange(resData.Select((text, i) => new SenseVoiceRes()
|
newCaptionsList.AddRange(resData.Select((text, i) => new SenseVoiceRes()
|
||||||
|
|
@ -232,13 +232,13 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
End = captionsArr[spanCount * s + i].End,
|
End = captionsArr[spanCount * s + i].End,
|
||||||
Text = text,
|
Text = text,
|
||||||
}));
|
}));
|
||||||
Console.WriteLine(DateTime.Now + $"=>字幕优化 分段{s}/{totalCount}完成√");
|
Console.WriteLine(DateTime.Now + $"=>{taskInfo.Id}字幕优化 分段{s}完成√ ");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var res = newCaptionsList.OrderBy(s => s.Start).ToArray();
|
var res = newCaptionsList.OrderBy(s => s.Start).ToArray();
|
||||||
Console.WriteLine(DateTime.Now + $"=>字幕优化执行完成");
|
Console.WriteLine(DateTime.Now + $"=>字幕优化执行完成");
|
||||||
var jsonData = JsonSerializer.Serialize(res);
|
var jsonData = res.ToJson();
|
||||||
await videoTaskDB.AsUpdateable()
|
await videoTaskDB.AsUpdateable()
|
||||||
.SetColumns(it => it.CaptionsAI == jsonData)
|
.SetColumns(it => it.CaptionsAI == jsonData)
|
||||||
.Where(it => it.Id == taskInfo.Id)
|
.Where(it => it.Id == taskInfo.Id)
|
||||||
|
|
@ -250,11 +250,11 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
/// 视频AI分析字幕
|
/// 视频AI分析字幕
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task Analytics(List<VideoKnowRes> questionRes, VideoTask taskInfo,
|
private async Task<VideoKnowRes[]> Analytics(VideoTask taskInfo,
|
||||||
TotalCaptionsDto captions, string sections)
|
TotalCaptionsDto captions, string sections)
|
||||||
{
|
{
|
||||||
var tryCount = 10;
|
var tryCount = 10;
|
||||||
while (tryCount-->0)
|
while (tryCount-- > 0)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -300,15 +300,12 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
break;
|
break;
|
||||||
case AttachmentsInfoType.活动:
|
case AttachmentsInfoType.活动:
|
||||||
case AttachmentsInfoType.班会:
|
case AttachmentsInfoType.班会:
|
||||||
throw new Exception("无效的课程类型");
|
|
||||||
default:
|
default:
|
||||||
break;
|
throw new Exception("无效的课程类型");
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine(DateTime.Now + $"=>{taskInfo.Id.ToString()}.开始分析视频内容 {tryCount}");
|
Console.WriteLine(DateTime.Now + $"=>{taskInfo.Id.ToString()}.开始分析视频内容 {tryCount}");
|
||||||
var resData = await ChatAsync<VideoKnowRes[]>(taskInfo.Id.ToString(), postMessages, "分析字幕");
|
return await ChatAsync<VideoKnowRes[]>(taskInfo.Id.ToString(), postMessages, "分析字幕");
|
||||||
questionRes.AddRange(resData);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -317,10 +314,21 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
Console.WriteLine(DateTime.Now + ex.StackTrace);
|
Console.WriteLine(DateTime.Now + ex.StackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
public async Task<T> ChatAsync<T>(string task, string postMessages, string title, string model = "deepseek-reasoner")
|
///
|
||||||
|
/// </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 = "deepseek-reasoner", int max_tokens = -1)
|
||||||
{
|
{
|
||||||
Message[] messageArr = [
|
Message[] messageArr = [
|
||||||
new Message(postMessages,"user"),
|
new Message(postMessages,"user"),
|
||||||
|
|
@ -330,24 +338,27 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
{
|
{
|
||||||
taskId = task,
|
taskId = task,
|
||||||
model = model,
|
model = model,
|
||||||
max_tokens= model== "deepseek-reasoner"?16000:8000,
|
max_tokens = model == "deepseek-reasoner" ? 16000 : 8000,
|
||||||
stream = true,
|
stream = true,
|
||||||
temperature = 0.2f,
|
temperature = 0.2f,
|
||||||
messages = messageArr
|
messages = messageArr
|
||||||
};
|
};
|
||||||
|
if (max_tokens != -1)
|
||||||
|
chatRep.max_tokens = max_tokens;
|
||||||
var tryCount = 10;
|
var tryCount = 10;
|
||||||
while (--tryCount > 0)
|
while (--tryCount > 0)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var time = title+DateTime.Now.ToString("MMddHHmmss");
|
var time = title + DateTime.Now.ToString("MMddHHmmss");
|
||||||
var redisCached = new object[2] { chatRep, null };
|
var redisCached = new object[2] { chatRep, null };
|
||||||
RedisExpand.SetTaskGPTCached(task, time,chatRep);
|
RedisExpand.SetTaskGPTCached(task, time, chatRep);
|
||||||
var chatResp = await chatClient.Chat(chatRep);
|
var chatResp = await chatClient.Chat(chatRep);
|
||||||
var chatResContent = chatResp?.res;
|
var chatResContent = chatResp?.res;
|
||||||
if (string.IsNullOrEmpty(chatResContent))
|
if (string.IsNullOrEmpty(chatResContent))
|
||||||
throw new Exception("GPT返回message无效结果");
|
throw new Exception("GPT返回message无效结果");
|
||||||
if (chatResp != null) {
|
if (chatResp != null)
|
||||||
|
{
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
@ -359,6 +370,8 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
chatResContent = chatResContent?.Replace("}|{", "},{");
|
chatResContent = chatResContent?.Replace("}|{", "},{");
|
||||||
chatResContent = chatResContent?.Trim();
|
chatResContent = chatResContent?.Trim();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(chatResContent))
|
||||||
|
throw new Exception("ChatGPT返回结果无有效JSON");
|
||||||
var startsStr = typeof(T).IsArray ? "[" : "{";
|
var startsStr = typeof(T).IsArray ? "[" : "{";
|
||||||
var endStr = typeof(T).IsArray ? "]" : "}";
|
var endStr = typeof(T).IsArray ? "]" : "}";
|
||||||
if (!chatResContent.StartsWith(startsStr))
|
if (!chatResContent.StartsWith(startsStr))
|
||||||
|
|
@ -404,17 +417,17 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
var videoKnowDic = knowledgeInfos
|
var videoKnowDic = knowledgeInfos
|
||||||
.GroupBy(s => s.Id)
|
.GroupBy(s => s.Id)
|
||||||
.ToDictionary(s => s.Key, s => s.First());
|
.ToDictionary(s => s.Key, s => s.First());
|
||||||
var insertData =new List<VideoQuestionOSSDto>();
|
var insertData = new List<VideoQuestionOSSDto>();
|
||||||
var insertQuestionKonw = new List<VideoQuestionKonw>();
|
var insertQuestionKonw = new List<VideoQuestionKonw>();
|
||||||
foreach (var item in farmeArr)
|
foreach (var item in farmeArr)
|
||||||
{
|
{
|
||||||
var knowInfoArr = videoKnowArr
|
var knowInfoArr = videoKnowArr
|
||||||
.Where(s => item+20 >= s.StartTime && item <= s.EndTime)
|
.Where(s => item + 20 >= s.StartTime && item <= s.EndTime)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
if (knowInfoArr is null || knowInfoArr.Count() ==0)
|
if (knowInfoArr is null || knowInfoArr.Count() == 0)
|
||||||
continue;
|
continue;
|
||||||
var tryCount = 50;
|
var tryCount = 50;
|
||||||
while (tryCount>1)
|
while (tryCount > 1)
|
||||||
{
|
{
|
||||||
tryCount--;
|
tryCount--;
|
||||||
try
|
try
|
||||||
|
|
@ -424,10 +437,10 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
.ProcessImageAsync(new SimpleTexOcrRequest(filePath));
|
.ProcessImageAsync(new SimpleTexOcrRequest(filePath));
|
||||||
if (!sRes.Success)
|
if (!sRes.Success)
|
||||||
continue;
|
continue;
|
||||||
if(sRes.Result.res.value.Trim().Length<10)//总试题内容长度小于10 视为无效题目
|
if (sRes.Result.res.value.Trim().Length < 10)//总试题内容长度小于10 视为无效题目
|
||||||
break;
|
break;
|
||||||
Console.WriteLine(DateTime.Now + $"=>{taskInfo.Id} 提取{knowInfoArr.First().StartTime}秒试题的试题内容");
|
Console.WriteLine(DateTime.Now + $"=>{taskInfo.Id} 提取{knowInfoArr.First().StartTime}秒试题的试题内容");
|
||||||
Console.WriteLine( sRes.Result.res.value);
|
Console.WriteLine(sRes.Result.res.value);
|
||||||
//var knowArr=JsonSerializer.Serialize(knowInfoArr.Select(s => new { s.KnowPointId, s.KnowPoint }));
|
//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 resFormat = """[{"Type":string(试题类型),"TopicStem":string(试题题干),"QuestionArr":[{"Question":string(子问题),"KnowPointId":(string)知识点ID}]}]""";
|
||||||
var postMessages =
|
var postMessages =
|
||||||
|
|
@ -444,7 +457,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
$"`{sRes.Result.res.value}`";
|
$"`{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");
|
||||||
//var resData = await ChatAsync<VideoQuestionOSSDto[]>(taskInfo.Id.ToString(), postMessages, "提取试题");
|
//var resData = await ChatAsync<VideoQuestionOSSDto[]>(taskInfo.Id.ToString(), postMessages, "提取试题");
|
||||||
if(resData is null || resData.Count()==0)
|
if (resData is null || resData.Count() == 0)
|
||||||
break;
|
break;
|
||||||
foreach (var q in resData)
|
foreach (var q in resData)
|
||||||
{
|
{
|
||||||
|
|
@ -460,13 +473,13 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
vq.Question = qt.Question;
|
vq.Question = qt.Question;
|
||||||
vq.TopicId = TopicId;
|
vq.TopicId = TopicId;
|
||||||
vq.Type = q.Type;
|
vq.Type = q.Type;
|
||||||
if(string.IsNullOrEmpty(qt.KnowPointId))
|
if (string.IsNullOrEmpty(qt.KnowPointId))
|
||||||
continue;//重试
|
continue;//重试
|
||||||
insertData.Add(vq);
|
insertData.Add(vq);
|
||||||
foreach (var kid in qt.KnowPointId.Split(","))
|
foreach (var kid in qt.KnowPointId.Split(","))
|
||||||
{
|
{
|
||||||
var tryOk = int.TryParse(kid.Split("|").First(),out int kidd);
|
var tryOk = int.TryParse(kid.Split("|").First(), out int kidd);
|
||||||
if(!tryOk || !videoKnowDic.ContainsKey(kidd))
|
if (!tryOk || !videoKnowDic.ContainsKey(kidd))
|
||||||
continue;//跳过未识别知识点
|
continue;//跳过未识别知识点
|
||||||
insertQuestionKonw.Add(new VideoQuestionKonw()
|
insertQuestionKonw.Add(new VideoQuestionKonw()
|
||||||
{
|
{
|
||||||
|
|
@ -491,7 +504,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
ossClient.AddVideoQuestionUrl(insertData);
|
ossClient.AddVideoQuestionUrl(insertData);
|
||||||
|
|
||||||
await videoQuestionDB.AsDeleteable()
|
await videoQuestionDB.AsDeleteable()
|
||||||
.Where(s=>s.VideoTaskId== taskInfo.Id)
|
.Where(s => s.VideoTaskId == taskInfo.Id)
|
||||||
.ExecuteCommandAsync();
|
.ExecuteCommandAsync();
|
||||||
await videoQuestionKonwDB.AsDeleteable()
|
await videoQuestionKonwDB.AsDeleteable()
|
||||||
.Where(s => s.VideoTaskId == taskInfo.Id)
|
.Where(s => s.VideoTaskId == taskInfo.Id)
|
||||||
|
|
@ -525,7 +538,17 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
Course_Id = 27;
|
Course_Id = 27;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
switch (taskInfo?.VideoType)
|
||||||
|
{
|
||||||
|
case AttachmentsInfoType.其他资料:
|
||||||
|
case AttachmentsInfoType.新课:
|
||||||
|
case AttachmentsInfoType.复习:
|
||||||
|
break;
|
||||||
|
case AttachmentsInfoType.活动:
|
||||||
|
case AttachmentsInfoType.班会:
|
||||||
|
default:
|
||||||
|
throw new Exception("无效的课程类型");
|
||||||
|
}
|
||||||
|
|
||||||
var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.Captions);
|
var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.Captions);
|
||||||
//处理视频授课章节
|
//处理视频授课章节
|
||||||
|
|
@ -543,16 +566,16 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
//合并字幕
|
//合并字幕
|
||||||
var captions = ExpandFunction.GetSpeakerCaptions(captionsArr);
|
var captions = ExpandFunction.GetSpeakerCaptions(captionsArr);
|
||||||
var maxVideoTime = captions?.TimeBase?.LastOrDefault()?.End ?? 0;
|
var maxVideoTime = captions?.TimeBase?.LastOrDefault()?.End ?? 0;
|
||||||
var questionRes = new List<VideoKnowRes>();
|
VideoKnowRes[]? questionRes =null;
|
||||||
while (true)
|
var tryCount = 20;
|
||||||
|
while (tryCount-- > 0)
|
||||||
{
|
{
|
||||||
questionRes = new List<VideoKnowRes>();
|
|
||||||
//视频字幕分析
|
//视频字幕分析
|
||||||
await Analytics(questionRes, taskInfo, captions, sections);
|
questionRes = await Analytics(taskInfo, captions, sections);
|
||||||
|
|
||||||
if (questionRes.Count == 0) continue;
|
if (questionRes is null) continue;
|
||||||
//处理分段 知识点
|
//处理分段 知识点
|
||||||
var insertData = await GetVideoKnow(questionRes, taskInfo, sections, knowledgeInfos);
|
var insertData = await GetVideoKnow(questionRes, taskInfo, sections, knowledgeInfos);
|
||||||
//校验结果质量
|
//校验结果质量
|
||||||
var checkRes = await VerifySpanQuality(questionRes, taskInfo, captions, sections, Course_Id);
|
var checkRes = await VerifySpanQuality(questionRes, taskInfo, captions, sections, Course_Id);
|
||||||
|
|
||||||
|
|
@ -575,7 +598,10 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (tryCount == 0)
|
||||||
|
{
|
||||||
|
throw new Exception("重试次数过多!");
|
||||||
|
}
|
||||||
await RedisExpand.Redis
|
await RedisExpand.Redis
|
||||||
.HMSetAsync(RedisExpandKey.Task(task), "VideoKnows", questionRes);
|
.HMSetAsync(RedisExpandKey.Task(task), "VideoKnows", questionRes);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
|
||||||
if (!string.IsNullOrEmpty(task))
|
if (!string.IsNullOrEmpty(task))
|
||||||
{
|
{
|
||||||
Console.WriteLine(DateTime.Now + "=> SenseVoice 字幕数量" + res.Count);
|
Console.WriteLine(DateTime.Now + "=> SenseVoice 字幕数量" + res.Count);
|
||||||
var captionsStr = JsonSerializer.Serialize(res);
|
var captionsStr = res.ToJson();
|
||||||
await DbScoped.Sugar
|
await DbScoped.Sugar
|
||||||
.Updateable<VideoTask>()
|
.Updateable<VideoTask>()
|
||||||
.SetColumns(it => it.Captions == captionsStr)
|
.SetColumns(it => it.Captions == captionsStr)
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
|
||||||
}, nint.Zero);
|
}, nint.Zero);
|
||||||
var res = segments.Select(s => new OfflineSpeakerRes(s));
|
var res = segments.Select(s => new OfflineSpeakerRes(s));
|
||||||
await RedisExpand.Redis.HSetAsync(RedisExpandKey.Task(task), "Speaker", res);
|
await RedisExpand.Redis.HSetAsync(RedisExpandKey.Task(task), "Speaker", res);
|
||||||
var speakerStr = JsonSerializer.Serialize(res);
|
var speakerStr = res.ToJson();
|
||||||
await DbScoped.Sugar
|
await DbScoped.Sugar
|
||||||
.Updateable<VideoTask>()
|
.Updateable<VideoTask>()
|
||||||
.SetColumns(it => it.Speaker == speakerStr)
|
.SetColumns(it => it.Speaker == speakerStr)
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ namespace VideoAnalysisCore.Common
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 程序配置
|
/// 程序配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -83,8 +82,9 @@ namespace VideoAnalysisCore.Common
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 拓展函数
|
/// 拓展函数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ExpandFunction
|
public static class ExpandFunction
|
||||||
{
|
{
|
||||||
|
|
||||||
static Dictionary<string, string> FormulaData;
|
static Dictionary<string, string> FormulaData;
|
||||||
static string FormulaDataKey;
|
static string FormulaDataKey;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -92,15 +92,31 @@ namespace VideoAnalysisCore.Common
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string FrameName = "frame_";
|
public static string FrameName = "frame_";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对象转化为JSON字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="o">拓展对象</param>
|
||||||
|
/// <param name="WriteIndented">美化输出?</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string ToJson(this object o, bool WriteIndented = false)
|
||||||
|
{
|
||||||
|
var jsonOptions = new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||||
|
WriteIndented = WriteIndented // 如果需要美化输出
|
||||||
|
};
|
||||||
|
return JsonSerializer.Serialize(o, jsonOptions);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取视频帧文件资源路径
|
/// 获取视频帧文件资源路径
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="task"></param>
|
/// <param name="task"></param>
|
||||||
/// <param name="fTime">帧文件 对应的时间轴</param>
|
/// <param name="fTime">帧文件 对应的时间轴</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string FramePath(this VideoTask task, int fTime)
|
public static string FramePath(this VideoTask task, int fTime)
|
||||||
{
|
{
|
||||||
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>
|
/// <summary>
|
||||||
|
|
@ -110,10 +126,10 @@ namespace VideoAnalysisCore.Common
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string HandleFormula(string f)
|
public static string HandleFormula(string f)
|
||||||
{
|
{
|
||||||
if (FormulaData is null)
|
if (FormulaData is null)
|
||||||
{
|
{
|
||||||
var hotwords = JsonSerializer.Deserialize<HotwordMode[]>(File.ReadAllText(Path.Combine(AppCommon.AIModelFile, "Hotwords.json")));
|
var hotwords = JsonSerializer.Deserialize<HotwordMode[]>(File.ReadAllText(Path.Combine(AppCommon.AIModelFile, "Hotwords.json")));
|
||||||
foreach (var item in hotwords.OrderByDescending(s=>s.key.Count()))
|
foreach (var item in hotwords.OrderByDescending(s => s.key.Count()))
|
||||||
foreach (var key in item.v)
|
foreach (var key in item.v)
|
||||||
FormulaData.Add(key, item.key);
|
FormulaData.Add(key, item.key);
|
||||||
}
|
}
|
||||||
|
|
@ -121,7 +137,7 @@ namespace VideoAnalysisCore.Common
|
||||||
FormulaDataKey = string.Join("|", FormulaData.Keys.Count);
|
FormulaDataKey = string.Join("|", FormulaData.Keys.Count);
|
||||||
if (string.IsNullOrEmpty(f))
|
if (string.IsNullOrEmpty(f))
|
||||||
return f;
|
return f;
|
||||||
return Regex.Replace(f, FormulaDataKey,
|
return Regex.Replace(f, FormulaDataKey,
|
||||||
match =>
|
match =>
|
||||||
FormulaData[match.Value]
|
FormulaData[match.Value]
|
||||||
);
|
);
|
||||||
|
|
@ -152,7 +168,7 @@ namespace VideoAnalysisCore.Common
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取Task处理后的 说话人字幕
|
/// 获取Task处理后的 说话人字幕
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static TotalCaptionsDto GetSpeakerCaptions(SenseVoiceRes[] captionsArr, OfflineSpeakerRes[]? speakerArr=null)
|
public static TotalCaptionsDto GetSpeakerCaptions(SenseVoiceRes[] captionsArr, OfflineSpeakerRes[]? speakerArr = null)
|
||||||
{
|
{
|
||||||
if (captionsArr is null || captionsArr.Length == 0)
|
if (captionsArr is null || captionsArr.Length == 0)
|
||||||
//|| speakerArr is null || speakerArr.Length == 0)
|
//|| speakerArr is null || speakerArr.Length == 0)
|
||||||
|
|
@ -160,15 +176,15 @@ namespace VideoAnalysisCore.Common
|
||||||
// 教师说话人Id
|
// 教师说话人Id
|
||||||
var techerId = speakerArr is null || !speakerArr.Any()
|
var techerId = speakerArr is null || !speakerArr.Any()
|
||||||
? 0
|
? 0
|
||||||
:speakerArr.GroupBy(s=>s.SpeakerIndex).Select(s => (s.Key,s.Sum(x=>x.Total)))
|
: speakerArr.GroupBy(s => s.SpeakerIndex).Select(s => (s.Key, s.Sum(x => x.Total)))
|
||||||
.OrderByDescending(s=>s.Item2).First().Key;
|
.OrderByDescending(s => s.Item2).First().Key;
|
||||||
var teacherSpeaking = 0f;
|
var teacherSpeaking = 0f;
|
||||||
var studentSpeaking = 0f;
|
var studentSpeaking = 0f;
|
||||||
var results = new Dictionary<SenseVoiceRes, List<int>>();
|
var results = new Dictionary<SenseVoiceRes, List<int>>();
|
||||||
var ss = new List<int> { 1 };
|
var ss = new List<int> { 1 };
|
||||||
if (speakerArr is null || speakerArr.Count() == 0)
|
if (speakerArr is null || speakerArr.Count() == 0)
|
||||||
{
|
{
|
||||||
results = captionsArr.ToDictionary(s => s, s=> ss);
|
results = captionsArr.ToDictionary(s => s, s => ss);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -213,12 +229,12 @@ namespace VideoAnalysisCore.Common
|
||||||
StudentSpeaking = (decimal)studentSpeaking,
|
StudentSpeaking = (decimal)studentSpeaking,
|
||||||
TeacherSpeaking = (decimal)teacherSpeaking,
|
TeacherSpeaking = (decimal)teacherSpeaking,
|
||||||
Captions = stringBuilder.ToString(),
|
Captions = stringBuilder.ToString(),
|
||||||
TimeBase = results.Select(s=>new TimeBase()
|
TimeBase = results.Select(s => new TimeBase()
|
||||||
{
|
{
|
||||||
Start = s.Key.Start,
|
Start = s.Key.Start,
|
||||||
End = s.Key.End,
|
End = s.Key.End,
|
||||||
Content = s.Key.Text,
|
Content = s.Key.Text,
|
||||||
TimeBaseType = s.Value.Count == 1 && s.Value.First() == techerId
|
TimeBaseType = s.Value.Count == 1 && s.Value.First() == techerId
|
||||||
? TimeBaseTypeEnum.教师讲授
|
? TimeBaseTypeEnum.教师讲授
|
||||||
: TimeBaseTypeEnum.互动交流
|
: TimeBaseTypeEnum.互动交流
|
||||||
})
|
})
|
||||||
|
|
@ -251,7 +267,7 @@ namespace VideoAnalysisCore.Common
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(value is null || string.IsNullOrEmpty(value.ToString()))
|
if (value is null || string.IsNullOrEmpty(value.ToString()))
|
||||||
return null;
|
return null;
|
||||||
if (Enum.TryParse<T>(value.ToString(), true, out var result) && Enum.IsDefined(typeof(T), result))
|
if (Enum.TryParse<T>(value.ToString(), true, out var result) && Enum.IsDefined(typeof(T), result))
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace VideoAnalysisCore.Common
|
||||||
StackTrace = context.Exception.StackTrace,
|
StackTrace = context.Exception.StackTrace,
|
||||||
};
|
};
|
||||||
// 将错误对象序列化为JSON格式
|
// 将错误对象序列化为JSON格式
|
||||||
var json = JsonSerializer.Serialize(errorObject);
|
var json =errorObject.ToJson();
|
||||||
|
|
||||||
// 设置响应内容类型为JSON
|
// 设置响应内容类型为JSON
|
||||||
context.HttpContext.Response.ContentType = "application/json";
|
context.HttpContext.Response.ContentType = "application/json";
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ namespace VideoAnalysisCore.Common.Expand
|
||||||
|
|
||||||
if (request.isolated_formula_wrapper != null)
|
if (request.isolated_formula_wrapper != null)
|
||||||
{
|
{
|
||||||
var isolatedWrapper = JsonSerializer.Serialize(request.isolated_formula_wrapper);
|
var isolatedWrapper = request.isolated_formula_wrapper.ToJson();
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ namespace VideoAnalysisCore.Controllers
|
||||||
[HttpPost(Name = "NodePackage")]
|
[HttpPost(Name = "NodePackage")]
|
||||||
public async Task<IActionResult> NodePackage(NodePackageReq[] reqArr)
|
public async Task<IActionResult> NodePackage(NodePackageReq[] reqArr)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"{DateTime.Now} 文件包订阅请求 req=" + JsonSerializer.Serialize(reqArr));
|
Console.WriteLine($"{DateTime.Now} 文件包订阅请求 req=" + reqArr.ToJson());
|
||||||
if (reqArr is null || reqArr.Count() == 0)
|
if (reqArr is null || reqArr.Count() == 0)
|
||||||
return BadRequest("无效视频列表数据");
|
return BadRequest("无效视频列表数据");
|
||||||
var videos = new List<VideoTask>(reqArr.Count());
|
var videos = new List<VideoTask>(reqArr.Count());
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ namespace VideoAnalysisCore.Job
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, postUrl);
|
var request = new HttpRequestMessage(HttpMethod.Post, postUrl);
|
||||||
request.Headers.Add("Area", item.Area); // 直接添加到本次请求头
|
request.Headers.Add("Area", item.Area); // 直接添加到本次请求头
|
||||||
request.Headers.Add("HostIP", item.HostIP); // 直接添加到本次请求头
|
request.Headers.Add("HostIP", item.HostIP); // 直接添加到本次请求头
|
||||||
request.Content = new StringContent(JsonSerializer.Serialize(postData), Encoding.UTF8, "application/json");
|
request.Content = new StringContent(postData.ToJson(), Encoding.UTF8, "application/json");
|
||||||
responseMessage = await apiClent.SendAsync(request);
|
responseMessage = await apiClent.SendAsync(request);
|
||||||
|
|
||||||
if (responseMessage.IsSuccessStatusCode)
|
if (responseMessage.IsSuccessStatusCode)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue