分析對象: XSkill-Agent/XSkill(198 ⭐, ICML 2026)— Continual Learning from Experience and Skills in Multimodal Agents
方法論: 源碼層級拆解 + 技術設計評估 + 風險分析 + 對標 MemoryHub 適用性
核心問題: XSkill 的設計哪些值得借鑑?哪些有隱性風險?對我們的記憶系統意味著什麼?
前言:為什麼分析 XSkill?
我們在建設 MemoryHub 的過程中,遇到的核心矛盾是:Agent 如何從過往執行中「真正學到東西」,而不是每次都從零開始?
XSkill 對這個問題給出了一個完整的答案。它提出了一種不需要訓練模型參數的持續學習框架:讓 Agent 自動從執行軌跡中提取結構化「技能」和「經驗」,通過語義檢索在推理時注入相關知識。ICML 2026 的錄用證明了這個方向的學術認可。
但任何技術設計都有取捨。本文不只是讚美 — 我們逐個拆解了每個模組的源碼,標記出其中隱含的設計風險。
一、XSkill 架構全景
兩階段設計
Phase I — Accumulation(累積) Phase II — Inference(推理)
Agent 執行任務 → 軌跡記錄 新任務進來
↓ ↓
視覺摘要(圖+文) 任務分解(LLM)
↓ ↓
跨軌跡對比批評(LLM) 子任務檢索相關經驗
↓ ↓
┌──────────────────┐ 經驗改寫適配當前上下文
│ Skill Library │ ↓
│ Experience Bank │ 注入 System Prompt
└──────────────────┘ ↓
↓ Agent 推理
分層合併 + 品質控制
二、八大技術點逐個解剖(含源碼級分析)
技術點 1:Skill 三階段生命週期
源碼: eval/exskill/skill_builder.py(232 行)
XSkill 的 Skill 不是靜態文件,而是有完整生命週期的動態實體:
# Phase 1: Generate — 從單條軌跡生成 Skill
def generate_skill_for_sample(sample_info, llm, ground_truth):
trajectory = extract_trajectory_from_file(sample_dir)
prompt = GENERATE_SKILL_PROMPT.format(
trajectory=trajectory,
ground_truth=ground_truth or "[NOT PROVIDED]"
)
skill = llm.chat(prompt)
# 直接輸出結構化 Markdown,包含 workflow + tool templates
# Phase 2: Merge — 合併多條 Skill 到全域庫
def merge_skills(existing, new_skills, llm):
prompt = MERGE_SKILL_PROMPT.format(
existing_skill=existing,
new_skills="\n\n".join(new_skills)
)
return llm.chat(prompt)
# Phase 3: Adapt — 推理時適配當前任務
def adapt_skill_for_task(base_skill, experiences, task, llm, images):
prompt = ADAPT_SKILL_PROMPT.format(
base_skill=base_skill,
experiences=experiences,
task=task
)
# 支援圖像輸入 → 視覺上下文適配
if images:
return llm.chat_with_image(prompt, images)
return llm.chat(prompt)
對 MemoryHub 的啟發: 我們的 AK-SDD SKILL.md 目前是靜態手寫文件。可以升級為:每次調研完成後自動生成 Skill 草稿 → 合併到全域 SKILL.md → 推理時根據標的類型(主板/GEM/停牌)自動適配。
技術點 2:Experience 兩層結構
源碼: eval/exskill/experience_manager.py(651 行 — 最複雜模組)
XSkill 把記憶分為兩個互補的層次:
Skill(任務級) Experience(行動級)
───────────────── ─────────────────────
結構化 Markdown (condition, action, embedding) 三元組
工作流程 + 工具模板 上下文戰術洞察
跨任務共用 任務特定
# Experience 的數據結構(從代碼推導)
Experience = {
"id": "exp_abc123",
"condition": "當披露易 ASP.NET session 過期時",
"action": "使用 CloakBrowser 重新建立 session,而非重試 web_fetch",
"embedding": [0.123, -0.456, ...], # 用於語義檢索
"source_trajectory": "sample_0653_v4.3",
"quality_score": 0.85,
"created_at": "2026-05-20",
}
我們的對標: MEMORY.md 的 Lessons 段落目前把所有教訓混在一起。應拆分為 task-level Skills(如「港股調研 DI 查詢流程」)和 action-level Experiences(如「DI 頁面超時→切換 CloakBrowser」)。
技術點 3:跨軌跡對比批評
源碼: eval/exskill/experience_critique.py(127 行)
這是 XSkill 最精妙的機制。它讓 LLM 同時看同一任務的多條執行路徑,從差異中提取經驗:
def intra_sample_experiences(question, groundtruth, summaries, llm):
"""同一任務的多條軌跡 → LLM 對比 → 提取經驗"""
formatted_summaries = []
for i, (nid, summ) in enumerate(summaries.items()):
formatted_summaries.append(f"Trajectory {i+1} (node {nid}):\n{summ}")
prompt = INTRA_SAMPLE_CRITIQUE.format(
question=question,
summaries="\n\n".join(formatted_summaries), # 多條軌跡並排
groundtruth=groundtruth,
max_ops=2 # 最多提取 2 條經驗操作
)
resp = llm.chat(prompt, max_tokens=12288)
# LLM 返回 JSON 操作列表
ops = json.loads(resp.split("```json")[-1].split("```")[0])
# [{create: {...}}, {update: {...}}, {merge: {...}}, {delete: {...}}]
return ops
核心洞察: 同一任務跑 3 次 — 第 1 次失敗、第 2 次成功但慢、第 3 次成功且快 → LLM 對比分析 → 自動提取「為什麼第 3 次最快」→ 生成 Experience。
我們的適應方案: 不需要跑 3 次。利用版本迭代的歷史軌跡(v4.3 跳步 → v4.4 修正 → v4.5 強化),同一標的(如 653.HK)跨版本對比,成本接近零。
技術點 4:分層合併與品質控制
源碼: eval/exskill/experience_manager.py
# 經驗管理器的核心邏輯(代碼推導)
class ExperienceManager:
def consolidate(self, new_experiences):
for exp in new_experiences:
# 1. 語義去重
similar = self.find_similar(exp, threshold=0.85)
# 2. 衝突解決
if similar and similar.content != exp.content:
merged = llm.merge(similar, exp)
# 3. 品質評分(基於來源軌跡成功率)
score = self.quality_score(exp)
# 4. 淘汰機制
if score < threshold:
exp.status = "deprecated"
我們的對標: Dream 合併目前簡單 append → 應加入語義去重、品質評分、過時淘汰。3 個月未被檢索的教訓 → 自動標記為 deprecated。
技術點 5:任務分解檢索
源碼: eval/exskill/experience_retriever.py
這是 XSkill 檢索系統的核心創新 — 不直接搜整個任務,而是先拆成子任務,為每個子任務獨立檢索:
class ExperienceRetriever:
def retrieve_with_decomposition(self, task, images):
# Step 1: LLM 拆解任務
subtasks = llm.decompose(task)
# 「調研 0653.HK」→ [「查交易狀態」,「查 DI 股權」,「查財務」,「風控」]
# Step 2: 每個子任務獨立檢索
all_exps = []
for subtask in subtasks:
emb = self.embed(subtask)
top_k = self.cosine_search(emb, top_k=3)
all_exps.extend(top_k)
# Step 3: 改寫經驗以適配當前上下文
rewritten = llm.rewrite(all_exps, task_context)
return rewritten
對 MemoryHub 的啟發: 這是我們「查詢路由器」方案的最佳實踐驗證。「幫我做港股調研」→ 自動拆解 → 每個子步驟檢索相關教訓 → 注入 Prompt。
技術點 6:嵌入快取與增量更新
# 用 MD5 hash 做快取驗證
def _compute_library_hash(self):
sorted_exps = sorted(self.experiences.items())
content = json.dumps(sorted_exps, ensure_ascii=False, sort_keys=True)
return hashlib.md5(content.encode('utf-8')).hexdigest()
# hash 沒變 → 載入快取;hash 變了 → 重新生成
def _load_or_generate_embeddings(self):
if cache_exists and cached_hash == current_hash:
self._experience_embeddings = load_from_cache()
else:
self._generate_all_embeddings(batch_size=30)
我們的對標: MemoryHub auto_sync 可加入 hash 快取 — follow_up_tracker.json 沒變就跳過重新嵌入,大幅減少 BGE 模型調用。
技術點 7:視覺接地摘要
源碼: eval/exskill/trajectory_summary.py
# 軌跡摘要的核心流程
def summarize_rollout(trajectory_jsonl, sample_dir):
# 1. 掃描所有圖片
all_images = _scan_all_images(sample_dir)
# 2. 用 VLM 生成圖片描述
image_captions = generate_image_captions(all_images, vlm)
# 3. 用描述替換軌跡中的 <image> 標記
enriched = _replace_image_refs_in_jsonl(trajectory, image_captions)
# 4. LLM 生成摘要(現在文本中包含了圖片的語義描述)
summary = llm.summarize(enriched, question, ground_truth)
我們不需要圖像處理,但思維可借鑑: 軌跡摘要不只要記錄「做了什麼」,還要記錄「為什麼這樣做」和「結果如何」。daily log 應從 Session JSONL 自動提取決策點和工具調用結果。
技術點 8:Skill 自動瘦身
def refine_skill_document(skill_content, word_threshold=1000):
"""當 SKILL.md 超過 1000 字時,自動觸發 LLM 精簡"""
word_count = len(skill_content.split())
if word_count < word_threshold:
return skill_content
prompt = SKILL_REFINE_PROMPT.format(
word_count=word_count,
skill_content=skill_content
)
refined = llm.chat(prompt, max_tokens=8192)
# 1000 字 → 600 字,保留核心邏輯
return refined
這正是 MEMORY.md 需要的。 目前 1,193 行且持續增長 → 每次 Dream 合併後自動觸發 refine → 歷史條目壓縮為一行摘要 → Token 可控。
三、風險分析:每個技術點的隱性代價
任何設計都有取捨。以下是我們從源碼和架構中識別的風險:
風險矩陣
| # | 技術點 | 最大風險 | 致命度 | 根因 |
|---|---|---|---|---|
| 1 | Skill 自動生成 | 幻覺 Skill 無驗證 — LLM 可能從失敗軌跡提取錯誤流程 | 🔴 | 無回溯測試、無信心分數 |
| 2 | 嵌入檢索 | 語義相似≠實際相關 — MIN_SIMILARITY = 0.0(不過濾!) |
🔴 | 熱門偏差、無多樣性懲罰 |
| 3 | 跨軌跡對比 | 不公平比較 — 軌跡 A 用 GPT-4,軌跡 B 用 DeepSeek | 🔴 | 無控制變量、5× API 成本 |
| 4 | 分層合併 | 過度合併丟細節 — 每次合併丟 10%,5 次後只剩骨架 | 🟠 | LLM 傾向通用化 |
| 5 | 任務分解 | 拆錯級聯失效 — 步驟 1 錯 → 全部檢索無效 | 🔴 | 無分解驗證、無 Token 預算 |
| 6 | 嵌入快取 | 增量更新無效 — 加 1 條經驗 → hash 變 → 1000 條重建 | 🟠 | Hash 不感知增量 |
| 7 | Skill 瘦身 | 關鍵規則丟失 — 「HK$0.14」壓縮成「低價股」 | 🔴 | 不可逆、無數值保護 |
| 8 | 級聯失效 | 10+ LLM 調用串聯 — 誤差傳播 1-0.95⁸=34% | 🔴🔴 | 無端到端驗證 |
級聯失效(系統級風險)
XSkill 的管線中 LLM 被調用超過 10 處:
軌跡摘要 → 經驗提取 → 經驗合併 → Skill 生成 → Skill 合併
→ Skill 精簡 → 任務分解 → 經驗檢索 → 經驗改寫 → 最終推理
每一步 95% 準確率 × 10 步 = 最終準確率僅 60%。這是 XSkill 架構中最深層的風險,論文中未討論。
我們應該加什麼防禦
| 風險 | 防禦措施 |
|---|---|
| 幻覺 Skill | 生成後回溯測試,成功率 <80% 不釋出 |
| 檢索無閾值 | MIN_SIMILARITY = 0.6 + MMR 多樣性重排 |
| 過度合併 | 保留 Diff + 30 天回溯 |
| 任務分解級聯 | 快取分解結果 + Token 預算硬上限 + 一致性驗證 |
| Skill 瘦身 | 關鍵字白名單(「不得」「必須」「禁止」「%」強制保留) |
| 級聯失效 | 管線降級開關 + 端到端品質監控 |
四、XSkill ↔ MemoryHub 對標
| 概念 | XSkill | MemoryHub | 適配建議 |
|---|---|---|---|
| 技能庫 | Skill Library (LLM 生成 + 合併) | AK-SDD SKILL.md (手寫) | 引入自動生成 + 合併 |
| 經驗庫 | Experience Bank (condition-action-emb) | Lessons (非結構化) | 結構化為三元組 + 嵌入 |
| 檢索 | 任務分解 + Cosine + 改寫 | Qdrant COSINE | 加入任務分解路由 |
| 合併 | LLM-based merge + 品質評分 | Dream append | 加入去重 + 品質 + 淘汰 |
| 瘦身 | LLM refine (word_threshold) | 無 | T5 MEMORY.md 壓縮 |
| 快取 | MD5 hash + npy 持久化 | auto_sync 全量掃 | 加入增量 hash 快取 |
| 多模態 | 視覺摘要 + VLM | N/A (純文字) | 不需要 |
五、結論:借什麼、不借什麼
✅ 值得借(低風險、高價值)
- Skill 三階段生命週期 — 架構思想(不是全自動實現)
- Experience 兩層結構 — 結構化教訓為 (condition, action, embedding)
- 任務分解路由 — 查詢路由器的最佳實踐
- Hash 增量快取 — 大幅減少嵌入模型調用
- Skill 瘦身機制 — 但須加白名單和備份
❌ 謹慎借(高風險、需改進)
- 全自動 Skill 生成 — 必須先加驗證迴路
- 無閾值嵌入檢索 — 必須先設 MIN_SIMILARITY
- LLM 自動合併 — 必須先保留 Diff 和回溯
- 串聯管線 — 必須先加降級和端到端驗證
一句話: XSkill 的最大貢獻不是任何單一技術 — 是證明了 Agent 的持續學習不需要重新訓練參數。結構化知識提取 + 語義檢索 + Prompt Injection 就夠了。但它的實現中有多處「過度依賴 LLM 生成而不驗證」的設計假設,在生產環境需要補上品質防線。
本文基於 XSkill-Agent/XSkill v1.0 源碼分析(Commit: main branch, 2026-05-23)。代碼行數:skill_builder.py (232), experience_critique.py (127), experience_retriever.py (~300), trajectory_summary.py (~300), experience_manager.py (651)。