1.配置和简介

Nacos3.x比Nacos2.x多了可以注册智能体的功能。

配置密钥,32位即可

启动分为集群模式和单机模式,单机模式下,默认存储在derby下。

2.智能体注册中心:

AgentScope也是自带注册中心的,叫AgentScopeA2aServer。

现在我们是把当前项目的注册中心改成nacos。

1.通过SpringBoot,以Bean的形式注册到注册中心

2.手动写入注册中心,好处能够自定义智能体卡片对象。通过Builder方法传入。

本项目采用Nacos为注册中心。

那么springBoot怎么知道我的注册中心是Nacos?

通过yml文件配置即可:
 

agentscope:
  a2a:
    server:
      enabled: true
      card:
        name: TripPlanner Agent
        description: 行程规划agent
    nacos:
      server-addr: localhost:8848
      username: nacos
      password: nacos

创建一个生成智能体的工具类:

@Slf4j
@Service
public class AgentUtils {

    //从配置中读取敏感资源,不能使用static

    @Resource
    private Properties properties;

    public ReActAgent.Builder getReActAgentBuilder(String name, String description) {
        return ReActAgent.builder()
                .name(name)
                .description(description)
                .model(DashScopeChatModel.builder()
                        //请求语言大模型的apikey
                        .apiKey(properties.getAlibabaDashscopeKey())
                        //所使用的语言大模型
                        .modelName(properties.getModelName())
                        .stream(true)
                        .build());
                

    }

     public static Flux<Event> streamResponse(AgentBase agent, String prompt) {
        return agent.stream(Msg.builder().role(MsgRole.USER)
                .content(List.of(TextBlock.builder().text(prompt).build())).build());
    }

}

主管智能体在nacos上获得了智能体卡片并知道了这个智能体的功能,然后就会把任务分发下去。
在routeMakingAgent目录下的agent包下创建这个类:

!注意主管智能体是不用注册到nacos的

@Component
@Slf4j
public class RouteMakingAgent {
    @Resource
    private AgentUtils agentUtils;

    @Resource
    private BaiduMapMCP baiduMapMCP;

    @Bean
    public ReActAgent getRouteMakingAgent() {

        //创建百度地图MCP客户端
        baiduMapMCP.getBaiduMapMCP();
        //初始化百度地图MCP客户端
        McpClientWrapper mcpClient = baiduMapMCP.initBaiduMapMCP();
        
        ToolUtils toolUtils = new ToolUtils();
        //将百度地图MCP注册到工具包
        Toolkit toolkit = toolUtils.getToolkit(mcpClient);

        //打印挂载的工具
        Set<String> toolNames = toolkit.getToolNames();
        log.info("=============");
        toolNames.stream().forEach(
                value -> log.info("挂载的工具名称:" + value)
        );
        log.info("=============");

        //注入到nacos
        return agentUtils.getReActAgentBuilder("RouteMakingAgent", "擅长路线制定规划")
                //工具包
                .toolkit(toolkit)
                .build();
    }
}
@Component
public class TripPlannerAgent {

    @Resource
    private AgentUtils agentUtils;

    @Resource
    private SuggestSightAgent suggestSightAgent;

    @Bean
    public ReActAgent getTripPlannerAgent() throws Exception {

        /* **********************
         *
         * 1.
         * AgentScope框架自带了注册中心: AgentScopeA2aServer
         *
         * 2.
         * AgentScope框架将智能体卡片注册到注册中心,有2种方案:
         * a. 通过SpringBoot, 以Bean的形式自动注入
         * b. 手动写入注册中心, 主要针对于AgentScopeA2aServer
         *
         *
         * *********************/
        Toolkit toolkit = new Toolkit();
        //子智能体
        toolkit.registration().subAgent(
                suggestSightAgent::getSuggestSightAgent
        ).apply();
        //构建skill ,将工具包和skill结合
        ReActAgent.Builder builder = agentUtils.getReActAgentBuilder(
                        "TripPlannerAgent",
                        "擅长处理景点行程规划"
                )
                //挂载工具包
                .toolkit(toolkit);

        return builder.build();
      }
}

写一个工具类让主管智能体去nacos发现是否有这样的智能体,读取智能体卡片,

@Slf4j
public class RemoteAgentTool {
    @Tool(description = "擅长制定最优驾车路线的Agent")
    public void callRouteMakingAgent(
            @ToolParam(name = "prompt", description = "驾车的起点和终点") String prompt
    ) throws NacosException {

        log.info("============");
        log.info("工具方法:路线制定智能体...正在调用中");
        log.info("============");

        A2aAgent agent = A2aAgent.builder()
                .name("RouteMakingAgent") //必须和注册中心的智能体名字一样
                .agentCardResolver(
                        //创建 Nacos 的 AgentCardResolver
                        new NacosAgentCardResolver(NacosUtil.getNacosClient()))
                .build();
        prompt = "调用百度地图MCP, 制定最优驾车路线:" + prompt;
        PromptUtils promptUtils = new PromptUtils();
        Msg userMsg = promptUtils.getPrompt(prompt);

        log.info("============");
        log.info("获取到的远程Agent描述:" + agent.getDescription());
        log.info("============");

        AgentUtils.streamResponse(agent, "调用百度地图MCP");

    }

