shinka-backup / eval_agent /design_draft /INTEGRATION_PLAN.md
JustinTX's picture
Add files using upload-large-folder tool
3f6526a verified
# EV2 Service Integration Plan - Minimal Changes
## 🎯 设计目标
**最小侵入性集成**
- ✅ 不改变现有演化逻辑
- ✅ 不阻塞演化流程
- ✅ 失败时不影响主流程
- ✅ 可选功能(默认禁用)
- ✅ 向后兼容(不破坏现有代码)
---
## 📊 架构分析
### 当前 ShinkaEvolve 流程
```
EvolutionRunner.run()
_submit_new_job() → 创建演化任务
scheduler.run() → 执行评估
_check_completed_jobs() → 检查完成
_process_completed_job() → 处理结果
├── 获取 results (line 792)
├── 提取 combined_score (line 821)
├── 保存到数据库 (line 851)
└── 更新 meta memory (line 857)
```
### 集成点
**最佳位置**`_process_completed_job()` 方法的**末尾**(line 886 之后)
**理由**
1. ✅ 所有数据已准备好(generation, score, results_dir)
2. ✅ 数据库已保存(不影响核心流程)
3. ✅ 不阻塞关键路径
4. ✅ 失败不影响演化
---
## 🔧 最小改动方案
### 改动 1: 添加配置选项(1 行)
**文件**:`shinka/core/runner.py`
**位置**:Line 64(EvolutionConfig 最后)
```python
@dataclass
class EvolutionConfig:
task_sys_msg: Optional[str] = None
# ... 其他现有字段 ...
use_text_feedback: bool = False
# ===== 新增字段 =====
eval_service_url: Optional[str] = None # e.g., "http://localhost:8765"
```
**影响**
- 向后兼容:默认 `None`,不启用
- 不影响现有代码
- 可以通过 YAML 配置启用
---
### 改动 2: 初始化通知器(~10 行)
**文件**:`shinka/core/runner.py`
**位置**:Line 95-101(`__init__` 方法中)
```python
class EvolutionRunner:
def __init__(
self,
evo_config: EvolutionConfig,
job_config: JobConfig,
db_config: DatabaseConfig,
verbose: bool = True,
):
# 保存 evo_config(如果还没有的话)
self.evo_config = evo_config # 可能已存在
self.job_config = job_config
self.db_config = db_config
self.verbose = verbose
# ... 现有初始化代码 ...
# ===== 新增:初始化 eval service 通知器 =====
self.eval_service_url = evo_config.eval_service_url
if self.eval_service_url:
logger.info(f"EV2 Eval Service enabled: {self.eval_service_url}")
```
**影响**
- 仅在配置了 URL 时记录日志
- 不导入额外依赖(requests 延迟导入)
---
### 改动 3: 添加通知方法(~30 行)
**文件**`shinka/core/runner.py`
**位置**:在 `_process_completed_job` 方法之后添加新方法
```python
def _notify_eval_service(
self,
generation: int,
combined_score: float,
results_dir: str
):
"""
Notify eval service of generation completion (non-blocking, fire-and-forget).
This is a best-effort notification that does not affect the evolution process.
If the service is unavailable or the notification fails, evolution continues normally.
"""
if not self.eval_service_url:
return
try:
import requests
# Prepare notification
payload = {
"generation": generation,
"results_dir": str(results_dir),
"primary_score": float(combined_score),
}
# Send notification (short timeout, non-blocking)
response = requests.post(
f"{self.eval_service_url}/api/v1/notify/generation_complete",
json=payload,
timeout=1.0 # Very short timeout (fire-and-forget)
)
if response.status_code == 200:
logger.debug(f"Notified eval service for generation {generation}")
else:
logger.debug(
f"Eval service notification failed: HTTP {response.status_code}"
)
except Exception as e:
# Silently ignore errors (evolution continues)
logger.debug(f"Failed to notify eval service: {e}")
pass
```
**特点**
- ✅ 非阻塞(timeout=1.0 秒)
- ✅ Fire-and-forget(失败不抛异常)
- ✅ 仅在启用时运行
- ✅ 延迟导入 requests(不增加启动开销)
- ✅ 使用 debug 级别日志(不干扰主日志)
---
### 改动 4: 调用通知(1 行)
**文件**`shinka/core/runner.py`
**位置**:Line 886(`_process_completed_job` 方法末尾)
```python
def _process_completed_job(self, job: RunningJob):
"""Process a completed job and add results to database."""
# ... 现有代码(line 788-886)...
# 保存最佳程序
self.db_path = self.results_dir / BEST_PROGRAM_FNAME
if db_program.combined_score > self.best_score:
self.best_score = db_program.combined_score
self.best_program_path = Path(job.exec_fname)
# Save best program copy
if self.best_program_path.exists():
shutil.copy(
self.best_program_path,
Path(self.results_dir) / BEST_PROGRAM_FNAME,
)
# ===== 新增:通知 eval service =====
self._notify_eval_service(
generation=job.generation,
combined_score=combined_score,
results_dir=job.results_dir
)
```
**影响**
- 仅在 `eval_service_url` 配置时生效
- 不阻塞(timeout=1.0s)
- 失败不影响演化
---
## 📋 完整改动总结
| 文件 | 位置 | 改动类型 | 行数 |
|------|------|---------|------|
| `shinka/core/runner.py` | Line 64 | 添加配置字段 | +1 |
| `shinka/core/runner.py` | Line 95-101 | 初始化变量 | +3 |
| `shinka/core/runner.py` | 新方法 | 添加通知方法 | +35 |
| `shinka/core/runner.py` | Line 886+ | 调用通知 | +5 |
| **总计** | | | **+44 行** |
---
## 🎯 使用方式
### 方式 1: YAML 配置
```yaml
# experiment_config.yaml
evolution:
# ... 现有配置 ...
eval_service_url: "http://localhost:8765" # 启用 eval service
```
### 方式 2: Python 代码
```python
from shinka.core import EvolutionRunner, EvolutionConfig
from shinka.launch import JobConfig
from shinka.database import DatabaseConfig
# 创建配置
evo_config = EvolutionConfig(
num_generations=100,
# ... 其他配置 ...
eval_service_url="http://localhost:8765", # 启用 eval service
)
# 运行演化(无需其他改动)
runner = EvolutionRunner(evo_config, job_config, db_config)
runner.run()
```
### 方式 3: 不使用(默认)
```python
# 不设置 eval_service_url,则不启用
evo_config = EvolutionConfig(
num_generations=100,
# eval_service_url=None # 默认值,可以不写
)
runner = EvolutionRunner(evo_config, job_config, db_config)
runner.run() # 正常运行,无任何改变
```
---
## ✅ 验证兼容性
### 1. 向后兼容性
**测试**:运行现有实验配置(不设置 `eval_service_url`
**预期**
- ✅ 完全相同的行为
- ✅ 无额外日志
- ✅ 无性能影响
- ✅ 无依赖问题
### 2. 前向兼容性
**测试**:设置 `eval_service_url` 但服务未启动
**预期**
- ✅ 演化正常运行
- ✅ Debug 日志显示通知失败
- ✅ 不抛异常
- ✅ 不影响结果
### 3. 完整集成
**测试**:启动 eval service 并运行演化
**预期**
- ✅ 演化正常运行
- ✅ 每代完成后发送通知
- ✅ Eval service 自主决策触发
- ✅ Agent 生成辅助指标
---
## 🚀 实施步骤
### Step 1: 代码修改(20 分钟)
1. 备份 `shinka/core/runner.py`
2. 按照上述方案修改 4 处
3. 语法检查:`python -m py_compile shinka/core/runner.py`
### Step 2: 单元测试(10 分钟)
测试基础功能:
```python
# test_integration.py
from shinka.core import EvolutionConfig
# Test 1: 默认配置(不启用)
config1 = EvolutionConfig()
assert config1.eval_service_url is None
# Test 2: 启用配置
config2 = EvolutionConfig(eval_service_url="http://localhost:8765")
assert config2.eval_service_url == "http://localhost:8765"
print("✅ Configuration tests passed")
```
### Step 3: 集成测试(30 分钟)
**测试场景 1**:不启用 service(向后兼容)
```bash
# 运行现有实验
python my/run_circle_packing_WITHOUT_vision_WITH_refined_aux.py
# 预期:正常运行,无任何变化
```
**测试场景 2**:启用 service 但未启动(容错)
```python
# 在实验脚本中添加
evolution_config = EvolutionConfig(
# ... 现有配置 ...
eval_service_url="http://localhost:8765",
)
# 运行实验(eval service 未启动)
# 预期:演化正常运行,debug 日志显示连接失败
```
**测试场景 3**:完整集成(正常工作)
```bash
# Terminal 1: 启动 eval service
uv run eval_agent/ev2_service_standalone.py --config eval_agent/ev2_service_config.yaml
# Terminal 2: 运行演化(小规模测试:5 代,interval=5)
# 修改实验脚本添加 eval_service_url
python my/test_with_eval_service.py
# 预期:
# - 演化正常运行
# - 第 5 代触发 eval agent
# - Agent 生成 EVAL_AGENTS.md
```
### Step 4: 文档更新(10 分钟)
创建 `eval_agent/USAGE_GUIDE.md`
- 如何启动 eval service
- 如何在实验中启用
- 示例配置
- 故障排除
---
## 📊 性能影响分析
### 不启用时(eval_service_url=None)
- CPU 开销:**0%**(完全不运行)
- 内存开销:**0 字节**
- 延迟:**0 毫秒**
- 网络:**0 请求**
### 启用时(service 正常运行)
- CPU 开销:**< 0.1%**(仅构建 JSON + 发送)
- 内存开销:**< 1 KB**(payload 数据)
- 延迟:**< 5 毫秒**(本地网络)
- 网络:**1 请求/代**
### 启用时(service 不可用)
- CPU 开销:**< 0.1%**(timeout 快速失败)
- 延迟:**1-2 毫秒**(connection refused 立即返回)
- 影响:**无**(catch 所有异常)
**结论**:✅ 性能影响可以忽略不计
---
## 🔒 安全性考虑
1. **网络隔离**
- 默认 `localhost:8765`
- 不暴露到公网
- 可以配置防火墙规则
2. **数据隐私**
- 仅发送:generation, score, results_dir
- 不发送代码内容
- Results_dir 路径已知(本地路径)
3. **失败处理**
- 所有异常被捕获
- 不影响主流程
- 日志级别 DEBUG(不泄露敏感信息)
4. **依赖安全**
- `requests` 是常用库(已在依赖中)
- 无新增外部依赖
---
## 🎯 优势总结
### 对 ShinkaEvolve
-**最小侵入**:仅 44 行代码,4 处修改
-**零风险**:失败不影响演化
-**可选功能**:默认禁用
-**向后兼容**:不破坏现有代码
-**无性能损失**:开销可忽略
-**易于维护**:代码清晰,注释完整
### 对用户
-**透明集成**:无需修改实验脚本
-**灵活配置**:YAML 或代码都可以
-**即插即用**:启动 service 即可
-**故障隔离**:service 崩溃不影响演化
-**增量采用**:可以先测试,再推广
### 对 Eval Service
-**完全解耦**:不依赖 ShinkaEvolve 内部实现
-**通用接口**:可以服务其他演化框架
-**自主决策**:何时分析由 service 决定
-**持久化**:跨演化运行累积经验
---
## 📝 检查清单
实施前检查:
- [ ] 已阅读并理解集成方案
- [ ] 已备份 `shinka/core/runner.py`
- [ ] 已准备测试环境(eval service 配置好)
- [ ] 已准备测试实验(小规模:5-10 代)
实施中检查:
- [ ] 代码修改完成(4 处)
- [ ] 语法检查通过
- [ ] 向后兼容测试通过
- [ ] 容错测试通过
实施后检查:
- [ ] 完整集成测试通过
- [ ] 文档更新完成
- [ ] 示例配置创建
- [ ] 团队成员知晓
---
## 🎉 预期成果
实施后,用户可以:
1. **无缝启用**
```python
evo_config = EvolutionConfig(
# ... 现有配置 ...
eval_service_url="http://localhost:8765"
)
```
2. **自动分析**
- 演化运行时,service 自动接收通知
- 根据策略(periodic/plateau)触发分析
- Agent 生成辅助指标和洞察
3. **实时监控**
- 访问 `http://localhost:8765/docs` 查看 API
- 查看 `results_dir/eval_agent_memory/EVAL_AGENTS.md`
- 实时了解演化进展
4. **灵活控制**
- 可以随时停止/启动 service
- 调整触发策略(interval, plateau)
- 手动触发分析(通过 API)
---
**准备好实施了吗?** 🚀
下一步:
1. 确认计划(你觉得这个方案怎么样?)
2. 开始实施(我可以帮你逐步完成)
3. 测试验证(确保一切正常)