前置:
1.部署Dify,见官方教程及介绍欢迎使用 Dify | Dify,本文主要讲基于部署完之后的java实现的调用它的接口实现AI智能聊天,其他AI功能后续有用到再补充,没有就看缘分
2.什么是Dify?可以简单理解为集成了各类AI大模型的一个中转平台,你的服务请求它的接口,再通过在Dify上配置好的应用尽情请求获取到回复内容
3.用到了Dify,但其他相关的提供大模型平台的用法可能都差不多,可做参考
4.用到springboot/java
AI机器人创建
1.先在Dify上创建一个聊天应用
选择聊天助手
创建完毕
获取请求地址跟API密钥,写入配置文件
开始开发
1.pom文件新增依赖
<dependency> <groupId>com.squareup.retrofit2</groupId> <artifactId>retrofit</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.squareup.retrofit2</groupId> <artifactId>converter-jackson</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.squareup.retrofit2</groupId> <artifactId>adapter-rxjava2</artifactId> <version>2.9.0</version> </dependency>
2.yml配置文件
dify:
#复制的apiKey,以下为假数据
apiKey: 'app-ugR39FF8DDDAOaY4yBZDq4ba'
#apiHost: 'http://localhost/v1/' 记得需要/结尾
apiHost: 'http://api-test.xxxxxx.cn/v1/'
流式请求与阻塞式请求
区别:简单来说流式就是一个字一个字给我们返回打印出来,代码实现相对复杂,阻塞式则是等机器人把问题想清楚了,全部内容返回给我们,先对来说实现比较容易,但是反应可能没那么快,具体需要看业务需要
流式请求实现
3.控制层
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
@RequiredArgsConstructor
@RestController
@Slf4j
@RequestMapping("/ai")
public class PsyAiChatController {
//流式模式
private final static String STREAMING_MODE = "streaming";
//阻塞模式
private final static String BLOCKING_MODE = "blocking";
@Resource
private IPsyAiChatService difyChatService;
/**
* AI陪聊
* @param bo
* @param response
* @return
*/
@PostMapping("/chat")
@ResponseBody
public ResponseBodyEmitter chatSeeMessage(@RequestBody @Valid AiChatBo bo, HttpServletResponse response) {
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
DifyRequest difyRequest = new DifyRequest();
difyRequest.setResponseMode(STREAMING_MODE);
difyRequest.setQuery(bo.getQuery());
difyRequest.setUser(bo.getUserId().toString());
if(StringUtils.isNotEmpty(bo.getConversationId())){
difyRequest.setConversationId(bo.getConversationId());
}
return difyChatService.sseChatPrompt(difyRequest);
}
}
4.前端请求实体
@Data
public class AiChatBo implements Serializable {
/**
* 用户id
*/
private Long userId;
/**
* 聊天内容
*/
private String query;
/**
* (选填)会话id,若基于之前的聊天记录继续对话,必传之前消息的 conversation_id
*/
private String conversationId;
}
5.请求Dify请求体
package com.xmzs.common.edu.domain.dify.bo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* dify聊天请求体
* @Author: zyt
* @CreateTime: 2024-11-05
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class DifyRequest {
/**
* 输入提问内容
*/
private String query;
/**
* (选填)允许传入 App 定义的各变量值
*/
private Map<String,String> inputs;
/**
* 回复模式:streaming流式模式,blocking阻塞模式
*/
@JsonProperty("response_mode")
private String responseMode;
/**
* (选填)会话id,需要基于之前的聊天记录继续对话,必须传之前消息的 conversation_id
* */
@JsonProperty("conversation_id")
private String conversationId;
/**
* 用户标识,用于定义终端用户的身份,方便检索、统计。 由开发者定义规则,需保证用户标识在应用内唯一。
* */
private String user="";
/**
* (选填)自动生成标题,默认 false。 可通过调用会话重命名接口并设置 auto_generate 为 true 实现异步生成标题
* */
@JsonProperty("autoGenerate_name")
private boolean autoGenerateName=false;
private List<UploadFile> files;
@Data
public class UploadFile{
/**
* 支持类型:图片 image(目前仅支持图片格式)
* */
private String type="image";
/**
* remote_url: 图片地址
* local_file: 上传文件
* */
@JsonProperty("transfer_method")
private String transferMethod;
/**
*
* */
private String url;
/**
* 上传文件 ID。(仅当传递方式为 local_file 时)
* */
@JsonProperty("upload_file_id")
private String uploadFileId;
}
}
6.service
接口
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
public interface IPsyAiChatS