    @Tool(description = "从Nacos注册中心获取行程规划Agent")
    public void callTripPlannerAgent() throws NacosException {

        A2aAgent agent = A2aAgent.builder()
                .name("TripPlannerAgent")
                .agentCardResolver(
                        //创建 Nacos 的 AgentCardResolver
                        new NacosAgentCardResolver(NacosUtil.getNacosClient()))
                .build();

        //远程Agent运行
        agent.call().block();

    }
}

创建一个百度地图MCP客户端

@Slf4j
@Component
public class BaiduMapMCP {

    @Resource
    private Properties properties;

    //MCP 客户端
    private volatile McpClientWrapper baiduMapMCP = null;
    //MCP 客户端初始化
    private volatile boolean mcpInitialized = false;

    public void getBaiduMapMCP() {

        //创建MCP客户端
        baiduMapMCP = McpClientBuilder.create("BaiduMap-mcp")
                //和MCP Server以SSE方式进行通信
                .sseTransport(properties.getBaiduMapAddr())
                //请求超时
                .timeout(Duration.ofSeconds(120))
                //异步请求
                .buildAsync()
                .block();

    }
    /**
     *
     * description: 初始化百度地图MCP客户端
     * @param :
     * @return io.agentscope.core.tool.mcp.McpClientWrapper
     */
    public McpClientWrapper initBaiduMapMCP() {

        //通过Optional判断百度MCP客户端是否为null
        Optional<McpClientWrapper> mcpClientWrapper = Optional.ofNullable(baiduMapMCP);
        if(mcpClientWrapper.isPresent()) {
            if(!mcpInitialized) { //线程锁
                synchronized (this) {
                    if (!mcpInitialized) {
                        try {
                            //MCP客户端初始化, 通过阻塞线程让客户端和服务端成功建立联系。
                            baiduMapMCP.initialize().block();

                            //获取MCP服务端工具列表
                            if(baiduMapMCP.isInitialized()) {

                                log.info("=============");
                                log.info("百度地图MCP 客户端初始化成功!");
                                log.info("=============");

                                baiduMapMCP.listTools().block().forEach(tool -> {
                                    log.info("==================");
                                    log.info("百度地图MCP工具列表:" + tool.name());
                                    log.info("==================");
                                });

                                mcpInitialized=true;
                            }
                        } catch (Exception e) {
                            log.error("百度地图MCP客户端初始化失败: {}", e.getMessage(), e);
                            baiduMapMCP = null;
                        }
                    }
                }
            }

        }
        return baiduMapMCP;
    }
}

在魔塔社区配置百度地图的客户端,这里使用百度地图,SSE协议就用SSE,

通过工具包挂载到智能体上面,在RouteMakingAgent的代码里面有详解,

具体的工具包类:

那么百度地图的MCP的客户端走第二个getToolkit方法,这是重写的方法。

public class ToolUtils {

    private final Toolkit toolkit;

    public ToolUtils() {
        toolkit = new Toolkit();
    }

    public Toolkit getToolkit(Object tool) {
        toolkit.registerTool(tool);
        return toolkit;
    }

    public Toolkit getToolkit(McpClientWrapper mcp) {
        toolkit.registerMcpClient(mcp);
        return toolkit;
    }
}

主管智能体会根据智能体的description的描述来分配任务,所以description有两种配置方式,

1.yml文件配置(优先级最高)

agentscope:
  a2a:
    server:
      enabled: true
      card:
        name: TripPlanner Agent
        description: 行程规划agent
    nacos:
      server-addr: localhost:8848
      username: nacos
      password: nacos
@Component
public class TripPlannerAgent {

    @Resource
    private AgentUtils agentUtils;

    @Resource
    private SuggestSightAgent suggestSightAgent;

    @Bean
    public ReActAgent getTripPlannerAgent() throws Exception {

        Toolkit toolkit = new Toolkit();
        //子智能体
        toolkit.registration().subAgent(
                suggestSightAgent::getSuggestSightAgent
        ).apply();
        //构建skill ,将工具包和skill结合

        return agentUtils.getReActAgentBuilder(
                        "TripPlannerAgent",
                        "擅长处理景点行程规划" //这里就是我对这个处理景点智能体的描述
                )
                //挂载工具包
                .toolkit(toolkit)
                .build();
    }
}

打开nacos:可以发现还是以yml文件为主

解决方法:注释description即可,但同时要先删除nacos已经注册的智能体卡片。

更多推荐