Files
Yi.Framework/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/AiChat/Impl/AzureRestChatService.cs
2025-06-25 17:12:09 +08:00

118 lines
3.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<string> CompleteChatAsync(AiModelDescribe aiModelDescribe, List<ChatMessage> messages,
[EnumeratorCancellation] CancellationToken cancellationToken)
{
// 设置API URL
var apiUrl = $"{aiModelDescribe.Endpoint}models/chat/completions";
var ss = messages.Select(x => new
{
role = x.GetRoleAsString(),
content = x.Content.FirstOrDefault()?.Text
}).ToList();
// 准备请求内容
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;
}
}
}