Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
pengjinning committed Sep 11, 2024
1 parent 73f031f commit 6eea325
Show file tree
Hide file tree
Showing 971 changed files with 8,606 additions and 16,896 deletions.
Binary file modified modules/.DS_Store
Binary file not shown.
Binary file modified modules/ai/.DS_Store
Binary file not shown.
8 changes: 0 additions & 8 deletions modules/ai/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,6 @@
<version>release-V4-2.3.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.25.2</version>
<scope>provided</scope>
</dependency>

<!-- ///////////////////////////////////////////////////////////////////////////// -->
<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @Author: jackning [email protected]
* @Date: 2024-08-19 21:16:26
* @LastEditors: jackning [email protected]
* @LastEditTime: 2024-08-28 09:29:01
* @LastEditTime: 2024-08-28 09:29:23
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
Expand Down
22 changes: 11 additions & 11 deletions modules/ai/src/main/java/com/bytedesk/ai/robot/Robot.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @Author: jackning [email protected]
* @Date: 2024-03-22 16:16:26
* @LastEditors: jackning [email protected]
* @LastEditTime: 2024-08-26 06:10:25
* @LastEditTime: 2024-08-30 08:34:31
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
Expand All @@ -14,15 +14,10 @@
*/
package com.bytedesk.ai.robot;

import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;

