阿里开源AgentScope多智能体框架解析系列(十六)第16章:企业级Skill系统-跨部门协同Agent系统

69 阅读13分钟

导读

本章基于第13章的Skill系统基础,通过复杂的企业级场景展示如何构建跨部门协同的Agent系统。


1.1 What - 场景理解

业务背景

某大型企业拥有5个主要部门,包括HR、财务、IT、运营、营销。每个部门都有独立的工作流和技能体系。现状存在以下问题:

  • 部门间信息流通困难,形成信息孤岛
  • 跨部门业务流程冗长(如员工离职流程需3-5天)
  • 重复开发相同的功能,浪费资源
  • 部门间缺乏有效的协作机制
  • 无法快速响应跨部门的复杂业务需求

Skill系统解决方案

构建一个企业级技能市场多Agent协同系统,使得:

  • 每个部门都能独立发布和管理自己的技能(共25个)
  • 其他部门可以发现、评价和使用这些技能
  • 支持跨部门的并行任务执行
  • 提供统一的任务协调和结果汇总机制
  • 实现知识共享和最佳实践推广

系统架构

┌──────────────────────────────────────────────────────────────────┐
│                  企业技能市场 (Enterprise Skill Marketplace)      │
│  ──────────────────────────────────────────────────────────────  │
│  核心功能:                                                       │
│  - 技能注册与发布 (Skill Registration & Publishing)             │
│  - 技能版本管理 (Version Control)                               │
│  - 技能搜索与发现 (Search & Discovery)                         │
│  - 技能评分系统 (Rating System)                                │
│  - 跨部门搜索 (Cross-Department Search)                        │
│  - 使用情况统计 (Usage Statistics)                             │
└──────────────────────────────────────────────────────────────────┘
                    ↑         ↑         ↑         ↑         ↑
        ┌───────────┴─────┬───┴────┬────┴──┬──────┴─────┬──┴──────┐
        │                 │        │       │            │         │
   ┌────▼─────┐   ┌──────▼────┐ ┌▼──────┐ ┌─────────┐ ┌▼───────┐
   │ HR Agent │   │Finance    │ │ IT    │ │Ops     │ │Marketing
   │          │   │Agent      │ │Agent  │ │Agent   │ │Agent
   └──────────┘   └───────────┘ └───────┘ └────────┘ └────────┘

五个部门Agent,各掌握5个技能,共25个技能:

部门技能分布

┌─────────────────────┬─────────────────────┬──────────────────────┐
│ 人力资源(HR) 5个    │ 财务(Finance) 5个   │ IT 5个              │
├─────────────────────┼─────────────────────┼──────────────────────┤
│ • 招聘管理          │ • 财务报表生成      │ • 系统监控          │
│ • 员工档案管理      │ • 成本分析          │ • 故障诊断          │
│ • 薪酬计算          │ • 预算规划          │ • 资源申请          │
│ • 考勤统计          │ • 审计合规          │ • 安全检查          │
│ • 绩效评估          │ • 费用报销          │ • 数据备份          │
└─────────────────────┴─────────────────────┴──────────────────────┘

┌─────────────────────┬─────────────────────────────────┐
│ 运营(Operations) 5个│ 营销(Marketing) 5个            │
├─────────────────────┼─────────────────────────────────┤
│ • 流程优化          │ • 活动策划                      │
│ • KPI统计          │ • 内容创建                      │
│ • 供应链管理        │ • 用户分群                      │
│ • 质量管理          │ • ROI分析                       │
│ • 风险评估          │ • 品牌管理                      │
└─────────────────────┴─────────────────────────────────┘

1.2 Why - 为什么需要跨部门协同

问题1:信息孤岛

  • 各部门独立运作,信息不流通
  • 无法获取其他部门的数据和能力
  • 导致决策延迟和资源浪费

解决方案

  • 建立统一的技能市场,所有部门技能可见
  • 提供跨部门的技能搜索和发现机制

问题2:协作效率低

  • 跨部门业务流程需要多次对接和沟通
  • 员工离职流程原需3-5天(涉及HR、Finance、IT、Ops)
  • 新产品发布需要多个部门协调

解决方案

  • 提供并行执行多部门任务的机制
  • 自动化跨部门协调流程
  • 降低沟通成本

