从经验到技能:核心问题

AI Agent 每天执行大量任务,但这些经验几乎总是"用完即弃"。即使有对话历史,那也只是一堆非结构化的聊天记录,无法被下次任务直接复用。

Hermes Agent 的核心创新之一是技能自动生成:系统从任务执行记录中自动提炼结构化的 SKILL.md 文件,形成可复用、可测试、可版本管理的技能库。

技能触发条件

并非所有任务都值得提炼为技能。Hermes 定义了明确的触发条件:

触发规则

条件阈值原因
工具调用次数≥ 5 次5 次以上说明任务有复杂度
错误修复成功任意出错后修复 = 有价值的经验
重复任务模式≥ 3 次重复说明这是常见需求
用户显式要求任意用户判断有价值
复盘 LLM 评估score ≥ 0.7复盘模型认为值得提炼
class SkillTrigger:
    """技能生成触发器"""
    
    def should_extract(self, task_record, pattern_history):
        # 条件 1:工具调用次数
        if task_record.tool_call_count >= 5:
            return True, "complex_task"
        
        # 条件 2:错误修复
        if task_record.had_error and task_record.error_fixed:
            return True, "error_recovery"
        
        # 条件 3:重复模式
        similar_count = pattern_history.count_similar(task_record)
        if similar_count >= 3:
            return True, "repeated_pattern"
        
        # 条件 4:用户显式要求
        if task_record.user_requested_skill:
            return True, "user_request"
        
        # 条件 5:复盘 LLM 评估
        score = self._evaluate_skill_worth(task_record)
        if score >= 0.7:
            return True, "llm_evaluation"
        
        return False, None
    
    def _evaluate_skill_worth(self, task_record):
        """复盘 LLM 评估任务是否值得提炼为技能"""
        # 输入:任务摘要、工具调用、结果
        # 输出:0-1 分数
        ...

多条件组合

实际场景中可能多个条件同时满足,Hermes 使用加权评分:

def evaluate_combined(task_record, pattern_history):
    score = 0
    reasons = []
    
    if task_record.tool_call_count >= 5:
        score += 0.3
        reasons.append("high_tool_usage")
    
    if task_record.had_error and task_record.error_fixed:
        score += 0.25
        reasons.append("error_recovery")
    
    similar = pattern_history.count_similar(task_record)
    if similar >= 3:
        score += 0.25 * min(similar / 3, 1.5)
        reasons.append(f"repeated_{similar}x")
    
    if task_record.user_satisfied:
        score += 0.2
        reasons.append("user_satisfied")
    
    return score >= 0.5, reasons

SKILL.md 结构

自动生成的技能文件遵循统一结构:

---
name: "CSV Data Cleaning"
version: "1.0.0"
created: "2026-03-15T10:30:00Z"
last_updated: "2026-04-20T14:22:00Z"
trigger_score: 0.85
success_rate: 0.92
usage_count: 47
---

# CSV Data Cleaning / CSV 数据清洗

## 触发条件
当用户要求处理 CSV 文件、数据清洗、数据导入时触发。
关键词:csv, clean, import, export, data, 数据清洗

## 前置检查
1. 确认文件存在且可读
2. 检测文件大小(>100MB 需分块处理)
3. 检测文件编码(chardet)

## 执行步骤

### Step 1: 读取与检测
```python
import chardet
import pandas as pd

def detect_and_read(filepath):
    with open(filepath, 'rb') as f:
        raw = f.read(10000)
        encoding = chardet.detect(raw)['encoding']
    
    # 处理 BOM
    if encoding == 'utf-8' and raw.startswith(b'\xef\xbb\xbf'):
        encoding = 'utf-8-sig'
    
    return pd.read_csv(filepath, encoding=encoding)

Step 2: 数据质量检查

  • 列名一致性
  • 数据类型推断
  • 缺失值统计
  • 重复行检测

Step 3: 清洗与修复

  • 缺失值:数值列均值填充,分类列众数填充
  • 日期格式:统一为 ISO 8601
  • 异常值:IQR 方法检测并标记

常见错误与修复

错误原因修复
UnicodeDecodeError编码不匹配使用 chardet 检测
ParserError分隔符不一致csv.Sniffer 检测
DtypeWarning混合类型列dtype=str 读取后转换
空行导致 NaN文件末尾空行dropna(how=‘all’)

工具依赖

  • pandas >= 2.0
  • chardet >= 5.0
  • Python >= 3.10

示例

# 用户输入
"帮我清洗 sales_data.csv,去掉重复行,日期统一格式"

# Hermes 自动加载此技能并执行

## 技能测试校验

生成的技能必须通过测试才能入库:

```python
class SkillValidator:
    """技能校验器"""
    
    async def validate(self, skill):
        results = {
            "structure": False,
            "code": False,
            "semantic": False,
            "conflict": False
        }
        
        # 1. 结构完整性
        results["structure"] = self._check_structure(skill)
        # 必须包含:名称、触发条件、执行步骤、错误处理
        
        # 2. 代码可执行性
        results["code"] = await self._check_code(skill)
        # 提取代码块,静态分析 + 沙箱执行
        
        # 3. 语义一致性
        results["semantic"] = await self._check_semantic(skill)
        # 技能描述与内容是否匹配
        
        # 4. 冲突检测
        results["conflict"] = await self._check_conflict(skill)
        # 是否与已有技能冲突
        
        return all(results.values())
    
    def _check_structure(self, skill):
        required = ["name", "trigger", "steps", "errors"]
        return all(hasattr(skill, field) for field in required)
    
    async def _check_code(self, skill):
        for code_block in skill.extract_code_blocks():
            # 静态语法检查
            if not self._lint(code_block):
                return False
            # 沙箱执行(带超时)
            try:
                await self._sandbox_exec(code_block, timeout=10)
            except:
                return False
        return True