import com.bytedesk.ai.settings.RobotServiceSettings;
import com.bytedesk.core.base.BaseEntity;
import com.bytedesk.core.constant.AvatarConsts;
import com.bytedesk.core.constant.BdConstants;
import com.bytedesk.core.constant.I18Consts;
import com.bytedesk.core.constant.TypeConsts;
import com.bytedesk.core.enums.LevelEnum;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
Expand Down Expand Up @@ -53,7 +48,8 @@ public class Robot extends BaseEntity {

private static final long serialVersionUID = 1L;

private String nickname;
@Builder.Default
private String nickname = I18Consts.I18N_ROBOT_NICKNAME;

@Builder.Default
private String avatar = AvatarConsts.DEFAULT_AVATAR_URL;
Expand All @@ -69,6 +65,10 @@ public class Robot extends BaseEntity {
@Builder.Default
private RobotLlm llm = new RobotLlm();

@Embedded
@Builder.Default
private RobotFlow flow = new RobotFlow();

// 如果未匹配到关键词,默认回复内容
@Builder.Default
private String defaultReply = I18Consts.I18N_ROBOT_REPLY;
Expand All @@ -86,10 +86,10 @@ public class Robot extends BaseEntity {
// private LevelEnum level = LevelEnum.ORGNIZATION;
private String level = LevelEnum.ORGNIZATION.name();

@Builder.Default
@Column(columnDefinition = TypeConsts.COLUMN_TYPE_JSON)
@JdbcTypeCode(SqlTypes.JSON)
private String flow = BdConstants.EMPTY_JSON_STRING;
// @Builder.Default
// @Column(columnDefinition = TypeConsts.COLUMN_TYPE_JSON)
// @JdbcTypeCode(SqlTypes.JSON)
// private String flow = BdConstants.EMPTY_JSON_STRING;

@Builder.Default
private boolean published = false;
Expand Down
187 changes: 103 additions & 84 deletions modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEventListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @Author: jackning [email protected]
* @Date: 2024-06-12 07:17:13
* @LastEditors: jackning [email protected]
* @LastEditTime: 2024-08-19 16:51:10
* @LastEditTime: 2024-09-07 18:49:09
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
Expand All @@ -15,9 +15,7 @@
package com.bytedesk.ai.robot;

import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import org.springframework.context.event.EventListener;
Expand All @@ -30,19 +28,22 @@
import com.alibaba.fastjson2.JSONObject;
import com.bytedesk.ai.utils.ConvertAiUtils;
import com.bytedesk.ai.zhipuai.ZhipuaiService;
import com.bytedesk.core.config.BytedeskEventPublisher;
import com.bytedesk.core.config.BytedeskProperties;
import com.bytedesk.core.constant.BdConstants;
import com.bytedesk.core.constant.I18Consts;
import com.bytedesk.core.enums.ClientEnum;
import com.bytedesk.core.message.MessageCache;
import com.bytedesk.core.message.MessageExtra;
import com.bytedesk.core.message.MessageJsonEvent;
import com.bytedesk.core.message.MessageProtoEvent;
import com.bytedesk.core.message.MessageProtobuf;
import com.bytedesk.core.message.MessageStatusEnum;
import com.bytedesk.core.message.MessageTypeEnum;
import com.bytedesk.core.message.MessageUtils;
import com.bytedesk.core.rbac.organization.Organization;
import com.bytedesk.core.rbac.organization.OrganizationCreateEvent;
import com.bytedesk.core.rbac.user.UserProtobuf;
import com.bytedesk.core.rbac.user.UserTypeEnum;
import com.bytedesk.core.redis.pubsub.RedisPubsubService;
import com.bytedesk.core.socket.protobuf.model.MessageProto;
import com.bytedesk.core.thread.ThreadCreateEvent;
import com.bytedesk.core.thread.ThreadProtobuf;
Expand All @@ -65,41 +66,57 @@ public class RobotEventListener {

private final ZhipuaiService zhipuaiService;

private final BytedeskEventPublisher bytedeskEventPublisher;
// private final BytedeskEventPublisher bytedeskEventPublisher;

private final UidUtils uidUtils;

private final ThreadService threadService;

private final RedisPubsubService redisPubsubService;

private final BytedeskProperties bytedeskProperties;

private final MessageCache messageCache;

@Order(5)
@EventListener
public void onOrganizationCreateEvent(OrganizationCreateEvent event) {
Organization organization = (Organization) event.getSource();
// User user = organization.getUser();
String orgUid = organization.getUid();
log.info("robot - organization created: {}", organization.getName());
//
List<String> faqUids = Arrays.asList(
orgUid + I18Consts.I18N_FAQ_DEMO_TITLE_1,
orgUid + I18Consts.I18N_FAQ_DEMO_TITLE_2);
//
// List<String> quickButtonUids = Arrays.asList(
// orgUid + I18Consts.I18N_QUICK_BUTTON_DEMO_TITLE_1,
// orgUid + I18Consts.I18N_QUICK_BUTTON_DEMO_TITLE_2);
//
RobotRequest robotRequest = RobotRequest.builder()
.nickname(I18Consts.I18N_ROBOT_NICKNAME)
.description(I18Consts.I18N_ROBOT_DESCRIPTION)
// .kb(kb)
// .llm(llm)
.build();
robotRequest.setType(RobotTypeEnum.SERVICE.name());
robotRequest.setOrgUid(orgUid);
//
robotRequest.getServiceSettings().setFaqUids(faqUids);
robotRequest.getServiceSettings().setQuickFaqUids(faqUids);
robotService.createDefaultRobot(orgUid, uidUtils.getCacheSerialUid());
robotService.createDefaultAgentAsistantRobot(orgUid);
}

//
@EventListener
public void onThreadCreateEvent(ThreadCreateEvent event) {
Thread thread = event.getThread();
log.info("robot ThreadCreateEvent: {}", thread.getUid());
//
robotService.create(robotRequest);
if (thread.getType().equals(ThreadTypeEnum.ROBOT.name())
&& thread.getAgent().equals(BdConstants.EMPTY_JSON_STRING)) {
// 机器人会话:org/robot/{robot_uid}/{visitor_uid}
String topic = thread.getTopic();
//
String[] splits = topic.split("/");
if (splits.length < 4) {
throw new RuntimeException("robot topic format error");
}
String robotUid = splits[2];
Optional<Robot> robotOptional = robotService.findByUid(robotUid);
if (robotOptional.isPresent()) {
Robot robot = robotOptional.get();
// 更新机器人配置+大模型相关信息
thread.setExtra(JSON.toJSONString(ConvertAiUtils.convertToServiceSettingsResponseVisitor(
robot.getServiceSettings())));
thread.setAgent(JSON.toJSONString(ConvertAiUtils.convertToRobotProtobuf(robot)));
//
threadService.save(thread);
}
}

}

@EventListener
Expand Down Expand Up @@ -132,24 +149,27 @@ public void onMessageProtoEvent(MessageProtoEvent event) {
private void processMessage(String messageJson) {
MessageProtobuf messageProtobuf = JSON.parseObject(messageJson, MessageProtobuf.class);
MessageTypeEnum messageType = messageProtobuf.getType();
if (messageType.equals(MessageTypeEnum.STREAM)) {
// ai回答暂不处理
return;
}
String query = messageProtobuf.getContent();
log.info("robot processMessage {}", query);
//
ThreadProtobuf thread = messageProtobuf.getThread();
if (thread == null) {
ThreadProtobuf threadProtobuf = messageProtobuf.getThread();
if (threadProtobuf == null) {
throw new RuntimeException("thread is null");
}
// 仅针对文本类型自动回复
if (!messageType.equals(MessageTypeEnum.TEXT)) {
return;
}
//
String threadTopic = thread.getTopic();
log.info("robot threadTopic {}, thread.type {}", threadTopic, thread.getType());
if (thread.getType().equals(ThreadTypeEnum.ROBOT)) {
String threadTopic = threadProtobuf.getTopic();
if (threadProtobuf.getType().equals(ThreadTypeEnum.ROBOT)) {
log.info("robot threadTopic {}, thread.type {}", threadTopic, threadProtobuf.getType());
// 机器人回复
log.info("robot thread reply");
// 机器人客服消息 org/robot/default_robot_uid/1420995827073219
// 机器人客服消息 org/robot/df_robot_uid/1420995827073219
String[] splits = threadTopic.split("/");
if (splits.length < 4) {
throw new RuntimeException("robot topic format error");
Expand All @@ -167,64 +187,63 @@ private void processMessage(String messageJson) {
user.setNickname(robot.getNickname());
user.setAvatar(robot.getAvatar());
//
MessageExtra extra = MessageExtra.builder()
// .isAutoReply(true)
// .autoReplyType(autoReplySettings.getAutoReplyType().name())
.orgUid(robot.getOrgUid())
.build();
//
MessageProtobuf message = MessageProtobuf.builder()
.uid(uidUtils.getCacheSerialUid())
.status(MessageStatusEnum.SUCCESS)
.thread(thread)
.user(user)
.client(ClientEnum.SYSTEM_AUTO)
.extra(JSONObject.toJSONString(extra))
.createdAt(new Date())
.build();
// 返回一个输入中消息,让访客端显示输入中
MessageProtobuf clonedMessage = SerializationUtils.clone(message);
clonedMessage.setUid(uidUtils.getCacheSerialUid());
clonedMessage.setType(MessageTypeEnum.PROCESSING);
String json = JSON.toJSONString(clonedMessage);
bytedeskEventPublisher.publishMessageJsonEvent(json);
// 绑定知识库
zhipuaiService.sendWsRobotMessage(query, robot.getKbUid(), robot, message);
sendRobotReply(threadProtobuf, user, query, robot);
} else {
log.error("robot not found");
}
} else if (threadProtobuf.getType().equals(ThreadTypeEnum.AGENT)
|| threadProtobuf.getType().equals(ThreadTypeEnum.WORKGROUP)) {
log.info("robot threadTopic {}, thread.type {}", threadTopic, threadProtobuf.getType());
Thread thread = threadService.findByTopic(threadTopic)
.orElseThrow(() -> new RuntimeException("thread with topic " + threadTopic + " not found"));
UserProtobuf agent = JSON.parseObject(thread.getAgent(), UserProtobuf.class);
// 当前会话为机器人接待,而且是访客发送的消息
if (agent.getType().equals(UserTypeEnum.ROBOT.name())
&& messageProtobuf.getUser().getType().equals(UserTypeEnum.VISITOR.name())) {
// 机器人回复
log.info("robot thread reply");
Robot robot = robotService.findByUid(agent.getUid())
.orElseThrow(() -> new RuntimeException("robot " + agent.getUid() + " not found"));
//
sendRobotReply(threadProtobuf, agent, query, robot);
}
}

}


//
@EventListener
public void onThreadCreateEvent(ThreadCreateEvent event) {
Thread thread = event.getThread();
log.info("robot ThreadCreateEvent: {}", thread.getUid());
private void sendRobotReply(ThreadProtobuf threadProtobuf, UserProtobuf user, String query, Robot robot) {
//
if (thread.getType().equals(ThreadTypeEnum.ROBOT)
&& thread.getAgent().equals(BdConstants.EMPTY_JSON_STRING)) {
// 机器人会话:org/robot/{robot_uid}/{visitor_uid}
String topic = thread.getTopic();
//
String[] splits = topic.split("/");
if (splits.length < 4) {
throw new RuntimeException("robot topic format error");
}
String robotUid = splits[2];
Optional<Robot> robotOptional = robotService.findByUid(robotUid);
if (robotOptional.isPresent()) {
Robot robot = robotOptional.get();
// 更新机器人配置+大模型相关信息
thread.setExtra(JSON.toJSONString(ConvertAiUtils.convertToServiceSettingsResponseVisitor(
robot.getServiceSettings())));
thread.setAgent(JSON.toJSONString(ConvertAiUtils.convertToRobotProtobuf(robot)));
//
threadService.save(thread);
}
}
String threadTopic = threadProtobuf.getTopic();
MessageExtra extra = MessageUtils.getMessageExtra(robot.getOrgUid());
//
String messageUid = uidUtils.getCacheSerialUid();
MessageProtobuf message = MessageProtobuf.builder()
.uid(messageUid)
.status(MessageStatusEnum.SUCCESS)
.thread(threadProtobuf)
.user(user)
.client(ClientEnum.SYSTEM_AUTO)
.extra(JSONObject.toJSONString(extra))
.createdAt(new Date())
.build();

// 返回一个输入中消息,让访客端显示输入中
MessageProtobuf clonedMessage = SerializationUtils.clone(message);
clonedMessage.setUid(uidUtils.getCacheSerialUid());
clonedMessage.setType(MessageTypeEnum.PROCESSING);
//
MessageUtils.notifyUser(clonedMessage);
// 知识库
if (bytedeskProperties.getJavaai()) {
zhipuaiService.sendWsRobotMessage(query, robot.getKbUid(), robot, message);
}
// 通知python ai模块处理回答
if (bytedeskProperties.getPythonai()) {
messageCache.put(messageUid, message);
redisPubsubService.sendQuestionMessage(messageUid, threadTopic, robot.getKbUid(),
query);
}
}


}
Loading

0 comments on commit 6eea325

Please sign in to comment.