Chain多个ServiceAI

  • 在一个应用中, 可能需要多个模型共同一起协作完成一个任务。
  • 为什么要这样做呢?
    • 某个LLM(大模型)可能并不需要知道那么多的tools。例如用户只是输入了很简单的常识问题给到LLM,这时让 LLM 访问数十或数百个tools的成本很高(LLM 调用中包含的每个tools都会消耗大量token),并且得到的结果可能也是意想不到的(LLM 可能会产生幻觉或被操纵以使用非预期的输入来调用tools)
    • 从RAG(检索增强生成)的角度,同样,有时需要为 LLM 提供一些上下文,但并不是永远需要这样,因为成本很高(更多上下文 = 更多token),并且相应时间也会增加(更多上下文 = 更高的延迟)
    • 而且,不同的AI适合不同的场景,例如推理和情感两种场景。
  • 拓展:AI协作流水线有个很好的框架是 dify,由python编写
  • Chain可以替换tools,实现效果
  • Chain可以怎么用?
    • 您可以一个接一个地调用 AI 服务(又称链接-chain)。
    • 您可以使用确定性和 LLM 支持的if/else语句(AI 服务可以返回boolean)。
    • 您可以使用确定性和 LLM 支持的switch语句(AI 服务可以返回enum)。
    • 您可以使用确定性和 LLM 驱动的for/while循环(AI 服务可以返回int和其他数字类型)。
    • 您可以在单元测试中模拟 AI 服务(因为它是一个接口)。
    • 您可以单独地对每个 AI 服务进行集成测试。
    • 并且我们可以自由的进行任务编排

