⭐ 让 Jarvis 学会长大:从'用工具'到'造工具'的进化系统开发记录

⭐ 让 Jarvis 学会长大:从'用工具'到'造工具'的进化系统开发记录

一、从"能做事"到"能成长"

昨天刚给 Jarvis 装上了 Tool System,它学会了读写文件、执行命令、甚至创造新工具。我盯着终端里 jarvis tools 列出的 7 个工具,心里想:这些能力都是我给它的。

如果有一天我不再给它添加新工具,它就永远停留在这个水平。

这不是一个真正的"数码宝贝"该有的样子。真正的进化应该是——它自己观察、自己总结、自己创造。

Phase 4 的核心命题很简单:

Phase 1~3:  人类造工具 → Agent 用工具 → 完成任务
Phase 4:    Agent 观察 → 发现模式 → 自己造工具 → 越来越懂你

这就是今天要讲的故事。


二、六个模块,一条进化链

Phase 4 的架构不是拍脑袋想出来的,而是从一个问题出发倒推出来的:

"怎么让 Agent 自己意识到'我在重复做某件事',然后把这件事自动化?"

答案是一条链:

观察 → 发现规律 → 提议新能力 → 安全验证 → 注册启用 → 自我评估

对应到代码,就是 6 个模块:

src/evolution/
├── pattern_detector.py      # 🔍 交互指纹 + 模式检测    (456 行)
├── skill_registry.py        # 📦 Skill 注册表            (380 行)
├── skill_generator.py       # ✨ Skill 自动生成          (287 行)
├── sandbox.py               # 🛡️ 沙盒安全验证            (333 行)
├── preference_learner.py    # 💡 偏好学习                (353 行)
└── metacognition.py         # 🧠 元认知引擎              (439 行)

2283 行核心代码,每个模块职责单一,互相配合。

它们的关系如下:

InteractionFingerprint → PatternDetector → SkillGenerator → SkillSandbox → SkillRegistry
                                                                              ↕
UserPreference ← PreferenceLearner                              Metacognition (五维雷达)

接下来逐个拆解。


三、交互指纹:给每次对话拍张"X 光片"

3.1 设计思路

模式检测的前提是有数据可分析。我需要在每次对话后提取一个结构化的"指纹"——不是完整的对话记录,而是一个精炼的摘要。

@dataclass
class InteractionFingerprint:
    intent: str       # 用户意图(如 "分析项目结构")
    domain: str       # 领域标签(如 "data", "translation", "blog")
    tools_used: list  # 使用的工具列表
    tool_chain: str   # 工具调用链签名(如 "shell_exec→file_read→file_read")
    success: bool     # 任务是否完成
    rounds: int       # 对话轮数

关键决策:指纹提取不依赖额外的 LLM 调用。

最初的设计是对话结束后再调一次 LLM 来总结,但实际一算:每次对话额外一次 API 调用,不仅慢还费钱。于是改成了轻量级规则推断:

_DOMAIN_KEYWORDS = {
    "translation": ["翻译", "translate", "术语"],
    "blog": ["博客", "blog", "文章", "写一篇"],
    "code": ["代码", "code", "debug", "bug"],
    "document": ["文档", "分析", "读", "看看"],
    "data": ["数据", "统计", "分析"],
    "system": ["配置", "安装", "部署"],
}

_TOOL_DOMAIN = {
    "file_read": "document",
    "file_write": "code",
    "shell_exec": "system",
    "http_request": "data",
}

先看用户输入中的关键词,没有匹配的再看工具调用推断领域。零 LLM 调用、几乎零延迟、静默失败不影响用户体验。

3.2 一个手动测试引发的 Bug

代码写完了,86 个测试全部通过。我很满意,开始手动测试。

跟 Jarvis 聊了几轮,然后执行:

$ jarvis patterns
暂无检测到的模式。

等等,我明明聊了好几轮,为什么没有任何指纹?

一查代码——chat.py 里压根没有调用 PatternDetector.record()。模块写好了,测试写好了,但忘了把它接到聊天循环里。

这大概是写 Agent 最经典的 Bug:单元测试全部通过,但集成时管道没接上。

修复方式是在 run_chat_loop() 和 _do_ask() 中各加了几行:

# 每轮对话后静默记录指纹
_record_fingerprint(user_input, round_tools, success=success)