问题3:能力重复开发

  • 多个部门开发相同的功能(如数据分析、报表生成等)
  • 浪费开发资源
  • 导致代码质量不一致

解决方案

  • 通过技能市场实现能力共享
  • 避免重复开发
  • 提高代码复用率

问题4:知识共享不足

  • 优秀的业务处理经验无法推广
  • 新员工培养时间长
  • 部门间的最佳实践无法互相借鉴

解决方案

  • 通过技能评分系统标记高质量技能
  • 提供使用统计和反馈机制
  • 促进最佳实践的传播

1.3 How - 代码实现

第一步:定义部门和技能模型

/**
 * 部门枚举
 */
enum Department {
    HR("HR", "人力资源部", "负责招聘、档案、薪酬等"),
    FINANCE("Finance", "财务部", "负责财务报表、预算、成本等"),
    IT("IT", "信息技术部", "负责系统、监控、安全等"),
    OPERATIONS("Ops", "运营部", "负责流程、KPI、供应链等"),
    MARKETING("Marketing", "营销部", "负责营销活动、内容、品牌等");
    
    private final String code;
    private final String name;
    private final String description;
    
    Department(String code, String name, String description) {
        this.code = code;
        this.name = name;
        this.description = description;
    }
    
    public String getCode() { return code; }
    public String getName() { return name; }
    public String getDescription() { return description; }
}

/**
 * 代理技能定义
 */
@Data
@Builder
class AgentSkill {
    private String id;
    private String name;
    private String displayName;
    private String description;
    private String version;
    private String author;
    private String category;
    private List<String> tags;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

/**
 * 跨部门任务定义
 */
@Data
@Builder
class CrossDepartmentTask {
    private String taskId;
    private String taskName;
    private Department initiatingDept;      // 发起部门
    private List<Department> involvedDepts; // 涉及部门
    private Map<String, Object> taskData;   // 任务数据
    private LocalDateTime createdAt;
    private String status;                  // PENDING, IN_PROGRESS, COMPLETED, FAILED
}

第二步:技能市场的实现

/**
 * 企业技能市场 - 管理所有部门的技能
 */
public class EnterpriseSkillMarketplace {
    
    private static final Logger logger = LoggerFactory.getLogger(EnterpriseSkillMarketplace.class);
    
    // 部门与其技能的映射
    private final Map<Department, List<AgentSkill>> departmentSkills = new ConcurrentHashMap<>();
    
    // 技能评分和使用统计
    private final Map<String, SkillRating> skillRatings = new ConcurrentHashMap<>();
    
    private final SearchEngine skillSearchEngine;
    
    public EnterpriseSkillMarketplace(SearchEngine skillSearchEngine) {
        this.skillSearchEngine = skillSearchEngine;
        initializeDepartmentSkills();
    }
    
