HuanMengProject/src/0-core/HuanMeng.MiaoYu.Code/Chat/Claude/ClaudeChat.cs
2024-07-24 04:58:00 +08:00

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);
}
}
}
}
}