using VideoAnalysisCore.Common;
using System.Net.Http.Headers;
using System.Text;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using System.Net.Http;
using Newtonsoft.Json;
using System.Net.Http.Json;
using System.Net;
using System.Threading;
using System;
using System.IO;
using VideoAnalysisCore.AICore.GPT.ChatGPT;
using System.Threading.Tasks;
using System.Text.Json;
namespace VideoAnalysisCore.AICore.GPT.DeepSeek
{
public class DeepSeekGPTClient
{
//private readonly string Path = "v1/chat/completions";
//public static string Host = AppCommon.Config.ChatGpt.aliyun.Host;
//public static string ApiKey = AppCommon.Config.ChatGpt.aliyun.ApiKey;
private readonly string Path = "";
public static string Host = AppCommon.Config.ChatGpt.DeepSeek.Host;
public static string ApiKey = AppCommon.Config.ChatGpt.DeepSeek.ApiKey;
//public static string Host = AppCommon.Config.ChatGpt.ChatGpt.Host;
//public static string ApiKey = AppCommon.Config.ChatGpt.ChatGpt.ApiKey;
//private readonly string Path = "v1/chat/completions";
private readonly IHttpClientFactory _httpClientFactory;
private readonly RedisManager redisManager;
public DeepSeekGPTClient(IHttpClientFactory httpClientFactory, RedisManager redisManager)
{
_httpClientFactory = httpClientFactory;
this.redisManager = redisManager;
}
///
/// Chat
///
///
/// Return HttpResponseMessage for SSE
public async Task<(Usage u, string res,string reasoning)?> Chat(ChatRequest chatReq)
{
//chatReq.model = "deepseek-r1";
if (chatReq.stream) return await ChatSSE(chatReq);
postStar:
var requestBody = chatReq.ToJson();
HttpResponseMessage chatResp = PostJsonStream(Path, requestBody);
var res1 = await chatResp.Content.ReadAsStringAsync();
if (res1 == null || string.IsNullOrEmpty(res1)|| !chatResp.IsSuccessStatusCode)
{
Console.WriteLine(DateTime.Now + $"=>GPT请求失败重试 Code = {chatResp.StatusCode} Res={res1}");
goto postStar;
}
//throw new Exception($" GPT模型返回异常 返回参数: " +
// $" {System.Text.Json.JsonSerializer.Serialize(res1)}");
Console.WriteLine(DateTime.Now + $"=>GPT请求头获取成功 Code = {chatResp.StatusCode} Res={res1}");
var res = await chatResp.Content.ReadFromJsonAsync();
if (res is null || res.error != null)
throw new Exception($" GPT模型返回异常 返回参数: " +
$" {res.ToJson()}");
var d = thinkMSG(res?.choices.FirstOrDefault()?.message);
var chatResContent = d.m1;
var chatResReasoning = d.m2;
if (string.IsNullOrEmpty(chatResContent))
return null;
return (res.usage, chatResContent, chatResReasoning);
}
private (string m1, string m2) thinkMSG(Message? m)
{
var chatResContent = m?.content.Trim();
var chatResReasoning = string.Empty;
if (chatResContent.StartsWith("") + 8);
}
else
chatResReasoning = m?.reasoning_content?.Trim();
return (chatResContent, chatResReasoning);
}
private HttpResponseMessage PostJsonStream(string path, string json)
{
var uriBuilder = new UriBuilder(Host + Path);
var maxRestart = 4;
var errorMSG = new Exception[maxRestart];
for (int i = 0; i < maxRestart; i++)
{
try
{
var client = _httpClientFactory.CreateClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", ApiKey);
client.Timeout = TimeSpan.FromSeconds(60 * 20);//超时时间20分钟
client.DefaultRequestVersion = HttpVersion.Version20;
client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrLower;
client.DefaultRequestHeaders.ConnectionClose = true;
var request = new HttpRequestMessage(HttpMethod.Post, uriBuilder.Uri);
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
return client.Send(request, HttpCompletionOption.ResponseHeadersRead);
}
catch (Exception e)
{
errorMSG[i] = e;
Console.WriteLine("====================[请求异常,重试]====================");
Console.WriteLine(uriBuilder.Uri);
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
Console.WriteLine("==============================================");
Thread.Sleep(1000);
}
}
throw errorMSG.Last(s => s != null);
}
///
/// ChatSSE[流式传输 更稳定]
///
///
/// Return HttpResponseMessage for SSE
public async Task<(Usage u, string res, string reasoning)?> ChatSSE(ChatRequest chatReq)
{
var requestBody = chatReq.ToJson();
PostJsonStream:
var chatResp = PostJsonStream(string.Empty, requestBody);
if (!chatResp.IsSuccessStatusCode)
{
Console.WriteLine(DateTime.Now + "=>请求GPT服务器异常 " + chatResp?.StatusCode);
Console.WriteLine(await chatResp.Content.ReadAsStringAsync());
goto PostJsonStream;
}
using var stream = chatResp.Content.ReadAsStream();
using var reader = new StreamReader(stream, Encoding.UTF8);
string line;
var messageBuilder = new StringBuilder();
var messageBuilder1 = new StringBuilder();
var lastChat = new ChatResSSE();
var splitCount = "data:".Length;
var maxLoop = 60*100000;
int threshold = 0;
while (maxLoop>0)
{
line = reader.ReadLine();
if (line is null || string.IsNullOrEmpty(line)|| line.StartsWith(": keep-alive")) {
Thread.Sleep(10);
maxLoop--;
continue;
}
else if (line.EndsWith("[DONE]"))
{
// 表示一条消息结束
string message = messageBuilder.ToString();
string message2 = messageBuilder1.ToString();
messageBuilder.Clear();
messageBuilder1.Clear();
var d =thinkMSG(new Message() { content = message, reasoning_content = message2 });
message = d.m1;
message2 = d.m2;
var u = lastChat?.usage;
if (u == null || string.IsNullOrEmpty(message))
return null;
return (u, message, message2);
}
else if (line.StartsWith("data:"))
{
try
{
var data = System.Text.Json.JsonSerializer.Deserialize(line.Substring(splitCount).Trim());
lastChat = data;
var delta = data?.choices.FirstOrDefault()?.delta;
var str = delta?.content;
var strReasoning = delta?.reasoning_content;
if (!string.IsNullOrEmpty(str))
messageBuilder.Append(str);
if (!string.IsNullOrEmpty(strReasoning))
messageBuilder1.Append(strReasoning);
var steamCount = messageBuilder.Length + messageBuilder1.Length;
if (++threshold%30==0)
redisManager.SetTaskProgress(chatReq.taskId, "steam=>"+ steamCount);
}
catch (Exception e)
{
Console.WriteLine("异常 ChatSSE=>");
Console.WriteLine(line);
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
}
Console.WriteLine(DateTime.Now + "=>AI请求超时 " + chatReq.taskId);
return null;
}
///
/// 请求AI
///
/// 返回JSON类型
/// 任务id
/// 提示词
/// 任务类型
/// GPT版本
/// 最大token 不设置默认最大值 16000/8000
///
///
public async Task ChatAsync(string task, string postMessages, string title, string model = "deepseek-reasoner", int max_tokens = -1)
{
Message[] messageArr = [
new Message(postMessages,"user"),
];
messageArr = messageArr.Where(s => s != null).ToArray();
var chatRep = new ChatRequest
{
taskId = task,
model = model,
max_tokens = model == "deepseek-reasoner" ? 16000 : 8000,
stream = true,
temperature = 0.2f,
messages = messageArr
};
if (max_tokens != -1)
chatRep.max_tokens = max_tokens;
var tryCount = 10;
while (tryCount-- > 0)
{
try
{
var time = title + DateTime.Now.ToString("MMddHHmmss");
var redisCached = new object[2] { chatRep, null };
redisManager.SetTaskGPTCached(task, time, chatRep);
var chatResp = await Chat(chatRep);
var chatResContent = chatResp?.res;
if (string.IsNullOrEmpty(chatResContent))
throw new Exception("GPT返回message无效结果");
if (chatResp != null)
{
redisCached[1] = new object[] { chatResp.Value.res, chatResp.Value.u, chatResp.Value.reasoning };
redisManager.SetTaskGPTCached(task, time, redisCached);
}
chatResContent = chatResContent?.ExtractJsonStrings()?.FirstOrDefault();
chatResContent = chatResContent?.Replace("\n", "");
chatResContent = chatResContent?.Replace("```json", "");
chatResContent = chatResContent?.Replace("```", "");
chatResContent = chatResContent?.Replace("}{", "},{");
chatResContent = chatResContent?.Replace("}|{", "},{");
chatResContent = chatResContent?.Trim();
if (string.IsNullOrEmpty(chatResContent))
throw new Exception("ChatGPT返回结果无有效JSON");
var startsStr = typeof(T).IsArray ? "[" : "{";
var endStr = typeof(T).IsArray ? "]" : "}";
if (!chatResContent.StartsWith(startsStr))
chatResContent = startsStr + chatResContent;
if (!chatResContent.EndsWith(endStr))
chatResContent = chatResContent + endStr;
var options = new JsonSerializerOptions
{
// 允许解析不严格符合 JSON 规范的字符串
AllowTrailingCommas = true,
// 处理不匹配的 JSON 字符
ReadCommentHandling = JsonCommentHandling.Skip
};
var questionRes = System.Text.Json.JsonSerializer.Deserialize(chatResContent, options);
if (questionRes is null)
throw new Exception("ChatGPT返回无效结果");
return questionRes;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(DateTime.Now + $"=>ChatGPT结果解析错误 重试剩余{tryCount}");
}
}
throw new Exception(DateTime.Now + "=>ChatGPT请求失败次数过多!!!");
}
}
}