    /**
     * 初始化各部门的技能集
     */
    private void initializeDepartmentSkills() {
        logger.info("开始初始化企业技能市场...");
        
        // ========== HR部门:5个技能 ==========
        departmentSkills.put(Department.HR, Arrays.asList(
            createSkill("recruitment_management", "招聘管理", Department.HR,
                "负责职位发布、简历筛选、面试安排等招聘工作流"),
            createSkill("employee_file_mgmt", "员工档案管理", Department.HR,
                "维护员工个人信息、合同、证件等档案"),
            createSkill("salary_calculation", "薪酬计算", Department.HR,
                "根据绩效、奖金、扣款等计算员工薪酬"),
            createSkill("attendance_stats", "考勤统计", Department.HR,
                "统计员工出勤情况、请假、迟到等"),
            createSkill("performance_evaluation", "绩效评估", Department.HR,
                "进行员工年度或定期绩效评估,生成评估报告")
        ));
        
        // ========== 财务部门:5个技能 ==========
        departmentSkills.put(Department.FINANCE, Arrays.asList(
            createSkill("financial_report", "财务报表生成", Department.FINANCE,
                "生成资产负债表、利润表、现金流量表等财务报表"),
            createSkill("cost_analysis", "成本分析", Department.FINANCE,
                "分析各部门、项目的成本组成和趋势"),
            createSkill("budget_planning", "预算规划", Department.FINANCE,
                "编制和管理部门年度预算"),
            createSkill("audit_compliance", "审计合规", Department.FINANCE,
                "进行内部审计,确保财务合规性"),
            createSkill("expense_reimbursement", "费用报销", Department.FINANCE,
                "处理员工差旅、会议等费用报销申请")
        ));
        
        // ========== IT部门:5个技能 ==========
        departmentSkills.put(Department.IT, Arrays.asList(
            createSkill("system_monitoring", "系统监控", Department.IT,
                "监控服务器、数据库、网络等系统状态"),
            createSkill("incident_diagnosis", "故障诊断", Department.IT,
                "诊断和解决系统故障、性能问题"),
            createSkill("resource_request", "资源申请", Department.IT,
                "处理服务器、许可证等IT资源申请"),
            createSkill("security_check", "安全检查", Department.IT,
                "进行系统安全检查,修复安全漏洞"),
            createSkill("data_backup", "数据备份", Department.IT,
                "执行定期数据备份,确保数据安全")
        ));
        
        // ========== 运营部门:5个技能 ==========
        departmentSkills.put(Department.OPERATIONS, Arrays.asList(
            createSkill("process_optimization", "流程优化", Department.OPERATIONS,
                "分析和优化业务流程,提高效率"),
            createSkill("kpi_statistics", "KPI统计", Department.OPERATIONS,
                "收集和统计关键业务指标"),
            createSkill("supply_chain_mgmt", "供应链管理", Department.OPERATIONS,
                "管理采购、库存、交付等供应链环节"),
            createSkill("quality_management", "质量管理", Department.OPERATIONS,
                "制定质量标准,进行质量检查和改进"),
            createSkill("risk_assessment", "风险评估", Department.OPERATIONS,
                "识别和评估业务风险,制定风险对策")
        ));
        
        // ========== 营销部门:5个技能 ==========
        departmentSkills.put(Department.MARKETING, Arrays.asList(
            createSkill("campaign_planning", "活动策划", Department.MARKETING,
                "策划营销活动,制定活动方案和预算"),
            createSkill("content_creation", "内容创建", Department.MARKETING,
                "创建营销文案、视频、图片等内容"),
            createSkill("user_segmentation", "用户分群", Department.MARKETING,
                "根据用户特征进行分群,支持精准营销"),
            createSkill("roi_analysis", "ROI分析", Department.MARKETING,
                "分析营销活动的投资回报率"),
            createSkill("brand_management", "品牌管理", Department.MARKETING,
                "管理品牌形象、宣传、危机公关等")
        ));
        
        int totalSkills = departmentSkills.values().stream().mapToInt(List::size).sum();
        logger.info("✓ 企业技能市场初始化完成");
        logger.info("  - 部门数: {}", departmentSkills.size());
        logger.info("  - 总技能数: {}", totalSkills);
        for (Department dept : Department.values()) {
            List<AgentSkill> skills = departmentSkills.get(dept);
            logger.info("  - {} 部门: {} 个技能", dept.getName(), skills.size());
        }
    }
    
    /**
     * 搜索技能
     */
    public List<SkillSearchResult> searchSkills(String keyword, Department... departments) 
            throws Exception {
        
        logger.info("搜索技能: keyword='{}', departments={}", 
            keyword, Arrays.toString(departments));
        
        List<Department> depts = Arrays.asList(departments);
        if (depts.isEmpty() || depts.get(0) == null) {
            depts = new ArrayList<>(departmentSkills.keySet());
        }
        
        List<SkillSearchResult> results = new ArrayList<>();
        
        for (Department dept : depts) {
            List<AgentSkill> skills = departmentSkills.getOrDefault(dept, Collections.emptyList());
            
            for (AgentSkill skill : skills) {
                // 检查是否匹配搜索关键词
                if (matchesKeyword(skill, keyword)) {
                    SkillRating rating = skillRatings.getOrDefault(skill.getId(),
                        SkillRating.builder()
                            .skillId(skill.getId())
                            .rating(4.5)
                            .reviewCount(0)
                            .usageCount(0)
                            .reviews(new ArrayList<>())
                            .build());
                    
                    results.add(SkillSearchResult.builder()
                        .skill(skill)
                        .department(dept)
                        .rating(rating.getRating())
                        .reviewCount(rating.getReviewCount())
                        .usageCount(rating.getUsageCount())
                        .build());
                }
            }
        }
        
        // 按评分降序排列
        results.sort((a, b) -> Double.compare(b.getRating(), a.getRating()));
        
        logger.info("搜索完成,找到 {} 个相关技能", results.size());
        
        return results;
    }
    
