阿里开源AgentScope多智能体框架解析系列(十三)第13章:Skill技能系统 - 构建企业级AI能力中台

155 阅读22分钟

导读

本章深入介绍Skill技能系统,这是AgentScope框架中用于标准化能力定义、组合和管理的核心组件。

在企业级AI应用中,我们经常面临以下挑战:

  • 如何复用已有的AI能力,避免重复开发?
  • 如何标准化不同团队开发的Agent能力?
  • 如何实现技能的版本管理和依赖管理?
  • 如何构建可组合、可扩展的AI能力体系?

本章将通过深入的技术讲解,帮助你掌握:

  • 技能的DSL(Domain-Specific Language)设计
  • 技能加载器的实现机制
  • 技能依赖图的解析和执行
  • 技能版本冲突的解决策略
  • 分布式技能仓库的设计

1. Skill系统架构设计(What - 是什么)

什么是Skill?

Skill(技能)是AgentScope中对Agent能力的标准化封装单元,类似于软件工程中的"组件"或"模块"。

Skill的定位:

软件工程类比:
├─ 函数/方法 → 基本能力单元
├─ 类/模块 → 能力的封装
├─ 库/框架 → 能力的集合
└─ Skill → Agent能力的标准化封装

Skill的核心价值:
┌─────────────────────────────────┐
│  标准化 (Standardization)      │  
│  → 统一的定义格式和接口        │
└─────────────────────────────────┘
           ↓
┌─────────────────────────────────┐
│  可复用 (Reusability)           │
│  → 一次定义,多处使用          │
└─────────────────────────────────┘
           ↓
┌─────────────────────────────────┐
│  可组合 (Composability)         │
│  → 技能可以相互依赖和调用      │
└─────────────────────────────────┘
           ↓
┌─────────────────────────────────┐
│  可管理 (Manageability)         │
│  → 版本控制、依赖管理、发布    │
└─────────────────────────────────┘
           ↓
┌─────────────────────────────────┐
│  可共享 (Shareability)          │
│  → 通过技能市场共享和交易      │
└─────────────────────────────────┘

Skill系统的整体架构

┌────────────────────────────────────────────────────────────┐
│                    Skill系统架构                            │
└────────────────────────────────────────────────────────────┘

┌──────────────┐
│ 技能定义层   │  
│ (Definition) │  ← Markdown DSL / Java Code
└──────┬───────┘
       ↓
┌──────────────┐
│ 技能加载层   │  
│ (Loader)     │  ← Parser + Validator + Resolver
└──────┬───────┘
       ↓
┌──────────────┐
│ 技能存储层   │  
│ (Storage)    │  ← Local File / Remote Repository / Database
└──────┬───────┘
       ↓
┌──────────────┐
│ 技能执行层   │  
│ (Executor)   │  ← Agent Integration + Dependency Resolution
└──────┬───────┘
       ↓
┌──────────────┐
│ 技能管理层   │  
│ (Management) │  ← Version Control + Marketplace + Analytics
└──────────────┘

Skill的完整组成

一个完整的Skill包含以下要素:

/**
 * Skill的数据模型
 */
@Data
@Builder
public class AgentSkill {
    // ========== 基础元信息 ==========
    private String id;                    // 唯一标识
    private String name;                  // 技能名称
    private String displayName;           // 显示名称
    private String description;           // 简短描述
    private String detailedDescription;   // 详细描述
    private String version;               // 版本号(语义化版本)
    private String author;                // 作者
    private String organization;          // 组织
    private LocalDateTime createdAt;      // 创建时间
    private LocalDateTime updatedAt;      // 更新时间
    private List<String> tags;            // 标签
    private List<String> keywords;        // 关键词
    private String category;              // 分类
    
    // ========== 技能定义 ==========
    private String objective;             // 技能目标
    private String usageMethod;           // 使用方法
    private Map<String, Object> inputSpec;     // 输入规范
    private Map<String, Object> outputSpec;    // 输出规范
    private List<SkillExample> examples;       // 使用示例
    private List<String> bestPractices;        // 最佳实践
    private List<String> limitations;          // 使用限制
    
    // ========== 依赖管理 ==========
    private List<SkillDependency> dependencies;  // 依赖的其他技能
    private List<SkillDependency> conflicts;     // 冲突的技能
    private Map<String, String> requires;        // 环境要求
    
    // ========== 执行配置 ==========
    private SkillExecutionConfig executionConfig;  // 执行配置
    private Map<String, Object> parameters;        // 可配置参数
    private SkillPerformanceMetrics metrics;       // 性能指标
    
    // ========== 质量保证 ==========
    private List<SkillTestCase> testCases;    // 测试用例
    private SkillQualityScore qualityScore;   // 质量评分
    private List<SkillReview> reviews;        // 用户评价
    
    // ========== 许可和计费 ==========
    private String license;               // 许可证
    private SkillPricing pricing;        // 定价信息
    private boolean isPublic;            // 是否公开
    
    // ========== 扩展字段 ==========
    private Map<String, Object> metadata;  // 自定义元数据
}

Skill定义语言(Skill DSL)

AgentScope使用Markdown + YAML Front Matter作为技能定义语言,这是一种既人类可读机器可解析的格式。

完整的Skill定义示例

---
# ========== 基础信息 ==========
id: skill-analytics-001
name: advanced_data_analytics
displayName: 高级数据分析
version: 2.1.0
author: DataScience Team
organization: AgentScope Inc.
createdAt: 2024-01-15T10:00:00Z
updatedAt: 2024-12-20T15:30:00Z

# ========== 分类和标签 ==========
category: analytics
tags:
  - data-analysis
  - statistics
  - visualization
  - business-intelligence
keywords:
  - 数据分析
  - 统计分析
  - 趋势预测
  - 异常检测
  - 相关性分析

# ========== 技能描述 ==========
description: >
  高级数据分析技能,支持统计分析、趋势预测、异常检测、
  相关性分析等多种分析方法。适用于销售数据、用户行为、
  业务指标等各类数据的深度分析。

detailedDescription: |
  本技能提供企业级的数据分析能力,包括:
  
  **核心功能**  - 描述性统计分析(均值、中位数、方差、分位数等)
  - 时间序列分析(趋势、季节性、周期性检测)
  - 异常值检测(基于统计方法和机器学习)
  - 相关性分析(Pearson、Spearman相关系数)
  - 聚类分析(K-means、DBSCAN等)
  - 回归分析(线性回归、逻辑回归)
  
  **技术特点**  - 支持大规模数据处理(百万级记录)
  - 自动数据预处理和清洗
  - 智能化的分析方法选择
  - 可视化结果输出
  - 业务洞察自动生成

# ========== 依赖管理 ==========
dependencies:
  - skill: statistical_summary
    version: ">=2.0.0"
    required: true
    reason: 提供基础统计计算能力
  
  - skill: data_visualization
    version: "^1.5.0"
    required: true
    reason: 生成图表和可视化
  
  - skill: data_preprocessing
    version: "~1.3.0"
    required: false
    reason: 高级数据清洗(可选)

conflicts:
  - skill: legacy_analytics
    reason: 功能重叠,可能导致执行冲突

requires:
  runtime: java
  minVersion: "17"
  memory: "512MB"
  libraries:
    - name: apache-commons-math
      version: "3.6.1"
    - name: jfreechart
      version: "1.5.3"

# ========== 执行配置 ==========
executionConfig:
  timeout: 300000  # 5分钟
  retries: 3
  parallelizable: true
  cacheable: true
  cacheExpiration: 3600  # 1小时

parameters:
  confidenceLevel:
    type: float
    default: 0.95
    min: 0.8
    max: 0.99
    description: 置信水平
  
  outlierThreshold:
    type: float
    default: 3.0
    min: 1.0
    max: 5.0
    description: 异常值检测的标准差倍数
  
  visualizationEnabled:
    type: boolean
    default: true
    description: 是否生成可视化图表

# ========== 性能指标 ==========
metrics:
  avgExecutionTime: 2500  # ms
  successRate: 0.987
  usageCount: 15234
  satisfactionScore: 4.7  # /5.0

# ========== 质量保证 ==========
qualityScore:
  overall: 4.8
  accuracy: 4.9
  performance: 4.6
  documentation: 4.9
  usability: 4.7

# ========== 许可和定价 ==========
license: Apache-2.0
pricing:
  model: freemium
  free:
    maxCalls: 1000
    maxDataSize: "10MB"
  premium:
    pricePerCall: 0.01  # USD
    pricePerMonth: 49.99  # USD
    features:
      - unlimited_calls
      - advanced_algorithms
      - priority_support

isPublic: true
---

# 高级数据分析技能

## 📋 技能目标

本技能旨在为Agent提供**企业级的数据分析能力**,能够从原始数据中提取有价值的洞察,支持业务决策。

**适用场景**- 销售数据分析和预测
- 用户行为分析
- 业务指标监控
- 市场趋势分析
- 运营效率评估

## 🔧 使用方法

### 基本流程

1. **数据准备**
   - 提供CSV、JSON或Excel格式的数据
   - 指定要分析的列和分析类型
   - 可选:配置分析参数

2. **执行分析**
   - 技能自动选择合适的分析方法
   - 执行数据预处理和清洗
   - 应用统计模型和算法

3. **结果输出**
   - 生成统计摘要
   - 输出可视化图表
   - 提供业务洞察和建议

### 高级用法

- **自定义分析流程**:通过参数配置选择特定的分析方法
- **批量分析**:同时分析多个数据集
- **增量分析**:基于历史分析结果进行增量更新
- **API集成**:通过RESTful API调用分析服务

## 📥 输入规范

