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 }