Commit 4319e361 authored by shiyu's avatar shiyu

ai会话

parent d15af2cf
......@@ -7,6 +7,12 @@ import lombok.Data;
@Data
public class SendChatMsgRequestDto implements Entity {
/**
* 发送消息的请求id
* 用于停止AI回答
*/
private String reqId;
/**
* 1:把消息同步到 From_Account 在线终端和漫游上
* 2:消息不同步至 From_Account
......
......@@ -54,16 +54,7 @@ public class ChatUserApi {
* @return
*/
public Result importUser(User user) {
String userSig = tlsSigApi.getUserSig(ADMIN_ID);
Random random = new Random(4294967295L);
long randomNum = random.nextInt();
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("?sdkappid=" + SDKAppID);
stringBuffer.append("&identifier=" + ADMIN_ID);
stringBuffer.append("&usersig=" + userSig);
stringBuffer.append("&random=" + randomNum);
stringBuffer.append("&contenttype=json");
String url = ACCOUNT_URL + stringBuffer.toString();
String url = imUtil.formatIMUrl(ACCOUNT_URL);
logger.info("============== IM导入用户请求url : {}", url);
OkHttpUtil okHttpUtil = OkHttpUtil.builder().url(url);
Map<String, Object> map = new HashMap<>();
......@@ -93,16 +84,7 @@ public class ChatUserApi {
* @return
*/
public Result importAiUser(AiAssistant aiAssistant) {
String userSig = tlsSigApi.getUserSig(ADMIN_ID);
Random random = new Random(4294967295L);
long randomNum = random.nextInt();
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("?sdkappid=" + SDKAppID);
stringBuffer.append("&identifier=" + ADMIN_ID);
stringBuffer.append("&usersig=" + userSig);
stringBuffer.append("&random=" + randomNum);
stringBuffer.append("&contenttype=json");
String url = ACCOUNT_URL + stringBuffer.toString();
String url = imUtil.formatIMUrl(ACCOUNT_URL);
logger.info("============== IM导入用户请求url : {}", url);
OkHttpUtil okHttpUtil = OkHttpUtil.builder().url(url);
Map<String, Object> map = new HashMap<>();
......
......@@ -17,7 +17,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.*;
......@@ -29,16 +28,10 @@ public class ConversationApi {
private static final Logger logger = LoggerFactory.getLogger(ConversationApi.class);
private static final String ACCOUNT_URL = "https://console.tim.qq.com/v4/openim/sendmsg";
private static final String SEND_MSG_URL = "https://console.tim.qq.com/v4/openim/sendmsg";
private static final String GET_CHAT_LIST_URL = "https://console.tim.qq.com/v4/recentcontact/get_list";
@Value("${dts.im.adminid}")
private String ADMIN_ID;
@Value("${dts.im.SDKAppID}")
private Long SDKAppID;
@Autowired
TLSSigApi tlsSigApi;
......@@ -51,16 +44,9 @@ public class ConversationApi {
* @return
*/
public Result sendChatMsg(SendChatMsgRequestDto sendChatMsgRequestDto) {
String userSig = tlsSigApi.getUserSig(ADMIN_ID);
Random random = new Random(4294967295L);
int randomNum = random.nextInt();
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("?sdkappid=" + SDKAppID);
stringBuffer.append("&identifier=" + ADMIN_ID);
stringBuffer.append("&usersig=" + userSig);
stringBuffer.append("&random=" + randomNum);
stringBuffer.append("&contenttype=json");
String url = ACCOUNT_URL + stringBuffer.toString();
String url = imUtil.formatIMUrl(SEND_MSG_URL);
OkHttpUtil okHttpUtil = OkHttpUtil.builder().url(url);
IMChatMsg imChatMsg = imUtil.convert(sendChatMsgRequestDto);
//消息同步至发送方
......@@ -89,18 +75,8 @@ public class ConversationApi {
* @return
*/
public Result getChatList(IMChatRequestDto imChatRequestDto) {
String userSig = tlsSigApi.getUserSig(ADMIN_ID);
Random random = new Random(4294967295L);
int randomNum = random.nextInt();
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("?sdkappid=" + SDKAppID);
stringBuffer.append("&identifier=" + ADMIN_ID);
stringBuffer.append("&usersig=" + userSig);
stringBuffer.append("&random=" + randomNum);
stringBuffer.append("&contenttype=json");
String url = GET_CHAT_LIST_URL + stringBuffer.toString();
String url = imUtil.formatIMUrl(GET_CHAT_LIST_URL);
OkHttpUtil okHttpUtil = OkHttpUtil.builder().url(url);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("From_Account", imUtil.formatUserId(imChatRequestDto.getUserId() + ""));
paramMap.put("TimeStamp", imChatRequestDto.getTimeStamp());
......
......@@ -3,12 +3,15 @@ package com.wwdz.ch.core.util;
import com.wwdz.ch.core.consts.IMEnum;
import com.wwdz.ch.core.entity.im.SendChatMsgRequestDto;
import com.wwdz.ch.core.entity.im.IMChatMsg;
import com.wwdz.ch.core.im.api.TLSSigApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@Component
public class IMUtil {
......@@ -16,6 +19,15 @@ public class IMUtil {
@Value("${dts.im.prefix}")
private String PREFIX;
@Value("${dts.im.adminid}")
private String ADMIN_ID;
@Value("${dts.im.SDKAppID}")
private Long SDKAppID;
@Autowired
TLSSigApi tlsSigApi;
/**
* 格式化用户id
* 转换为im对话中的用户id
......@@ -54,4 +66,18 @@ public class IMUtil {
imChatMsg.setMsgBody(Arrays.asList(msgContentMap));
return imChatMsg;
}
public String formatIMUrl(String url) {
String userSig = tlsSigApi.getUserSig(ADMIN_ID);
Random random = new Random(4294967295L);
int randomNum = random.nextInt();
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("?sdkappid=" + SDKAppID);
stringBuffer.append("&identifier=" + ADMIN_ID);
stringBuffer.append("&usersig=" + userSig);
stringBuffer.append("&random=" + randomNum);
stringBuffer.append("&contenttype=json");
return url + stringBuffer.toString();
}
}
......@@ -28,6 +28,7 @@ dts:
secret: b5873a44e46efd086015a51e171e6e09fdeb4dce778752c891e63ed17aa1a81e
prefix: cjxc-applet-dev_
adminid: cjxc
default-ai-code: ai10000
#通知相关配置
notify:
......
......@@ -27,6 +27,7 @@ dts:
secret: b5873a44e46efd086015a51e171e6e09fdeb4dce778752c891e63ed17aa1a81e
prefix: cjxc-applet_
adminid: cjxc
default-ai-code: ai10000
#通知相关配置
notify:
......
......@@ -9,4 +9,8 @@ public interface AiAssistantDao {
List<AiAssistant> findList (AiAssistantRequestDto dto);
AiAssistant findByCode (String code);
AiAssistant findByType (Integer type);
}
......@@ -6,9 +6,20 @@ import lombok.Data;
@Data
public class AiDefaultQuestionRequestDto extends BaseRequestDto implements Entity {
/**
* 当前用户id
*/
private Long userId;
/**
* 问题类型
*/
private Integer type;
/**
* 是否换一批问题
* 1是; 0否
*/
private Integer isChangeList;
}
......@@ -21,6 +21,8 @@ public class AiAssistantDaoImpl implements AiAssistantDao {
@Override
public List<AiAssistant> findList(AiAssistantRequestDto dto) {
AiAssistantExample aiAssistantExample = new AiAssistantExample();
//排除默认机器人
aiAssistantExample.createCriteria().andTypeNotEqualTo(0);
PageHelper.startPage(dto.getPage(), dto.getLimit());
return aiAssistantMapper.selectByExample(aiAssistantExample);
}
......@@ -31,4 +33,12 @@ public class AiAssistantDaoImpl implements AiAssistantDao {
aiAssistantExample.createCriteria().andCodeEqualTo(code);
return aiAssistantMapper.selectOneByExample(aiAssistantExample);
}
@Override
public AiAssistant findByType(Integer type) {
AiAssistantExample aiAssistantExample = new AiAssistantExample();
aiAssistantExample.createCriteria().andTypeEqualTo(type);
return aiAssistantMapper.selectOneByExample(aiAssistantExample);
}
}
......@@ -72,7 +72,7 @@
<javaClientGenerator type="XMLMAPPER" targetPackage="com.wwdz.ch.db.mapper"
targetProject="ch-dao/src/main/java"/>
<table tableName="category_temp" enableCountByExample="true" enableUpdateByExample="true" enableDeleteByExample="true" enableSelectByExample="true" selectByExampleQueryId="true">
<table tableName="ai_assistant" enableCountByExample="true" enableUpdateByExample="true" enableDeleteByExample="true" enableSelectByExample="true" selectByExampleQueryId="true">
<generatedKey column="id" sqlStatement="Mysql" identity="true" />
</table>
......
......@@ -18,6 +18,7 @@ import com.xxdxxs.utils.EntityMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
......@@ -41,6 +42,8 @@ public class AiAssistantServiceImpl implements AiAssistantService {
@Autowired
IMUtil imUtil;
@Value("${dts.im.default-ai-code}")
private String DEFAULT_AI_CODE;
@Override
public Result findList(AiAssistantRequestDto dto) {
......
package com.wwdz.ch.wx.impl;
import com.wwdz.ch.core.type.Result;
import com.wwdz.ch.core.util.RedisUtils;
import com.wwdz.ch.db.dao.AiAssistantDao;
import com.wwdz.ch.db.dao.AiDefaultQuestionDao;
import com.wwdz.ch.db.domain.AiAssistant;
import com.wwdz.ch.db.domain.AiDefaultQuestion;
import com.wwdz.ch.db.dto.request.AiDefaultQuestionRequestDto;
import com.wwdz.ch.wx.service.AiAssistantService;
import com.wwdz.ch.wx.service.AiDefaultQuestionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* ai助手默认问题
......@@ -20,15 +27,35 @@ public class AiDefaultQuestionServiceImpl implements AiDefaultQuestionService {
private static final Logger logger = LoggerFactory.getLogger(AiDefaultQuestionServiceImpl.class);
private static final String AI_DEFAULT_QUESTION_KEY_PREFIX = "AI-DEFAULT-QUESTION:";
@Autowired
AiDefaultQuestionDao aiDefaultQuestionDao;
@Autowired
RedisUtils redisUtils;
@Autowired
AiAssistantDao aiAssistantDao;
@Override
public Result findList(AiDefaultQuestionRequestDto dto) {
try {
String key = AI_DEFAULT_QUESTION_KEY_PREFIX + dto.getUserId();
if (redisUtils.hasKey(key) && dto.getIsChangeList() == 0){
return Result.success();
}
List<AiDefaultQuestion> aiDefaultQuestionList = aiDefaultQuestionDao.findList(dto);
return Result.success(aiDefaultQuestionList);
Map<String, Object> map = new HashMap<>();
map.put("data", aiDefaultQuestionList);
//查询ai机器人简介
AiAssistant aiAssistant = aiAssistantDao.findByType(dto.getType());
map.put("profile", aiAssistant.getProfile());
//一小时内打开会话不重复返回默认问题
redisUtils.set(key, null, 1, TimeUnit.HOURS);
return Result.success(map);
} catch (Exception e) {
logger.error("查询ai默认问题列表error : {}", e);
}
......
......@@ -7,6 +7,7 @@ import com.wwdz.ch.core.im.api.ConversationApi;
import com.wwdz.ch.core.im.api.TLSSigApi;
import com.wwdz.ch.core.type.Result;
import com.wwdz.ch.core.util.IMUtil;
import com.wwdz.ch.core.util.RedisUtils;
import com.wwdz.ch.db.dao.AiAssistantDao;
import com.wwdz.ch.db.domain.AiAssistant;
import com.wwdz.ch.wx.api.ChatApi;
......@@ -18,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* 会话
......@@ -42,6 +44,9 @@ public class IMServiceImpl implements IMService {
@Autowired
ChatApi chatApi;
@Autowired
RedisUtils redisUtils;
/**
* 新增ai会话,发送默认打招呼的消息
* @param dto
......@@ -119,6 +124,11 @@ public class IMServiceImpl implements IMService {
answerDto.setToAccount(dto.getFromAccount());
answerDto.setMsgType(IMEnum.MsgTypeEnum.TIMTextElem.getCode());
answerDto.setMsgContent(answer);
//判断该AI回答是否已被停止
if (redisUtils.hasKey(dto.getReqId())){
return Result.success("回答已被终止");
}
Result answerResult = conversationApi.sendChatMsg(answerDto);
if (!answerResult.getSuccess()) {
logger.info("=============== 发送问题的ai答复消息失败 =============");
......@@ -127,10 +137,17 @@ public class IMServiceImpl implements IMService {
} else {
return Result.failed("目前尚不支持除文本外的消息发送");
}
logger.info("=============== AI的回答信息发送成功 ===============");
return Result.success();
} catch (Exception e) {
logger.error("发送聊天消息失败:{}", e);
}
return Result.failed();
}
@Override
public Result stopAiAnswer(SendChatMsgRequestDto dto) {
redisUtils.set(dto.getReqId(), false, 10, TimeUnit.SECONDS);
return Result.success();
}
}
......@@ -2,6 +2,7 @@ package com.wwdz.ch.wx.impl;
import com.alibaba.fastjson.JSONObject;
import com.wwdz.ch.core.consts.ResultCode;
import com.wwdz.ch.core.im.api.ChatUserApi;
import com.wwdz.ch.core.notify.AliSmsSender;
import com.wwdz.ch.core.notify.NotifyService;
import com.wwdz.ch.core.notify.SmsResult;
......@@ -55,7 +56,8 @@ public class UserServiceImpl implements UserService {
private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
//默认的ai机器人编码,用于ai助手的聊天,该机器人永远在会话列表中置顶
private static final String DEFAULT_AI_CODE = "ai10000";
@Value("${dts.im.default-ai-code}")
private String DEFAULT_AI_CODE;
@Autowired
private UserDao userDao;
......@@ -63,32 +65,42 @@ public class UserServiceImpl implements UserService {
private UserTokenManager userTokenManager;
@Autowired
private NotifyService notifyService;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private WxLoginManager wxLoginManager;
@Autowired
private AlipayLoginManager alipayLoginManager;
@Autowired
private TikTokLoginManager tikTokLoginManager;
@Autowired
private RedisUtil redisUtil;
@Value("${avatar-url}")
private String avatarUrl;
@Autowired
private AliSmsSender aliSmsSender;
@Autowired
private InviteRecordService inviteRecordService;
@Autowired
private SwitchService switchService;
@Autowired
private ItemCommonService itemCommonService;
@Autowired
private FollowFansRecordService followFansRecordService;
@Autowired
ChatUserApi chatUserApi;
@Override
......@@ -508,6 +520,12 @@ public class UserServiceImpl implements UserService {
user.setLastLoginIp(IpUtil.client(request));
user.setShareUserId(0L);
userDao.insert(user);
//把新增用户同步到IM
Result synUserResult = chatUserApi.importUser(user);
if (synUserResult.getSuccess()) {
logger.info("新增用户同步至IM成功");
}
} else {
// 注册过的用户修改最后登录的时间以及绑定微信openid和支付宝user_id
if (org.springframework.util.StringUtils.hasLength(dto.getWxOpenId())) {
......
......@@ -43,4 +43,10 @@ public interface IMService {
* @return
*/
Result sendAiChatMsg(SendChatMsgRequestDto dto);
/**
* 停止AI回答
*/
Result stopAiAnswer(SendChatMsgRequestDto dto);
}
......@@ -87,6 +87,17 @@ public class IMController {
}
return imService.sendAiChatMsg(dto);
}
@ApiOperation(value = "停止ai回答")
@PostMapping("/stopAiAnswer")
public Result stopAiAnswer(@RequestBody SendChatMsgRequestDto dto) {
logger.info("【请求开始】停止ai回答,请求参数:{}", JSON.toJSONString(dto));
if (StringUtils.isEmpty(dto.getReqId())) {
return Result.failed("reqId不能为空");
}
return imService.stopAiAnswer(dto);
}
}
......@@ -90,7 +90,7 @@ public class ChatApiTest {
public void sendChatMsg() {
SendChatMsgRequestDto sendChatMsgRequestDto = new SendChatMsgRequestDto();
sendChatMsgRequestDto.setToAccount("241");
sendChatMsgRequestDto.setFromAccount("ai10000");
sendChatMsgRequestDto.setFromAccount("273");
sendChatMsgRequestDto.setMsgType(IMEnum.MsgTypeEnum.TIMTextElem.getCode());
long timestamp = System.currentTimeMillis();
String msgContent = timestamp + " >> ai测试消息的数据, 是否可以接收到";
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment