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
}