master
lige2333 10 hours ago
parent 3c85f51768
commit 5701fb6c43

@ -40,9 +40,14 @@
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.21</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
@ -64,12 +69,6 @@
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>

@ -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();

@ -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<String> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return this.chatClient.prompt()
.user(message)
.stream()
.content();
}
}

@ -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<Map<String,String>> getChatGptResStream(String input, SysUser sysUser) throws IOException {
if(Objects.isNull(sysUser)){
throw new RuntimeException("用户信息获取失败!");
}
public Flux<Map<String,String>> getChatGptResStream(String input) throws IOException {
String id = UUID.randomUUID().toString();
Map<String, String> finishMap = new HashMap<>();
finishMap.put("content", "[DONE]");
@ -96,163 +67,4 @@ public class ChatGptService {
}
public ChatCompletionResponse getCompletionRes(ChatCompletion chatCompletion) {
List<Message> 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<ChatCompletionResponse> getStreamingRes(ChatCompletion chatCompletion) {
List<Message> messages = chatCompletion.getMessages();
if(CollUtil.isNotEmpty(messages)){
Message message = messages.get(messages.size() - 1);
Flux<ChatCompletionResponse> 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<Message> 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<Message> getMessages(String input, SysUser sysUser) {
String messageContext = (String) LocalCache.CACHE.get(sysUser.getUserName());
List<Message> 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<Content> 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<Content> 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<ChatCompletionResponse> 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;
}
}

@ -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<StockSearchRequest, StockInfo> 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<CardInfoRequest, CardDto> getCardInfo(){
return cardInfoRequest -> {
try {
return cardService.getCardInfo(cardInfoRequest.userId());
}catch (Exception e){
return new CardDto();
}
};
}
@Bean
@Description("上班打卡")
public Function<CardInfoRequest, String> 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<CardInfoRequest, String> 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<JenkinsBuildRequest, String> 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();

@ -1 +1,4 @@
spring.application.name=ligeai
server.port=8100
spring.ai.openai.api-key=123
spring.ai.openai.base-url=123
Loading…
Cancel
Save