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 AntDesign; using OneOf.Types; using System.Net; /// /// https://platform.moonshot.cn/docs/api-reference /// namespace VideoAnalysisCore.AICore.ChatGPT.KIMI { public class MoonshotClient { private readonly ILogger _logger; private readonly IHttpClientFactory _httpClientFactory; public MoonshotClient(ILogger logger, IHttpClientFactory httpClientFactory) { _logger = logger; _httpClientFactory = httpClientFactory; } /// /// list models /// /// public async Task ListModels() { var response = await GetAsync("/v1/models"); return await ParseResp(response); } /// /// Chat /// /// /// Return HttpResponseMessage for SSE public async Task Chat(string requestBody) { var chatResp = await PostJsonStreamAsync("/v1/chat/completions", requestBody); return await chatResp.Content.ReadFromJsonAsync(); } /// /// Chat /// /// /// Return HttpResponseMessage for SSE public async Task Chat(ChatReq chatReq) { var requestBody = System.Text.Json.JsonSerializer.Serialize(chatReq); var chatResp = await PostJsonStreamAsync("/v1/chat/completions", requestBody); return await chatResp.Content.ReadFromJsonAsync(); } /// /// 计算token长度 /// /// 文本 /// /// public async Task GetAsTiMateTokenCount(string chatReqText) { var reqObject = new { model = "moonshot-v1-128k", messages = new List() { new MessagesItem(chatReqText,"system"), } }; var response = await PostJsonStreamAsync("/v1/tokenizers/estimate-token-count", JsonConvert.SerializeObject(reqObject)); var responseText = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { var responseObj = JToken.Parse(responseText); return responseObj?["data"]?["total_tokens"]?.ToObject(); } var error = JsonConvert.DeserializeObject(responseText); _logger.LogError($"{error?.error?.type}: {error?.error?.message}"); throw new Exception($"{error?.error.type}: {error?.error.message}"); } /// /// Get as timate token count /// /// /// public async Task GetAsTiMateTokenCount(ChatReq chatReq) { var chatReqText = JsonConvert.SerializeObject(chatReq); return await GetAsTiMateTokenCount(chatReqText); } /// /// List files /// public virtual async Task ListFiles() { var response = await GetAsync("/v1/files"); return await ParseResp(response); } /// /// Upload file /// public virtual async Task UploadFile(string filePath) { if (!File.Exists(filePath)) { throw new FileNotFoundException($"{filePath} not found"); } var client = _httpClientFactory.CreateClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ApiKey); var request = new HttpRequestMessage(HttpMethod.Post, $"{Host}/v1/files"); var content = new MultipartFormDataContent { { new StreamContent(File.OpenRead(filePath)), "file", filePath } }; request.Content = content; var response = await client.SendAsync(request); return await ParseResp(response); } /// /// Upload file stream /// public virtual async Task UploadFileStream(Stream stream, string fileName) { var client = _httpClientFactory.CreateClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ApiKey); var request = new HttpRequestMessage(HttpMethod.Post, $"{Host}/v1/files"); var content = new MultipartFormDataContent { { new StreamContent(stream), "file", fileName } }; request.Content = content; var response = await client.SendAsync(request); return await ParseResp(response); } /// /// Get file content /// public virtual async Task GetFileContent(string fileId) { var response = await GetAsync($"/v1/files/{fileId}/content"); return await ParseResp(response); } private async Task GetAsync(string path) { var client = _httpClientFactory.CreateClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ApiKey); return await client.GetAsync(Host + path); } private async Task PostJsonAsync(string path, string json) { var client = _httpClientFactory.CreateClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ApiKey); return await client.PostAsync(Host + path, new StringContent(json, Encoding.UTF8, "application/json")); } private async Task PostJsonStreamAsync(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.Timeout = TimeSpan.FromSeconds(60 * 20);//超时时间20分钟 client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ApiKey); client.DefaultRequestVersion = HttpVersion.Version20; client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrLower; client.DefaultRequestHeaders.ConnectionClose = true; //var request = ToHttpRequest(path); //request.Version = HttpVersion.Version20; //request.VersionPolicy = HttpVersionPolicy.RequestVersionOrLower; //request.Content = new StringContent(json, Encoding.UTF8, "application/json"); //return await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); var content = new StringContent(json, Encoding.UTF8, "application/json"); return await client.PostAsync(uriBuilder.Uri, content); } 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); } private HttpRequestMessage ToHttpRequest(string path) { var request = new HttpRequestMessage(); var uriBuilder = new UriBuilder(Host + path); request.RequestUri = uriBuilder.Uri; request.Method = new HttpMethod("POST"); request.Headers.Host = (new Uri(Host)).Host; return request; } /// /// Parse response /// private async Task ParseResp(HttpResponseMessage response) { var responseText = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { return JsonConvert.DeserializeObject(responseText) ?? default; } var error = JsonConvert.DeserializeObject(responseText); _logger.LogError($"{error?.error.type}: {error?.error.message}"); throw new Exception($"{error?.error.type}: {error?.error.message}"); } private static string _host = "https://api.moonshot.cn"; public static string Host { get { if (string.IsNullOrEmpty(_host) && !string.IsNullOrEmpty(AppCommon.Config.ChatGpt.KIMI.Host)) { _host = AppCommon.Config.ChatGpt.KIMI.Host ?? ""; } return _host; } set { _host = value; } } private static string _apiKey = "sk_"; public static string ApiKey { get { if (string.IsNullOrEmpty(_apiKey) && !string.IsNullOrEmpty(AppCommon.Config.ChatGpt.KIMI.ApiKey)) { _apiKey = AppCommon.Config.ChatGpt.KIMI.ApiKey ?? ""; } return _apiKey; } set { _apiKey = value; } } } }