KiMiApi.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. using OASystem.Domain.Dtos.Groups;
  2. using OASystem.Domain.Dtos.KiMi;
  3. using System.Net.Http.Headers;
  4. namespace OASystem.API.OAMethodLib.KiMiApi
  5. {
  6. public class KiMiApiClient
  7. {
  8. //读取配置文件
  9. private KiMiSetting _kimiSetting { get; set; }
  10. private readonly HttpClient _httpClient;
  11. public KiMiApiClient()
  12. {
  13. _httpClient = new HttpClient();
  14. _kimiSetting = AutofacIocManager.Instance.GetService<KiMiSetting>();
  15. // 设置公共请求头
  16. _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _kimiSetting.Key);
  17. }
  18. //private string apiKey = "sk-AY1Sv4rLnSUgGGHcC8SGSWYYKzGID7leZJcFfxAYozLC8dIc";
  19. //private string baseUrl = "https://api.moonshot.cn/v1";
  20. public async Task<string> UploadFileAsync(IFormFile file)
  21. {
  22. string message = string.Empty;
  23. byte[] fileBytes = null;
  24. using (var memoryStream = new MemoryStream())
  25. {
  26. await file.CopyToAsync(memoryStream);
  27. fileBytes = memoryStream.ToArray();
  28. }
  29. // 上传文件
  30. var fileContent = new ByteArrayContent(fileBytes);
  31. var fileFormData = new MultipartFormDataContent
  32. {
  33. { fileContent, "file", file.FileName },
  34. { new StringContent("file-extract"), "purpose" }
  35. };
  36. HttpResponseMessage fileResponse = await _httpClient.PostAsync($"{_kimiSetting.BaseUrl}/files", fileFormData);
  37. string fileResponseContent = await fileResponse.Content.ReadAsStringAsync();
  38. if (!fileResponse.IsSuccessStatusCode)
  39. {
  40. throw new Exception($"Failed to upload file: {fileResponseContent}");
  41. }
  42. dynamic fileObject = JsonConvert.DeserializeObject(fileResponseContent);
  43. string fileId = fileObject.id;
  44. HttpResponseMessage contentResponse = await _httpClient.GetAsync($"{_kimiSetting.BaseUrl}/files/{fileId}/content");
  45. string fileContentText = await contentResponse.Content.ReadAsStringAsync();
  46. if (!contentResponse.IsSuccessStatusCode)
  47. {
  48. throw new Exception($"Failed to get file content: {fileContentText}");
  49. }
  50. message = fileContentText;
  51. return message;
  52. }
  53. public async Task<List<SeedMessages>> UploadFilesAsync(List<IFormFile> files)
  54. {
  55. List<SeedMessages> result = new List<SeedMessages>();
  56. foreach (IFormFile file in files)
  57. {
  58. var fileConter = await this.UploadFileAsync(file);
  59. result.Add(new SeedMessages() { Role = KimiRole.system , Content = fileConter });
  60. }
  61. return result;
  62. }
  63. public async Task<string> SeedMessage(List<SeedMessages> messages)
  64. {
  65. string completionResponseContent = await SeedAsync(messages);
  66. // 解析返回的完成结果
  67. var completion = JObject.Parse(completionResponseContent);
  68. string reply = completion["choices"][0]["message"].ToString();
  69. return reply;
  70. }
  71. public async Task<KiMiRoot> SeedMessageByFullConterObject(List<SeedMessages> messages)
  72. {
  73. var respStr = await SeedAsync(messages);
  74. return JsonConvert.DeserializeObject<KiMiRoot>(respStr);
  75. }
  76. private async Task<string> SeedAsync(List<SeedMessages> messages)
  77. {
  78. var completionRequest = new
  79. {
  80. model = _kimiSetting.Model,
  81. messages = messages.Select(x => new
  82. {
  83. Role = StringEnumHelper.ToStringValue(x.Role),
  84. x.Content
  85. }),
  86. temperature = 1,
  87. max_tokens = 4096
  88. };
  89. var completionJson = JsonConvert.SerializeObject(completionRequest);
  90. var completionContent = new StringContent(completionJson, Encoding.UTF8, "application/json");
  91. HttpResponseMessage completionResponse = await _httpClient.PostAsync($"{_kimiSetting.BaseUrl}/chat/completions", completionContent);
  92. string completionResponseContent = await completionResponse.Content.ReadAsStringAsync();
  93. if (!completionResponse.IsSuccessStatusCode)
  94. {
  95. throw new Exception($"Failed to seed message: {completionResponseContent}");
  96. }
  97. return completionResponseContent;
  98. }
  99. }
  100. public class SeedMessages
  101. {
  102. public KimiRole Role { get; set; }
  103. public string Content { get; set; }
  104. }
  105. public class KiMiRoot
  106. {
  107. public string Id { get; set; }
  108. public string Object { get; set; }
  109. public long Created { get; set; }
  110. public string Model { get; set; }
  111. public List<Choice> Choices { get; set; }
  112. public Usage Usage { get; set; }
  113. }
  114. public class Choice
  115. {
  116. [JsonProperty("index")]
  117. public int Index { get; set; }
  118. public ReturnMessage Message { get; set; }
  119. [JsonProperty("finish_reason")]
  120. public string FinishReason { get; set; }
  121. }
  122. public class Usage
  123. {
  124. public int PromptTokens { get; set; }
  125. public int CompletionTokens { get; set; }
  126. public int TotalTokens { get; set; }
  127. }
  128. public class ReturnMessage
  129. {
  130. public string Role { get; set; }
  131. public string Content { get; set; }
  132. }
  133. public enum KimiRole
  134. {
  135. system,
  136. user
  137. }
  138. public static class StringEnumHelper
  139. {
  140. public static string ToStringValue(KimiRole value)
  141. {
  142. return value switch
  143. {
  144. KimiRole.system => "system",
  145. KimiRole.user => "user",
  146. _ => throw new ArgumentOutOfRangeException(nameof(value), value, null)
  147. };
  148. }
  149. }
  150. }