服务端配置
服务端配置
通过配置服务端和客户端,利用环信即时通信 IM 服务器回调功能,在 IM 中引入 AI 服务(以 MiniMax 中文大语言模型为例),创建机器人账号,从而跑通示例项目。本文介绍通过跑通示例项目如何配置服务端。
此外,利用 AI 聊天功能,你可以设置问候语,让机器人用户每天定时主动向聊天用户发送问候语,实现详情请参见 FAQ。
若要体验 Demo,你可以扫描以下二维码:
环境准备
部署要求:Windows 或者 Linux 服务器
环境要求
- JDK 1.8+
- Redis 3.0.504
- Redis 绑定地址更改为 127.0.0.1
- MySQL 8.0.30
代码下载
当部署环境准备好后,通过 GitHub 链接下载服务端代码。
信息配置
服务端配置信息全部集中在以下文件中,主要配置包含三个部分:环信即时通讯 IM、miniMax 和 redis,配置内容如下:
src/main/resources/application.yml
环信即时通讯 IM 相关配置
1. 创建应用
登录环信即时通讯云控制台,点击添加应用,填写应用相关信息。
2. 获取 app 信息
选中创建的应用,点击管理,进入应用详情页面,获取 App Key、ClientID 及ClientSecret。
logging:
level:
com.easemob.im.http: debug #启动之后可打印的日志级别
server:
port: 80 #修改启动端口,只能为数字(请确保该端口没有被占用)
easemob:
appkey: {appkey} # 创建应用获取到的 App Key,可通过环信即时通讯云控制台的 “应用详情” 页面上的 “APPKEY” 字段获取。
clientId:{clientId} # App 的 client_id,可通过环信即时通讯云控制台的 “应用详情” 页面上的 “Client ID” 字段获取。
clientSecret:{clientSecret} # App 的 client_secret,可通过环信即时通讯云控制台的 “应用详情” 页面上的 “ClientSecret” 字段获取。
3. 关闭好友关系检查
设置用户注册模式为开放注册,关闭好友关系检查。
4. 创建机器人账号
选择应用概览 > 用户认证 创建机器人账号,进行单聊或群组聊天。
示例项目中创建了 3 个智能体,因此建议设置 3 个机器人账号与智能体一 一绑定,即 com.easemob.chattyai.chat.util.BotSettingUtil
中的 botBean0.setAccount
(机器人用户 ID)与 botBean0.setName
(智能体名称)为一 一对应关系,见下方代码。
下图红框中的用户 ID(bot1222700215765565440
、bot1223027765968633856
和 bot1223027786982096896
)为示例项目中的与智能体绑定的机器人账号,若使用其他用户 ID,则需同步修改 BotSettingUtil
的 botBean0.setAccount
中的值,否则无法跑通示例项目。
static{
BotBean botBean0 = new BotBean();
botBean0.setAccount("boy0");
botBean0.setName("智能体名称");
botBean0.setGender(0);
botBean0.setContent("智能体介绍" +
");
botBean0.setDesc("智能体相关信息,例如特征等。");
bots.put("boy0",botBean0);
}
5. 配置发送前回调规则
若使用消息发送前回调功能,你需要在环信即时通讯云控制台开通该功能,详见回调配置相关文档。该功能为增值服务,费用详见功能费用文档。
回调功能开通后,选择即时通讯 > 功能配置 > 消息回调,点击添加回调地址,配置发送前回调规则。其中,会话类型选择单聊和群聊,消息类型选择文本,启用状态选择启用,回调地址需确保设置为环信即时通讯 IM 可以通过外网访问到回调地址,格式为 http(s)://ip:端口/chatty/callback.json
。其他参数的含义详见配置回调规则相关文档。
大语言模型(LLM)信息配置
本代码示例以 MiniMax 为例 MiniMax 开放平台快速开始,若使用其他大语言模型,可按其他语言模型配置要求进行调整。
miniMax:
groupId:{groupId} # MiniMax 基础信息的 groupID。选择 “MiniMax账号管理” > “账户信息”页面,获取 “groupID” 字段。
appkey: {appkey} # MiniMax 的接口密钥。当需要复制 API 密钥时,可以重新创建一个以完成复制操作。
url: https://api.minimax.chat/v1/text/chatcompletion_pro?GroupId=
MySQL 配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
url: xxxx
username: xxxx
password: xxxx
initial-size: 10
max-active: 100
min-idle: 10
max-wait: 60000
pool-prepared-statements: true
redis 配置
redis 安装完成以后,设置上 redis 的密码(也可以设置为空),确保 "host:port" 链接可以访问 redis 即可。
redis:
host: {host} #redis 地址
port: {port} #redis 端口
password: {password} #redis 密码
# 连接超时时间(毫秒)
timeout: 30000
# 连接池中的最大空闲连接
max-idle: 8
# 连接池中的最小空闲连接
min-idle: 10
# 连接池最大连接数(使用负值表示没有限制)
max-active: 100
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
数据库初始化
导入下方脚本:
/*
SQLyog 企业版 - MySQL GUI v8.14
MySQL - 8.3.0 : Database - chattyai
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`chattyai` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
USE `chattyai`;
/*Table structure for table `chat_bot` */
DROP TABLE IF EXISTS `chat_bot`;
CREATE TABLE `chat_bot` (
`id` bigint NOT NULL AUTO_INCREMENT,
`bot_name` varchar(50) DEFAULT NULL COMMENT '名称',
`describe` varchar(2000) DEFAULT NULL COMMENT '描述',
`pic` varchar(50) DEFAULT NULL COMMENT '头像地址',
`open` tinyint NOT NULL DEFAULT '1' COMMENT '是否公开',
`ea_account` varchar(50) DEFAULT NULL COMMENT '环信账号',
`create_account` varchar(50) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='聊天机器人';
/*Data for the table `chat_bot` */
insert into `chat_bot` (`id`, `bot_name`, `describe`, `pic`, `open`, `ea_account`, `create_account`, `create_time`) values('1','智能助手','理解人类语言、生成内容,是生活和工作的智能助手。','1','1','bot1222700215765565440','default','2024-03-28 00:14:08');
insert into `chat_bot` (`id`, `bot_name`, `describe`, `pic`, `open`, `ea_account`, `create_account`, `create_time`) values('2','编程助手','一个经验丰富的程序员开发助手,擅长 web 前端、springboot 后端和 Android 开发','2','1','bot1223027765968633856','default','2024-03-28 00:14:07');
insert into `chat_bot` (`id`, `bot_name`, `describe`, `pic`, `open`, `ea_account`, `create_account`, `create_time`) values('3','法律顾问','你精通各个领域的法律知识,能够提供专业且贴心的法律咨询服务','3','1','bot1223027786982096896','default','2024-03-28 00:14:06');
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
启动说明
host
填写为127.0.0.1
。port
填写为 redis 所占用的端口。password
填写 redis 的密码(如果没有密码,使用#
注释该配置)。
- 使用
mvn install
将项目打包为jar
。
- 找到对应位置的
jar
包,上传到服务器。
使用命令启动即可:
nohup java -jar $APP_DIR/chattyai-0.0.1-SNAPSHOT.jar --server.port=$PORT >> ./chattyai.log 2>&1 &
$APP_DIR
替换为上传 jar 包存在的根路径。$PORT
替换为需要占用的端口。
- 查看启动日志。
tail -f $APP_DIR/chattyai.log
FAQ
- Q: 项目为何启动失败?
A: 确保 JDK 配置正确,端口没有被占用,redis 能被访问到。
- Q: 项目启动后为何无法访问?
A: 检查以下两方面:
- 配置 nginx 的情况下,请确保 nginx 配置正确。
- 未配置 nginx 的情况下,请确保端口对外开放。
- Q: MiniMax 的调用失败,无返回结果,是什么原因?
A: 请确保 MiniMax 有余额,否则可能导致调用 MiniMax 的调用失败。
- Q: 如何实现问候语?
A: 你可以设置问候语,让机器人用户每天定时主动向聊天用户发送问候语。
com.easemob.chattyai.chat.util.GreetUtil
类中存在一个静态代码块和以下三个镜头属性。
静态代码用于加载该类时,分别向这三个 List 中添加对应的问候语。
/**
* 早上问候语 list
*/
public static List<String> moringGreetList = new ArrayList<>();
/**
* 中午问候语 list
*/
public static List<String> noonGreetList = new ArrayList<>();
/**
* 晚上问候语 list
*/
public static List<String> eveningGreetList = new ArrayList<>();
设置问候语后,可在 com.easemob.chattyai.task.GreetTask
类中设置定时任务。定时任务触发的 Cron 如下所示。例如,若用户 A 与机器人用户 B 聊过天,机器人用户 B 会在每天早上 9 点、中午 12 点和晚上 21 点给用户发送消息。
0 0 9,12,21 * * ?
- Q: 如何获取历史消息?
A: 下图中的 MiniMaxAiSingleHandler
为单聊的 MinMax 处理类,MiniMaxAiGroupHandler
为群聊的 MinMax 的处理类。
在本示例项目中,与智能体交互后,聊天记录会同步处理到 从 redis 获取的 key (Constant.CHAT_GROUP_HISTORY_REDIS_KEY_PREFIX+发送人的环信用户ID+:+机器人的环信 ID
)的对应的 value 中,方便下一次聊天时作为历史消息传递给 AI。示例项目中只取最近 10 条消息作为历史数据,对应的代码如下所示:
long l = redisUtil.lGetListSize(key);
if (l > 10) {
redisUtil.leftpop(key, 2L);
}