    private boolean matchesKeyword(AgentSkill skill, String keyword) {
        return skill.getName().contains(keyword) || 
               skill.getDisplayName().contains(keyword) ||
               skill.getDescription().contains(keyword);
    }
    
    /**
     * 获取指定部门的所有技能
     */
    public List<AgentSkill> getDepartmentSkills(Department department) {
        return departmentSkills.getOrDefault(department, Collections.emptyList());
    }
    
    /**
     * 对技能评分
     */
    public synchronized void rateSkill(String skillId, double rating, String review) {
        logger.debug("对技能评分: skillId={}, rating={}, review={}", skillId, rating, review);
        
        skillRatings.compute(skillId, (k, v) -> {
            if (v == null) {
                return SkillRating.builder()
                    .skillId(skillId)
                    .rating(rating)
                    .reviewCount(1)
                    .usageCount(1)
                    .reviews(new ArrayList<>(Collections.singletonList(review)))
                    .build();
            } else {
                // 计算新的平均评分
                double newRating = (v.getRating() * v.getReviewCount() + rating) 
                    / (v.getReviewCount() + 1);
                v.setRating(newRating);
                v.setReviewCount(v.getReviewCount() + 1);
                v.setUsageCount(v.getUsageCount() + 1);
                v.getReviews().add(review);
                return v;
            }
        });
    }
    
    /**
     * 获取技能评分
     */
    public SkillRating getSkillRating(String skillId) {
        return skillRatings.getOrDefault(skillId, SkillRating.builder()
            .skillId(skillId)
            .rating(4.0)
            .reviewCount(0)
            .usageCount(0)
            .reviews(new ArrayList<>())
            .build());
    }
    
    /**
     * 获取热门技能
     */
    public List<SkillSearchResult> getPopularSkills(int topN) {
        return departmentSkills.entrySet().stream()
            .flatMap(entry -> entry.getValue().stream()
                .map(skill -> {
                    SkillRating rating = getSkillRating(skill.getId());
                    return SkillSearchResult.builder()
                        .skill(skill)
                        .department(entry.getKey())
                        .rating(rating.getRating())
                        .reviewCount(rating.getReviewCount())
                        .usageCount(rating.getUsageCount())
                        .build();
                }))
            .sorted((a, b) -> Integer.compare(b.getUsageCount(), a.getUsageCount()))
            .limit(topN)
            .collect(Collectors.toList());
    }
    
    /**
     * 获取统计信息
     */
    public MarketplaceStatistics getStatistics() {
        int totalSkills = departmentSkills.values().stream().mapToInt(List::size).sum();
        double avgRating = skillRatings.values().stream()
            .mapToDouble(SkillRating::getRating)
            .average()
            .orElse(0.0);
        int totalUsages = skillRatings.values().stream()
            .mapToInt(SkillRating::getUsageCount)
            .sum();
        
        return MarketplaceStatistics.builder()
            .totalDepartments(departmentSkills.size())
            .totalSkills(totalSkills)
            .averageRating(avgRating)
            .totalUsages(totalUsages)
            .statisticsTime(LocalDateTime.now())
            .build();
    }
    
    private AgentSkill createSkill(String id, String displayName, Department dept, String description) {
        return AgentSkill.builder()
            .id(dept.getCode() + "_" + id)
            .name(id)
            .displayName(displayName)
            .description(description + " - 由" + dept.getName() + "提供")
            .version("1.0.0")
            .author(dept.getName())
            .category(dept.getCode().toLowerCase())
            .tags(List.of(dept.getName(), displayName))
            .createdAt(LocalDateTime.now())
            .updatedAt(LocalDateTime.now())
            .build();
    }
}

/**
 * 技能评分
 */
@Data
@Builder
class SkillRating {
    private String skillId;
    private double rating;           // 平均评分(1-5星)
    private int reviewCount;         // 评分总数
    private int usageCount;          // 使用次数
    private List<String> reviews;    // 用户评论
}

/**
 * 技能搜索结果
 */
@Data
@Builder
class SkillSearchResult {
    private AgentSkill skill;
    private Department department;
    private double rating;
    private int reviewCount;
    private int usageCount;
}

/**
 * 技能市场统计
 */
@Data
@Builder
class MarketplaceStatistics {
    private int totalDepartments;
    private int totalSkills;
    private double averageRating;
    private int totalUsages;
    private LocalDateTime statisticsTime;
}

第三步:跨部门协同编排器

/**
 * 跨部门协同协调器
 */
public class CrossDepartmentOrchestrator {
    