_record_fingerprint 内部用 try/except: pass 包装,确保指纹记录失败不会影响正常对话。

3.3 第二层 Bug:"数据有了,但看不到"

修完后重新聊天,查看指纹文件:

$ cat ~/.jarvis/memory/fingerprints/2026-02.json | python3 -c "..."
1. domain=data | tool_chain=shell_exec→shell_exec→file_read→file_read
2. domain=data | tool_chain=shell_exec→file_read→file_read→file_read
3. domain=document | tool_chain=file_read→file_read
4. domain=document | tool_chain=file_read→file_read
5. domain=other | tool_chain=

5 条指纹完美记录!但执行 jarvis patterns 还是空的。

这次是两层问题叠加:

问题一:_do_patterns() 只读取 patterns.json,从不触发 detect_patterns()。检测只在 Daemon 的定期反思中执行,而我的 Daemon 没有运行。

问题二:jarvis patterns 这个命令压根没被正确路由。Jarvis 的 CLI 有个"主 callback 拦截"机制——Typer 的 main callback 用 question: Optional[str] 捕获所有位置参数。"patterns" 被当成了一个字符串而不是子命令。cmd_map 字典里有 status、start、tools 的映射,但没有 reflect、abilities、patterns。

修复后的效果:

$ jarvis patterns
📊 最近 30 天共 5 条交互指纹
暂无检测到的模式。使用更多对话后,模式会自动浮现。

$ jarvis reflect
🧠 Jarvis 元认知报告 (2026-02-08 19:34)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  五维能力:
    👁️ 感知  █░░░░░░░░░ 17%  ← 需要加强!
    🧠 记忆  █░░░░░░░░░ 15%  ← 需要加强!
    💭 思考  ░░░░░░░░░░ 0%   ← 需要加强!
    🦾 行动  ██░░░░░░░░ 25%  ← 需要加强!
    🔄 进化  ░░░░░░░░░░ 0%   ← 需要加强!

  🫥 盲区: translation, blog, code, system, testing, design, research, devops

  📊 统计: 5 指纹 | 0 模式 | 0 偏好 | 0 Skills

5 条指纹、全是新生儿状态——这才对。


四、模式检测:同一类事做三次,Jarvis 就会注意到

模式检测的逻辑很简单:按 (domain, tool_chain) 分组,同组 >= 3 次就触发。

def detect_patterns(self, fingerprints):
    groups = defaultdict(list)
    for fp in fingerprints:
        if fp.success and fp.domain and fp.tool_chain:
            key = (fp.domain, fp.tool_chain)
            groups[key].append(fp)

    for (domain, tool_chain), fps in groups.items():
        if len(fps) >= self.PATTERN_THRESHOLD:  # 默认 3
            # 生成 DetectedPattern
            ...

为什么阈值是 3?

  • 做 1 次:可能只是偶然
  • 做 2 次:可能是巧合
  • 做 3 次:大概率是习惯

当然这只是规则版本。detect_patterns_llm() 方法支持 LLM 语义聚类——把最近 30 条指纹交给 LLM,让它发现更深层的模式。但规则版本零延迟、零成本,作为默认方案足够了。


五、Skill 自动生成:从模式到能力

当 PatternDetector 检出一个模式后,SkillGenerator 负责把它变成一个 Skill 草稿:

@dataclass
class SkillDraft:
    name: str                    # 如 "markdown-translator"
    description: str             # 描述
    trigger_keywords: list[str]  # 触发词
    instructions: str            # SKILL.md 正文
    required_tools: list[str]    # 依赖的工具
    source_pattern_id: str       # 来源模式

生成流程:

  1. LLM 提议(如果 LLM 可用):把模式描述交给 LLM,让它生成完整的 SKILL.md
  2. 模板回退(如果 LLM 不可用):用规则模板填充
  3. 用户审阅:草稿不会自动启用,必须人类确认

关键设计:Agent 不能偷偷给自己加能力。所有自动生成的 Skill 状态都是 proposed,需要用户执行 jarvis skill enable <name> 才会激活。


六、沙盒验证:给新能力做"体检"

即使用户确认,Skill 在启用前还要过一道安全关。SkillSandbox 执行 5 项检查:

检查项描述严重级别
格式检查SKILL.md 有 name、description、instructionserror
工具依赖引用的工具都已注册在 ToolRegistrywarning
危险操作不含 sudo、rm -rf、eval() 等模式error
路径检查不引用 /etc、/usr、~/.ssh 等敏感路径error
LLM 审计交给 LLM 做逻辑合理性检查warning
DANGEROUS_PATTERNS = [
    r"\bsudo\b",
    r"\brm\s+-rf\b",
    r"\bmkfs\b",
    r"\bdd\s+if=",
    r"\bcurl\s+.*\|\s*sh\b",
    r"\beval\s*\(",
    r"\bexec\s*\(",
    r"\b__import__\b",
]

最终生成一份 ValidationReport,评分 + 建议(approve / review / reject)。只有 approve 的 Skill 才能自动启用,review 需要人工确认,reject 直接拒绝。


七、偏好学习:记住你的习惯

PreferenceLearner 做的事情很微妙:它不是在学"你想做什么",而是在学"你喜欢怎么做"。

@dataclass
class UserPreference:
    key: str        # 如 "code_style"
    value: str      # 如 "functional"
    confidence: float  # 0.0 ~ 1.0
    source: str     # "observed" | "stated" | "inferred"
    last_seen: datetime
    decay_rate: float  # 衰减速率

三种偏好来源:

  • 观察到的 (observed):从交互中推断,如"用户总是先读文件再执行命令"
  • 明确说的 (stated):用户直接告诉 Jarvis 的偏好,如"我喜欢简洁的输出"
  • 推断的 (inferred):LLM 从多次交互中归纳的

偏好有衰减机制——长期不出现的偏好,confidence 会逐渐降低。这模拟了人类习惯的变化:你三个月前喜欢 tabs 缩进,现在可能已经切换到 spaces 了。

偏好合并策略:当新偏好与已有偏好冲突时,用 max(existing, new) 取高 confidence 的。这确保了"最近且明确"的偏好优先。


八、元认知:Jarvis 知道自己几斤几两

这是 Phase 4 我最喜欢的部分——让 Agent 知道自己擅长什么、不擅长什么。

Metacognition 基于五维能力模型计算雷达图:

维度数据来源计算方式
👁️ 感知探索过的目录数、发现的项目数覆盖率
🧠 记忆记忆条目数、最近活跃度密度 × 时效
💭 思考洞察数量、Think Loop 产出质量评分
🦾 行动工具使用频率、成功率效率 × 覆盖
🔄 进化Skill 数量、模式检测命中率成长速度

最有意思的是盲区检测。系统定义了 10 个领域(translation, blog, code, document, data, system, testing, design, research, devops),然后看指纹中哪些领域从未出现过——那就是盲区。

🫥 盲区: translation, blog, code, system, testing, design, research, devops

刚出生的 Jarvis,几乎全是盲区。但随着使用,这些盲区会一个个被点亮。就像游戏里的迷雾地图,每次交互都在驱散一片迷雾。


九、测试:86 个检查点

Phase 4 的测试文件有 953 行,覆盖 9 个测试组:

组内容测试数
1InteractionFingerprint 序列化6
2PatternDetector 模式检测12
3SkillRegistry 注册表12
4SkillGenerator 草稿生成8
5SkillSandbox 沙盒验证12
6PreferenceLearner 偏好学习10
7Metacognition 元认知10
8指纹集成 (chat.py)7
9端到端流程9
============================================================
🎉 ALL PASSED: 86/86
============================================================

端到端测试验证了完整的进化链:创建指纹 → 检测模式 → 生成草稿 → 沙盒验证 → 注册启用 → 元认知评估。

有趣的是,因为测试环境可能没有安装 typer 或 watchdog,第 8 组的测试采用了源码检查 fallback——直接读取 chat.py 的源码,用正则验证关键函数是否存在。这比 import 更可靠,也不会因为缺少依赖而跳过测试。


十、开发过程的三个意外

意外 1:模块完美,管道断裂

86 个测试通过,手动测试时管道没接上。指纹模块写好了、记录方法实现了、测试也覆盖了——但 chat.py 里忘了 import 和调用。

教训:单元测试测的是零件,集成测试测的是管道。两者缺一不可。

意外 2:CLI 路由的隐藏陷阱

