using System; using System.Collections; using System.Collections.Generic; using System.Net.WebSockets; using System.Text; using System.Threading; using System.Threading.Tasks; using XFEExtension.XFEJsonTransform; namespace XFEExtension.XFEChatGPT { /// /// APIKey命令 /// public enum ApiKeyCommand { /// /// 获取APIKey列表 /// GetApiKey, /// /// 设置APIKey列表 /// SetApiKey } /// /// XFE通讯协议 /// public enum XFEComProtocol { /// /// 响应速度快速,不安全的通讯协议 /// XFEFAST, /// /// 响应速度适中,安全的通讯协议 /// XFEHARD } /// /// 文本生成状态 /// public enum GenerateState { /// /// 表示生成已经开始 /// Start, /// /// 表示生成正在进行中 /// Continue, /// /// 表示生成已经结束 /// End, /// /// 表示生成出错 /// Error } /// /// ChatGPT的模型 /// public enum ChatGPTModel { /// /// 比任何 GPT-3.5 型号都更强大,能够执行更复杂的任务,并针对聊天进行了优化。将在发布 2 周后使用我们最新的模型迭代进行更新。 /// gpt4, /// /// 最新的GPT-4模型,具有改进的指令跟随、JSON模式、可复制输出、并行函数调用等功能。最多返回4096个输出标记。此预览模型还不适合生产流量。 /// gpt4turbo, /// /// 能够理解图像,以及所有其他GPT-4 Turbo功能。最多返回4096个输出标记。这是一个预览模型版本,还不适合生产流量。 /// gpt4turbovision, /// /// 13 年 2023 月 3 日带有函数调用数据的快照。与gpt-4不同,此模型不会收到更新,并将在新版本发布3个月后弃用。基于gpt-4 /// gpt40613, /// /// 功能与gpt4基本模型相同,但上下文长度是其 4 倍。将使用最新的模型迭代进行更新。基于gpt-4 /// gpt432k, /// /// 13 年 2023 月 3 日的快照。与GPT-4-32K不同,此模型不会收到更新,并将在新版本发布 3 个月后弃用。基于gpt-4-32k /// gpt432k0613, /// /// 功能最强大的 GPT-3.5 型号,针对聊天进行了优化,成本仅为 .将在发布 1 周后使用最新的模型迭代进行更新。 /// gpt3point5turbo, /// /// 功能与标准模型相同,但上下文是其 4 倍。 /// gpt3point5turbo16k, /// /// 13 年 2023 月 3 日的快照。与GPT-3.5-16K不同,此模型不会收到更新,并将在新版本发布 3 个月后弃用。 /// gpt3point5turbo0613, /// /// 13 年 2023 月 3 日的快照。与GPT-3.5-turbo-16k不同,此模型不会收到更新,并将在新版本发布 3 个月后弃用。 /// gpt3point5turbo16k0613, /// /// 可以完成任何语言任务,质量更好,输出时间更长,并且遵循一致的指令,而不是居里,巴贝奇或ADA模型。还支持一些附加功能,例如插入文本。 /// textdavinci003, /// /// 与监督微调而不是强化学习类似的能力,但经过训练。 /// textdavinci002, /// /// 针对代码完成任务进行优化的模型 /// codedavinci002 } /// /// ChatGPT模型的拓展 /// public static class ChatGPTModelExtension { /// /// 获取模型的字符串 /// /// /// /// 意料之外的模型 public static string GetModelString(this ChatGPTModel chatGPTModel) { switch (chatGPTModel) { case ChatGPTModel.gpt4: return "gpt-4"; case ChatGPTModel.gpt4turbo: return "gpt-4-1106-preview"; case ChatGPTModel.gpt4turbovision: return "gpt-4-vision-preview"; case ChatGPTModel.gpt40613: return "gpt-4-0613"; case ChatGPTModel.gpt432k: return "gpt-4-32k"; case ChatGPTModel.gpt432k0613: return "gpt-4-32k-0613"; case ChatGPTModel.gpt3point5turbo: return "gpt-3.5-turbo"; case ChatGPTModel.gpt3point5turbo16k: return "gpt-3.5-turbo-16k"; case ChatGPTModel.gpt3point5turbo0613: return "gpt-3.5-turbo-0613"; case ChatGPTModel.gpt3point5turbo16k0613: return "gpt-3.5-turbo-16k-0613"; case ChatGPTModel.textdavinci003: return "text-davinci-003"; case ChatGPTModel.textdavinci002: return "text-davinci-002"; case ChatGPTModel.codedavinci002: return "code-davinci-002"; default: throw new XFEChatGPTException("未知的ChatGPT模型"); } } /// /// 通过字符串获取模型 /// /// /// /// 意料之外的模型 public static ChatGPTModel GetModel(this string chatGPTModel) { switch (chatGPTModel) { case "gpt-3.5-turbo": return ChatGPTModel.gpt3point5turbo; case "gpt-3.5-turbo-16k": return ChatGPTModel.gpt3point5turbo16k; case "gpt-3.5-turbo-0613": return ChatGPTModel.gpt3point5turbo0613; case "gpt-3.5-turbo-16k-0613": return ChatGPTModel.gpt3point5turbo16k0613; case "text-davinci-003": return ChatGPTModel.textdavinci003; case "text-davinci-002": return ChatGPTModel.textdavinci002; case "code-davinci-002": return ChatGPTModel.codedavinci002; default: throw new XFEChatGPTException("未知的ChatGPT模型"); } } } /// /// XFEChatGPT的基类 /// public class XFEChatGPTBase { private protected List threadList = new List(); } /// /// 基于gpt.api.xfegzs.com开放接口的ChatGPT问答类 /// public class XFEChatGPT : XFEChatGPTBase { #region 私有字段 private readonly XFEAskGPTMessage xFEAskGPTMessage; #endregion #region 公有封装字段 /// /// ChatGPT的系统设置,即设置ChatGPT的背景故事(类比) /// public string SystemString { get { if (xFEAskGPTMessage.isSelfEditData) { throw new XFEChatGPTException("自定义数据模式下不可获取"); } else { return xFEAskGPTMessage.systemContent; } } set { if (xFEAskGPTMessage.isSelfEditData) { throw new XFEChatGPTException("自定义数据模式下不可设置"); } else { xFEAskGPTMessage.systemContent = value; } } } /// /// 向ChatGPT提问的内容 /// public string AskContent { get { if (xFEAskGPTMessage.isSelfEditData) { throw new XFEChatGPTException("自定义数据模式下不可获取"); } else { return xFEAskGPTMessage.askContent; } } set { if (xFEAskGPTMessage.isSelfEditData) { throw new XFEChatGPTException("自定义数据模式下不可设置"); } else { xFEAskGPTMessage.askContent = value; } } } /// /// ChatGPT的语言模型 /// public ChatGPTModel GPTModel { get { if (xFEAskGPTMessage.isSelfEditData) { return xFEAskGPTMessage.EnvironmentGPTData.model.GetModel(); } else { return xFEAskGPTMessage.chatGPTModel.GetModel(); } } set { if (xFEAskGPTMessage.isSelfEditData) { xFEAskGPTMessage.EnvironmentGPTData.model = value.GetModelString(); } else { xFEAskGPTMessage.chatGPTModel = value.GetModelString(); } } } /// /// XFE通信协议 /// public XFEComProtocol XFEComProtocol { get { return xFEAskGPTMessage.comProtocol; } } /// /// 设置是否为自定义数据模式 /// public bool IsSelfEditData { get { return xFEAskGPTMessage.isSelfEditData; } } /// /// 流式输出(打字效果)还是一次性输出 /// public bool StreamMode { get { if (xFEAskGPTMessage.isSelfEditData) { return xFEAskGPTMessage.EnvironmentGPTData.stream; } else { return xFEAskGPTMessage.stream; } } } /// /// ChatGPT的环境数据 /// public EnvironmentGPTData EnvironmentGPTData { get { return 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); } /// /// 释放资源 /// public void Dispose() { foreach (var thread in threadList) { thread.Abort(); } } #endregion #region 静态方法 /// /// 发送消息并获取GPT回复 /// /// 待发送的消息 /// public static async Task SendAndGetGPTResponse(string message) { string receivedMessage = string.Empty; try { ClientWebSocket webSocket = new ClientWebSocket(); 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); byte[] buffer = new byte[1024]; WebSocketReceiveResult 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) { string receivedMessage = string.Empty; string command = string.Empty; try { if (apiKeyCommand == ApiKeyCommand.GetApiKey) { command = "[获取]"; } else { command = commandString; } ClientWebSocket webSocket = new ClientWebSocket(); 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); byte[] buffer = new byte[1024]; WebSocketReceiveResult 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; string messageId = messageIdAndThread.messageId; Thread thread = messageIdAndThread.thread; if (StreamMode) { bool isStarted = false; try { #region 进行HTTP请求 ClientWebSocket webSocket = new ClientWebSocket(); await webSocket.ConnectAsync(new Uri("ws://gpt.api.xfegzs.com/"), CancellationToken.None); await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(xFEAskGPTMessage.ConvertToJson())), WebSocketMessageType.Text, true, CancellationToken.None); #endregion while (true) { #region 读取消息 byte[] 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; } else 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; } else 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 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 ClientWebSocket(); await webSocket.ConnectAsync(new Uri("ws://gpt.api.xfegzs.com/"), CancellationToken.None); await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(xFEAskGPTMessage.ConvertToJson())), WebSocketMessageType.Text, true, CancellationToken.None); #endregion #region 读取消息 byte[] buffer = new byte[1024]; WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);//接收消息 string 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 } /// /// 基于gpt.api.xfegzs.com开放接口的ChatGPT问答类(记忆模式) /// public class MemorableXFEChatGPT : XFEChatGPTBase { private readonly XFEGPTMemoryDialog xFEGPTMemoryDialog; /// /// 获取或设置对话记录 /// public XFEGPTMemoryDialog MemoryDialog { get { return xFEGPTMemoryDialog; } } #region 公共方法 #region 创建对话 /// /// 创建一个新的对话,使用默认通信协议(快速响应通讯协议) /// /// 对话的ID /// 系统消息 public void CreateDialog(string dialogId, string system) { xFEGPTMemoryDialog.Add(dialogId, new XFEGPTMessageCollection(new XFEGPTMessage[] { new XFEGPTMessage(dialogId, new GPTMessage("system", system)) }, false, ChatGPTModel.gpt3point5turbo, XFEComProtocol.XFEFAST, false, 0.7)); } /// /// 创建一个新的对话,使用默认通信协议(快速响应通讯协议) /// /// 对话的ID /// 系统消息 /// 是否记录对话信息 public void CreateDialog(string dialogId, string system, bool hasMemory) { xFEGPTMemoryDialog.Add(dialogId, new XFEGPTMessageCollection(new XFEGPTMessage[] { new XFEGPTMessage(dialogId, new GPTMessage("system", system)) }, false, ChatGPTModel.gpt3point5turbo, XFEComProtocol.XFEFAST, hasMemory, 0.7)); } /// /// 创建一个新的对话,使用默认通信协议(快速响应通讯协议) /// /// 对话的ID /// 系统消息 /// 是否记录对话信息 /// 是否为流式输出 public void CreateDialog(string dialogId, string system, bool hasMemory, bool streamMode) { xFEGPTMemoryDialog.Add(dialogId, new XFEGPTMessageCollection(new XFEGPTMessage[] { new XFEGPTMessage(dialogId, new GPTMessage("system", system)) }, streamMode, ChatGPTModel.gpt3point5turbo, XFEComProtocol.XFEFAST, hasMemory, 0.7)); } /// /// 创建一个新的对话,使用默认通信协议(快速响应通讯协议) /// /// 对话的ID /// 系统消息 /// 是否记录对话信息 /// 是否为流式输出 /// 所用的ChatGPT模型 public void CreateDialog(string dialogId, string system, bool hasMemory, bool streamMode, ChatGPTModel chatGPTModel) { xFEGPTMemoryDialog.Add(dialogId, new XFEGPTMessageCollection(new XFEGPTMessage[] { new XFEGPTMessage(dialogId, new GPTMessage("system", system)) }, streamMode, chatGPTModel, XFEComProtocol.XFEFAST, hasMemory, 0.7)); } /// /// 创建一个新的对话,使用默认通信协议(快速响应通讯协议) /// /// 对话的ID /// 系统消息 /// 是否记录对话信息 /// 是否为流式输出 /// 所用的ChatGPT模型 /// 系统的Temperature public void CreateDialog(string dialogId, string system, bool hasMemory, bool streamMode, ChatGPTModel chatGPTModel, double temperature) { xFEGPTMemoryDialog.Add(dialogId, new XFEGPTMessageCollection(new XFEGPTMessage[] { new XFEGPTMessage(dialogId, new GPTMessage("system", system)) }, streamMode, chatGPTModel, XFEComProtocol.XFEFAST, hasMemory, temperature)); } /// /// 创建一个新的对话,自定义通讯协议 /// /// 对话的ID /// 系统消息 /// 是否记录对话信息 /// 是否为流式输出 /// 所用的ChatGPT模型 /// 通信协议 public void CreateDialog(string dialogId, string system, bool hasMemory, bool streamMode, ChatGPTModel chatGPTModel, XFEComProtocol comProtocol) { xFEGPTMemoryDialog.Add(dialogId, new XFEGPTMessageCollection(new XFEGPTMessage[] { new XFEGPTMessage(dialogId, new GPTMessage("system", system)) }, streamMode, chatGPTModel, comProtocol, hasMemory, 0.7)); } /// /// 创建一个新的对话,自定义通讯协议 /// /// 对话的ID /// 系统消息 /// 是否记录对话信息 /// 是否为流式输出 /// 所用的ChatGPT模型 /// 系统的Temperature /// 通信协议 public void CreateDialog(string dialogId, string system, bool hasMemory, bool streamMode, ChatGPTModel chatGPTModel, double temperature, XFEComProtocol comProtocol) { xFEGPTMemoryDialog.Add(dialogId, new XFEGPTMessageCollection(new XFEGPTMessage[] { new XFEGPTMessage(dialogId, new GPTMessage("system", system)) }, streamMode, chatGPTModel, comProtocol, hasMemory, temperature)); } #endregion #region 插入对话 /// /// 插入对话 /// /// 要插入的对话ID /// 用户对话内容 /// AI对话的内容 /// 插入的消息ID public string InsertDialog(string dialogId, string userMessage, string assistantMessage) { string messageId = Guid.NewGuid().ToString(); xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId, new GPTMessage("user", userMessage))); xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId + "_Assistant", new GPTMessage("assistant", assistantMessage))); return messageId; } /// /// 插入对话 /// /// 要插入的对话ID /// 插入的消息ID /// 用户对话内容 /// AI对话的内容 public void InsertDialog(string dialogId, string messageId, string userMessage, string assistantMessage) { xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId, new GPTMessage("user", userMessage))); xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId + "_Assistant", new GPTMessage("assistant", assistantMessage))); } /// /// 插入对话 /// /// 要插入的对话ID /// 对话,以二维数组的形式 /// public string[] InsertDialog(string dialogId, string[,] dialogMessage) { try { if (dialogMessage.GetLength(1) != 2) { throw new XFEChatGPTException("dialogMessage的格式不正确!应为string[任意数量,2]"); } else if (dialogMessage.Length % 2 == 1) { throw new XFEChatGPTException("dialogMessage不合法!只能成对添加user和assistant"); } else { string[] messageId = new string[dialogMessage.Length]; for (int i = 0; i < dialogMessage.Length; i += 2) { messageId[i] = Guid.NewGuid().ToString(); messageId[i + 1] = messageId[i] + "_Assistant"; xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId[i], new GPTMessage("user", dialogMessage[i == 0 ? 0 : i / 2, 0]))); xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId[i + 1], new GPTMessage("assistant", dialogMessage[i == 0 ? 0 : i / 2, 1]))); } return messageId; } } catch (IndexOutOfRangeException ex) { throw new XFEChatGPTException("dialogMessage的格式不正确!应为string[任意数量,2]", ex); } } /// /// 插入对话 /// /// 要插入的对话ID /// 对话 /// /// public string[] InsertDialog(string dialogId, params string[] dialogMessage) { try { if (dialogMessage.Length % 2 == 1) { throw new XFEChatGPTException("dialogMessage不合法!只能成对添加user和assistant"); } else { string[] messageId = new string[dialogMessage.Length]; for (int i = 0; i < dialogMessage.Length; i += 2) { messageId[i] = Guid.NewGuid().ToString(); messageId[i + 1] = messageId[i] + "_Assistant"; xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId[i], new GPTMessage("user", dialogMessage[i]))); xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId[i + 1], new GPTMessage("assistant", dialogMessage[i + 1]))); } return messageId; } } catch (IndexOutOfRangeException ex) { throw new XFEChatGPTException("dialogMessage的格式不正确!应为string[任意数量,2]", ex); } } /// /// 插入对话 /// /// 要插入的对话ID /// 对话的消息ID,以数组的形式 /// 对话,以二维数组的形式 /// public void InsertDialog(string dialogId, string[] messageId, string[,] dialogMessage) { try { if (messageId.Length != dialogMessage.Length) { throw new XFEChatGPTException("messageId与dialogMessage数量不对应"); } else if (dialogMessage.GetLength(1) != 2) { throw new XFEChatGPTException("dialogMessage的格式不正确!应为string[任意数量,2]"); } else if (dialogMessage.Length % 2 == 1) { throw new XFEChatGPTException("dialogMessage不合法!只能成对添加user和assistant"); } else { for (int i = 0; i < dialogMessage.Length; i += 2) { xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId[i], new GPTMessage("user", dialogMessage[i == 0 ? 0 : i / 2, 0]))); xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId[i + 1], new GPTMessage("assistant", dialogMessage[i == 0 ? 0 : i / 2, 1]))); } } } catch (IndexOutOfRangeException ex) { throw new Exception("dialogMessage的格式不正确!应为string[任意数量,2]", ex); } } /// /// 插入对话 /// /// 要插入的对话ID /// 对话的消息ID,以数组的形式 /// 对话,以一维数组的形式 /// public void InsertDialog(string dialogId, string[] messageId, string[] dialogMessage) { try { if (messageId.Length != dialogMessage.Length) { throw new XFEChatGPTException("messageId与dialogMessage数量不对应"); } else if (dialogMessage.Length % 2 == 1) { throw new XFEChatGPTException("dialogMessage不合法!只能成对添加user和assistant"); } else { for (int i = 0; i < dialogMessage.Length; i += 2) { xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId[i], new GPTMessage("user", dialogMessage[i]))); xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId[i + 1], new GPTMessage("assistant", dialogMessage[i + 1]))); } } } catch (IndexOutOfRangeException ex) { throw new XFEChatGPTException("dialogMessage的格式不正确!应为string[任意数量,2]", ex); } } /// /// 插入对话,自动补全对话 /// /// 要插入的对话ID /// 对话 /// /// public string[] InsertDialogAutoComplete(string dialogId, params string[] dialogMessage) { try { string[] messageId = dialogMessage.Length % 2 == 0 ? new string[dialogMessage.Length] : new string[dialogMessage.Length + 1]; for (int i = 0; i < dialogMessage.Length; i += 2) { messageId[i] = Guid.NewGuid().ToString(); messageId[i + 1] = messageId[i] + "_Assistant"; xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId[i], new GPTMessage("user", dialogMessage[i]))); xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId[i + 1], new GPTMessage("assistant", dialogMessage.Length > i + 1 ? dialogMessage[i + 1] : "该条问题未回复"))); } return messageId; } catch (IndexOutOfRangeException ex) { throw new XFEChatGPTException("dialogMessage的格式不正确!", ex); } } #endregion #region 其余操作 /// /// 获取对话 /// /// 对话ID /// public GPTMessage[] GetDialog(string dialogId) { return xFEGPTMemoryDialog[dialogId].GetGPTMessages(); } /// /// 以字符串数组的形式获取对话 /// /// /// public string[] GetDialogStrings(string dialogId) { return xFEGPTMemoryDialog[dialogId].GetGPTMessageStrings(); } #endregion #region 开始对话 /// /// 开始对话 /// /// 对话ID /// 本消息ID /// 询问的内容 public void AskChatGPT(string dialogId, string messageId, string askMessage) { if (xFEGPTMemoryDialog[dialogId].GetGPTMessages().CheckLegal()) { //判断如果最后一条消息是用户消息,则在添加新的用户消息前添加一条助手消息然后再添加用户消息,否则直接添加用户消息 if (xFEGPTMemoryDialog[dialogId].GetLastRole() == "user") { xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId + "_Assistant", new GPTMessage("assistant", "正在思考中..."))); xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId, new GPTMessage("user", askMessage))); } else { xFEGPTMemoryDialog[dialogId].Add(new XFEGPTMessage(messageId, new GPTMessage("user", askMessage))); } var nowThread = new Thread(StartGetGPTMessage); nowThread.Start(new MessageIdDialogIdAndThread(messageId, dialogId, nowThread)); } else { throw new XFEChatGPTException("对话信息不合法"); } } #endregion #region 停止对话 //TODO: #endregion #endregion #region 线程方法 private async void StartGetGPTMessage(object sender) { var messageIdAndThread = (MessageIdDialogIdAndThread)sender; string dialogId = messageIdAndThread.dialogId; string messageId = messageIdAndThread.messageId; Thread thread = messageIdAndThread.thread; var nowDialog = xFEGPTMemoryDialog[dialogId]; if (nowDialog.StreamMode) { bool isStarted = false; try { #region 进行HTTP请求 ClientWebSocket webSocket = new ClientWebSocket(); await webSocket.ConnectAsync(new Uri("ws://gpt.api.xfegzs.com/"), CancellationToken.None); if (nowDialog.MemorableMode) { await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(nowDialog.CreateAskMessage().ConvertToJson())), WebSocketMessageType.Text, true, CancellationToken.None); } else { await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(new XFEAskGPTMessage(false, nowDialog.StreamMode, nowDialog.ChatGPTModel.GetModelString(), null, nowDialog.XFEComProtocol, nowDialog.System, nowDialog[nowDialog.Count - 1].gPTMessage.Content).ConvertToJson())), WebSocketMessageType.Text, true, CancellationToken.None); } #endregion while (true) { #region 读取消息 byte[] buffer = new byte[1024]; WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);//接收消息 string nowReceivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count);//将消息转换为字符串 #endregion if (nowDialog.XFEComProtocol == XFEComProtocol.XFEFAST) { if (nowReceivedMessage == "[DONE]") { XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs("[XFEDONE]", messageId, GenerateState.End, dialogId)); break; } else if (nowReceivedMessage.Contains("[XFERemoteAPIError]")) { if (!isStarted) { XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs("[XFESTART]", messageId, GenerateState.Start, dialogId)); xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", "该回复发生了一个错误,可能需要重新回复", true); } else { xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", "该回复发生了一个错误,可能需要重新回复", false); } XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs(nowReceivedMessage.Replace("[XFERemoteAPIError]", string.Empty), messageId, GenerateState.Error, dialogId)); } else if (nowReceivedMessage == "[XFE]") { XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs("[XFESTART]", messageId, GenerateState.Start, dialogId)); isStarted = true; xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", string.Empty, true); } else { xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", nowReceivedMessage, false); XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs(nowReceivedMessage, messageId, GenerateState.Continue, dialogId)); } } else { if (nowReceivedMessage == "[DONE]") { XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs("[XFEDONE]", messageId, GenerateState.End, dialogId)); break; } else if (nowReceivedMessage.Contains("[XFERemoteAPIError]")) { if (!isStarted) { XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs("[XFESTART]", messageId, GenerateState.Start, dialogId)); xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", "该回复发生了一个错误,可能需要重新回复", true); } else { xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", "该回复发生了一个错误,可能需要重新回复", false); } XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs(nowReceivedMessage.Replace("[XFERemoteAPIError]", string.Empty), messageId, GenerateState.Error, dialogId)); } else if (nowReceivedMessage == "[XFE]") { XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs("[XFESTART]", messageId, GenerateState.Start, dialogId)); isStarted = true; xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", string.Empty, true); } else { if (nowReceivedMessage.Contains("[XFE]")) { nowReceivedMessage = nowReceivedMessage.Replace("[XFE]", string.Empty); xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", nowReceivedMessage, false); XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs(nowReceivedMessage, messageId, GenerateState.Continue, dialogId)); } else { if (!isStarted) { XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs("[XFESTART]", messageId, GenerateState.Start, dialogId)); xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", "该回复发生了一个错误,可能需要重新回复", true); } else { xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", "该回复发生了一个错误,可能需要重新回复", false); } } } } } await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection closed.", CancellationToken.None); } catch (Exception ex) when (!(ex is XFEChatGPTException)) { if (!isStarted) { XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs("[XFESTART]", messageId, GenerateState.Start, dialogId)); xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", "该回复发生了一个错误,可能需要重新回复", true); } else { xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", "该回复发生了一个错误,可能需要重新回复", false); } XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs(ex.ToString(), messageId, GenerateState.Error, dialogId)); Console.WriteLine(ex.ToString()); } } else { try { #region 进行HTTP请求 ClientWebSocket webSocket = new ClientWebSocket(); await webSocket.ConnectAsync(new Uri("ws://gpt.api.xfegzs.com/"), CancellationToken.None); if (nowDialog.MemorableMode) { await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(nowDialog.CreateAskMessage().ConvertToJson())), WebSocketMessageType.Text, true, CancellationToken.None); } else { await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(new XFEAskGPTMessage(false, nowDialog.StreamMode, nowDialog.ChatGPTModel.GetModelString(), null, nowDialog.XFEComProtocol, nowDialog.System, nowDialog[nowDialog.Count - 1].gPTMessage.Content).ConvertToJson())), WebSocketMessageType.Text, true, CancellationToken.None); } #endregion #region 读取消息 byte[] buffer = new byte[1024]; WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);//接收消息 string nowReceivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count);//将消息转换为字符串 #endregion if (nowReceivedMessage.Contains("[XFE]")) { nowReceivedMessage = nowReceivedMessage.Replace("[XFE]", string.Empty); xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", nowReceivedMessage, true); XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs(nowReceivedMessage, messageId, GenerateState.Start, dialogId)); } else { xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", nowReceivedMessage, true); XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs(nowReceivedMessage.Replace("[XFERemoteAPIError]", string.Empty), messageId, GenerateState.Error, dialogId)); } await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection closed.", CancellationToken.None); } catch (Exception ex) { xFEGPTMemoryDialog.InstanceUpdate(dialogId, messageId + "_Assistant", ex.ToString(), true); XFEChatGPTMessageReceived.Invoke(this, new PrivateMemorableGPTMessageReceivedEventArgs(ex.ToString(), messageId, GenerateState.Error, dialogId)); Console.WriteLine(ex.ToString()); } } threadList.Remove(thread); } #endregion #region 公有事件 /// /// 当收到ChatGPT的消息时触发 /// public event EventHandler XFEChatGPTMessageReceived; #endregion #region 构造方法 /// /// 创建一个有记忆功能的XFEChatGPT对象 /// public MemorableXFEChatGPT() { xFEGPTMemoryDialog = new PrivateXFEGPTMemoryDialog(); } #endregion } /// /// XFEChatGPT的扩展方法 /// public static class XFEChatGPTExtension { /// /// 检查是否合法(system在最前,接着是user,然后是Assistant,以此类推...,不能连着2个user或者Assistant) /// /// 是否合法 public static bool CheckLegal(this GPTMessage[] xFEGPTMessages) { if (xFEGPTMessages.Length == 0) { return true; } else { if (xFEGPTMessages[0].Role != "system") { return false; } else { string lastRole = xFEGPTMessages[0].Role; for (int i = 1; i < xFEGPTMessages.Length; i++) { if (xFEGPTMessages[i].Role == lastRole) { return false; } else { lastRole = xFEGPTMessages[i].Role; } } return true; } } } } #region ChatGPT类 #region ChatGPT默认类 /// /// 接收到的GPT消息 /// public abstract class ReceivedGPTMessage { /// /// 消息ID /// public string id { get; private set; } /// /// 消息对象 /// public string Object { get; private set; } /// /// 消息创建时间 /// public long created { get; private set; } /// /// 使用的GPT模型 /// public string model { get; private set; } /// /// Token令牌的使用情况 /// public TokenUsage usage { get; private set; } /// /// GPT返回的具体数据(数组的形式) /// public MessageChoice[] choices { get; private set; } /// /// 接收到的GPT消息 /// /// /// /// /// /// /// public ReceivedGPTMessage(string id, string @object, long created, string model, TokenUsage usage, MessageChoice[] choices) { this.id = id; Object = @object; this.created = created; this.model = model; this.usage = usage; this.choices = choices; } } /// /// GPT消息链的组成单元 /// public abstract class MessageChoice { /// /// Delta消息(用于流式接收) /// public GPTMessage delta { get; private set; } /// /// 单个消息(用于单个接收) /// public GPTMessage message { get; private set; } /// /// 结束原因 /// public string finish_reason { get; private set; } /// /// 消息索引 /// public int index { get; private set; } /// /// GPT消息链的组成单元 /// /// /// /// /// public MessageChoice(GPTMessage delta, GPTMessage message, string finish_reason, int index) { this.delta = delta; this.message = message; this.finish_reason = finish_reason; this.index = index; } /// /// GPT消息链的组成单元 /// /// GPTMessage消息对象 /// 结束原因 /// 消息索引 public MessageChoice(GPTMessage message, string finish_reason, int index) { this.message = message; this.finish_reason = finish_reason; this.index = index; } } /// /// Token令牌的使用情况 /// public class TokenUsage { /// /// 用于提示的Token令牌 /// public int prompt_tokens { get; private set; } /// /// 用于完成的Token令牌 /// public int completion_tokens { get; private set; } /// /// 总共使用的Token令牌 /// public int total_tokens { get; private set; } /// /// Token令牌的使用情况 /// /// /// /// public TokenUsage(int prompt_tokens, int completion_tokens, int total_tokens) { this.prompt_tokens = prompt_tokens; this.completion_tokens = completion_tokens; this.total_tokens = total_tokens; } } /// /// GPT环境数据 /// public class EnvironmentGPTData { /// /// 使用的GPT模型 /// public string model { get; set; } /// /// 是否为流式接收 /// public bool stream { get; set; } /// /// 温度,此处为GPT的创造性 /// public double temperature { get; set; } /// /// 发送给GPT的消息 /// public GPTMessage[] messages { get; set; } /// /// GPT环境数据 /// /// /// /// /// public EnvironmentGPTData(string model, bool stream, double temperature, GPTMessage[] messages) { this.model = model; this.stream = stream; this.temperature = temperature; this.messages = messages; } } /// /// GPT消息 /// public class GPTMessage { private string role; /// /// 角色(目前已知有:System,User和Assistant) /// public string Role { get { return role; } set { role = SetRoleAndCheckRoleLegal(value); } } /// /// 与角色对应的消息内容 /// public string Content { get; set; } private string SetRoleAndCheckRoleLegal(string inputRole) { string lowerRole = inputRole.ToLower(); if (lowerRole == "system" || lowerRole == "user" || lowerRole == "assistant") { return lowerRole; } else { throw new XFEChatGPTException($"角色名称不合法:{inputRole}\n应为system,user或assistant三者中的一个"); } } /// /// GPT消息 /// /// 角色 /// 内容 public GPTMessage(string role, string content) { this.role = role; this.Content = content; } } #endregion #region ChatGPT自定义类 class XFEAskGPTMessage { /// /// 获取或设置是否直接使用调用方提供的 GPT 环境数据。 /// public bool isSelfEditData { get; set; } /// /// 获取或设置是否以流式方式接收 GPT 响应。 /// public bool stream { get; set; } /// /// 获取或设置请求使用的 GPT 模型名称。 /// public string chatGPTModel { get; set; } /// /// 获取或设置调用方自定义的 GPT 环境数据。 /// public EnvironmentGPTData EnvironmentGPTData { get; set; } /// /// 获取或设置请求使用的 XFE 通讯协议。 /// public XFEComProtocol comProtocol { get; set; } /// /// 获取或设置用于定义 GPT 行为的系统消息内容。 /// public string systemContent { get; set; } /// /// 获取或设置发送给 GPT 的提问内容。 /// public string askContent { get; set; } /// /// 使用请求模式、模型、环境数据及消息内容创建 GPT 请求消息。 /// /// 是否直接使用调用方提供的 GPT 环境数据。 /// 是否以流式方式接收 GPT 响应。 /// 请求使用的 GPT 模型名称。 /// 调用方自定义的 GPT 环境数据。 /// 请求使用的 XFE 通讯协议。 /// 用于定义 GPT 行为的系统消息内容。 /// 发送给 GPT 的提问内容。 public XFEAskGPTMessage(bool isSelfEditData, bool stream, string chatGPTModel, EnvironmentGPTData EnvironmentGPTData, XFEComProtocol comProtocol, string systemContent, string askContent) { this.isSelfEditData = isSelfEditData; this.stream = stream; this.chatGPTModel = chatGPTModel; this.EnvironmentGPTData = EnvironmentGPTData; this.comProtocol = comProtocol; this.systemContent = systemContent; this.askContent = askContent; } /// /// 创建一个使用默认属性值的空 GPT 请求消息。 /// public XFEAskGPTMessage() { } } /// /// 从服务器接收到的GPT消息 /// public abstract class XFEGPTMessageReceivedEventArgs : EventArgs { /// /// 消息内容 /// public string message { get; set; } /// /// 消息接收器ID /// public string messageId { get; set; } /// /// 生成状态 /// public GenerateState generateState { get; set; } /// /// 从服务器接收到的GPT消息 /// /// /// /// public XFEGPTMessageReceivedEventArgs(string message, string messageId, GenerateState generateState) { this.message = message; this.messageId = messageId; this.generateState = generateState; } } class PrivateXFEGPTMessageReceivedEventArgs : XFEGPTMessageReceivedEventArgs { /// /// 创建包含消息内容、接收器 ID 和生成状态的 GPT 消息接收事件参数实现。 /// /// 从服务器接收到的消息内容。 /// 消息接收器 ID。 /// 当前消息的生成状态。 public PrivateXFEGPTMessageReceivedEventArgs(string message, string id, GenerateState generateState) : base(message, id, generateState) { } } /// /// 从服务器接收到的GPT消息(记忆模式) /// public abstract class MemorableGPTMessageReceivedEventArgs : XFEGPTMessageReceivedEventArgs { /// /// 对话ID /// public string dialogId { get; set; } /// /// 从服务器接收到的GPT消息(记忆模式) /// /// /// /// /// public MemorableGPTMessageReceivedEventArgs(string message, string id, GenerateState generateState, string dialogId) : base(message, id, generateState) { this.dialogId = dialogId; } } class PrivateMemorableGPTMessageReceivedEventArgs : MemorableGPTMessageReceivedEventArgs { /// /// 创建包含对话 ID 的记忆模式 GPT 消息接收事件参数实现。 /// /// 从服务器接收到的消息内容。 /// 消息接收器 ID。 /// 当前消息的生成状态。 /// 消息所属的对话 ID。 public PrivateMemorableGPTMessageReceivedEventArgs(string message, string id, GenerateState generateState, string dialogId) : base(message, id, generateState, dialogId) { } } class PrivateMessageChoice : MessageChoice { /// /// 创建同时包含流式增量消息和完整消息的 GPT 候选结果。 /// /// 流式接收时的增量消息。 /// 本次候选结果的完整消息。 /// 消息生成结束的原因。 /// 候选结果在响应中的索引。 public PrivateMessageChoice(GPTMessage delta, GPTMessage message, string finish_reason, int index) : base(delta, message, finish_reason, index) { } /// /// 创建仅包含完整消息的 GPT 候选结果。 /// /// 本次候选结果的完整消息。 /// 消息生成结束的原因。 /// 候选结果在响应中的索引。 public PrivateMessageChoice(GPTMessage message, string finish_reason, int index) : base(message, finish_reason, index) { } } class PrivateReceivedGPTMessage : ReceivedGPTMessage { /// /// 使用响应元数据、令牌用量和候选结果创建接收到的 GPT 消息实现。 /// /// GPT 响应的消息 ID。 /// 响应对象的类型标识。 /// 响应的创建时间戳。 /// 生成响应所使用的 GPT 模型。 /// 本次响应的令牌使用情况。 /// GPT 返回的候选消息集合。 public PrivateReceivedGPTMessage(string id, string @object, long created, string model, TokenUsage usage, PrivateMessageChoice[] choices) : base(id, @object, created, model, usage, choices) { } } /// /// XFEGPT消息(具有消息ID) /// public class XFEGPTMessage { /// /// 消息ID /// public string messageId { get; set; } /// /// GPT消息 /// public GPTMessage gPTMessage { get; set; } /// /// XFEGPT消息(具有消息ID) /// /// 消息ID /// GPT消息 public XFEGPTMessage(string messageId, GPTMessage gPTMessage) { this.messageId = messageId; this.gPTMessage = gPTMessage; } } /// /// XFEGPT的对话 /// public class XFEGPTMessageCollection : IEnumerable { #region 属性 private readonly List xFEGPTMessages; /// /// 消息数量 /// public int Count { get { return xFEGPTMessages.Count; } } /// /// XFE通讯协议 /// public XFEComProtocol XFEComProtocol { get; set; } /// /// 使用的模型 /// public ChatGPTModel ChatGPTModel { get; set; } /// /// 是否为流式输出 /// public bool StreamMode { get; set; } /// /// 是否为记忆模式 /// public bool MemorableMode { get; set; } /// /// 对话的系统设置 /// public string System { get { if (xFEGPTMessages.Count > 0 && xFEGPTMessages[0].gPTMessage.Role == "system") { return xFEGPTMessages[0].gPTMessage.Content; } else { throw new XFEChatGPTException("消息集合中没有系统消息!"); } } set { if (xFEGPTMessages.Count > 0 && xFEGPTMessages[0].gPTMessage.Role == "system") { xFEGPTMessages[0].gPTMessage.Content = value; } else { throw new XFEChatGPTException("消息集合中没有系统消息!"); } } } /// /// 对话的Temperature /// public double Temperature { get; set; } #endregion #region 外部方法 /// /// 添加XFEGPT消息 /// /// public void Add(XFEGPTMessage xFEGPTMessage) { xFEGPTMessages.Add(xFEGPTMessage); } /// /// 添加XFEGPT消息 /// /// public void AddRange(XFEGPTMessage[] xFEGPTMessages) { this.xFEGPTMessages.AddRange(xFEGPTMessages); } /// /// 根据指定的ID移除XFEGPT消息 /// /// public void RemoveAt(int index) { xFEGPTMessages.RemoveAt(index); } /// /// 移除XFEGPT消息 /// /// public void Remove(XFEGPTMessage xFEGPTMessage) { xFEGPTMessages.Remove(xFEGPTMessage); } /// /// 根据指定的ID在其后插入XFEGPT消息 /// /// /// /// public void InsertByMessageId(string messageId, XFEGPTMessage xFEGPTMessage) { for (int i = 0; i < xFEGPTMessages.Count; i++) { if (xFEGPTMessages[i].messageId == messageId) { xFEGPTMessages.Insert(i, xFEGPTMessage); return; } } throw new XFEChatGPTException("消息集合中没有指定ID的消息!"); } /// /// 清除XFEGPT消息 /// public void Clear() { xFEGPTMessages.Clear(); } /// /// 通过消息ID获取XFEGPT消息 /// /// /// public XFEGPTMessage GetXFEGPTMessageByMessageId(string messageId) { foreach (XFEGPTMessage xFEGPTMessage in xFEGPTMessages) { if (xFEGPTMessage.messageId == messageId) { return xFEGPTMessage; } } return null; } /// /// 获取本集合的GPTMessage数组 /// /// public GPTMessage[] GetGPTMessages() { List gPTMessages = new List(); foreach (XFEGPTMessage xFEGPTMessage in xFEGPTMessages) { gPTMessages.Add(xFEGPTMessage.gPTMessage); } return gPTMessages.ToArray(); } /// /// 以字符串的形式获取本集合的GPTMessage数组 /// /// public string[] GetGPTMessageStrings() { List gPTMessages = new List(); foreach (XFEGPTMessage xFEGPTMessage in xFEGPTMessages) { gPTMessages.Add(xFEGPTMessage.gPTMessage.Content); } return gPTMessages.ToArray(); } /// /// 对本集合进行索引器操作 /// /// 索引 /// public XFEGPTMessage this[int index] { get { return xFEGPTMessages[index]; } set { xFEGPTMessages[index] = value; } } /// /// 获取最后一个角色 /// /// 最后一个角色 public string GetLastRole() { return xFEGPTMessages[Count - 1].gPTMessage.Role; } internal XFEAskGPTMessage CreateAskMessage() { return new XFEAskGPTMessage(true, StreamMode, ChatGPTModel.GetModelString(), new EnvironmentGPTData(ChatGPTModel.GetModelString(), StreamMode, Temperature, GetGPTMessages()), XFEComProtocol, string.Empty, string.Empty); } /// /// 获取迭代器 /// /// public IEnumerator GetEnumerator() { return xFEGPTMessages.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return xFEGPTMessages.GetEnumerator(); } #endregion #region 构造方法 /// /// XFEGPT的对话 /// /// /// /// /// /// /// public XFEGPTMessageCollection(XFEGPTMessage[] xFEGPTMessages, bool memorableMode, ChatGPTModel chatGPTModel, XFEComProtocol comProtocol, bool streamMode, double temperature) { this.xFEGPTMessages = new List(xFEGPTMessages); MemorableMode = memorableMode; XFEComProtocol = comProtocol; ChatGPTModel = chatGPTModel; StreamMode = streamMode; Temperature = temperature; } /// /// XFEGPT的对话 /// internal XFEGPTMessageCollection() { xFEGPTMessages = new List(); } #endregion } /// /// GPT对话记录 /// public abstract class XFEGPTMemoryDialog : IEnumerable { private Dictionary gPTMessageWithId; internal XFEGPTMemoryDialog() { gPTMessageWithId = new Dictionary(); } #region 操作部分 /// /// 通过对话ID操作对话 /// /// 对话的ID /// public XFEGPTMessageCollection this[string dialogId] { get { try { return gPTMessageWithId[dialogId]; } catch (Exception ex) { throw new XFEChatGPTException("查找指定ID的对话时出错!", ex); } } set { try { gPTMessageWithId[dialogId] = value; } catch (Exception ex) { throw new XFEChatGPTException("设置指定ID的对话时出错!", ex); } } } /// /// 添加一个对话记录 /// /// 对话ID /// XFEGPT的对话 public void Add(string dialogId, XFEGPTMessageCollection xFEGPTMessages) { gPTMessageWithId.Add(dialogId, xFEGPTMessages); } /// /// 添加多个对话记录 /// /// ID和XFEGPT的对话的键值对 public void AddRange(KeyValuePair[] messages) { foreach (var item in messages) { gPTMessageWithId.Add(item.Key, item.Value); } } /// /// 移除一个对话记录 /// /// 对话ID public void Remove(string dialogId) { gPTMessageWithId.Remove(dialogId); } /// /// 移除多个对话记录 /// /// 对话ID的数组 public void RemoveRange(string[] ids) { foreach (var item in ids) { gPTMessageWithId.Remove(item); } } /// /// 清空所有对话的对话记录 /// public void Clear() { gPTMessageWithId.Clear(); } /// /// 更新指定对话ID的对话记录 /// /// 对话ID /// XFEGPT的对话 public void Update(string dialogId, XFEGPTMessageCollection messages) { gPTMessageWithId[dialogId] = messages; } /// /// 实时更新对话记录 /// /// /// /// /// public void InstanceUpdate(string dialogId, string messageId, string nowMessage, bool clear) { var xFEGPTMessages = gPTMessageWithId[dialogId]; if (xFEGPTMessages.GetXFEGPTMessageByMessageId(messageId) is null) { xFEGPTMessages.Add(new XFEGPTMessage(messageId, new GPTMessage("assistant", nowMessage))); } else { if (xFEGPTMessages.GetLastRole() == "system") { throw new XFEChatGPTException("系统消息无法更改"); } else { if (clear) { xFEGPTMessages.GetXFEGPTMessageByMessageId(messageId).gPTMessage.Content = nowMessage; } else { xFEGPTMessages.GetXFEGPTMessageByMessageId(messageId).gPTMessage.Content += nowMessage; } } } } #endregion #region 获取部分 /// /// 判断是否包含某个对话 /// /// 对话ID /// 是否含有该对话 public bool Contains(string dialogId) { return gPTMessageWithId.ContainsKey(dialogId); } /// /// 获取对话记录 /// /// 对话ID /// public XFEGPTMessageCollection GetXFEGPTMessages(string dialogId) { return gPTMessageWithId[dialogId]; } /// /// 获取迭代器 /// /// public IEnumerator GetEnumerator() { foreach (var item in gPTMessageWithId) { foreach (var item2 in item.Value) { yield return item2; } } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #endregion } class PrivateXFEGPTMemoryDialog : XFEGPTMemoryDialog { /// /// 创建一个使用默认设置的 GPT 记忆对话实现。 /// public PrivateXFEGPTMemoryDialog() { } } /// /// API密钥 /// public class ApiKey { /// /// APIKEY /// public string APIKey { get; set; } /// /// APIKey的描述 /// public string Description { get; set; } /// /// 转换为字符串 /// /// public override string ToString() { return $"{{[+-{Description}-+][+-{APIKey}-+]}}"; } /// /// 将字符串转换为ApiKey的List /// /// /// public static List ToApiKey(string keyString) { string[] keyGroup = keyString.Split(new char[] { '{', '}' }); List apiKeys = new List(); foreach (string key in keyGroup) { string[] oneKey = key.Split(new string[] { "[+-", "-+]" }, StringSplitOptions.RemoveEmptyEntries); if (oneKey.Length == 2) { apiKeys.Add(new ApiKey(oneKey[1], oneKey[0])); } } return apiKeys; } /// /// APIKey秘钥 /// /// 秘钥 /// 描述 public ApiKey(string APIKey, string Description) { this.APIKey = APIKey; this.Description = Description; } } #endregion #endregion #region 其余类 class MessageIdAndThread { /// /// 获取或设置后台处理线程所对应的消息 ID。 /// public string messageId { get; set; } /// /// 获取或设置处理该消息的线程。 /// public Thread thread { get; set; } /// /// 创建消息 ID 与后台处理线程之间的关联记录。 /// /// 后台处理线程所对应的消息 ID。 /// 处理该消息的线程。 public MessageIdAndThread(string messageId, Thread thread) { this.messageId = messageId; this.thread = thread; } } class MessageIdDialogIdAndThread : MessageIdAndThread { /// /// 获取或设置后台处理线程所对应的对话 ID。 /// public string dialogId { get; set; } /// /// 创建消息 ID、对话 ID 与后台处理线程之间的关联记录。 /// /// 后台处理线程所对应的消息 ID。 /// 后台处理线程所对应的对话 ID。 /// 处理该消息的线程。 public MessageIdDialogIdAndThread(string messageId, string dialogId, Thread thread) : base(messageId, thread) { this.dialogId = dialogId; } } #endregion }