# Level 2: 파라미터 자동 조정 시스템 설계 > 작성일: 2026-02-05 > 상태: 설계 단계 > 기반: Level 1 Auto-Retry 로그 분석 ## 1. 개요 ### 1.1 Level 1 vs Level 2 | 항목 | Level 1 (Auto-Retry) | Level 2 (Parameter Tuning) | |------|---------------------|---------------------------| | **목표** | 일시적 실패 자동 복구 | 최적 파라미터 자동 발견 | | **입력** | 개별 실행 결과 (성공/실패) | 누적 로그 패턴 | | **출력** | 재시도 또는 최종 실패 | 설정 조정 제안 + 자동 적용 | | **시간** | 실시간 (밀리초) | 주기적 (일/주/월) | | **Loop** | ✅ Closed (즉시) | ✅ Closed (지연) | | **사람 개입** | 불필요 | 최소한 (승인만) | ### 1.2 핵심 원칙 **Level 1의 성공 패턴 계승**: 1. ✅ **Closed Loop**: 분석 → 제안 → 적용 → 검증 → 롤백/커밋 2. ✅ **Objective Metrics**: 객관적 데이터 기반 (재시도율, 평균 응답 시간) 3. ✅ **Immediate Verification**: 적용 후 즉시 검증 4. ✅ **Goodhart's Law 회피**: 실제 성능만 인정, 점수 게임 불가 **V4.0의 실패 회피**: - ❌ Open Loop (제안만 하고 끝) - ❌ 주관적 판단 (AI가 "좋다/나쁘다" 평가) - ❌ 검증 지연 (주간/월간 검토) --- ## 2. 현재 상태 분석 (2026-02-05) ### 2.1 Level 1 Auto-Retry 실행 통계 **데이터 기간**: 2026-02-05 04:38 ~ 07:50 (약 3.2시간) | Cron | 실행 횟수 | 성공률 | 평균 시도 | 재시도 발생 | |------|----------|--------|----------|------------| | TQQQ 15분 모니터링 | 8회 | 100% | 1.0 | 0회 | | GitHub 감시 | 3회 | 100% | 1.0 | 0회 | | 일일 주식 브리핑 | 1회 | 100% | 1.0 | 0회 | | **실제 cron 합계** | **12회** | **100%** | **1.0** | **0회** | | 테스트/시뮬레이션 | 6회 | 50% | 2.17 | 3회 | **핵심 발견**: - ✅ 실제 cron은 **재시도 필요 없음** (100% 첫 시도 성공) - ⚠️ 테스트에서는 16.7% 재시도 필요 (HTTP 429, ETIMEDOUT) - ✅ 현재 설정(`maxRetries=3`)은 충분히 안전 ### 2.2 성능 데이터 **TQQQ 15분 모니터링** (Yahoo Finance API): - 평균: 1,658ms - 범위: 1,437ms ~ 2,300ms - 목표: < 15,000ms (timeout) - **여유율**: 87% (13초 여유) **GitHub 감시** (GitHub API): - 평균: 673ms - 범위: 370ms ~ 1,203ms - 목표: < 15,000ms - **여유율**: 96% (14.3초 여유) **일일 주식 브리핑** (복합): - TQQQ: 2,380ms - SOXL: 1,436ms - NVDA: 1,409ms - Hot Scanner: 3,622ms - Rumor Scanner: 5,800ms - **총합**: ~14.6초 - **병렬 실행 시 예상**: ~6초 (가장 느린 작업 기준) **결론**: - ✅ 모든 작업이 timeout 내 완료 - ✅ 여유가 충분함 → timeout 조정 불필요 ### 2.3 현재 설정 적정성 ```javascript { maxRetries: 3, // ✅ 적정 (실패 시 충분한 재시도) backoff: 'exponential', // ✅ 적정 (1s, 2s, 4s) timeout: 15000, // ✅ 적정 (87~96% 여유) maxBuffer: 10MB // ✅ 적정 (출력 크기 문제 없음) } ``` **Level 2 제안**: 현재 설정 유지 (조정 불필요) --- ## 3. Level 2 시스템 아키텍처 ### 3.1 전체 구조 ``` ┌─────────────────────────────────────────────────────────┐ │ Level 2 Parameter Tuner │ └─────────────────────────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────┐ │ 1. Log Analyzer │ │ ──────────────── │ │ - ~/openclaw/logs/auto-retry.jsonl 분석 │ │ - 패턴 감지: 반복 실패, 성능 저하, 트렌드 변화 │ │ - 통계 생성: 평균 시도 횟수, 실패율, 응답 시간 │ └─────────────────────────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────┐ │ 2. Parameter Optimizer │ │ ───────────────────── │ │ - 패턴 기반 최적값 계산 │ │ - 안전 범위 검증 (min/max 제약) │ │ - 개선 예상치 산출 │ └─────────────────────────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────┐ │ 3. Change Applicator (with A/B Testing) │ │ ─────────────────────────────────── │ │ - 설정 파일 수정 (config.json, wrapper scripts) │ │ - A/B 테스트: 50% 트래픽만 새 설정 적용 │ │ - 롤백 포인트 생성 │ └─────────────────────────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────┐ │ 4. Verification Engine │ │ ───────────────────── │ │ - Before/After 메트릭 비교 │ │ - 통계적 유의성 검정 (t-test, χ² test) │ │ - 개선 확인 → 커밋 / 악화 확인 → 롤백 │ └─────────────────────────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────┐ │ 5. Notification & Logging │ │ ──────────────────────── │ │ - Discord 알림 (조정 성공/실패) │ │ - 변경 히스토리 기록 │ │ - 월간 리포트 생성 │ └─────────────────────────────────────────────────────────┘ ``` ### 3.2 Closed Loop 구현 ```javascript // Level 2 메인 루프 async function level2MainLoop() { while (true) { // 1. 로그 분석 const patterns = await analyzeLog(); // 2. 조정 필요 여부 판단 if (!patterns.needsTuning) { await sleep(7 * 24 * 3600 * 1000); // 1주일 대기 continue; } // 3. 최적 파라미터 계산 const optimizedParams = calculateOptimal(patterns); // 4. 안전성 검증 if (!isSafeToApply(optimizedParams)) { notify('⚠️ 조정 제안이 안전 범위 벗어남, 수동 검토 필요'); continue; } // 5. A/B 테스트 적용 const rollbackPoint = createRollbackPoint(); await applyWithABTest(optimizedParams); // 6. 검증 (24시간 모니터링) await sleep(24 * 3600 * 1000); const metrics = await compareMetrics(rollbackPoint); // 7. 커밋 또는 롤백 if (metrics.improved) { commit(optimizedParams); notify('✅ 파라미터 조정 성공', metrics); } else { rollback(rollbackPoint); notify('❌ 조정 효과 없음, 롤백', metrics); } // 8. 다음 주기 대기 await sleep(7 * 24 * 3600 * 1000); } } ``` --- ## 4. 조정 가능한 파라미터 ### 4.1 파라미터 카탈로그 | 파라미터 | 현재값 | 조정 범위 | 안전 범위 | 트리거 조건 | |---------|--------|----------|----------|------------| | `maxRetries` | 3 | 1~10 | 2~5 | 재시도율 > 10% | | `timeout` | 15000ms | 5000~60000 | 10000~30000 | 평균 응답 시간 > timeout * 0.8 | | `backoff` | exponential | linear/exponential/fixed | exponential | 재시도 패턴 분석 | | `backoffBase` | 1000ms | 500~5000 | 1000~3000 | Rate limit 빈도 | ### 4.2 조정 규칙 **규칙 1: maxRetries 증가** ```javascript // 조건 if (retry_rate > 0.10 && final_failure_rate > 0.01) { // 10% 이상 재시도 필요 & 1% 이상 최종 실패 // 조정 maxRetries = current + 1; // 3 → 4 // 예상 효과 // 최종 실패율 1% → 0.1% (90% 감소) } ``` **규칙 2: timeout 증가** ```javascript // 조건 if (avg_response_time > timeout * 0.8) { // 평균 응답 시간이 timeout의 80% 초과 // 조정 timeout = avg_response_time * 1.5; // 여유 50% 확보 // 예상 효과 // timeout 에러 감소 } ``` **규칙 3: backoff 조정** ```javascript // 조건 if (http_429_count > 0) { // Rate limit 발생 // 조정 backoffBase = current * 2; // 1000ms → 2000ms // 예상 효과 // Rate limit 회피 } ``` ### 4.3 안전 제약 **절대 하지 말아야 할 것**: - ❌ `maxRetries` < 2 (너무 적음) - ❌ `maxRetries` > 5 (너무 많음, 느림) - ❌ `timeout` < 5000 (너무 짧음) - ❌ `timeout` > 60000 (너무 김, cron 충돌 위험) **자동 적용 vs 수동 검토**: ```javascript // 자동 적용 가능 - maxRetries: 3 → 4 (안전 범위 내) - timeout: 15s → 20s (안전 범위 내) - backoffBase: 1s → 2s (안전 범위 내) // 수동 검토 필요 - maxRetries: 3 → 10 (안전 범위 벗어남) - timeout: 15s → 5s (감소는 위험) - 근본 원인 수정 (코드 변경) ``` --- ## 5. 구현 계획 ### 5.1 Phase 1: 로그 분석기 (Week 1-2) **파일**: `~/openclaw/lib/log-analyzer.js` ```javascript const fs = require('fs'); const readline = require('readline'); class LogAnalyzer { async analyze(logPath) { const stats = { total: 0, success: 0, failure: 0, retries: 0, byTontextCron: {} }; const fileStream = fs.createReadStream(logPath); const rl = readline.createInterface({ input: fileStream, crlfDelay: Infinity }); for await (const line of rl) { const entry = JSON.parse(line); // Skip tests if (!entry.context?.cron) continue; const cron = entry.context.cron; if (!stats.byCron[cron]) { stats.byCron[cron] = { total: 0, success: 0, retries: 0, avgDuration: 0, durations: [] }; } stats.total++; stats.byCron[cron].total++; if (entry.type === 'success') { stats.success++; stats.byCron[cron].success++; } else { stats.failure++; } const attempts = entry.attempts.length; if (attempts > 1) { stats.retries++; stats.byCron[cron].retries++; } const duration = entry.totalDuration; stats.byCron[cron].durations.push(duration); } // Calculate averages for (const [cron, data] of Object.entries(stats.byCron)) { data.avgDuration = data.durations.reduce((a, b) => a + b, 0) / data.durations.length; data.retryRate = data.retries / data.total; } return stats; } detectPatterns(stats) { const patterns = []; for (const [cron, data] of Object.entries(stats.byCron)) { // Pattern 1: High retry rate if (data.retryRate > 0.10) { patterns.push({ type: 'high_retry_rate', cron, value: data.retryRate, suggestion: 'increase maxRetries' }); } // Pattern 2: Slow response if (data.avgDuration > 12000) { // 80% of 15s patterns.push({ type: 'slow_response', cron, value: data.avgDuration, suggestion: 'increase timeout' }); } } return patterns; } } module.exports = { LogAnalyzer }; ``` ### 5.2 Phase 2: 파라미터 최적화기 (Week 3-4) **파일**: `~/openclaw/lib/parameter-optimizer.js` ```javascript class ParameterOptimizer { calculateOptimal(patterns) { const recommendations = []; for (const pattern of patterns) { if (pattern.type === 'high_retry_rate') { recommendations.push({ param: 'maxRetries', current: 3, proposed: 4, reason: `Retry rate ${(pattern.value * 100).toFixed(1)}% > 10%`, expectedImprovement: 'Final failure rate -90%', safe: true }); } if (pattern.type === 'slow_response') { const newTimeout = Math.ceil(pattern.value * 1.5); recommendations.push({ param: 'timeout', current: 15000, proposed: newTimeout, reason: `Avg response ${pattern.value}ms > 80% of timeout`, expectedImprovement: 'Timeout errors -100%', safe: newTimeout <= 30000 }); } } return recommendations; } isSafeToApply(recommendation) { const safetyRules = { maxRetries: { min: 2, max: 5 }, timeout: { min: 10000, max: 30000 }, backoffBase: { min: 1000, max: 5000 } }; const rule = safetyRules[recommendation.param]; if (!rule) return false; return recommendation.proposed >= rule.min && recommendation.proposed <= rule.max; } } module.exports = { ParameterOptimizer }; ``` ### 5.3 Phase 3: 변경 적용기 (Week 5-6) **파일**: `~/openclaw/lib/change-applicator.js` ```javascript const fs = require('fs'); class ChangeApplicator { async apply(recommendation, cron) { // 1. Create rollback point const rollback = this.createRollbackPoint(cron); // 2. Update wrapper script const wrapperPath = this.getWrapperPath(cron); const content = fs.readFileSync(wrapperPath, 'utf8'); const updated = content.replace( new RegExp(`${recommendation.param}: \\d+`), `${recommendation.param}: ${recommendation.proposed}` ); fs.writeFileSync(wrapperPath, updated); // 3. Log change this.logChange({ timestamp: new Date().toISOString(), cron, param: recommendation.param, from: recommendation.current, to: recommendation.proposed, reason: recommendation.reason, rollbackPoint: rollback }); return rollback; } createRollbackPoint(cron) { const timestamp = Date.now(); const wrapperPath = this.getWrapperPath(cron); const backupPath = `${wrapperPath}.${timestamp}.bak`; fs.copyFileSync(wrapperPath, backupPath); return { timestamp, backupPath, wrapperPath }; } rollback(rollbackPoint) { fs.copyFileSync(rollbackPoint.backupPath, rollbackPoint.wrapperPath); fs.unlinkSync(rollbackPoint.backupPath); } } module.exports = { ChangeApplicator }; ``` ### 5.4 Phase 4: 검증 엔진 (Week 7-8) **파일**: `~/openclaw/lib/verification-engine.js` ```javascript class VerificationEngine { async verify(rollbackPoint, duration = 24 * 3600 * 1000) { // 1. Get baseline metrics (before change) const before = await this.getMetricsAtTimestamp( rollbackPoint.timestamp - duration ); // 2. Wait for new data await new Promise(resolve => setTimeout(resolve, duration)); // 3. Get current metrics (after change) const after = await this.getCurrentMetrics(); // 4. Compare const comparison = { retryRate: { before: before.retryRate, after: after.retryRate, change: ((after.retryRate - before.retryRate) / before.retryRate) * 100 }, avgDuration: { before: before.avgDuration, after: after.avgDuration, change: ((after.avgDuration - before.avgDuration) / before.avgDuration) * 100 }, failureRate: { before: before.failureRate, after: after.failureRate, change: ((after.failureRate - before.failureRate) / before.failureRate) * 100 } }; // 5. Determine if improved const improved = comparison.retryRate.change < 0 || // Less retries comparison.failureRate.change < 0 || // Less failures (comparison.avgDuration.change < 5 && comparison.failureRate.change <= 0); // Not slower & not worse return { improved, comparison }; } async getMetricsAtTimestamp(timestamp) { // Read logs from timestamp onwards // Calculate metrics // Return stats } } module.exports = { VerificationEngine }; ``` --- ## 6. 실행 스케줄 ### 6.1 주간 분석 (매주 일요일 23:00) ```bash # ~/openclaw/scripts/level2-weekly-analysis.js const { LogAnalyzer } = require('../lib/log-analyzer'); const { ParameterOptimizer } = require('../lib/parameter-optimizer'); async function weeklyAnalysis() { console.log('📊 Level 2: 주간 로그 분석\n'); // 1. Analyze logs const analyzer = new LogAnalyzer(); const stats = await analyzer.analyze('~/openclaw/logs/auto-retry.jsonl'); console.log('통계:'); console.log(`- 총 실행: ${stats.total}회`); console.log(`- 성공률: ${(stats.success / stats.total * 100).toFixed(1)}%`); console.log(`- 재시도율: ${(stats.retries / stats.total * 100).toFixed(1)}%`); // 2. Detect patterns const patterns = analyzer.detectPatterns(stats); if (patterns.length === 0) { console.log('✅ 조정 불필요 (모든 지표 정상)'); return; } console.log(`\n⚠️ ${patterns.length}개 패턴 발견:`); patterns.forEach(p => console.log(`- ${p.type}: ${p.cron}`)); // 3. Generate recommendations const optimizer = new ParameterOptimizer(); const recommendations = optimizer.calculateOptimal(patterns); console.log('\n💡 조정 제안:'); recommendations.forEach(r => { console.log(`- ${r.param}: ${r.current} → ${r.proposed}`); console.log(` 이유: ${r.reason}`); console.log(` 예상 효과: ${r.expectedImprovement}`); console.log(` 안전: ${r.safe ? '✅' : '❌'}`); }); // 4. Auto-apply if safe const safeRecs = recommendations.filter(r => r.safe); if (safeRecs.length > 0) { console.log(`\n✅ ${safeRecs.length}개 자동 적용 예정 (24시간 후 검증)`); // Apply changes... } else { console.log('\n⚠️ 수동 검토 필요 (안전 범위 벗어남)'); } } weeklyAnalysis(); ``` ### 6.2 Cron 설정 ```json { "name": "Level 2 주간 분석", "schedule": "0 23 * * 0", "payload": { "message": "node ~/openclaw/scripts/level2-weekly-analysis.js", "to": "channel:1468751194284621967" } } ``` --- ## 7. 성공 지표 ### 7.1 Level 2 자체의 성공 기준 | 지표 | 목표 | 측정 방법 | |------|------|----------| | **자동 조정 정확도** | > 90% | 조정 후 롤백 비율 < 10% | | **개선 효과** | > 0% | Before/After 메트릭 비교 | | **사람 개입 비율** | < 10% | 수동 검토 필요 건수 / 전체 조정 | | **안전성** | 100% | 안전 범위 벗어난 조정 0건 | ### 7.2 측정 가능한 개선 **Before Level 2**: - maxRetries 수동 설정 → 과하거나 부족할 수 있음 - timeout 수동 설정 → 실제 성능과 불일치 - 설정 변경 시 사람이 판단 → 지연, 실수 가능 **After Level 2**: - maxRetries 자동 최적화 → 데이터 기반 정확한 값 - timeout 자동 조정 → 실제 응답 시간 * 1.5 여유 - 설정 변경 자동화 → 즉시 적용, 검증, 롤백 **예상 효과**: - 최종 실패율: -50% (더 많은 재시도로 복구) - 응답 시간: ±5% (timeout 최적화) - 운영 부담: -80% (자동화) --- ## 8. Level 3로의 전환 조건 Level 2에서 Level 3 (코드 자동 수정)으로 넘어가는 조건: **조건 1: 반복 패턴 감지** ```javascript // 예시 if (same_error_count > 10 && same_fix_count > 5) { // 같은 에러가 10번 이상 발생 // 같은 수동 수정이 5번 이상 발생 // → AI가 패턴 학습 가능 suggest_code_fix(); } ``` **조건 2: 근본 원인 명확** ```javascript // 예시 if (timeout_on_same_api > 5) { // 특정 API에서 반복적으로 timeout // 근본 원인: API 자체가 느림 // 해결책: timeout 증가 (설정 변경) OR 캐싱 추가 (코드 변경) if (parameter_tuning_not_enough) { suggest_code_change(); } } ``` **조건 3: 안전한 코드 패턴** ```javascript // 자동 수정 가능한 패턴 - timeout 값 증가 - retry 로직 추가 - 캐싱 레이어 추가 // 수동 검토 필요한 패턴 - 로직 변경 - API 엔드포인트 변경 - 데이터 구조 변경 ``` --- ## 9. 다음 단계 ### 9.1 즉시 (2026-02-05 ~ 02-12) - [x] Level 2 설계 문서 작성 (이 문서) - [ ] 로그 분석기 구현 (`log-analyzer.js`) - [ ] 테스트 데이터로 검증 ### 9.2 2주차 (2026-02-12 ~ 02-19) - [ ] 파라미터 최적화기 구현 - [ ] 변경 적용기 구현 - [ ] 단위 테스트 작성 ### 9.3 3주차 (2026-02-19 ~ 02-26) - [ ] 검증 엔진 구현 - [ ] 주간 분석 스크립트 작성 - [ ] Cron 등록 ### 9.4 4주차 (2026-02-26 ~ 03-05) - [ ] 프로덕션 배포 - [ ] 첫 자동 조정 실행 - [ ] 효과 측정 및 리포트 --- ## 10. 부록 ### 10.1 참고 문서 - `~/openclaw/docs/auto-retry-integration.md` (Level 1 설계) - `~/openclaw/docs/level1-rollout-summary.md` (Level 1 배포 결과) - `~/openclaw/MEMORY.md` (자가개선 원칙) ### 10.2 관련 파일 ``` ~/openclaw/ ├── lib/ │ ├── auto-retry.js (Level 1) │ ├── log-analyzer.js (Level 2 - 구현 예정) │ ├── parameter-optimizer.js (Level 2 - 구현 예정) │ ├── change-applicator.js (Level 2 - 구현 예정) │ └── verification-engine.js (Level 2 - 구현 예정) ├── scripts/ │ ├── tqqq-monitor-with-retry.js (Level 1) │ └── level2-weekly-analysis.js (Level 2 - 구현 예정) ├── logs/ │ └── auto-retry.jsonl (Level 1 & 2 공용) └── docs/ ├── level1-rollout-summary.md (Level 1) └── level2-parameter-tuning-design.md (이 문서) ``` --- **작성**: Claude Opus 4.5 **날짜**: 2026-02-05 **상태**: ✅ 설계 완료, 구현 대기