diff --git a/pom.xml b/pom.xml index b15e10c..b323b86 100644 --- a/pom.xml +++ b/pom.xml @@ -1,113 +1,112 @@ - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.3.5 - - - cn.lige2333 - ligeai - 0.0.1-SNAPSHOT - ligeai - ligeai - - - - - - - - - - - - - - - 17 - 1.0.0-M3 - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-webflux - - - org.mybatis.spring.boot - mybatis-spring-boot-starter - 3.0.3 - - - org.springframework.ai - spring-ai-openai-spring-boot-starter - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.3.5 + + + cn.lige2333 + ligeai + 0.0.1-SNAPSHOT + ligeai + ligeai + + + + + + + + + + + + + + + 17 + 1.0.0-M3 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-webflux + + + com.alibaba + fastjson + 1.2.58 + + + cn.hutool + hutool-all + 5.8.21 + + + org.springframework.ai + spring-ai-openai-spring-boot-starter + - - org.projectlombok - lombok - true - - - org.springframework.boot - spring-boot-starter-test - test - - - io.projectreactor - reactor-test - test - - - org.mybatis.spring.boot - mybatis-spring-boot-starter-test - 3.0.3 - test - - - - - - org.springframework.ai - spring-ai-bom - ${spring-ai.version} - pom - import - - - + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + io.projectreactor + reactor-test + test + + + + + + org.springframework.ai + spring-ai-bom + ${spring-ai.version} + pom + import + + + - - - - org.springframework.boot - spring-boot-maven-plugin - - - - org.projectlombok - lombok - - - - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + diff --git a/src/main/java/cn/lige2333/ligeai/LigeaiApplication.java b/src/main/java/cn/lige2333/ligeai/LigeaiApplication.java index 98726d0..de4f9cc 100644 --- a/src/main/java/cn/lige2333/ligeai/LigeaiApplication.java +++ b/src/main/java/cn/lige2333/ligeai/LigeaiApplication.java @@ -6,8 +6,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class LigeaiApplication { - public static void main(String[] args) { - SpringApplication.run(LigeaiApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(LigeaiApplication.class, args); + } } diff --git a/src/main/java/cn/lige2333/ligeai/base/GptConfig.java b/src/main/java/cn/lige2333/ligeai/base/GptConfig.java index b17c2af..1953af0 100644 --- a/src/main/java/cn/lige2333/ligeai/base/GptConfig.java +++ b/src/main/java/cn/lige2333/ligeai/base/GptConfig.java @@ -1,61 +1,18 @@ -package cn.lige2333.qrdouble.common.config; +package cn.lige2333.ligeai.base; -import com.unfbx.chatgpt.OpenAiClient; -import com.unfbx.chatgpt.OpenAiStreamClient; -import com.unfbx.chatgpt.interceptor.OpenAiResponseInterceptor; -import okhttp3.OkHttpClient; import org.springframework.ai.chat.memory.ChatMemory; import org.springframework.ai.chat.memory.InMemoryChatMemory; import org.springframework.ai.embedding.EmbeddingModel; -import org.springframework.ai.reader.TextReader; -import org.springframework.ai.transformer.splitter.TokenTextSplitter; import org.springframework.ai.vectorstore.SimpleVectorStore; import org.springframework.ai.vectorstore.VectorStore; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.CommandLineRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.Resource; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.concurrent.TimeUnit; @Configuration public class GptConfig { - @Value("${chatgpt.token}") - private String token; - - @Bean - public OkHttpClient okHttpClient() { - return new OkHttpClient - .Builder() - .connectTimeout(1000, TimeUnit.SECONDS)//自定义超时时间 - .writeTimeout(3000, TimeUnit.SECONDS)//自定义超时时间 - .readTimeout(3000, TimeUnit.SECONDS)//自定义超时时间 - .build(); - } - @Bean - public OpenAiClient openAiClient() { - - return OpenAiClient.builder() - .apiKey(Arrays.asList(token)) - .apiHost("http://gptapi.kurtwang.com/") - .okHttpClient(okHttpClient()) - .build(); - } - - @Bean - public OpenAiStreamClient openAiStreamClient() { - return OpenAiStreamClient.builder() - .apiHost("http://gptapi.kurtwang.com/") - .apiKey(Arrays.asList(token)) - .okHttpClient(okHttpClient()) - .build(); - } - @Bean public ChatMemory chatMemory(){ return new InMemoryChatMemory(); diff --git a/src/main/java/cn/lige2333/ligeai/chatgpt/controller/ChatGptController.java b/src/main/java/cn/lige2333/ligeai/chatgpt/controller/ChatGptController.java index 50adcb2..bf1e344 100644 --- a/src/main/java/cn/lige2333/ligeai/chatgpt/controller/ChatGptController.java +++ b/src/main/java/cn/lige2333/ligeai/chatgpt/controller/ChatGptController.java @@ -1,2 +1,39 @@ -package cn.lige2333.ligeai.chatgpt.controller;public class ChatGptController { +package cn.lige2333.ligeai.chatgpt.controller; + +import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.openai.OpenAiChatModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; + + +@RestController +@RequestMapping("/ajax") +@CrossOrigin +public class ChatGptController { + @Autowired + private OpenAiChatModel chatModel; + + private final ChatClient chatClient; + + public ChatGptController(ChatClient.Builder chatClientBuilder) { + this.chatClient = chatClientBuilder.build(); + } + + @GetMapping("/ai/generate") + public String generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) { + return this.chatClient.prompt() + .user(message) + .call() + .content(); + } + + @GetMapping(value = "/ai/generateStream",produces = MediaType.TEXT_EVENT_STREAM_VALUE) + public Flux generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) { + return this.chatClient.prompt() + .user(message) + .stream() + .content(); + } } diff --git a/src/main/java/cn/lige2333/ligeai/chatgpt/service/ChatGptService.java b/src/main/java/cn/lige2333/ligeai/chatgpt/service/ChatGptService.java index 652e5b8..d8aa51f 100644 --- a/src/main/java/cn/lige2333/ligeai/chatgpt/service/ChatGptService.java +++ b/src/main/java/cn/lige2333/ligeai/chatgpt/service/ChatGptService.java @@ -1,31 +1,11 @@ -package cn.lige2333.qrdouble.chatgpt.service; +package cn.lige2333.ligeai.chatgpt.service; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONUtil; -import cn.lige2333.qrdouble.security.entity.SysUser; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.unfbx.chatgpt.OpenAiClient; -import com.unfbx.chatgpt.OpenAiStreamClient; -import com.unfbx.chatgpt.entity.chat.*; -import com.unfbx.chatgpt.entity.common.Choice; -import com.unfbx.chatgpt.entity.images.Image; -import com.unfbx.chatgpt.entity.images.ImageResponse; -import com.unfbx.chatgpt.entity.images.SizeEnum; -import com.unfbx.chatgpt.sse.ConsoleEventSourceListener; import lombok.extern.slf4j.Slf4j; -import org.apache.logging.log4j.util.Strings; -import org.jetbrains.annotations.NotNull; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor; import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor; -import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor; import org.springframework.ai.chat.memory.ChatMemory; import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.vectorstore.SearchRequest; -import org.springframework.ai.vectorstore.VectorStore; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.CrossOrigin; @@ -41,12 +21,6 @@ import java.util.*; @CrossOrigin public class ChatGptService { - @Autowired - private OpenAiClient openAiClient; - - @Autowired - private OpenAiStreamClient openAiStreamClient; - private final ChatClient chatClient; public ChatGptService(ChatClient.Builder chatClientBuilder, ChatMemory chatMemory) { @@ -74,10 +48,7 @@ public class ChatGptService { .build(); } - public Flux> getChatGptResStream(String input, SysUser sysUser) throws IOException { - if(Objects.isNull(sysUser)){ - throw new RuntimeException("用户信息获取失败!"); - } + public Flux> getChatGptResStream(String input) throws IOException { String id = UUID.randomUUID().toString(); Map finishMap = new HashMap<>(); finishMap.put("content", "[DONE]"); @@ -96,163 +67,4 @@ public class ChatGptService { } - public ChatCompletionResponse getCompletionRes(ChatCompletion chatCompletion) { - List messages = chatCompletion.getMessages(); - ChatCompletionResponse chatCompletionResponse = new ChatCompletionResponse(); - if (CollUtil.isNotEmpty(messages)) { - Message message = messages.get(messages.size() - 1); - ChatResponse currentDate = this.chatClient.prompt() - .user(message.getContent()) - .system(promptSystemSpec -> promptSystemSpec.param("current_date", LocalDateTime.now().toString())) - .advisors(advisorSpec -> advisorSpec.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)) - .call().chatResponse(); - - chatCompletionResponse.setId(currentDate.getMetadata().getId()); - ChatChoice choice = new ChatChoice(); - choice.setIndex(0); - choice.setMessage(Message.builder().content(currentDate.getResult().getOutput().getContent()).role(Message.Role.ASSISTANT).build()); - choice.setFinishReason(currentDate.getResult().getMetadata().getFinishReason()); - chatCompletionResponse.setChoices(Arrays.asList(choice)); - return chatCompletionResponse; - } - return chatCompletionResponse; - } - public Flux getStreamingRes(ChatCompletion chatCompletion) { - List messages = chatCompletion.getMessages(); - if(CollUtil.isNotEmpty(messages)){ - Message message = messages.get(messages.size() - 1); - Flux result = this.chatClient.prompt() - .user(message.getContent()) - .system(promptSystemSpec -> promptSystemSpec.param("current_date", LocalDateTime.now().toString())) - .advisors(advisorSpec -> advisorSpec.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)) - .stream().chatResponse().map(res -> { - ChatCompletionResponse chatCompletionResponse = new ChatCompletionResponse(); - chatCompletionResponse.setId(res.getMetadata().getId()); - ChatChoice choice = new ChatChoice(); - choice.setIndex(0); - choice.setDelta(Message.builder().content(res.getResult().getOutput().getContent()).role(Message.Role.ASSISTANT).build()); - choice.setFinishReason(res.getResult().getMetadata().getFinishReason()); - chatCompletionResponse.setChoices(Arrays.asList(choice)); - return chatCompletionResponse; - }); - return result; - } - return Flux.just(new ChatCompletionResponse()); - } - - public String getChatGptRes(String input, SysUser sysUser) { - List messages = getMessages(input, sysUser); - ChatCompletion chatCompletion = ChatCompletion.builder().messages(messages).model(ChatCompletion.Model.GPT_4.getName()).build(); - ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion); - return chatCompletionResponse.getChoices().get(0).getMessage().getContent().replaceAll("\r|\n", ""); - } - - private List getMessages(String input, SysUser sysUser) { - String messageContext = (String) LocalCache.CACHE.get(sysUser.getUserName()); - List messages = new ArrayList<>(); - if (StrUtil.isNotBlank(messageContext)) { - messages = JSONUtil.toList(messageContext, Message.class); - if (messages.size() >= 10) { - messages = messages.subList(1, 10); - } - Message currentMessage = Message.builder().content(input).role(Message.Role.USER).build(); - messages.add(currentMessage); - } else { - Message currentMessage = Message.builder().content(input).role(Message.Role.USER).build(); - messages.add(currentMessage); - } - return messages; - } - - public void pictureChat(String text,String imgUrl, SysUser sysUser) { - Content textContent = Content.builder().text(text).type(Content.Type.TEXT.getName()).build(); - ImageUrl imageUrl = ImageUrl.builder().url(imgUrl).build(); - Content imageContent = Content.builder().imageUrl(imageUrl).type(Content.Type.IMAGE_URL.getName()).build(); - List contentList = new ArrayList<>(); - contentList.add(textContent); - contentList.add(imageContent); - MessagePicture message = MessagePicture.builder().role(Message.Role.USER).content(contentList).build(); - ChatCompletionWithPicture chatCompletion = ChatCompletionWithPicture - .builder() - .messages(Collections.singletonList(message)) - .model(ChatCompletion.Model.GPT_4_VISION_PREVIEW.getName()) - .build(); - ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion); - chatCompletionResponse.getChoices().forEach(e -> System.out.println(e.getMessage())); - } - - public SseEmitter pictureChatStream(String text,String imgUrl, SysUser sysUser) throws IOException { - Content textContent = Content.builder().text(text).type(Content.Type.TEXT.getName()).build(); - ImageUrl imageUrl = ImageUrl.builder().url(imgUrl).build(); - Content imageContent = Content.builder().imageUrl(imageUrl).type(Content.Type.IMAGE_URL.getName()).build(); - SseEmitter sseEmitter = new SseEmitter(0l); - sseEmitter.send(SseEmitter.event().id("1").name("连接成功!!!!").data(LocalDateTime.now()).reconnectTime(3000)); - sseEmitter.onCompletion(() -> { - log.info(LocalDateTime.now() + "on completion"); - }); - sseEmitter.onTimeout(() -> log.info(LocalDateTime.now() + ", on timeout#" + sseEmitter.getTimeout())); - sseEmitter.onError( - throwable -> { - try { - log.info(LocalDateTime.now() + ", uid#" + "765431" + ", on error#" + throwable.toString()); - sseEmitter.send(SseEmitter.event().id("765431").name("发生异常!").data(throwable.getMessage()).reconnectTime(3000)); - } catch (IOException e) { - e.printStackTrace(); - } - } - ); - OpenAISSEEventSourceListener openAIEventSourceListener = new OpenAISSEEventSourceListener(sseEmitter); - List contentList = new ArrayList<>(); - contentList.add(textContent); - contentList.add(imageContent); - MessagePicture message = MessagePicture.builder().role(Message.Role.USER).content(contentList).build(); - ChatCompletionWithPicture chatCompletion = ChatCompletionWithPicture - .builder() - .messages(Collections.singletonList(message)) - .model(ChatCompletion.Model.GPT_4_VISION_PREVIEW.getName()) - .build(); - openAiStreamClient.streamChatCompletion(chatCompletion, openAIEventSourceListener); - return sseEmitter; - } - - public String generateImage(String content) { - Image image = Image.builder() - .responseFormat(com.unfbx.chatgpt.entity.images.ResponseFormat.URL.getName()) - .model(Image.Model.DALL_E_3.getName()) - .prompt(content) - .n(1) - .quality(Image.Quality.HD.getName()) - .size(SizeEnum.size_1024_1792.getName()) - .style(Image.Style.NATURAL.getName()) - .build(); - ImageResponse imageResponse = openAiClient.genImages(image); - return imageResponse.getData().get(0).getUrl(); - } - - public SseEmitter getStreaming(ChatCompletion chatCompletion) { - Flux streamingRes = getStreamingRes(chatCompletion); - SseEmitter sseEmitter = new SseEmitter(0l); - Flux.from(streamingRes) - .doOnNext(sseEvent -> { - try { - sseEmitter.send(SseEmitter.event() - .id(sseEvent.getId()) - .data(sseEvent) - .reconnectTime(3000)); - } catch (IOException e) { - throw new RuntimeException(e); - } - - }) - .doOnError(error -> { - log.error("连接断开: {}", error.getMessage()); - }) - .doOnComplete(() -> { - log.info("完成"); - }).subscribe(); - - return sseEmitter; - - } - } diff --git a/src/main/java/cn/lige2333/ligeai/chatgpt/service/GptFunctions.java b/src/main/java/cn/lige2333/ligeai/chatgpt/service/GptFunctions.java index c0a3885..3e093e6 100644 --- a/src/main/java/cn/lige2333/ligeai/chatgpt/service/GptFunctions.java +++ b/src/main/java/cn/lige2333/ligeai/chatgpt/service/GptFunctions.java @@ -1,13 +1,6 @@ -package cn.lige2333.qrdouble.chatgpt.functions; +package cn.lige2333.ligeai.chatgpt.service; -import cn.hutool.http.Header; import cn.hutool.http.HttpRequest; -import cn.lige2333.qrdouble.parking.entity.CardDto; -import cn.lige2333.qrdouble.parking.service.CardService; -import cn.lige2333.qrdouble.stock.entity.Stock; -import cn.lige2333.qrdouble.stock.enums.StockMarket; -import cn.lige2333.qrdouble.stock.service.StockService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Description; import org.springframework.stereotype.Component; @@ -16,82 +9,14 @@ import java.util.function.Function; @Component public class GptFunctions { - - @Autowired - private StockService stockService; - - @Autowired - private CardService cardService; - - public record StockSearchRequest(Integer marketCode,String stockCode){} - - public record CardInfoRequest(String userId){} - public record JenkinsBuildRequest(String projectName){} - public record StockInfo(String stockCode, String stockName, StockMarket stockMarket,Double currentPrice,Double lastClosePrice,String priceRate){} - - @Bean - @Description("查找股票信息") - public Function findStock(){ - return stockSearchRequest -> { - Stock stockByCode = stockService.getStockByCode(stockSearchRequest.marketCode(), stockSearchRequest.stockCode()); - return new StockInfo(stockByCode.getStockCode(),stockByCode.getStockName(),StockMarket.getEnumByCode(stockByCode.getStockMarket()),stockByCode.getCurrentPrice(),stockByCode.getLastClosePrice(),stockByCode.getPriceRate()); - }; - } - - @Bean - @Description("查找打卡信息") - public Function getCardInfo(){ - return cardInfoRequest -> { - try { - return cardService.getCardInfo(cardInfoRequest.userId()); - }catch (Exception e){ - return new CardDto(); - } - }; - } - - @Bean - @Description("上班打卡") - public Function cardOn(){ - return cardInfoRequest -> { - try { - String res = cardService.doCardOn(cardInfoRequest.userId()); - if("1".equals(res)){ - return "成功"; - } else { - return "失败"; - } - }catch (Exception e){ - return "失败"; - } - }; - } - - @Bean - @Description("下班打卡") - public Function cardOff(){ - return cardInfoRequest -> { - try { - String res = cardService.doCardOff(cardInfoRequest.userId()); - if("1".equals(res)){ - return "成功"; - } else { - return "失败"; - } - }catch (Exception e){ - return "失败"; - } - }; - } - @Bean @Description("Jenkins构建") public Function jenkinsBuild(){ return jenkinsBuildRequest -> { try { - String url = "http://panel.lige2333.cn/buildByToken/build?token=lige2333&job="+jenkinsBuildRequest.projectName(); + String url = "http://jenkins.url"+jenkinsBuildRequest.projectName(); String body = HttpRequest.get(url) .timeout(10000) .execute().body(); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index fde55f2..4ab1f71 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,4 @@ spring.application.name=ligeai +server.port=8100 +spring.ai.openai.api-key=123 +spring.ai.openai.base-url=123 \ No newline at end of file diff --git a/src/test/java/cn/lige2333/ligeai/LigeaiApplicationTests.java b/src/test/java/cn/lige2333/ligeai/LigeaiApplicationTests.java index 03483ad..e3df417 100644 --- a/src/test/java/cn/lige2333/ligeai/LigeaiApplicationTests.java +++ b/src/test/java/cn/lige2333/ligeai/LigeaiApplicationTests.java @@ -6,8 +6,8 @@ import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class LigeaiApplicationTests { - @Test - void contextLoads() { - } + @Test + void contextLoads() { + } }