    private static final Logger logger = LoggerFactory.getLogger(CrossDepartmentOrchestrator.class);
    
    private final Map<Department, ReActAgent> departmentAgents;
    private final EnterpriseSkillMarketplace skillMarketplace;
    
    public CrossDepartmentOrchestrator(
            EnterpriseSkillMarketplace skillMarketplace,
            Model languageModel) {
        this.skillMarketplace = skillMarketplace;
        this.departmentAgents = initializeDepartmentAgents(languageModel);
    }
    
    /**
     * 初始化各部门Agent
     */
    private Map<Department, ReActAgent> initializeDepartmentAgents(Model languageModel) {
        logger.info("初始化各部门Agent...");
        
        Map<Department, ReActAgent> agents = new ConcurrentHashMap<>();
        
        for (Department dept : Department.values()) {
            List<AgentSkill> skills = skillMarketplace.getDepartmentSkills(dept);
            
            ReActAgent agent = ReActAgent.builder()
                .name(dept.getName() + " Agent")
                .model(languageModel)
                .skills(skills)
                .systemPrompt(buildDepartmentSystemPrompt(dept))
                .build();
            
            agents.put(dept, agent);
            
            logger.info("✓ 初始化 {} Agent(拥有 {} 个技能)", 
                dept.getName(), skills.size());
        }
        
        return agents;
    }
    
    /**
     * 处理跨部门任务
     */
    public CrossDepartmentTaskResult handleCrossDepartmentTask(CrossDepartmentTask task) 
            throws Exception {
        
        logger.info("\n" + "=".repeat(70));
        logger.info("开始处理跨部门任务");
        logger.info("任务ID: {}", task.getTaskId());
        logger.info("任务名称: {}", task.getTaskName());
        logger.info("发起部门: {}", task.getInitiatingDept().getName());
        logger.info("涉及部门: {}", 
            task.getInvolvedDepts().stream()
                .map(Department::getName)
                .collect(Collectors.joining(", ")));
        logger.info("=".repeat(70));
        
        long startTime = System.currentTimeMillis();
        List<DepartmentTaskResult> results = new ArrayList<>();
        
        try {
            // ========== Step 1:发起部门提出任务 ==========
            logger.info("\n[Step 1] {} 提出任务", task.getInitiatingDept().getName());
            ReActAgent initiatingAgent = departmentAgents.get(task.getInitiatingDept());
            
            String initiatingPrompt = String.format("""
                请处理以下跨部门任务:
                任务名称: %s
                任务数据: %s
                
                请分析这个任务涉及哪些步骤和其他部门的协助。
                """, task.getTaskName(), task.getTaskData());
            
            Msg initiatingResponse = initiatingAgent.call(Msg.builder()
                .textContent(initiatingPrompt)
                .build()).block();
            
            logger.info("✓ 任务提出完成");
            
            // ========== Step 2:各涉及部门并行处理任务 ==========
            logger.info("\n[Step 2] 各部门并行处理任务");
            
            ExecutorService executor = Executors.newFixedThreadPool(
                Math.min(task.getInvolvedDepts().size(), 5));
            
            List<CompletableFuture<DepartmentTaskResult>> futures = 
                task.getInvolvedDepts().stream()
                    .map(dept -> CompletableFuture.supplyAsync(() -> {
                        try {
                            return processDepartmentTask(dept, task);
                        } catch (Exception e) {
                            logger.error("{} 处理任务失败", dept.getName(), e);
                            return DepartmentTaskResult.failure(dept, e.getMessage());
                        }
                    }, executor))
                    .collect(Collectors.toList());
            
            // 等待所有部门完成
            for (CompletableFuture<DepartmentTaskResult> future : futures) {
                results.add(future.join());
            }
            
            executor.shutdown();
            
            // ========== Step 3:汇总结果 ==========
            logger.info("\n[Step 3] 汇总任务结果");
            
            long totalTime = System.currentTimeMillis() - startTime;
            
            logger.info("\n" + "=".repeat(70));
            logger.info("跨部门任务完成");
            logger.info("总耗时: {}ms", totalTime);
            printTaskSummary(results);
            logger.info("=".repeat(70));
            
            return buildTaskResult(task, results, totalTime);
            
        } catch (Exception e) {
            logger.error("跨部门任务执行失败", e);
            throw e;
        }
    }
    
