using System.Runtime.CompilerServices; using System.Text; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using OpenAI.Chat; using Yi.Framework.AiHub.Domain.Extensions; using Yi.Framework.AiHub.Domain.Shared.Dtos; namespace Yi.Framework.AiHub.Domain.AiChat.Impl; public class AzureRestChatService : IChatService { public AzureRestChatService() { } public async IAsyncEnumerable CompleteChatAsync(AiModelDescribe aiModelDescribe, List messages, [EnumeratorCancellation] CancellationToken cancellationToken) { // 设置API URL var apiUrl = $"{aiModelDescribe.Endpoint}"; // 准备请求内容 var requestBody = new { messages = messages.Select(x => new { role = x.GetRoleAsString(), content = x.Content.FirstOrDefault()?.Text }).ToList(), stream = true, max_tokens = 2048, temperature = 0.8, top_p = 0.1, // presence_penalty = 0, // frequency_penalty = 0, model = aiModelDescribe.ModelId }; // 序列化请求内容为JSON string jsonBody = JsonConvert.SerializeObject(requestBody); using var httpClient = new HttpClient(); // 设置请求头 httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {aiModelDescribe.ApiKey}"); // 其他头信息如Content-Type在StringContent中设置 // 构造 POST 请求 var request = new HttpRequestMessage(HttpMethod.Post, apiUrl); // 设置请求内容(示例) request.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json"); // 发送POST请求 HttpResponseMessage response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken); // 确认响应成功 response.EnsureSuccessStatusCode(); // 读取响应内容 var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken); // 从流中读取数据并输出到控制台 using var streamReader = new StreamReader(responseStream); string line; while ((line = await streamReader.ReadLineAsync(cancellationToken)) != null) { var result = GetContent(line); if (result is not null) { yield return result; } } } private string? GetContent(string line) { if (string.IsNullOrWhiteSpace(line)) return null; string prefix = "data: "; line = line.Substring(prefix.Length); try { // 解析为JObject var jsonObj = JObject.Parse(line); var content = jsonObj["choices"][0]["delta"]["content"].ToString(); return content; // // 判断choices是否存在且是数组,并且有元素 // if (jsonObj.TryGetValue("choices", out var choicesToken) && choicesToken is JArray choicesArray && // choicesArray.Count > 0) // { // var firstChoice = choicesArray[0] as JObject; // // 判断delta字段是否存在 // if (firstChoice.TryGetValue("delta", out var deltaToken)) // { // // 获取content字段 // if (deltaToken.Type == JTokenType.Object && ((JObject)deltaToken).TryGetValue("content", out var contentToken)) // { // return contentToken.ToString(); // } // } // } } catch (Exception) { // 解析失败 return null; } } }