欢迎来到OpenClaw 7天学习教程的第六天!在前五天的学习中,我们已经完成了基础安装、个性定制、飞书集成和技能扩展。今天,我们将深入探讨OpenClaw的记忆管理与个性化对话能力,让你的AI助手能够更好地记住与你的交流内容,形成更连贯、个性化的对话体验。
🧠 理解AI助手的记忆系统
OpenClaw能够变成你的助手,而不是问一句答一句的AI非常重要的一点是它的记忆功能。合理配置记忆功能,可以让AI更了解你、了解你们的工作进度并提供支持,但是太长的记忆会让每次对话都有超长的上下文,token燃烧飞快,所以合理配置OpenClaw的记忆系统格外重要。本章内容比较进阶,可以根据需求,选择性学习,不一定需要完全按照教程设置。
根据OpenClaw的设计,AI助手的记忆系统主要基于文件存储,分为以下几个部分:
记忆类型
- 短期记忆:当前对话会话中的内容,会随会话结束而消失
- 日常记录:每日记录
memory/YYYY-MM-DD.md,记录每天对话的重要 - 长期记忆:
MEMORY.md文件,存储经过整理的重要信息和上下文
记忆管理原则
- 只在主会话加载:长期记忆只在与用户的直接对话中加载,不在共享上下文中加载
- 写下来才能记住:重要信息必须写入文件,而不是"心理记录"
- 安全第一:不在群聊或共享场景下暴露个人信息
- 定期整理:从日常记录中提炼重要信息到长期记忆
📝 创建基础记忆文件结构
让我们建立一个有效的记忆文件结构(可能初始化时已经创建好了,如果没有按照以下命令创建):
- 首先,创建必要的目录和文件:
# 创建记忆目录
mkdir -p ~/.openclaw/memory
# 创建长期记忆文件
touch ~/.openclaw/MEMORY.md
# 创建今天的日常记录文件(格式为YYYY-MM-DD.md)
touch ~/.openclaw/memory/$(date +%Y-%m-%d).md- 初始化长期记忆文件 (MEMORY.md) 结构:
cat > ~/.openclaw/MEMORY.md << 'EOF'
# 长期记忆索引
这是OpenClaw助手的长期记忆文件,存储所有重要信息的索引和关键内容。
## 用户偏好
*记录用户的重要偏好和习惯。*
- **通信偏好**: [尚未记录]
- **工作习惯**: [尚未记录]
- **兴趣爱好**: [尚未记录]
## 进行中的项目
*当前正在进行的项目及其状态。*
-
## 知识库索引
*重要知识的索引,按类别组织。*
- **技术笔记**: `knowledge/tech/`
- **工作流程**: `knowledge/workflows/`
- **常用命令**: `knowledge/commands.md`
## 重要决策记录
*记录重要决策及其背景原因。*
- 尚未有记录
## 定期回顾
*定期回顾和反思的记录。*
- 尚未有记录
EOF📔 MEMORY.md 的结构与管理
长期记忆文件(MEMORY.md)是AI助手记忆系统的核心。它应该是一个精心组织的索引,而不是所有记忆的堆砌。以下是一些最佳实践:
- 结构化索引:使用清晰的章节来组织不同类型的信息
- 引用而非复制:引用具体文件而不是将所有内容复制到一处
- 定期更新:从日常记忆文件中提炼重要信息,更新长期记忆
- 创建项目进度追踪文件:
# 创建项目目录
mkdir -p ~/.openclaw/projects/openclaw_learning
# 创建项目进度文件
cat > ~/.openclaw/projects/openclaw_learning/progress.md << 'EOF'
# OpenClaw学习进度
## 最新状态
- **当前进度**: 学习Day 6 - 记忆管理与个性化对话
- **完成日期**: [尚未完成]
- **下一步**: 完成Day 7 - 多模态与高级应用
## 进度详情
### Day 1: 基础安装与配置
- ✅ 完成安装
- ✅ 完成基础配置
- ✅ 测试基本功能
### Day 2: 个性化定制
- ✅ 完成个性设置
- ✅ 配置提示词模板
- ✅ 测试个性化回复
### Day 3: 飞书集成
- ✅ 完成飞书机器人创建
- ✅ 建立OpenClaw与飞书的连接
- ✅ 测试消息收发功能
### Day 4: 工具使用与插件
- ✅ 配置基础工具
- ✅ 添加自定义插件
- ✅ 测试工具功能
### Day 5: 技能扩展
- ✅ 学习技能概念
- ✅ 添加自定义技能
- ✅ 测试技能功能
### Day 6: 记忆管理与个性化对话
- 🔄 设置记忆文件结构
- 🔄 创建记忆管理流程
- 🔄 测试记忆功能
### Day 7: 多模态与高级应用
- ⏳ 未开始
## 学习笔记
- OpenClaw是一个功能强大的AI助手框架,可以通过多种方式进行定制
- 个性化设置可以让助手更符合特定场景的需求
- 工具和技能扩展极大增强了助手的能力范围
EOF🔖 创建记忆管理脚本
为了更方便地管理记忆,我们可以创建一些辅助脚本:
- 创建每日记忆文件生成脚本:
cat > ~/.openclaw/scripts/create_daily_memory.sh << 'EOF'
#!/bin/bash
# 设置记忆目录
MEMORY_DIR=~/.openclaw/memory
# 确保目录存在
mkdir -p $MEMORY_DIR
# 获取今天的日期
TODAY=$(date +%Y-%m-%d)
MEMORY_FILE="$MEMORY_DIR/$TODAY.md"
# 如果文件不存在,则创建
if [ ! -f "$MEMORY_FILE" ]; then
echo "# 记忆记录: $TODAY" > "$MEMORY_FILE"
echo "" >> "$MEMORY_FILE"
echo "## 对话摘要" >> "$MEMORY_FILE"
echo "" >> "$MEMORY_FILE"
echo "## 重要信息" >> "$MEMORY_FILE"
echo "" >> "$MEMORY_FILE"
echo "## 行动项" >> "$MEMORY_FILE"
echo "" >> "$MEMORY_FILE"
echo "创建了今天的记忆文件: $MEMORY_FILE"
else
echo "今天的记忆文件已存在: $MEMORY_FILE"
fi
EOF
chmod +x ~/.openclaw/scripts/create_daily_memory.sh- 创建记忆搜索脚本:
cat > ~/.openclaw/scripts/search_memory.sh << 'EOF'
#!/bin/bash
# 设置搜索目录
MEMORY_DIR=~/.openclaw/memory
LONG_TERM_MEMORY=~/.openclaw/MEMORY.md
PROJECTS_DIR=~/.openclaw/projects
# 检查参数
if [ $# -eq 0 ]; then
echo "用法: $0 <搜索关键词>"
exit 1
fi
# 获取搜索词
SEARCH_TERM="$*"
echo "搜索: '$SEARCH_TERM'"
echo "========================================"
# 搜索长期记忆
echo "## 在长期记忆中搜索"
if [ -f "$LONG_TERM_MEMORY" ]; then
grep -i --color=always "$SEARCH_TERM" "$LONG_TERM_MEMORY" | head -n 10
RESULTS=$(grep -i -c "$SEARCH_TERM" "$LONG_TERM_MEMORY")
echo "找到 $RESULTS 处匹配"
else
echo "长期记忆文件不存在"
fi
echo "========================================"
# 搜索日常记忆
echo "## 在日常记忆中搜索"
if [ -d "$MEMORY_DIR" ]; then
grep -i --color=always -r "$SEARCH_TERM" "$MEMORY_DIR" | head -n 10
RESULTS=$(grep -i -r -c "$SEARCH_TERM" "$MEMORY_DIR" | wc -l)
echo "找到 $RESULTS 处匹配"
else
echo "记忆目录不存在"
fi
echo "========================================"
# 搜索项目文件
echo "## 在项目文件中搜索"
if [ -d "$PROJECTS_DIR" ]; then
grep -i --color=always -r "$SEARCH_TERM" "$PROJECTS_DIR" | head -n 10
RESULTS=$(grep -i -r -c "$SEARCH_TERM" "$PROJECTS_DIR" | wc -l)
echo "找到 $RESULTS 处匹配"
else
echo "项目目录不存在"
fi
EOF
chmod +x ~/.openclaw/scripts/search_memory.sh- 创建记忆摘要生成脚本:
cat > ~/.openclaw/scripts/summarize_daily_memory.sh << 'EOF'
#!/bin/bash
# 设置记忆目录
MEMORY_DIR=~/.openclaw/memory
LONG_TERM_MEMORY=~/.openclaw/MEMORY.md
# 获取昨天的日期
YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)
MEMORY_FILE="$MEMORY_DIR/$YESTERDAY.md"
# 检查昨天的记忆文件是否存在
if [ ! -f "$MEMORY_FILE" ]; then
echo "昨天的记忆文件不存在: $MEMORY_FILE"
exit 1
fi
echo "正在处理昨天的记忆文件: $MEMORY_FILE"
# 使用OpenClaw生成摘要
# 这里假设OpenClaw有一个命令行接口
# 实际上你可能需要通过API或其他方式与OpenClaw交互
echo "请求OpenClaw生成摘要..."
# 生成摘要的提示词
PROMPT="请为以下日常记忆内容生成一个简洁的摘要,提取出所有重要信息、决策和行动项。这些信息将被添加到长期记忆中。只返回摘要内容,不需要其他解释。记忆内容如下:\n\n$(cat $MEMORY_FILE)"
# 这里你需要根据OpenClaw的实际接口来调用它
# 例如,可能是通过API调用
# 以下仅为示例,需要根据实际情况修改
# openclaw generate "$PROMPT" > summary.txt
echo "摘要已生成,请检查并手动添加到长期记忆文件: $LONG_TERM_MEMORY"
EOF
chmod +x ~/.openclaw/scripts/summarize_daily_memory.sh- 添加这些脚本到启动流程中:
cat >> ~/.openclaw/startup.sh << 'EOF'
# 创建今天的记忆文件
~/.openclaw/scripts/create_daily_memory.sh
# 输出记忆系统已准备好的消息
echo "记忆系统已准备就绪!"
EOF👤 创建用户偏好记录文件
为了更好地跟踪用户偏好,我们可以创建专门的偏好文件:
mkdir -p ~/.openclaw/knowledge
cat > ~/.openclaw/knowledge/user_preferences.md << 'EOF'
# 用户偏好记录
本文件记录用户的各种偏好和习惯,以便提供更加个性化的服务。
## 通信偏好
- **沟通风格**: [尚未记录]
- **回复长度**: [尚未记录]
- **回复格式**: [尚未记录]
- **反馈方式**: [尚未记录]
## 工作习惯
- **工作时间**: [尚未记录]
- **专注时段**: [尚未记录]
- **休息模式**: [尚未记录]
- **提醒设置**: [尚未记录]
## 内容偏好
- **信息详细度**: [尚未记录]
- **技术复杂度**: [尚未记录]
- **示例偏好**: [尚未记录]
- **视觉元素**: [尚未记录]
## 个人兴趣
- **专业领域**: [尚未记录]
- **学习主题**: [尚未记录]
- **娱乐偏好**: [尚未记录]
- **其他兴趣**: [尚未记录]
## 更新记录
- **初始创建**: [日期]
- **最近更新**: [日期]
EOF
# 更新MEMORY.md中的索引
sed -i 's|**兴趣爱好**: \[尚未记录\]|**兴趣爱好**: 参见 `knowledge/user_preferences.md`|' ~/.openclaw/MEMORY.md🗂️ 创建项目模板
为了更好地管理项目相关的记忆,我们可以创建一个项目模板:
mkdir -p ~/.openclaw/templates
cat > ~/.openclaw/templates/project_template.md << 'EOF'
# [项目名称]
## 项目概览
- **开始日期**: [YYYY-MM-DD]
- **预计完成**: [YYYY-MM-DD]
- **项目类型**: [类型]
- **优先级**: [高/中/低]
## 最新状态
- **当前阶段**: [阶段描述]
- **完成度**: [进度百分比]
- **最近更新**: [YYYY-MM-DD]
## 目标与范围
[描述项目的主要目标和范围]
## 任务清单
- [ ] 任务1
- [ ] 子任务1.1
- [ ] 子任务1.2
- [ ] 任务2
- [ ] 任务3
## 参考资料
- [参考资料1]
- [参考资料2]
## 笔记与思考
[项目相关的笔记和思考]
## 决策记录
| 日期 | 决策 | 原因 | 替代方案 | 影响 |
|------|------|------|----------|------|
| [日期] | [决策] | [原因] | [替代方案] | [影响] |
## 进展日志
### [YYYY-MM-DD]
- [进展内容]
EOF
# 创建一个项目创建脚本
cat > ~/.openclaw/scripts/create_project.sh << 'EOF'
#!/bin/bash
# 检查参数
if [ $# -eq 0 ]; then
echo "用法: $0 <项目名称>"
exit 1
fi
# 获取项目名称并规范化
PROJECT_NAME="$*"
DIR_NAME=$(echo "$PROJECT_NAME" | tr ' ' '_' | tr '[:upper:]' '[:lower:]')
# 设置项目目录
PROJECTS_DIR=~/.openclaw/projects
PROJECT_DIR="$PROJECTS_DIR/$DIR_NAME"
# 确保目录存在
mkdir -p "$PROJECT_DIR"
# 拷贝模板
TEMPLATE=~/.openclaw/templates/project_template.md
cp "$TEMPLATE" "$PROJECT_DIR/progress.md"
# 替换项目名称
sed -i "s/\[项目名称\]/$PROJECT_NAME/" "$PROJECT_DIR/progress.md"
sed -i "s/\[YYYY-MM-DD\]/$(date +%Y-%m-%d)/" "$PROJECT_DIR/progress.md"
# 更新长期记忆索引
MEMORY_FILE=~/.openclaw/MEMORY.md
if grep -q "## 进行中的项目" "$MEMORY_FILE"; then
# 添加到现有项目列表
sed -i "/## 进行中的项目/a - **$PROJECT_NAME**: 参见 \`projects/$DIR_NAME/progress.md\`" "$MEMORY_FILE"
else
# 如果没有项目部分,添加它
echo "## 进行中的项目" >> "$MEMORY_FILE"
echo "" >> "$MEMORY_FILE"
echo "- **$PROJECT_NAME**: 参见 \`projects/$DIR_NAME/progress.md\`" >> "$MEMORY_FILE"
fi
echo "项目 '$PROJECT_NAME' 已创建: $PROJECT_DIR/progress.md"
echo "长期记忆文件已更新"
EOF
chmod +x ~/.openclaw/scripts/create_project.sh📊 创建记忆提取与整理工作流
以下是一个简单的工作流,用于从对话中提取重要信息并整理到记忆文件中:
- 创建记忆管理工作流文件:
mkdir -p ~/.openclaw/workflows
cat > ~/.openclaw/workflows/memory_workflow.py << 'EOF'
import os
import re
import json
from datetime import datetime
from openclaw.agents import Agent
from openclaw.utils.logger import logger
class MemoryManager:
def __init__(self):
# 设置记忆文件路径
self.memory_dir = os.path.expanduser("~/.openclaw/memory")
self.long_term_memory = os.path.expanduser("~/.openclaw/MEMORY.md")
# 确保记忆目录存在
os.makedirs(self.memory_dir, exist_ok=True)
# 获取今天的日期
self.today = datetime.now().strftime("%Y-%m-%d")
self.daily_memory_file = os.path.join(self.memory_dir, f"{self.today}.md")
# 确保今天的记忆文件存在
self._ensure_daily_file()
def _ensure_daily_file(self):
"""确保今天的记忆文件存在"""
if not os.path.exists(self.daily_memory_file):
with open(self.daily_memory_file, 'w', encoding='utf-8') as f:
f.write(f"# 记忆记录: {self.today}\n\n")
f.write("## 对话摘要\n\n")
f.write("## 重要信息\n\n")
f.write("## 行动项\n\n")
def append_to_daily_memory(self, section, content):
"""添加内容到今天的记忆文件"""
self._ensure_daily_file()
with open(self.daily_memory_file, 'r', encoding='utf-8') as f:
lines = f.readlines()
# 找到指定部分
section_pattern = f"## {section}"
section_index = -1
next_section_index = len(lines)
for i, line in enumerate(lines):
if line.strip() == section_pattern:
section_index = i
elif section_index >= 0 and line.startswith("## "):
next_section_index = i
break
if section_index >= 0:
# 在部分末尾添加内容
timestamp = datetime.now().strftime("%H:%M")
content_with_timestamp = f"- [{timestamp}] {content}\n"
lines.insert(next_section_index, content_with_timestamp)
with open(self.daily_memory_file, 'w', encoding='utf-8') as f:
f.writelines(lines)
return True
return False
def extract_important_info(self, text, agent):
"""从文本中提取重要信息"""
if not agent:
return None
extract_prompt = f"""
请分析以下文本,提取出以下三类信息:
1. 重要信息:任何值得记住的事实、偏好或关键点
2. 决策:任何做出的决定或承诺
3. 行动项:需要跟进的任何任务或提醒
对于每一类,如果有相关内容,请以简洁的方式列出;如果没有,返回"无"。
只返回提取的信息,格式如下:
重要信息:
- [提取的信息1]
- [提取的信息2]
决策:
- [提取的决策1]
- [提取的决策2]
行动项:
- [提取的行动项1]
- [提取的行动项2]
文本:
{text}
"""
response = agent.generate(extract_prompt)
return response
def process_conversation(self, messages, agent):
"""处理对话并提取重要信息"""
# 合并对话内容
conversation = "\n".join([
f"{m.get('role', 'unknown')}: {m.get('content', '')}"
for m in messages[-10:] # 只处理最近的10条消息
])
# 提取重要信息
extracted = self.extract_important_info(conversation, agent)
if extracted:
# 处理提取的信息
info_match = re.search(r'重要信息:\n(.*?)\n\n', extracted, re.DOTALL)
decisions_match = re.search(r'决策:\n(.*?)\n\n', extracted, re.DOTALL)
actions_match = re.search(r'行动项:\n(.*?)$', extracted, re.DOTALL)
if info_match and info_match.group(1).strip() != "无":
for line in info_match.group(1).strip().split('\n'):
if line.strip() and not line.strip() == "- 无":
self.append_to_daily_memory("重要信息", line.strip().lstrip('- '))
if decisions_match and decisions_match.group(1).strip() != "无":
for line in decisions_match.group(1).strip().split('\n'):
if line.strip() and not line.strip() == "- 无":
self.append_to_daily_memory("重要决策", line.strip().lstrip('- '))
if actions_match and actions_match.group(1).strip() != "无":
for line in actions_match.group(1).strip().split('\n'):
if line.strip() and not line.strip() == "- 无":
self.append_to_daily_memory("行动项", line.strip().lstrip('- '))
# 创建记忆管理器实例
memory_manager = MemoryManager()
def register_callbacks(agent):
@agent.on_conversation_end
def process_ended_conversation(messages, **kwargs):
"""在对话结束时处理记忆"""
if len(messages) > 3: # 只处理足够长的对话
memory_manager.process_conversation(messages, agent)
@agent.after_user_message
def detect_memory_commands(message, **kwargs):
"""检测与记忆相关的命令"""
# 检测记忆相关命令
if re.search(r'^(记住|请记住|记录|请记录).*', message, re.IGNORECASE):
# 提取要记住的内容
content = re.sub(r'^(记住|请记住|记录|请记录)\s*', '', message)
# 添加到今天的记忆
memory_manager.append_to_daily_memory("重要信息", content)
return "我已经记住了这条信息,并将其添加到今天的记忆文件中。"
return None # 继续正常处理消息
EOF
# 在OpenClaw启动时注册记忆工作流
echo 'openclaw workflow register memory_workflow' >> ~/.openclaw/startup.sh🔍 用户偏好提取工作流
让我们创建一个用户偏好提取工作流:
cat > ~/.openclaw/workflows/preference_workflow.py << 'EOF'
import os
import re
import json
from datetime import datetime
from openclaw.agents import Agent
from openclaw.utils.logger import logger
class PreferenceManager:
def __init__(self):
self.preferences_file = os.path.expanduser("~/.openclaw/knowledge/user_preferences.md")
# 确保目录存在
os.makedirs(os.path.dirname(self.preferences_file), exist_ok=True)
# 确保偏好文件存在
if not os.path.exists(self.preferences_file):
self._create_default_preferences()
def _create_default_preferences(self):
"""创建默认的偏好文件"""
with open(self.preferences_file, 'w', encoding='utf-8') as f:
f.write("# 用户偏好记录\n\n")
f.write("本文件记录用户的各种偏好和习惯,以便提供更加个性化的服务。\n\n")
f.write("## 通信偏好\n\n")
f.write("- **沟通风格**: [尚未记录]\n")
f.write("- **回复长度**: [尚未记录]\n")
f.write("- **回复格式**: [尚未记录]\n\n")
f.write("## 工作习惯\n\n")
f.write("- **工作时间**: [尚未记录]\n")
f.write("- **专注时段**: [尚未记录]\n\n")
f.write("## 内容偏好\n\n")
f.write("- **信息详细度**: [尚未记录]\n")
f.write("- **技术复杂度**: [尚未记录]\n\n")
f.write("## 个人兴趣\n\n")
f.write("- **专业领域**: [尚未记录]\n")
f.write("- **学习主题**: [尚未记录]\n\n")
f.write("## 更新记录\n\n")
f.write(f"- **初始创建**: {datetime.now().strftime('%Y-%m-%d')}\n")
f.write(f"- **最近更新**: {datetime.now().strftime('%Y-%m-%d')}\n")
def update_preference(self, category, key, value):
"""更新用户偏好"""
if not os.path.exists(self.preferences_file):
self._create_default_preferences()
with open(self.preferences_file, 'r', encoding='utf-8') as f:
lines = f.readlines()
# 查找分类
category_pattern = f"## {category}"
category_index = -1
next_category_index = len(lines)
for i, line in enumerate(lines):
if line.strip() == category_pattern:
category_index = i
elif category_index >= 0 and line.startswith("## "):
next_category_index = i
break
# 如果找不到分类,添加一个
if category_index == -1:
category_index = next_category_index - 1
lines.insert(category_index + 1, f"## {category}\n\n")
next_category_index += 2
# 查找键
key_pattern = f"- **{key}**:"
key_found = False
for i in range(category_index + 1, next_category_index):
if key_pattern in lines[i]:
lines[i] = f"- **{key}**: {value}\n"
key_found = True
break
# 如果找不到键,添加一个
if not key_found:
lines.insert(next_category_index, f"- **{key}**: {value}\n")
# 更新最近更新时间
update_time = f"- **最近更新**: {datetime.now().strftime('%Y-%m-%d')}\n"
update_found = False
for i, line in enumerate(lines):
if "- **最近更新**:" in line:
lines[i] = update_time
update_found = True
break
if not update_found:
lines.append("\n## 更新记录\n\n")
lines.append(update_time)
with open(self.preferences_file, 'w', encoding='utf-8') as f:
f.writelines(lines)
return True
def extract_preferences(self, text, agent):
"""从文本中提取用户偏好"""
if not agent:
return None
extract_prompt = f"""
请从以下文本中提取用户明确表达的偏好,并按以下格式返回:
偏好:
- 分类: [分类], 键: [键], 值: [值]
- 分类: [分类], 键: [键], 值: [值]
分类可以是:通信偏好、工作习惯、内容偏好、个人兴趣或其他合适的类别。
键应该是具体的偏好类型,如沟通风格、回复长度等。
只提取明确表达的偏好,不要猜测。如果没有明确的偏好,返回"未发现明确的偏好表达"。
文本:
{text}
"""
response = agent.generate(extract_prompt)
# 解析响应
if "未发现明确的偏好表达" in response:
return None
preferences = []
pref_lines = re.findall(r'- 分类: (.*?), 键: (.*?), 值: (.*?)$', response, re.MULTILINE)
for category, key, value in pref_lines:
preferences.append({
"category": category.strip(),
"key": key.strip(),
"value": value.strip()
})
return preferences
# 创建偏好管理器实例
preference_manager = PreferenceManager()
def register_callbacks(agent):
@agent.after_user_message
def extract_preferences(message, **kwargs):
"""从用户消息中提取偏好"""
# 尝试提取偏好
preferences = preference_manager.extract_preferences(message, agent)
if preferences:
for pref in preferences:
preference_manager.update_preference(
pref["category"],
pref["key"],
pref["value"]
)
logger.info(f"已提取并更新 {len(preferences)} 个用户偏好")
# 检测显式的偏好设置命令
if re.search(r'^设置偏好\s+.*', message, re.IGNORECASE):
match = re.match(r'^设置偏好\s+([^:]+):\s*(.+)$', message)
if match:
key, value = match.groups()
# 简单确定分类
if key.lower() in ['沟通风格', '回复长度', '回复格式']:
category = "通信偏好"
elif key.lower() in ['工作时间', '专注时段', '休息模式']:
category = "工作习惯"
elif key.lower() in ['信息详细度', '技术复杂度', '示例偏好']:
category = "内容偏好"
else:
category = "个人兴趣"
preference_manager.update_preference(category, key, value)
return f"已设置偏好: {key} = {value}"
return None # 继续正常处理
EOF
# 在OpenClaw启动时注册偏好工作流
echo 'openclaw workflow register preference_workflow' >> ~/.openclaw/startup.sh📔 MEMORY.md 的结构与管理
长期记忆文件(MEMORY.md)是AI助手记忆系统的核心。它应该是一个精心组织的索引,而不是所有记忆的堆砌。以下是一些最佳实践:
- 结构化索引:使用清晰的章节来组织不同类型的信息
- 引用而非复制:引用具体文件而不是将所有内容复制到一处
- 定期更新:从日常记忆文件中提炼重要信息,更新长期记忆
- 安全考虑:仅在与用户的直接对话中加载,不在共享上下文中暴露
让我们更新MEMORY.md的结构,增加一些实用的索引:
cat > ~/.openclaw/MEMORY.md << 'EOF'
# 长期记忆索引
这是OpenClaw助手的长期记忆文件,存储所有重要信息的索引和关键内容。它只在主会话中加载,不在共享上下文中加载。
## 用户基本信息
*关于用户的基本信息,帮助提供个性化服务。*
- **通信偏好**: 参见 `knowledge/user_preferences.md` - 通信偏好部分
- **工作习惯**: 参见 `knowledge/user_preferences.md` - 工作习惯部分
- **个人兴趣**: 参见 `knowledge/user_preferences.md` - 个人兴趣部分
## 进行中的项目
*当前正在进行的项目及其状态。*
- **OpenClaw学习**: 参见 `projects/openclaw_learning/progress.md`
## 知识库索引
*重要知识的索引,按类别组织。*
- **技术笔记**: `knowledge/tech/`
- **工作流程**: `knowledge/workflows/`
- **常用命令**: `knowledge/commands.md`
## 重要决策记录
*记录重要决策及其背景原因。*
- 参见每个项目目录下的 `decisions.md` 文件
## 最近记忆
*最近的重要记忆,按时间倒序排列。*
- **2023-06-01**: 用户开始学习OpenClaw,对AI助手的个性化定制特别感兴趣
- **2023-06-02**: 完成了OpenClaw的基础设置和个性化定制
- **2023-06-03**: 设置了飞书集成功能,增强了与团队的协作能力
- **2023-06-04**: 学习并配置了多种工具和插件,扩展了功能范围
- **2023-06-05**: 掌握了技能扩展的方法,增强了专业能力
## 记忆系统使用指南
*如何有效使用记忆系统的说明。*
### 记忆命令
- **记住 [内容]**: 将重要信息添加到当天的记忆文件
- **设置偏好 [键]: [值]**: 设置用户偏好
- **创建项目 [项目名称]**: 创建新项目并建立相关记忆文件
### 文件结构
- **MEMORY.md**: 长期记忆索引文件
- **memory/YYYY-MM-DD.md**: 每日记忆文件
- **projects/**: 项目相关记忆
- **knowledge/**: 知识库和用户偏好
### 最佳实践
- 使用"记住"命令保存重要信息
- 定期整理每日记忆,提炼到长期记忆
- 项目信息保存在专门的项目文件中
- 在MEMORY.md中保持清晰的索引结构
EOF🔮 高级记忆实践:上下文检索
让我们创建一个上下文检索系统,帮助AI在对话中智能地检索相关记忆:
cat > ~/.openclaw/workflows/context_retrieval_workflow.py << 'EOF'
import os
import re
from datetime import datetime, timedelta
from openclaw.agents import Agent
from openclaw.utils.logger import logger
class ContextRetriever:
def __init__(self):
self.memory_dir = os.path.expanduser("~/.openclaw/memory")
self.long_term_memory = os.path.expanduser("~/.openclaw/MEMORY.md")
self.projects_dir = os.path.expanduser("~/.openclaw/projects")
self.knowledge_dir = os.path.expanduser("~/.openclaw/knowledge")
def simple_keyword_search(self, query, file_content):
"""简单的关键词搜索"""
# 将查询分解为关键词
keywords = query.lower().split()
content = file_content.lower()
# 计算匹配度
matches = sum(1 for keyword in keywords if keyword in content)
return matches / len(keywords) if keywords else 0
def retrieve_from_file(self, query, filepath, max_chars=1000):
"""从文件中检索相关内容"""
if not os.path.exists(filepath):
return None
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# 简单的相关性检查
relevance = self.simple_keyword_search(query, content)
if relevance > 0.3: # 只返回足够相关的内容
# 找到最相关的部分
best_section = content
# 如果内容太长,尝试找到最相关的部分
if len(content) > max_chars:
sections = re.split(r'\n#+\s+', content)
best_relevance = 0
for section in sections:
section_relevance = self.simple_keyword_search(query, section)
if section_relevance > best_relevance:
best_relevance = section_relevance
best_section = section
# 如果还是太长,截断它
if len(best_section) > max_chars:
best_section = best_section[:max_chars] + "..."
return {
"content": best_section,
"source": os.path.basename(filepath),
"relevance": relevance
}
except Exception as e:
logger.error(f"读取文件 {filepath} 时出错: {e}")
return None
def search_recent_memories(self, query, days=7):
"""搜索最近的记忆文件"""
results = []
# 获取最近几天的日期
dates = []
for i in range(days):
date = (datetime.now() - timedelta(days=i)).strftime("%Y-%m-%d")
dates.append(date)
# 搜索每天的记忆文件
for date in dates:
memory_file = os.path.join(self.memory_dir, f"{date}.md")
result = self.retrieve_from_file(query, memory_file)
if result:
results.append(result)
return results
def search_long_term_memory(self, query):
"""搜索长期记忆"""
return self.retrieve_from_file(query, self.long_term_memory)
def search_projects(self, query):
"""搜索项目文件"""
results = []
if os.path.exists(self.projects_dir):
for project in os.listdir(self.projects_dir):
project_dir = os.path.join(self.projects_dir, project)
if os.path.isdir(project_dir):
progress_file = os.path.join(project_dir, "progress.md")
result = self.retrieve_from_file(query, progress_file)
if result:
results.append(result)
return results
def search_knowledge(self, query):
"""搜索知识库"""
results = []
if os.path.exists(self.knowledge_dir):
for file in os.listdir(self.knowledge_dir):
if file.endswith(".md"):
knowledge_file = os.path.join(self.knowledge_dir, file)
result = self.retrieve_from_file(query, knowledge_file)
if result:
results.append(result)
return results
def retrieve_context(self, query):
"""检索与查询相关的上下文"""
all_results = []
# 搜索长期记忆
ltm_result = self.search_long_term_memory(query)
if ltm_result:
all_results.append(ltm_result)
# 搜索最近记忆
recent_results = self.search_recent_memories(query)
all_results.extend(recent_results)
# 搜索项目
project_results = self.search_projects(query)
all_results.extend(project_results)
# 搜索知识库
knowledge_results = self.search_knowledge(query)
all_results.extend(knowledge_results)
# 按相关性排序
sorted_results = sorted(all_results, key=lambda x: x["relevance"], reverse=True)
# 只返回最相关的几个结果
top_results = sorted_results[:3]
if not top_results:
return None
# 格式化上下文
context = "以下是与当前查询相关的记忆内容:\n\n"
for result in top_results:
context += f"--- 来自 {result['source']} ---\n{result['content']}\n\n"
return context
# 创建上下文检索器实例
context_retriever = ContextRetriever()
def register_callbacks(agent):
@agent.before_generate
def inject_relevant_context(prompt, **kwargs):
"""在生成回复前注入相关上下文"""
# 检索相关上下文
context = context_retriever.retrieve_context(prompt)
if context:
# 在提示前添加上下文
augmented_prompt = f"{context}\n\n当前查询: {prompt}"
return augmented_prompt
return prompt
EOF
# 在OpenClaw启动时注册上下文检索工作流
echo 'openclaw workflow register context_retrieval_workflow' >> ~/.openclaw/startup.sh📝 创建记忆维护命令
为了简化记忆的维护,我们创建一个简单的命令行工具:
cat > ~/.openclaw/scripts/memory-cli.sh << 'EOF'
#!/bin/bash
# 设置基础目录
BASE_DIR=~/.openclaw
MEMORY_DIR=$BASE_DIR/memory
PROJECTS_DIR=$BASE_DIR/projects
KNOWLEDGE_DIR=$BASE_DIR/knowledge
# 帮助信息
show_help() {
echo "OpenClaw记忆管理工具"
echo ""
echo "用法: memory-cli [命令] [参数]"
echo ""
echo "可用命令:"
echo " today 创建或打开今天的记忆文件"
echo " add [内容] 添加内容到今天的记忆"
echo " list [天数] 列出最近的记忆文件 (默认: 7天)"
echo " search [关键词] 搜索记忆"
echo " project new [名称] 创建新项目"
echo " project list 列出所有项目"
echo " summary [日期] 生成指定日期的记忆摘要 (默认: 昨天)"
echo " help 显示此帮助信息"
echo ""
}
# 创建今天的记忆文件
create_today_memory() {
TODAY=$(date +%Y-%m-%d)
TODAY_FILE="$MEMORY_DIR/$TODAY.md"
mkdir -p "$MEMORY_DIR"
if [ ! -f "$TODAY_FILE" ]; then
echo "# 记忆记录: $TODAY" > "$TODAY_FILE"
echo "" >> "$TODAY_FILE"
echo "## 对话摘要" >> "$TODAY_FILE"
echo "" >> "$TODAY_FILE"
echo "## 重要信息" >> "$TODAY_FILE"
echo "" >> "$TODAY_FILE"
echo "## 行动项" >> "$TODAY_FILE"
echo "" >> "$TODAY_FILE"
echo "创建了今天的记忆文件: $TODAY_FILE"
else
echo "今天的记忆文件已存在: $TODAY_FILE"
fi
# 如果EDITOR环境变量已设置,则打开文件
if [ ! -z "$EDITOR" ]; then
$EDITOR "$TODAY_FILE"
else
# 尝试几个常见的编辑器
if command -v nano > /dev/null; then
nano "$TODAY_FILE"
elif command -v vim > /dev/null; then
vim "$TODAY_FILE"
else
echo "提示: 设置EDITOR环境变量以自动打开文件"
fi
fi
}
# 添加内容到今天的记忆
add_to_today() {
if [ $# -eq 0 ]; then
echo "错误: 请提供要添加的内容"
return 1
fi
TODAY=$(date +%Y-%m-%d)
TODAY_FILE="$MEMORY_DIR/$TODAY.md"
mkdir -p "$MEMORY_DIR"
if [ ! -f "$TODAY_FILE" ]; then
create_today_memory
fi
# 添加到重要信息部分
TIMESTAMP=$(date +%H:%M)
echo "- [$TIMESTAMP] $*" >> "$TODAY_FILE"
echo "已添加到今天的记忆文件"
}
# 列出最近的记忆文件
list_memories() {
DAYS=${1:-7}
echo "最近 $DAYS 天的记忆文件:"
echo "------------------------"
for i in $(seq 0 $(($DAYS - 1))); do
DATE=$(date -d "$i days ago" +%Y-%m-%d)
FILE="$MEMORY_DIR/$DATE.md"
if [ -f "$FILE" ]; then
# 计算文件行数作为内容指示
LINES=$(wc -l < "$FILE")
# 提取第一个标题作为摘要
SUMMARY=$(grep -m 1 "^# " "$FILE" | sed 's/^# //')
echo "$DATE ($LINES 行) - $SUMMARY"
fi
done
}
# 搜索记忆
search_memories() {
if [ $# -eq 0 ]; then
echo "错误: 请提供搜索关键词"
return 1
fi
SEARCH_TERM="$*"
echo "搜索: '$SEARCH_TERM'"
echo "------------------------"
# 搜索记忆目录
if [ -d "$MEMORY_DIR" ]; then
echo "在记忆文件中:"
grep -l -i "$SEARCH_TERM" "$MEMORY_DIR"/*.md 2>/dev/null | while read FILE; do
FILENAME=$(basename "$FILE")
echo "- $FILENAME:"
grep -i --color=always -A 1 -B 1 "$SEARCH_TERM" "$FILE" | head -n 5
echo " ..."
echo ""
done
fi
# 搜索项目目录
if [ -d "$PROJECTS_DIR" ]; then
echo "在项目文件中:"
find "$PROJECTS_DIR" -name "*.md" -exec grep -l -i "$SEARCH_TERM" {} \; | while read FILE; do
REL_PATH=${FILE#$BASE_DIR/}
echo "- $REL_PATH:"
grep -i --color=always -A 1 -B 1 "$SEARCH_TERM" "$FILE" | head -n 5
echo " ..."
echo ""
done
fi
# 搜索知识库
if [ -d "$KNOWLEDGE_DIR" ]; then
echo "在知识库中:"
find "$KNOWLEDGE_DIR" -name "*.md" -exec grep -l -i "$SEARCH_TERM" {} \; | while read FILE; do
REL_PATH=${FILE#$BASE_DIR/}
echo "- $REL_PATH:"
grep -i --color=always -A 1 -B 1 "$SEARCH_TERM" "$FILE" | head -n 5
echo " ..."
echo ""
done
fi
# 搜索长期记忆
LONG_TERM="$BASE_DIR/MEMORY.md"
if [ -f "$LONG_TERM" ] && grep -q -i "$SEARCH_TERM" "$LONG_TERM"; then
echo "在长期记忆中:"
grep -i --color=always -A 1 -B 1 "$SEARCH_TERM" "$LONG_TERM" | head -n 5
echo " ..."
echo ""
fi
}
# 创建新项目
create_project() {
if [ $# -eq 0 ]; then
echo "错误: 请提供项目名称"
return 1
fi
PROJECT_NAME="$*"
DIR_NAME=$(echo "$PROJECT_NAME" | tr ' ' '_' | tr '[:upper:]' '[:lower:]')
PROJECT_DIR="$PROJECTS_DIR/$DIR_NAME"
mkdir -p "$PROJECT_DIR"
# 创建项目文件
PROGRESS_FILE="$PROJECT_DIR/progress.md"
TODAY=$(date +%Y-%m-%d)
cat > "$PROGRESS_FILE" << END
# $PROJECT_NAME
## 项目概览
- **开始日期**: $TODAY
- **预计完成**: [待定]
- **项目类型**: [待定]
- **优先级**: [待定]
## 最新状态
- **当前阶段**: 初始化
- **完成度**: 0%
- **最近更新**: $TODAY
## 目标与范围
[项目目标和范围描述]
## 任务清单
- [ ] 初始化项目
- [ ] 定义具体目标
- [ ] 规划实施步骤
## 参考资料
- [待添加]
## 笔记与思考
[项目相关的笔记和思考]
## 决策记录
| 日期 | 决策 | 原因 | 替代方案 | 影响 |
|------|------|------|----------|------|
| $TODAY | 创建项目 | 需要组织相关信息 | 无结构化记录 | 更好地跟踪进度 |
## 进展日志
### $TODAY
- 创建了项目框架
END
echo "已创建项目: $PROJECT_NAME"
echo "项目文件: $PROGRESS_FILE"
# 更新长期记忆
MEMORY_FILE="$BASE_DIR/MEMORY.md"
if grep -q "## 进行中的项目" "$MEMORY_FILE"; then
sed -i "/## 进行中的项目/a - **$PROJECT_NAME**: 参见 \`projects/$DIR_NAME/progress.md\`" "$MEMORY_FILE"
fi
}
# 列出所有项目
list_projects() {
echo "项目列表:"
echo "------------------------"
if [ -d "$PROJECTS_DIR" ]; then
for PROJECT in $(ls -1 "$PROJECTS_DIR"); do
if [ -d "$PROJECTS_DIR/$PROJECT" ]; then
# 尝试提取项目名称和状态
PROGRESS_FILE="$PROJECTS_DIR/$PROJECT/progress.md"
if [ -f "$PROGRESS_FILE" ]; then
# 提取项目名称
NAME=$(grep -m 1 "^# " "$PROGRESS_FILE" | sed 's/^# //')
# 提取当前阶段
STAGE=$(grep -A 1 "**当前阶段**:" "$PROGRESS_FILE" | tail -n 1 | sed 's/- //g')
# 提取完成度
PROGRESS=$(grep -A 1 "**完成度**:" "$PROGRESS_FILE" | tail -n 1 | sed 's/- //g')
# 提取最后更新时间
UPDATE=$(grep -A 1 "**最近更新**:" "$PROGRESS_FILE" | tail -n 1 | sed 's/- //g')
echo "$NAME [$STAGE, $PROGRESS, 更新: $UPDATE]"
else
echo "$PROJECT [无进度文件]"
fi
fi
done
else
echo "项目目录不存在"
fi
}
# 生成记忆摘要
generate_summary() {
DATE=${1:-$(date -d "yesterday" +%Y-%m-%d)}
MEMORY_FILE="$MEMORY_DIR/$DATE.md"
if [ ! -f "$MEMORY_FILE" ]; then
echo "错误: 无法找到 $DATE 的记忆文件"
return 1
fi
echo "生成 $DATE 的记忆摘要..."
# 这里我们只做简单的提取,实际上可能需要更复杂的摘要生成逻辑
echo "摘要 ($DATE):"
echo "------------------------"
# 提取重要信息
echo "重要信息:"
grep -A 100 "^## 重要信息" "$MEMORY_FILE" | grep -m 100 -B 100 "^##" | grep -v "^## " | grep "^\- "
# 提取行动项
echo ""
echo "行动项:"
grep -A 100 "^## 行动项" "$MEMORY_FILE" | grep -m 100 -B 100 "^##" | grep -v "^## " | grep "^\- "
# 提示手动添加到长期记忆
echo ""
echo "请考虑将这些重要信息添加到长期记忆文件 (MEMORY.md) 中"
}
# 主函数
main() {
case "$1" in
today)
create_today_memory
;;
add)
shift
add_to_today "$@"
;;
list)
list_memories "$2"
;;
search)
shift
search_memories "$@"
;;
project)
case "$2" in
new)
shift 2
create_project "$@"
;;
list)
list_projects
;;
*)
echo "未知的项目命令: $2"
show_help
;;
esac
;;
summary)
generate_summary "$2"
;;
help|--help|-h)
show_help
;;
*)
echo "未知命令: $1"
show_help
;;
esac
}
# 如果没有参数,显示帮助
if [ $# -eq 0 ]; then
show_help
exit 1
fi
main "$@"
EOF
chmod +x ~/.openclaw/scripts/memory-cli.sh
# 创建符号链接到用户的bin目录
mkdir -p ~/bin
ln -sf ~/.openclaw/scripts/memory-cli.sh ~/bin/memory-cli
# 添加到PATH(如果还没有的话)
if ! grep -q "PATH=\$PATH:~/bin" ~/.bashrc; then
echo 'export PATH=$PATH:~/bin' >> ~/.bashrc
echo '记忆管理CLI工具已安装,请重新加载终端或运行 "source ~/.bashrc" 使其生效'
fi🧩 创建记忆小部件
最后,让我们添加一个交互式记忆小部件,方便用户查看和管理记忆:
mkdir -p ~/.openclaw/widgets
cat > ~/.openclaw/widgets/memory_widget.html << 'EOF'
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OpenClaw记忆管理</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
color: #333;
background-color: #f9f9f9;
}
h1, h2, h3 {
color: #2c3e50;
}
.container {
max-width: 800px;
margin: 0 auto;
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.tabs {
display: flex;
margin-bottom: 20px;
border-bottom: 1px solid #ddd;
}
.tab {
padding: 10px 20px;
cursor: pointer;
margin-right: 5px;
border-radius: 5px 5px 0 0;
background-color: #f1f1f1;
}
.tab.active {
background-color: #3498db;
color: white;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
input, textarea, button, select {
padding: 8px;
margin-bottom: 10px;
border-radius: 4px;
border: 1px solid #ddd;
width: 100%;
}
button {
background-color: #3498db;
color: white;
border: none;
cursor: pointer;
width: auto;
}
button:hover {
background-color: #2980b9;
}
.card {
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
margin-bottom: 10px;
background-color: white;
}
.search-result {
margin-top: 20px;
border-top: 1px solid #ddd;
padding-top: 10px;
}
.memory-item {
border-bottom: 1px solid #eee;
padding: 5px 0;
}
.highlight {
background-color: #ffffcc;
padding: 2px;
}
</style>
</head>
<body>
<div class="container">
<h1>OpenClaw记忆管理</h1>
<div class="tabs">
<div class="tab active" data-tab="search">搜索记忆</div>
<div class="tab" data-tab="add">添加记忆</div>
<div class="tab" data-tab="projects">项目管理</div>
<div class="tab" data-tab="preferences">用户偏好</div>
</div>
<div class="tab-content active" id="search">
<h2>搜索记忆</h2>
<input type="text" id="search-input" placeholder="输入关键词搜索...">
<button id="search-btn">搜索</button>
<div class="search-options">
<label>
<input type="checkbox" id="search-memory" checked>
日常记忆
</label>
<label>
<input type="checkbox" id="search-long-term" checked>
长期记忆
</label>
<label>
<input type="checkbox" id="search-projects" checked>
项目文件
</label>
</div>
<div id="search-results" class="search-result"></div>
</div>
<div class="tab-content" id="add">
<h2>添加记忆</h2>
<select id="memory-type">
<option value="info">重要信息</option>
<option value="action">行动项</option>
<option value="decision">决策</option>
</select>
<textarea id="memory-content" rows="4" placeholder="输入要记住的内容..."></textarea>
<button id="add-memory-btn">添加到今天的记忆</button>
<div id="add-result"></div>
</div>
<div class="tab-content" id="projects">
<h2>项目管理</h2>
<div id="projects-list">
<h3>当前项目</h3>
<div id="current-projects">
加载中...
</div>
<h3>创建新项目</h3>
<input type="text" id="project-name" placeholder="项目名称">
<button id="create-project-btn">创建项目</button>
<div id="project-result"></div>
</div>
</div>
<div class="tab-content" id="preferences">
<h2>用户偏好</h2>
<div id="preferences-section">
<h3>添加新偏好</h3>
<select id="preference-category">
<option value="通信偏好">通信偏好</option>
<option value="工作习惯">工作习惯</option>
<option value="内容偏好">内容偏好</option>
<option value="个人兴趣">个人兴趣</option>
</select>
<input type="text" id="preference-key" placeholder="偏好名称 (如: 回复长度)">
<input type="text" id="preference-value" placeholder="偏好值 (如: 简洁)">
<button id="add-preference-btn">添加偏好</button>
<h3>当前偏好</h3>
<div id="current-preferences">
加载中...
</div>
<div id="preference-result"></div>
</div>
</div>
</div>
<script>
// 切换标签
document.querySelectorAll('.tab').forEach(tab => {
tab.addEventListener('click', () => {
// 移除所有活动标签
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
// 激活当前标签
tab.classList.add('active');
const tabId = tab.getAttribute('data-tab');
document.getElementById(tabId).classList.add('active');
});
});
// 模拟数据 (在实际实现中,这些数据应该从OpenClaw记忆文件中读取)
const mockData = {
memories: [
{ date: '2023-06-05', type: 'info', content: '用户喜欢简洁的回复风格' },
{ date: '2023-06-04', type: 'action', content: '提醒用户下周参加项目会议' },
{ date: '2023-06-03', type: 'info', content: '用户对AI助手的定制功能特别感兴趣' }
],
projects: [
{ name: 'OpenClaw学习', progress: '75%', stage: '记忆管理' },
{ name: '网站开发', progress: '30%', stage: '设计阶段' }
],
preferences: {
'通信偏好': [
{ key: '回复风格', value: '简洁' },
{ key: '回复格式', value: '结构化' }
],
'工作习惯': [
{ key: '工作时间', value: '上午9点至下午6点' }
]
}
};
// 搜索功能
document.getElementById('search-btn').addEventListener('click', () => {
const query = document.getElementById('search-input').value.trim();
if (query === '') return;
const resultsDiv = document.getElementById('search-results');
resultsDiv.innerHTML = '<h3>搜索结果</h3>';
// 模拟搜索结果
const results = mockData.memories.filter(m =>
m.content.toLowerCase().includes(query.toLowerCase())
);
if (results.length === 0) {
resultsDiv.innerHTML += '<p>没有找到匹配的结果</p>';
return;
}
results.forEach(result => {
const highlighted = result.content.replace(
new RegExp(query, 'gi'),
match => `<span class="highlight">${match}</span>`
);
const card = document.createElement('div');
card.className = 'card';
card.innerHTML = `
<p><strong>${result.date}</strong> (${result.type})</p>
<p>${highlighted}</p>
`;
resultsDiv.appendChild(card);
});
});
// 添加记忆
document.getElementById('add-memory-btn').addEventListener('click', () => {
const type = document.getElementById('memory-type').value;
const content = document.getElementById('memory-content').value.trim();
if (content === '') {
document.getElementById('add-result').innerHTML = '<p style="color:red;">请输入内容</p>';
return;
}
// 模拟添加记忆
const today = new Date().toISOString().split('T')[0];
mockData.memories.unshift({
date: today,
type: type,
content: content
});
document.getElementById('memory-content').value = '';
document.getElementById('add-result').innerHTML = '<p style="color:green;">记忆已添加!</p>';
// 3秒后清除结果消息
setTimeout(() => {
document.getElementById('add-result').innerHTML = '';
}, 3000);
});
// 加载项目列表
function loadProjects() {
const projectsDiv = document.getElementById('current-projects');
projectsDiv.innerHTML = '';
mockData.projects.forEach(project => {
const card = document.createElement('div');
card.className = 'card';
card.innerHTML = `
<h4>${project.name}</h4>
<p>进度: ${project.progress}</p>
<p>当前阶段: ${project.stage}</p>
<button class="view-project-btn" data-project="${project.name}">查看详情</button>
`;
projectsDiv.appendChild(card);
});
// 添加查看详情事件
document.querySelectorAll('.view-project-btn').forEach(btn => {
btn.addEventListener('click', () => {
const projectName = btn.getAttribute('data-project');
alert(`显示项目 ${projectName} 的详细信息`);
});
});
}
// 创建项目
document.getElementById('create-project-btn').addEventListener('click', () => {
const projectName = document.getElementById('project-name').value.trim();
if (projectName === '') {
document.getElementById('project-result').innerHTML = '<p style="color:red;">请输入项目名称</p>';
return;
}
// 模拟创建项目
mockData.projects.push({
name: projectName,
progress: '0%',
stage: '初始化'
});
document.getElementById('project-name').value = '';
document.getElementById('project-result').innerHTML = '<p style="color:green;">项目已创建!</p>';
// 更新项目列表
loadProjects();
// 3秒后清除结果消息
setTimeout(() => {
document.getElementById('project-result').innerHTML = '';
}, 3000);
});
// 加载偏好
function loadPreferences() {
const preferencesDiv = document.getElementById('current-preferences');
preferencesDiv.innerHTML = '';
Object.entries(mockData.preferences).forEach(([category, prefs]) => {
const categoryDiv = document.createElement('div');
categoryDiv.className = 'preference-category';
categoryDiv.innerHTML = `<h4>${category}</h4>`;
prefs.forEach(pref => {
const prefDiv = document.createElement('div');
prefDiv.className = 'memory-item';
prefDiv.innerHTML = `<strong>${pref.key}:</strong> ${pref.value}`;
categoryDiv.appendChild(prefDiv);
});
preferencesDiv.appendChild(categoryDiv);
});
}
// 添加偏好
document.getElementById('add-preference-btn').addEventListener('click', () => {
const category = document.getElementById('preference-category').value;
const key = document.getElementById('preference-key').value.trim();
const value = document.getElementById('preference-value').value.trim();
if (key === '' || value === '') {
document.getElementById('preference-result').innerHTML = '<p style="color:red;">请输入偏好名称和值</p>';
return;
}
// 模拟添加偏好
if (!mockData.preferences[category]) {
mockData.preferences[category] = [];
}
// 检查是否已存在
const existingIndex = mockData.preferences[category].findIndex(p => p.key === key);
if (existingIndex >= 0) {
mockData.preferences[category][existingIndex].value = value;
} else {
mockData.preferences[category].push({ key, value });
}
document.getElementById('preference-key').value = '';
document.getElementById('preference-value').value = '';
document.getElementById('preference-result').innerHTML = '<p style="color:green;">偏好已添加!</p>';
// 更新偏好列表
loadPreferences();
// 3秒后清除结果消息
setTimeout(() => {
document.getElementById('preference-result').innerHTML = '';
}, 3000);
});
// 初始加载
loadProjects();
loadPreferences();
</script>
</body>
</html>
EOF🎯 今日小结
在Day 6中,我们深入探讨了OpenClaw基于文件的记忆管理系统,包括:
- 记忆文件结构:建立了清晰的记忆文件组织方式
- 长期记忆索引 (
MEMORY.md) - 日常记忆记录 (
memory/YYYY-MM-DD.md) - 项目记忆管理 (
projects/) - 知识库索引 (
knowledge/)
- 记忆管理工具:创建了一系列便于记忆管理的工具和脚本
- 日常记忆创建和管理
- 记忆搜索功能
- 项目创建和管理
- 记忆摘要生成
- 工作流实现:开发了记忆管理相关的工作流
- 从对话中提取重要信息
- 用户偏好的识别和存储
- 上下文相关记忆检索
- 记忆命令处理
- 记忆最佳实践:学习了有效管理AI记忆的最佳方法
- 使用索引而不是堆积所有内容
- 定期整理和提炼记忆
- 分离临时记忆和长期记忆
- 保护隐私和敏感信息
通过这些功能,你的AI助手现在能够:
- 记住重要的对话内容和用户偏好
- 在对话中智能地引用相关的历史记忆
- 有效地管理项目信息和进度
- 维护持续的上下文理解,提供更个性化的服务
与复杂的向量数据库不同,我们采用了基于文件的记忆系统,使其更易于理解、使用和维护,同时保留了强大的记忆能力。
🔮 明日预告
明天,我们将迎来OpenClaw 7天学习教程的最后一天:Day 7: 多模态与高级应用。
我们将探讨如何:
- 实现图像识别和处理能力
- 添加语音交互功能
- 创建多模态工作流
- 构建复杂的应用场景
- 学习高级部署和优化技巧
准备好让你的AI助手进入多模态时代,处理图像、语音等更丰富的内容形式了吗?明天见!🚀