    /**
     * 处理单个部门的任务
     */
    private DepartmentTaskResult processDepartmentTask(
            Department department,
            CrossDepartmentTask task) throws Exception {
        
        logger.info("  [{}] 开始处理任务...", department.getName());
        
        ReActAgent agent = departmentAgents.get(department);
        
        String taskPrompt = String.format("""
            跨部门任务详情:
            任务名称: %s
            发起部门: %s
            涉及部门: %s
            任务数据: %s
            
            请使用你部门的技能来完成这个任务。
            """,
            task.getTaskName(),
            task.getInitiatingDept().getName(),
            String.join(", ", task.getInvolvedDepts()
                .stream()
                .map(Department::getName)
                .collect(Collectors.toList())),
            task.getTaskData());
        
        long startTime = System.currentTimeMillis();
        
        Msg response = agent.call(Msg.builder()
            .textContent(taskPrompt)
            .build()).block();
        
        long duration = System.currentTimeMillis() - startTime;
        
        logger.info("  ✓ [{}] 完成处理(耗时: {}ms)", department.getName(), duration);
        
        return DepartmentTaskResult.builder()
            .department(department)
            .result(response.getTextContent())
            .duration(duration)
            .success(true)
            .build();
    }
    
    private void printTaskSummary(List<DepartmentTaskResult> results) {
        logger.info("\n【各部门执行结果】");
        for (DepartmentTaskResult result : results) {
            if (result.isSuccess()) {
                logger.info("  ✓ [{}] 成功完成(耗时: {}ms)", 
                    result.getDepartment().getName(), result.getDuration());
            } else {
                logger.info("  ✗ [{}] 执行失败: {}", 
                    result.getDepartment().getName(), result.getErrorMessage());
            }
        }
    }
    
    private String buildDepartmentSystemPrompt(Department dept) {
        List<AgentSkill> skills = skillMarketplace.getDepartmentSkills(dept);
        
        return String.format(
            "你是%s的智能Agent。你代表%s部门与其他部门协作。\n\n" +
            "你拥有以下技能(共%d个):\n%s\n\n" +
            "在处理跨部门任务时:\n" +
            "1. 优先使用自己部门的技能\n" +
            "2. 如果需要其他部门的帮助,请明确说明需要什么\n" +
            "3. 与其他部门保持友好和专业的协作态度\n" +
            "4. 及时反馈进展和结果",
            
            dept.getName(), dept.getName(), skills.size(),
            
            skills.stream()
                .map(s -> "- " + s.getDisplayName() + ": " + s.getDescription())
                .collect(Collectors.joining("\n")));
    }
    
    private CrossDepartmentTaskResult buildTaskResult(
            CrossDepartmentTask task,
            List<DepartmentTaskResult> results,
            long totalTime) {
        
        boolean allSuccess = results.stream().allMatch(DepartmentTaskResult::isSuccess);
        
        return CrossDepartmentTaskResult.builder()
            .taskId(task.getTaskId())
            .taskName(task.getTaskName())
            .departmentResults(results)
            .overallStatus(allSuccess ? "SUCCESS" : "PARTIAL_SUCCESS")
            .totalTime(totalTime)
            .completedAt(LocalDateTime.now())
            .build();
    }
}

/**
 * 部门任务结果
 */
@Data
@Builder
class DepartmentTaskResult {
    private Department department;
    private String result;
    private long duration;
    private boolean success;
    private String errorMessage;
    
