"""StrategyTuner - 策略调优 自动调整 Agent 参数(temperature, tool 选择权重, Pipeline 路径)。 使用简化的 Bayesian-inspired 优化替代随机扰动。 """ import logging import math import random from dataclasses import dataclass, field from typing import Any logger = logging.getLogger(__name__) @dataclass class StrategyConfig: """策略配置""" temperature: float = 0.5 tool_weights: dict[str, float] = field(default_factory=dict) max_iterations: int = 5 timeout_seconds: int = 300 class StrategyTuner: """策略调优器 基于历史效果数据自动调整 Agent 参数。 使用简化的 Bayesian-inspired 1D 优化:对每个参数, 找到历史最优值并添加小高斯噪声。 """ def __init__(self, param_ranges: dict[str, tuple[float, float]] | None = None): self._param_ranges = param_ranges or { "temperature": (0.0, 1.0), "max_iterations": (1, 10), } self._history: list[dict[str, Any]] = [] def record(self, config: StrategyConfig, metric: float) -> None: """记录配置和对应的效果指标""" self._history.append({ "config": config, "metric": metric, }) async def suggest(self, current: StrategyConfig) -> StrategyConfig: """基于历史数据建议新的策略配置 使用简化的 Bayesian-inspired 优化: 1. 对每个参数,在历史中找到得分最高的配置对应的参数值 2. 在该最优值附近添加小高斯噪声进行探索 """ if len(self._history) < 3: logger.info("Not enough history for strategy tuning") return current # Find best config in history best = max(self._history, key=lambda x: x["metric"]) best_config = best["config"] # For each parameter, find the best value and add Gaussian noise suggested_temperature = self._optimize_param_1d( param_name="temperature", get_value=lambda c: c.temperature, best_value=best_config.temperature, noise_std=0.05, ) suggested_max_iterations = int(self._optimize_param_1d( param_name="max_iterations", get_value=lambda c: c.max_iterations, best_value=best_config.max_iterations, noise_std=0.5, )) suggested = StrategyConfig( temperature=suggested_temperature, tool_weights=dict(best_config.tool_weights), max_iterations=suggested_max_iterations, timeout_seconds=current.timeout_seconds, ) logger.info( f"Strategy suggestion: temperature {current.temperature:.2f} -> {suggested.temperature:.2f}, " f"max_iterations {current.max_iterations} -> {suggested.max_iterations}" ) return suggested def _optimize_param_1d( self, param_name: str, get_value: Any, best_value: float, noise_std: float, ) -> float: """简化的 1D Bayesian-inspired 优化 在历史最优值附近添加高斯噪声进行探索。 噪声标准差随历史数据量递减(探索-利用平衡)。 """ # Decay noise as we accumulate more data (exploit more, explore less) decay_factor = 1.0 / (1.0 + len(self._history) / 10.0) effective_noise = noise_std * decay_factor # Add Gaussian noise around the best value perturbation = random.gauss(0, effective_noise) new_value = best_value + perturbation # Clamp to valid range min_val, max_val = self._param_ranges.get(param_name, (0.0, 1.0)) return max(min_val, min(max_val, new_value)) @staticmethod def _clamp(value: float, min_val: float, max_val: float) -> float: return max(min_val, min(max_val, value))