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<AiBotService, AiBot> {
|
|
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<String, Object> options) {
|
AiBot aiBot = service.getById(id);
|
Map<String, Object> 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<String, Object> llmOptions) {
|
AiBot aiBot = service.getById(id);
|
Map<String, Object> 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 = "file") String file,//上传文件
|
HttpServletResponse response) {
|
response.setContentType("text/event-stream");
|
AiBot aiBot = service.getById(botId);
|
if (aiBot == null) {
|
return ChatManager.getInstance().sseEmitterForContent("机器人不存在");
|
}
|
Map<String, Object> llmOptions = aiBot.getLlmOptions();
|
String systemPrompt = llmOptions != null ? (String) llmOptions.get("systemPrompt") : null;
|
|
if (StringUtil.hasText(aiBot.getModelAPI())){
|
if (aiBot.getBotTypeId() == 2) {
|
|
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);
|
String fileId = file;
|
|
// 2. 构建文件参数对象
|
Map<String, Object> fileParam = new HashMap<>();
|
fileParam.put("transfer_method", "local_file");
|
fileParam.put("upload_file_id", fileId);
|
// fileParam.put("type", fileJson.get("extension").getAsString()); // 例如 "excel"、"pdf" 等
|
fileParam.put("type", "document"); // 例如 "excel"、"pdf" 等
|
|
// 3. 组装 inputs 参数
|
Map<String, Object> inputs = new HashMap<>();
|
inputs.put("w", 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<Integer> 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<AiBotMessage> 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<String, Object> 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 <UNK>message<UNK>" + 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<String, Object> errorRespnseMsg(int errorCode, String message) {
|
HashMap<String, Object> 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<FunctionCaller> 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<AiBotWorkflow> 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<AiBotKnowledge> 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> 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<BigInteger> 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<AiPluginTool> aiPluginTools = aiPluginToolService.getMapper().selectListWithRelationsByQuery(queryTool);
|
for (AiPluginTool item : aiPluginTools) {
|
humanMessage.addFunction(item.toFunction());
|
}
|
|
|
}
|
}
|