    public static DepartmentTaskResult failure(Department dept, String error) {
        return DepartmentTaskResult.builder()
            .department(dept)
            .success(false)
            .errorMessage(error)
            .build();
    }
}

/**
 * 跨部门任务结果
 */
@Data
@Builder
class CrossDepartmentTaskResult {
    private String taskId;
    private String taskName;
    private List<DepartmentTaskResult> departmentResults;
    private String overallStatus;
    private long totalTime;
    private LocalDateTime completedAt;
}

23.1.4 完整运行示例

public class CrossDepartmentDemo {
    
    private static final Logger logger = LoggerFactory.getLogger(CrossDepartmentDemo.class);
    
    public static void main(String[] args) throws Exception {
        // ========== 初始化 ==========
        logger.info("初始化跨部门协同系统...");
        
        // 初始化语言模型
        Model languageModel = DashScopeModel.builder()
            .modelName("qwen-turbo")
            .apiKey(System.getenv("DASHSCOPE_API_KEY"))
            .build();
        
        // 创建技能市场
        EnterpriseSkillMarketplace marketplace = 
            new EnterpriseSkillMarketplace(new MockSearchEngine());
        
        // 创建协同协调器
        CrossDepartmentOrchestrator orchestrator = 
            new CrossDepartmentOrchestrator(marketplace, languageModel);
        
        // ========== 演示技能市场 ==========
        demonstrateSkillMarketplace(marketplace);
        
        // ========== 演示跨部门协同 ==========
        demonstrateEmployeeOffboarding(orchestrator);
        demonstrateProjectLaunch(orchestrator);
    }
    
    /**
     * 演示技能市场的功能
     */
    private static void demonstrateSkillMarketplace(
            EnterpriseSkillMarketplace marketplace) throws Exception {
        
        System.out.println("\n" + "=".repeat(70));
        System.out.println("演示1:企业技能市场");
        System.out.println("=".repeat(70));
        
        // 获取统计信息
        MarketplaceStatistics stats = marketplace.getStatistics();
        System.out.println("\n【技能市场统计】");
        System.out.println("部门数: " + stats.getTotalDepartments());
        System.out.println("技能总数: " + stats.getTotalSkills());
        System.out.println("平均评分: " + String.format("%.2f", stats.getAverageRating()));
        System.out.println("总使用次数: " + stats.getTotalUsages());
        
        // 搜索技能
        System.out.println("\n【搜索技能:'薪酬'】");
        List<SkillSearchResult> searchResults = marketplace.searchSkills("薪酬");
        for (SkillSearchResult result : searchResults) {
            System.out.println("  - [" + result.getDepartment().getName() + "] " +
                result.getSkill().getDisplayName() +
                " (评分: " + String.format("%.1f", result.getRating()) + 
                " 星, 使用: " + result.getUsageCount() + " 次)");
        }
        
        // 获取热门技能
        System.out.println("\n【热门技能 Top 5】");
        List<SkillSearchResult> topSkills = marketplace.getPopularSkills(5);
        int rank = 1;
        for (SkillSearchResult result : topSkills) {
            System.out.println("  " + rank + ". [" + result.getDepartment().getName() + "] " +
                result.getSkill().getDisplayName() +
                " (使用: " + result.getUsageCount() + " 次)");
            rank++;
        }
        
        // 各部门技能展示
        System.out.println("\n【各部门技能展示】");
        for (Department dept : Department.values()) {
            List<AgentSkill> skills = marketplace.getDepartmentSkills(dept);
            System.out.println("  " + dept.getName() + " (" + skills.size() + "个技能):");
            for (AgentSkill skill : skills) {
                System.out.println("    - " + skill.getDisplayName());
            }
        }
    }
    
    /**
     * 演示:员工离职流程
     */
    private static void demonstrateEmployeeOffboarding(
            CrossDepartmentOrchestrator orchestrator) throws Exception {
        
        System.out.println("\n" + "=".repeat(70));
        System.out.println("演示2:员工离职流程(跨部门协同)");
        System.out.println("=".repeat(70));
        
        CrossDepartmentTask task = CrossDepartmentTask.builder()
            .taskId("task_" + System.currentTimeMillis())
            .taskName("处理员工离职手续")
            .initiatingDept(Department.HR)
            .involvedDepts(Arrays.asList(
                Department.HR,
                Department.FINANCE,
                Department.IT,
                Department.OPERATIONS))
            .taskData(Map.of(
                "employeeId", "EMP_12345",
                "employeeName", "张三",
                "department", "销售部",
                "position", "高级销售经理",
                "lastWorkingDate", "2024-12-31",
                "reason", "个人发展"
            ))
            .createdAt(LocalDateTime.now())
            .status("PENDING")
            .build();
        
        CrossDepartmentTaskResult result = 
            orchestrator.handleCrossDepartmentTask(task);
        
        printTaskResult(result);
    }
    
