18586361686
2025-04-17 37193955173064e7f768c01403789a76931873ea
feat: add external bot api
1个文件已修改
2个文件已添加
177 ■■■■■ 已修改文件
aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/controller/AiBotController.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/entity/AiBotExternalMessageMemory.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/entity/AiBotExternalMsgResult.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/controller/AiBotController.java
@@ -1,5 +1,6 @@
package tech.aiflowy.ai.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import tech.aiflowy.ai.entity.*;
import tech.aiflowy.ai.mapper.AiBotConversationMessageMapper;
import tech.aiflowy.ai.service.*;
@@ -31,6 +32,7 @@
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigInteger;
import java.util.HashMap;
@@ -99,6 +101,15 @@
        return Result.success();
    }
    /**
     * 当前系统用户调用对话
     * @param prompt
     * @param botId
     * @param sessionId
     * @param isExternalMsg
     * @param response
     * @return
     */
    @PostMapping("chat")
    public SseEmitter chat(@JsonBody(value = "prompt", required = true) String prompt,
                           @JsonBody(value = "botId", required = true) BigInteger botId,
@@ -147,7 +158,7 @@
        if (humanMessage.getFunctions() != null && !humanMessage.getFunctions().isEmpty()) {
            try {
                AiMessageResponse aiMessageResponse = llm.chat(historiesPrompt);
                function_call(aiMessageResponse, emitter, needClose, historiesPrompt, llm, prompt);
                function_call(aiMessageResponse, emitter, needClose, historiesPrompt, llm, prompt, false);
            } catch (Exception e) {
                emitter.completeWithError(e);
            }
@@ -163,7 +174,7 @@
                public void onMessage(ChatContext context, AiMessageResponse response) {
                    try {
                        function_call(response, emitter, needClose, historiesPrompt, llm, prompt);
                        function_call(response, emitter, needClose, historiesPrompt, llm, prompt, false);
                    } catch (Exception e) {
                        emitter.completeWithError(e);
                    }
@@ -187,15 +198,127 @@
        return emitter;
    }
    /**
     * 外部用户调用智能体进行对话
     * 需要用户传 apiKey 对用户进行身份验证
     * @return
     */
    @SaIgnore
    @PostMapping("externalChat")
    public SseEmitter externalChat(
            @JsonBody(value = "messages", required = true) List<AiBotMessage> messages,
            @JsonBody(value = "botId", required = true ) BigInteger botId,
            HttpServletResponse response,
            HttpServletRequest request
    ){
    private void function_call(AiMessageResponse aiMessageResponse, MySseEmitter emitter, Boolean[] needClose, HistoriesPrompt historiesPrompt, Llm llm, String prompt) {
        response.setContentType("text/event-stream");
        request.getAuthType();
        String apiKey = request.getHeader("Authorization");
        AiBot aiBot = service.getById(botId);
        if (aiBot == null) {
            return ChatManager.getInstance().sseEmitterForContent("机器人不存在");
        }
        Map<String, Object> llmOptions = aiBot.getLlmOptions();
        AiLlm aiLlm = aiLlmService.getById(aiBot.getLlmId());
        if (aiLlm == null) {
            return ChatManager.getInstance().sseEmitterForContent("LLM不存在");
        }
        Llm llm = aiLlm.toLlm();
        AiBotExternalMessageMemory messageMemory = new AiBotExternalMessageMemory(messages);
        final HistoriesPrompt historiesPrompt = new HistoriesPrompt();
        historiesPrompt.setSystemMessage(SystemMessage.of((String) llmOptions.get("systemPrompt")));
        historiesPrompt.setMemory(messageMemory);
        String prompt = messages.get(messages.size() - 1).getContent();
        HumanMessage humanMessage = new HumanMessage();
        // 添加插件相关的function calling
        appendPluginFunctions(botId, humanMessage);
        //添加工作流相关的 Function Calling
        appendWorkflowFunctions(botId, humanMessage);
        //添加知识库相关的 Function Calling
        appendKnowledgeFunctions(botId, humanMessage);
        final HistoriesPrompt historiesPrompts = new HistoriesPrompt();
        historiesPrompts.addMessage(humanMessage);
        MySseEmitter emitter = new MySseEmitter((long) (1000 * 60 * 2));
        final Boolean[] needClose = {true};
        if (humanMessage.getFunctions() != null && !humanMessage.getFunctions().isEmpty()) {
            try {
                AiMessageResponse aiMessageResponse = llm.chat(historiesPrompts);
                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;
    }
    /**
     *
     * @param aiMessageResponse
     * @param emitter
     * @param needClose
     * @param historiesPrompt
     * @param llm
     * @param prompt
     * @param isChatApi 该参数用于分辨外部地址用户通过apiKey的方式传参,不涉及外部调用的默认 false
     */
    private void function_call(AiMessageResponse aiMessageResponse, MySseEmitter emitter, Boolean[] needClose, HistoriesPrompt historiesPrompt, Llm llm, String prompt, boolean isChatApi) {
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        RequestContextHolder.setRequestAttributes(sra, true);
        String content = aiMessageResponse.getMessage().getContent();
        Object messageContent = aiMessageResponse.getMessage();
        if (StringUtil.hasText(content)) {
            String jsonResult = JSON.toJSONString(messageContent);
            emitter.send(jsonResult);
            String jsonResult;
            if (isChatApi){
                // 这里如果是需要外部用户使用apiKey调用返回结果的时候需要对返回的结果进行处理,设置我们自定义的数据给用户,该结果还未确定,待测试
                jsonResult = JSON.toJSONString(messageContent);
                emitter.send(jsonResult);
            } else {
                jsonResult = JSON.toJSONString(messageContent);
                emitter.send(jsonResult);
            }
        }
        List<FunctionCaller> functionCallers = aiMessageResponse.getFunctionCallers();
        if (CollectionUtil.hasItems(functionCallers)) {
aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/entity/AiBotExternalMessageMemory.java
New file
@@ -0,0 +1,36 @@
package tech.aiflowy.ai.entity;
import com.agentsflex.core.memory.ChatMemory;
import com.agentsflex.core.message.Message;
import java.util.ArrayList;
import java.util.List;
public class AiBotExternalMessageMemory  implements ChatMemory {
    List<AiBotMessage> historyMessages;
    public AiBotExternalMessageMemory( List<AiBotMessage> historyMessage) {
        this.historyMessages = historyMessage;
    }
    @Override
    public List<Message> getMessages() {
        List<Message> messages = new ArrayList<>();
        for (AiBotMessage aiBotMessage : historyMessages) {
            Message message = aiBotMessage.toMessage();
            if (message != null) messages.add(message);
        }
        return messages;
    }
    @Override
    public void addMessage(Message message) {
    }
    @Override
    public Object id() {
        return null;
    }
}
aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/entity/AiBotExternalMsgResult.java
New file
@@ -0,0 +1,8 @@
package tech.aiflowy.ai.entity;
import com.agentsflex.core.message.AbstractTextMessage;
public class AiBotExternalMsgResult extends AbstractTextMessage {
}