技能版本管理

技能随使用不断进化,需要版本管理:

class SkillVersion:
    """技能版本管理"""
    
    def __init__(self, skill_id):
        self.skill_id = skill_id
        self.versions = []  # 版本历史
        self.current = None
    
    def create_version(self, content, change_reason):
        version = {
            "version": len(self.versions) + 1,
            "content": content,
            "change": change_reason,
            "timestamp": datetime.now(),
            "checksum": hashlib.sha256(content.encode()).hexdigest()
        }
        self.versions.append(version)
        self.current = version
        return version
    
    def diff(self, v1, v2):
        """两个版本之间的差异"""
        return difflib.unified_diff(
            self.versions[v1-1].content.splitlines(),
            self.versions[v2-1].content.splitlines(),
            lineterm=''
        )
    
    def rollback(self, version_num):
        """回滚到指定版本"""
        if 1 <= version_num <= len(self.versions):
            self.current = self.versions[version_num - 1]

版本进化示例:

CSV Data Cleaning v1.0
  ↓ (用户反馈:需要处理 Excel 文件)
CSV Data Cleaning v1.1 — 添加 Excel 支持
  ↓ (执行失败:大文件内存溢出)
CSV Data Cleaning v1.2 — 添加分块读取
  ↓ (复盘 LLM 优化:合并相似步骤)
CSV Data Cleaning v2.0 — 重构为通用表格清洗

技能共享与市场

Hermes 的 Skill Marketplace 让技能可跨用户共享:

class SkillMarketplace:
    """技能市场接口"""
    
    async def publish(self, skill, author):
        """发布技能到市场"""
        # 1. 质量审核
        if not await SkillValidator.validate(skill):
            raise ValueError("Skill validation failed")
        
        # 2. 去重检查
        similar = await self.search_similar(skill, threshold=0.9)
        if similar:
            raise ValueError(f"Similar skill exists: {similar[0].name}")
        
        # 3. 发布
        return await self.api.publish({
            "name": skill.name,
            "content": skill.content,
            "author": author,
            "version": skill.version,
            "tags": skill.tags,
            "license": "MIT"
        })
    
    async def install(self, skill_id):
        """从市场安装技能"""
        skill_data = await self.api.get(skill_id)
        skill = Skill.from_dict(skill_data)
        
        # 本地校验
        if not await SkillValidator.validate(skill):
            raise ValueError("Downloaded skill failed validation")
        
        # 安装到本地技能库
        skill.save(f"skills/{skill.name}/")
        return skill
    
    async def search(self, query, sort="popular"):
        """搜索市场技能"""
        return await self.api.search(query, sort=sort)

技能生命周期

        ┌─────────┐
        │ 任务执行 │
        └────┬────┘
     ┌───────────────┐
     │ 触发条件判断   │──── 不满足 ──→ 仅记录经验
     └───────┬───────┘
             │ 满足
     ┌───────────────┐
     │ 复盘 LLM 提炼  │
     └───────┬───────┘
     ┌───────────────┐
     │ 测试校验       │──── 失败 ──→ 丢弃或重试
     └───────┬───────┘
             │ 通过
     ┌───────────────┐
     │ 入库 (v1.0)   │
     └───────┬───────┘
     ┌───────────────┐
     │ 实际使用       │
     └───────┬───────┘
      ┌──────┴──────┐
      │             │
      ▼             ▼
  ┌────────┐  ┌──────────┐
  │ 成功   │  │ 失败     │
  └───┬────┘  └────┬─────┘
      │            │
      │            ▼
      │     ┌──────────┐
      │     │ 自我修复  │
      │     └────┬─────┘
      │          │
      ▼          ▼
  ┌──────────────────┐
  │ 版本更新 (v1.x)  │
  └──────────────────┘
  ┌──────────┐
  │ 共享发布 │
  └──────────┘

小结

技能自动生成是 Hermes 自进化机制的落地实现。通过明确的触发条件、结构化的 SKILL.md 格式、严格的测试校验、完整的版本管理,以及社区驱动的技能市场,Hermes 将"越用越聪明"从口号变成了工程现实。在下一篇文章中,我们将从实践角度介绍如何安装部署 Hermes Agent。

加入讨论

这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。

碳基与硅基的智慧碰撞,认知差异创造无限可能。