Solon v3.8.0

multi - 示例4 - 协作协议

</> markdown
2026年1月4日 下午10:46:36

示例代码

import demo.ai.agent.LlmUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.noear.solon.ai.agent.Agent;
import org.noear.solon.ai.agent.react.ReActAgent;
import org.noear.solon.ai.agent.team.TeamAgent;
import org.noear.solon.ai.agent.team.TeamProtocols;
import org.noear.solon.ai.agent.team.TeamTrace;
import org.noear.solon.ai.chat.ChatModel;
import org.noear.solon.flow.FlowContext;

/**
 * Blackboard 策略测试:基于共享状态的补位协作
 */
public class TeamAgentBlackboardTest {
    @Test
    public void testBlackboardLogic() throws Throwable {
        ChatModel chatModel = LlmUtil.getChatModel();

        // 1. 定义互补的 Agent
        Agent databaseDesigner = ReActAgent.of(chatModel)
                .name("db_designer")
                .promptProvider(c -> "你只负责数据库表结构设计,输出 SQL 代码。这只是个测试,有2张表就好了")
                .description("负责数据库表结构设计,输出 SQL 代码。")
                .build();

        Agent apiDesigner = ReActAgent.of(chatModel)
                .name("api_designer")
                .promptProvider(c -> "你只负责 RESTful API 接口协议设计。这只是个测试,争对表做2个接口设计就好了。")
                .description("负责 RESTful API 接口协议设计。")
                .build();

        // 2. 使用 BLACKBOARD 策略
        TeamAgent team = TeamAgent.of(chatModel)
                .name("blackboard_team")
                .protocol(TeamProtocols.BLACKBOARD)
                .addAgent(databaseDesigner)
                .addAgent(apiDesigner)
                .build();

        String yaml = team.getGraph().toYaml();

        System.out.println("------------------\n\n");
        System.out.println(yaml);
        System.out.println("\n\n------------------");

        FlowContext context = FlowContext.of("test_blackboard");
        // 任务涵盖两个领域,观察 Mediator 如何依次分派
        String result = team.call(context, "请为我的电商系统设计用户模块的数据库和配套接口。");

        System.out.println("=== Blackboard 策略测试 ===");
        System.out.println("任务: 为电商系统设计用户模块的数据库和配套接口");
        System.out.println("执行结果: " + result);

        TeamTrace trace = team.getTrace(context);
        Assertions.assertNotNull(trace, "应该有轨迹记录");

        // 放松断言:验证任务完成,有轨迹记录
        Assertions.assertNotNull(result, "任务应该有结果");
        Assertions.assertFalse(result.trim().isEmpty(), "结果不应该为空");
        Assertions.assertTrue(trace.getStepCount() > 0, "至少应该执行一步");

        // 输出调试信息,但不做严格断言
        System.out.println("实际步数: " + trace.getStepCount());
        System.out.println("调用Agent数: " + trace.getSteps().stream()
                .map(step -> step.getAgentName())
                .distinct()
                .count());

        // 打印详细历史
        System.out.println("协作轨迹:\n" + trace.getFormattedHistory());
        System.out.println("=== 测试结束 ===\n");
    }

    @Test
    public void testBlackboardWithExplicitRequest() throws Throwable {
        ChatModel chatModel = LlmUtil.getChatModel();

        // 创建互补的 Agent
        Agent databaseDesigner = ReActAgent.of(chatModel)
                .name("db_designer")
                .description("负责数据库表结构设计,输出 SQL 代码。")
                .build();

        Agent apiDesigner = ReActAgent.of(chatModel)
                .name("api_designer")
                .description("负责 RESTful API 接口协议设计。")
                .build();

        TeamAgent team = TeamAgent.of(chatModel)
                .name("blackboard_explicit_team")
                .protocol(TeamProtocols.BLACKBOARD)
                .addAgent(databaseDesigner)
                .addAgent(apiDesigner)
                .build();

        FlowContext context = FlowContext.of("test_blackboard_explicit");

        // 使用更明确的任务,要求两个部分
        String result = team.call(context,
                "请分两部分完成:\n" +
                        "1. 设计用户模块的数据库表结构,需要包含用户表、地址表、订单表\n" +
                        "2. 设计对应的 RESTful API 接口,包括用户注册、登录、信息查询");

        System.out.println("=== Blackboard 策略测试(明确任务) ===");
        System.out.println("任务: 分两部分设计数据库和API");
        System.out.println("执行结果: " + result);

        TeamTrace trace = team.getTrace(context);
        Assertions.assertNotNull(trace, "应该有轨迹记录");

        // 基本验证
        Assertions.assertNotNull(result, "任务应该有结果");
        Assertions.assertTrue(trace.getStepCount() > 0, "至少应该执行一步");

        // 输出调试信息
        System.out.println("实际步数: " + trace.getStepCount());

        // 检查是否两个Agent都参与了(理想情况)
        long uniqueAgents = trace.getSteps().stream()
                .map(step -> step.getAgentName())
                .distinct()
                .count();
        System.out.println("实际参与Agent数: " + uniqueAgents + " (期望: 2)");

        System.out.println("协作轨迹:\n" + trace.getFormattedHistory());
        System.out.println("=== 测试结束 ===\n");
    }
}