commit 48ab525e9d74e9132284e62b71fed6f1a174fc80 Author: dashan Date: Sun Feb 12 22:49:15 2023 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d621c0d --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +/*.iml + +/*/*.iml +/.idea/ + +/docs/ppt/~*.pptx +/docs/config/docker.config diff --git a/README.md b/README.md new file mode 100644 index 0000000..88a0734 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +## BUILD +`mvn clean package` \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..6fa52e5 --- /dev/null +++ b/pom.xml @@ -0,0 +1,78 @@ + + + 4.0.0 + + cn.dashan + chatbot-api + 1.0-SNAPSHOT + + + 8 + 8 + + + + org.springframework.boot + spring-boot-starter-parent + 2.3.5.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + com.alibaba + fastjson + 1.2.58 + + + + + chatbot-api + + + src/main/resources + true + + **/** + + + + + + src/test/resources + true + + **/** + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12.4 + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + \ No newline at end of file diff --git a/src/main/java/cn/dashan/chatbot/ChatBotApplication.java b/src/main/java/cn/dashan/chatbot/ChatBotApplication.java new file mode 100644 index 0000000..4bb4e38 --- /dev/null +++ b/src/main/java/cn/dashan/chatbot/ChatBotApplication.java @@ -0,0 +1,23 @@ +package cn.dashan.chatbot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; + +/** + * @author ds + * @since 2023/2/11 + */ +@SpringBootApplication +public class ChatBotApplication { + + public static void main(String[] args) { + SpringApplication.run(ChatBotApplication.class,args); + } + + @Bean + public RestTemplate restTemplate(){ + return new RestTemplate(); + } +} diff --git a/src/main/java/cn/dashan/chatbot/api/ChatBotApi.java b/src/main/java/cn/dashan/chatbot/api/ChatBotApi.java new file mode 100644 index 0000000..ca84375 --- /dev/null +++ b/src/main/java/cn/dashan/chatbot/api/ChatBotApi.java @@ -0,0 +1,40 @@ +package cn.dashan.chatbot.api; + +import cn.dashan.chatbot.common.RestResponse; +import cn.dashan.chatbot.model.enums.OpenAIModel; +import cn.dashan.chatbot.service.IOpenAI; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author ds + * @since 2023/2/11 + */ +@RestController +public class ChatBotApi { + + Logger logger = LoggerFactory.getLogger(ChatBotApi.class); + + private final IOpenAI openAI; + + public ChatBotApi(IOpenAI openAI) { + this.openAI = openAI; + } + + @GetMapping("/bot") + public RestResponse bot( + @RequestParam("question") String question, + @RequestParam("model") OpenAIModel model + ){ + logger.info("执行bot接口,客户端传参-model:{},question:{}",model,question); + try { + return new RestResponse.Builder(RestResponse.MSG.SUCCESS).setDate(openAI.doChatGPT(question,model)).builder(); + }catch (RuntimeException e){ + logger.error("ChatGPT执行异常:",e); + return new RestResponse.Builder(RestResponse.MSG.FAILURE).setMsg(e.getMessage()).builder(); + } + } +} diff --git a/src/main/java/cn/dashan/chatbot/common/RestResponse.java b/src/main/java/cn/dashan/chatbot/common/RestResponse.java new file mode 100644 index 0000000..13bec11 --- /dev/null +++ b/src/main/java/cn/dashan/chatbot/common/RestResponse.java @@ -0,0 +1,84 @@ +package cn.dashan.chatbot.common; + +import java.io.Serializable; + +/** + * @author ds + * @since 2023/2/11 + */ +public class RestResponse implements Serializable { + + private final int code; + private final String msg; + private final T data; + + + public enum MSG{ + SUCCESS(1,"SUCCESS"), + FAILURE(0,"FAILURE"); + + private final int code; + private final String msg; + + MSG(int code, String msg) { + this.code = code; + this.msg = msg; + } + + public int getCode() { + return this.code; + } + + public String getMsg() { + return this.msg; + } + } + + public static class Builder{ + private final int code; + private String msg; + private T data; + + public Builder(int code){ + this.code=code; + } + + public Builder(MSG msg){ + this.msg=msg.msg; + this.code= msg.code; + } + + public Builder setMsg(String msg){ + this.msg=msg; + return this; + } + + public Builder setDate(T data){ + this.data=data; + return this; + } + + public RestResponse builder(){ + return new RestResponse<>(this); + } + + } + + private RestResponse(Builder builder){ + this.code=builder.code; + this.msg=builder.msg; + this.data=builder.data; + } + + public int getCode() { + return code; + } + + public String getMsg() { + return msg; + } + + public T getData() { + return data; + } +} diff --git a/src/main/java/cn/dashan/chatbot/model/enums/OpenAIModel.java b/src/main/java/cn/dashan/chatbot/model/enums/OpenAIModel.java new file mode 100644 index 0000000..05af4aa --- /dev/null +++ b/src/main/java/cn/dashan/chatbot/model/enums/OpenAIModel.java @@ -0,0 +1,36 @@ +package cn.dashan.chatbot.model.enums; + +/** + * @author ds + * @since 2023/2/11 + */ +public enum OpenAIModel { + TEXT_DEVINCI_003(1,"text-davinci-003",4000), + TEXT_CURIE_001(2,"text-curie-001",2000), + TEXT_BABBAGE_001(3,"text-babbage-001",2000), + TEXT_ADA_001(4,"text-ada-001",2000) + ; + + + private final int modelId; + private final String model; + private final int maxTokens; + + OpenAIModel(int modelId, String model, int maxTokens) { + this.modelId = modelId; + this.model = model; + this.maxTokens = maxTokens; + } + + public int getMaxTokens() { + return maxTokens; + } + + public int getModelId() { + return modelId; + } + + public String getModel() { + return model; + } +} diff --git a/src/main/java/cn/dashan/chatbot/model/vo/AIAnswer.java b/src/main/java/cn/dashan/chatbot/model/vo/AIAnswer.java new file mode 100644 index 0000000..be46f6e --- /dev/null +++ b/src/main/java/cn/dashan/chatbot/model/vo/AIAnswer.java @@ -0,0 +1,59 @@ +package cn.dashan.chatbot.model.vo; + +import java.util.List; + +/** + * @author ds + * @since 2023/2/12 + */ +public class AIAnswer { + private String id; + + private String object; + + private int created; + + private String model; + + private List choices; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getObject() { + return object; + } + + public void setObject(String object) { + this.object = object; + } + + public int getCreated() { + return created; + } + + public void setCreated(int created) { + this.created = created; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public List getChoices() { + return choices; + } + + public void setChoices(List choices) { + this.choices = choices; + } +} diff --git a/src/main/java/cn/dashan/chatbot/model/vo/Choices.java b/src/main/java/cn/dashan/chatbot/model/vo/Choices.java new file mode 100644 index 0000000..f63cefc --- /dev/null +++ b/src/main/java/cn/dashan/chatbot/model/vo/Choices.java @@ -0,0 +1,47 @@ +package cn.dashan.chatbot.model.vo; + +/** + * @author ds + * @since 2023/2/12 + */ +public class Choices { + private String text; + + private int index; + + private String logprobs; + + private String finish_reason; + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public String getLogprobs() { + return logprobs; + } + + public void setLogprobs(String logprobs) { + this.logprobs = logprobs; + } + + public String getFinish_reason() { + return finish_reason; + } + + public void setFinish_reason(String finish_reason) { + this.finish_reason = finish_reason; + } +} diff --git a/src/main/java/cn/dashan/chatbot/service/IOpenAI.java b/src/main/java/cn/dashan/chatbot/service/IOpenAI.java new file mode 100644 index 0000000..d791d04 --- /dev/null +++ b/src/main/java/cn/dashan/chatbot/service/IOpenAI.java @@ -0,0 +1,19 @@ +package cn.dashan.chatbot.service; + +import cn.dashan.chatbot.model.enums.OpenAIModel; + +/** + * @author ds + * @since 2023/2/11 + */ +public interface IOpenAI { + + /** + * 向chatGPT发送请求 + * @param question 问题 + * @param model 型号 + * @return 回答 + * @throws RuntimeException 请求chatGPT异常或解析响应结果异常 + */ + String doChatGPT(String question, OpenAIModel model) throws RuntimeException; +} diff --git a/src/main/java/cn/dashan/chatbot/service/impl/OpenAI.java b/src/main/java/cn/dashan/chatbot/service/impl/OpenAI.java new file mode 100644 index 0000000..8bfa53e --- /dev/null +++ b/src/main/java/cn/dashan/chatbot/service/impl/OpenAI.java @@ -0,0 +1,91 @@ +package cn.dashan.chatbot.service.impl; + +import cn.dashan.chatbot.model.enums.OpenAIModel; +import cn.dashan.chatbot.model.vo.AIAnswer; +import cn.dashan.chatbot.model.vo.Choices; +import cn.dashan.chatbot.service.IOpenAI; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author ds + * @since 2023/2/11 + */ +@Service +public class OpenAI implements IOpenAI { + Logger logger = LoggerFactory.getLogger(OpenAI.class); + + @Value("${chatbot-api.bot.openAiKey}") + private String openAiKey; + + private final RestTemplate restTemplate; + public OpenAI(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + /** + * 使用RestTemplate 实现chatGPT发送请求 + * @param question 问题 + * @param model 型号 + * @return 回答 + * @throws RuntimeException 请求chatGPT异常或解析响应结果异常 + */ + @Override + public String doChatGPT(String question, OpenAIModel model) throws RuntimeException { + logger.info("机器人{},接收消息:{}",model,question); + //构建请求头 + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization","Bearer "+openAiKey); + headers.set("Content-Type", "application/json"); + + //请求参数 + Map params = new HashMap<>(); + params.put("model",model.getModel()); + params.put("prompt",question); + params.put("temperature",0); + params.put("max_tokens",model.getMaxTokens()); + + //构建请求体 + HttpEntity request = new HttpEntity<>(JSON.toJSONString(params),headers); + + //执行请求 + ResponseEntity responseEntity = restTemplate.postForEntity("https://api.openai.com/v1/completions", request, String.class); + + //判断执行是否成功 + if (!HttpStatus.OK.equals(responseEntity.getStatusCode())){ + logger.error("OpenAI 服务端接口请求异常:{}-{}",responseEntity.getStatusCode().value(),responseEntity.getStatusCode().getReasonPhrase()); + throw new RuntimeException("ChatGPT 任务执行异常"); + } + + + //解析请求 + StringBuilder stringBuilder = new StringBuilder(); + try { + AIAnswer answer = JSON.parseObject(responseEntity.getBody(),AIAnswer.class); + assert answer != null; + for (Choices choice : answer.getChoices()) { + stringBuilder.append(choice.getText()); + } + }catch (RuntimeException e){ + logger.error("answer 解析失败",e); + throw new RuntimeException("answer 解析失败"); + } + + String answerTest = stringBuilder.toString().replaceFirst("\\n", "").replaceFirst("\\n", ""); + + logger.info("机器人{},回答问题:{}",model,answerTest); + return answerTest; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..085b772 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,6 @@ +server: + port: 8092 + # 分组任务配置 +chatbot-api: + bot: + openAiKey: ###设置openai上申请的api key \ No newline at end of file diff --git a/target/classes/application.yml b/target/classes/application.yml new file mode 100644 index 0000000..1e008b0 --- /dev/null +++ b/target/classes/application.yml @@ -0,0 +1,6 @@ +server: + port: 8092 + # 分组任务配置 +chatbot-api: + bot: + openAiKey: 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 \ No newline at end of file