Spaces:
Sleeping
Sleeping
File size: 4,706 Bytes
6719409 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | #!/usr/bin/env python3
"""
OpenClaw 记忆同步脚本
将本地记忆文件同步至 Hugging Face Dataset,并从 Dataset 恢复。
"""
import os
import sys
import time
import logging
from pathlib import Path
from huggingface_hub import HfApi, hf_hub_download, upload_file, list_repo_files
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class MemorySync:
def __init__(self):
self.hf_token = os.getenv('HF_TOKEN')
# 请将下面的 'your-username/openclaw-memory' 替换成你实际创建的 Dataset 名字
self.hf_dataset = os.getenv('HF_MEMORY_DATASET', 'a8926764/openclaw-memory')
# 确保这个路径和启动脚本中设置的 OPENCLAW_MEMORY_DIR 一致
self.local_memory_dir = Path(os.getenv('OPENCLAW_MEMORY_DIR', '/root/.openclaw/memory'))
self.api = HfApi(token=self.hf_token)
def ensure_memory_dir(self):
"""确保本地记忆目录存在"""
self.local_memory_dir.mkdir(parents=True, exist_ok=True)
logger.info(f"Memory directory ensured: {self.local_memory_dir}")
def download_memory(self):
"""从 Dataset 拉取所有记忆文件(.md 文件)"""
self.ensure_memory_dir()
try:
logger.info(f'开始从 Dataset 下载记忆文件: {self.hf_dataset}')
files = list_repo_files(repo_id=self.hf_dataset, repo_type="dataset")
downloaded_count = 0
for file_name in files:
if file_name.endswith('.md'):
try:
local_path = hf_hub_download(
repo_id=self.hf_dataset,
filename=file_name,
repo_type="dataset",
token=self.hf_token,
local_dir=self.local_memory_dir
)
logger.info(f'已下载记忆文件: {file_name}')
downloaded_count += 1
except Exception as e:
logger.error(f'下载文件 {file_name} 失败: {e}')
continue
if downloaded_count == 0:
logger.info('Dataset 中未找到记忆文件,将使用新记忆。')
else:
logger.info(f'记忆文件下载完成,共下载 {downloaded_count} 个文件。')
return True
except Exception as e:
logger.error(f'从 Dataset 拉取记忆失败: {e}')
# 首次运行时 Dataset 可能为空,这不一定是错误,返回 True 允许流程继续
return True
def upload_memory(self):
"""推送本地所有 .md 记忆文件到 Dataset"""
self.ensure_memory_dir()
try:
logger.info(f'开始推送记忆文件到 Dataset: {self.hf_dataset}')
memory_files = list(self.local_memory_dir.glob('*.md'))
if not memory_files:
logger.warning('本地没有找到 .md 格式的记忆文件,跳过上传。')
return False
uploaded_count = 0
for mem_file in memory_files:
try:
upload_file(
path_or_fileobj=str(mem_file),
path_in_repo=mem_file.name,
repo_id=self.hf_dataset,
repo_type="dataset",
token=self.hf_token,
commit_message=f"自动同步记忆: {mem_file.name} - {time.strftime('%Y-%m-%d %H:%M:%S')}"
)
logger.info(f'已上传记忆文件: {mem_file.name}')
uploaded_count += 1
except Exception as e:
logger.error(f'上传文件 {mem_file.name} 失败: {e}')
continue
logger.info(f'记忆文件上传完成,共上传 {uploaded_count} 个文件。')
return uploaded_count > 0
except Exception as e:
logger.error(f'推送记忆到 Dataset 失败: {e}')
return False
def main():
"""主函数,处理命令行参数"""
if len(sys.argv) != 2 or sys.argv[1] not in ['download', 'upload']:
print('用法: python memory_sync.py [download|upload]')
sys.exit(1)
sync = MemorySync()
mode = sys.argv[1]
if mode == 'download':
success = sync.download_memory()
sys.exit(0 if success else 1)
elif mode == 'upload':
success = sync.upload_memory()
sys.exit(0 if success else 1)
if __name__ == '__main__':
main() |