AI Model Hub:一个高效的大模型应用开发集成框架(4)- 使用salt-function-flow实现LLM流程编排

系列文章:
AI Model Hub:一个高效的大模型应用开发集成框架(1)
AI Model Hub:一个高效的大模型应用开发集成框架(2)- 对接本地llama3
AI Model Hub:一个高效的大模型应用开发集成框架(3)- 存储设计

设计思路

使用salt-function-flow流程编排框架,将原来的LLM过程,包括:Agent配置获取、历史对话上下文构建、调用模型、存储对话记录等过程,重构进行编排串联,具体实现如下:

ai-model-hub github:https://github.com/flower-trees/ai-model-hub
salt-function-flow github:https://github.com/flower-trees/salt-function-flow

加入引用

<dependency>
    <groupId>cn.fenglingsoftware</groupId>
    <artifactId>salt-function-flow</artifactId>
    <version>1.0.2</version>
</dependency>

定义节点功能

通用参数构建
@NodeIdentity(nodeId = "paramBuilder")
public class ParamBuilder extends FlowNode {

    @Override
    public void process(IContextBus iContextBus) {

        //Init param
        AiChatRequest aiChatRequest = (AiChatRequest) iContextBus.getParam();

        AiChatDto aiChatDto = new AiChatDto();

        aiChatDto.setId(aiChatRequest.getId());
        aiChatDto.setSession(aiChatRequest.getSession());
        aiChatDto.setAgent(aiChatRequest.getAgent());

        if (aiChatDto.getMessages() == null) {
            aiChatDto.setMessages(new ArrayList<>());
        }

        iContextBus.putTransmitInfo(AiChatDto.class.getName(), aiChatDto);
    }
}
Agent配置构建节点
@NodeIdentity(nodeId = "agentConfiger")
public class AgentConfiger extends FlowNodeWithReturn<AiChatDto> {

    @Autowired
    AgentService agentService;

    @Override
    public AiChatDto doProcess(IContextBus iContextBus) {

        //Init param
        AiChatRequest aiChatRequest = (AiChatRequest) iContextBus.getParam();
        AiChatDto aiChatDto = (AiChatDto) iContextBus.getTransmitInfo(AiChatDto.class.getName());

        AgentVo agentVo = agentService.load(aiChatRequest.getAgent());
        AgentVo.Configs configs = JsonUtil.fromJson(agentVo.getConfigs(), AgentVo.Configs.class);

        assert configs != null;
        aiChatDto.setVendor(configs.getVendor());
        aiChatDto.setModel(configs.getModel());

        return aiChatDto;
    }
}
对话上下文构建节点
@NodeIdentity(nodeId = "contextBuilder")
public class ContextBuilder extends FlowNodeWithReturn<AiChatDto> {

    @Autowired
    ChatService chatService;

    @Override
    public AiChatDto doProcess(IContextBus iContextBus) {

        //Init param
        AiChatRequest aiChatRequest = (AiChatRequest) iContextBus.getParam();
        AiChatDto aiChatDto = (AiChatDto) iContextBus.getTransmitInfo(AiChatDto.class.getName());

        //Query and Add Context
        List<ChatVo> chatVoList = chatService.queryLastList(aiChatRequest.getSession(), 3);
        if (!CollectionUtils.isEmpty(chatVoList)) {
            chatVoList.forEach(chatVo -> {
                AiChatDto.Message messageUser = new AiChatDto.Message();
                messageUser.setRole(RoleType.USER.getCode());
                messageUser.setContent(chatVo.getQuestion());
                aiChatDto.getMessages().add(messageUser);

                List<AiChatResponse.Message> messages = JsonUtil.fromJson(chatVo.getAnswer(), new TypeReference<>() {});
                if (!CollectionUtils.isEmpty(messages)) {
                    AiChatResponse.Message messageMarkdown = messages.stream().filter(message -> MessageType.MARKDOWN.equalsV(message.getType())).findFirst().orElse(null);
                    if (messageMarkdown != null) {
                        AiChatDto.Message message = new AiChatDto.Message();
                        message.setRole(RoleType.ASSISTANT.getCode());
                        message.setContent((String) messageMarkdown.getContent());
                        aiChatDto.getMessages().add(message);
                    }
                }
            });
        }

        //Add user questions
        AiChatDto.Message message = new AiChatDto.Message();
        message.setRole(RoleType.USER.getCode());
        message.setContent(aiChatRequest.getContent());
        aiChatDto.getMessages().add(message);

        return aiChatDto;
    }
}
模型调用节点
@NodeIdentity(nodeId = "llm")
public class LLM extends FlowNodeWithReturn<AiChatResponse> {

	@Autowired
    ChatGPTActuator chatGPTActuator;

    @Autowired
    DoubaoActuator doubaoActuator;

    @Autowired
    AliyunActuator aliyunActuator;

    @Autowired
    MoonshotActuator moonshotActuator;

    @Autowired
    OllamaActuator ollamaActuator;
	
