feat: refactor API key configuration and enhance application initialization
- Renamed `check_environment` to `check_api_key_configured` for clarity, simplifying the API key validation logic. - Removed the blocking behavior of the API key check during application startup, allowing the app to run while providing a prompt for configuration. - Updated `LocalAgentApp` to accept an `api_configured` parameter, enabling conditional messaging for API key setup. - Enhanced the `SandboxRunner` to support backup management and improved execution result handling with detailed metrics. - Integrated data governance strategies into the `HistoryManager`, ensuring compliance and improved data management. - Added privacy settings and metrics tracking across various components to enhance user experience and application safety.
This commit is contained in:
167
llm/config_metrics.py
Normal file
167
llm/config_metrics.py
Normal file
@@ -0,0 +1,167 @@
|
||||
"""
|
||||
配置变更度量模块
|
||||
跟踪配置保存后的首次调用成功率和重试次数
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from typing import Optional, Dict, Any
|
||||
from dataclasses import dataclass, asdict
|
||||
|
||||
|
||||
@dataclass
|
||||
class ConfigChangeMetric:
|
||||
"""配置变更度量记录"""
|
||||
timestamp: str
|
||||
config_changed: bool # 是否发生配置变更
|
||||
first_call_success: Optional[bool] # 首次调用是否成功
|
||||
retry_count: int # 重试次数
|
||||
error_message: Optional[str] # 错误信息
|
||||
connection_test_success: bool # 保存后连通性测试是否成功
|
||||
time_to_success_ms: Optional[int] # 从配置变更到首次成功调用的时间(毫秒)
|
||||
|
||||
|
||||
class ConfigMetricsManager:
|
||||
"""配置度量管理器"""
|
||||
|
||||
def __init__(self, metrics_file: Path):
|
||||
self.metrics_file = metrics_file
|
||||
self.metrics_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# 当前配置变更状态
|
||||
self._config_changed = False
|
||||
self._config_change_time: Optional[datetime] = None
|
||||
self._connection_test_success = False
|
||||
self._first_call_recorded = False
|
||||
self._retry_count = 0
|
||||
|
||||
def mark_config_changed(self, connection_test_success: bool) -> None:
|
||||
"""标记配置已变更"""
|
||||
self._config_changed = True
|
||||
self._config_change_time = datetime.now()
|
||||
self._connection_test_success = connection_test_success
|
||||
self._first_call_recorded = False
|
||||
self._retry_count = 0
|
||||
|
||||
def record_first_call(self, success: bool, error_message: Optional[str] = None) -> None:
|
||||
"""记录配置变更后的首次调用"""
|
||||
if not self._config_changed or self._first_call_recorded:
|
||||
return
|
||||
|
||||
time_to_success_ms = None
|
||||
if self._config_change_time:
|
||||
delta = datetime.now() - self._config_change_time
|
||||
time_to_success_ms = int(delta.total_seconds() * 1000)
|
||||
|
||||
metric = ConfigChangeMetric(
|
||||
timestamp=datetime.now().isoformat(),
|
||||
config_changed=True,
|
||||
first_call_success=success,
|
||||
retry_count=self._retry_count,
|
||||
error_message=error_message,
|
||||
connection_test_success=self._connection_test_success,
|
||||
time_to_success_ms=time_to_success_ms
|
||||
)
|
||||
|
||||
self._save_metric(metric)
|
||||
self._first_call_recorded = True
|
||||
|
||||
# 如果成功,重置状态
|
||||
if success:
|
||||
self._config_changed = False
|
||||
self._retry_count = 0
|
||||
|
||||
def increment_retry(self) -> None:
|
||||
"""增加重试计数"""
|
||||
if self._config_changed:
|
||||
self._retry_count += 1
|
||||
|
||||
def record_retry_success(self, retry_count: int) -> None:
|
||||
"""记录重试后成功的请求"""
|
||||
# 可以用于统计重试恢复率
|
||||
pass
|
||||
|
||||
def record_retry_failure(self, retry_count: int) -> None:
|
||||
"""记录重试后仍失败的请求"""
|
||||
# 可以用于统计重试失败率
|
||||
pass
|
||||
|
||||
def _save_metric(self, metric: ConfigChangeMetric) -> None:
|
||||
"""保存度量记录"""
|
||||
try:
|
||||
# 读取现有记录
|
||||
metrics = []
|
||||
if self.metrics_file.exists():
|
||||
with open(self.metrics_file, 'r', encoding='utf-8') as f:
|
||||
metrics = json.load(f)
|
||||
|
||||
# 添加新记录
|
||||
metrics.append(asdict(metric))
|
||||
|
||||
# 只保留最近 100 条记录
|
||||
if len(metrics) > 100:
|
||||
metrics = metrics[-100:]
|
||||
|
||||
# 保存
|
||||
with open(self.metrics_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(metrics, f, ensure_ascii=False, indent=2)
|
||||
except Exception as e:
|
||||
print(f"保存配置度量失败: {e}")
|
||||
|
||||
def get_statistics(self) -> Dict[str, Any]:
|
||||
"""获取统计信息"""
|
||||
try:
|
||||
if not self.metrics_file.exists():
|
||||
return {
|
||||
"total_config_changes": 0,
|
||||
"first_call_success_rate": 0.0,
|
||||
"avg_retry_count": 0.0,
|
||||
"connection_test_success_rate": 0.0
|
||||
}
|
||||
|
||||
with open(self.metrics_file, 'r', encoding='utf-8') as f:
|
||||
metrics = json.load(f)
|
||||
|
||||
if not metrics:
|
||||
return {
|
||||
"total_config_changes": 0,
|
||||
"first_call_success_rate": 0.0,
|
||||
"avg_retry_count": 0.0,
|
||||
"connection_test_success_rate": 0.0
|
||||
}
|
||||
|
||||
total = len(metrics)
|
||||
success_count = sum(1 for m in metrics if m.get('first_call_success'))
|
||||
total_retries = sum(m.get('retry_count', 0) for m in metrics)
|
||||
connection_test_success = sum(1 for m in metrics if m.get('connection_test_success'))
|
||||
|
||||
return {
|
||||
"total_config_changes": total,
|
||||
"first_call_success_rate": success_count / total if total > 0 else 0.0,
|
||||
"avg_retry_count": total_retries / total if total > 0 else 0.0,
|
||||
"connection_test_success_rate": connection_test_success / total if total > 0 else 0.0,
|
||||
"recent_metrics": metrics[-10:] # 最近 10 条记录
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"获取配置度量统计失败: {e}")
|
||||
return {
|
||||
"total_config_changes": 0,
|
||||
"first_call_success_rate": 0.0,
|
||||
"avg_retry_count": 0.0,
|
||||
"connection_test_success_rate": 0.0
|
||||
}
|
||||
|
||||
|
||||
# 全局单例
|
||||
_metrics_manager: Optional[ConfigMetricsManager] = None
|
||||
|
||||
|
||||
def get_config_metrics(workspace: Path) -> ConfigMetricsManager:
|
||||
"""获取配置度量管理器单例"""
|
||||
global _metrics_manager
|
||||
if _metrics_manager is None:
|
||||
metrics_file = workspace / ".metrics" / "config_metrics.json"
|
||||
_metrics_manager = ConfigMetricsManager(metrics_file)
|
||||
return _metrics_manager
|
||||
|
||||
Reference in New Issue
Block a user