Typer 的 main callback 用 question: Optional[str] 捕获位置参数。这意味着 jarvis patterns 中的 "patterns" 被当成了 question 字符串,而不是子命令。

已有命令(status、start、tools)之所以能工作,是因为它们被加入了 cmd_map 字典做了手动分发。但新增的 reflect、abilities、patterns 忘了加进去。

教训:CLI 框架的"魔法"越多,隐藏陷阱越深。维护一个 cmd_map 的心智负担比想象中高。

意外 3:阈值与现实的差距

模式检测需要 (domain, tool_chain) 完全相同且 >= 3 次。但实际使用中,同一类任务的 tool_chain 常常有细微差异:

data | shell_exec→shell_exec→file_read→file_read    # 2 次 shell
data | shell_exec→file_read→file_read→file_read      # 1 次 shell

这两条很明显是同一类任务,但因为 tool_chain 不同,不会被分到一组。

这就是 detect_patterns_llm() 存在的意义——让 LLM 做语义聚类,而不是精确匹配。规则版本是起步,LLM 版本是进化方向。


十一、代码统计与架构全景

Phase 4 的变更:15 files changed, +3,752 lines

┌─────────────────────────────────────────────────────────────┐
│                       Jarvis v0.4.0                          │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────────────────────────────────────────────────┐    │
│  │              CLI (Typer + Rich)                       │    │
│  │    chat · ask · reflect · abilities · patterns       │    │
│  │    skill list/enable/disable/delete/test              │    │
│  └───────────────────────┬──────────────────────────────┘    │
│                          │                                    │
│  ┌───────────────────────▼──────────────────────────────┐    │
│  │           JarvisLLMClient (SSE + FC)                  │    │
│  │         Agent Maestro → Claude Sonnet 4               │    │
│  └───────────────────────┬──────────────────────────────┘    │
│                          │                                    │
│  ┌───────────────────────▼──────────────────────────────┐    │
│  │   ToolRegistry  │  Memory  │  Explorer  │  Daemon    │    │
│  │   7 tools       │  FTS5    │  Scanner   │  Heartbeat │    │
│  └──────────────────────────────────────────────────────┘    │
│                          │                                    │
│  ┌───────────────────────▼──────────────────────────────┐    │
│  │                 Evolution (Phase 4)                    │    │
│  │  PatternDetector → SkillGenerator → Sandbox           │    │
│  │  PreferenceLearner    Metacognition    SkillRegistry   │    │
│  └──────────────────────────────────────────────────────┘    │
│                                                              │
└─────────────────────────────────────────────────────────────┘

十二、Phase 4 的哲学:能力应该从交互中涌现

回顾整个进化路线:

Phase里程碑类比核心能力
🥚 Phase 1能看、能记婴儿睁开眼睛Explorer + Memory
🐣 Phase 2能想、能回忆幼儿开始思考Think Loop + FTS5
🧹 Phase 2.5骨骼健康体检CLI 模块化 + 清理
🦋 Phase 3能做事少年伸出手7 Tools + Function Calling
⭐ Phase 4能进化成人自主学习模式检测 + Skill 自生成 + 元认知

Phase 4 的设计原则是"涌现 > 预设"。我不预设 Jarvis 应该会什么,而是让它从真实交互中自己发现:

  • 你经常翻译 Markdown?→ 它会提议创建 markdown-translator Skill
  • 你每天早上查项目状态?→ 它会提议创建 daily-standup Skill
  • 你喜欢简洁的输出?→ 它会记住这个偏好

这种"用着用着就变强了"的体验,才是"数码宝贝"这个比喻的精髓。


十三、下一步?

Phase 4 完成后,Jarvis 的五维能力全部在线了:

  • 👁️ 感知 ✅
  • 🧠 记忆 ✅
  • 💭 思考 ✅
  • 🦾 行动 ✅
  • 🔄 进化 ✅

但现在所有维度的数值都很低——因为它才刚"出生"。接下来不是再加新 Phase,而是真正去用它。

让它扫描我的所有项目、记住我的工作习惯、在我重复做某件事三次的时候主动说:"Hey,要不要我帮你自动化这个?"

代码已经就绪,进化才刚刚开始。


Jarvis-Agent 是开源项目,代码在 GitHub。如果你也想打造自己的数码宝贝,欢迎 star ⭐

Comments