package cn.com.poc.agent_application.aggregate.impl;

import cn.com.poc.thirdparty.resource.demand.ai.entity.dbchain.DBChainResult;

import cn.com.poc.agent_application.aggregate.AgentApplicationService;
import cn.com.poc.agent_application.constant.*;
import cn.com.poc.agent_application.domain.FunctionResult;
import cn.com.poc.agent_application.entity.*;
import cn.com.poc.agent_application.query.DialogsIdsQueryByAgentIdQueryItem;
import cn.com.poc.agent_application.service.*;
import cn.com.poc.agent_application.utils.AgentApplicationTools;
import cn.com.poc.common.constant.CommonConstant;
import cn.com.poc.common.utils.Assert;
import cn.com.poc.common.utils.BlContext;
import cn.com.poc.common.utils.JsonUtils;
import cn.com.poc.common.utils.SSEUtil;
import cn.com.poc.knowledge.constant.KnowledgeConstant;
import cn.com.poc.knowledge.entity.BizKnowledgeDatabaseEntity;
import cn.com.poc.knowledge.entity.BizKnowledgeDocumentEntity;
import cn.com.poc.knowledge.query.KnowledgeDocumentRelationQueryItem;
import cn.com.poc.knowledge.service.BizKnowledgeDatabaseService;
import cn.com.poc.knowledge.service.BizKnowledgeDocumentService;
import cn.com.poc.support.security.oauth.entity.UserBaseEntity;
import cn.com.poc.thirdparty.resource.demand.ai.aggregate.AICreateImageService;
import cn.com.poc.thirdparty.resource.demand.ai.aggregate.DemandKnowledgeService;
import cn.com.poc.thirdparty.resource.demand.ai.constants.KnowledgeSearchTypeEnum;
import cn.com.poc.thirdparty.resource.demand.ai.constants.LLMRoleEnum;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dbchain.DBChainResponse;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Message;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.MultiContent;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Tool;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.ToolFunction;
import cn.com.poc.thirdparty.resource.demand.ai.entity.function.FunctionCallResult;
import cn.com.poc.thirdparty.resource.demand.ai.entity.generations.BaiduAISailsText2ImageRequest;
import cn.com.poc.thirdparty.resource.demand.ai.entity.generations.BaiduAISailsText2ImageResult;
import cn.com.poc.thirdparty.resource.demand.ai.entity.knowledge.SearchKnowledgeResult;
import cn.com.poc.thirdparty.resource.demand.ai.entity.largemodel.LargeModelDemandResult;
import cn.com.poc.thirdparty.resource.demand.ai.entity.largemodel.LargeModelResponse;
import cn.com.poc.thirdparty.resource.demand.ai.function.AbstractFunctionResult;
import cn.com.poc.thirdparty.resource.demand.ai.function.LargeModelFunctionEnum;
import cn.com.poc.thirdparty.resource.demand.ai.function.long_memory.AgentLongMemoryEntity;
import cn.com.poc.thirdparty.resource.demand.ai.function.long_memory.LongMemory;
import cn.com.poc.thirdparty.resource.demand.ai.function.memory_variable_writer.MemoryVariableWriter;
import cn.com.poc.thirdparty.service.ChainService;
import cn.com.poc.thirdparty.service.LLMService;
import cn.com.yict.framemax.core.exception.BusinessException;
import cn.com.yict.framemax.core.i18n.I18nMessageException;
import cn.com.yict.framemax.data.model.PagingInfo;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

import static cn.com.poc.common.constant.XLangConstant.*;

@Component
public class AgentApplicationServiceImpl implements AgentApplicationService {

    final private String TEXT_EVENT_STREAM_CHARSET_UTF_8 = "text/event-stream;charset=UTF-8";

    final private String EVENT_STREAM_PREFIX = "data: ";

    final private Logger logger = LoggerFactory.getLogger(AgentApplicationService.class);

    final private ThreadPoolExecutor executor = new ThreadPoolExecutor(16, 64, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(100));

    @Resource
    private BizKnowledgeDocumentService bizKnowledgeDocumentService;

    @Resource
    private BizAgentApplicationLargeModelListService bizAgentApplicationLargeModelListService;

    @Resource
    private BizAgentApplicationGcConfigService bizAgentApplicationGcConfigService;

    @Resource
    private BizAgentApplicationInfoService bizAgentApplicationInfoService;

    @Resource
    private BizAgentApplicationPublishService bizAgentApplicationPublishService;

    @Resource
    private DemandKnowledgeService demandKnowledgeService;

    @Resource
    private AICreateImageService aiCreateImageService;

    @Resource
    private LLMService llmService;

    @Resource
    private BizAgentApplicationMallService bizAgentApplicationMallService;

    @Resource
    private BizMemberAgentApplicationCollectService bizMemberAgentApplicationCollectService;

    @Resource
    private BizAgentApplicationDialoguesRecordService bizAgentApplicationDialoguesRecordService;

    @Resource
    private BizAgentApplicationPluginService bizAgentApplicationPluginService;

    @Resource
    private BizKnowledgeDatabaseService bizKnowledgeDatabaseService;

    @Resource
    private ChainService chainService;


    @Override
    public BizAgentApplicationInfoEntity saveOrUpdate(BizAgentApplicationInfoEntity entity) throws Exception {

        // 如果存在agentId，则判断变量结构是否有变化，如果有变化，则删除redis中的数据
        if (StringUtils.isNotBlank(entity.getAgentId())) {
            BizAgentApplicationInfoEntity infoEntity = bizAgentApplicationInfoService.getByAgentId(entity.getAgentId());
            updateStructVariable(entity.getAgentId(), infoEntity.getVariableStructure(), entity.getVariableStructure());
        }
        // 检查数据库是否存在
        if (ArrayUtils.isNotEmpty(entity.getKnowledgeDatabaseIds())) {
            Integer[] isExistIds = bizKnowledgeDatabaseService.checkIsExist(entity.getKnowledgeDatabaseIds(), entity.getMemberId());
            logger.info("agent database check exist , input:{}, exist:{}", entity.getKnowledgeDatabaseIds(), isExistIds);
            entity.setKnowledgeDatabaseIds(isExistIds);
        }


        // 保存或更新
        return StringUtils.isEmpty(entity.getAgentId()) ? bizAgentApplicationInfoService.save(entity) : bizAgentApplicationInfoService.update(entity);
    }