    /**
     * 演示:新产品发布
     */
    private static void demonstrateProjectLaunch(
            CrossDepartmentOrchestrator orchestrator) throws Exception {
        
        System.out.println("\n" + "=".repeat(70));
        System.out.println("演示3:新产品发布(跨部门协同)");
        System.out.println("=".repeat(70));
        
        CrossDepartmentTask task = CrossDepartmentTask.builder()
            .taskId("task_" + System.currentTimeMillis())
            .taskName("新产品发布计划")
            .initiatingDept(Department.MARKETING)
            .involvedDepts(Arrays.asList(
                Department.MARKETING,
                Department.IT,
                Department.OPERATIONS,
                Department.FINANCE))
            .taskData(Map.of(
                "productName", "智能助手Pro",
                "productCode", "PROD_AI_2024",
                "releaseDate", "2024-02-15",
                "targetMarket", "企业客户",
                "budget", "5000000",
                "expectedRevenue", "50000000"
            ))
            .createdAt(LocalDateTime.now())
            .status("PENDING")
            .build();
        
        CrossDepartmentTaskResult result = 
            orchestrator.handleCrossDepartmentTask(task);
        
        printTaskResult(result);
    }
    
    /**
     * 打印任务结果
     */
    private static void printTaskResult(CrossDepartmentTaskResult result) {
        System.out.println("\n【任务执行结果】");
        System.out.println("任务ID: " + result.getTaskId());
        System.out.println("任务名称: " + result.getTaskName());
        System.out.println("总体状态: " + result.getOverallStatus());
        System.out.println("总耗时: " + result.getTotalTime() + "ms");
        
        System.out.println("\n【各部门执行情况】");
        for (DepartmentTaskResult deptResult : result.getDepartmentResults()) {
            String status = deptResult.isSuccess() ? "✓ 成功" : "✗ 失败";
            System.out.println("  [" + deptResult.getDepartment().getName() + "] " +
                status + " (耗时: " + deptResult.getDuration() + "ms)");
        }
        
        System.out.println("\n【完成时间】");
        System.out.println("  " + result.getCompletedAt());
    }
}

运行输出示例

======================================================================
演示2:员工离职流程(跨部门协同)
======================================================================

======================================================================
开始处理跨部门任务
任务ID: task_1704019807000
任务名称: 处理员工离职手续
发起部门: 人力资源部
涉及部门: 人力资源部, 财务部, 信息技术部, 运营部
======================================================================

[Step 1] 人力资源部 提出任务
✓ 任务提出完成

[Step 2] 各部门并行处理任务
  [人力资源部] 开始处理任务...
  [财务部] 开始处理任务...
  [信息技术部] 开始处理任务...
  [运营部] 开始处理任务...
  ✓ [人力资源部] 完成处理(耗时: 1234ms)
  ✓ [财务部] 完成处理(耗时: 987ms)
  ✓ [信息技术部] 完成处理(耗时: 1456ms)
  ✓ [运营部] 完成处理(耗时: 765ms)

[Step 3] 汇总任务结果

======================================================================
跨部门任务完成
总耗时: 4442ms

【各部门执行结果】
  ✓ [人力资源部] 成功完成(耗时: 1234ms)
  ✓ [财务部] 成功完成(耗时: 987ms)
  ✓ [信息技术部] 成功完成(耗时: 1456ms)
  ✓ [运营部] 成功完成(耗时: 765ms)

======================================================================

【任务执行结果】
任务ID: task_1704019807000
任务名称: 处理员工离职手续
总体状态: SUCCESS
总耗时: 4442ms

【各部门执行情况】
  [人力资源部] ✓ 成功 (耗时: 1234ms)
  [财务部] ✓ 成功 (耗时: 987ms)
  [信息技术部] ✓ 成功 (耗时: 1456ms)
  [运营部] ✓ 成功 (耗时: 765ms)

【完成时间】
  2024-12-30T15:30:42.123