```json
{
  "data": {
    "type": "object",
    "required": true,
    "description": "待分析的数据",
    "properties": {
      "format": {
        "type": "string",
        "enum": ["csv", "json", "excel", "parquet"],
        "default": "json"
      },
      "content": {
        "type": "string",
        "description": "数据内容或文件路径"
      },
      "columns": {
        "type": "array",
        "items": {"type": "string"},
        "description": "要分析的列名"
      }
    }
  },
  "analysisType": {
    "type": "array",
    "items": {
      "type": "string",
      "enum": [
        "statistical",      // 统计分析
        "trend",            // 趋势分析
        "anomaly",          // 异常检测
        "correlation",      // 相关性分析
        "clustering",       // 聚类分析
        "regression",       // 回归分析
        "forecasting"       // 预测分析
      ]
    },
    "default": ["statistical", "trend"]
  },
  "options": {
    "type": "object",
    "description": "可选配置",
    "properties": {
      "confidenceLevel": {"type": "number", "default": 0.95},
      "outlierThreshold": {"type": "number", "default": 3.0},
      "visualizationEnabled": {"type": "boolean", "default": true},
      "groupBy": {"type": "string", "description": "分组字段"},
      "timeSeries": {
        "type": "object",
        "properties": {
          "dateColumn": {"type": "string"},
          "frequency": {"type": "string", "enum": ["daily", "weekly", "monthly"]}
        }
      }
    }
  }
}

📤 输出规范

{
  "status": {
    "type": "string",
    "enum": ["success", "partial_success", "failure"],
    "description": "执行状态"
  },
  "summary": {
    "type": "object",
    "description": "统计摘要",
    "properties": {
      "recordCount": {"type": "integer"},
      "columnCount": {"type": "integer"},
      "missingValues": {"type": "object"},
      "dataTypes": {"type": "object"}
    }
  },
  "analyses": {
    "type": "array",
    "items": {
      "type": "object",
      "properties": {
        "type": {"type": "string"},
        "results": {"type": "object"},
        "confidence": {"type": "number"},
        "interpretation": {"type": "string"}
      }
    }
  },
  "visualizations": {
    "type": "array",
    "items": {
      "type": "object",
      "properties": {
        "type": {"type": "string", "enum": ["line", "bar", "scatter", "heatmap"]},
        "title": {"type": "string"},
        "data": {"type": "object"},
        "imageUrl": {"type": "string"}
      }
    }
  },
  "insights": {
    "type": "array",
    "items": {
      "type": "object",
      "properties": {
        "category": {"type": "string", "enum": ["trend", "anomaly", "pattern", "correlation"]},
        "severity": {"type": "string", "enum": ["high", "medium", "low"]},
        "description": {"type": "string"},
        "evidence": {"type": "array", "items": {"type": "string"}}
      }
    }
  },
  "recommendations": {
    "type": "array",
    "items": {
      "type": "object",
      "properties": {
        "priority": {"type": "string", "enum": ["critical", "high", "medium", "low"]},
        "action": {"type": "string"},
        "rationale": {"type": "string"},
        "expectedImpact": {"type": "string"}
      }
    }
  },
  "metadata": {
    "type": "object",
    "properties": {
      "executionTime": {"type": "integer", "description": "执行时间(毫秒)"},
      "skillVersion": {"type": "string"},
      "timestamp": {"type": "string", "format": "date-time"}
    }
  }
}

📚 使用示例

示例1:销售数据多维度分析

业务背景: 某电商公司需要分析过去12个月的销售数据,识别销售趋势、异常订单、地区差异等。

输入

{
  "data": {
    "format": "csv",
    "content": "sales_data_2024.csv",
    "columns": ["date", "amount", "region", "category", "quantity"]
  },
  "analysisType": ["statistical", "trend", "anomaly", "correlation"],
  "options": {
    "groupBy": "region",
    "timeSeries": {
      "dateColumn": "date",
      "frequency": "monthly"
    },
    "visualizationEnabled": true
  }
}

执行步骤

  1. 加载12个月的销售数据(约50万条记录)
  2. 执行数据清洗:处理缺失值、异常值
  3. 按地区分组进行统计分析
  4. 时间序列分析:识别月度趋势和季节性
  5. 异常检测:标记异常订单和异常波动
  6. 相关性分析:分析销售额与其他因素的关系
  7. 生成可视化图表:折线图、柱状图、热力图
  8. 提取业务洞察和建议

输出

{
  "status": "success",
  "summary": {
    "recordCount": 487235,
    "columnCount": 5,
    "dateRange": "2024-01-01 to 2024-12-31",
    "totalRevenue": 15847892.50
  },
  "analyses": [
    {
      "type": "statistical",
      "results": {
        "byRegion": {
          "North": {"mean": 325.50, "median": 298.00, "std": 127.30},
          "South": {"mean": 412.80, "median": 389.00, "std": 156.20},
          "East": {"mean": 378.90, "median": 345.00, "std": 142.10},
          "West": {"mean": 295.60, "median": 275.00, "std": 98.70}
        }
      },
      "confidence": 0.95,
      "interpretation": "南部地区平均订单金额最高,西部地区最低但波动性也最小"
    },
    {
      "type": "trend",
      "results": {
        "overallTrend": "increasing",
        "growthRate": 0.187,
        "seasonality": {
          "pattern": "quarterly",
          "peaks": ["Q2", "Q4"],
          "troughs": ["Q1", "Q3"]
        }
      },
      "confidence": 0.89,
      "interpretation": "整体销售呈上升趋势,年增长率18.7%,Q2和Q4是销售旺季"
    },
    {
      "type": "anomaly",
      "results": {
        "anomalyCount": 247,
        "anomalyRate": 0.0005,
        "topAnomalies": [
          {"date": "2024-03-15", "amount": 8950.00, "zscore": 4.2},
          {"date": "2024-07-22", "amount": 9200.00, "zscore": 4.5},
          {"date": "2024-11-11", "amount": 12500.00, "zscore": 5.8}
        ]
      },
      "confidence": 0.92,
      "interpretation": "检测到247个异常订单,主要集中在促销活动期间"
    }
  ],
  "insights": [
    {
      "category": "trend",
      "severity": "high",
      "description": "销售额呈现稳定增长趋势,预计明年可达1850万",
      "evidence": ["月度增长率平均1.5%", "Q4增长加速至2.1%", "客单价稳步提升"]
    },
    {
      "category": "pattern",
      "severity": "medium",
      "description": "明显的季节性模式,Q2和Q4是销售高峰",
      "evidence": ["Q2平均增长35%", "Q4增长42%", "与节假日高度相关"]
    },
    {
      "category": "correlation",
      "severity": "high",
      "description": "南部地区销售额与营销投入呈强正相关",
      "evidence": ["相关系数0.87", "每增加1万营销投入,销售额平均增加15万"]
    }
  ],
  "recommendations": [
    {
      "priority": "critical",
      "action": "加大Q2和Q4的库存备货,提前1个月准备",
      "rationale": "历史数据显示这两个季度需求激增,库存不足风险高",
      "expectedImpact": "预计可减少缺货率50%,增加销售额8-12%"
    },
    {
      "priority": "high",
      "action": "针对南部地区加大营销投入,ROI最高",
      "rationale": "南部地区对营销活动响应度最高,客单价也最高",
      "expectedImpact": "预计ROI提升15-20%"
    },
    {
      "priority": "medium",
      "action": "分析西部地区低销售原因,制定改进方案",
      "rationale": "西部地区销售额明显低于其他地区",
      "expectedImpact": "挖掘市场潜力,预计增长空间30%以上"
    }
  ],
  "metadata": {
    "executionTime": 2347,
    "skillVersion": "2.1.0",
    "timestamp": "2024-12-30T10:30:00Z"
  }
}

业务价值

  • 发现销售增长机会:预测明年可达1850万
  • 优化库存管理:提前备货减少缺货
  • 精准营销投放:聚焦高ROI地区
  • 市场潜力挖掘:改进低表现地区

示例2:用户行为深度分析

业务背景: SaaS公司需要分析用户的使用行为,识别流失风险、提升活跃度、优化产品功能。

输入

{
  "data": {
    "format": "json",
    "content": "user_behavior_logs.json",
    "columns": ["user_id", "timestamp", "action", "duration", "feature", "device"]
  },
  "analysisType": ["statistical", "clustering", "correlation"],
  "options": {
    "confidenceLevel": 0.95,
    "groupBy": "feature"
  }
}

分析维度

  1. 用户活跃度分析

    • 日活(DAU)、周活(WAU)、月活(MAU)
    • 留存率分析:次日、7日、30日留存
    • 活跃时段分布
  2. 用户分层

    • 基于RFM模型的用户价值分层
    • K-means聚类识别用户群体
    • 高价值用户特征分析
  3. 功能使用分析

    • 各功能的使用频率和时长
    • 功能间的跳转路径
    • 冷门功能识别
  4. 流失风险预测

    • 流失用户特征提取
    • 流失预警指标
    • 挽回策略建议

输出洞察

{
  "insights": [
    {
      "category": "pattern",
      "severity": "high",
      "description": "用户在使用'高级功能A'后,留存率提升35%",
      "evidence": [
        "使用过该功能的用户7日留存率达78%,未使用仅43%",
        "该功能的用户NPS评分高出平均值22分"
      ]
    },
    {
      "category": "anomaly",
      "severity": "critical",
      "description": "识别出15%的用户存在流失风险",
      "evidence": [
        "连续7天未登录",
        "最近30天使用时长下降60%",
        "未参与任何营销活动"
      ]
    }
  ],
  "recommendations": [
    {
      "priority": "critical",
      "action": "针对流失风险用户推送个性化内容和优惠",
      "rationale": "及时挽回可减少50%的流失",
      "expectedImpact": "预计挽回3000+用户,价值约15万月费"
    },
    {
      "priority": "high",
      "action": "在新用户引导中重点突出'高级功能A'",
      "rationale": "提升该功能的渗透率可显著提升留存",
      "expectedImpact": "预计整体留存率提升10-15%"
    }
  ]
}

示例3:实时业务监控仪表盘

场景:运营团队需要实时监控关键业务指标,快速发现异常并响应。

持续分析配置

{
  "mode": "streaming",
  "dataSource": {
    "type": "kafka",
    "topic": "business_metrics",
    "pollInterval": 60000  // 1分钟
  },
  "analysisType": ["statistical", "anomaly", "trend"],
  "options": {
    "alertThreshold": {
      "orderVolume": {"min": 100, "max": 5000},
      "averageOrderValue": {"min": 50, "max": 1000},
      "conversionRate": {"min": 0.02}
    },
    "alertChannels": ["email", "slack", "sms"]
  }
}

实时告警示例

{
  "alert": {
    "level": "critical",
    "metric": "conversionRate",
    "currentValue": 0.0125,
    "expectedValue": 0.035,
    "deviation": -64.3,
    "detectedAt": "2024-12-30T14:25:00Z",
    "possibleCauses": [
      "支付系统响应缓慢",
      "商品详情页加载失败",
      "营销活动配置错误"
    ],
    "suggestedActions": [
      "立即检查支付网关状态",
      "回滚最近的前端部署",
      "暂停当前营销活动"
    ]
  }
}

⚠️ 使用限制

  1. 数据规模限制

    • 免费版:最大10MB数据,1000次/月
    • 高级版:最大1GB数据,无限次调用
    • 企业版:无限制
  2. 性能考虑

    • 大数据集(>100万行)建议使用采样分析
    • 复杂分析(聚类、回归)可能需要5-10分钟
    • 实时分析模式延迟<5秒
  3. 数据质量要求

    • 至少70%的数据完整性
    • 数值列不应包含过多异常值
    • 时间序列数据需要连续性
  4. 兼容性

    • 需要Java 17+
    • 建议内存:>=512MB
    • 推荐CPU:>=2核心

✅ 最佳实践

数据准备

// ✓ 好的做法
public void prepareData() {
    // 1. 数据清洗
    data.removeNullValues();
    data.handleMissingValues(strategy = "median");
    
    // 2. 数据验证
    validator.checkDataQuality(data);
    if (validator.getCompleteness() < 0.7) {
        throw new DataQualityException("数据完整性不足");
    }
    
    // 3. 数据转换
    data.normalizeNumericColumns();
    data.encodeCategoricalColumns();
}

// ✗ 不好的做法
public void prepareData() {
    // 直接使用原始数据,可能包含大量噪声和异常值
    analyzeDirectly(rawData);
}

分析方法选择

// ✓ 根据数据特征选择合适的方法
public AnalysisType selectAnalysisMethod(Dataset data) {
    if (data.isTimeSeries()) {
        return AnalysisType.TREND_ANALYSIS;
    } else if (data.hasCategoricalTarget()) {
        return AnalysisType.CLASSIFICATION;
    } else if (data.hasContinuousTarget()) {
        return AnalysisType.REGRESSION;
    } else {
        return AnalysisType.STATISTICAL_SUMMARY;
    }
}

// ✗ 盲目使用所有分析方法
public void analyze(Dataset data) {
    // 浪费计算资源,结果可能无意义
    runAll Analysis(data);
}

结果解释

// ✓ 提供业务相关的洞察
public Insight generateInsight(AnalysisResult result) {
    return Insight.builder()
        .description("销售额Q4增长42%,主要由促销活动驱动")
        .evidence(List.of(
            "促销期间日均订单量增加3倍",
            "客单价提升25%",
            "新客户占比达35%"
        ))
        .recommendation("建议在Q1继续推出类似促销活动")
        .expectedImpact("预计可增加销售额15-20%")
        .build();
}

// ✗ 仅输出统计数字
public String generateInsight(AnalysisResult result) {
    return "Mean: 425.5, Std: 127.3";
}

性能优化

// ✓ 大数据集使用采样
public void analyzeL argeDataset(Dataset data) {
    if (data.size() > 1_000_000) {
        Dataset sample = data.randomSample(100_000);
        AnalysisResult result = analyze(sample);
        result.addNote("基于10万样本的分析结果");
        return result;
    }
    return analyze(data);
}

// ✓ 启用缓存
@Cacheable(key = "#dataHash", expiration = "1h")
public AnalysisResult analyze(String dataHash, Dataset data) {
    return performAnalysis(data);
}

Skill定义的关键要素解析

1. YAML Front Matter(元数据)

---
# 这部分是机器可解析的结构化数据
id: skill-analytics-001          # 全局唯一ID
name: advanced_data_analytics    # 技能名称(programmatic)
displayName: 高级数据分析        # 显示名称(human-readable)
version: 2.1.0                   # 语义化版本
...
---

设计考虑

  • 使用YAML格式便于人类阅读和编辑
  • 结构化数据便于程序解析和验证
  • 版本号遵循SemVer规范(Major.Minor.Patch)

2. Markdown Body(文档)

# 技能标题

## 各个章节...

设计考虑

  • Markdown格式便于编写和渲染
  • 支持代码高亮、表格、链接等丰富格式
  • 可以生成HTML文档供用户浏览

3. 依赖管理

dependencies:
  - skill: statistical_summary
    version: ">=2.0.0"      # 语义化版本约束
    required: true
    reason: 提供基础统计计算能力

版本约束语法

  • "1.0.0" - 精确匹配
  • ">=1.0.0" - 大于等于
  • "^1.5.0" - 兼容版本(1.5.x,但不包括2.x)
  • "~1.3.0" - 近似版本(1.3.x)
  • "1.0.0 - 2.0.0" - 范围

(How - 如何实现)

Skill加载器的完整实现

/**
 * Skill加载器:负责从各种来源加载Skill定义
 */
public class SkillLoader {
    
    private static final Logger logger = LoggerFactory.getLogger(SkillLoader.class);
    private static final SkillValidator validator = new SkillValidator();
    private static final DependencyResolver dependencyResolver = new DependencyResolver();
    private static final Map<String, AgentSkill> skillCache = new ConcurrentHashMap<>();
    
    /**
     * 从Mark down文件加载Skill(主要方式)
     */
    public static AgentSkill loadFromMarkdown(String markdownContent) 
            throws SkillLoadException {
        try {
            // 1. 解析YAML Front Matter
            SkillMetadata metadata = parseYamlFrontMatter(markdownContent);
            
            // 2. 解析Markdown Body
            SkillDocumentation doc = parseMarkdownBody(markdownContent);
            
            // 3. 构建AgentSkill对象
            AgentSkill skill = AgentSkill.builder()
                .id(metadata.getId())
                .name(metadata.getName())
                .displayName(metadata.getDisplayName())
                .description(metadata.getDescription())
                .detailedDescription(metadata.getDetailedDescription())
                .version(metadata.getVersion())
                .author(metadata.getAuthor())
                .organization(metadata.getOrganization())
                .createdAt(metadata.getCreatedAt())
                .updatedAt(metadata.getUpdatedAt())
                .tags(metadata.getTags())
                .keywords(metadata.getKeywords())
                .category(metadata.getCategory())
                .objective(doc.getObjective())
                .usageMethod(doc.getUsageMethod())
                .inputSpec(doc.getInputSpec())
                .outputSpec(doc.getOutputSpec())
                .examples(doc.getExamples())
                .bestPractices(doc.getBestPractices())
                .limitations(doc.getLimitations())
                .dependencies(metadata.getDependencies())
                .conflicts(metadata.getConflicts())
                .requires(metadata.getRequires())
                .executionConfig(metadata.getExecutionConfig())
                .parameters(metadata.getParameters())
                .metrics(metadata.getMetrics())
                .testCases(doc.getTestCases())
                .qualityScore(metadata.getQualityScore())
                .reviews(metadata.getReviews())
                .license(metadata.getLicense())
                .pricing(metadata.getPricing())
                .isPublic(metadata.isPublic())
                .metadata(metadata.getCustomMetadata())
                .build();
            
            // 4. 验证Skill定义
            ValidationResult validationResult = validator.validate(skill);
            if (!validationResult.isValid()) {
                throw new SkillValidationException(
                    "Skill验证失败: " + validationResult.getErrors()
                );
            }
            
            // 5. 解析依赖
            DependencyResolutionResult depResult = dependencyResolver.resolve(skill);
            if (!depResult.isResolved()) {
                logger.warn("依赖解析失败: {}", depResult.getUnresolvedDependencies());
            }
            
            // 6. 缓存Skill
            skillCache.put(skill.getId(), skill);
            
            logger.info("✓ 成功加载技能: {} v{}", skill.getName(), skill.getVersion());
            return skill;
            
        } catch (Exception e) {
            logger.error("加载技能失败", e);
            throw new SkillLoadException("无法加载技能: " + e.getMessage(), e);
        }
    }
    
    /**
     * 从本地文件加载
     */
    public static AgentSkill loadFromFile(Path skillFile) throws SkillLoadException {
        try {
            String content = Files.readString(skillFile, StandardCharsets.UTF_8);
            return loadFromMarkdown(content);
        } catch (IOException e) {
            throw new SkillLoadException("读取文件失败: " + skillFile, e);
        }
    }
    
    /**
     * 从远程URL加载
     */
    public static AgentSkill loadFromURL(String url) throws SkillLoadException {
        try {
            // 检查缓存
            String cacheKey = "url:" + url;
            if (skillCache.containsKey(cacheKey)) {
                logger.debug("从缓存加载: {}", url);
                return skillCache.get(cacheKey);
            }
            
            // 下载内容
            HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .timeout(Duration.ofSeconds(30))
                .build();
            
            HttpResponse<String> response = client.send(
                request, 
                HttpResponse.BodyHandlers.ofString()
            );
            
            if (response.statusCode() != 200) {
                throw new SkillLoadException(
                    "HTTP错误: " + response.statusCode()
                );
            }
            
            AgentSkill skill = loadFromMarkdown(response.body());
            skillCache.put(cacheKey, skill);
            return skill;
            
        } catch (Exception e) {
            throw new SkillLoadException("从 URL 加载失败: " + url, e);
        }
    }
    
    /**
     * 从Java代码定义加载
     */
    public static AgentSkill loadFromClass(Class<? extends SkillDefinition> skillClass) 
            throws SkillLoadException {
        try {
            SkillDefinition skillDef = skillClass.getDeclaredConstructor().newInstance();
            AgentSkill skill = skillDef.define();
            
            // 验证
            ValidationResult validationResult = validator.validate(skill);
            if (!validationResult.isValid()) {
                throw new SkillValidationException(
                    "Skill验证失败: " + validationResult.getErrors()
                );
            }
            
            skillCache.put(skill.getId(), skill);
            return skill;
            
        } catch (Exception e) {
            throw new SkillLoadException("从类加载失败: " + skillClass.getName(), e);
        }
    }
    
    /**
     * 批量加载技能
     */
    public static List<AgentSkill> loadFromDirectory(Path directory) 
            throws SkillLoadException {
        List<AgentSkill> skills = new ArrayList<>();
        
        try (Stream<Path> paths = Files.walk(directory)) {
            List<Path> skillFiles = paths
                .filter(Files::isRegularFile)
                .filter(p -> p.toString().endsWith(".md"))
                .collect(Collectors.toList());
            
            logger.info("发现 {} 个技能文件", skillFiles.size());
            
            for (Path skillFile : skillFiles) {
                try {
                    AgentSkill skill = loadFromFile(skillFile);
                    skills.add(skill);
                } catch (SkillLoadException e) {
                    logger.error("加载失败: {}", skillFile, e);
                    // 继续加载其他技能
                }
            }
            
        } catch (IOException e) {
            throw new SkillLoadException("遍历目录失败: " + directory, e);
        }
        
        logger.info("✓ 成功加载 {} 个技能", skills.size());
        return skills;
    }
    
    /**
     * 清理缓存
     */
    public static void clearCache() {
        skillCache.clear();
        logger.info("技能缓存已清理");
    }
    
    /**
     * 获取缓存的技能
     */
    public static Optional<AgentSkill> getCached(String skillId) {
        return Optional.ofNullable(skillCache.get(skillId));
    }
    
    // ========== 私有辅助方法 ==========
    
    private static SkillMetadata parseYamlFrontMatter(String content) {
        // 提取YAML Front Matter
        Pattern pattern = Pattern.compile("^---\\s*\\n(.*?)\\n---\\s*\\n", 
            Pattern.DOTALL);
        Matcher matcher = pattern.matcher(content);
        
        if (!matcher.find()) {
            throw new IllegalArgumentException("未找到YAML Front Matter");
        }
        
        String yamlContent = matcher.group(1);
        
        // 解析YAML
        Yaml yaml = new Yaml();
        Map<String, Object> yamlData = yaml.load(yamlContent);
        
        // 转换为SkillMetadata
        return SkillMetadata.fromMap(yamlData);
    }
    
    private static SkillDocumentation parseMarkdownBody(String content) {
        // 移除YAML Front Matter
        String markdownBody = content.replaceFirst(
            "^---\\s*\\n.*?\\n---\\s*\\n", 
            ""
        );
        
        // 解析Markdown结构
        CommonMarkParser parser = CommonMarkParser.builder().build();
        Node document = parser.parse(markdownBody);
        
        // 提取各个章节
        SkillDocumentation.Builder docBuilder = SkillDocumentation.builder();
        
        document.accept(new AbstractVisitor() {
            private String currentSection = null;
            private StringBuilder sectionContent = new StringBuilder();
            
            @Override
            public void visit(Heading heading) {
                // 处理上一个章节
                if (currentSection != null) {
                    processSection(currentSection, sectionContent.toString(), docBuilder);
                }
                
                // 开始新章节
                currentSection = ((Text)heading.getFirstChild()).getLiteral();
                sectionContent = new StringBuilder();
                
                super.visit(heading);
            }
            
            @Override
            public void visit(Text text) {
                if (currentSection != null) {
                    sectionContent.append(text.getLiteral());
                }
                super.visit(text);
            }
        });
        
        return docBuilder.build();
    }
    
    private static void processSection(String section, String content, 
            SkillDocumentation.Builder builder) {
        switch (section.trim()) {
            case "技能目标":
            case "📋 技能目标":
                builder.objective(content.trim());
                break;
            case "使用方法":
            case "🔧 使用方法":
                builder.usageMethod(content.trim());
                break;
            case "输入规范":
            case "📥 输入规范":
                builder.inputSpec(parseJsonSchema(content));
                break;
            case "输出规范":
            case "📤 输出规范":
                builder.outputSpec(parseJsonSchema(content));
                break;
            case "使用示例":
            case "📚 使用示例":
                builder.examples(parseExamples(content));
                break;
            case "最佳实践":
            case "✅ 最佳实践":
                builder.bestPractices(parseBestPractices(content));
                break;
            case "使用限制":
            case "⚠️ 使用限制":
                builder.limitations(parseLimitations(content));
                break;
        }
    }
    
    private static Map<String, Object> parseJsonSchema(String content) {
        // 提取JSON代码块
        Pattern pattern = Pattern.compile("```json\\s*\\n(.*?)\\n```", 
            Pattern.DOTALL);
        Matcher matcher = pattern.matcher(content);
        
        if (matcher.find()) {
            String jsonContent = matcher.group(1);
            ObjectMapper mapper = new ObjectMapper();
            try {
                return mapper.readValue(jsonContent, 
                    new TypeReference<Map<String, Object>>() {});
            } catch (JsonProcessingException e) {
                logger.error("解析JSON Schema失败", e);
                return Collections.emptyMap();
            }
        }
        
        return Collections.emptyMap();
    }
    
    private static List<SkillExample> parseExamples(String content) {
        // TODO: 实现示例解析逻辑
        return Collections.emptyList();
    }
    
    private static List<String> parseBestPractices(String content) {
        // TODO: 实现最佳实践解析逻辑
        return Collections.emptyList();
    }
    
    private static List<String> parseLimitations(String content) {
        // TODO: 实现限制解析逻辑
        return Collections.emptyList();
    }
}

Skill验证器

/**
 * Skill验证器:验证Skill定义的完整性和正确性
 */
public class SkillValidator {
    
    private static final Logger logger = LoggerFactory.getLogger(SkillValidator.class);
    
    /**
     * 验证Skill
     */
    public ValidationResult validate(AgentSkill skill) {
        List<ValidationError> errors = new ArrayList<>();
        List<ValidationWarning> warnings = new ArrayList<>();
        
        // 1. 验证基础信息
        validateBasicInfo(skill, errors);
        
        // 2. 验证版本号
        validateVersion(skill, errors);
        
        // 3. 验证依赖
        validateDependencies(skill, errors, warnings);
        
        // 4. 验证输入/输出Schema
        validateSchemas(skill, errors);
        
        // 5. 验证示例
        validateExamples(skill, warnings);
        
        // 6. 验证执行配置
        validateExecutionConfig(skill, warnings);
        
        return ValidationResult.builder()
            .valid(errors.isEmpty())
            .errors(errors)
            .warnings(warnings)
            .build();
    }
    
    private void validateBasicInfo(AgentSkill skill, List<ValidationError> errors) {
        // 必填字段
        if (StringUtils.isBlank(skill.getId())) {
            errors.add(new ValidationError("id", "技能ID不能为空"));
        }
        
        if (StringUtils.isBlank(skill.getName())) {
            errors.add(new ValidationError("name", "技能名称不能为空"));
        } else {
            // 验证命名规范:小写字母、数字、下划线
            if (!skill.getName().matches("^[a-z0-9_]+$")) {
                errors.add(new ValidationError("name", 
                    "技能名称应仅包含小写字母、数字和下划线"));
            }
        }
        
        if (StringUtils.isBlank(skill.getDescription())) {
            errors.add(new ValidationError("description", "技能描述不能为空"));
        }
        
        // 检查描述长度
        if (skill.getDescription() != null && skill.getDescription().length() > 200) {
            errors.add(new ValidationError("description", 
                "简短描述应少于200字符"));
        }
    }
    
    private void validateVersion(AgentSkill skill, List<ValidationError> errors) {
        if (StringUtils.isBlank(skill.getVersion())) {
            errors.add(new ValidationError("version", "版本号不能为空"));
            return;
        }
        
        // 验证语义化版本号格式:Major.Minor.Patch
        if (!skill.getVersion().matches("^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.]+)?$")) {
            errors.add(new ValidationError("version", 
                "版本号应遵循SemVer格式(如: 1.0.0, 2.1.0-beta)"));
        }
    }
    
    private void validateDependencies(AgentSkill skill, 
            List<ValidationError> errors, 
            List<ValidationWarning> warnings) {
        if (skill.getDependencies() == null || skill.getDependencies().isEmpty()) {
            return;
        }
        
        for (SkillDependency dep : skill.getDependencies()) {
            // 验证依赖名称
            if (StringUtils.isBlank(dep.getSkillName())) {
                errors.add(new ValidationError("dependencies", 
                    "依赖技能名称不能为空"));
            }
            
            // 验证版本约束
            if (StringUtils.isBlank(dep.getVersionConstraint())) {
                warnings.add(new ValidationWarning("dependencies", 
                    "建议指定依赖的版本约束: " + dep.getSkillName()));
            }
            
            // 验证版本约束语法
            if (!isValidVersionConstraint(dep.getVersionConstraint())) {
                errors.add(new ValidationError("dependencies", 
                    "无效的版本约束: " + dep.getVersionConstraint()));
            }
        }
        
        // 检查循环依赖
        if (hasCircularDependency(skill)) {
            errors.add(new ValidationError("dependencies", 
                "检测到循环依赖"));
        }
    }
    
    private void validateSchemas(AgentSkill skill, List<ValidationError> errors) {
        // 验证输入Schema
        if (skill.getInputSpec() != null) {
            try {
                validateJsonSchema(skill.getInputSpec());
            } catch (Exception e) {
                errors.add(new ValidationError("inputSpec", 
                    "输入Schema格式错误: " + e.getMessage()));
            }
        }
        
        // 验证输出Schema
        if (skill.getOutputSpec() != null) {
            try {
                validateJsonSchema(skill.getOutputSpec());
            } catch (Exception e) {
                errors.add(new ValidationError("outputSpec", 
                    "输出Schema格式错误: " + e.getMessage()));
            }
        }
    }
    
    private void validateExamples(AgentSkill skill, List<ValidationWarning> warnings) {
        if (skill.getExamples() == null || skill.getExamples().isEmpty()) {
            warnings.add(new ValidationWarning("examples", 
                "建议提供至少一个使用示例"));
        }
    }
    
    private void validateExecutionConfig(AgentSkill skill, 
            List<ValidationWarning> warnings) {
        SkillExecutionConfig config = skill.getExecutionConfig();
        if (config == null) {
            return;
        }
        
        // 检查超时设置
        if (config.getTimeout() <= 0) {
            warnings.add(new ValidationWarning("executionConfig.timeout", 
                "超时时间应大于0"));
        }
        
        if (config.getTimeout() > 600000) {  // 10分钟
            warnings.add(new ValidationWarning("executionConfig.timeout", 
                "超时时间过长,可能影响用户体验"));
        }
        
        // 检查重试次数
        if (config.getRetries() > 5) {
            warnings.add(new ValidationWarning("executionConfig.retries", 
                "重试次数过多,建议不超过5次"));
        }
    }
    
    private boolean isValidVersionConstraint(String constraint) {
        if (StringUtils.isBlank(constraint)) {
            return false;
        }
        
        // 支持的格式:>=1.0.0, ^1.5.0, ~1.3.0, 1.0.0 - 2.0.0
        String[] patterns = {
            "^\\d+\\.\\d+\\.\\d+$",                    // 1.0.0
            "^[><=!]+\\d+\\.\\d+\\.\\d+$",              // >=1.0.0, <=2.0.0
            "^\\^\\d+\\.\\d+\\.\\d+$",                   // ^1.5.0
            "^~\\d+\\.\\d+\\.\\d+$",                    // ~1.3.0
            "^\\d+\\.\\d+\\.\\d+ - \\d+\\.\\d+\\.\\d+$"  // 1.0.0 - 2.0.0
        };
        
        for (String pattern : patterns) {
            if (constraint.matches(pattern)) {
                return true;
            }
        }
        
        return false;
    }
    
    private boolean hasCircularDependency(AgentSkill skill) {
        // TODO: 实现循环依赖检测
        return false;
    }
    
    private void validateJsonSchema(Map<String, Object> schema) {
        // TODO: 使用JSON Schema验证器
    }
}

/**
 * 验证结果
 */
@Data
@Builder
public class ValidationResult {
    private boolean valid;
    private List<ValidationError> errors;
    private List<ValidationWarning> warnings;
    
    public String getErrorSummary() {
        if (valid) {
            return "验证通过";
        }
        
        StringBuilder sb = new StringBuilder("验证失败:\n");
        for (ValidationError error : errors) {
            sb.append("  - ").append(error.getField())
              .append(": ").append(error.getMessage())
              .append("\n");
        }
        return sb.toString();
    }
}

@Data
@AllArgsConstructor
public class ValidationError {
    private String field;
    private String message;
}

@Data
@AllArgsConstructor
public class ValidationWarning {
    private String field;
    private String message;
}

依赖解析器

/**
 * 依赖解析器:解析技能的依赖关系
 */
public class DependencyResolver {
    
    private static final Logger logger = LoggerFactory.getLogger(DependencyResolver.class);
    private final SkillRepository repository;
    
    public DependencyResolver() {
        this.repository = null;  // 默认使用全局仓库
    }
    
    public DependencyResolver(SkillRepository repository) {
        this.repository = repository;
    }
    
    /**
     * 解析技能的所有依赖
     */
    public DependencyResolutionResult resolve(AgentSkill skill) {
        Map<String, AgentSkill> resolvedDeps = new HashMap<>();
        List<String> unresolvedDeps = new ArrayList<>();
        List<String> conflicts = new ArrayList<>();
        
        if (skill.getDependencies() == null || skill.getDependencies().isEmpty()) {
            return DependencyResolutionResult.builder()
                .resolved(true)
                .dependencies(Collections.emptyMap())
                .unresolvedDependencies(Collections.emptyList())
                .conflicts(Collections.emptyList())
                .build();
        }
        
        // 构建依赖图
        DependencyGraph graph = buildDependencyGraph(skill);
        
        // 拓扑排序
        List<String> sortedDeps = graph.topologicalSort();
        
        // 逐个解析
        for (String depName : sortedDeps) {
            SkillDependency dep = findDependency(skill, depName);
            if (dep == null) continue;
            
            try {
                AgentSkill resolvedSkill = resolveSingleDependency(dep);
                if (resolvedSkill != null) {
                    resolvedDeps.put(depName, resolvedSkill);
                } else {
                    unresolvedDeps.add(depName);
                }
            } catch (DependencyConflictException e) {
                conflicts.add(e.getMessage());
            }
        }
        
        boolean resolved = unresolvedDeps.isEmpty() && conflicts.isEmpty();
        
        return DependencyResolutionResult.builder()
            .resolved(resolved)
            .dependencies(resolvedDeps)
            .unresolvedDependencies(unresolvedDeps)
            .conflicts(conflicts)
            .build();
    }
    
    private AgentSkill resolveSingleDependency(SkillDependency dep) 
            throws DependencyConflictException {
        // 1. 尝试从缓存加载
        Optional<AgentSkill> cached = SkillLoader.getCached(dep.getSkillName());
        if (cached.isPresent()) {
            AgentSkill skill = cached.get();
            if (matchesVersionConstraint(skill.getVersion(), dep.getVersionConstraint())) {
                logger.debug("从缓存解析: {} v{}", skill.getName(), skill.getVersion());
                return skill;
            }
        }
        
        // 2. 从仓库加载
        if (repository != null) {
            List<AgentSkill> candidates = repository.searchSkills(dep.getSkillName());
            
            for (AgentSkill candidate : candidates) {
                if (matchesVersionConstraint(candidate.getVersion(), 
                        dep.getVersionConstraint())) {
                    logger.info("从仓库解析: {} v{}", 
                        candidate.getName(), candidate.getVersion());
                    return candidate;
                }
            }
        }
        
        // 3. 尝试下载最新版本
        if (repository != null) {
            try {
                AgentSkill skill = repository.downloadSkill(
                    dep.getSkillName(), 
                    "latest"
                );
                if (skill != null && matchesVersionConstraint(
                        skill.getVersion(), dep.getVersionConstraint())) {
                    logger.info("下载并解析: {} v{}", 
                        skill.getName(), skill.getVersion());
                    return skill;
                }
            } catch (Exception e) {
                logger.error("下载依赖失败: {}", dep.getSkillName(), e);
            }
        }
        
        logger.warn("无法解析依赖: {} {}", 
            dep.getSkillName(), dep.getVersionConstraint());
        return null;
    }
    
    private boolean matchesVersionConstraint(String version, String constraint) {
        if (StringUtils.isBlank(constraint)) {
            return true;  // 无约束
        }
        
        SemVer actualVersion = SemVer.parse(version);
        
        if (constraint.startsWith(">=")) {
            SemVer minVersion = SemVer.parse(constraint.substring(2));
            return actualVersion.compareTo(minVersion) >= 0;
        }
        else if (constraint.startsWith(">")) {
            SemVer minVersion = SemVer.parse(constraint.substring(1));
            return actualVersion.compareTo(minVersion) > 0;
        }
        else if (constraint.startsWith("<=")) {
            SemVer maxVersion = SemVer.parse(constraint.substring(2));
            return actualVersion.compareTo(maxVersion) <= 0;
        }
        else if (constraint.startsWith("<")) {
            SemVer maxVersion = SemVer.parse(constraint.substring(1));
            return actualVersion.compareTo(maxVersion) < 0;
        }
        else if (constraint.startsWith("^")) {
            // 兼容版本:^1.5.0 匹配 1.5.x 但不包括 2.x
            SemVer baseVersion = SemVer.parse(constraint.substring(1));
            return actualVersion.getMajor() == baseVersion.getMajor() &&
                   actualVersion.compareTo(baseVersion) >= 0;
        }
        else if (constraint.startsWith("~")) {
            // 近似版本:~1.3.0 匹配 1.3.x
            SemVer baseVersion = SemVer.parse(constraint.substring(1));
            return actualVersion.getMajor() == baseVersion.getMajor() &&
                   actualVersion.getMinor() == baseVersion.getMinor() &&
                   actualVersion.compareTo(baseVersion) >= 0;
        }
        else if (constraint.contains(" - ")) {
            // 范围:1.0.0 - 2.0.0
            String[] parts = constraint.split(" - ");
            SemVer minVersion = SemVer.parse(parts[0].trim());
            SemVer maxVersion = SemVer.parse(parts[1].trim());
            return actualVersion.compareTo(minVersion) >= 0 &&
                   actualVersion.compareTo(maxVersion) <= 0;
        }
        else {
            // 精确匹配
            SemVer requiredVersion = SemVer.parse(constraint);
            return actualVersion.equals(requiredVersion);
        }
    }
    
    private DependencyGraph buildDependencyGraph(AgentSkill skill) {
        DependencyGraph graph = new DependencyGraph();
        buildGraphRecursive(skill, graph, new HashSet<>());
        return graph;
    }
    
    private void buildGraphRecursive(AgentSkill skill, 
            DependencyGraph graph, 
            Set<String> visited) {
        if (visited.contains(skill.getName())) {
            return;  // 避免循环
        }
        visited.add(skill.getName());
        
        if (skill.getDependencies() == null) {
            return;
        }
        
        for (SkillDependency dep : skill.getDependencies()) {
            graph.addEdge(skill.getName(), dep.getSkillName());
            
            // 递归构建依赖的依赖
            Optional<AgentSkill> depSkill = SkillLoader.getCached(dep.getSkillName());
            if (depSkill.isPresent()) {
                buildGraphRecursive(depSkill.get(), graph, visited);
            }
        }
    }
    
    private SkillDependency findDependency(AgentSkill skill, String depName) {
        if (skill.getDependencies() == null) {
            return null;
        }
        
        return skill.getDependencies().stream()
            .filter(d -> d.getSkillName().equals(depName))
            .findFirst()
            .orElse(null);
    }
}

/**
 * 依赖图
 */
class DependencyGraph {
    private final Map<String, List<String>> adjacencyList = new HashMap<>();
    
    public void addEdge(String from, String to) {
        adjacencyList.computeIfAbsent(from, k -> new ArrayList<>()).add(to);
    }
    
    public List<String> topologicalSort() {
        Map<String, Integer> inDegree = new HashMap<>();
        List<String> result = new ArrayList<>();
        
        // 计算入度
        for (String node : adjacencyList.keySet()) {
            inDegree.putIfAbsent(node, 0);
            for (String neighbor : adjacencyList.get(node)) {
                inDegree.put(neighbor, inDegree.getOrDefault(neighbor, 0) + 1);
            }
        }
        
        // 找到所有入度为0的节点
        Queue<String> queue = new LinkedList<>();
        for (Map.Entry<String, Integer> entry : inDegree.entrySet()) {
            if (entry.getValue() == 0) {
                queue.offer(entry.getKey());
            }
        }
        
        // BFS
        while (!queue.isEmpty()) {
            String node = queue.poll();
            result.add(node);
            
            if (adjacencyList.containsKey(node)) {
                for (String neighbor : adjacencyList.get(node)) {
                    inDegree.put(neighbor, inDegree.get(neighbor) - 1);
                    if (inDegree.get(neighbor) == 0) {
                        queue.offer(neighbor);
                    }
                }
            }
        }
        
        return result;
    }
}

/**
 * 语义化版本号
 */
@Data
@AllArgsConstructor
class SemVer implements Comparable<SemVer> {
    private int major;
    private int minor;
    private int patch;
    private String preRelease;  // 可选,如 "beta", "alpha.1"
    
    public static SemVer parse(String version) {
        String[] parts = version.split("-", 2);
        String[] numbers = parts[0].split("\\.");
        
        int major = Integer.parseInt(numbers[0]);
        int minor = numbers.length > 1 ? Integer.parseInt(numbers[1]) : 0;
        int patch = numbers.length > 2 ? Integer.parseInt(numbers[2]) : 0;
        String preRelease = parts.length > 1 ? parts[1] : null;
        
        return new SemVer(major, minor, patch, preRelease);
    }
    
    @Override
    public int compareTo(SemVer other) {
        if (this.major != other.major) {
            return Integer.compare(this.major, other.major);
        }
        if (this.minor != other.minor) {
            return Integer.compare(this.minor, other.minor);
        }
        if (this.patch != other.patch) {
            return Integer.compare(this.patch, other.patch);
        }
        
        // 比较预发布版本
        if (this.preRelease == null && other.preRelease == null) {
            return 0;
        }
        if (this.preRelease == null) {
            return 1;  // 正式版本 > 预发布版本
        }
        if (other.preRelease == null) {
            return -1;
        }
        return this.preRelease.compareTo(other.preRelease);
    }
    
    @Override
    public String toString() {
        String version = major + "." + minor + "." + patch;
        if (preRelease != null) {
            version += "-" + preRelease;
        }
        return version;
    }
}

/**
 * 依赖解析结果
 */
@Data
@Builder
class DependencyResolutionResult {
    private boolean resolved;
    private Map<String, AgentSkill> dependencies;
    private List<String> unresolvedDependencies;
    private List<String> conflicts;
}

class DependencyConflictException extends Exception {
    public DependencyConflictException(String message) {
        super(message);
    }
}

class SkillLoadException extends Exception {
    public SkillLoadException(String message) {
        super(message);
    }
    
    public SkillLoadException(String message, Throwable cause) {
        super(message, cause);
    }
}

class SkillValidationException extends SkillLoadException {
    public SkillValidationException(String message) {
        super(message);
    }
}

在Agent中使用Skill - 基础示例

public class SkillUsageDemo {
    
    public static void main(String[] args) throws Exception {
        Model model = DashScopeModel.builder()
            .modelName("qwen-turbo")
            .apiKey(System.getenv("DASHSCOPE_API_KEY"))
            .build();
        
        // 1. 加载技能
        System.out.println("=== 加载技能 ===\n");
        
        AgentSkill analysisSkill = SkillLoader.loadFromFile(
            Paths.get("skills/data_analysis.md")
        );
        
        AgentSkill visualizationSkill = SkillLoader.loadFromFile(
            Paths.get("skills/data_visualization.md")
        );
        
        // 2. 创建Agent并注入技能
        System.out.println("=== 创建支持技能的Agent ===\n");
        
        ReActAgent agent = ReActAgent.builder()
            .name("DataAnalystAgent")
            .model(model)
            .skills(List.of(analysisSkill, visualizationSkill))
            .systemPrompt(buildSystemPrompt(List.of(analysisSkill, visualizationSkill)))
            .build();
        
        // 3. 使用Agent
        System.out.println("=== Agent执行任务 ===\n");
        
        Msg response = agent.call(Msg.builder()
            .textContent("""
                这是我们公司过去6个月的销售数据:
                [数据内容...]
                
                请使用技能进行分析和可视化。
                """)
            .build()).block();
        
        System.out.println("分析结果:\n" + response.getTextContent());
    }
    
    private static String buildSystemPrompt(List<AgentSkill> skills) {
        StringBuilder prompt = new StringBuilder();
        prompt.append("你是一个数据分析助手,拥有以下技能:\n\n");
        
        for (AgentSkill skill : skills) {
            prompt.append("【技能:").append(skill.getName()).append("】\n");
            prompt.append("描述:").append(skill.getDescription()).append("\n");
            prompt.append("使用方法:\n").append(skill.getUsageMethod()).append("\n\n");
        }
        
        prompt.append("请在回答用户问题时合理使用这些技能。");
        return prompt.toString();
    }
}


本章总结

Skill技能系统是AgentScope框架中的核心能力中台,提供了:

核心特性

  • 标准化定义:Markdown + YAML Front Matter格式
  • 复用性:一次定义,多处使用
  • 组合性:技能可以相互依赖和调用
  • 版本管理:语义化版本号和依赖解析
  • 共享性:通过技能市场共享和交易

关键组件

  1. SkillLoader:从多种来源加载技能(文件、URL、类)
  2. SkillValidator:验证技能定义的完整性和正确性
  3. DependencyResolver:解析和管理技能依赖
  4. SkillRepository:技能库管理,支持本地和远程
  5. SkillOrchestrator:编排和执行多个技能

使用场景

  • 企业AI能力中台
  • 多Agent协作系统
  • 领域专业知识封装
  • 技能市场和生态