using System.Net.WebSockets;
using System.Text;
using XFEExtension.NetCore.Exceptions;
using XFEExtension.NetCore.XFEChatGPT.ChatGPTInnerClass.DefaultClass;
using XFEExtension.NetCore.XFEChatGPT.ChatGPTInnerClass.HelperClass;
using XFEExtension.NetCore.XFEChatGPT.OtherInnerClass;
using XFEExtension.NetCore.XFETransform;
using XFEExtension.NetCore.XFETransform.Json;
namespace XFEExtension.NetCore.XFEChatGPT;
///
/// 基于gpt.api.xfegzs.com开放接口的ChatGPT问答类
///
public class XFEChatGPT : XFEChatGPTBase
{
#region 私有字段
private readonly XFEAskGPTMessage _xFEAskGPTMessage;
#endregion
#region 公有封装字段
///
/// ChatGPT的系统设置,即设置ChatGPT的背景故事(类比)
///
public string? SystemString
{
get => _xFEAskGPTMessage.IsSelfEditData ? throw new XFEChatGPTException("自定义数据模式下不可获取") : _xFEAskGPTMessage.SystemContent;
set
{
if (_xFEAskGPTMessage.IsSelfEditData)
{
throw new XFEChatGPTException("自定义数据模式下不可设置");
}
_xFEAskGPTMessage.SystemContent = value;
}
}
///
/// 向ChatGPT提问的内容
///
public string? AskContent
{
get => _xFEAskGPTMessage.IsSelfEditData ? throw new XFEChatGPTException("自定义数据模式下不可获取") : _xFEAskGPTMessage.AskContent;
set
{
if (_xFEAskGPTMessage.IsSelfEditData)
{
throw new XFEChatGPTException("自定义数据模式下不可设置");
}
_xFEAskGPTMessage.AskContent = value;
}
}
///
/// ChatGPT的语言模型
///
public ChatGPTModel GPTModel
{
get => _xFEAskGPTMessage.IsSelfEditData ? _xFEAskGPTMessage.EnvironmentGPTData!.Model.GetModel() : _xFEAskGPTMessage.ChatGPTModel!.GetModel();
set
{
if (_xFEAskGPTMessage.IsSelfEditData)
{
_xFEAskGPTMessage.EnvironmentGPTData!.Model = value.GetModelString();
}
else
{
_xFEAskGPTMessage.ChatGPTModel = value.GetModelString();
}
}
}
///
/// XFE通信协议
///
public XFEComProtocol XFEComProtocol => _xFEAskGPTMessage.ComProtocol;
///
/// 设置是否为自定义数据模式
///
public bool IsSelfEditData => _xFEAskGPTMessage.IsSelfEditData;
///
/// 流式输出(打字效果)还是一次性输出
///
public bool StreamMode => _xFEAskGPTMessage.IsSelfEditData ? _xFEAskGPTMessage.EnvironmentGPTData!.Stream : _xFEAskGPTMessage.Stream;
///
/// ChatGPT的环境数据
///
public EnvironmentGPTData? EnvironmentGPTData
{
get => _xFEAskGPTMessage.EnvironmentGPTData;
set => _xFEAskGPTMessage.EnvironmentGPTData = value;
}
#endregion
#region 公有方法
///
/// 向ChatGPT发送消息
///
/// 提问的消息ID,用于标识回复
/// 远程服务器返回出错时抛出"
public void SendGPTMessage(string messageId)
{
var askGPTThread = new Thread(StartGetGPTMessage);
askGPTThread.Start(new MessageIdAndThread(messageId, askGPTThread));
ThreadList.Add(askGPTThread);
}
///
/// 向ChatGPT发送指定消息
///
/// 提问的消息ID,用于标识回复
/// 提问的内容
/// 远程服务器返回出错时抛出"
public void SendGPTMessage(string messageId, string askContent)
{
AskContent = askContent;
SendGPTMessage(messageId);
}
///
/// 释放资源
///
[Obsolete("方法已经过时,请使用MemorableXFEChatGPT")]
public void Dispose()
{
foreach (var thread in ThreadList)
{
thread.Abort();
}
}
#endregion
#region 静态方法
///
/// 发送消息并获取GPT回复
///
/// 待发送的消息
///
public static async Task SendAndGetGPTResponse(string message)
{
var receivedMessage = string.Empty;
try
{
ClientWebSocket webSocket = new();
await webSocket.ConnectAsync(new Uri("ws://gpt.api.xfegzs.com/"), CancellationToken.None);
await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(message)), WebSocketMessageType.Text, true, CancellationToken.None);
var buffer = new byte[1024];
var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);
receivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count);
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection closed.", CancellationToken.None);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
return receivedMessage;
}
///
/// 获取及更新APIKey秘钥
///
/// APIKey服务器密码
/// APIKey指令
/// 待执行的指令
///
public static async Task GPTAPIKeyCommand(string password, ApiKeyCommand apiKeyCommand, string commandString)
{
var receivedMessage = string.Empty;
try
{
var command = apiKeyCommand == ApiKeyCommand.GetApiKey ? "[获取]" : commandString;
ClientWebSocket webSocket = new();
webSocket.Options.SetRequestHeader("XFEPassword", password);
await webSocket.ConnectAsync(new Uri("ws://api.xfegzs.com/"), CancellationToken.None);
await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(command)), WebSocketMessageType.Text, true, CancellationToken.None);
var buffer = new byte[1024];
var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);
receivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count);
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection closed.", CancellationToken.None);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
return receivedMessage;
}
#endregion
#region 线程方法
private async void StartGetGPTMessage(object? sender)
{
var messageIdAndThread = (MessageIdAndThread)sender!;
var messageId = messageIdAndThread.MessageId;
var thread = messageIdAndThread.Thread;
if (StreamMode)
{
var isStarted = false;
try
{
#region 进行HTTP请求
ClientWebSocket webSocket = new();
await webSocket.ConnectAsync(new Uri("ws://gpt.api.xfegzs.com/"), CancellationToken.None);
var json = XFEJson.Serialize(_xFEAskGPTMessage);
if (json is not null)
await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(json)), WebSocketMessageType.Text, true, CancellationToken.None);
#endregion
while (true)
{
#region 读取消息
var buffer = new byte[1024];
var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);//接收消息
var nowReceivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count);//将消息转换为字符串
#endregion
if (XFEComProtocol == XFEComProtocol.XFEFAST)
{
if (nowReceivedMessage == "[DONE]")
{
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs("[XFEDONE]", messageId, GenerateState.End));
break;
}
if (nowReceivedMessage.Contains("[XFERemoteAPIError]"))
{
if (!isStarted)
{
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs("[XFESTART]", messageId, GenerateState.Start));
}
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs(nowReceivedMessage.Replace("[XFERemoteAPIError]", string.Empty), messageId, GenerateState.Error));
}
else if (nowReceivedMessage == "[XFE]")
{
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs("[XFESTART]", messageId, GenerateState.Start));
}
else
{
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs(nowReceivedMessage, messageId, GenerateState.Continue));
}
}
else
{
if (nowReceivedMessage == "[DONE]")
{
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs("[XFEDONE]", messageId, GenerateState.End));
break;
}
if (nowReceivedMessage.Contains("[XFERemoteAPIError]"))
{
if (!isStarted)
{
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs("[XFESTART]", messageId, GenerateState.Start));
}
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs(nowReceivedMessage.Replace("[XFERemoteAPIError]", string.Empty), messageId, GenerateState.Error));
}
else if (nowReceivedMessage == "[XFE]")
{
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs("[XFESTART]", messageId, GenerateState.Start));
}
else
{
if (nowReceivedMessage.Contains("[XFE]"))
{
nowReceivedMessage = nowReceivedMessage.Replace("[XFE]", string.Empty);
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs(nowReceivedMessage, messageId, GenerateState.Continue));
}
else
{
if (!isStarted)
{
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs("[XFESTART]", messageId, GenerateState.Start));
}
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs(nowReceivedMessage.Replace("[XFERemoteAPIError]", string.Empty), messageId, GenerateState.Error));
}
}
}
}
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection closed.", CancellationToken.None);
}
catch (Exception ex) when (ex is not XFEChatGPTException)
{
if (!isStarted)
{
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs("[XFESTART]", messageId, GenerateState.Start));
}
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs(ex.ToString(), messageId, GenerateState.Error));
Console.WriteLine(ex.ToString());
}
}
else
{
try
{
#region 进行HTTP请求
ClientWebSocket webSocket = new();
await webSocket.ConnectAsync(new Uri("ws://gpt.api.xfegzs.com/"), CancellationToken.None);
var json = XFEJson.Serialize(_xFEAskGPTMessage);
if (json is not null)
await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(json)), WebSocketMessageType.Text, true, CancellationToken.None);
#endregion
#region 读取消息
var buffer = new byte[1024];
var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);//接收消息
var nowReceivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count);//将消息转换为字符串
#endregion
if (XFEComProtocol == XFEComProtocol.XFEFAST)
{
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs(nowReceivedMessage, messageId, GenerateState.Start));
}
else
{
if (nowReceivedMessage.Contains("[XFE]"))
{
nowReceivedMessage = nowReceivedMessage.Replace("[XFE]", string.Empty);
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs(nowReceivedMessage, messageId, GenerateState.Start));
}
else
{
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs(nowReceivedMessage.Replace("[XFERemoteAPIError]", string.Empty), messageId, GenerateState.Error));
}
}
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection closed.", CancellationToken.None);
}
catch (Exception ex)
{
XFEChatGPTMessageReceived?.Invoke(this, new PrivateXFEGPTMessageReceivedEventArgs(ex.ToString(), messageId, GenerateState.Error));
Console.WriteLine(ex.ToString());
}
}
ThreadList.Remove(thread);
}
#endregion
#region 公有事件
///
/// 当收到ChatGPT的消息时触发
///
public event EventHandler? XFEChatGPTMessageReceived;
#endregion
#region 构造方法
///
/// 从EnvironmentGPTData构造,使用默认通信协议(快速响应通讯协议)
///
/// ChatGPT环境设置
public XFEChatGPT(EnvironmentGPTData environmentGPTData) => _xFEAskGPTMessage = new XFEAskGPTMessage(true, environmentGPTData.Stream, environmentGPTData.Model, environmentGPTData, XFEComProtocol.XFEFAST, string.Empty, string.Empty);
///
/// 从EnvironmentGPTData构造,自定义通讯协议
///
/// ChatGPT环境设置
/// 通信协议
public XFEChatGPT(EnvironmentGPTData environmentGPTData, XFEComProtocol comProtocol) => _xFEAskGPTMessage = new XFEAskGPTMessage(true, environmentGPTData.Stream, environmentGPTData.Model, environmentGPTData, comProtocol, string.Empty, string.Empty);
#region 默认模型构造
///
/// 使用系统和内容构造,使用默认通信协议(快速响应通讯协议)
///
/// ChatGPT的系统设置,即设置ChatGPT的背景故事(类比)
/// 向ChatGPT提问的内容
public XFEChatGPT(string systemContent, string askContent)
{
_xFEAskGPTMessage = new XFEAskGPTMessage(false, false, ChatGPTModel.gpt3point5turbo.GetModelString(), null, XFEComProtocol.XFEFAST, systemContent, askContent);
}
///
/// 使用系统和内容构造,可设置流式输出(打字效果)还是一次性输出,使用默认通信协议(快速响应通讯协议)
///
/// ChatGPT的系统设置,即设置ChatGPT的背景故事(类比)
/// 向ChatGPT提问的内容
/// 设置流式输出(打字效果)还是一次性输出
public XFEChatGPT(string systemContent, string askContent, bool stream)
{
_xFEAskGPTMessage = new XFEAskGPTMessage(false, stream, ChatGPTModel.gpt3point5turbo.GetModelString(), null, XFEComProtocol.XFEFAST, systemContent, askContent);
}
///
/// 使用系统构造
///
/// ChatGPT的系统设置,即设置ChatGPT的背景故事(类比)
public XFEChatGPT(string systemContent)
{
_xFEAskGPTMessage = new XFEAskGPTMessage(false, false, ChatGPTModel.gpt3point5turbo.GetModelString(), null, XFEComProtocol.XFEFAST, systemContent, string.Empty);
}
///
/// 使用系统构造,可设置流式输出(打字效果)还是一次性输出,自定义通讯协议
///
/// ChatGPT的系统设置,即设置ChatGPT的背景故事(类比)
/// 设置流式输出(打字效果)还是一次性输出
public XFEChatGPT(string systemContent, bool stream)
{
_xFEAskGPTMessage = new XFEAskGPTMessage(false, stream, ChatGPTModel.gpt3point5turbo.GetModelString(), null, XFEComProtocol.XFEFAST, systemContent, string.Empty);
}
///
/// 使用系统构造,可设置流式输出(打字效果)还是一次性输出,自定义通讯协议
///
/// ChatGPT的系统设置,即设置ChatGPT的背景故事(类比)
/// 设置流式输出(打字效果)还是一次性输出
/// 通信协议
public XFEChatGPT(string systemContent, bool stream, XFEComProtocol comProtocol)
{
_xFEAskGPTMessage = new XFEAskGPTMessage(false, stream, ChatGPTModel.gpt3point5turbo.GetModelString(), null, comProtocol, systemContent, string.Empty);
}
#endregion
#region 自定义模型构造
///
/// 使用系统和内容构造,自定义模型,使用默认通信协议(快速响应通讯协议)
///
/// ChatGPT的系统设置,即设置ChatGPT的背景故事(类比)
/// 向ChatGPT提问的内容
/// 选用的GPT模型
public XFEChatGPT(string systemContent, string askContent, ChatGPTModel chatGPTModel)
{
_xFEAskGPTMessage = new XFEAskGPTMessage(false, false, chatGPTModel.GetModelString(), null, XFEComProtocol.XFEFAST, systemContent, askContent);
}
///
/// 使用系统和内容构造,可设置流式输出(打字效果)还是一次性输出,自定义模型,使用默认通信协议(快速响应通讯协议)
///
/// ChatGPT的系统设置,即设置ChatGPT的背景故事(类比)
/// 向ChatGPT提问的内容
/// 设置流式输出(打字效果)还是一次性输出
/// 选用的GPT模型
public XFEChatGPT(string systemContent, string askContent, bool stream, ChatGPTModel chatGPTModel)
{
_xFEAskGPTMessage = new XFEAskGPTMessage(false, stream, chatGPTModel.GetModelString(), null, XFEComProtocol.XFEFAST, systemContent, askContent);
}
///
/// 使用系统构造,自定义模型,使用默认通信协议(快速响应通讯协议)
///
/// ChatGPT的系统设置,即设置ChatGPT的背景故事(类比)
/// 选用的GPT模型
public XFEChatGPT(string systemContent, ChatGPTModel chatGPTModel)
{
_xFEAskGPTMessage = new XFEAskGPTMessage(false, false, chatGPTModel.GetModelString(), null, XFEComProtocol.XFEFAST, systemContent, string.Empty);
}
///
/// 使用系统构造,可设置流式输出(打字效果)还是一次性输出,自定义模型,使用默认通信协议(快速响应通讯协议)
///
/// ChatGPT的系统设置,即设置ChatGPT的背景故事(类比)
/// 设置流式输出(打字效果)还是一次性输出
/// 选用的GPT模型
public XFEChatGPT(string systemContent, bool stream, ChatGPTModel chatGPTModel)
{
_xFEAskGPTMessage = new XFEAskGPTMessage(false, stream, chatGPTModel.GetModelString(), null, XFEComProtocol.XFEFAST, systemContent, string.Empty);
}
///
/// 使用系统构造,可设置流式输出(打字效果)还是一次性输出,自定义模型,自定义通讯协议
///
/// ChatGPT的系统设置,即设置ChatGPT的背景故事(类比)
/// 设置流式输出(打字效果)还是一次性输出
/// 选用的GPT模型
/// 通信协议
public XFEChatGPT(string systemContent, bool stream, ChatGPTModel chatGPTModel, XFEComProtocol comProtocol)
{
_xFEAskGPTMessage = new XFEAskGPTMessage(false, stream, chatGPTModel.GetModelString(), null, comProtocol, systemContent, string.Empty);
}
#endregion
#endregion
}