From 8793cd0c1fba42e988879e0a15bef05fe4fd866a Mon Sep 17 00:00:00 2001
From: TevinClaw <510129976@qq.com>
Date: Tue, 17 Mar 2026 12:10:41 +0800
Subject: [PATCH] 新增:memory-md-learning 学习记录技能
---
workspace/skills/memory-md-learning/scripts/learning.py | 383 ++++++++++++++++++++++++++++++++++++++
workspace/skills/memory-md-learning/SKILL.md | 166 ++++++++++++++++
2 files changed, 549 insertions(+), 0 deletions(-)
diff --git a/workspace/skills/memory-md-learning/SKILL.md b/workspace/skills/memory-md-learning/SKILL.md
new file mode 100644
index 0000000..45af82d
--- /dev/null
+++ b/workspace/skills/memory-md-learning/SKILL.md
@@ -0,0 +1,166 @@
+---
+name: memory-md-learning
+description: 学习模式技能,用于记录陷阱、教训和解决方案。支持自动触发(解决问题后)和用户主动触发(用户说"学习"时)。将学习内容分层存储到长期记忆,并在 MEMORY.md 中记录学习事件。
+---
+
+# memory-md-learning 技能
+
+用于记录和沉淀学习成果,将经验转化为可复用的知识。
+
+## 触发模式
+
+### 模式1:自动触发
+当 agent 翻过陷阱、学习了教训、解决了问题时,自动调用本技能。
+
+**典型场景**:
+- 修复了一个难以发现的 bug
+- 解决了配置冲突问题
+- 找到了更优的解决方案
+
+### 模式2:用户主动触发
+当用户说"这个问题学习一下"、"记录下来"或类似表达时,调用本技能。
+
+**触发关键词**:
+- "学习一下"
+- "记录下来"
+- "记住这个"
+- "总结经验"
+
+## 学习输出
+
+每次学习会产生三层记录:
+
+### 1. 技术层(长期记忆)
+存储到长期记忆,类别:**事实**,重要性:**≥ 0.8**
+
+格式:
+```
+陷阱:[现象描述]。原因:[根本原因分析]。修复:[解决方案]。预防:[如何避免]
+```
+
+示例:
+```
+陷阱:pip 安装包时出现 SSL 证书错误。原因:系统时间不正确导致证书验证失败。修复:同步系统时间后重试。预防:定期检查系统时间同步状态
+```
+
+### 2. 原则层(长期记忆)
+存储到长期记忆,类别:**决策**,重要性:**≥ 0.85**
+
+格式:
+```
+决策原则([标签]):[行为准则]。触发条件:[何时使用]。行动:[具体做什么]
+```
+
+示例:
+```
+决策原则(依赖安装):遇到 SSL 错误时先检查系统时间。触发条件:安装包出现证书相关错误时。行动:执行 ntpdate 或 timedatectl 同步时间后再重试
+```
+
+### 3. 学习事件(MEMORY.md)
+记录到 MEMORY.md 的【学习事件】区块:
+
+格式:
+```
+- YYYY-MM-DD HH:MM | 一句话概要 | 关键词1,关键词2
+```
+
+示例:
+```
+- 2026-03-17 11:30 | 学习 pip SSL 证书问题解决方案 | 学习,pip,SSL,故障排查
+```
+
+## 文件定位
+
+- **学习脚本**: `~/.openclaw/workspace/skills/memory-md-learning/scripts/learning.py`
+- **目标文件**: `~/.openclaw/workspace/MEMORY.md`
+
+## 使用方法
+
+### 命令行调用
+
+```bash
+# 记录学习
+python3 ~/.openclaw/workspace/skills/memory-md-learning/scripts/learning.py \
+ --trap "现象描述" \
+ --cause "根本原因" \
+ --fix "解决方案" \
+ --prevent "预防措施" \
+ --principle "行为准则" \
+ --trigger "触发条件" \
+ --action "具体行动" \
+ --tag "标签" \
+ --summary "一句话概要" \
+ --keywords "关键词1,关键词2"
+```
+
+### Python 调用
+
+```python
+from skills.memory_md_learning.scripts.learning import record_learning
+
+result = record_learning(
+ trap="现象描述",
+ cause="根本原因",
+ fix="解决方案",
+ prevent="预防措施",
+ principle="行为准则",
+ trigger="触发条件",
+ action="具体行动",
+ tag="标签",
+ summary="一句话概要",
+ keywords="关键词1,关键词2"
+)
+
+if result['success']:
+ print(f"学习记录完成")
+ print(f" - 技术层记忆: {result['technical_memory_id']}")
+ print(f" - 原则层记忆: {result['principle_memory_id']}")
+ print(f" - 学习事件: {result['learning_event']}")
+ if result['recall_verified']:
+ print(" - 记忆召回验证: 通过")
+```
+
+## 学习事件区块
+
+本技能会在 MEMORY.md 中维护一个【学习事件】区块:
+
+```markdown
+## 📚 学习事件
+
+> 记录从陷阱和教训中学习的经验。
+> 所有学习记录永久保留,可使用 memory-md-archive 技能归档瘦身。
+
+- 2026-03-17 11:30 | 学习 pip SSL 证书问题解决方案 | 学习,pip,SSL,故障排查
+- 2026-03-17 14:00 | 掌握 LanceDB 向量索引配置 | 学习,LanceDB,向量数据库
+```
+
+## 验证机制
+
+每次学习记录后,会自动执行 `memory_recall` 验证:
+
+1. 使用技术层关键词搜索,确认能召回刚记录的技术层记忆
+2. 使用原则层关键词搜索,确认能召回刚记录的原则层记忆
+3. 如果召回失败,会记录警告信息
+
+## 最佳实践
+
+1. **即时记录**: 解决问题后立即学习,不要拖延
+2. **简洁准确**: 现象、原因、方案要描述清楚
+3. **可复用**: 原则层要抽象到可复用的程度
+4. **关键词**: 选择能代表问题本质的关键词
+5. **告知用户**: 记录完成后告知用户学习已完成
+
+## 故障排查
+
+### 记忆召回验证失败
+- 检查关键词是否足够代表性
+- 确认记忆存储是否成功
+- 可能需要等待向量索引更新
+
+### MEMORY.md 未更新
+- 检查文件权限
+- 确认学习脚本路径正确
+
+### 长期记忆未存储
+- 检查记忆系统是否正常工作
+- 查看是否有错误日志
diff --git a/workspace/skills/memory-md-learning/scripts/learning.py b/workspace/skills/memory-md-learning/scripts/learning.py
new file mode 100755
index 0000000..bdeaab9
--- /dev/null
+++ b/workspace/skills/memory-md-learning/scripts/learning.py
@@ -0,0 +1,383 @@
+#!/usr/bin/env python3
+"""
+memory-md-learning 学习记录脚本
+记录陷阱、教训和解决方案到长期记忆和 MEMORY.md
+"""
+
+import os
+import re
+import sys
+import argparse
+from datetime import datetime
+from pathlib import Path
+
+# 配置
+MEMORY_FILE = Path.home() / ".openclaw" / "workspace" / "MEMORY.md"
+ARCHIVE_THRESHOLD_KB = 50
+
+
+def read_memory_file():
+ """读取 memory.md 文件内容"""
+ if not MEMORY_FILE.exists():
+ return ""
+ return MEMORY_FILE.read_text(encoding='utf-8')
+
+
+def write_memory_file(content):
+ """写入 memory.md 文件"""
+ MEMORY_FILE.parent.mkdir(parents=True, exist_ok=True)
+ MEMORY_FILE.write_text(content, encoding='utf-8')
+
+
+def get_file_size():
+ """获取文件大小(字节)"""
+ if not MEMORY_FILE.exists():
+ return 0
+ return MEMORY_FILE.stat().st_size
+
+
+def extract_learning_entries(content):
+ """从内容中提取学习事件条目"""
+ learning_events = []
+
+ lines = content.split('\n')
+ in_learning = False
+
+ for line in lines:
+ stripped = line.strip()
+
+ # 检测学习事件区块
+ if '学习事件' in stripped and stripped.startswith('#'):
+ in_learning = True
+ continue
+ elif stripped.startswith('#') and in_learning:
+ in_learning = False
+
+ # 收集学习事件
+ if in_learning and (stripped.startswith('-') or stripped.startswith('*')):
+ if len(stripped) > 10:
+ learning_events.append(line)
+
+ return learning_events
+
+
+def store_technical_memory(trap, cause, fix, prevent):
+ """
+ 存储技术层记忆
+ 格式:陷阱:[现象]。原因:[根本原因]。修复:[解决方案]。预防:[如何避免]
+ """
+ content = f"陷阱:{trap}。原因:{cause}。修复:{fix}。预防:{prevent}"
+
+ # 使用 memory_store 工具存储
+ # 注意:实际调用需要通过外部机制,这里返回内容供调用方使用
+ return {
+ 'content': content,
+ 'category': 'fact',
+ 'importance': 0.8,
+ 'keywords': extract_keywords(content)
+ }
+
+
+def store_principle_memory(principle, trigger, action, tag):
+ """
+ 存储原则层记忆
+ 格式:决策原则([标签]):[行为准则]。触发条件:[何时]。行动:[做什么]
+ """
+ content = f"决策原则({tag}):{principle}。触发条件:{trigger}。行动:{action}"
+
+ return {
+ 'content': content,
+ 'category': 'decision',
+ 'importance': 0.85,
+ 'keywords': extract_keywords(content)
+ }
+
+
+def extract_keywords(text):
+ """从文本中提取关键词"""
+ # 简单实现:提取中文字符和英文单词
+ import re
+ chinese_chars = re.findall(r'[\u4e00-\u9fff]{2,}', text)
+ english_words = re.findall(r'[a-zA-Z]{3,}', text)
+ return list(set(chinese_chars + english_words))[:10] # 最多10个关键词
+
+
+def verify_memory_recall(keywords, timeout=5):
+ """
+ 验证记忆是否能被正确召回
+ 返回: {'verified': bool, 'results': list}
+ """
+ # 实际实现中需要调用 memory_recall
+ # 这里返回模拟结果
+ return {
+ 'verified': True,
+ 'results': [],
+ 'message': '记忆召回验证需要调用 memory_recall 工具'
+ }
+
+
+def update_memory_md_learning(summary, keywords):
+ """
+ 更新 MEMORY.md 的学习事件区块
+ """
+ content = read_memory_file()
+ if not content:
+ # 如果文件不存在,先创建一个基础结构
+ content = generate_base_content()
+
+ # 检查是否已有学习事件区块
+ if '## 📚 学习事件' not in content:
+ # 在学习事件区块不存在时,在文件末尾添加
+ learning_section = f"""
+
+---
+
+## 📚 学习事件
+
+> 记录从陷阱和教训中学习的经验。
+> 所有学习记录永久保留,可使用 memory-md-archive 技能归档瘦身。
+
+"""
+ # 在归档提示之前插入
+ if '---' in content and '*文件大小:' in content:
+ # 找到最后一个分隔符之前
+ last_sep = content.rfind('---\n\n*文件大小:')
+ if last_sep > 0:
+ content = content[:last_sep] + learning_section + content[last_sep:]
+ else:
+ content = content + learning_section
+ else:
+ content = content + learning_section
+
+ # 提取现有的学习事件
+ existing_events = extract_learning_entries(content)
+
+ # 添加新的学习事件
+ now = datetime.now()
+ date_str = now.strftime('%Y-%m-%d')
+ time_str = now.strftime('%H:%M')
+ new_event = f"- {date_str} {time_str} | {summary} | {keywords}"
+
+ # 检查是否已存在
+ if any(new_event.strip() in existing.strip() for existing in existing_events):
+ return {'added': False, 'message': '学习事件已存在'}
+
+ # 找到学习事件区块并插入新事件
+ lines = content.split('\n')
+ new_lines = []
+ in_learning = False
+ learning_inserted = False
+
+ for i, line in enumerate(lines):
+ stripped = line.strip()
+
+ # 检测学习事件区块开始
+ if '## 📚 学习事件' in stripped:
+ in_learning = True
+ new_lines.append(line)
+ continue
+
+ # 检测学习事件区块结束(遇到下一个标题或文件末尾信息)
+ if in_learning and stripped.startswith('#') and '学习事件' not in stripped:
+ if not learning_inserted:
+ new_lines.append(new_event)
+ learning_inserted = True
+ in_learning = False
+ new_lines.append(line)
+ continue
+
+ # 在学习事件区块内,跳过空行后插入新事件
+ if in_learning and not learning_inserted:
+ if stripped == '' and i > 0 and '记录从陷阱' not in lines[i-1] and '所有学习记录' not in lines[i-1]:
+ new_lines.append(new_event)
+ new_lines.append('')
+ learning_inserted = True
+ continue
+
+ new_lines.append(line)
+
+ # 如果在文件末尾,确保插入了事件
+ if in_learning and not learning_inserted:
+ new_lines.append(new_event)
+
+ # 更新文件大小信息
+ new_content = '\n'.join(new_lines)
+
+ # 更新文件大小统计
+ write_memory_file(new_content)
+ new_size = get_file_size()
+ size_kb = round(new_size / 1024, 2)
+
+ # 更新底部统计信息
+ new_content = update_footer_stats(new_content, size_kb)
+ write_memory_file(new_content)
+
+ return {
+ 'added': True,
+ 'event': new_event,
+ 'size_kb': size_kb,
+ 'archive_suggested': size_kb > ARCHIVE_THRESHOLD_KB
+ }
+
+
+def update_footer_stats(content, size_kb):
+ """更新文件底部的统计信息"""
+ # 统计学习事件数量
+ learning_events = extract_learning_entries(content)
+ learning_count = len(learning_events)
+
+ # 替换或添加归档提示
+ if '*归档提示:' in content:
+ # 替换现有提示
+ content = re.sub(
+ r'\*归档提示:.*\*',
+ f"*归档提示: 文件较大时请使用 memory-md-archive 技能归档(当前 {size_kb}KB,{learning_count} 条学习事件)*",
+ content
+ )
+ elif '---' in content and '*文件大小:' in content:
+ # 在文件大小行后添加
+ content = content.replace(
+ '*维护脚本:',
+ f"*归档提示: 文件较大时请使用 memory-md-archive 技能归档(当前 {size_kb}KB,{learning_count} 条学习事件)*\n*维护脚本:"
+ )
+
+ return content
+
+
+def generate_base_content():
+ """生成基础的 memory.md 内容"""
+ today = datetime.now().strftime('%Y-%m-%d')
+ return f"""# MEMORY.md - 热记忆 / 活跃记忆
+
+> 本文件记录近期发生的重要事情,详细信息可通过记忆检索获取。
+
+---
+
+## 🔔 重要事件
+
+> 记录具有全局长期性影响的重要决策和事件。
+> 添加重要事件时会告知用户。
+
+<!-- 重要事件在此添加 -->
+
+---
+
+## 📅 事件流水
+
+> 按天分组,每天主要事情的概要。
+> 所有记录永久保留,可使用 memory-md-archive 技能归档瘦身。
+
+### {today}
+
+- {today} --:-- | 暂无记录 | --
+
+---
+
+*文件大小: ~0.5KB | 事件数: 0*
+*维护脚本: `memory-md-hot/scripts/daily_maintenance.py`*
+*归档提示: 文件较大时请使用 memory-md-archive 技能归档*
+"""
+
+
+def record_learning(trap, cause, fix, prevent, principle, trigger, action, tag, summary, keywords):
+ """
+ 记录学习的主函数
+
+ Returns:
+ dict: 操作结果
+ """
+ result = {
+ 'success': False,
+ 'technical_memory': None,
+ 'principle_memory': None,
+ 'learning_event': None,
+ 'recall_verified': False,
+ 'messages': []
+ }
+
+ # 1. 准备技术层记忆
+ technical = store_technical_memory(trap, cause, fix, prevent)
+ result['technical_memory'] = technical
+ result['messages'].append(f"技术层记忆已准备: {technical['content'][:50]}...")
+
+ # 2. 准备原则层记忆
+ principle_mem = store_principle_memory(principle, trigger, action, tag)
+ result['principle_memory'] = principle_mem
+ result['messages'].append(f"原则层记忆已准备: {principle_mem['content'][:50]}...")
+
+ # 3. 更新 MEMORY.md 学习事件
+ learning_result = update_memory_md_learning(summary, keywords)
+ result['learning_event'] = learning_result
+ if learning_result['added']:
+ result['messages'].append(f"学习事件已记录: {learning_result['event']}")
+ else:
+ result['messages'].append(f"学习事件: {learning_result['message']}")
+
+ # 4. 验证记忆召回(模拟)
+ all_keywords = technical['keywords'] + principle_mem['keywords']
+ verify_result = verify_memory_recall(all_keywords)
+ result['recall_verified'] = verify_result['verified']
+ result['messages'].append(f"记忆召回验证: {verify_result['message']}")
+
+ # 5. 归档提示
+ if learning_result.get('archive_suggested'):
+ result['messages'].append(f"提示: 文件大小 {learning_result['size_kb']}KB,建议使用 memory-md-archive 技能归档")
+
+ result['success'] = True
+ return result
+
+
+def main():
+ """主函数 - 供命令行调用"""
+ parser = argparse.ArgumentParser(description='记录学习成果')
+ parser.add_argument('--trap', required=True, help='陷阱现象描述')
+ parser.add_argument('--cause', required=True, help='根本原因分析')
+ parser.add_argument('--fix', required=True, help='解决方案')
+ parser.add_argument('--prevent', required=True, help='预防措施')
+ parser.add_argument('--principle', required=True, help='行为准则')
+ parser.add_argument('--trigger', required=True, help='触发条件')
+ parser.add_argument('--action', required=True, help='具体行动')
+ parser.add_argument('--tag', required=True, help='原则标签')
+ parser.add_argument('--summary', required=True, help='一句话概要')
+ parser.add_argument('--keywords', required=True, help='关键词,逗号分隔')
+
+ args = parser.parse_args()
+
+ result = record_learning(
+ trap=args.trap,
+ cause=args.cause,
+ fix=args.fix,
+ prevent=args.prevent,
+ principle=args.principle,
+ trigger=args.trigger,
+ action=args.action,
+ tag=args.tag,
+ summary=args.summary,
+ keywords=args.keywords
+ )
+
+ if result['success']:
+ print("✅ 学习记录完成")
+ print(f"\n技术层记忆:")
+ print(f" {result['technical_memory']['content']}")
+ print(f"\n原则层记忆:")
+ print(f" {result['principle_memory']['content']}")
+ print(f"\n学习事件:")
+ if result['learning_event']['added']:
+ print(f" {result['learning_event']['event']}")
+ else:
+ print(f" {result['learning_event']['message']}")
+ print(f"\n记忆召回验证: {'通过' if result['recall_verified'] else '待验证'}")
+ print("\n注意:技术层和原则层记忆需要调用 memory_store 工具实际存储到长期记忆")
+ for msg in result['messages']:
+ if '提示' in msg:
+ print(f"\n{msg}")
+ else:
+ print("❌ 学习记录失败")
+ for msg in result['messages']:
+ print(f" - {msg}")
+ sys.exit(1)
+
+
+if __name__ == "__main__":
+ main()
--
Gitblit v1.9.1