    @Override
    public AiChatResponse doProcess(IContextBus iContextBus) {

        //Init param
        AiChatRequest aiChatRequest = (AiChatRequest) iContextBus.getParam();
        AiChatDto aiChatDto = (AiChatDto) iContextBus.getTransmitInfo(AiChatDto.class.getName());

        if (aiChatDto.getVendor().equals(VendorType.CHATGPT.getCode())) {
            return chatGPTActuator.pursueSyc(aiChatDto, aiChatRequest.getResponder());
        } else if (aiChatDto.getVendor().equals(VendorType.DOUBAO.getCode())) {
            return doubaoActuator.pursueSyc(aiChatDto, aiChatRequest.getResponder());
        } else if (aiChatDto.getVendor().equals(VendorType.ALIYUN.getCode())) {
            return aliyunActuator.pursueSyc(aiChatDto, aiChatRequest.getResponder());
        } else if (aiChatDto.getVendor().equals(VendorType.MOONSHOT.getCode())) {
            return moonshotActuator.pursueSyc(aiChatDto, aiChatRequest.getResponder());
        } else if (aiChatDto.getVendor().equals(VendorType.OLLAMA.getCode())) {
            return ollamaActuator.pursueSyc(aiChatDto, aiChatRequest.getResponder());
        }

        return null;
    }
}
对话记录保存节点
@NodeIdentity(nodeId = "chatSaver")
public class ChatSaver  extends FlowNodeWithReturn<AiChatResponse> {

    @Autowired
    SessionService sessionService;

    @Autowired
    ChatService chatService;

    @Autowired
    ChatHisService chatHisService;

    @Override
    public AiChatResponse doProcess(IContextBus iContextBus) {

        //Init param
        AiChatResponse aiChatResponse = (AiChatResponse) iContextBus.getPreResult();
        AiChatDto aiChatDto = (AiChatDto) iContextBus.getTransmitInfo(AiChatDto.class.getName());

        if (!AiChatCode.ERROR.equalsV(aiChatResponse.getCode())) {

            //Save conversation records
            SessionVo sessionVo = sessionService.load(aiChatResponse.getSession());
            if (sessionVo == null) {
                sessionVo = new SessionVo();
                sessionVo.setSessionId(aiChatResponse.getSession());
                sessionVo.setAgentId(aiChatResponse.getAgent());
                sessionService.create(sessionVo);
            }

            String question = aiChatDto.getMessages().get(aiChatDto.getMessages().size() - 1).getContent();
            String answer = JsonUtil.toJson(aiChatResponse.getMessages());

            //Save chat records
            ChatVo chatVo = chatService.load(aiChatResponse.getId());
            if (chatVo == null) {
                chatVo = new ChatVo();
                chatVo.setSessionId(aiChatResponse.getSession());
                chatVo.setChatId(aiChatResponse.getId());
                chatVo.setQuestion(question);
                chatVo.setAnswer(answer);
                chatService.create(chatVo);
            } else {
                chatVo.setQuestion(question);
                chatVo.setAnswer(answer);
                chatService.update(chatVo);
            }

            //Save chat his records
            ChatHisVo chatHisVo = new ChatHisVo();
            chatHisVo.setSessionId(aiChatResponse.getSession());
            chatHisVo.setChatId(aiChatResponse.getId());
            chatHisVo.setChatHisId(IdsUtil.newChatId());
            chatHisVo.setQuestion(question);
            chatHisVo.setAnswer(answer);
            chatHisService.create(chatHisVo);
        }

        return aiChatResponse;
    }
}

编排流程

@Slf4j
@Service
public class ChatHubService {
	......
	@Async
    public void flow(AiChatRequest aiChatRequest, Consumer<AiChatResponse> responder) {

        if (StringUtils.isBlank(aiChatRequest.getSession())) aiChatRequest.setSession(IdsUtil.newSessionId());
        if (StringUtils.isBlank(aiChatRequest.getId())) aiChatRequest.setId(IdsUtil.newChatId());

        aiChatRequest.setResponder(responder);
        
        try {
        	//构建流程
            FlowInstance flowInstance = flowEngine.builder()
                    .id(IdsUtil.newFlowId())		//定义流程ID
                    .next("paramBuilder")			//构建参数
                    .next("agentConfiger") 			//查询Agent配置
                    .next("contextBuilder")			//构建对话历史上下文
                    .next("llm")					//调用模型
                    .next("chatSaver")				//保存对话记录
                    .buildDynamic();
            //执行流程
            flowEngine.execute(flowInstance, aiChatRequest);
            
        } catch (Exception e) {
            log.error("ai models flow fail, e:", e);
            AiChatResponse aiChatResponse = new AiChatResponse();
            aiChatResponse.setCode(AiChatCode.ERROR.getCode());
            aiChatResponse.setMessage(AiChatCode.ERROR.getMessage());
            responder.accept(aiChatResponse);
        }
    }
}
调用测试

以豆包模型为例:

curl --location 'http://127.0.0.1:8080/ai-model-hub/ai/stream/chat/flow' \
--header 'Content-Type: application/json' \
--data '{
    "agent": "2",
    "content": "介绍一下军博,使用20个汉字以内"
}'

文件位置

ai-model-hub/
│
├── src/
│   └── main/
│       ├── java/
│       │   └── org/
│       │       └── salt/
│       │           └── ai/
│       │               └── hub/
│       │                   │	├── flow/
  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值