作者 钟来

模块整理

@@ -55,7 +55,7 @@ public class ChatController { @@ -55,7 +55,7 @@ public class ChatController {
55 @ResponseBody 55 @ResponseBody
56 public ChatResponse sseChat(@RequestBody ChatRequest chatRequest, @RequestHeader Map<String, String> headers, HttpServletResponse response) { 56 public ChatResponse sseChat(@RequestBody ChatRequest chatRequest, @RequestHeader Map<String, String> headers, HttpServletResponse response) {
57 String uid = getUid(headers); 57 String uid = getUid(headers);
58 - return sseService.sseChat(uid, chatRequest, ChatCompletion.Model.GPT_3_5_TURBO_0301,null); 58 + return sseService.sseChat(true,0,uid, chatRequest, ChatCompletion.Model.GPT_3_5_TURBO_0301,null);
59 } 59 }
60 60
61 /** 61 /**
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
4 import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse; 4 import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse;
5 import com.unfbx.chatgpt.entity.chat.Message; 5 import com.unfbx.chatgpt.entity.chat.Message;
6 import com.zhonglai.luhui.chatgpt.event.MyEvent; 6 import com.zhonglai.luhui.chatgpt.event.MyEvent;
  7 +import com.zhonglai.luhui.chatgpt.service.CompleteCallback;
7 import lombok.SneakyThrows; 8 import lombok.SneakyThrows;
8 import lombok.extern.slf4j.Slf4j; 9 import lombok.extern.slf4j.Slf4j;
9 import okhttp3.Response; 10 import okhttp3.Response;
@@ -28,8 +29,16 @@ public class OpenAISSEEventSourceListener extends EventSourceListener { @@ -28,8 +29,16 @@ public class OpenAISSEEventSourceListener extends EventSourceListener {
28 29
29 private SseEmitter sseEmitter; 30 private SseEmitter sseEmitter;
30 31
31 - public OpenAISSEEventSourceListener(SseEmitter sseEmitter) { 32 + private StringBuffer contents = new StringBuffer();
  33 +
  34 + private CompleteCallback completeCallback;
  35 +
  36 + private boolean isHaveData;
  37 + private int recordId;
  38 + public OpenAISSEEventSourceListener(SseEmitter sseEmitter, CompleteCallback completeCallback,int recordId) {
32 this.sseEmitter = sseEmitter; 39 this.sseEmitter = sseEmitter;
  40 + this.completeCallback = completeCallback;
  41 + this.recordId = recordId;
33 } 42 }
34 43
35 /** 44 /**
@@ -73,8 +82,14 @@ public class OpenAISSEEventSourceListener extends EventSourceListener { @@ -73,8 +82,14 @@ public class OpenAISSEEventSourceListener extends EventSourceListener {
73 Message delta = completionResponse.getChoices().get(0).getDelta(); 82 Message delta = completionResponse.getChoices().get(0).getDelta();
74 if(null != delta.getContent()) 83 if(null != delta.getContent())
75 { 84 {
  85 + if(isHaveData)
  86 + {
  87 + sseEmitter.send(delta.getContent(), MediaType.TEXT_EVENT_STREAM);
  88 + }else{
76 sseEmitter.send(new MyEvent().data(delta.getContent(), MediaType.TEXT_EVENT_STREAM)); 89 sseEmitter.send(new MyEvent().data(delta.getContent(), MediaType.TEXT_EVENT_STREAM));
77 } 90 }
  91 + contents.append(delta.getContent());
  92 + }
78 // sseEmitter.send(SseEmitter.event() 93 // sseEmitter.send(SseEmitter.event()
79 // .id(completionResponse.getId()) 94 // .id(completionResponse.getId())
80 // .data(delta.getContent()) 95 // .data(delta.getContent())
@@ -92,6 +107,10 @@ public class OpenAISSEEventSourceListener extends EventSourceListener { @@ -92,6 +107,10 @@ public class OpenAISSEEventSourceListener extends EventSourceListener {
92 public void onClosed(EventSource eventSource) { 107 public void onClosed(EventSource eventSource) {
93 log.info("流式输出返回值总共{}tokens", tokens() - 2); 108 log.info("流式输出返回值总共{}tokens", tokens() - 2);
94 log.info("OpenAI关闭sse连接..."); 109 log.info("OpenAI关闭sse连接...");
  110 + if(null != completeCallback)
  111 + {
  112 + completeCallback.sseChatEnd(recordId,tokens,contents.toString());
  113 + }
95 } 114 }
96 115
97 116
@@ -117,4 +136,13 @@ public class OpenAISSEEventSourceListener extends EventSourceListener { @@ -117,4 +136,13 @@ public class OpenAISSEEventSourceListener extends EventSourceListener {
117 public long tokens() { 136 public long tokens() {
118 return tokens; 137 return tokens;
119 } 138 }
  139 +
  140 + public String contents()
  141 + {
  142 + return contents.toString();
  143 + }
  144 +
  145 + public void setHaveData(boolean haveData) {
  146 + isHaveData = haveData;
  147 + }
120 } 148 }
1 package com.zhonglai.luhui.chatgpt.service; 1 package com.zhonglai.luhui.chatgpt.service;
2 2
3 import com.unfbx.chatgpt.entity.chat.ChatCompletion; 3 import com.unfbx.chatgpt.entity.chat.ChatCompletion;
  4 +import com.zhonglai.luhui.chatgpt.controller.request.ChatRequest;
4 import com.zhonglai.luhui.chatgpt.listener.OpenAISSEEventSourceListener; 5 import com.zhonglai.luhui.chatgpt.listener.OpenAISSEEventSourceListener;
5 6
6 public interface CompleteCallback { 7 public interface CompleteCallback {
7 - void sseChatEnd(ChatCompletion chatCompletion, OpenAISSEEventSourceListener openAISSEEventSourceListener); 8 + void sseChatEnd(int recordId,long tokens,String contents);
  9 + int recordSseChat(Integer user_id, ChatRequest chatRequest, ChatCompletion chatCompletion);
8 } 10 }
@@ -30,5 +30,5 @@ public interface SseService { @@ -30,5 +30,5 @@ public interface SseService {
30 * @param uid 30 * @param uid
31 * @param chatRequest 31 * @param chatRequest
32 */ 32 */
33 - ChatResponse sseChat(String uid, ChatRequest chatRequest, ChatCompletion.Model model, CompleteCallback completeCallback); 33 + ChatResponse sseChat(Boolean isHaveData,Integer user_id,String uid, ChatRequest chatRequest, ChatCompletion.Model model, CompleteCallback completeCallback);
34 } 34 }
@@ -87,7 +87,7 @@ public class SseServiceImpl implements SseService { @@ -87,7 +87,7 @@ public class SseServiceImpl implements SseService {
87 } 87 }
88 88
89 @Override 89 @Override
90 - public ChatResponse sseChat(String uid, ChatRequest chatRequest, ChatCompletion.Model model, CompleteCallback completeCallback) { 90 + public ChatResponse sseChat(Boolean isHaveData,Integer user_id,String uid, ChatRequest chatRequest, ChatCompletion.Model model, CompleteCallback completeCallback) {
91 if (ArrayUtil.isEmpty(chatRequest.getMsg())) { 91 if (ArrayUtil.isEmpty(chatRequest.getMsg())) {
92 log.info("参数异常,msg为null", uid); 92 log.info("参数异常,msg为null", uid);
93 throw new BaseException("参数异常,msg不能为空~"); 93 throw new BaseException("参数异常,msg不能为空~");
@@ -120,20 +120,27 @@ public class SseServiceImpl implements SseService { @@ -120,20 +120,27 @@ public class SseServiceImpl implements SseService {
120 log.info("聊天消息推送失败uid:[{}],没有创建连接,请重试。", uid); 120 log.info("聊天消息推送失败uid:[{}],没有创建连接,请重试。", uid);
121 throw new BaseException("聊天消息推送失败uid:[{}],没有创建连接,请重试。~"); 121 throw new BaseException("聊天消息推送失败uid:[{}],没有创建连接,请重试。~");
122 } 122 }
123 - OpenAISSEEventSourceListener openAIEventSourceListener = new OpenAISSEEventSourceListener(sseEmitter); 123 + log.info("{}加载监听业务", uid);
  124 +
124 ChatCompletion completion = ChatCompletion 125 ChatCompletion completion = ChatCompletion
125 .builder() 126 .builder()
126 .messages(messages) 127 .messages(messages)
127 .model(model.getName()) 128 .model(model.getName())
128 .build(); 129 .build();
  130 +
  131 + int recordId = 0;
  132 + if(null != completeCallback)
  133 + {
  134 + recordId = completeCallback.recordSseChat(user_id,chatRequest,completion);
  135 + }
  136 +
  137 + OpenAISSEEventSourceListener openAIEventSourceListener = new OpenAISSEEventSourceListener(sseEmitter,completeCallback,recordId);
  138 + openAIEventSourceListener.setHaveData(isHaveData);
129 openAiStreamClient.streamChatCompletion(completion, openAIEventSourceListener); 139 openAiStreamClient.streamChatCompletion(completion, openAIEventSourceListener);
130 // LocalCache.CACHE.put("msg" + uid, JSONUtil.toJsonStr(messages), LocalCache.TIMEOUT); 140 // LocalCache.CACHE.put("msg" + uid, JSONUtil.toJsonStr(messages), LocalCache.TIMEOUT);
131 ChatResponse response = new ChatResponse(); 141 ChatResponse response = new ChatResponse();
132 response.setQuestionTokens(completion.tokens()); 142 response.setQuestionTokens(completion.tokens());
133 - if(null != completeCallback)  
134 - {  
135 - completeCallback.sseChatEnd(completion,openAIEventSourceListener);  
136 - } 143 +
137 return response; 144 return response;
138 } 145 }
139 } 146 }
@@ -2,9 +2,14 @@ package com.zhonglai.luhui.openai; @@ -2,9 +2,14 @@ package com.zhonglai.luhui.openai;
2 2
3 import com.ruoyi.common.utils.StringUtils; 3 import com.ruoyi.common.utils.StringUtils;
4 import okhttp3.OkHttpClient; 4 import okhttp3.OkHttpClient;
  5 +import org.apache.tomcat.util.http.LegacyCookieProcessor;
