LinkToolAddin/common/HttpRequest.cs

126 lines
4.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using LinkToolAddin.host.llm.entity;
using LinkToolAddin.host.llm.entity.stream;
using Newtonsoft.Json;
namespace LinkToolAddin.common;
public class HttpRequest
{
public static async Task<string> SendPostRequestAsync(string url, string jsonContent, string apiKey)
{
using var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
var response = await httpClient.PostAsync(url, new StringContent(jsonContent, Encoding.UTF8, "application/json"));
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}
public static async IAsyncEnumerable<string> SendStreamPostRequestAsync(string url, string jsonContent, string apiKey)
{
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
// 发送 POST 请求并获取响应流
var response = await client.PostAsync(url,new StringContent(jsonContent, Encoding.UTF8, "application/json"));
// 验证响应状态
response.EnsureSuccessStatusCode();
// 获取响应流
using var stream = await response.Content.ReadAsStreamAsync();
using var reader = new StreamReader(stream);
// 流式读取
string line;
while ((line = await reader.ReadLineAsync()) != null)
{
string content = ProcessPartialResponse(line);
yield return content;
}
}
private static string ProcessPartialResponse(string rawData)
{
try
{
var lines = rawData.Split(new[] { "data: " }, StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var trimmedLine = line.Trim();
if (!string.IsNullOrEmpty(trimmedLine))
{
var result = JsonConvert.DeserializeObject<LlmStreamChat>(trimmedLine);
return result.Choices[0].Delta.Content;
}
}
}
catch { /* 处理解析异常 */ }
return null;
}
public static async IAsyncEnumerable<LlmStreamChat> PostWithStreamingResponseAsync(
string url,
string body,
string apiKey,
string contentType = "application/json",
Action<HttpRequestMessage> configureHeaders = null)
{
using (var client = new HttpClient())
{
// 设置超时时间为30分钟
client.Timeout = TimeSpan.FromMinutes(30);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
using (var request = new HttpRequestMessage(HttpMethod.Post, url))
{
// 设置请求头和Body
Console.WriteLine("开始请求...");
configureHeaders?.Invoke(request);
request.Content = new StringContent(body, Encoding.UTF8, contentType);
// 发送请求并立即开始读取响应流
using (var response = await client.SendAsync(
request,
HttpCompletionOption.ResponseHeadersRead))
{
response.EnsureSuccessStatusCode();
// 获取响应流
using (var stream = await response.Content.ReadAsStreamAsync())
using (var reader = new StreamReader(stream))
{
string line;
StringBuilder incompleteJsonBuffer = new StringBuilder();
// 流式读取并输出到控制台
while ((line = await reader.ReadLineAsync()) != null)
{
foreach (var chunk in line.Split(new[] { "data: " }, StringSplitOptions.RemoveEmptyEntries))
{
LlmStreamChat dataObj = null;
try
{
dataObj = JsonConvert.DeserializeObject<LlmStreamChat>(chunk);
}catch{/*process exception*/}
if (dataObj is not null)
{
yield return dataObj;
}
}
}
}
}
}
}
}
}