Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: OpenAI聊天机器人 #64

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public class RedisKey {
*/
public static final String USER_SUMMARY_STRING = "userSummary:uid_%d";

/**
* 用户AI聊天次数
*/
public static final String USER_CHAT_NUM = "userAIChatNum:uid_%d";

public static String getKey(String key, Object... objects) {
return BASE_KEY + String.format(key, objects);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.abin.mallchat.common.common.utils;

import java.util.Calendar;
import java.util.Date;

public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
public static Long getEndTimeByToday() {
Calendar instance = Calendar.getInstance();
Date now = new Date();
instance.setTime(now);
instance.set(Calendar.HOUR_OF_DAY, 23);
instance.set(Calendar.MINUTE, 59);
instance.set(Calendar.SECOND, 59);
return instance.getTime().getTime() - now.getTime();
}
}
13 changes: 9 additions & 4 deletions mallchat-common/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mybatis-plus:
spring:
profiles:
#运行的环境
active: my-prod
active: test
application:
name: mallchat
datasource:
Expand All @@ -37,8 +37,8 @@ spring:
database: 0
# 连接超时时间
timeout: 1800000
# 设置密码
password: ${mallchat.redis.password}
# # 设置密码
# password: ${mallchat.redis.password}
lettuce:
pool:
# 最大阻塞等待时间,负数表示没有限制
Expand All @@ -62,4 +62,9 @@ wx:
- appId: ${mallchat.wx.appId} # 第一个公众号的appid
secret: ${mallchat.wx.secret} # 公众号的appsecret
token: ${mallchat.wx.token} # 接口配置里的Token值
aesKey: ${mallchat.wx.aesKey} # 接口配置里的EncodingAESKey值
aesKey: ${mallchat.wx.aesKey} # 接口配置里的EncodingAESKey值
openai:
use-openai: true
ai-user-id: xxxxx
key: xxxxxxx
proxy-url: https://xxxxxxx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.abin.mallchat.custom.chat.service.strategy.msg.AbstractMsgHandler;
import com.abin.mallchat.custom.chat.service.strategy.msg.MsgHandlerFactory;
import com.abin.mallchat.custom.chat.service.strategy.msg.RecallMsgHandler;
import com.abin.mallchat.custom.openai.event.OpenAIEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -95,6 +96,7 @@ public Long sendMsg(ChatMessageReq request, Long uid) {
msgHandler.saveMsg(insert, request);
//发布消息发送事件
applicationEventPublisher.publishEvent(new MessageSendEvent(this, insert.getId()));
applicationEventPublisher.publishEvent(new OpenAIEvent(this, insert.getId()));
return insert.getId();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void checkMsg(ChatMessageReq request, Long uid) {
AssertUtil.equal(replyMsg.getRoomId(), request.getRoomId(), "只能回复相同会话内的消息");
}
if (CollectionUtil.isNotEmpty(body.getAtUidList())) {
AssertUtil.isTrue(body.getAtUidList().size() > 10, "一次别艾特这么多人");
AssertUtil.isFalse(body.getAtUidList().size() > 10, "一次别艾特这么多人");
List<Long> atUidList = body.getAtUidList();
Map<Long, User> batch = userInfoCache.getBatch(atUidList);
AssertUtil.equal(atUidList.size(), batch.values().size(), "@用户不存在");
Expand All @@ -86,6 +86,7 @@ public void saveMsg(Message msg, ChatMessageReq request) {//插入文本内容
update.setContent(SensitiveWordUtils.filter(body.getContent()));
update.setExtra(extra);
//如果有回复消息

if (Objects.nonNull(body.getReplyMsgId())) {
Integer gapCount = messageDao.getGapCount(request.getRoomId(), body.getReplyMsgId(), msg.getId());
update.setGapCount(gapCount);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.abin.mallchat.custom.openai.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@AllArgsConstructor
@Getter
public enum OpenAIModelEnums {
// chat
GPT_35_TURBO("gpt-3.5-turbo", 3, 40000),
GPT_35_TURBO_0301("gpt-3.5-turbo-0301", 3, 40000),
GPT_35_TURBO_0613("gpt-3.5-turbo-0613", 3, 40000),
GPT_35_TURBO_16K("gpt-3.5-turbo-16k", 3, 40000),
GPT_35_TURBO_16K_0613("gpt-3.5-turbo-16k-0613", 3, 40000),
// text
ADA("ada", 60, 150000),
ADA_CODE_SEARCH_CODE("ada-code-search-code", 60, 150000),
ADA_CODE_SEARCH_TEXT("ada-code-search-text", 60, 150000),
ADA_SEARCH_DOCUMENT("ada-search-document", 60, 150000),
ADA_SEARCH_QUERY("ada-search-query", 60, 150000),
ADA_SIMILARITY("ada-similarity", 60, 150000),
BABBAGE("babbage", 60, 150000),
BABBAGE_CODE_SEARCH_CODE("babbage-code-search-code", 60, 150000),
BABBAGE_CODE_SEARCH_TEXT("babbage-code-search-text", 60, 150000),
BABBAGE_SEARCH_DOCUMENT("babbage-search-document", 60, 150000),
BABBAGE_SEARCH_QUERY("babbage-search-query", 60, 150000),
BABBAGE_SIMILARITY("babbage-similarity", 60, 150000),
CODE_DAVINCI_EDIT_001("code-davinci-edit-001", 20, 150000),
CODE_SEARCH_ADA_CODE_001("code-search-ada-code-001", 60, 150000),
CODE_SEARCH_ADA_TEXT_001("code-search-ada-text-001", 60, 150000),
CODE_SEARCH_BABBAGE_CODE_001("code-search-babbage-code-001", 60, 150000),
CODE_SEARCH_BABBAGE_TEXT_001("code-search-babbage-text-001", 60, 150000),
CURIE("curie", 60, 150000),
CURIE_INSTRUCT_BETA("curie-instruct-beta", 60, 150000),
CURIE_SEARCH_DOCUMENT("curie-search-document", 60, 150000),
CURIE_SEARCH_QUERY("curie-search-query", 60, 150000),
CURIE_SIMILARITY("curie-similarity", 60, 150000),
DAVINCI("davinci", 60, 150000),
DAVINCI_INSTRUCT_BETA("davinci-instruct-beta", 60, 150000),
DAVINCI_SEARCH_DOCUMENT("davinci-search-document", 60, 150000),
DAVINCI_SEARCH_QUERY("davinci-search-query", 60, 150000),
DAVINCI_SIMILARITY("davinci-similarity", 60, 150000),
TEXT_ADA_001("text-ada-001", 60, 150000),
TEXT_BABBAGE_001("text-babbage-001", 60, 150000),
TEXT_CURIE_001("text-curie-001", 60, 150000),
TEXT_DAVINCI_001("text-davinci-001", 60, 150000),
TEXT_DAVINCI_002("text-davinci-002", 60, 150000),
TEXT_DAVINCI_003("text-davinci-003", 60, 150000),
TEXT_DAVINCI_EDIT_001("text-davinci-edit-001", 20, 150000),
TEXT_EMBEDDING_ADA_002("text-embedding-ada-002", 60, 150000),
TEXT_SEARCH_ADA_DOC_001("text-search-ada-doc-001", 60, 150000),
TEXT_SEARCH_ADA_QUERY_001("text-search-ada-query-001", 60, 150000),
TEXT_SEARCH_BABBAGE_DOC_001("text-search-babbage-doc-001", 60, 150000),
TEXT_SEARCH_BABBAGE_QUERY_001("text-search-babbage-query-001", 60, 150000),
TEXT_SEARCH_CURIE_DOC_001("text-search-curie-doc-001", 60, 150000),
TEXT_SEARCH_CURIE_QUERY_001("text-search-curie-query-001", 60, 150000),
TEXT_SEARCH_DAVINCI_DOC_001("text-search-davinci-doc-001", 60, 150000),
TEXT_SEARCH_DAVINCI_QUERY_001("text-search-davinci-query-001", 60, 150000),
TEXT_SIMILARITY_ADA_001("text-similarity-ada-001", 60, 150000),
TEXT_SIMILARITY_BABBAGE_001("text-similarity-babbage-001", 60, 150000),
TEXT_SIMILARITY_CURIE_001("text-similarity-curie-001", 60, 150000),
TEXT_SIMILARITY_DAVINCI_001("text-similarity-davinci-001", 60, 150000);

/**
* 名字
*/
private final String name;
/**
* 每分钟请求数
*/
private final Integer RPM;
/**
* 每分钟令牌数
*/
private final Integer TPM;

private static final Map<String, OpenAIModelEnums> cache;

static {
cache = Arrays.stream(OpenAIModelEnums.values()).collect(Collectors.toMap(OpenAIModelEnums::getName, Function.identity()));
}

public static OpenAIModelEnums of(String name) {
return cache.get(name);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.abin.mallchat.custom.openai.event;

import lombok.Getter;
import org.springframework.context.ApplicationEvent;

@Getter
public class OpenAIEvent extends ApplicationEvent {
private Long msgId;

public OpenAIEvent(Object source, Long msgId) {
super(source);
this.msgId = msgId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.abin.mallchat.custom.openai.event.listener;

import com.abin.mallchat.common.chat.dao.MessageDao;
import com.abin.mallchat.common.chat.domain.entity.Message;
import com.abin.mallchat.custom.openai.event.OpenAIEvent;
import com.abin.mallchat.custom.openai.service.IOpenAIService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;

import static com.abin.mallchat.custom.openai.service.impl.OpenAIServiceImpl.MALL_CHAT_AI_NAME;

/**
* 是否AI回复监听器
*
* @author zhaoyuhang
* @date 2023/06/29
*/
@Slf4j
@Component
public class OpenAIListener {
@Autowired
private IOpenAIService openAIService;
@Autowired
private MessageDao messageDao;

@TransactionalEventListener(classes = OpenAIEvent.class, fallbackExecution = true)
public void notifyAllOnline(@NotNull OpenAIEvent event) {
Message message = messageDao.getById(event.getMsgId());
if (ATedAI(message)) {
openAIService.chat(message);
}
}

/**
* @return boolean
* @了AI
*/
private boolean ATedAI(Message message) {
/* 前端传@信息后取消注释 */

// MessageExtra extra = message.getExtra();
// if (extra == null) {
// return false;
// }
// if (CollectionUtils.isEmpty(extra.getAtUidList())) {
// return false;
// }
// if (!extra.getAtUidList().contains(OpenAIServiceImpl.AI_USER_ID)) {
// return false;
// }

if (StringUtils.isBlank(message.getContent())) {
return false;
}
return StringUtils.contains(message.getContent(), "@" + MALL_CHAT_AI_NAME)
&& StringUtils.isNotBlank(message.getContent().replace(MALL_CHAT_AI_NAME, "").trim());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.abin.mallchat.custom.openai.service;

import com.abin.mallchat.common.chat.domain.entity.Message;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq;

public interface IOpenAIService {


void chat(ChatMessageReq chatMessageReq, Long uid);
void chat(Message message);
}
Loading