    @Override
    public boolean updateAndPublish(BizAgentApplicationInfoEntity bizAgentApplicationInfoEntity) throws Exception {
        UserBaseEntity userBaseEntity = BlContext.getCurrentUserNotException();
        Long userId = userBaseEntity.getUserId();
        bizAgentApplicationInfoEntity.setMemberId(userId.intValue());
        bizAgentApplicationInfoEntity.setAgentPublishStatus(AgentApplicationConstants.AGENT_PUBLISH_STATUS.PUBLISH);
        bizAgentApplicationInfoEntity.setPublishTime(new Date());
        if (null == bizAgentApplicationInfoService.update(bizAgentApplicationInfoEntity)) {
            logger.error("update and publish agent error , bizAgentApplicationInfoEntity:{}", bizAgentApplicationInfoEntity);
            throw new I18nMessageException("exception/publication.failed");
        }

        // 检查数据库是否存在
        if (ArrayUtils.isNotEmpty(bizAgentApplicationInfoEntity.getKnowledgeDatabaseIds())) {
            Integer[] isExistIds = bizKnowledgeDatabaseService.checkIsExist(bizAgentApplicationInfoEntity.getKnowledgeDatabaseIds(), bizAgentApplicationInfoEntity.getMemberId());
            logger.info("agent database check exist , input:{}, exist:{}", bizAgentApplicationInfoEntity.getKnowledgeDatabaseIds(), isExistIds);
            bizAgentApplicationInfoEntity.setKnowledgeDatabaseIds(isExistIds);
        }

        //发布应用
        BizAgentApplicationPublishEntity publishEntity = new BizAgentApplicationPublishEntity();
        BeanUtil.copyProperties(bizAgentApplicationInfoEntity, publishEntity);
        BizAgentApplicationPublishEntity oldPublishEntity = bizAgentApplicationPublishService.getByAgentId(bizAgentApplicationInfoEntity.getAgentId());
        if (oldPublishEntity != null) {
            publishEntity.setId(oldPublishEntity.getId());
            bizAgentApplicationPublishService.update(publishEntity);
        } else {
            bizAgentApplicationPublishService.save(publishEntity);
        }

        //【变量】结构改变，删除会话缓存
        List<DialogsIdsQueryByAgentIdQueryItem> items = bizAgentApplicationDialoguesRecordService.queryDialogsIds(bizAgentApplicationInfoEntity.getAgentId());
        if (CollectionUtils.isNotEmpty(items)) {
            logger.info("variables structure cache remove，items:{}", items);
            for (DialogsIdsQueryByAgentIdQueryItem item : items) {
                MemoryVariableWriter.cleanByPre(AgentApplicationTools.identifier(item.getDialogsId(), bizAgentApplicationInfoEntity.getAgentId()));
            }
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deletedAgentApplication(String agentId) throws Exception {
        bizAgentApplicationInfoService.deletedByAgentId(agentId);
        // 删除应用
        BizAgentApplicationPublishEntity publishEntity = bizAgentApplicationPublishService.getByAgentId(agentId);
        if (publishEntity != null) {
            // 删除应用市场表中的应用
            bizAgentApplicationMallService.deletedByAgentPublishId(publishEntity.getId());
            // 删除发布表中的应用
            bizAgentApplicationPublishService.deleteByAgentId(agentId);
        }
        return true;
    }

    @Override
    public AgentResultEntity callAgentApplication(String agentId, String dialogueId, String largeModel, String agentSystem, Integer[] kdIds, Integer[] databaseIds, Integer communicationTurn, Float topP, Float temperature, List<Message> messages, List<Tool> tools, FunctionCallResult functionCallResult, boolean stream, Double score, Integer topK, KnowledgeSearchTypeEnum knowledgeSearchType, KnowledgeSuperclassProblemConfig superclassProblemConfig, HttpServletResponse httpServletResponse) throws Exception {

        CompletableFuture<List<DBChainResult>> dbChainResultsFuture = CompletableFuture
                .supplyAsync(() -> database(messages, databaseIds), executor)
                .exceptionally(ex -> {
                    logger.error("database chain error", ex);
                    return (List<DBChainResult>) CollectionUtils.EMPTY_COLLECTION;
                });
        CompletableFuture<List<KnowledgeContentResult>> knowledgeResultFuture = CompletableFuture
                .supplyAsync(() -> knowledge(kdIds, messages, topK, score, knowledgeSearchType), executor)
                .exceptionally(ex -> {
                    logger.error("knowledge chain error", ex);
                    return (List<KnowledgeContentResult>) CollectionUtils.EMPTY_COLLECTION;
                });

        // 等待所有任务完成并获取结果
        CompletableFuture.allOf(dbChainResultsFuture, knowledgeResultFuture).join();
        List<DBChainResult> dbChainResults = dbChainResultsFuture.get();
        List<KnowledgeContentResult> knowledgeResult = knowledgeResultFuture.get();

        FunctionResult functionResult = functionCall(dialogueId, functionCallResult, agentId, dbChainResults, knowledgeResult);
        if (superclassProblem(superclassProblemConfig, kdIds, knowledgeResult)) {

            return sendProblemMess(stream, superclassProblemConfig, httpServletResponse);

        } else {

            String promptTemplate = buildDialogsPrompt(functionResult, agentSystem, tools.toArray(new Tool[0]), dialogueId, agentId, knowledgeResult, dbChainResults);

            Message[] messageArray = buildMessages(messages, communicationTurn, promptTemplate);

            return llmExecutorAndOutput(topP, stream, modelConvert(largeModel), messageArray, functionResult, knowledgeResult, dbChainResults, httpServletResponse);
        }
    }

    /**
     * 发送知识库超纲回答
     *
     * @param stream
     * @param superclassProblemConfig
     * @param httpServletResponse
     * @return
     * @throws IOException
     */
    private AgentResultEntity sendProblemMess(boolean stream, KnowledgeSuperclassProblemConfig superclassProblemConfig, HttpServletResponse httpServletResponse) throws IOException {
        String mess = superclassProblemConfig.getKnowledgeCustomResponse()[0];
        logger.info("触发知识库超纲回答,mess{}", mess);
        if (stream) {
            SSEUtil sseUtil = new SSEUtil(httpServletResponse);
            LargeModelDemandResult result = new LargeModelDemandResult();
            result.setCode("0");
            result.setMessage(mess);
            result.setFinish_reason("finish");
            sseUtil.send(JsonUtils.serialize(result));
            sseUtil.send("[DONE]");
            sseUtil.complete();
        }
        AgentResultEntity agentResultEntity = new AgentResultEntity();
        agentResultEntity.setMessage(mess);
        return agentResultEntity;
    }


    @Override
    public void createAgentSystem(String input, String optimizationSuggestions, HttpServletResponse httpServletResponse) throws Exception {
        BizAgentApplicationGcConfigEntity configEntity = bizAgentApplicationGcConfigService.getByConfigCode(AgentApplicationGCConfigConstants.AGENT_SYSTEM);
        if (null == configEntity || StringUtils.isBlank(configEntity.getConfigSystem())) {
            throw new I18nMessageException("exception/create.[role.instruction].configuration.does.not.exist");
        }
        Message systemMessage = new Message();
        systemMessage.setContent(configEntity.getConfigSystem());
        systemMessage.setRole(LLMRoleEnum.SYSTEM.getRole());

        String content = "标题或原角色指令\n [\"" + input + "\"]";
        if (StringUtils.isNotBlank(optimizationSuggestions)) {
            content = content + "\n 优化建议 \n [" + optimizationSuggestions + "]";
        }
        Message message = new Message();
        message.setContent(content);
        message.setRole(LLMRoleEnum.USER.getRole());
        List<Message> messages = new ArrayList<Message>() {{
            add(systemMessage);
            add(message);
        }};

        LargeModelResponse largeModelResponse = new LargeModelResponse();
        largeModelResponse.setModel(configEntity.getLargeModel());
        largeModelResponse.setMessages(messages.toArray(new Message[1]));
        largeModelResponse.setTopP(configEntity.getTopP());
        largeModelResponse.setUser("POC-CREATE-AGENT-SYSTEM");

        BufferedReader bufferedReader = llmService.chatChunk(largeModelResponse);
        textOutputStream(httpServletResponse, bufferedReader);
    }

    @Override
    public String createPreamble(String agentTitle, String agentDesc, String agentSystem) {
        BizAgentApplicationGcConfigEntity configEntity = bizAgentApplicationGcConfigService.getByConfigCode(AgentApplicationGCConfigConstants.AGENT_PREAMBLE);
        if (null == configEntity || StringUtils.isBlank(configEntity.getConfigSystem())) {
            throw new I18nMessageException("exception/create.[opening.statement].configuration.does.not.exist");
        }

        List<MultiContent> multiContents = new ArrayList<>();
        multiContents.add(new MultiContent() {{
            String configSystem = configEntity.getConfigSystem();
            configSystem = buildPreambleConfigSystem(configSystem, agentTitle, agentDesc, agentSystem);

            setText(configSystem);
            setType("text");
        }});
        Message message = new Message();
        message.setContent(multiContents);
        message.setRole(LLMRoleEnum.USER.getRole());
        List<Message> messages = new ArrayList<Message>() {{
            add(message);
        }};

        LargeModelResponse largeModelResponse = new LargeModelResponse();
        largeModelResponse.setModel(configEntity.getLargeModel());
        largeModelResponse.setMessages(messages.toArray(new Message[1]));
        largeModelResponse.setTopP(configEntity.getTopP());
        largeModelResponse.setUser("POC-CREATE-PREAMBLE");

        LargeModelDemandResult largeModelDemandResult = llmService.chat(largeModelResponse);
        if (largeModelDemandResult == null || !"0".equals(largeModelDemandResult.getCode())) {
            logger.error("create preamble error, largeModelResponse:{}", largeModelResponse);
            throw new I18nMessageException("exception/failed.to.create.[opening.statement]");
        }

        return largeModelDemandResult.getMessage();
    }

    @Override
    public List<String> createFeaturedQuestions(String agentTitle, String agentDesc) {
        BizAgentApplicationGcConfigEntity configEntity = bizAgentApplicationGcConfigService.getByConfigCode(AgentApplicationGCConfigConstants.AGENT_FEATURED_QUESTIONS);
        if (null == configEntity || StringUtils.isBlank(configEntity.getConfigSystem())) {
            throw new I18nMessageException("exception/create.[opening.statement].configuration.does.not.exist");
        }

        List<MultiContent> multiContents = new ArrayList<>();
        multiContents.add(new MultiContent() {{
            String configSystem = configEntity.getConfigSystem();
            configSystem = configSystem.replace("${agent_title}", StringUtils.isNotBlank(agentTitle) ? agentTitle : StringUtils.EMPTY);
            configSystem = configSystem.replace("${agent_desc}", StringUtils.isNotBlank(agentDesc) ? agentDesc : StringUtils.EMPTY);
            setText(configSystem);
            setType("text");
        }});
        Message message = new Message();
        message.setContent(multiContents);
        message.setRole(LLMRoleEnum.USER.getRole());
        List<Message> messages = new ArrayList<Message>() {{
            add(message);
        }};

        LargeModelResponse largeModelResponse = new LargeModelResponse();
        largeModelResponse.setModel(configEntity.getLargeModel());
        largeModelResponse.setMessages(messages.toArray(new Message[1]));
        largeModelResponse.setTopP(configEntity.getTopP());
        largeModelResponse.setUser("POC-FEATURED-QUESTIONS");

        LargeModelDemandResult largeModelDemandResult = llmService.chat(largeModelResponse);
        String res = largeModelDemandResult.getMessage();
        int start = res.lastIndexOf("[");
        int end = res.lastIndexOf("]");
        return JsonUtils.deSerialize(res.substring(start, end + 1), new TypeReference<List<String>>() {
        }.getType());
    }

    @Override
    public String createAgentIcon(String agentTitle, String agentDesc) throws Exception {

        BizAgentApplicationGcConfigEntity configEntity = bizAgentApplicationGcConfigService.getByConfigCode(AgentApplicationGCConfigConstants.AGENT_ICON);
        if (null == configEntity || StringUtils.isBlank(configEntity.getConfigSystem())) {
            throw new I18nMessageException("exception/the.configuration.for.creating.[avatar.prompt].does.not.exist.please.contact.the.administrator");
        }

        List<MultiContent> multiContents = new ArrayList<>();
        multiContents.add(new MultiContent() {{
            String configSystem = configEntity.getConfigSystem();
            configSystem = configSystem.replace("${agent_title}", StringUtils.isNotBlank(agentTitle) ? agentTitle : StringUtils.EMPTY);
            configSystem = configSystem.replace("${agent_desc}", StringUtils.isNotBlank(agentDesc) ? agentDesc : StringUtils.EMPTY);
            setText(configSystem);
            setType("text");
        }});
        Message message = new Message();
        message.setContent(multiContents);
        message.setRole(LLMRoleEnum.USER.getRole());
        List<Message> messages = new ArrayList<Message>() {{
            add(message);
        }};

        LargeModelResponse largeModelResponse = new LargeModelResponse();
        largeModelResponse.setModel(configEntity.getLargeModel());
        largeModelResponse.setMessages(messages.toArray(new Message[1]));
        largeModelResponse.setTopP(configEntity.getTopP());
        largeModelResponse.setUser("POC-CREATE-AGENT-PROMPT");
        LargeModelDemandResult largeModelDemandResult = llmService.chat(largeModelResponse);

        if (largeModelDemandResult == null || !"0".equals(largeModelDemandResult.getCode()) || StringUtils.isEmpty(largeModelDemandResult.getMessage())) {
            logger.error("create agent icon prompt error, largeModelResponse:{}", largeModelResponse);
            throw new I18nMessageException("exception/failed.to.create.[avatar].please.try.again.later");
        }

        logger.info("create agent application icon prompt, result:{}", largeModelDemandResult);

        String createIconPrompt = largeModelDemandResult.getMessage();
        BaiduAISailsText2ImageRequest baiduAISailsText2ImageRequest = new BaiduAISailsText2ImageRequest();
        baiduAISailsText2ImageRequest.setPrompt(createIconPrompt);
        baiduAISailsText2ImageRequest.setNegativePrompt(null);
        baiduAISailsText2ImageRequest.setSize("768x768");
        baiduAISailsText2ImageRequest.setN(1);
        baiduAISailsText2ImageRequest.setSteps(15);
        baiduAISailsText2ImageRequest.setSamplerIndex("Euler a");
        baiduAISailsText2ImageRequest.setSeed(null);
        baiduAISailsText2ImageRequest.setCfgCcale(null);
        baiduAISailsText2ImageRequest.setStyle("Base");
        baiduAISailsText2ImageRequest.setUserId("AGENT-APPLICATION-ICON-CREATE");
        baiduAISailsText2ImageRequest.setAcctId(null);

        BaiduAISailsText2ImageResult baiduAISailsText2ImageResult = aiCreateImageService.executeSailsText2Image(baiduAISailsText2ImageRequest);
        if (baiduAISailsText2ImageResult == null || CollectionUtils.isEmpty(baiduAISailsText2ImageResult.getData()) || StringUtils.isEmpty(baiduAISailsText2ImageResult.getData().get(0).getUrl())) {
            logger.error("create agent icon error, baiduAISailsText2ImageRequest:{} ", baiduAISailsText2ImageRequest);
            throw new I18nMessageException("exception/failed.to.create.[avatar].please.try.again.later");
        }
        return baiduAISailsText2ImageResult.getData().get(0).getUrl();
    }

    @Override
    public CreateAgentTitleAndDescEntity createAgentTitleAndDesc(String input) {
        BizAgentApplicationGcConfigEntity configEntity = bizAgentApplicationGcConfigService.getByConfigCode(AgentApplicationGCConfigConstants.AGENT_INFO);
        if (null == configEntity || StringUtils.isBlank(configEntity.getConfigSystem())) {
            throw new I18nMessageException("exception/create.[application.information].configuration.does.not.exist.please.contact.the.administrator");
        }
        List<MultiContent> multiContents = new ArrayList<>();
        multiContents.add(new MultiContent() {{
            String configSystem = configEntity.getConfigSystem();
            configSystem = configSystem.replace("${input}", StringUtils.isNotBlank(input) ? input : StringUtils.EMPTY);
            setText(configSystem);
            setType("text");
        }});
        Message message = new Message();
        message.setContent(multiContents);
        message.setRole(LLMRoleEnum.USER.getRole());
        List<Message> messages = new ArrayList<Message>() {{
            add(message);
        }};

        LargeModelResponse largeModelResponse = new LargeModelResponse();
        largeModelResponse.setModel(configEntity.getLargeModel());
        largeModelResponse.setMessages(messages.toArray(new Message[1]));
        largeModelResponse.setTopP(configEntity.getTopP());
        largeModelResponse.setUser("POC-CREATE-AGENT-INFO");
        LargeModelDemandResult largeModelDemandResult = llmService.chat(largeModelResponse);

        if (largeModelDemandResult == null || !"0".equals(largeModelDemandResult.getCode()) || StringUtils.isEmpty(largeModelDemandResult.getMessage())) {
            logger.error("create agent icon title And desc error, largeModelResponse:{}", largeModelResponse);
            throw new I18nMessageException("exception/failed.to.create.[application.information].please.try.again.later");
        }
        logger.info("create agent application icon title And desc, response:{},result:{}", largeModelResponse, largeModelDemandResult);
        String res = largeModelDemandResult.getMessage();
        int start = res.lastIndexOf("{");
        int end = res.lastIndexOf("}");

        return JsonUtils.deSerialize(res.substring(start, end + 1), CreateAgentTitleAndDescEntity.class);
    }

    @Override
    public boolean unPublish(String agentId) throws Exception {
        bizAgentApplicationPublishService.deleteByAgentId(agentId);
        bizAgentApplicationInfoService.unPublish(agentId);
        return true;
    }

    @Override
    public void collectOrCancelAgentInMall(Integer id, String agentId) throws Exception {
        UserBaseEntity userBaseEntity = BlContext.getCurrentUserNotException();
        if (userBaseEntity == null) {
            throw new I18nMessageException("exception/user.not.login");
        }

        BizAgentApplicationMallEntity mallEntity = bizAgentApplicationMallService.get(id);
        if (mallEntity == null) {
            throw new I18nMessageException("exception/application.does.not.exist");
        }

        // 先判断当前应用被当前用户收藏了吗
        BizMemberAgentApplicationCollectEntity collectEntity = new BizMemberAgentApplicationCollectEntity();
        collectEntity.setAgentId(agentId);
        collectEntity.setMemberId(userBaseEntity.getUserId().intValue());
        List<BizMemberAgentApplicationCollectEntity> collectEntities = bizMemberAgentApplicationCollectService.findByExample(collectEntity, new PagingInfo());
        if (collectEntities.isEmpty() || CommonConstant.IsDeleted.N.equals(collectEntities.get(0).getIsCollect())) {   //如果没被收藏
            // 收藏该应用
            // 说明从来没收藏过
            if (collectEntities.isEmpty()) {
                // 在用户收藏表中添加数据
                BizMemberAgentApplicationCollectEntity entity = new BizMemberAgentApplicationCollectEntity();
                entity.setIsCollect(CommonConstant.IsDeleted.Y);
                entity.setMemberId(userBaseEntity.getUserId().intValue());
                entity.setAgentId(agentId);
                bizMemberAgentApplicationCollectService.save(entity);
            } else {  // 说明之前收藏过，则只需要做个修改
                collectEntity.setIsCollect(CommonConstant.IsDeleted.Y);
                bizMemberAgentApplicationCollectService.update(collectEntity);
            }
            // 在应用广场的应用中 添加收藏数
            mallEntity.setCollectNumber(mallEntity.getCollectNumber() + 1);
        } else {
            // 取消收藏该应用
            collectEntities.get(0).setIsCollect(CommonConstant.IsDeleted.N);
            bizMemberAgentApplicationCollectService.update(collectEntity);
            // 在应用广场的应用中 取消收藏数
            mallEntity.setCollectNumber(mallEntity.getCollectNumber() - 1);
        }
        bizAgentApplicationMallService.update(mallEntity);
    }

    @Override
    public void collectOrCancelAgentInPerson(String agentId) throws Exception {
        UserBaseEntity userBaseEntity = BlContext.getCurrentUserNotException();
        if (userBaseEntity == null) {
            throw new I18nMessageException("exception/user.not.login");
        }

        // 先判断当前应用被当前用户收藏了吗
        BizMemberAgentApplicationCollectEntity collectEntity = new BizMemberAgentApplicationCollectEntity();
        collectEntity.setAgentId(agentId);
        collectEntity.setMemberId(userBaseEntity.getUserId().intValue());
        List<BizMemberAgentApplicationCollectEntity> collectEntities = bizMemberAgentApplicationCollectService.findByExample(collectEntity, new PagingInfo());
        Integer isCollect = 0;
        if (collectEntities.isEmpty() || CommonConstant.IsDeleted.N.equals(collectEntities.get(0).getIsCollect())) {   //如果没被收藏
            // 收藏该应用
            // 说明从来没收藏过
            if (collectEntities.isEmpty()) {
                // 在用户收藏表中添加数据
                BizMemberAgentApplicationCollectEntity entity = new BizMemberAgentApplicationCollectEntity();
                entity.setIsCollect(CommonConstant.IsDeleted.Y);
                entity.setMemberId(userBaseEntity.getUserId().intValue());
                entity.setAgentId(agentId);
                bizMemberAgentApplicationCollectService.save(entity);
            } else {  // 说明之前收藏过，则只需要做个修改
                collectEntities.get(0).setIsCollect(CommonConstant.IsDeleted.Y);
                bizMemberAgentApplicationCollectService.update(collectEntities.get(0));
            }
            isCollect = 1;
        } else {
            // 取消收藏该应用
            collectEntities.get(0).setIsCollect(CommonConstant.IsDeleted.N);
            bizMemberAgentApplicationCollectService.update(collectEntities.get(0));
            isCollect = -1;
        }

        BizAgentApplicationPublishEntity publishEntity = bizAgentApplicationPublishService.getByAgentId(agentId);
        if (publishEntity == null) {
            logger.warn("应用尚未发布,agentId:{}", agentId);
            return;
        }
        Integer id = publishEntity.getId();
        BizAgentApplicationMallEntity mallEntity = bizAgentApplicationMallService.getByAgentPublishId(id);
        if (mallEntity == null || CommonConstant.YOrN.N.equals(mallEntity.getIsSale())) {
            logger.warn("应用尚未上架,agentId:{}", agentId);
            return;
        }
        mallEntity.setCollectNumber(mallEntity.getCollectNumber() + isCollect);
        bizAgentApplicationMallService.update(mallEntity);
    }


    @Override
    public boolean hasPublishAgentPermission(String agentId, Long memberId) {
        BizAgentApplicationPublishEntity publishEntity = bizAgentApplicationPublishService.getByAgentId(agentId);
        if (publishEntity != null && publishEntity.getMemberId().equals(memberId.intValue())) {
            return true;
        }
        return false;
    }

    /**
     * 编辑器编辑功能
     *
     * @param agentGcConfigCode
     * @param articleContent
     * @param editorRequired
     * @param httpServletResponse
     * @return
     * @throws Exception
     */
    @Override
    public String editorFunction(String agentGcConfigCode, String articleContent, String editorRequired, HttpServletResponse httpServletResponse) throws Exception {
        if (StringUtils.isBlank(agentGcConfigCode)) {
            throw new I18nMessageException("exception/agentGcConfigCode.does.not.exist");
        }

        BizAgentApplicationGcConfigEntity configEntity = bizAgentApplicationGcConfigService.getByConfigCode(agentGcConfigCode);
        if (null == configEntity || StringUtils.isBlank(configEntity.getConfigSystem())) {
            throw new I18nMessageException("exception/create.[opening.statement].configuration.does.not.exist");
        }


        String configSystem = configEntity.getConfigSystem();
        if (StringUtils.isNotBlank(configSystem)) {
            configSystem = configSystem.replace("{" + AiGcTemplateConstant.ContentPlaceholder.EXAMPLE + "1}", articleContent);
            configSystem = configSystem.replace("{" + AiGcTemplateConstant.ContentPlaceholder.EXAMPLE + "2}", editorRequired);
        }

        Message message = new Message();
        message.setContent(configSystem);
        message.setRole(LLMRoleEnum.USER.getRole());
        List<Message> messages = new ArrayList<Message>() {{
            add(message);
        }};

        LargeModelResponse largeModelResponse = new LargeModelResponse();
        largeModelResponse.setModel(configEntity.getLargeModel());
        largeModelResponse.setMessages(messages.toArray(new Message[1]));
        largeModelResponse.setTopP(configEntity.getTopP());
        largeModelResponse.setUser("POC-CREATE-PREAMBLE");

        BufferedReader bufferedReader = llmService.chatChunk(largeModelResponse);

        SSEUtil sseUtil = new SSEUtil(httpServletResponse);
        textOutputStream(sseUtil, bufferedReader, null);
        return null;
    }

    /**
     * 执行LLM，并输出结果
     *
     * @param topP                topP
     * @param stream              是否流式输出
     * @param model               模型
     * @param messageArray        消息
     * @param functionResult      函数结果
     * @param knowledgeResult     知识库结果
     * @param dbChainResults      数据库链结果
     * @param httpServletResponse 响应
     * @return 输出结果
     * @throws Exception
     */
    private AgentResultEntity llmExecutorAndOutput(Float topP, boolean stream, String model, Message[] messageArray, FunctionResult functionResult, List<KnowledgeContentResult> knowledgeResult, List<DBChainResult> dbChainResults, HttpServletResponse httpServletResponse) throws Exception {
        if (stream) {
            SSEUtil sseUtil = new SSEUtil(httpServletResponse);
            ToolFunction toolFunction = null;
            if (CollectionUtils.isNotEmpty(dbChainResults)) {
                LargeModelDemandResult result = new LargeModelDemandResult();
                result.setCode("0");
                result.setFunction(null);
                result.setDbChainResult(dbChainResults);
                result.setKnowledgeContentResult(null);
                sseUtil.send(JsonUtils.serialize(result));
            }
            if (CollectionUtils.isNotEmpty(knowledgeResult)) {
                LargeModelDemandResult result = new LargeModelDemandResult();
                result.setCode("0");
                result.setFunction(null);
                result.setDbChainResult(null);
                result.setKnowledgeContentResult(knowledgeResult);
                sseUtil.send(JsonUtils.serialize(result));
            }
            if (ObjectUtil.isNotNull(functionResult) && StringUtils.isNotBlank(functionResult.getFunctionName())) {
                LargeModelDemandResult result = new LargeModelDemandResult();
                result.setCode("0");
                toolFunction = functionResultConvertToolFunction(functionResult);
                result.setFunction(toolFunction);
                result.setDbChainResult(null);
                result.setKnowledgeContentResult(null);
                sseUtil.send(JsonUtils.serialize(result));
            }
            BufferedReader bufferedReader = invokeLLMStream(model, messageArray, topP);
            return textOutputStream(sseUtil, bufferedReader, toolFunction);
        } else {
            LargeModelDemandResult largeModelDemandResult = invokeLLM(model, messageArray, topP);
            if (ObjectUtil.isNotNull(functionResult) && StringUtils.isNotBlank(functionResult.getFunctionName())) {
                ToolFunction toolFunction = functionResultConvertToolFunction(functionResult);
                largeModelDemandResult.setFunction(toolFunction);
            }
            return textOutput(httpServletResponse, largeModelDemandResult);
        }
    }


    /**
     * 构建应用信息提示词
     *
     * @param configSystem
     * @param agentTitle
     * @param agentDesc
     * @param agentSystem
     * @return
     */
    private String buildPreambleConfigSystem(String configSystem, String agentTitle, String agentDesc, String agentSystem) {
        //若 name  desc    prompt  都为空，传入默认参数  name  入参 智能问答机器人   desc  随时为你解答问题
        if (StringUtils.isBlank(agentSystem) && StringUtils.isBlank(agentTitle) && StringUtils.isBlank(agentDesc)) {
            return configSystem.replace("${agent_title}", "智能问答机器人").replace("${agent_desc}", " 随时为你解答问题");
        }
        //若 name  desc   其中一项不为空则入参  不传入prompt
        if (StringUtils.isNotBlank(agentTitle) || (StringUtils.isNotBlank(agentDesc))) {
            return configSystem.replace("${agent_title}", StringUtils.isNotBlank(agentTitle) ? agentTitle : StringUtils.EMPTY).replace("${agent_desc}", StringUtils.isNotBlank(agentDesc) ? agentDesc : StringUtils.EMPTY);
        }

        // 若 name  desc 都空   prompt 有内容，则把prompt 传入desc
        if (StringUtils.isNotBlank(agentSystem)) {
            return configSystem.replace("${agent_desc}", agentSystem).replace("${agent_title}", "智能问答机器人");
        }
        return configSystem;
    }


    /**
     * 构建对话提示词
     *
     * @param functionResult          函数结果
     * @param agentSystem             应用角色指令
     * @param tools                   组件
     * @param dialogueId              对话标识符
     * @param knowledgeContentResults 知识库结果
     * @param dbChainResults          数据库链结果
     * @return
     */
    private String buildDialogsPrompt(FunctionResult functionResult, String agentSystem, Tool[] tools, String dialogueId, String agentId, List<KnowledgeContentResult> knowledgeContentResults, List<DBChainResult> dbChainResults) {
        String promptTemplate = bizAgentApplicationGcConfigService.getByConfigCode(AgentApplicationGCConfigConstants.AGENT_BASE_SYSTEM).getConfigSystem();
        // 系统语言
        String language = "";
        if (BlContext.getCurrentLocaleLanguageToLowerCase().equals(ZH_TW)) {
            language = "中文繁体";
        } else if (BlContext.getCurrentLocaleLanguageToLowerCase().equals(ZH_CN)) {
            language = "中文简体";
        } else {
            language = "English";
        }
        promptTemplate = promptTemplate.replace("${language}", language);
        // 应用角色指令
        promptTemplate = promptTemplate.replace("${agentSystem}", StringUtils.isNotBlank(agentSystem) ? agentSystem : StringUtils.EMPTY);
        // 调用知识库
        promptTemplate = buildKnowledgePrompt(knowledgeContentResults, promptTemplate);
        //调用数据库
        promptTemplate = buildDBChainPrompt(dbChainResults, promptTemplate);
        // 记忆
        promptTemplate = buildMemoryPrompt(promptTemplate, tools, dialogueId, agentId);
        // 函数调用
        promptTemplate = buildFunctionPrompt(functionResult, promptTemplate);
        return promptTemplate;
    }

    private String buildDBChainPrompt(List<DBChainResult> dbChainResults, String promptTemplate) {
        StringBuilder dbChainPromptBuilder = new StringBuilder("");
        if (CollectionUtils.isNotEmpty(dbChainResults)) {
            for (int i = 1; i <= dbChainResults.size(); i++) {
                dbChainPromptBuilder.append("### DBChain Result ").append(i).append(":").append(StringUtils.LF).append(dbChainResults.get(i - 1).getResult()).append(StringUtils.LF);
            }
        }
        promptTemplate = promptTemplate.replace("${databaseResult}", dbChainPromptBuilder.toString());
        return promptTemplate;
    }

    /**
     * 构建知识库提示词
     *
     * @param knowledgeContentResults
     * @return
     */
    private String buildKnowledgePrompt(List<KnowledgeContentResult> knowledgeContentResults, String promptTemplate) {
        StringBuilder knowledgePromptBuilder = new StringBuilder("");
        if (CollectionUtils.isNotEmpty(knowledgeContentResults)) {
            for (int i = 1; i <= knowledgeContentResults.size(); i++) {
                knowledgePromptBuilder.append("### Chunk ").append(i).append(":").append(StringUtils.LF).append(knowledgeContentResults.get(i - 1).getContent()).append(StringUtils.LF);
            }
        }
        promptTemplate = promptTemplate.replace("${knowledgeResults}", knowledgePromptBuilder.toString());
        return promptTemplate;
    }

    /**
     * 构造记忆体提示词
     *
     * @param promptTemplate
     * @param tools
     * @param dialogueId
     * @param agentId
     * @return
     */
    private String buildMemoryPrompt(String promptTemplate, Tool[] tools, String dialogueId, String agentId) {
        String longMemoryContent = StringUtils.EMPTY;
        String valueMemoryContent = StringUtils.EMPTY;
        if (ArrayUtils.isNotEmpty(tools)) {
            for (Tool tool : tools) {
                String name = tool.getFunction().getName();
                // 长期记忆
                if (LargeModelFunctionEnum.set_long_memory.name().equals(name)) {
                    List<AgentLongMemoryEntity> longMemoryEntities = LongMemory.get(AgentApplicationTools.identifier(dialogueId, agentId));
                    if (CollectionUtils.isNotEmpty(longMemoryEntities)) {
                        StringBuilder stringBuilder = new StringBuilder("");
                        for (AgentLongMemoryEntity agentLongMemoryEntity : longMemoryEntities) {
                            stringBuilder.append("Time").append(":").append(agentLongMemoryEntity.getTimestamp()).append(StringUtils.SPACE).append("Content").append(":").append(agentLongMemoryEntity.getContent()).append(StringUtils.LF);
                        }
                        longMemoryContent = stringBuilder.toString();
                    }
                }

                // 变量记忆
                if (LargeModelFunctionEnum.memory_variable_writer.name().equals(name)) {
                    Map<Object, Object> map = MemoryVariableWriter.get(AgentApplicationTools.identifier(dialogueId, agentId));
                    StringBuilder stringBuilder = new StringBuilder("");
                    if (MapUtils.isNotEmpty(map)) {
                        Set<Object> keySet = map.keySet();
                        for (Object key : keySet) {
                            stringBuilder.append(key.toString()).append(":").append(map.get(key)).append(StringUtils.LF);
                        }
                    }
                    valueMemoryContent = stringBuilder.toString();
                }
            }
        }
        return promptTemplate.replace("${longMemoryResult}", longMemoryContent).replace("${valueMemoryResult}", valueMemoryContent);
    }

    /**
     * 构建函数调用提示词
     *
     * @param functionResult
     * @param promptTemplate
     * @return
     */
    private String buildFunctionPrompt(FunctionResult functionResult, String promptTemplate) {
        if (functionResult != null) {
            promptTemplate = promptTemplate.replace("${functionName}", StringUtils.isNotBlank(functionResult.getFunctionName()) ? functionResult.getFunctionName() : StringUtils.EMPTY).replace("${functionArg}", StringUtils.isNotBlank(functionResult.getFunctionArg()) ? functionResult.getFunctionArg() : StringUtils.EMPTY).replace("${functionDesc}", StringUtils.isNotBlank(functionResult.getFunctionDesc()) ? functionResult.getFunctionDesc() : StringUtils.EMPTY).replace("${functionResult}", StringUtils.isNotBlank(functionResult.getPromptContent()) ? functionResult.getPromptContent() : StringUtils.EMPTY);
        }
        return promptTemplate;
    }

    /**
     * * 调用llm-流
     *
     * @param largeModel
     * @param messageArray
     * @param topP
     * @return
     * @throws Exception
     */
    private BufferedReader invokeLLMStream(String largeModel, Message[] messageArray, Float topP) throws Exception {
        LargeModelResponse largeModelResponse = new LargeModelResponse();
        largeModelResponse.setModel(largeModel);
        largeModelResponse.setMessages(messageArray);
        largeModelResponse.setTopP(topP);
        largeModelResponse.setStream(true);
        largeModelResponse.setUser("POE");
        return llmService.chatChunk(largeModelResponse);
    }


    /**
     * * 调用llm-非流
     *
     * @param largeModel
     * @param messageArray
     * @param topP
     * @return
     * @throws Exception
     */
    private LargeModelDemandResult invokeLLM(String largeModel, Message[] messageArray, Float topP) throws Exception {
        LargeModelResponse largeModelResponse = new LargeModelResponse();
        largeModelResponse.setModel(largeModel);
        largeModelResponse.setMessages(messageArray);
        largeModelResponse.setTopP(topP);
        largeModelResponse.setStream(false);
        largeModelResponse.setUser("POE");
        return llmService.chat(largeModelResponse);
    }

    /**
     * 文本输出结果
     *
     * @param httpServletResponse
     * @throws IOException
     */
    private AgentResultEntity textOutput(HttpServletResponse httpServletResponse, LargeModelDemandResult largeModelDemandResult) throws IOException {
        PrintWriter writer = httpServletResponse.getWriter();
        writer.write(JsonUtils.serialize(largeModelDemandResult));
        writer.flush();
        writer.close();
        AgentResultEntity agentResultEntity = new AgentResultEntity();
        agentResultEntity.setMessage(largeModelDemandResult.getMessage());
        agentResultEntity.setReasoningContent(largeModelDemandResult.getReasoningContent());
        agentResultEntity.setFunction(largeModelDemandResult.getFunction());
        return agentResultEntity;
    }

    /**
     * 文本输出结果
     *
     * @param sseUtil
     * @param bufferedReader
     * @throws IOException
     */
    private AgentResultEntity textOutputStream(SSEUtil sseUtil, BufferedReader bufferedReader, ToolFunction toolFunction) {
        String res = "";
        StringBuilder output = new StringBuilder();
        StringBuilder reasoningContent = new StringBuilder();
        try {
            while ((res = bufferedReader.readLine()) != null) {
                if (StringUtils.isEmpty(res)) {
                    continue;
                }
                res = StringUtils.replace(res, EVENT_STREAM_PREFIX, StringUtils.EMPTY);
                LargeModelDemandResult result = JsonUtils.deSerialize(res, LargeModelDemandResult.class);
                if (!"0".equals(result.getCode())) {
                    logger.error("LLM Error,code:{}", result.getCode());
                    I18nMessageException ex = new I18nMessageException("exception/call.failure");
                    result.setMessage(ex.getMessage());
                    sseUtil.send(JsonUtils.serialize(result));
                    sseUtil.send("[DONE]");
                    sseUtil.complete();
                    throw ex;
                }
                result.setFunction(null);
                result.setDbChainResult(null);
                result.setKnowledgeContentResult(null);
                sseUtil.send(JsonUtils.serialize(result));
                if (StringUtils.isNotEmpty(result.getMessage())) {
                    output.append(result.getMessage());
                }
                if (StringUtils.isNotEmpty(result.getReasoningContent())) {
                    reasoningContent.append(result.getReasoningContent());
                }
            }
            bufferedReader.close();
            // 关闭资源
            sseUtil.send("[DONE]");
            sseUtil.complete();
        } catch (IOException e) {
            logger.error("连接断开,code:{}", e.getMessage());
        } finally {
            sseUtil.complete();
            AgentResultEntity agentResultEntity = new AgentResultEntity();
            agentResultEntity.setMessage(output.toString());
            agentResultEntity.setReasoningContent(reasoningContent.toString());
            agentResultEntity.setFunction(toolFunction);
            return agentResultEntity;
        }
    }

    /**
     * 文本输出结果
     *
     * @param httpServletResponse
     * @param bufferedReader
     * @throws IOException
     */
    private AgentResultEntity textOutputStream(HttpServletResponse httpServletResponse, BufferedReader bufferedReader) throws IOException {
        String res = "";
        httpServletResponse.setContentType(TEXT_EVENT_STREAM_CHARSET_UTF_8);
        PrintWriter writer = httpServletResponse.getWriter();
        StringBuilder output = new StringBuilder();
        StringBuilder reasoningContent = new StringBuilder();
        while ((res = bufferedReader.readLine()) != null) {
            if (StringUtils.isEmpty(res)) {
                continue;
            }
            res = StringUtils.replace(res, EVENT_STREAM_PREFIX, StringUtils.EMPTY);
            LargeModelDemandResult result = JsonUtils.deSerialize(res, LargeModelDemandResult.class);
            if (!"0".equals(result.getCode())) {
                logger.error("LLM Error,code:{}", result.getCode());
                I18nMessageException ex = new I18nMessageException("exception/call.failure");
                result.setMessage(ex.getMessage());
                writer.write(EVENT_STREAM_PREFIX + JsonUtils.serialize(result) + "\n\n");
                writer.write(EVENT_STREAM_PREFIX + "[DONE]\n\n");
                writer.flush();
                writer.close();
                throw ex;
            }
            if (StringUtils.isNotEmpty(result.getMessage())) {
                output.append(result.getMessage());
            }
            if (StringUtils.isNotEmpty(result.getReasoningContent())) {
                reasoningContent.append(result.getReasoningContent());
            }
            writer.write(EVENT_STREAM_PREFIX + res + "\n\n");
            writer.flush();
        }
        // 关闭资源
        writer.write(EVENT_STREAM_PREFIX + "[DONE]\n\n");
        writer.close();
        bufferedReader.close();
        AgentResultEntity agentResultEntity = new AgentResultEntity();
        agentResultEntity.setMessage(output.toString());
        agentResultEntity.setReasoningContent(reasoningContent.toString());
        return agentResultEntity;
    }

    private ToolFunction functionResultConvertToolFunction(FunctionResult functionResult) {
        ToolFunction toolFunction = new ToolFunction();
        BizAgentApplicationPluginEntity bizAgentApplicationPluginEntity = bizAgentApplicationPluginService.getInfoByPluginId(functionResult.getFunctionName());
        if (bizAgentApplicationPluginEntity != null && !bizAgentApplicationPluginEntity.getClassification().equals("system")) {
            String lang = BlContext.getCurrentLocaleLanguageToLowerCase();
            switch (lang) {
                case ZH_CN:
                    toolFunction.setName(bizAgentApplicationPluginEntity.getZhCnTitle());
                    break;
                case ZH_TW:
                    toolFunction.setName(bizAgentApplicationPluginEntity.getZhTwTitle());
                    break;
                case EN:
                    toolFunction.setName(bizAgentApplicationPluginEntity.getEnTitle());
                    break;
            }
            toolFunction.setDisplayFormat(bizAgentApplicationPluginEntity.getDisplayFormat());
        }
        toolFunction.setArguments(functionResult.getFunctionArg());
        String functionResultStr = functionResult.getFunctionResult() instanceof String ? String.valueOf(functionResult.getFunctionResult()) : JsonUtils.serialize(functionResult.getFunctionResult());
        toolFunction.setResult(functionResultStr);
        return toolFunction;
    }

    /**
     * 构建消息【大模型参数】
     *
     * @param messages
     * @param communicationTurn
     * @param promptTemplate
     * @return
     */
    private Message[] buildMessages(List<Message> messages, Integer communicationTurn, String promptTemplate) {
        int messLength = messages.size() - 1;
        int skip = communicationTurn * 2;
        if (skip < messLength) {
            messages = messages.subList(messLength - skip, messages.size());
        }

        if (StringUtils.isNotBlank(promptTemplate)) {
            Message systemMessage = new Message();
            systemMessage.setRole(AgentApplicationDialoguesRecordConstants.ROLE.SYSTEM);
            systemMessage.setContent(promptTemplate);
            messages.add(0, systemMessage);
        }
        // 转换消息体
        Message[] messageArray = new Message[messages.size()];
        int index = 0;
        for (Message message : messages) {
            if (message.getContent() instanceof List) {
                List<HashMap<String, Object>> content = (List<HashMap<String, Object>>) message.getContent();
                HashMap<String, Object> map = content.get(0);
                if (map.containsKey("type") && map.get("type").equals("text") && map.containsKey("text")) {
                    message.setContent(map.get("text").toString());
                }
            }
            messageArray[index++] = message;
        }
        return messageArray;
    }


    /**
     * 获取模型
     *
     * @param largeModel 模型名称
     * @return
     */
    private String modelConvert(String largeModel) {
        BizAgentApplicationLargeModelListEntity largeModelEntity = bizAgentApplicationLargeModelListService.findByModelNickName(largeModel);
        if (largeModelEntity == null) {
            throw new BusinessException("模型不存在");
        }
        return largeModelEntity.getModelName();
    }

    /**
     * 判断是否需要FunctionCall
     *
     * @param dialogueId         对话id
     * @param functionCallResult 函数调用结果
     * @param agentId            应用id
     */
    private FunctionResult functionCall(String dialogueId, FunctionCallResult functionCallResult, String agentId, List<DBChainResult> dbChainResults, List<KnowledgeContentResult> knowledgeContentResults) {
        FunctionResult result = new FunctionResult();
        if (functionCallResult != null && functionCallResult.isNeed()) {
            // 执行函数返回结果
            LargeModelFunctionEnum functionEnum = LargeModelFunctionEnum.valueOf(functionCallResult.getFunctionCall().getName());
            AbstractFunctionResult abstractFunctionResult = functionEnum.getFunction().doFunction(functionCallResult.getFunctionCall().getArguments(), AgentApplicationTools.identifier(dialogueId, agentId), dbChainResults, knowledgeContentResults);
            if (ObjectUtil.isNull(abstractFunctionResult) || StringUtils.isBlank(abstractFunctionResult.getPromptContent())) {
                throw new BusinessException("插件执行失败");
            }
            //构造返回结果
            result.setFunctionName(functionCallResult.getFunctionCall().getName());
            result.setFunctionArg(functionCallResult.getFunctionCall().getArguments());
            result.setFunctionDesc(functionEnum.getFunction().getDesc());
            result.setPromptContent(abstractFunctionResult.getPromptContent());
            result.setFunctionResult(abstractFunctionResult.getFunctionResult());
        }
        return result;
    }

    private List<KnowledgeContentResult> knowledge(Integer[] kdIds, List<Message> messages, Integer topK, Double score, KnowledgeSearchTypeEnum searchTypeEnum) {
        List<KnowledgeContentResult> knowledgeContentResults = new ArrayList<>();
        if (ArrayUtils.isEmpty(kdIds)) {
            return knowledgeContentResults;
        }
        List<String> knowledgeIds = new ArrayList<>();
        for (Integer kdId : kdIds) {
            BizKnowledgeDocumentEntity knowledgeDocumentEntity = bizKnowledgeDocumentService.get(kdId);
            // 筛选训练完成的文档，否则跳过该文档
            if (null == knowledgeDocumentEntity && KnowledgeConstant.TrainStatus.COMPLETE.equals(knowledgeDocumentEntity.getTrainStatus())) {
                continue;
            }
            knowledgeIds.add(knowledgeDocumentEntity.getKnowledgeId());
        }
        String query = getMessageQuestion(messages);
        SearchKnowledgeResult searchKnowledgeResult = demandKnowledgeService.searchKnowledge(query, knowledgeIds, topK, score, searchTypeEnum);

        if (CollectionUtils.isNotEmpty(searchKnowledgeResult.getDocuments())) {
            for (int i = 1; i <= searchKnowledgeResult.getDocuments().size(); i++) {
                KnowledgeContentResult knowledgeContentResult = new KnowledgeContentResult();
                knowledgeContentResult.setContent(searchKnowledgeResult.getDocuments().get(i - 1));
                knowledgeContentResult.setKnowledgeId(searchKnowledgeResult.getKnowledgeIds().get(i - 1));
                knowledgeContentResult.setScore(searchKnowledgeResult.getScore().get(i - 1));
                knowledgeContentResults.add(knowledgeContentResult);
            }
            // 根据knowledgeId获取知识库名和文档名
            knowledgeIds = knowledgeContentResults.stream().map(KnowledgeContentResult::getKnowledgeId).distinct().collect(Collectors.toList());
            List<KnowledgeDocumentRelationQueryItem> knowledgeDocumentRelationQueryItems = bizKnowledgeDocumentService.knowledgeDocumentRelationQuery(knowledgeIds, null);
            for (KnowledgeContentResult result : knowledgeContentResults) {
                String knowledgeId = result.getKnowledgeId();
                KnowledgeDocumentRelationQueryItem item = knowledgeDocumentRelationQueryItems.stream().filter(v -> v.getKnowledgeId().equals(knowledgeId)).findFirst().get();
                result.setKnowledgeName(item.getKnowledgeName());
                result.setKdId(item.getKdId());
                result.setDocumentName(item.getDocumentName());
            }
        }

        return knowledgeContentResults;
    }

    private List<DBChainResult> database(List<Message> messages, Integer[] databaseIds) {
        if (ArrayUtils.isEmpty(databaseIds)) {
            return null;
        }
        String query = getMessageQuestion(messages);
        String context = getContext(messages);
        List<DBChainResult> results = new ArrayList<>();
        for (Integer databaseId : databaseIds) {
            BizKnowledgeDatabaseEntity bizKnowledgeDatabaseEntity = bizKnowledgeDatabaseService.get(databaseId.longValue());
            if (bizKnowledgeDatabaseEntity == null) {
                continue;
            }
            DBChainResponse dbChainResponse = new DBChainResponse();
            dbChainResponse.setQuestion(query);
            dbChainResponse.setContext(context);
            dbChainResponse.setPrompt(null);
            dbChainResponse.setTableFilters(null);
            dbChainResponse.setMysqlUser(bizKnowledgeDatabaseEntity.getDbUsername());
            dbChainResponse.setMysqlPassword(bizKnowledgeDatabaseEntity.getDbPassword());
            dbChainResponse.setMysqlHost(bizKnowledgeDatabaseEntity.getDbHost());
            dbChainResponse.setMysqlPort(bizKnowledgeDatabaseEntity.getDbPort());
            dbChainResponse.setMysqlDatabase(bizKnowledgeDatabaseEntity.getDbName());
            DBChainResult dbChainResult = chainService.dbChain(dbChainResponse);
            if (dbChainResult != null) {
                dbChainResult.setSql("```SQL\n" + dbChainResult.getSql() + "\n```");
                results.add(dbChainResult);
            }
        }
        return results;
    }

    private static String getMessageQuestion(List<Message> messages) {
        Object content = messages.get(messages.size() - 1).getContent();
        String query = "";
        if (content instanceof List) {
            query = ((List<HashMap>) content).get(0).get("text").toString();
        } else {
            query = content.toString();
        }
        return query;
    }

    private String getContext(List<Message> messages) {
        StringBuilder context = new StringBuilder();
        if (messages.size() >= 6) {
            for (int i = 6; i > 0; i--) {
                Message message = messages.get(messages.size() - i);
                context.append(message.getRole()).append(":").append(message.getContent()).append(StringUtils.LF);
            }
        } else {
            for (Message message : messages) {
                context.append(message.getRole()).append(":").append(message.getContent()).append(StringUtils.LF);
            }
        }
        return "";
    }

    /**
     * 更新【记忆变量】结构
     *
     * @param agentId     应用ID
     * @param originals   原字段结构
     * @param transformed 变换后的字段结构
     * @author alex.yao
     * @deprecated 更新规则:
     * 1. 原字段已存在，并存在值则不更新，否则更新并赋予该字段新结构默认值
     * 2. 原字段不存在，则新增并赋予新结构的默认值
     * 3. 原字段存在，但新结构中不存在，则删除原字段
     * 注意: 若transformed为空会清除所有字段，删除对话中所有【记忆变量】缓存
     */
    private void updateStructVariable(String agentId, List<Variable> originals, List<Variable> transformed) {
        Assert.notBlank(agentId);
        String identifier = AgentApplicationTools.identifier(agentId, agentId);
        if (CollectionUtils.isEmpty(transformed)) {
            // 清除所有字段
            MemoryVariableWriter.clean(identifier);
        }
        // 原【变量记忆】为空，则不需要处理
        if (CollectionUtils.isEmpty(originals)) {
            return;
        }
        // 【记忆变量】对话缓存不存在，则不需要处理
        Map<Object, Object> memoryVariable = MemoryVariableWriter.get(identifier);
        if (MapUtils.isEmpty(memoryVariable)) {
            return;
        }

        // 1. 获取需要删除的字段集合
        // 2. 获取需要更新值的字段集合
        Set<String> delKeys = new HashSet<>();
        Set<String> updateKeys = new HashSet<>();
        for (Variable variable : originals) {
            String key = variable.getKey();
            boolean needDel = transformed.stream().noneMatch(v -> v.getKey().equals(key));
            if (needDel) {
                delKeys.add(key);
            }

            boolean needUpdate = transformed.stream().anyMatch(v -> v.getKey().equals(key));
            if (needUpdate) {
                Optional<Variable> target = transformed.stream().filter(v -> v.getKey().equals(key)).findFirst();
                if (StringUtils.isBlank(target.get().getVariableDefault())) {
                    continue;
                }
                Map<Object, Object> map = MemoryVariableWriter.get(identifier);
                if (map == null) {
                    map = new HashMap<>();
                }
                Object value = map.get(key);
                if (value == null || StringUtils.isBlank(value.toString())) {
                    updateKeys.add(key);
                }
            }
        }
        // 3. 获取需要新增的字段集合
        Set<String> addKeys = new HashSet<>();
        for (Variable variable : transformed) {
            String key = variable.getKey();
            boolean needAdd = originals.stream().noneMatch(v -> v.getKey().equals(key));
            if (needAdd) {
                addKeys.add(key);
            }
        }

        // 删除
        if (!delKeys.isEmpty()) {
            MemoryVariableWriter.delItem(identifier, delKeys.toArray(new String[0]));
        }
        // 新增
        if (!addKeys.isEmpty()) {
            Map<String, Object> map = new HashMap<>();
            for (String key : addKeys) {
                Variable variable = transformed.stream().filter(v -> v.getKey().equals(key)).findFirst().get();
                map.put(variable.getKey(), variable.getVariableDefault());
            }
            MemoryVariableWriter.addItem(identifier, map);
        }
        // 更新
        if (!updateKeys.isEmpty()) {
            Map<String, Object> map = new HashMap<>();
            for (String key : updateKeys) {
                Variable variable = transformed.stream().filter(v -> v.getKey().equals(key)).findFirst().get();
            }
            MemoryVariableWriter.addItem(identifier, map);
        }
    }

    private boolean superclassProblem(KnowledgeSuperclassProblemConfig superclassProblemConfig, Integer[] kdIds, List<KnowledgeContentResult> knowledgeContentResult) {
        if (ArrayUtils.isNotEmpty(kdIds) && CollectionUtils.isEmpty(knowledgeContentResult)) {
            String knowledgeResponseType = superclassProblemConfig.getKnowledgeResponseType();
            if (AgentApplicationKnowledgeConstants.SUPER_CLASS_PROBLEM_TYPE.CUSTOM.equals(knowledgeResponseType) && ArrayUtils.isNotEmpty(superclassProblemConfig.getKnowledgeCustomResponse()) && StringUtils.isNotBlank(superclassProblemConfig.getKnowledgeCustomResponse()[0])) {
                return true;
            }
        }
        return false;
    }
}
