diff --git a/config.json b/config.json index 5c7c2d8..b00e8b1 100644 --- a/config.json +++ b/config.json @@ -4,8 +4,11 @@ "get_token_url": "", "copilot_chat_version": "0.14.2024031401", "prefix": "", + "one_selfCopilot_limit": 2, + "one_copilot_limit": 2, "vscode_version": "vscode\/1.85.2", "serverPort": 8080, "maxPoolSize": 300, - "gpt4_sleepTime": 100 + "gpt4_sleepTime": 100, + "one_coCopilot_limit": 2 } \ No newline at end of file diff --git a/src/main/java/com/gpt4/copilot/controller/ChatController.java b/src/main/java/com/gpt4/copilot/controller/ChatController.java index 800572c..235a1b8 100644 --- a/src/main/java/com/gpt4/copilot/controller/ChatController.java +++ b/src/main/java/com/gpt4/copilot/controller/ChatController.java @@ -1,6 +1,5 @@ package com.gpt4.copilot.controller; -import com.alibaba.fastjson2.JSON; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.gpt4.copilot.copilotApplication; @@ -17,6 +16,7 @@ import org.json.JSONException; import org.json.JSONObject; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -56,6 +56,18 @@ public class ChatController { * 缓存selfToken */ private static final HashMap selfTokenList; + /** + * 缓存cocopilotToken_limit + */ + private static final ConcurrentHashMap copilotTokenLimitList; + /** + * 缓存copilotToken_limit + */ + private static final ConcurrentHashMap coCopilotTokenLimitList; + /** + * 缓存selfToken_limit + */ + private static final ConcurrentHashMap selfTokenLimitList; /** * 模型 */ @@ -108,6 +120,45 @@ public class ChatController { * 自定义maxPoolSize */ private static Integer maxPoolSize; + /** + * one copilot_token max requests per minute + */ + private static Integer one_copilot_limit; + + public static Integer getOne_copilot_limit() { + return one_copilot_limit; + } + + public static void setOne_copilot_limit(Integer one_copilot_limit) { + ChatController.one_copilot_limit = one_copilot_limit; + } + + public static Integer getOne_coCopilot_limit() { + return one_coCopilot_limit; + } + + public static void setOne_coCopilot_limit(Integer one_coCopilot_limit) { + ChatController.one_coCopilot_limit = one_coCopilot_limit; + } + + public static Integer getOne_selfCopilot_limit() { + return one_selfCopilot_limit; + } + + public static void setOne_selfCopilot_limit(Integer one_selfCopilot_limit) { + ChatController.one_selfCopilot_limit = one_selfCopilot_limit; + } + + /** + * one coCopilot_token max requests per minute + */ + private static Integer one_coCopilot_limit; + + /** + * one selfCopilot_token max requests per minute + */ + private static Integer one_selfCopilot_limit; + /** * 定义okhttp库 */ @@ -139,6 +190,9 @@ public class ChatController { selfTokenList = new HashMap<>(); copilotTokenList = new HashMap<>(); coCopilotTokenList = new HashMap<>(); + selfTokenLimitList = new ConcurrentHashMap<>(); + copilotTokenLimitList = new ConcurrentHashMap<>(); + coCopilotTokenLimitList = new ConcurrentHashMap<>(); machineId = generateMachineId(); SystemSetting systemSetting = selectSetting(); setGpt4_sleepTime(systemSetting.getGpt4_sleepTime()); @@ -149,6 +203,10 @@ public class ChatController { setCopilot_chat_version(systemSetting.getCopilot_chat_version()); setMaxPoolSize(systemSetting.getMaxPoolSize()); setExecutor(systemSetting.getMaxPoolSize()); + setOne_copilot_limit(systemSetting.getOne_copilot_limit()); + setOne_coCopilot_limit(systemSetting.getOne_coCopilot_limit()); + setOne_selfCopilot_limit(systemSetting.getOne_selfCopilot_limit()); + } public static String getCopilot_chat_version() { @@ -211,6 +269,8 @@ public class ChatController { ChatController.get_token_url = get_token_url; } + public static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); + /** * 初始化获取环境变量 */ @@ -306,6 +366,30 @@ public class ChatController { log.info("config.json没有新增get_token_url参数,现已增加!"); exist = false; } + + try { + jsonObject.getString("one_copilot_limit"); + } catch (JSONException e) { + jsonObject.put("get_token_url", 30); + log.info("config.json没有新增one_copilot_limit参数,现已增加!"); + exist = false; + } + + try { + jsonObject.getString("one_coCopilot_limit"); + } catch (JSONException e) { + jsonObject.put("one_coCopilot_limit", 30); + log.info("config.json没有新增one_coCopilot_limit参数,现已增加!"); + exist = false; + } + + try { + jsonObject.getString("one_selfCopilot_limit"); + } catch (JSONException e) { + jsonObject.put("one_selfCopilot_limit", 30); + log.info("config.json没有新增one_selfCopilot_limit参数,现已增加!"); + exist = false; + } // 将 JSONObject 转换为 Config 类的实例 SystemSetting config = new SystemSetting(); config.setPassword(jsonObject.optString("password")); @@ -315,6 +399,9 @@ public class ChatController { config.setVscode_version(jsonObject.optString("vscode_version")); config.setCopilot_chat_version(jsonObject.optString("copilot_chat_version")); config.setGet_token_url(jsonObject.optString("get_token_url")); + config.setOne_copilot_limit(jsonObject.optInt("one_copilot_limit")); + config.setOne_coCopilot_limit(jsonObject.optInt("one_coCopilot_limit")); + config.setOne_selfCopilot_limit(jsonObject.optInt("one_selfCopilot_limit")); if (exist == false) { // 将修改后的 JSONObject 转换为格式化的 JSON 字符串 @@ -328,6 +415,15 @@ public class ChatController { return null; } + @Scheduled(cron = "0 */1 * * * ?") + public void resetLimit() { + ExecutorService updateExecutor = Executors.newFixedThreadPool(3); + updateExecutor.submit(() -> copilotTokenLimitList.replaceAll((k, v) -> new AtomicInteger(0))); + updateExecutor.submit(() -> coCopilotTokenLimitList.replaceAll((k, v) -> new AtomicInteger(0))); + updateExecutor.submit(() -> selfTokenLimitList.replaceAll((k, v) -> new AtomicInteger(0))); + updateExecutor.shutdown(); + } + private static String generateMachineId() { try { UUID uuid = UUID.randomUUID(); @@ -484,17 +580,22 @@ public class ChatController { if (token == null) { return new ResponseEntity<>(Result.error("Github Copilot APIKey is wrong"), HttpStatus.UNAUTHORIZED); } + copilotTokenLimitList.putIfAbsent(apiKey, new AtomicInteger(1)); copilotTokenList.put(apiKey, token); log.info("Github CopilotToken初始化成功!"); } + else { + int requestNum = copilotTokenLimitList.get(apiKey).incrementAndGet(); + if(requestNum > one_copilot_limit){ + return new ResponseEntity<>(Result.error("current requests is "+ requestNum + " rate limit exceeded"), HttpStatus.TOO_MANY_REQUESTS); + } + } // 创建OkHttpClient请求 请求https://api.githubcopilot.com/chat/completions String chat_token = copilotTokenList.get(apiKey); Map headersMap = new HashMap<>(); //添加头部 addHeader(headersMap, chat_token); String json = com.alibaba.fastjson2.JSON.toJSONString(conversation); - // 创建一个 RequestBody 对象 - MediaType JSON = MediaType.get("application/json; charset=utf-8"); RequestBody requestBody = RequestBody.create(json, JSON); Request.Builder requestBuilder = new Request.Builder().url(github_chat_url).post(requestBody); headersMap.forEach(requestBuilder::addHeader); @@ -573,17 +674,22 @@ public class ChatController { if (token == null) { return new ResponseEntity<>(Result.error("cocopilot APIKey is wrong"), HttpStatus.UNAUTHORIZED); } + coCopilotTokenLimitList.put(apiKey, new AtomicInteger(1)); coCopilotTokenList.put(apiKey, token); log.info("coCopilotToken初始化成功!"); } + else { + int requestNum = coCopilotTokenLimitList.get(apiKey).incrementAndGet(); + if(requestNum > one_coCopilot_limit){ + return new ResponseEntity<>(Result.error("current requests is "+ requestNum + " rate limit exceeded"), HttpStatus.TOO_MANY_REQUESTS); + } + } // 创建OkHttpClient请求 请求https://api.githubcopilot.com/chat/completions String chat_token = coCopilotTokenList.get(apiKey); Map headersMap = new HashMap<>(); //添加头部 addHeader(headersMap, chat_token); String json = com.alibaba.fastjson2.JSON.toJSONString(conversation); - // 创建一个 RequestBody 对象 - MediaType JSON = MediaType.get("application/json; charset=utf-8"); RequestBody requestBody = RequestBody.create(json, JSON); Request.Builder requestBuilder = new Request.Builder().url(github_chat_url).post(requestBody); headersMap.forEach(requestBuilder::addHeader); @@ -638,17 +744,21 @@ public class ChatController { return new ResponseEntity<>(Result.error("自定义self APIKey is wrong"), HttpStatus.UNAUTHORIZED); } selfTokenList.put(apiKey, token); + selfTokenLimitList.put(apiKey,new AtomicInteger(1)); log.info("自定义selfToken初始化成功!"); } + else { + int requestNum = selfTokenLimitList.get(apiKey).incrementAndGet(); + if(requestNum > one_selfCopilot_limit){ + return new ResponseEntity<>(Result.error("current requests is "+ requestNum + " rate limit exceeded"), HttpStatus.TOO_MANY_REQUESTS); + } + } // 创建OkHttpClient请求 请求https://api.githubcopilot.com/chat/completions String chat_token = selfTokenList.get(apiKey); Map headersMap = new HashMap<>(); //添加头部 addHeader(headersMap, chat_token); String json = com.alibaba.fastjson2.JSON.toJSONString(conversation); - log.info(conversation.toString()); - // 创建一个 RequestBody 对象 - MediaType JSON = MediaType.get("application/json; charset=utf-8"); RequestBody requestBody = RequestBody.create(json, JSON); Request.Builder requestBuilder = new Request.Builder().url(github_chat_url).post(requestBody); headersMap.forEach(requestBuilder::addHeader); @@ -697,9 +807,7 @@ public class ChatController { Map headersMap = new HashMap<>(); //添加头部 addHeader(headersMap, token); - String json = JSON.toJSONString(conversation); - // 创建一个 RequestBody 对象 - MediaType JSON = MediaType.get("application/json; charset=utf-8"); + String json = com.alibaba.fastjson2.JSON.toJSONString(conversation); RequestBody requestBody = RequestBody.create(json, JSON); Request.Builder requestBuilder = new Request.Builder().url(github_chat_url).post(requestBody); headersMap.forEach(requestBuilder::addHeader); @@ -753,17 +861,22 @@ public class ChatController { if (token == null) { return new ResponseEntity<>(Result.error("Github Copilot APIKey is wrong"), HttpStatus.UNAUTHORIZED); } + copilotTokenLimitList.put(apiKey, new AtomicInteger(1)); copilotTokenList.put(apiKey, token); log.info("Github CopilotToken初始化成功!"); } + else { + int requestNum = copilotTokenLimitList.get(apiKey).incrementAndGet(); + if(requestNum > one_copilot_limit){ + return new ResponseEntity<>(Result.error("current requests is "+ requestNum + " rate limit exceeded"), HttpStatus.TOO_MANY_REQUESTS); + } + } // 创建OkHttpClient请求 请求https://api.githubcopilot.com/chat/completions String chat_token = copilotTokenList.get(apiKey); Map headersMap = new HashMap<>(); //添加头部 addHeader(headersMap, chat_token); String json = com.alibaba.fastjson2.JSON.toJSONString(conversation); - // 创建一个 RequestBody 对象 - MediaType JSON = MediaType.get("application/json; charset=utf-8"); RequestBody requestBody = RequestBody.create(json, JSON); Request.Builder requestBuilder = new Request.Builder().url(github_embaddings).post(requestBody); headersMap.forEach(requestBuilder::addHeader); @@ -846,16 +959,22 @@ public class ChatController { if (token == null) { return new ResponseEntity<>(Result.error("copilot APIKey is wrong"), HttpStatus.UNAUTHORIZED); } + coCopilotTokenLimitList.put(apiKey, new AtomicInteger(1)); coCopilotTokenList.put(apiKey, token); log.info("coCopilotToken初始化成功!"); } + else { + int requestNum = coCopilotTokenLimitList.get(apiKey).incrementAndGet(); + if(requestNum > one_coCopilot_limit){ + return new ResponseEntity<>(Result.error("current requests is "+ requestNum + " rate limit exceeded"), HttpStatus.TOO_MANY_REQUESTS); + } + } // 创建OkHttpClient请求 请求https://api.githubcopilot.com/chat/completions String chat_token = coCopilotTokenList.get(apiKey); Map headersMap = new HashMap<>(); //添加头部 addHeader(headersMap, chat_token); String json = com.alibaba.fastjson2.JSON.toJSONString(conversation); - MediaType JSON = MediaType.get("application/json; charset=utf-8"); RequestBody requestBody = RequestBody.create(json, JSON); Request.Builder requestBuilder = new Request.Builder().url(github_embaddings).post(requestBody); headersMap.forEach(requestBuilder::addHeader); @@ -923,15 +1042,21 @@ public class ChatController { if (token == null) { return new ResponseEntity<>(Result.error("自定义APIKey is wrong"), HttpStatus.UNAUTHORIZED); } + selfTokenLimitList.put(apiKey,new AtomicInteger(1)); selfTokenList.put(apiKey, token); log.info("自定义selfToken初始化成功!"); } + else { + int requestNum = selfTokenLimitList.get(apiKey).incrementAndGet(); + if(requestNum > one_selfCopilot_limit){ + return new ResponseEntity<>(Result.error("current requests is "+ requestNum + " rate limit exceeded"), HttpStatus.TOO_MANY_REQUESTS); + } + } String chat_token = selfTokenList.get(apiKey); Map headersMap = new HashMap<>(); //添加头部 addHeader(headersMap, chat_token); String json = com.alibaba.fastjson2.JSON.toJSONString(conversation); - MediaType JSON = MediaType.get("application/json; charset=utf-8"); RequestBody requestBody = RequestBody.create(json, JSON); Request.Builder requestBuilder = new Request.Builder().url(github_embaddings).post(requestBody); headersMap.forEach(requestBuilder::addHeader); @@ -968,9 +1093,7 @@ public class ChatController { Map headersMap = new HashMap<>(); //添加头部 addHeader(headersMap, token); - String json = JSON.toJSONString(conversation); - // 创建一个 RequestBody 对象 - MediaType JSON = MediaType.get("application/json; charset=utf-8"); + String json = com.alibaba.fastjson2.JSON.toJSONString(conversation); RequestBody requestBody = RequestBody.create(json, JSON); Request.Builder requestBuilder = new Request.Builder().url(github_embaddings).post(requestBody); headersMap.forEach(requestBuilder::addHeader); diff --git a/src/main/java/com/gpt4/copilot/copilotApplication.java b/src/main/java/com/gpt4/copilot/copilotApplication.java index 9522c97..c4be9c9 100644 --- a/src/main/java/com/gpt4/copilot/copilotApplication.java +++ b/src/main/java/com/gpt4/copilot/copilotApplication.java @@ -209,11 +209,15 @@ public class copilotApplication { System.out.println("vscode_version:" + ChatController.getVscode_version()); System.out.println("copilot_chat_version:" + ChatController.getCopilot_chat_version()); System.out.println("get_token_url:" + ChatController.getGet_token_url()); + System.out.println("one_copilot_limit:" + ChatController.getOne_copilot_limit()); + System.out.println("one_coCopilot_limit:" + ChatController.getOne_coCopilot_limit()); + System.out.println("one_selfCopilot_limit:" + ChatController.getOne_selfCopilot_limit()); System.out.println("gpt4-copilot-java 初始化接口成功!"); System.out.println("======================================================"); - System.out.println("******原神gpt4-copilot-java-native v0.0.6启动成功******"); + System.out.println("******原神gpt4-copilot-java-native v0.0.7启动成功******"); System.out.println("* 采用graalvm打包,运行内存大幅度减小"); System.out.println("* 适配官方requestBody,减小被查询异常"); + System.out.println("* 使用ConcurrentHashMap,粗略的对于每个密钥按每分钟进行限速"); System.out.println("URL地址:http://0.0.0.0:" + config.getServerPort() + config.getPrefix() + ""); System.out.println("======================================================"); } diff --git a/src/main/java/com/gpt4/copilot/pojo/SystemSetting.java b/src/main/java/com/gpt4/copilot/pojo/SystemSetting.java index ef7d616..eb655b2 100644 --- a/src/main/java/com/gpt4/copilot/pojo/SystemSetting.java +++ b/src/main/java/com/gpt4/copilot/pojo/SystemSetting.java @@ -56,4 +56,19 @@ public class SystemSetting { */ private Integer maxPoolSize; + /** + * one copilot_token max requests per minute + */ + private Integer one_copilot_limit; + + /** + * one coCopilot_token max requests per minute + */ + private Integer one_coCopilot_limit; + + /** + * one selfCopilot_token max requests per minute + */ + private Integer one_selfCopilot_limit; + } \ No newline at end of file diff --git a/target/classes/com/gpt4/copilot/controller/ChatController$1.class b/target/classes/com/gpt4/copilot/controller/ChatController$1.class index 2ef1c1b..1e3a06a 100644 Binary files a/target/classes/com/gpt4/copilot/controller/ChatController$1.class and b/target/classes/com/gpt4/copilot/controller/ChatController$1.class differ diff --git a/target/classes/com/gpt4/copilot/controller/ChatController.class b/target/classes/com/gpt4/copilot/controller/ChatController.class index 612a806..b31fdd0 100644 Binary files a/target/classes/com/gpt4/copilot/controller/ChatController.class and b/target/classes/com/gpt4/copilot/controller/ChatController.class differ diff --git a/target/classes/com/gpt4/copilot/copilotApplication.class b/target/classes/com/gpt4/copilot/copilotApplication.class index f25f74e..c4634c9 100644 Binary files a/target/classes/com/gpt4/copilot/copilotApplication.class and b/target/classes/com/gpt4/copilot/copilotApplication.class differ diff --git a/target/classes/com/gpt4/copilot/pojo/SystemSetting.class b/target/classes/com/gpt4/copilot/pojo/SystemSetting.class index 7e143d1..e1b6f87 100644 Binary files a/target/classes/com/gpt4/copilot/pojo/SystemSetting.class and b/target/classes/com/gpt4/copilot/pojo/SystemSetting.class differ