package tech.aiflowy.ai.controller; import cn.dev33.satoken.annotation.SaIgnore; import cn.hutool.core.util.ObjectUtil; import com.agentsflex.core.llm.ChatContext; import com.agentsflex.core.llm.Llm; import com.agentsflex.core.llm.StreamResponseListener; import com.agentsflex.core.llm.functions.Function; import com.agentsflex.core.llm.response.AiMessageResponse; import com.agentsflex.core.llm.response.FunctionCaller; import com.agentsflex.core.message.AiMessage; import com.agentsflex.core.message.HumanMessage; import com.agentsflex.core.message.SystemMessage; import com.agentsflex.core.prompt.HistoriesPrompt; import com.agentsflex.core.prompt.ToolPrompt; import com.agentsflex.core.util.CollectionUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializeConfig; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.table.TableInfo; import com.mybatisflex.core.table.TableInfoFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.*; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import tech.aiflowy.ai.config.DifyStreamClient; import tech.aiflowy.ai.config.FileReference; import tech.aiflowy.ai.entity.*; import tech.aiflowy.ai.mapper.AiBotConversationMessageMapper; import tech.aiflowy.ai.service.*; import tech.aiflowy.common.ai.ChatManager; import tech.aiflowy.common.ai.MySseEmitter; import tech.aiflowy.common.domain.Result; import tech.aiflowy.common.entity.LoginAccount; import tech.aiflowy.common.satoken.util.SaTokenUtil; import tech.aiflowy.common.util.StringUtil; import tech.aiflowy.common.web.controller.BaseCurdController; import tech.aiflowy.common.web.jsonbody.JsonBody; import tech.aiflowy.system.entity.SysApiKey; import tech.aiflowy.system.mapper.SysApiKeyMapper; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.math.BigInteger; import java.util.*; /** * 控制层。 * * @author michael * @since 2024-08-23 */ @RestController @RequestMapping("/api/v1/aiBot") public class AiBotController extends BaseCurdController { private final AiLlmService aiLlmService; private final AiBotWorkflowService aiBotWorkflowService; private final AiBotKnowledgeService aiBotKnowledgeService; private final AiBotMessageService aiBotMessageService; @Resource private SysApiKeyMapper aiBotApiKeyMapper; @Resource private AiBotConversationMessageService aiBotConversationMessageService; @Resource private AiBotConversationMessageMapper aiBotConversationMessageMapper; private static final Logger logger = LoggerFactory.getLogger(AiBotController.class); @Autowired private RestTemplate restTemplate; public AiBotController(AiBotService service, AiLlmService aiLlmService, AiBotWorkflowService aiBotWorkflowService, AiBotKnowledgeService aiBotKnowledgeService, AiBotMessageService aiBotMessageService) { super(service); this.aiLlmService = aiLlmService; this.aiBotWorkflowService = aiBotWorkflowService; this.aiBotKnowledgeService = aiBotKnowledgeService; this.aiBotMessageService = aiBotMessageService; } @Resource private AiBotPluginsService aiBotPluginsService; @Resource private AiPluginToolService aiPluginToolService; @PostMapping("updateOptions") public Result updateOptions(@JsonBody("id") BigInteger id, @JsonBody("options") Map options) { AiBot aiBot = service.getById(id); Map existOptions = aiBot.getOptions(); if (existOptions == null) { existOptions = new HashMap<>(); } if (options != null) { existOptions.putAll(options); } aiBot.setOptions(existOptions); service.updateById(aiBot); return Result.success(); } @PostMapping("updateLlmOptions") public Result updateLlmOptions(@JsonBody("id") BigInteger id, @JsonBody("llmOptions") Map llmOptions) { AiBot aiBot = service.getById(id); Map existLlmOptions = aiBot.getLlmOptions(); if (existLlmOptions == null) { existLlmOptions = new HashMap<>(); } if (llmOptions != null) { existLlmOptions.putAll(llmOptions); } aiBot.setLlmOptions(existLlmOptions); service.updateById(aiBot); return Result.success(); } /** * 当前系统用户调用对话 * * @param prompt * @param botId * @param sessionId * @param isExternalMsg * @param response * @return */ @Autowired private ObjectMapper objectMapper; // @PostMapping("chat") // public SseEmitter chat2(@JsonBody(value = "prompt", required = true) String prompt, // @JsonBody(value = "botId", required = true) BigInteger botId, // @JsonBody(value = "sessionId", required = true) String sessionId, // @JsonBody(value = "isExternalMsg") int isExternalMsg, // @JsonBody("file") String file,//上传文件 // HttpServletResponse response){ // File file = // } @PostMapping("chat") public SseEmitter chat(@JsonBody(value = "prompt", required = true) String prompt, @JsonBody(value = "botId", required = true) BigInteger botId, @JsonBody(value = "sessionId", required = true) String sessionId, @JsonBody(value = "isExternalMsg") int isExternalMsg, @JsonBody(value = "files") List files,//上传文件 @JsonBody(value = "file") String file,//上传文件 HttpServletResponse response) { response.setContentType("text/event-stream"); AiBot aiBot = service.getById(botId); if (aiBot == null) { return ChatManager.getInstance().sseEmitterForContent("机器人不存在"); } Map llmOptions = aiBot.getLlmOptions(); String systemPrompt = llmOptions != null ? (String) llmOptions.get("systemPrompt") : null; if (StringUtil.hasText(aiBot.getModelAPI())){ if (aiBot.getBotTypeId() == 2 || aiBot.getBotTypeId() == 3) { String apiUrl = aiBot.getModelAPI()+"/workflows/run"; // 替换为实际API URL String apiKey = aiBot.getModelKEY(); // 替换为实际API Key DifyStreamClient client = new DifyStreamClient(apiUrl, apiKey, aiBotMessageService); // DifyStreamClient uploadClient = new DifyStreamClient(aiBot.getModelAPI()+"/files/upload", apiKey, aiBotMessageService); Map inputs = new HashMap<>(); if(aiBot.getBotTypeId() == 3){ // 2. 构建文件参数对象 HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", apiKey); HttpEntity requestEntity = new HttpEntity<>(null, headers); ResponseEntity parameters = restTemplate.exchange( aiBot.getModelAPI()+"/parameters", HttpMethod.GET, requestEntity, // 请求体(GET 无请求体) String.class // 响应结果类型 ); org.json.JSONObject jsonObj = new org.json.JSONObject(parameters.getBody()); // 先获取 user_input_form 数组 org.json.JSONArray userInputFormArr = jsonObj.getJSONArray("user_input_form"); String variable = null; String type = ""; // 遍历数组,找到 file - list 结构 for (int i = 0; i < userInputFormArr.length(); i++) { org.json.JSONObject formItem = userInputFormArr.getJSONObject(i); if (formItem.has("file-list")) { org.json.JSONObject fileListObj = formItem.getJSONObject("file-list"); // 提取 variable 参数 variable = fileListObj.getString("variable"); // 提取 allowed_file_types 参数(数组形式) org.json.JSONArray allowedFileTypesArr = fileListObj.getJSONArray("allowed_file_types"); System.out.println("variable: " + variable); System.out.println("allowed_file_types: " + allowedFileTypesArr.toString()); type = allowedFileTypesArr.toString().replace("[\"", "").replace("\"]", ""); break; // 这里假设只有一个符合的 file - list,找到就退出循环,可根据实际情况调整 } } List fileList = new ArrayList<>(); Map fileParam = new HashMap<>(); for (String fileId : files) { fileParam.put("transfer_method", "local_file"); fileParam.put("upload_file_id", fileId); fileParam.put("type", type); // 例如 "excel"、"pdf" 等 fileList.add(fileParam); } // 3. 组装 inputs 参数 inputs.put(variable, fileList); // 添加文件参数,variableName 如 "document" } else { HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", apiKey); Map fileParam = new HashMap<>(); fileParam.put("transfer_method", "local_file"); fileParam.put("upload_file_id", file); HttpEntity requestEntity = new HttpEntity<>(null, headers); ResponseEntity parameters = restTemplate.exchange( aiBot.getModelAPI()+"/parameters", HttpMethod.GET, requestEntity, // 请求体(GET 无请求体) String.class // 响应结果类型 ); // System.out.println("========================\n"+parameters.getBody()+"\n====================="); String variable = null; String type = ""; try { // 解析 JSON 字符串 org.json.JSONObject configJson = new org.json.JSONObject(parameters.getBody()); // 获取 user_input_form 数组 org.json.JSONArray userInputFormArray = configJson.getJSONArray("user_input_form"); // 遍历 user_input_form 数组中的每个元素 for (int i = 0; i < userInputFormArray.length(); i++) { org.json.JSONObject formElement = userInputFormArray.getJSONObject(i); // 检查是否包含 "file" 对象 if (formElement.has("file")) { org.json.JSONObject fileObject = formElement.getJSONObject("file"); // 提取 variable variable = fileObject.getString("variable"); // 提取 allowed_file_types 数组 org.json.JSONArray allowedFileTypesArray = fileObject.getJSONArray("allowed_file_types"); // 打印结果 System.out.println("Variable: " + variable); System.out.print("Document Types: "); for (int j = 0; j < allowedFileTypesArray.length(); j++) { type = type + allowedFileTypesArray.getString(j); System.out.print(allowedFileTypesArray.getString(j) + " "); } System.out.println(); } } } catch (Exception e) { e.printStackTrace(); } fileParam.put("type", type); // 例如 "excel"、"pdf" 等 // 3. 组装 inputs 参数 inputs.put(variable, fileParam); // 添加文件参数,variableName 如 "document" } AiBotMessageMemory memory = new AiBotMessageMemory(botId, SaTokenUtil.getLoginAccount().getId(), sessionId, isExternalMsg, aiBotMessageService, aiBotConversationMessageMapper, aiBotConversationMessageService); final HistoriesPrompt historiesPrompt = new HistoriesPrompt(); if (systemPrompt != null) { historiesPrompt.setSystemMessage(SystemMessage.of(systemPrompt)); } historiesPrompt.setMemory(memory); HumanMessage humanMessage = new HumanMessage(prompt); // 添加插件相关的function calling appendPluginToolFunction(botId, humanMessage); //添加工作流相关的 Function Calling appendWorkflowFunctions(botId, humanMessage); //添加知识库相关的 Function Calling appendKnowledgeFunctions(botId, humanMessage); historiesPrompt.addMessage(humanMessage); final Boolean[] needClose = {true}; ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); MySseEmitter emitter = new MySseEmitter(1000L * 60 * 2); // 2分钟超时 try { String userId = SaTokenUtil.getLoginAccount().getId() + ""; client.runWorkflow(inputs, prompt, userId, emitter, sessionId, botId); } catch (Exception e) { emitter.completeWithError(e); } // System.out.println(emitter.toString()); return emitter; } aiBot.setModelAPI(aiBot.getModelAPI()+"/chat-messages"); String apiUrl = aiBot.getModelAPI(); // 替换为实际API URL String apiKey = aiBot.getModelKEY(); // 替换为实际API Key DifyStreamClient client = new DifyStreamClient(apiUrl, apiKey, aiBotMessageService); AiBotMessageMemory memory = new AiBotMessageMemory(botId, SaTokenUtil.getLoginAccount().getId(), sessionId, isExternalMsg, aiBotMessageService, aiBotConversationMessageMapper, aiBotConversationMessageService); final HistoriesPrompt historiesPrompt = new HistoriesPrompt(); if (systemPrompt != null) { historiesPrompt.setSystemMessage(SystemMessage.of(systemPrompt)); } historiesPrompt.setMemory(memory); HumanMessage humanMessage = new HumanMessage(prompt); // 添加插件相关的function calling appendPluginToolFunction(botId, humanMessage); //添加工作流相关的 Function Calling appendWorkflowFunctions(botId, humanMessage); //添加知识库相关的 Function Calling appendKnowledgeFunctions(botId, humanMessage); historiesPrompt.addMessage(humanMessage); final Boolean[] needClose = {true}; ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); MySseEmitter emitter = new MySseEmitter(1000L * 60 * 2); // 2分钟超时 try { String userId = SaTokenUtil.getLoginAccount().getId() + ""; client.chatStream(prompt, userId, emitter, sessionId, botId); } catch (Exception e) { emitter.completeWithError(e); } // System.out.println(emitter.toString()); return emitter; } else{ AiLlm aiLlm = aiLlmService.getById(aiBot.getLlmId()); if (aiLlm == null) { return ChatManager.getInstance().sseEmitterForContent("LLM不存在"); } Llm llm = aiLlm.toLlm(); if (llm == null) { return ChatManager.getInstance().sseEmitterForContent("LLM获取为空"); } AiBotMessageMemory memory = new AiBotMessageMemory(botId, SaTokenUtil.getLoginAccount().getId(), sessionId, isExternalMsg, aiBotMessageService, aiBotConversationMessageMapper, aiBotConversationMessageService); final HistoriesPrompt historiesPrompt = new HistoriesPrompt(); if (systemPrompt != null) { historiesPrompt.setSystemMessage(SystemMessage.of(systemPrompt)); } historiesPrompt.setMemory(memory); HumanMessage humanMessage = new HumanMessage(prompt); // 添加插件相关的function calling appendPluginToolFunction(botId, humanMessage); //添加工作流相关的 Function Calling appendWorkflowFunctions(botId, humanMessage); //添加知识库相关的 Function Calling appendKnowledgeFunctions(botId, humanMessage); historiesPrompt.addMessage(humanMessage); MySseEmitter emitter = new MySseEmitter((long) (1000 * 60 * 2)); final Boolean[] needClose = {true}; ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); // 统一使用流式处理,无论是否有 Function Calling llm.chatStream(historiesPrompt, new StreamResponseListener() { @Override public void onMessage(ChatContext context, AiMessageResponse response) { try { RequestContextHolder.setRequestAttributes(sra, true); if (response != null) { // 检查是否需要触发 Function Calling if (response.getFunctionCallers() != null && CollectionUtil.hasItems(response.getFunctionCallers())) { needClose[0] = false; function_call(response, emitter, needClose, historiesPrompt, llm, prompt, false); } else { // 强制流式返回,即使有 Function Calling 也先返回部分结果 if (response.getMessage() != null) { String content = response.getMessage().getContent(); if (StringUtil.hasText(content)) { System.out.println(response); emitter.send(JSON.toJSONString(response.getMessage())); } } } } } catch (Exception e) { emitter.completeWithError(e); } } @Override public void onStop(ChatContext context) { if (needClose[0]) { emitter.complete(); } } @Override public void onFailure(ChatContext context, Throwable throwable) { emitter.completeWithError(throwable); } }); System.out.println(emitter.toString()); return emitter; } } @PostMapping("files/upload") public Result filesUpload(@RequestParam("botId") BigInteger botId, @RequestParam("file") MultipartFile file, HttpServletResponse response){ try{ String userId = SaTokenUtil.getLoginAccount().getId() + ""; response.setContentType("text/event-stream"); AiBot aiBot = service.getById(botId); aiBot.setModelAPI(aiBot.getModelAPI()+"/files/upload"); String apiUrl = aiBot.getModelAPI(); // 替换为实际API URL String apiKey = aiBot.getModelKEY(); // 替换为实际API Key DifyStreamClient client = new DifyStreamClient(apiUrl, apiKey, aiBotMessageService); String s = client.fileUpload(userId, file); return Result.success(s); }catch (Exception e){ return Result.fail(400,String.valueOf(e)); } } public Result save(@RequestBody String jsonStr) { // 解析JSON JSONObject json = JSONObject.parseObject(jsonStr); // 合并所有secondMenuId*字段 List menuIds = new ArrayList<>(); for (String key : json.keySet()) { if (key.startsWith("secondMenuId")) { Object value = json.get(key); if (value instanceof Integer) { menuIds.add((Integer) value); } } } // 保留第一个ID(根据需要调整) if (!menuIds.isEmpty()) { json.put("secondMenuId", menuIds.get(0)); } // 转换为实体类 AiBot entity = json.toJavaObject(AiBot.class); // 后续处理保持不变 Result result = onSaveOrUpdateBefore(entity, true); if (result != null) return result; if (entity == null) { throw new NullPointerException("entity is null"); } LoginAccount loginAccount = SaTokenUtil.getLoginAccount(); commonFiled(entity,loginAccount.getId(),loginAccount.getTenantId(),loginAccount.getDeptId()); boolean success = service.save(entity); onSaveOrUpdateAfter(entity, true); TableInfo tableInfo = TableInfoFactory.ofEntityClass(entity.getClass()); Object[] pkArgs = tableInfo.buildPkSqlArgs(entity); return Result.create(success).set("id", pkArgs); } /** * 外部用户调用智能体进行对话 * 需要用户传 apiKey 对用户进行身份验证 * * @param stream [true: 返回sse false: 返回json * @return */ @SaIgnore @PostMapping("externalChat") public Object externalChat( @JsonBody(value = "messages", required = true) List messages, @JsonBody(value = "botId", required = true) BigInteger botId, @JsonBody(value = "stream", required = false) boolean stream, HttpServletResponse response, HttpServletRequest request ) { // 设置响应类型 if (stream) { response.setContentType("text/event-stream"); } else { response.setContentType("application/json"); } // 获取 API Key 和 Bot 信息 String apiKey = request.getHeader("Authorization"); QueryWrapper queryWrapper = QueryWrapper.create() .select("api_key", "status", "expired_at") .from("tb_sys_api_key") .where("api_key = ? ", apiKey); SysApiKey aiBotApiKey = aiBotApiKeyMapper.selectOneByQuery(queryWrapper); if (aiBotApiKey == null) { return createResponse(stream, JSON.toJSONString(errorRespnseMsg(1, "该apiKey不存在"))); } if (aiBotApiKey.getStatus() == 0) { return createResponse(stream, JSON.toJSONString(errorRespnseMsg(2, "该apiKey未启用"))); } if (aiBotApiKey.getExpiredAt().getTime() < new Date().getTime()) { return createResponse(stream, JSON.toJSONString(errorRespnseMsg(3, "该apiKey已失效"))); } AiBot aiBot = service.getById(botId); if (aiBot == null) { return createResponse(stream, JSON.toJSONString(errorRespnseMsg(4, "机器人不存在"))); } Map llmOptions = aiBot.getLlmOptions(); String systemPrompt = llmOptions != null ? (String) llmOptions.get("systemPrompt") : null; AiLlm aiLlm = aiLlmService.getById(aiBot.getLlmId()); if (aiLlm == null) { return createResponse(stream, JSON.toJSONString(errorRespnseMsg(5, "LLM不存在"))); } Llm llm = aiLlm.toLlm(); AiBotExternalMessageMemory messageMemory = new AiBotExternalMessageMemory(messages); HistoriesPrompt historiesPrompt = new HistoriesPrompt(); if (systemPrompt != null) { historiesPrompt.setSystemMessage(SystemMessage.of(systemPrompt)); } historiesPrompt.setMemory(messageMemory); String prompt = messages.get(messages.size() - 1).getContent(); HumanMessage humanMessage = new HumanMessage(); // 添加插件、工作流、知识库相关的 Function Calling appendPluginToolFunction(botId, humanMessage); appendWorkflowFunctions(botId, humanMessage); appendKnowledgeFunctions(botId, humanMessage); historiesPrompt.addMessage(humanMessage); // 根据 responseType 返回不同的响应 if (stream) { MySseEmitter emitter = new MySseEmitter((long) (1000 * 60 * 2)); final Boolean[] needClose = {true}; if (humanMessage.getFunctions() != null && !humanMessage.getFunctions().isEmpty()) { try { AiMessageResponse aiMessageResponse = llm.chat(historiesPrompt); function_call(aiMessageResponse, emitter, needClose, historiesPrompt, llm, prompt, true); } catch (Exception e) { emitter.completeWithError(e); } if (needClose[0]) { System.out.println("function chat complete"); emitter.complete(); } } else { llm.chatStream(historiesPrompt, new StreamResponseListener() { @Override public void onMessage(ChatContext context, AiMessageResponse response) { try { function_call(response, emitter, needClose, historiesPrompt, llm, prompt, true); } catch (Exception e) { emitter.completeWithError(e); } } @Override public void onStop(ChatContext context) { if (needClose[0]) { System.out.println("normal chat complete"); emitter.complete(); } } @Override public void onFailure(ChatContext context, Throwable throwable) { emitter.completeWithError(throwable); } }); } return emitter; } else { AiMessageResponse resultFunctionCall; if (humanMessage.getFunctions() != null && !humanMessage.getFunctions().isEmpty()) { try { AiMessageResponse aiMessageResponse = llm.chat(historiesPrompt); resultFunctionCall = jsonResultJsonFunctionCall(aiMessageResponse, historiesPrompt, llm, prompt); return JSON.toJSONString(resultFunctionCall.getMessage(), new SerializeConfig()); } catch (Exception e) { return createErrorResponse(e); } } else { AiMessageResponse messageResponse = llm.chat(historiesPrompt); resultFunctionCall = jsonResultJsonFunctionCall(messageResponse, historiesPrompt, llm, prompt); AiBotExternalMsgJsonResult result = handleMessageResult(resultFunctionCall.getMessage()); return JSON.toJSONString(result, new SerializeConfig()); } } } private AiBotExternalMsgJsonResult handleMessageResult(AiMessage aiMessage) { AiBotExternalMsgJsonResult messageResult = new AiBotExternalMsgJsonResult(); messageResult.setCreated(new Date().getTime()); AiBotExternalMsgJsonResult.Usage usage = new AiBotExternalMsgJsonResult.Usage(); if (aiMessage.getTotalTokens() != null){ usage.setTotalTokens(aiMessage.getTotalTokens()); } if (aiMessage.getCompletionTokens() != null){ usage.setCompletionTokens(aiMessage.getCompletionTokens()); } if (aiMessage.getPromptTokens() != null){ usage.setPromptTokens(aiMessage.getPromptTokens()); } messageResult.setUsage(usage); AiBotExternalMsgJsonResult.Choice choice = new AiBotExternalMsgJsonResult.Choice(); AiBotExternalMsgJsonResult.Message message = new AiBotExternalMsgJsonResult.Message(); message.setContent(aiMessage.getContent()); message.setRole("assistant"); choice.setMessage(message); messageResult.setChoices(choice); messageResult.setStatus(aiMessage.getStatus().name()); return messageResult; } // 辅助方法:创建响应 private Object createResponse(boolean stream, String content) { if (stream) { MySseEmitter emitter = new MySseEmitter((long) (1000 * 60 * 2)); emitter.send(content); emitter.complete(); return emitter; } else { return ResponseEntity.ok(content); } } // 辅助方法:创建错误响应 private Object createErrorResponse(Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); } /** * @param aiMessageResponse 大模型返回的消息 * @param emitter * @param needClose 是否需要关闭流 * @param historiesPrompt 消息历史记录 * @param llm 大模型 * @param prompt 提示词 * @param isExternalChatApi true 外部系统调用bot false 内部系统调用bot */ private String function_call(AiMessageResponse aiMessageResponse, MySseEmitter emitter, Boolean[] needClose, HistoriesPrompt historiesPrompt, Llm llm, String prompt, boolean isExternalChatApi) { ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); RequestContextHolder.setRequestAttributes(sra, true); String content = aiMessageResponse.getMessage().getContent(); Object messageContent = aiMessageResponse.getMessage(); if (StringUtil.hasText(content)) { // 如果是外部系统调用chat if (isExternalChatApi) { AiBotExternalMsgJsonResult result = handleMessageStreamJsonResult(aiMessageResponse.getMessage()); emitter.send(JSON.toJSONString(result, new SerializeConfig())); } else { emitter.send(JSON.toJSONString(messageContent)); } } System.out.println("function call 接收到的参数message:" + aiMessageResponse); llm.chatStream(ToolPrompt.of(aiMessageResponse), new StreamResponseListener() { @Override public void onMessage(ChatContext context, AiMessageResponse response) { System.out.println("function call message" + aiMessageResponse); String content = response.getMessage().getContent(); if (StringUtil.hasText(content)) { System.out.println("if content" + content); emitter.send(JSON.toJSONString(response.getMessage())); } } @Override public void onStop(ChatContext context) { System.out.println("function call complete"); emitter.complete(); } @Override public void onFailure(ChatContext context, Throwable throwable) { logger.error("function_call报错:",throwable); AiMessage aiMessage = new AiMessage(); aiMessage.setContent("未查询到相关信息..."); emitter.send(JSON.toJSONString(aiMessage)); System.out.println("function call complete with error"); } }); return JSON.toJSONString(messageContent); } private Map errorRespnseMsg(int errorCode, String message) { HashMap result = new HashMap<>(); result.put("error", errorCode); result.put("message", message); return result; } private AiBotExternalMsgJsonResult handleMessageStreamJsonResult(AiMessage message) { AiBotExternalMsgJsonResult result = new AiBotExternalMsgJsonResult(); AiBotExternalMsgJsonResult.Choice choice = new AiBotExternalMsgJsonResult.Choice(); AiBotExternalMsgJsonResult.Delta delta = new AiBotExternalMsgJsonResult.Delta(); delta.setRole("assistant"); delta.setContent(message.getContent()); choice.setDelta(delta); result.setCreated(new Date().getTime()); result.setChoices(choice); result.setStatus(message.getStatus().name()); return result; } private AiMessageResponse jsonResultJsonFunctionCall(AiMessageResponse aiMessageResponse, HistoriesPrompt historiesPrompt, Llm llm, String prompt) { List functionCallers = aiMessageResponse.getFunctionCallers(); if (CollectionUtil.hasItems(functionCallers)) { for (FunctionCaller functionCaller : functionCallers) { Object result = functionCaller.call(); if (ObjectUtil.isNotEmpty(result)) { String newPrompt = "请根据以下内容回答用户,内容是:\n" + result + "\n 用户的问题是:" + prompt; historiesPrompt.addMessageTemporary(new HumanMessage(newPrompt)); return llm.chat(historiesPrompt); } } } return aiMessageResponse; } private void appendWorkflowFunctions(BigInteger botId, HumanMessage humanMessage) { QueryWrapper queryWrapper = QueryWrapper.create().eq(AiBotWorkflow::getBotId, botId); List aiBotWorkflows = aiBotWorkflowService.getMapper().selectListWithRelationsByQuery(queryWrapper); if (aiBotWorkflows != null) { for (AiBotWorkflow aiBotWorkflow : aiBotWorkflows) { Function function = aiBotWorkflow.getWorkflow().toFunction(); humanMessage.addFunction(function); } } } private void appendKnowledgeFunctions(BigInteger botId, HumanMessage humanMessage) { QueryWrapper queryWrapper = QueryWrapper.create().eq(AiBotKnowledge::getBotId, botId); List aiBotKnowledges = aiBotKnowledgeService.getMapper().selectListWithRelationsByQuery(queryWrapper); if (aiBotKnowledges != null) { for (AiBotKnowledge aiBotKnowledge : aiBotKnowledges) { Function function = aiBotKnowledge.getKnowledge().toFunction(); humanMessage.addFunction(function); } } } // private void appendPluginFunctions(BigInteger botId, HumanMessage humanMessage) { // QueryWrapper queryWrapper = QueryWrapper.create().eq(AiBotPlugins::getBotId, botId); // List aiBotPlugins = aiBotPluginsService.getMapper().selectListWithRelationsByQuery(queryWrapper); // if (cn.hutool.core.collection.CollectionUtil.isNotEmpty(aiBotPlugins)) { // for (AiBotPlugins aiBotPlugin : aiBotPlugins) { // Function function = aiBotPlugin.getAiPlugins().toFunction(); // humanMessage.addFunction(function); // } // } // } private void appendPluginToolFunction(BigInteger botId, HumanMessage humanMessage) { QueryWrapper queryWrapper = QueryWrapper.create().select("plugin_tool_id").eq(AiBotPlugins::getBotId, botId); List pluginToolIds = aiBotPluginsService.getMapper().selectListWithRelationsByQueryAs(queryWrapper, BigInteger.class); if (pluginToolIds == null || pluginToolIds.isEmpty()) { return; } QueryWrapper queryTool = QueryWrapper.create() .select("*") .from("tb_ai_plugin_tool") .in("id", pluginToolIds); List aiPluginTools = aiPluginToolService.getMapper().selectListWithRelationsByQuery(queryTool); for (AiPluginTool item : aiPluginTools) { humanMessage.addFunction(item.toFunction()); } } }