添加连续对话 调试模式

This commit is contained in:
ddaodan 2024-07-21 14:18:47 +08:00
parent b8aaaaf6a3
commit 0944aa1a85
9 changed files with 190 additions and 9 deletions

View File

@ -13,13 +13,24 @@
- [ ] 自定义prompt
## 安装
- 下载插件放在plugins文件夹中
- 重启服务器
1. 下载插件放在plugins文件夹中
2. 重启服务器
> 为兼容更多版本插件使用1.13版本进行构建,因此在较高版本加载插件时,控制台会出现以下错误信息,这属于正常现象。
> ```
> [Server thread/WARN]: Initializing Legacy Material Support. Unless you have legacy plugins and/or data this is a bug!
> [Server thread/WARN]: Legacy plugin MineChatGPT v1.0 does not specify an api-version.
> ```
3. 打开配置文件`config.yml`,修改以下两项设置:
```yaml
# API 相关设置
api:
# 你的 OpenAI API key用于身份验证
# 获取 API key 的方法:访问 https://platform.openai.com/account/api-keys 并创建一个新的 API key
key: "sk-your_openai_api_key"
# OpenAI API 的基础 URL用于构建请求
base_url: "https://api.openai.com/v1"
```
4. 输入`/chatgpt reload`重新加载配置文件
## 截图
- 服务端截图Spigot 1.20.1
@ -95,6 +106,7 @@ version: 2.1
|Mohist 1.20.1|✔|
|Spigot 1.20.1|✔|
|Spigot 1.12.2|✔|
|KCauldron 1.7.10|×|
## 常见问题
### `Failed to contact ChatGPT.` `无法联系ChatGPT。`

View File