5 import org.springframework.boot.SpringApplication; 6 import org.springframework.boot.SpringApplication;
6 import org.springframework.boot.autoconfigure.SpringBootApplication; 7 import org.springframework.boot.autoconfigure.SpringBootApplication;
7 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 8 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  9 +import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
  10 +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
  11 +import org.springframework.boot.web.server.WebServerFactoryCustomizer;
  12 +import org.springframework.context.annotation.Bean;
8 import org.springframework.context.annotation.ComponentScan; 13 import org.springframework.context.annotation.ComponentScan;
9 14
10 import java.net.URL; 15 import java.net.URL;
@@ -27,4 +32,11 @@ public class OpenaiApplication { @@ -27,4 +32,11 @@ public class OpenaiApplication {
27 SpringApplication.run(OpenaiApplication.class,args); 32 SpringApplication.run(OpenaiApplication.class,args);
28 System.out.println("启动成功"); 33 System.out.println("启动成功");
29 } 34 }
  35 +
  36 + @Bean
  37 + public WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieProcessorCustomizer() {
  38 + return tomcatServletWebServerFactory -> tomcatServletWebServerFactory.addContextCustomizers((TomcatContextCustomizer) context -> {
  39 + context.setCookieProcessor(new LegacyCookieProcessor());
  40 + });
  41 + }
