一、前言
在之前的两篇文章中,我们学习了如何构建基本的即时消息(IM)功能。今天,我们将进一步将IM模块与AI服务进行连接,实现用户提问并由模型进行回答,最后将结果展示在用户界面上。
二、术语
2.1. Spring Boot
是一个用于快速构建基于Spring框架的Java应用程序的开源框架。它简化了Spring应用程序的初始化和配置过程,使开发人员能够更专注于业务逻辑的实现。
2.2. 读超时时间(Read Timeout)
是指在进行网络通信时,接收数据的操作所允许的最长等待时间。当一个请求被发送到服务器,并且在规定的时间内没有收到服务器的响应数据,就会触发读超时错误。读超时时间用于控制客户端等待服务器响应的时间,以防止长时间的阻塞。
2.3. 写超时时间(Write Timeout)
是指在进行网络通信时,发送数据的操作所允许的最长等待时间。当一个请求被发送到服务器,但在规定的时间内无法将数据完全发送完成,就会触发写超时错误。写超时时间用于控制客户端发送数据的时间,以防止长时间的阻塞。
2.4. 连接超时时间(Connection Timeout)
是指在建立网络连接时,客户端尝试连接到服务器所允许的最长等待时间。当一个客户端尝试连接到服务器时,如果在规定的时间内无法建立连接,就会触发连接超时错误。连接超时时间用于控制客户端与服务器建立连接的时间,以防止长时间的等待。
三、前置条件
3.1. 调通最基本的WebSocket流程(参见开源模型应用落地-业务整合篇(二))
3.2. 已经部署至少单节点的AI服务
四、技术实现
# 打通IM和AI服务之间的通道
4.1. 新增AI服务调用的公共类
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Objects;@Slf4j
@Component
public class AIChatUtils {@Autowiredprivate AIConfig aiConfig;private Request buildRequest(Long userId, String prompt) throws Exception {//创建一个请求体对象(body)MediaType mediaType = MediaType.parse("application/json");RequestBody requestBody = RequestBody.create(mediaType, prompt);return buildHeader(userId, new Request.Builder().post(requestBody)).url(aiConfig.getUrl()).build();}private Request.Builder buildHeader(Long userId, Request.Builder builder) throws Exception {return builder.addHeader("Content-Type", "application/json").addHeader("userId", String.valueOf(userId)).addHeader("secret",generateSecret(userId))}/*** 生成请求密钥** @param userId 用户ID* @return*/private String generateSecret(Long userId) throws Exception {String key = aiConfig.getServerKey();String content = key + userId + key;MessageDigest digest = MessageDigest.getInstance("SHA-256");byte[] hash = digest.digest(content.getBytes(StandardCharsets.UTF_8));StringBuilder hexString = new StringBuilder();for (byte b : hash) {String hex = Integer.toHexString(0xff & b);if (hex.length() == 1) {hexString.append('0');}hexString.append(hex);}return hexString.toString();}public String chatStream(ApiReqMessage apiReqMessage) throws Exception {//定义请求的参数String prompt = JSON.toJSONString(AIChatReqVO.init(apiReqMessage.getContents(), apiReqMessage.getHistory()));log.info("【AIChatUtils】调用AI聊天,用户({}),prompt:{}", apiReqMessage.getUserId(), prompt);//创建一个请求对象Request request = buildRequest(apiReqMessage.getUserId(), prompt);InputStream is = null;try {// 从线程池获取http请求并执行Response response =OkHttpUtils.getInstance(aiConfig).getOkHttpClient().newCall(request).execute();// 响应结果StringBuffer resultBuff = new StringBuffer();//正常返回if (response.code() == 200) {//打印返回的字符数据is = response.body().byteStream();byte[]