@ -9,6 +9,10 @@ import org.json.JSONObject;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.nio.charset.StandardCharsets;
import java.io.UnsupportedEncodingException;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
@ -16,20 +20,33 @@ public class CommandHandler implements CommandExecutor {
private final Main plugin;
private final ConfigManager configManager;
private static final Logger logger = Logger.getLogger(CommandHandler.class.getName());
private final Map<String, ConversationContext> userContexts;
private final Map<String, Boolean> userContextEnabled;
public CommandHandler(Main plugin, ConfigManager configManager) {
this.plugin = plugin;
this.configManager = configManager;
this.userContexts = new HashMap<>();
this.userContextEnabled = new HashMap<>();
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
String userId = sender.getName();
if (!userContexts.containsKey(userId)) {
userContexts.put(userId, new ConversationContext(configManager.getMaxHistorySize()));
userContextEnabled.put(userId, configManager.isContextEnabled()); // 使用配置文件中的默认值
}
ConversationContext conversationContext = userContexts.get(userId);
boolean contextEnabled = userContextEnabled.get(userId);
if (command.getName().equalsIgnoreCase("chatgpt")) {
if (args.length == 0) {
sendHelpMessage(sender);
return true;
}
String subCommand = args[0];
if (subCommand.equalsIgnoreCase("reload")) {
if (!sender.hasPermission("minechatgpt.reload")) {
@ -70,6 +87,20 @@ public class CommandHandler implements CommandExecutor {
sender.sendMessage("- " + model);
}
return true;
} else if (args.length > 0 && args[0].equalsIgnoreCase("context")) {
contextEnabled = !contextEnabled; // 切换上下文开关状态
userContextEnabled.put(userId, contextEnabled);
String status = contextEnabled ? configManager.getContextToggleEnabledMessage() : configManager.getContextToggleDisabledMessage();
sender.sendMessage(configManager.getContextToggleMessage().replace("%s", status));
return true;
} else if (subCommand.equalsIgnoreCase("clear")) {
if (!sender.hasPermission("minechatgpt.clear")) {
sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.clear"));
return true;
}
conversationContext.clearHistory();
sender.sendMessage(configManager.getClearMessage());
return true;
} else {
if (!sender.hasPermission("minechatgpt.use")) {
sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.use"));
@ -77,49 +108,91 @@ public class CommandHandler implements CommandExecutor {
}
String question = String.join(" ", args);
// Logic to send question to ChatGPT
if (contextEnabled) {
conversationContext.addMessage(question); // 仅在启用上下文时添加到历史记录
}
sender.sendMessage(configManager.getQuestionMessage().replace("%s", question));
askChatGPT(sender, question);
askChatGPT(sender, question, conversationContext, contextEnabled);
return true;
}
}
return false;
}
private void askChatGPT(CommandSender sender, String question) {
private void askChatGPT(CommandSender sender, String question, ConversationContext conversationContext, boolean contextEnabled) {
logger.info("Original question: " + question);
// 尝试将问题转换为 UTF-8 编码
String utf8Question = convertToUTF8(question);
logger.info("Converted question: " + utf8Question);
JSONObject json = new JSONObject();
json.put("model", configManager.getDefaultModel());
JSONArray messages = new JSONArray();
JSONObject message = new JSONObject();
message.put("role", "user");
message.put("content", question);
message.put("content", utf8Question);
//message.put("content", question);
messages.put(message);
if (contextEnabled) {
String history = conversationContext.getConversationHistory();
if (!history.isEmpty()) {
JSONObject historyMessage = new JSONObject();
historyMessage.put("role", "system");
historyMessage.put("content", history);
messages.put(historyMessage);
}
}
json.put("messages", messages);
json.put("model", configManager.getCurrentModel());
// 记录构建的请求
logger.info("Built request: " + json.toString());
HttpRequest request = HttpRequest.post(configManager.getBaseUrl() + "/chat/completions")
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + configManager.getApiKey())
.body(json.toString());
if (configManager.isDebugMode()) {
logger.info("Sending request to ChatGPT: " + request.toString());
}
HttpResponse response = request.send();
if (configManager.isDebugMode()) {
logger.info("Received response from ChatGPT: " + response.toString());
}
if (response.statusCode() == 200) {
String responseBody = response.bodyText();
JSONObject jsonResponse = new JSONObject(responseBody);
String answer = jsonResponse.getJSONArray("choices").getJSONObject(0).getJSONObject("message").getString("content");
sender.sendMessage(configManager.getChatGPTResponseMessage().replace("%s", answer));
if (contextEnabled) {
conversationContext.addMessage(answer); // 仅在启用上下文时添加AI响应到历史记录
}
} else {
String errorBody = response.bodyText();
logger.log(Level.SEVERE, "Failed to get a response from ChatGPT: " + errorBody);
sender.sendMessage(configManager.getChatGPTErrorMessage());
}
}
private String convertToUTF8(String input) {
try {
// 尝试将输入字符串转换为 UTF-8 编码
byte[] bytes = input.getBytes(StandardCharsets.UTF_8);
return new String(bytes, StandardCharsets.UTF_8);
} catch (Exception e) {
logger.severe("Failed to convert input to UTF-8: " + e.getMessage());
return input; // 如果转换失败返回原始输入
}
}
private void sendHelpMessage(CommandSender sender) {
sender.sendMessage(configManager.getHelpMessage());
sender.sendMessage(configManager.getHelpAskMessage());
sender.sendMessage(configManager.getHelpReloadMessage());
sender.sendMessage(configManager.getHelpModelMessage());
sender.sendMessage(configManager.getHelpModelListMessage());
sender.sendMessage(configManager.getHelpContextMessage());
sender.sendMessage(configManager.getHelpClearMessage());
}
}

View File

@ -13,7 +13,9 @@ public class ConfigManager {
this.plugin = plugin;
reloadConfig();
}
public boolean isDebugMode() {
return config.getBoolean("debug", false);
}
public void reloadConfig() {
plugin.reloadConfig();
config = plugin.getConfig();
@ -74,6 +76,15 @@ public class ConfigManager {
return translateColorCodes(config.getString("messages.help_modellist"));
}
public String getHelpContextMessage() {
return translateColorCodes(config.getString("messages.help_context", "/chatgpt context - Toggle context mode."));
}
public String getHelpClearMessage() {
return translateColorCodes(config.getString("messages.help_clear", "/chatgpt clear - Clear conversation history."));
}
public String getModelSwitchMessage() {
return translateColorCodes(config.getString("messages.model_switch"));
}
@ -105,4 +116,27 @@ public class ConfigManager {
public String getCurrentModelInfoMessage() {
return translateColorCodes(config.getString("messages.current_model_info"));
}
public int getMaxHistorySize() {
return config.getInt("conversation.max_history_size", 10);
}
public boolean isContextEnabled() {
return config.getBoolean("conversation.context_enabled", false);
}
public String getContextToggleMessage() {
return translateColorCodes(config.getString("messages.context_toggle", "Context is now %s."));
}
public String getContextToggleEnabledMessage() {
return translateColorCodes(config.getString("messages.context_toggle_enabled", "enabled"));
}
public String getContextToggleDisabledMessage() {
return translateColorCodes(config.getString("messages.context_toggle_disabled", "disabled"));
}
public String getClearMessage() {
return translateColorCodes(config.getString("messages.clear", "Conversation history has been cleared."));
}
}

View File

@ -0,0 +1,29 @@
package com.ddaodan.MineChatGPT;
import java.util.LinkedList;
import java.util.Queue;
public class ConversationContext {
private Queue<String> conversationHistory;
private int maxHistorySize;
public ConversationContext(int maxHistorySize) {
this.maxHistorySize = maxHistorySize;
this.conversationHistory = new LinkedList<>();
}
public void addMessage(String message) {
if (conversationHistory.size() >= maxHistorySize) {
conversationHistory.poll(); // Remove the oldest message
}
conversationHistory.offer(message); // Add the new message
}
public String getConversationHistory() {
return String.join("\n", conversationHistory);
}
public void clearHistory() {
conversationHistory.clear();
}
}

View File

@ -20,6 +20,9 @@ public final class Main extends JavaPlugin {
Objects.requireNonNull(getCommand("chatgpt")).setExecutor(commandHandler);
Objects.requireNonNull(getCommand("chatgpt")).setTabCompleter(tabCompleter);
checkAndUpdateConfig();
if (configManager.isDebugMode()) {
getLogger().info( "DEBUG MODE IS TRUE!!!!!");
}
// Initialize bStats
int pluginId = 22635;
new Metrics(this, pluginId);

View File

@ -23,6 +23,8 @@ public class MineChatGPTTabCompleter implements TabCompleter {
completions.add("reload");
completions.add("model");
completions.add("modellist");
completions.add("context");
completions.add("clear");
} else if (args.length == 2 && args[0].equalsIgnoreCase("model")) {
// 补全模型名称
completions.addAll(configManager.getModels());

View File

@ -23,14 +23,23 @@ models:
# And more...
# The default model to use
default_model: "gpt-3.5-turbo"
conversation:
max_history_size: 10
context_enabled: false
# Message settings
messages:
reload: "&aConfiguration reloaded successfully!"
clear: "Conversation history has been cleared!"
help: "&e===== MineChatGPT Help ====="
help_ask: "&e/chatgpt <text> - Ask ChatGPT a question."
help_reload: "&e/chatgpt reload - Reload the configuration file."
help_model: "&e/chatgpt model <model_name> - Switch to a different model."
help_modellist: "&e/chatgpt modellist - List available models."
help_context: "/chatgpt context - Toggle context mode."
help_clear: "/chatgpt clear - Clear conversation history."
context_toggle: "Context is now %s."
context_toggle_enabled: "enabled"
context_toggle_disabled: "disabled"
current_model_info: "&eCurrent model: %s. Use /chatgpt model <model_name> to switch models."
model_switch: "&aModel switched to %s"
chatgpt_error: "&cFailed to contact ChatGPT."
@ -39,5 +48,7 @@ messages:
invalid_model: "&cInvalid model. Use /chatgpt modellist to see available models."
available_models: "&eAvailable models:"
no_permission: "&cYou do not have permission to use this command. Required permission: %s"
# If you don't know what this is, don't change it
debug: false
# DO NOT EDIT!!!!!
version: 2.2

View File

@ -23,14 +23,23 @@ models:
# 以及更多...
# 默认使用的模型
default_model: "gpt-3.5-turbo"
conversation:
max_history_size: 10
context_enabled: false
# 消息相关设置
messages:
reload: "&a已重新加载配置文件"
clear: "&a对话历史已清空"
help: "&e===== MineChatGPT 帮助 ====="
help_ask: "&e/chatgpt <text> - 向ChatGPT提问"
help_reload: "&e/chatgpt reload - 重新加载配置文件"
help_model: "&e/chatgpt model <model_name> - 切换至其他模型"
help_modellist: "&e/chatgpt modellist - 可用的模型列表"
help_context: "&e/chatgpt context - 切换连续对话模式"
help_clear: "/chatgpt clear - 清空对话历史"
context_toggle: "&a连续对话模式已%s。"
context_toggle_enabled: "开启"
context_toggle_disabled: "关闭"
current_model_info: "&e当前模型%s输入 /chatgpt model <model_name> 来切换模型。"
model_switch: "&a已切换至模型 %s"
chatgpt_error: "&c无法联系ChatGPT。"
@ -39,5 +48,7 @@ messages:
invalid_model: "&c模型无效。使用 /chatgpt modellist 查看可用模型。"
available_models: "&e可用模型列表"
no_permission: "&c你没有权限使用这个指令。需要的权限%s"
# 如果你不知道这是什么,请不要动
debug: false
# 不要动!!!!!
version: 2.2

View File

@ -21,3 +21,9 @@ permissions:
minechatgpt.modellist:
description: Allows listing available models
default: op
minechatgpt.context:
description: Allows toggling context mode
default: true
chatgpt.clear:
description: Allows clearing conversation history
default: true