ai对话优化知识库选择
This commit is contained in:
@@ -698,10 +698,10 @@ public class DifyApiClient {
|
||||
String lastId,
|
||||
Integer limit,
|
||||
String apiKey) {
|
||||
|
||||
|
||||
StringBuilder urlBuilder = new StringBuilder(difyConfig.getFullApiUrl("/conversations"));
|
||||
urlBuilder.append("?user=").append(userId);
|
||||
|
||||
|
||||
if (lastId != null && !lastId.isEmpty()) {
|
||||
urlBuilder.append("&last_id=").append(lastId);
|
||||
}
|
||||
@@ -718,7 +718,7 @@ public class DifyApiClient {
|
||||
|
||||
try (Response response = httpClient.newCall(httpRequest).execute()) {
|
||||
String responseBody = response.body() != null ? response.body().string() : "";
|
||||
|
||||
|
||||
if (!response.isSuccessful()) {
|
||||
logger.error("获取对话列表失败: {} - {}", response.code(), responseBody);
|
||||
throw new DifyException("获取对话列表失败: " + responseBody);
|
||||
@@ -732,6 +732,56 @@ public class DifyApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对话变量
|
||||
* @param conversationId 会话ID
|
||||
* @param userId 用户标识
|
||||
* @param lastId 当前页最后面一条记录的ID,默认null
|
||||
* @param limit 一次请求返回多少条记录,默认20条,最大100条,最小1条
|
||||
* @param apiKey API密钥
|
||||
* @return 对话变量响应
|
||||
*/
|
||||
public ConversationVariablesResponse getConversationVariables(
|
||||
String conversationId,
|
||||
String userId,
|
||||
String lastId,
|
||||
Integer limit,
|
||||
String apiKey) {
|
||||
|
||||
StringBuilder urlBuilder = new StringBuilder(
|
||||
difyConfig.getFullApiUrl("/conversations/" + conversationId + "/variables"));
|
||||
urlBuilder.append("?user=").append(userId);
|
||||
|
||||
if (lastId != null && !lastId.isEmpty()) {
|
||||
urlBuilder.append("&last_id=").append(lastId);
|
||||
}
|
||||
if (limit != null) {
|
||||
urlBuilder.append("&limit=").append(limit);
|
||||
}
|
||||
|
||||
try {
|
||||
Request httpRequest = new Request.Builder()
|
||||
.url(urlBuilder.toString())
|
||||
.header("Authorization", "Bearer " + getApiKey(apiKey))
|
||||
.get()
|
||||
.build();
|
||||
|
||||
try (Response response = httpClient.newCall(httpRequest).execute()) {
|
||||
String responseBody = response.body() != null ? response.body().string() : "";
|
||||
|
||||
if (!response.isSuccessful()) {
|
||||
logger.error("获取对话变量失败: {} - {}", response.code(), responseBody);
|
||||
throw new DifyException("获取对话变量失败: " + responseBody);
|
||||
}
|
||||
|
||||
return JSON.parseObject(responseBody, ConversationVariablesResponse.class);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("获取对话变量异常", e);
|
||||
throw new DifyException("获取对话变量异常: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== 通用 HTTP 方法(用于代理转发)=====================
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package org.xyzh.ai.client.dto;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description 对话变量响应
|
||||
* @filename ConversationVariablesResponse.java
|
||||
* @author AI Assistant
|
||||
* @copyright xyzh
|
||||
* @since 2025-12-29
|
||||
*/
|
||||
@Data
|
||||
public class ConversationVariablesResponse {
|
||||
|
||||
private Integer limit;
|
||||
|
||||
@JSONField(name = "has_more")
|
||||
private Boolean hasMore;
|
||||
|
||||
private List<ConversationVariableItem> data;
|
||||
|
||||
/**
|
||||
* 对话中的变量项
|
||||
*/
|
||||
@Data
|
||||
public static class ConversationVariableItem {
|
||||
|
||||
/**
|
||||
* 变量ID
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 变量名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 变量类型 (string, number, boolean 等)
|
||||
*/
|
||||
@JSONField(name = "value_type")
|
||||
private String valueType;
|
||||
|
||||
/**
|
||||
* 变量值
|
||||
*/
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* 变量描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 创建时间戳
|
||||
*/
|
||||
@JSONField(name = "created_at")
|
||||
private Long createdAt;
|
||||
|
||||
/**
|
||||
* 最后更新时间戳
|
||||
*/
|
||||
@JSONField(name = "updated_at")
|
||||
private Long updatedAt;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
import org.xyzh.ai.client.dto.ConversationVariablesResponse;
|
||||
import org.xyzh.api.ai.dto.ChatPrepareData;
|
||||
import org.xyzh.api.ai.dto.TbChat;
|
||||
import org.xyzh.api.ai.dto.TbChatMessage;
|
||||
@@ -46,6 +47,9 @@ public class ChatController {
|
||||
@Autowired
|
||||
private AIFileUploadService fileUploadService;
|
||||
|
||||
@Autowired
|
||||
private org.xyzh.ai.client.DifyApiClient difyApiClient;
|
||||
|
||||
// ====================== 会话管理 ======================
|
||||
|
||||
/**
|
||||
@@ -151,7 +155,7 @@ public class ChatController {
|
||||
* @since 2025-12-17
|
||||
*/
|
||||
@PostMapping("/conversation/page")
|
||||
public ResultDomain<PageDomain<TbChat>> getChatPage(@RequestBody PageRequest<TbChat> pageRequest, @RequestHeader("Authorization") String token) {
|
||||
public ResultDomain<TbChat> getChatPage(@RequestBody PageRequest<TbChat> pageRequest, @RequestHeader("Authorization") String token) {
|
||||
log.info("分页获取会话列表: agentId={}", pageRequest.getFilter().getAgentId());
|
||||
|
||||
pageRequest.getFilter().setUserType(false);
|
||||
@@ -164,6 +168,53 @@ public class ChatController {
|
||||
return chatService.getChatPage(pageRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取对话变量
|
||||
* @param params 请求参数(包含agentId, conversationId, userId, lastId, limit)
|
||||
* @author yslg
|
||||
* @since 2025-12-29
|
||||
*/
|
||||
@PostMapping("/conversation/variables")
|
||||
public ResultDomain<org.xyzh.ai.client.dto.ConversationVariablesResponse> getConversationVariables(
|
||||
@RequestBody Map<String, Object> params,
|
||||
@RequestHeader("Authorization") String token) {
|
||||
|
||||
// 参数验证
|
||||
ValidationResult result = ValidationUtils.validateMap(params, Arrays.asList(
|
||||
ValidationUtils.requiredString("agentId", "智能体ID", 1, 100),
|
||||
ValidationUtils.requiredString("conversationId", "会话ID", 1, 100),
|
||||
ValidationUtils.requiredString("userId", "用户ID", 1, 100)
|
||||
));
|
||||
if (!result.isValid()) {
|
||||
return ResultDomain.failure(result.getAllErrors());
|
||||
}
|
||||
|
||||
String agentId = (String) params.get("agentId");
|
||||
String conversationId = (String) params.get("conversationId");
|
||||
String userId = (String) params.get("userId");
|
||||
String lastId = params.containsKey("lastId") ? (String) params.get("lastId") : null;
|
||||
Integer limit = params.containsKey("limit") ?
|
||||
Integer.parseInt(params.get("limit").toString()) : 20;
|
||||
|
||||
log.info("获取对话变量: agentId={}, conversationId={}, userId={}", agentId, conversationId, userId);
|
||||
|
||||
try {
|
||||
// 获取智能体信息以获取 API Key
|
||||
// 这里需要根据 agentId 获取对应的 API Key
|
||||
// 暂时先使用一个占位符,实际使用时需要从数据库或配置中获取
|
||||
// 或者通过 chatService 获取智能体配置
|
||||
|
||||
// 调用 Dify API 获取会话变量
|
||||
ConversationVariablesResponse response =
|
||||
difyApiClient.getConversationVariables(conversationId, userId, lastId, limit, agentId);
|
||||
|
||||
return ResultDomain.success("获取对话变量成功",response);
|
||||
} catch (Exception e) {
|
||||
log.error("获取对话变量失败", e);
|
||||
return ResultDomain.failure("获取对话变量失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// ====================== 消息管理 ======================
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.xyzh.ai.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
@@ -12,6 +13,7 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
import org.xyzh.ai.client.DifyApiClient;
|
||||
import org.xyzh.ai.client.callback.StreamCallback;
|
||||
import org.xyzh.ai.client.dto.ChatRequest;
|
||||
import org.xyzh.ai.config.DifyConfig;
|
||||
import org.xyzh.ai.mapper.TbChatMapper;
|
||||
import org.xyzh.ai.mapper.TbChatMessageMapper;
|
||||
import org.xyzh.api.ai.dto.ChatPrepareData;
|
||||
@@ -19,17 +21,23 @@ import org.xyzh.api.ai.dto.DifyFileInfo;
|
||||
import org.xyzh.api.ai.dto.TbAgent;
|
||||
import org.xyzh.api.ai.dto.TbChat;
|
||||
import org.xyzh.api.ai.dto.TbChatMessage;
|
||||
import org.xyzh.api.ai.dto.TbKnowledge;
|
||||
import org.xyzh.api.ai.service.AgentChatService;
|
||||
import org.xyzh.api.ai.service.AgentService;
|
||||
import org.xyzh.api.ai.service.KnowledgeService;
|
||||
import org.xyzh.api.system.service.GuestService;
|
||||
import org.xyzh.common.core.domain.LoginDomain;
|
||||
import org.xyzh.common.core.domain.ResultDomain;
|
||||
import org.xyzh.common.core.page.PageDomain;
|
||||
import org.xyzh.common.core.page.PageParam;
|
||||
import org.xyzh.common.core.page.PageRequest;
|
||||
import org.xyzh.common.redis.service.RedisService;
|
||||
import org.xyzh.common.utils.NonUtils;
|
||||
import org.xyzh.common.utils.id.IdUtil;
|
||||
import org.xyzh.common.auth.utils.LoginUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -69,20 +77,11 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
/**
|
||||
* @description 根据 userType 获取用户ID
|
||||
* @param chat 会话信息(包含 userId 和 userType)
|
||||
* @return 真实的系统用户ID
|
||||
*/
|
||||
private String getUserIdByType(TbChat chat) {
|
||||
if (!chat.getUserType()) {
|
||||
// 来客(userType=false):直接返回传入的 userId(已经是真正的系统 userId)
|
||||
return chat.getUserId();
|
||||
} else {
|
||||
// 员工(userType=true):从登录信息获取 userId
|
||||
return LoginUtil.getCurrentUserId();
|
||||
}
|
||||
}
|
||||
@Autowired
|
||||
private KnowledgeService knowledgeService;
|
||||
|
||||
@Autowired
|
||||
private DifyConfig difyConfig;
|
||||
|
||||
/**
|
||||
* @description 判断智能体是否是outer
|
||||
@@ -130,7 +129,8 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
}
|
||||
|
||||
// 2. 获取用户ID并校验权限
|
||||
String userId = getUserIdByType(chat);
|
||||
LoginDomain loginDomain = LoginUtil.getCurrentLogin();
|
||||
String userId = loginDomain.getUser().getUserId();
|
||||
if (userId == null) {
|
||||
return ResultDomain.failure("用户信息获取失败");
|
||||
}
|
||||
@@ -164,7 +164,8 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
return ResultDomain.failure("智能体不可用");
|
||||
}
|
||||
// 2. 获取用户ID并校验权限
|
||||
String userId = getUserIdByType(filter);
|
||||
LoginDomain loginDomain = LoginUtil.getCurrentLogin();
|
||||
String userId = loginDomain.getUser().getUserId();
|
||||
if (userId == null) {
|
||||
return ResultDomain.failure("用户信息获取失败");
|
||||
}
|
||||
@@ -189,12 +190,9 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
|
||||
@Override
|
||||
public ResultDomain<TbChat> getChatList(TbChat filter) {
|
||||
// 判断agent是否是outer
|
||||
if(!isOuterAgent(filter.getAgentId())){
|
||||
return ResultDomain.failure("智能体不可用");
|
||||
}
|
||||
|
||||
// 获取用户ID
|
||||
String userId = getUserIdByType(filter);
|
||||
String userId = LoginUtil.getCurrentUserId();
|
||||
if (userId == null) {
|
||||
return ResultDomain.failure("用户信息获取失败");
|
||||
}
|
||||
@@ -204,16 +202,16 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultDomain<PageDomain<TbChat>> getChatPage(PageRequest<TbChat> pageRequest) {
|
||||
public ResultDomain<TbChat> getChatPage(PageRequest<TbChat> pageRequest) {
|
||||
TbChat filter = pageRequest.getFilter();
|
||||
// 判断agent是否是outer(来客才需要校验)
|
||||
if (!filter.getUserType() && !isOuterAgent(filter.getAgentId())) {
|
||||
return ResultDomain.<PageDomain<TbChat>>failure("智能体不可用");
|
||||
return ResultDomain.<TbChat>failure("智能体不可用");
|
||||
}
|
||||
// 获取用户ID
|
||||
String userId = getUserIdByType(filter);
|
||||
String userId = LoginUtil.getCurrentUserId();
|
||||
if (userId == null) {
|
||||
return ResultDomain.<PageDomain<TbChat>>failure("用户信息获取失败");
|
||||
return ResultDomain.<TbChat>failure("用户信息获取失败");
|
||||
}
|
||||
filter.setUserId(userId);
|
||||
|
||||
@@ -224,7 +222,7 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
pageParam.setTotal((int) total);
|
||||
|
||||
PageDomain<TbChat> pageDomain = new PageDomain<>(pageParam, chatList);
|
||||
return ResultDomain.<PageDomain<TbChat>>success("查询成功", pageDomain);
|
||||
return ResultDomain.<TbChat>success("查询成功", pageDomain);
|
||||
}
|
||||
|
||||
// ====================== 智能体聊天管理 ======================
|
||||
@@ -241,7 +239,7 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
return ResultDomain.failure("智能体不可用");
|
||||
}
|
||||
// 2. 获取用户ID并校验权限
|
||||
String userId = getUserIdByType(filter);
|
||||
String userId = LoginUtil.getCurrentUserId();
|
||||
if (userId == null) {
|
||||
return ResultDomain.failure("用户信息获取失败");
|
||||
}
|
||||
@@ -272,7 +270,8 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
chatFilter.setUserId(prepareData.getUserId());
|
||||
chatFilter.setUserType(prepareData.getUserType());
|
||||
|
||||
String userId = getUserIdByType(chatFilter);
|
||||
LoginDomain loginDomain = LoginUtil.getCurrentLogin();
|
||||
String userId = loginDomain.getUser().getUserId();
|
||||
if (userId == null) {
|
||||
return ResultDomain.failure("用户信息获取失败");
|
||||
}
|
||||
@@ -299,6 +298,8 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
sessionData.put("userId", userId);
|
||||
sessionData.put("filesData", prepareData.getFiles());
|
||||
sessionData.put("apiKey", agent.getApiKey());
|
||||
sessionData.put("outer", agent.getIsOuter());
|
||||
sessionData.put("service", prepareData.getService());
|
||||
|
||||
String cacheKey = CHAT_SESSION_PREFIX + sessionId;
|
||||
redisService.set(cacheKey, sessionData, SESSION_TTL, TimeUnit.SECONDS);
|
||||
@@ -332,6 +333,9 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
String query = (String) sessionData.get("query");
|
||||
String userId = (String) sessionData.get("userId");
|
||||
String apiKey = (String) sessionData.get("apiKey");
|
||||
String service = (String) sessionData.get("service");
|
||||
Boolean outer = (Boolean) sessionData.get("outer");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<DifyFileInfo> filesData = (List<DifyFileInfo>) sessionData.get("filesData");
|
||||
|
||||
@@ -365,7 +369,23 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
chatRequest.setQuery(query);
|
||||
chatRequest.setUser(userId);
|
||||
chatRequest.setResponseMode("streaming");
|
||||
chatRequest.setInputs(new HashMap<>()); // Dify API 要求 inputs 必传
|
||||
Map<String, Object> inputsMap = new HashMap<>();
|
||||
chatRequest.setInputs(inputsMap); // Dify API 要求 inputs 必传
|
||||
// 处理动态知识库的问题
|
||||
if(outer && NonUtils.isNotEmpty(service)){
|
||||
TbKnowledge filter = new TbKnowledge();
|
||||
filter.setService(service);
|
||||
filter.setCategory("external");
|
||||
ResultDomain<TbKnowledge> knowledgeRD = knowledgeService.listKnowledges(filter);
|
||||
List<String> datasets = new ArrayList<>();
|
||||
if(knowledgeRD.getSuccess()){
|
||||
datasets = knowledgeRD.getDataList().stream().map(TbKnowledge::getDifyDatasetId).toList();
|
||||
}
|
||||
inputsMap.put("datasets", JSON.toJSONString(datasets));
|
||||
inputsMap.put("dataset_apikey", difyConfig.getKnowledgeApiKey());
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (filesData != null && !filesData.isEmpty()) {
|
||||
chatRequest.setFiles(filesData);
|
||||
@@ -454,7 +474,7 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
TbAgent agent = agentResult.getData();
|
||||
|
||||
// 2. 获取用户ID
|
||||
String userId = getUserIdByType(filter);
|
||||
String userId = LoginUtil.getCurrentUserId();
|
||||
if (userId == null) {
|
||||
return ResultDomain.failure("用户信息获取失败");
|
||||
}
|
||||
@@ -480,7 +500,7 @@ public class AgentChatServiceImpl implements AgentChatService {
|
||||
}
|
||||
|
||||
// 2. 获取用户ID
|
||||
String userId = getUserIdByType(filter);
|
||||
String userId = LoginUtil.getCurrentUserId();
|
||||
if (userId == null) {
|
||||
return ResultDomain.failure("用户信息获取失败");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user