139 lines
5.8 KiB
C#
139 lines
5.8 KiB
C#
using HuanMeng.MiaoYu.Code.Chat.Contract;
|
|
|
|
using Microsoft.Extensions.Primitives;
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net.Http.Headers;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Json;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Newtonsoft.Json.Serialization;
|
|
using HuanMeng.MiaoYu.Code.Chat.Claude.Model;
|
|
|
|
namespace HuanMeng.MiaoYu.Code.Chat.Claude
|
|
{
|
|
/// <summary>
|
|
/// Claude3 https://docs.anthropic.com/en/api/messages ClaudeChatInfo
|
|
/// </summary>
|
|
public class ClaudeChat(ClaudeChatConfig claudeChatConfig, IHttpClientFactory factory) : IChat
|
|
{
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="chatParams"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="ArgumentException"></exception>
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
public async Task<BaseChatInfo> MessagesAsync(BaseChatParams chatParams)
|
|
{
|
|
var claudeChatChatParams = chatParams as ClaudeChatChatParams;
|
|
if (claudeChatChatParams == null)
|
|
{
|
|
throw new ArgumentException("参数异常");
|
|
}
|
|
//添加默认值
|
|
if (claudeChatChatParams.MaxTokens == 0)
|
|
{
|
|
claudeChatChatParams.MaxTokens = claudeChatConfig.MaxTokens;
|
|
}
|
|
//添加默认值
|
|
if (string.IsNullOrEmpty(claudeChatChatParams.Model))
|
|
{
|
|
claudeChatChatParams.Model = claudeChatConfig.Model;
|
|
}
|
|
//去线程池里拿http线程
|
|
using (var httpClient = factory.CreateClient())
|
|
{
|
|
// 设置请求头
|
|
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
|
httpClient.DefaultRequestHeaders.Add("x-api-key", claudeChatConfig.ApiKey);
|
|
httpClient.DefaultRequestHeaders.Add("anthropic-version", claudeChatConfig.AnthropicVersion);
|
|
|
|
var settings = new JsonSerializerSettings
|
|
{
|
|
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
|
};
|
|
string json = JsonConvert.SerializeObject(chatParams, settings);
|
|
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
|
var response = await httpClient.PostAsync(claudeChatConfig.RequestUrl, content);
|
|
if (response.IsSuccessStatusCode)
|
|
{
|
|
//var chatInfo1 = await response.Content.ReadFromJsonAsync<ClaudeChatResponse?>();
|
|
string responseBody = await response.Content.ReadAsStringAsync();
|
|
var chatInfo = JsonConvert.DeserializeObject<ClaudeChatResponse>(responseBody);
|
|
return chatInfo;
|
|
}
|
|
else
|
|
{
|
|
// 读取并打印返回消息
|
|
string responseBody = await response.Content.ReadAsStringAsync();
|
|
Console.WriteLine($"返回消息: {responseBody}");
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public async IAsyncEnumerable<string> MessagesStreamAsync(BaseChatParams chatParams)
|
|
{
|
|
var claudeChatChatParams = chatParams as ClaudeChatChatStreamParams;
|
|
if (claudeChatChatParams == null)
|
|
{
|
|
throw new ArgumentException("参数异常");
|
|
}
|
|
//添加默认值
|
|
if (claudeChatChatParams.MaxTokens == 0)
|
|
{
|
|
claudeChatChatParams.MaxTokens = claudeChatConfig.MaxTokens;
|
|
}
|
|
claudeChatChatParams.Stream = true;
|
|
//添加默认值
|
|
if (!string.IsNullOrEmpty(claudeChatChatParams.Model))
|
|
{
|
|
claudeChatChatParams.Model = claudeChatChatParams.Model;
|
|
}
|
|
//去线程池里拿http线程
|
|
using (var httpClient = factory.CreateClient())
|
|
{
|
|
// 设置请求头
|
|
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
|
httpClient.DefaultRequestHeaders.Add("x-api-key", claudeChatConfig.ApiKey);
|
|
httpClient.DefaultRequestHeaders.Add("anthropic-version", claudeChatConfig.AnthropicVersion);
|
|
|
|
var settings = new JsonSerializerSettings
|
|
{
|
|
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
|
};
|
|
string json = JsonConvert.SerializeObject(chatParams, settings);
|
|
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
|
var response = await httpClient.PostAsync(claudeChatConfig.RequestUrl, content);
|
|
if (response.IsSuccessStatusCode)
|
|
{
|
|
var chatInfo = await response.Content.ReadFromJsonAsync<ClaudeChatStreamResponse?>();
|
|
if (chatInfo?.Type == "message_delta")
|
|
{
|
|
claudeChatChatParams.OutCharResponse.Usage.OutputTokens = chatInfo.Usage?.OutputTokens ?? 0;
|
|
}
|
|
else if (chatInfo?.Type == "content_block_start")
|
|
{
|
|
claudeChatChatParams.OutCharResponse = chatInfo?.Message ?? new ClaudeChatResponse();
|
|
}
|
|
else if (chatInfo?.Type == "content_block_delta")
|
|
{
|
|
var text = chatInfo?.Delta?.Text ?? "";
|
|
if (!string.IsNullOrEmpty(text))
|
|
{
|
|
yield return text;
|
|
}
|
|
}
|
|
claudeChatChatParams.OutObj.Add(chatInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|