30 } 42 }
@@ -38,12 +38,11 @@ import java.util.concurrent.TimeUnit; @@ -38,12 +38,11 @@ import java.util.concurrent.TimeUnit;
38 @RequestMapping("/chatGPTStream") 38 @RequestMapping("/chatGPTStream")
39 public class ChatGPTStreamController extends BaseController { 39 public class ChatGPTStreamController extends BaseController {
40 private static String sessionkey = "CHAT_HISTORY_CONTEXT";//上下文关联存放地址 40 private static String sessionkey = "CHAT_HISTORY_CONTEXT";//上下文关联存放地址
41 - @Autowired  
42 - private PublicService publicService;  
43 41
44 @Autowired 42 @Autowired
45 private VipServiceImpl vipService; 43 private VipServiceImpl vipService;
46 - 44 + @Autowired
  45 + private CompleteCallback completeCallback;
47 @Autowired 46 @Autowired
48 private ScheduledExecutorService scheduledExecutorService; 47 private ScheduledExecutorService scheduledExecutorService;
49 private final SseService sseService; 48 private final SseService sseService;
@@ -67,23 +66,13 @@ public class ChatGPTStreamController extends BaseController { @@ -67,23 +66,13 @@ public class ChatGPTStreamController extends BaseController {
67 OpenAiLoginUser userInfo = (OpenAiLoginUser) SecurityUtils.getLoginUser(); 66 OpenAiLoginUser userInfo = (OpenAiLoginUser) SecurityUtils.getLoginUser();
68 67
69 Integer user_id= SecurityUtils.getUserId().intValue(); 68 Integer user_id= SecurityUtils.getUserId().intValue();
70 - String room_id = String.valueOf(user_id);  
71 69
72 String uid = UUID.randomUUID().toString(); 70 String uid = UUID.randomUUID().toString();
73 SseEmitter sseEmitter = sseService.createSse(uid); 71 SseEmitter sseEmitter = sseService.createSse(uid);
74 72
75 scheduledExecutorService.schedule(() -> { 73 scheduledExecutorService.schedule(() -> {
76 try{ 74 try{
77 - BigDecimal[] bs = vipService.getUnitprice();  
78 - BigDecimal openaiUnitprice = bs[0];  
79 - BigDecimal realityUnitprice = bs[1];  
80 - if(openaiUnitprice.doubleValue()==0 || realityUnitprice.doubleValue()==0)  
81 - {  
82 - throw new BaseException("系统未配置流量单价,请联系管理员");  
83 - }  
84 -  
85 OpenAiUserInfo openAiUserInfo = (OpenAiUserInfo) userInfo.getUser(); 75 OpenAiUserInfo openAiUserInfo = (OpenAiUserInfo) userInfo.getUser();
86 -  
87 //验证余额是否充足 76 //验证余额是否充足
88 if(vipService.isCharging(openAiUserInfo.getVip_level()) && openAiUserInfo.getFlow_packet_remain()<=0) 77 if(vipService.isCharging(openAiUserInfo.getVip_level()) && openAiUserInfo.getFlow_packet_remain()<=0)
89 { 78 {
@@ -95,56 +84,57 @@ public class ChatGPTStreamController extends BaseController { @@ -95,56 +84,57 @@ public class ChatGPTStreamController extends BaseController {
95 completionChoiceMessage3_5.setContent(stringBuffer.toString()); 84 completionChoiceMessage3_5.setContent(stringBuffer.toString());
96 throw new BaseException("您的余额不足请联系管理员或者充值"); 85 throw new BaseException("您的余额不足请联系管理员或者充值");
97 } 86 }
  87 + sseService.sseChat(true,user_id,uid, chatRequest, chatRequest.getModel(),completeCallback);
  88 + }catch (Exception e)
  89 + {
  90 + log.error("主业务流程异常",e);
  91 + try {
  92 + String estr = e.getMessage();
  93 + if(null == estr)
  94 + {
  95 + estr = "系统异常,请联系管理员";
  96 + }
  97 + sseEmitter.send(estr, MediaType.TEXT_EVENT_STREAM);
  98 + } catch (IOException ex) {
  99 + log.error("sse信息推送失败!");
  100 + e.printStackTrace();
  101 + }
  102 + sseService.closeSse(uid);
  103 + }
98 104
99 - CompleteCallback completeCallback = (chatCompletion, openAISSEEventSourceListener) -> {  
100 - GptMessage gptMessage = new GptMessage();  
101 - gptMessage.setRoom_id(room_id);  
102 - gptMessage.setUser_id(user_id);  
103 - gptMessage.setCreate_time(DateUtils.getNowTimeMilly());  
104 - gptMessage.setSend_role("user");  
105 -  
106 - StringBuffer content = new StringBuffer();  
107 - for (com.unfbx.chatgpt.entity.chat.Message messge : chatCompletion.getMessages()) {  
108 - content.append(messge.getContent()); 105 + },1, TimeUnit.SECONDS);
  106 + return sseEmitter;
109 } 107 }
110 - gptMessage.setSend_content(content.toString());  
111 - gptMessage.setSend_size(gptMessage.getSend_content().length());  
112 - //统计代币  
113 - gptMessage.setCompletion_tokens(UnitPriceCountUtil.countToken(chatRequest.getModel(),openAISSEEventSourceListener.tokens(),UnitPriceCountUtil.FlowType.Completion));  
114 - gptMessage.setPrompt_tokens(UnitPriceCountUtil.countToken(chatRequest.getModel(),chatCompletion.tokens(),UnitPriceCountUtil.FlowType.Completion));  
115 - gptMessage.setTotal_tokens(gptMessage.getCompletion_tokens() + gptMessage.getPrompt_tokens());  
116 - gptMessage.setMessage_role(chatCompletion.getMessages().get(0).getRole());  
117 -// gptMessage.setMessage_content(openAISSEEventSourceListener.contents());  
118 - gptMessage.setMessage_size(Long.valueOf(openAISSEEventSourceListener.tokens()).intValue());  
119 - publicService.insertToTable(gptMessage, "`lk_openai`.`gpt_message`");  
120 -  
121 - UserFlowPacketRemainLog userFlowPacketRemainLog = new UserFlowPacketRemainLog();  
122 - userFlowPacketRemainLog.setCreate_time(DateUtils.getNowTimeMilly());  
123 - userFlowPacketRemainLog.setUser_id(user_id);  
124 - userFlowPacketRemainLog.setType(2); //消费  
125 108
  109 +
  110 + @ApiOperation(value = "聊天接口返回data")
  111 + @Transactional
  112 + @PostMapping("/chatNotData")
  113 + @ResponseBody
  114 + public SseEmitter chatNotData(@RequestBody ChatRequest chatRequest) {
  115 +
  116 + OpenAiLoginUser userInfo = (OpenAiLoginUser) SecurityUtils.getLoginUser();
  117 +
  118 + Integer user_id= SecurityUtils.getUserId().intValue();
  119 +
  120 + String uid = UUID.randomUUID().toString();
  121 + SseEmitter sseEmitter = sseService.createSse(uid);
  122 +
  123 + scheduledExecutorService.schedule(() -> {
  124 + try{
  125 + OpenAiUserInfo openAiUserInfo = (OpenAiUserInfo) userInfo.getUser();
  126 + //验证余额是否充足
  127 + if(vipService.isCharging(openAiUserInfo.getVip_level()) && openAiUserInfo.getFlow_packet_remain()<=0)
  128 + {
  129 + CompletionChoiceMessage3_5 completionChoiceMessage3_5 = new CompletionChoiceMessage3_5();
  130 + completionChoiceMessage3_5.setRole("assistant");
126 StringBuffer stringBuffer = new StringBuffer(); 131 StringBuffer stringBuffer = new StringBuffer();
127 - stringBuffer.append("房间号:");  
128 - stringBuffer.append(room_id);  
129 - stringBuffer.append(";");  
130 - stringBuffer.append("发送代币:");  
131 - stringBuffer.append(gptMessage.getPrompt_tokens());  
132 - stringBuffer.append(";");  
133 - stringBuffer.append("返回代币:");  
134 - stringBuffer.append(gptMessage.getCompletion_tokens());  
135 - stringBuffer.append(";");  
136 -  
137 - userFlowPacketRemainLog.setDescribe(stringBuffer.toString());  
138 - userFlowPacketRemainLog.setTotal_tokens(gptMessage.getTotal_tokens());  
139 -  
140 - userFlowPacketRemainLog.setOpenai_money((openaiUnitprice.multiply(new BigDecimal(gptMessage.getTotal_tokens()))).divide(new BigDecimal(1000), 6, BigDecimal.ROUND_HALF_UP));  
141 - userFlowPacketRemainLog.setReality_money((realityUnitprice.multiply(new BigDecimal(gptMessage.getTotal_tokens()))).divide(new BigDecimal(1000), 6, BigDecimal.ROUND_HALF_UP));  
142 - publicService.insertToTable(userFlowPacketRemainLog, "`lk_openai`.`user_flow_packet_remain_log`");  
143 -  
144 - publicService.updateBySql("UPDATE `lk_openai`.`user_info` SET flow_packet_remain=flow_packet_remain-" + userFlowPacketRemainLog.getTotal_tokens() + " WHERE id=" + openAiUserInfo.getId());  
145 -  
146 - };  
147 - sseService.sseChat(uid, chatRequest, chatRequest.getModel(),completeCallback); 132 + stringBuffer.append("您的余额不足请联系管理员或者点击链接充值:\\n\\n");
  133 + stringBuffer.append("https://充值链接.com");
  134 + completionChoiceMessage3_5.setContent(stringBuffer.toString());
  135 + throw new BaseException("您的余额不足请联系管理员或者充值");
  136 + }
  137 + sseService.sseChat(false,user_id,uid, chatRequest, chatRequest.getModel(),completeCallback);
148 }catch (Exception e) 138 }catch (Exception e)
149 { 139 {
150 log.error("主业务流程异常",e); 140 log.error("主业务流程异常",e);
@@ -166,6 +156,7 @@ public class ChatGPTStreamController extends BaseController { @@ -166,6 +156,7 @@ public class ChatGPTStreamController extends BaseController {
166 return sseEmitter; 156 return sseEmitter;
167 } 157 }
168 158
  159 +
169 /** 160 /**
170 * 关闭连接 161 * 关闭连接
171 * 162 *
@@ -16,6 +16,26 @@ public class GptMessage { @@ -16,6 +16,26 @@ public class GptMessage {
16 16
17 private Long total_tokens; //bigint(20) DEFAULT NULL COMMENT '总代币', 17 private Long total_tokens; //bigint(20) DEFAULT NULL COMMENT '总代币',
18 18
  19 + private Integer user_flow_packet_remain_log_id; //用户加油包消费日志id
  20 +
  21 + private String model; //请求模型
  22 +
  23 + public String getModel() {
  24 + return model;
  25 + }
  26 +
  27 + public void setModel(String model) {
  28 + this.model = model;
  29 + }
  30 +
  31 + public Integer getUser_flow_packet_remain_log_id() {
  32 + return user_flow_packet_remain_log_id;
  33 + }
  34 +
  35 + public void setUser_flow_packet_remain_log_id(Integer user_flow_packet_remain_log_id) {
  36 + this.user_flow_packet_remain_log_id = user_flow_packet_remain_log_id;
  37 + }
  38 +
19 public Long getTotal_tokens() { 39 public Long getTotal_tokens() {
20 return total_tokens; 40 return total_tokens;
21 } 41 }
  1 +package com.zhonglai.luhui.openai.service;
  2 +
  3 +import com.ruoyi.common.utils.DateUtils;
  4 +import com.unfbx.chatgpt.entity.chat.ChatCompletion;
  5 +import com.unfbx.chatgpt.exception.BaseException;
  6 +import com.zhonglai.luhui.chatgpt.controller.request.ChatRequest;
  7 +import com.zhonglai.luhui.chatgpt.listener.OpenAISSEEventSourceListener;
  8 +import com.zhonglai.luhui.chatgpt.service.CompleteCallback;
  9 +import com.zhonglai.luhui.dao.service.PublicService;
  10 +import com.zhonglai.luhui.openai.dto.GptMessage;
  11 +import com.zhonglai.luhui.openai.dto.UserFlowPacketRemainLog;
  12 +import com.zhonglai.luhui.openai.utils.UnitPriceCountUtil;
  13 +import com.zhonglai.luhui.security.dto.OpenAiUserInfo;
  14 +import org.springframework.beans.factory.annotation.Autowired;
  15 +import org.springframework.stereotype.Service;
  16 +
  17 +import java.math.BigDecimal;
  18 +import java.util.Arrays;
  19 +
  20 +@Service
  21 +public class CompleteCallbackImpl implements CompleteCallback {
  22 +
  23 + @Autowired
  24 + private PublicService publicService;
  25 +
  26 + @Autowired
  27 + private VipServiceImpl vipService;
  28 +
  29 + @Override
  30 + public void sseChatEnd(int recordId,long tokens,String contents) {
  31 + BigDecimal[] bs = vipService.getUnitprice();
  32 + BigDecimal openaiUnitprice = bs[0];
  33 + BigDecimal realityUnitprice = bs[1];
  34 + if(openaiUnitprice.doubleValue()==0 || realityUnitprice.doubleValue()==0)
  35 + {
  36 + throw new BaseException("系统未配置流量单价,请联系管理员");
  37 + }
  38 +
  39 + if(0 == recordId)
  40 + {
  41 + return;
  42 + }
  43 +
  44 + GptMessage gptMessage = publicService.getObjectForTableName(GptMessage.class,"id",recordId+"","`lk_openai`.`gpt_message`");
  45 +
  46 + GptMessage upGptMessage = new GptMessage();
  47 + gptMessage.setCompletion_tokens(tokens);
  48 + upGptMessage.setTotal_tokens(gptMessage.getCompletion_tokens() + gptMessage.getPrompt_tokens());
  49 + Arrays.stream(ChatCompletion.Model.values()).forEach(model -> {
  50 + if (model.getName().equals(gptMessage.getModel()))
  51 + upGptMessage.setCompletion_tokens(UnitPriceCountUtil.countToken(model,tokens,UnitPriceCountUtil.FlowType.Completion));
  52 + });
  53 + upGptMessage.setMessage_content(contents);
  54 + upGptMessage.setMessage_size(upGptMessage.getMessage_content().length());
  55 + upGptMessage.setId(gptMessage.getId());
  56 + publicService.updateObjectByTable(upGptMessage,"id","`lk_openai`.`gpt_message`");
  57 +
  58 + StringBuffer stringBuffer = new StringBuffer();
  59 + stringBuffer.append("房间号:");
  60 + stringBuffer.append(gptMessage.getRoom_id());
  61 + stringBuffer.append(";");
  62 + stringBuffer.append("发送代币:");
  63 + stringBuffer.append(gptMessage.getPrompt_tokens());
  64 + stringBuffer.append(";");
  65 + stringBuffer.append("返回代币:");
  66 + stringBuffer.append(gptMessage.getCompletion_tokens());
  67 + stringBuffer.append(";");
  68 +
  69 + UserFlowPacketRemainLog userFlowPacketRemainLog = new UserFlowPacketRemainLog();
  70 + userFlowPacketRemainLog.setDescribe(stringBuffer.toString());
  71 + userFlowPacketRemainLog.setTotal_tokens(upGptMessage.getTotal_tokens());
  72 + userFlowPacketRemainLog.setOpenai_money((openaiUnitprice.multiply(new BigDecimal(upGptMessage.getTotal_tokens()))).divide(new BigDecimal(1000), 6, BigDecimal.ROUND_HALF_UP));
  73 + userFlowPacketRemainLog.setReality_money((realityUnitprice.multiply(new BigDecimal(upGptMessage.getTotal_tokens()))).divide(new BigDecimal(1000), 6, BigDecimal.ROUND_HALF_UP));
  74 + userFlowPacketRemainLog.setId(gptMessage.getUser_flow_packet_remain_log_id());
  75 + publicService.updateObjectByTable(userFlowPacketRemainLog,"id","`lk_openai`.`user_flow_packet_remain_log`");
  76 +
  77 + publicService.updateBySql("UPDATE `lk_openai`.`user_info` SET flow_packet_remain=flow_packet_remain-" + userFlowPacketRemainLog.getTotal_tokens() + " WHERE id=" + gptMessage.getUser_id());
  78 +
  79 + }
  80 +
  81 + @Override
  82 + public int recordSseChat(Integer user_id, ChatRequest chatRequest, ChatCompletion chatCompletion) {
  83 +
  84 + String room_id = String.valueOf(user_id);
  85 +
  86 + UserFlowPacketRemainLog userFlowPacketRemainLog = new UserFlowPacketRemainLog();
  87 + userFlowPacketRemainLog.setCreate_time(DateUtils.getNowTimeMilly());
  88 + userFlowPacketRemainLog.setUser_id(user_id);
  89 + userFlowPacketRemainLog.setType(2); //消费
  90 + publicService.insertToTable(userFlowPacketRemainLog, "`lk_openai`.`user_flow_packet_remain_log`");
  91 +
  92 + GptMessage gptMessage = new GptMessage();
  93 + gptMessage.setRoom_id(room_id);
  94 + gptMessage.setUser_id(user_id);
  95 + gptMessage.setCreate_time(DateUtils.getNowTimeMilly());
  96 + gptMessage.setSend_role("user");
  97 + gptMessage.setModel(chatRequest.getModel().getName());
  98 + StringBuffer content = new StringBuffer();
  99 + for (com.unfbx.chatgpt.entity.chat.Message messge : chatCompletion.getMessages()) {
  100 + content.append(messge.getContent());
  101 + }
  102 + gptMessage.setSend_content(content.toString());
  103 + gptMessage.setSend_size(gptMessage.getSend_content().length());
  104 + //统计代币
  105 + gptMessage.setPrompt_tokens(UnitPriceCountUtil.countToken(chatRequest.getModel(),chatCompletion.tokens(),UnitPriceCountUtil.FlowType.Completion));
  106 + gptMessage.setMessage_role(chatCompletion.getMessages().get(0).getRole());
  107 +
  108 + gptMessage.setUser_flow_packet_remain_log_id(userFlowPacketRemainLog.getId());
  109 + publicService.insertToTable(gptMessage, "`lk_openai`.`gpt_message`");
  110 +
  111 + return gptMessage.getId();
  112 + }
  113 +}
1 -# 项目相关配置 jhlt: # 名称 name: zhonglai # 版本 version: 3.8.2 # 版权年份 copyrightYear: 2022 # 获取ip地址开关 addressEnabled: false profile: /www/wwwroot/lh-openai # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 port: 8082 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # 连接数满后的排队数,默认为100 accept-count: 1000 threads: # tomcat最大线程数,默认为200 max: 800 # Tomcat启动初始化的线程数,默认值10 min-spare: 100 # 日志配置 logging: level: com.ruoyi: debug org.springframework: warn # Spring配置 spring: # 资源信息 messages: # 国际化资源文件路径 basename: i18n/messages profiles: active: druid # 文件上传 servlet: multipart: # 单个文件大小 max-file-size: 10MB # 设置总上传的文件大小 max-request-size: 20MB # 服务模块 devtools: restart: # 热部署开关 enabled: true # redis 配置 redis: # 地址 host: 47.112.163.61 # 端口,默认为6379 port: 9527 # 数据库索引 database: 1 # 密码 password: Luhui586 # 连接超时时间 timeout: 10s lettuce: pool: # 连接池中的最小空闲连接 min-idle: 0 # 连接池中的最大空闲连接 max-idle: 8 # 连接池的最大数据库连接数 max-active: 8 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # web: # resources: # static-locations: classpath:/static/, classpath:/templates/ # token配置 token: # 令牌自定义标识 header: Authorization # 令牌密钥 secret: abcdefghijklmnopqrstuvwxyz # 令牌有效期(默认30分钟) expireTime: 1440 rediskey: lh-openai # MyBatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 pagehelper: helperDialect: mysql supportMethodsArguments: true params: count=countSql # Swagger配置 swagger: # 是否开启swagger enabled: true # 请求前缀 pathMapping: /dev-api # 防止XSS攻击 xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* sys: ## // 对于登录login 注册register 验证码captchaImage 允许匿名访问 antMatchers: /login,/register,/captchaImage,/getCacheObject,/v2/api-docs,/openAiUserLogin/*,/chatGPTStream/upUserFlowPacketRemain,/createSse,/chat,/closeSse chatgpt: token: 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 timeout: 5000 apiHost: https://api.openai.com/ proxy: isProxy: fales host: 127.0.0.1 port: 7890  
  1 +# 项目相关配置 jhlt: # 名称 name: zhonglai # 版本 version: 3.8.2 # 版权年份 copyrightYear: 2022 # 获取ip地址开关 addressEnabled: false profile: /www/wwwroot/lh-openai # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 port: 8082 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # 连接数满后的排队数,默认为100 accept-count: 1000 threads: # tomcat最大线程数,默认为200 max: 800 # Tomcat启动初始化的线程数,默认值10 min-spare: 100 # 日志配置 logging: level: com.ruoyi: debug org.springframework: warn # Spring配置 spring: # 资源信息 messages: # 国际化资源文件路径 basename: i18n/messages profiles: active: druid # 文件上传 servlet: multipart: # 单个文件大小 max-file-size: 10MB # 设置总上传的文件大小 max-request-size: 20MB # 服务模块 devtools: restart: # 热部署开关 enabled: true # redis 配置 redis: # 地址 host: 47.112.163.61 # 端口,默认为6379 port: 9527 # 数据库索引 database: 1 # 密码 password: Luhui586 # 连接超时时间 timeout: 10s lettuce: pool: # 连接池中的最小空闲连接 min-idle: 0 # 连接池中的最大空闲连接 max-idle: 8 # 连接池的最大数据库连接数 max-active: 8 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # web: # resources: # static-locations: classpath:/static/, classpath:/templates/ # token配置 token: # 令牌自定义标识 header: Authorization # 令牌密钥 secret: abcdefghijklmnopqrstuvwxyz # 令牌有效期(默认30分钟) expireTime: 1440 rediskey: lh-openai # MyBatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 pagehelper: helperDialect: mysql supportMethodsArguments: true params: count=countSql # Swagger配置 swagger: # 是否开启swagger enabled: true # 请求前缀 pathMapping: /dev-api # 防止XSS攻击 xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* sys: ## // 对于登录login 注册register 验证码captchaImage 允许匿名访问 antMatchers: /login,/register,/captchaImage,/getCacheObject,/v2/api-docs,/openAiUserLogin/*,/chatGPTStream/upUserFlowPacketRemain,/createSse,/chat,/closeSse chatgpt: token: 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 timeout: 5000 apiHost: https://api.openai.com/ proxy: isProxy: true host: 127.0.0.1 port: 7890