演示

  • 以下演示2个模型协调合作,1个负责任务拆分分配, 1个模型负责任务tools回调执行
  • 新建一个项目
  • pom.xml
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.qi</groupId>
      <artifactId>LangChain4j_demo05</artifactId>
      <version>1.0-SNAPSHOT</version>
      <name>LangChain4j_demo05</name>
      <url>http://maven.apache.org</url>
    
        <dependencies>
            <dependency>
                <groupId>dev.langchain4j</groupId>
                <artifactId>langchain4j-open-ai</artifactId>
                <version>1.0.0-beta3</version>
            </dependency>
            <!-- 阿里云百炼 -->
            <dependency>
                <groupId>dev.langchain4j</groupId>
                <artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId>
                <version>1.0.0-beta3</version>
            </dependency>
    
            <!-- langchain4j核心 -->
            <dependency>
                <groupId>dev.langchain4j</groupId>
                <artifactId>langchain4j</artifactId>
                <version>1.0.0-beta3</version>
            </dependency>
        </dependencies>
    </project>
    
    
  • 任务类型枚举
    package com.qi;
    
    import dev.langchain4j.model.output.structured.Description;
    
    //任务类型枚举
    public enum TASK_TYPE {
    
        @Description("查询机票")
        QUERY_TICKET("查询机票"),
    
        @Description("取消预定")
        CANCEL_TICKET("取消预定"),
    
        @Description("修改预定")
        MODIFY_TICKET("修改预定"),
    
        @Description("其他")
        OTHER("其他")
    
        ;
    
        private String name;
    
        TASK_TYPE(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
  • 工作类
    package com.qi;
    
    import dev.langchain4j.service.SystemMessage;
    import dev.langchain4j.service.UserMessage;
    
    public class MilesOfSmiles {
    
        //分配任务 助手
        interface GreetingExpert {
            @UserMessage("以下文本是什么任务: {{it}}")
            TASK_TYPE isTask(String text);
        }
    
        //航空公司客服 助手
        interface ChatBot {
            @SystemMessage("你是一名航空公司客服代理,请为客户服务:")
            String reply(String userMessage);
        }
    
        //两个工作助手
        private GreetingExpert greetingExpert;
        private ChatBot chatBot;
    
        public MilesOfSmiles(GreetingExpert greetingExpert, ChatBot chatBot) {
            this.greetingExpert = greetingExpert;
            this.chatBot = chatBot;
        }
    
        //分配任务的方法
        public String handle(String userMessage) {
            TASK_TYPE task = greetingExpert.isTask(userMessage);
    
            switch (task) {
                case MODIFY_TICKET:
                    return task.getName() + "调用修改预定service方法处理";
                case QUERY_TICKET:
                    return task.getName() + "调用查询机票service方法查询";
                case CANCEL_TICKET:
                    return task.getName() + "调用取消预定service方法处理";
                case OTHER:
                    return chatBot.reply(userMessage); //其他问题,让航空公司客服助手回答
            }
            return null;
        }
    
    }
    
  • main执行程序
    package com.qi;
    
    import dev.langchain4j.community.model.dashscope.QwenChatModel;
    import dev.langchain4j.model.chat.ChatLanguageModel;
    import dev.langchain4j.model.openai.OpenAiChatModel;
    import dev.langchain4j.service.AiServices;
    import com.qi.MilesOfSmiles.GreetingExpert;
    import com.qi.MilesOfSmiles.ChatBot;
    
    public class Main {
    
        public static void main(String[] args) {
            ChatLanguageModel qwen = QwenChatModel
                    .builder()
                    .apiKey("sk-xxxxxx")
                    .modelName("qwen-max")
                    .build();
    
            ChatLanguageModel deepseek = OpenAiChatModel
                    .builder()
                    .baseUrl("https://api.deepseek.com")
                    .apiKey("sk-xxxxxx")
                    .modelName("deepseek-reasoner")
                    .build();
    
            //分配任务让deepseek来干
            GreetingExpert greetingExpert = AiServices.create(GreetingExpert.class, deepseek);
    
            //航空客服让千问来干
            ChatBot chatBot = AiServices.create(ChatBot.class, qwen);
    
            //创建工作对象
            MilesOfSmiles milesOfSmiles = new MilesOfSmiles(greetingExpert, chatBot);
    
            //用户发起任务
            String greeting1 = milesOfSmiles.handle("任务一:我要退票!");
            System.out.println(greeting1);
            System.out.println("_________________________");
            String greeting2 = milesOfSmiles.handle("任务二:3*6等于多少?");
            System.out.println(greeting2);
    
        }
    
    }
    
  • 控制台
    在这里插入图片描述

MCP

  • 就是tools的一种外部调用的方式
  • 是一种协议,由 Anthropic(Claude 母公司)于 2024 年 11 月开源的标准化协议。
  • 其实就是,利用一种json-rpc2.0的json格式,告知可用工具及参数、确定调用工具、反馈对应数据。
  • 目标是统一大模型与外部数据源、工具的交互方式。
  • 一般将一些公共的服务按MCP协议抽取成一个外部应用,然后在tools中用到的时候去调用。
  • 常见的MCPServer有很多,例如获取GitHub信息的、操作浏览器的、查网页的、获取数据库的等等。
  • MCPServer管理平台有很多,例如:https://mcp.so

在IDEA中使用

  • 在插件中搜索 Cline 安装
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 此时会跳转登陆页面,使用谷歌账号登录即可
  • 登录成功后,配置大模型,这里我们选择阿里的千问,需要填入apiKey。然后点击Done保存
    在这里插入图片描述
  • 配置MCPServer
    在这里插入图片描述
  • 可以看到这里提供了很多MCPServer,也可以在这里一键安装
    在这里插入图片描述

IDEA中接入百度地图

在百度地图中创建应用

应用中安装

  • 我们还是选择在 mcp.so 网站中进行选择。
    在这里插入图片描述
    在这里插入图片描述
  • 也可以前往github中查看详细文档。可以看到,提供了python和node.JS 两种接入方法
    在这里插入图片描述
  • 我们使用nodeJS的方式接入
    {
      "mcpServers": {
        "baidu-map": {
          "command": "npx",
          "args": [
            "-y",
            "@baidumap/mcp-server-baidu-map"
          ],
          "env": {
            "BAIDU_MAP_API_KEY": "<YOUR_API_KEY>"
          }
        }
      }
    }
    
  • 写入idea中cline中
    在这里插入图片描述
  • 需要进行简单的修改(目的是解决 Windows 系统下直接执行 npx 命令可能失败的兼容性问题)
    {
      "mcpServers": {
        "baidu-map": {
          "command": "cmd",
          "args": [
            "/c",
            "npx",
            "-y",
            "@baidumap/mcp-server-baidu-map"
          ],
          "env": {
            "BAIDU_MAP_API_KEY": "xxxxxx"
          }
        }
      }
    }
    
  • 然后把刚才百度地图应用的AK密钥填在上面 BAIDU_MAP_API_KEY 中即可
  • 此时便能看到 baidu-map,点击Done保存
    在这里插入图片描述
  • 允许Cline使用MCP,自己看情况选择性勾选
    在这里插入图片描述
    在这里插入图片描述
  • 此时我们提问:从北京西站到故宫开车需要多久。过程中需要我们批准他使用百度地图的MCPServer。
    在这里插入图片描述

langchain4j接入MCPSercer

  • langchain4j 没有提供mcp server的实现, 但是提供的mcp client的实现
  • 我们基于上面的代码
  • pom.xml
    <!--mcp-->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-mcp</artifactId>
        <version>1.0.0-beta3</version>
    </dependency>
    
  • java
    package com.qi2;
    
    import dev.langchain4j.community.model.dashscope.QwenChatModel;
    import dev.langchain4j.mcp.McpToolProvider;
    import dev.langchain4j.mcp.client.DefaultMcpClient;
    import dev.langchain4j.mcp.client.McpClient;
    import dev.langchain4j.mcp.client.transport.McpTransport;
    import dev.langchain4j.mcp.client.transport.stdio.StdioMcpTransport;
    import dev.langchain4j.model.chat.ChatLanguageModel;
    import dev.langchain4j.service.AiServices;
    import dev.langchain4j.service.tool.ToolProvider;
    
    import java.util.List;
    import java.util.Map;
    
    public class Main {
    
        interface Bot {
            String chat(String userMessage);
        }
    
        public static void main(String[] args) throws Exception {
            // 1.构建模型
            ChatLanguageModel model = QwenChatModel
                    .builder()
                    .apiKey("sk-xxxxxx")
                    .modelName("qwen-max")
                    .build();
    
            // 2.构建MCP服务传输方式  有sse和stdio两种, 这里演示的是stdio
            McpTransport transport = new StdioMcpTransport.Builder()
                    .command(List.of("cmd",
                            "/c",
                            "npx",
                            "-y",
                            "@baidumap/mcp-server-baidu-map",
                            "mcp/github"))
                    .environment(Map.of("BAIDU_MAP_API_KEY", "xxxxxx"))
                    .logEvents(true)
                    .build();
    
            // 3.构建MCP客户端, 指定传输方式
            McpClient mcpClient = new DefaultMcpClient.Builder()
                    .transport(transport)
                    .build();
    
            // 4.构建MCP工具提供者, 指定MCP客户端
            ToolProvider toolProvider = McpToolProvider.builder()
                    .mcpClients(List.of(mcpClient)) //这里可以绑定多个MCPServer
                    .build();
    
            // 5.构建服务代理, 指定模型和工具提供者
            Bot bot = AiServices.builder(Bot.class)
                    .chatLanguageModel(model)
                    .toolProvider(toolProvider)
                    .build();
    
            try {
                // 对话请求
                String response = bot.chat("规划北京西到天安门的骑行路线");
                System.out.println("RESPONSE: " + response);
            } finally {
                mcpClient.close();
            }
    
        }
    
    }
    
    
  • 控制台
    在这里插入图片描述
  • 参考bilibili学习视频
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