Initial Phase A intelligence core
This commit is contained in:
commit
94eae8ceba
11 changed files with 4261 additions and 0 deletions
63
syncpatch/replay_buffer.py
Normal file
63
syncpatch/replay_buffer.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
DEFAULT_REPLAY_ROOT = Path('/home/openclaw/.openclaw/workspace/data/replay_buffer')
|
||||
DEFAULT_POLICY_STATS = Path('/home/openclaw/.openclaw/workspace/data/policy_stats.json')
|
||||
|
||||
|
||||
|
||||
def _safe_slug(value: str) -> str:
|
||||
out = ''.join(ch if ch.isalnum() or ch in {'_', '-'} else '_' for ch in (value or 'unknown').strip().lower())
|
||||
return out[:80] or 'unknown'
|
||||
|
||||
|
||||
|
||||
def replay_path(record: dict[str, Any], replay_root: Path = DEFAULT_REPLAY_ROOT) -> Path:
|
||||
ts = str(record.get('ts') or datetime.now(timezone.utc).isoformat())
|
||||
day = ts[:10]
|
||||
task = _safe_slug(str(record.get('normalized_task') or 'unknown'))
|
||||
return replay_root / day / f'{task}.jsonl'
|
||||
|
||||
|
||||
|
||||
def append_replay_record(record: dict[str, Any], replay_root: Path = DEFAULT_REPLAY_ROOT) -> Path:
|
||||
path = replay_path(record, replay_root)
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with path.open('a', encoding='utf-8') as f:
|
||||
f.write(json.dumps(record, ensure_ascii=False) + '\n')
|
||||
return path
|
||||
|
||||
|
||||
|
||||
def update_policy_stats(record: dict[str, Any], stats_path: Path = DEFAULT_POLICY_STATS) -> dict[str, Any]:
|
||||
stats_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
try:
|
||||
data = json.loads(stats_path.read_text(encoding='utf-8'))
|
||||
except Exception:
|
||||
data = {'plans': {}, 'families': {}, 'updated_at': ''}
|
||||
|
||||
plan_key = str(record.get('chosen_plan') or 'single_tool')
|
||||
family_key = str(record.get('family') or 'unknown')
|
||||
reward = float(record.get('reward') or 0.0)
|
||||
status = str(record.get('outcome_status') or '')
|
||||
|
||||
for bucket_name, key in [('plans', plan_key), ('families', family_key)]:
|
||||
bucket = data.setdefault(bucket_name, {})
|
||||
row = bucket.setdefault(key, {'count': 0, 'success': 0, 'failure': 0, 'clarification': 0, 'reward_sum': 0.0})
|
||||
row['count'] += 1
|
||||
row['reward_sum'] += reward
|
||||
if status == 'success':
|
||||
row['success'] += 1
|
||||
elif status == 'needs_clarification':
|
||||
row['clarification'] += 1
|
||||
else:
|
||||
row['failure'] += 1
|
||||
|
||||
data['updated_at'] = datetime.now(timezone.utc).isoformat()
|
||||
stats_path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding='utf-8')
|
||||
return data
|
||||
Loading…
Add table
Add a link
Reference in a new issue