Coverage for agentos/config/loader.py: 85%

284 statements  

« prev     ^ index     » next       coverage.py v7.14.3, created at 2026-07-06 12:29 +0800

1""" 

2AgentOS v0.80 统一配置系统。 

3v0.80新增: BenchmarkCfg。 

4v0.70基线: PluginsCfg, GeminiCfg, ContractsCfg, OrchestratorCfg, ScorerCfg。 

5v0.60基线: GuardrailsCfg, RateLimitCfg, StateMachineCfg, ResilienceCfg。 

6""" 

7 

8from __future__ import annotations 

9 

10import os 

11from dataclasses import dataclass, field, fields 

12 

13 

14@dataclass 

15class ModelConfig: 

16 """LLM 模型配置。""" 

17 

18 default: str = "deepseek-v3.1" 

19 fallback_chain: list[str] = field(default_factory=lambda: ["kimi-k2.6", "qwen-3.6-plus"]) 

20 auto_select: bool = True 

21 max_retries: int = 3 

22 request_timeout: int = 120 

23 api_base: str = "" 

24 api_key: str = "" 

25 

26 

27@dataclass 

28class LoopCfg: 

29 """Agent 主循环配置。""" 

30 

31 max_iterations: int = 100 

32 max_retries_per_step: int = 2 

33 step_timeout_seconds: int = 120 

34 enable_streaming: bool = False 

35 enable_checkpoints: bool = True 

36 checkpoint_interval: int = 5 

37 

38 

39@dataclass 

40class MemoryCfg: 

41 """记忆系统配置。""" 

42 

43 short_term_capacity: int = 50 

44 long_term_enabled: bool = True 

45 long_term_max_entries: int = 100000 

46 vector_dim: int = 1536 

47 vector_backend: str = "faiss" 

48 vector_persist_dir: str = "./vector_data" 

49 compression_interval: int = 20 

50 

51 

52@dataclass 

53class SecurityCfg: 

54 """安全策略配置。""" 

55 

56 sandbox_enabled: bool = False 

57 sandbox_image: str = "agentos-sandbox:latest" 

58 max_file_size_mb: int = 100 

59 allowed_paths: list[str] = field(default_factory=lambda: [".", "/tmp/agentos"]) 

60 

61 

62@dataclass 

63class ObservabilityCfg: 

64 """可观测性配置。""" 

65 

66 tracer_enabled: bool = True 

67 tracer_backend: str = "console" 

68 langsmith_api_key: str = "" 

69 log_level: str = "INFO" 

70 

71 

72@dataclass 

73class MCPServersCfg: 

74 """MCP 服务器列表配置。""" 

75 

76 servers: list[dict] = field(default_factory=list) 

77 

78 

79@dataclass 

80class ReflectionCfg: 

81 """反思循环配置。""" 

82 

83 enabled: bool = True 

84 frequency: int = 3 

85 max_loops: int = 3 

86 enable_self_critique: bool = True 

87 

88 

89@dataclass 

90class CostCfg: 

91 """成本控制配置。""" 

92 

93 enabled: bool = True 

94 budget_limit: float = 0.0 

95 warn_threshold: float = 0.8 

96 

97 

98@dataclass 

99class FeedbackCfg: 

100 """反馈回路配置。""" 

101 

102 enabled: bool = True 

103 human_in_the_loop: bool = False 

104 approval_trigger: str = "high_risk" 

105 storage_path: str = "./feedback_data.jsonl" 

106 

107 

108@dataclass 

109class APICfg: 

110 """API 服务配置。""" 

111 

112 enabled: bool = True 

113 host: str = "0.0.0.0" 

114 port: int = 8080 

115 cors_origins: list[str] = field(default_factory=lambda: ["*"]) 

116 

117 

118@dataclass 

119class SwarmCfg: 

120 """Swarm 多 Agent 协作配置。""" 

121 

122 enabled: bool = True 

123 topology: str = "sequential" # sequential|parallel|debate|hierarchical|broadcast 

124 max_parallel_agents: int = 4 

125 enable_communication: bool = True 

126 enable_blackboard: bool = True 

127 

128 

129@dataclass 

130class QueueCfg: 

131 """任务队列配置。""" 

132 

133 enabled: bool = False 

134 backend: str = "memory" # memory|redis 

135 redis_url: str = "redis://localhost:6379/0" 

136 concurrency: int = 4 

137 max_retries: int = 3 

138 retry_backoff: str = "exponential" # exponential|linear|fixed 

139 

140 

141@dataclass 

142class CacheCfg: 

143 """语义缓存配置。""" 

144 

145 enabled: bool = True 

146 lru_size: int = 500 

147 semantic_enabled: bool = True 

148 similarity_threshold: float = 0.92 

149 default_ttl: float = 3600 

150 

151 

152@dataclass 

153class ExperimentCfg: 

154 """A/B 实验配置。""" 

155 

156 enabled: bool = False 

157 auto_evaluator: str = "llm_judge" 

158 trials_per_variant: int = 3 

159 shuffle_trials: bool = True 

160 

161 

162@dataclass 

163class MultimodalCfg: 

164 """多模态处理配置。""" 

165 

166 enabled: bool = True 

167 max_image_size: int = 2048 

168 whisper_model: str = "base" 

169 document_parser: str = "auto" # auto|PyPDF2|unstructured 

170 

171 

172@dataclass 

173class MCPServerCfg: 

174 """MCP 服务端配置。""" 

175 

176 enabled: bool = False 

177 transport: str = "stdio" 

178 host: str = "0.0.0.0" 

179 port: int = 9000 

180 server_name: str = "AgentOS-MCP-Server" 

181 

182 

183@dataclass 

184class GuardrailsCfg: 

185 """安全护栏配置。""" 

186 

187 enabled: bool = True 

188 block_pii: bool = True 

189 block_injection: bool = True 

190 moderation_threshold: str = "medium" 

191 

192 

193@dataclass 

194class RateLimitCfg: 

195 """限流配置。""" 

196 

197 enabled: bool = True 

198 strategy: str = "token_bucket" 

199 max_requests: int = 60 

200 per_seconds: float = 60.0 

201 burst_size: int = 10 

202 max_concurrent: int = 5 

203 queue_timeout: float = 30.0 

204 

205 

206@dataclass 

207class StateMachineCfg: 

208 """状态机配置。""" 

209 

210 max_thinking_time: float = 300.0 

211 max_acting_time: float = 120.0 

212 max_observing_time: float = 60.0 

213 max_total_time: float = 3600.0 

214 auto_recover: bool = True 

215 

216 

217@dataclass 

218class ResilienceCfg: 

219 """弹性容错配置。""" 

220 

221 retry_max: int = 3 

222 retry_base_delay: float = 1.0 

223 retry_max_delay: float = 30.0 

224 circuit_failure_threshold: int = 5 

225 circuit_timeout: float = 30.0 

226 

227 

228# ── v0.70 新增配置段 ──────────────────────────────────────────────────── 

229 

230 

231@dataclass 

232class PluginsCfg: 

233 """插件系统配置。""" 

234 

235 enabled: bool = True 

236 plugins_dir: str = "./plugins" 

237 auto_discover: bool = True 

238 hot_reload: bool = False 

239 max_plugins: int = 50 

240 

241 

242@dataclass 

243class GeminiCfg: 

244 """Gemini 模型配置。""" 

245 

246 enabled: bool = True 

247 api_key: str = "" 

248 default_model: str = "gemini-2.5-flash" 

249 vision_enabled: bool = True 

250 max_image_size: int = 4096 

251 safety_threshold: str = "BLOCK_ONLY_HIGH" 

252 

253 

254@dataclass 

255class ContractsCfg: 

256 """能力契约配置。""" 

257 

258 enabled: bool = True 

259 auto_discover: bool = True 

260 heartbeat_interval: float = 30.0 

261 stale_timeout: float = 300.0 

262 max_registered: int = 100 

263 

264 

265@dataclass 

266class OrchestratorCfg: 

267 """编排器配置。""" 

268 

269 enabled: bool = True 

270 global_timeout: float = 300.0 

271 default_retries: int = 3 

272 max_concurrent_tools: int = 10 

273 dag_export_dir: str = "./dags" 

274 

275 

276@dataclass 

277class ScorerCfg: 

278 """评分器配置。""" 

279 

280 enabled: bool = True 

281 strategy: str = "composite" 

282 pass_threshold: float = 0.6 

283 enable_semantic: bool = True 

284 

285 

286# ── v0.80 新增配置段 ──────────────────────────────────────────────────── 

287 

288 

289@dataclass 

290class BenchmarkCfg: 

291 """性能基准配置。""" 

292 

293 enabled: bool = True 

294 output_dir: str = "./benchmarks" 

295 warmup_iterations: int = 3 

296 measure_iterations: int = 10 

297 concurrency_levels: list[int] = field(default_factory=lambda: [1, 4, 8]) 

298 timeout_per_run: float = 30.0 

299 

300 

301@dataclass 

302class HealthCfg: 

303 """健康检查配置。""" 

304 

305 readiness_enabled: bool = True 

306 liveness_enabled: bool = True 

307 disk_threshold_mb: int = 100 

308 memory_threshold_mb: int = 50 

309 

310 

311@dataclass 

312class AuditCfg: 

313 """安全审计配置。""" 

314 

315 enabled: bool = False 

316 severity_threshold: str = "medium" 

317 report_format: str = "markdown" 

318 auto_scan_on_startup: bool = False 

319 

320 

321@dataclass 

322class DeployCfg: 

323 """部署配置。""" 

324 

325 base_image: str = "python:3.11-slim" 

326 port: int = 8000 

327 workers: int = 4 

328 healthcheck_endpoint: str = "/health" 

329 

330 

331@dataclass 

332class MiddlewareCfg: 

333 """中间件配置。""" 

334 

335 cors_enabled: bool = True 

336 cors_origins: list = field(default_factory=lambda: ["*"]) 

337 auth_enabled: bool = False 

338 request_logging: bool = True 

339 rate_limit_rpm: int = 0 

340 

341 

342@dataclass 

343class AgentOSConfig: 

344 """AgentOS v0.90 总配置。""" 

345 

346 model: ModelConfig = field(default_factory=ModelConfig) 

347 loop: LoopCfg = field(default_factory=LoopCfg) 

348 memory: MemoryCfg = field(default_factory=MemoryCfg) 

349 security: SecurityCfg = field(default_factory=SecurityCfg) 

350 observability: ObservabilityCfg = field(default_factory=ObservabilityCfg) 

351 mcp: MCPServersCfg = field(default_factory=MCPServersCfg) 

352 reflection: ReflectionCfg = field(default_factory=ReflectionCfg) 

353 cost: CostCfg = field(default_factory=CostCfg) 

354 feedback: FeedbackCfg = field(default_factory=FeedbackCfg) 

355 api: APICfg = field(default_factory=APICfg) 

356 swarm: SwarmCfg = field(default_factory=SwarmCfg) 

357 queue: QueueCfg = field(default_factory=QueueCfg) 

358 cache: CacheCfg = field(default_factory=CacheCfg) 

359 experiment: ExperimentCfg = field(default_factory=ExperimentCfg) 

360 multimodal: MultimodalCfg = field(default_factory=MultimodalCfg) 

361 mcp_server: MCPServerCfg = field(default_factory=MCPServerCfg) 

362 guardrails: GuardrailsCfg = field(default_factory=GuardrailsCfg) 

363 rate_limit: RateLimitCfg = field(default_factory=RateLimitCfg) 

364 state_machine: StateMachineCfg = field(default_factory=StateMachineCfg) 

365 resilience: ResilienceCfg = field(default_factory=ResilienceCfg) 

366 plugins: PluginsCfg = field(default_factory=PluginsCfg) 

367 gemini: GeminiCfg = field(default_factory=GeminiCfg) 

368 contracts: ContractsCfg = field(default_factory=ContractsCfg) 

369 orchestrator: OrchestratorCfg = field(default_factory=OrchestratorCfg) 

370 scorer: ScorerCfg = field(default_factory=ScorerCfg) 

371 benchmark: BenchmarkCfg = field(default_factory=BenchmarkCfg) 

372 health: HealthCfg = field(default_factory=HealthCfg) 

373 audit: AuditCfg = field(default_factory=AuditCfg) 

374 deploy: DeployCfg = field(default_factory=DeployCfg) 

375 middleware: MiddlewareCfg = field(default_factory=MiddlewareCfg) 

376 version: str = "0.90.0" 

377 

378 def to_dict(self) -> dict: 

379 result = {} 

380 for f in fields(self): 

381 val = getattr(self, f.name) 

382 if hasattr(val, "__dataclass_fields__"): 

383 result[f.name] = {ff.name: getattr(val, ff.name) for ff in fields(val)} 

384 else: 

385 result[f.name] = val 

386 return result 

387 

388 

389def load_config(path: str | None = None) -> AgentOSConfig: 

390 config = AgentOSConfig() 

391 if path and os.path.exists(path): 

392 try: 

393 import yaml 

394 

395 with open(path) as f: 

396 data = yaml.safe_load(f) 

397 _merge(config, data) 

398 except ImportError: 

399 pass 

400 except Exception: 

401 pass 

402 _override_from_env(config) 

403 return config 

404 

405 

406def _merge(config: AgentOSConfig, data: dict): 

407 for key, val in data.items(): 

408 if hasattr(config, key): 

409 section = getattr(config, key) 

410 if hasattr(section, "__dataclass_fields__") and isinstance(val, dict): 

411 for sk, sv in val.items(): 

412 if hasattr(section, sk): 

413 setattr(section, sk, sv) 

414 else: 

415 setattr(config, key, val) 

416 

417 

418def _override_from_env(config: AgentOSConfig): 

419 env_map = { 

420 "AGENTOS_MODEL": ("model", "default"), 

421 "AGENTOS_MAX_ITERATIONS": ("loop", "max_iterations"), 

422 "AGENTOS_ENABLE_STREAMING": ("loop", "enable_streaming"), 

423 "AGENTOS_LOG_LEVEL": ("observability", "log_level"), 

424 "AGENTOS_BUDGET_LIMIT": ("cost", "budget_limit"), 

425 "AGENTOS_ENABLE_REFLECTION": ("reflection", "enabled"), 

426 "AGENTOS_ENABLE_COST_TRACKING": ("cost", "enabled"), 

427 "AGENTOS_API_PORT": ("api", "port"), 

428 "AGENTOS_SWARM_TOPOLOGY": ("swarm", "topology"), 

429 "AGENTOS_SWARM_MAX_PARALLEL": ("swarm", "max_parallel_agents"), 

430 "AGENTOS_CACHE_LRU_SIZE": ("cache", "lru_size"), 

431 "AGENTOS_CACHE_SEMANTIC": ("cache", "semantic_enabled"), 

432 "AGENTOS_QUEUE_CONCURRENCY": ("queue", "concurrency"), 

433 "AGENTOS_MCP_SERVER_PORT": ("mcp_server", "port"), 

434 "AGENTOS_PLUGINS_DIR": ("plugins", "plugins_dir"), 

435 "AGENTOS_PLUGINS_HOT_RELOAD": ("plugins", "hot_reload"), 

436 "AGENTOS_GEMINI_API_KEY": ("gemini", "api_key"), 

437 "AGENTOS_GEMINI_MODEL": ("gemini", "default_model"), 

438 "AGENTOS_CONTRACTS_ENABLED": ("contracts", "enabled"), 

439 "AGENTOS_ORCHESTRATOR_TIMEOUT": ("orchestrator", "global_timeout"), 

440 "AGENTOS_SCORER_STRATEGY": ("scorer", "strategy"), 

441 "AGENTOS_SCORER_THRESHOLD": ("scorer", "pass_threshold"), 

442 } 

443 for env_key, (section, field_name) in env_map.items(): 

444 val = os.environ.get(env_key) 

445 if val is not None: 

446 sec = getattr(config, section) 

447 default_type = type(getattr(type(sec)(), field_name, "")) 

448 if default_type is bool: 

449 val_typed = val.lower() in ("1", "true", "yes") 

450 elif default_type is float: 

451 val_typed = float(val) 

452 elif default_type is int: 

453 val_typed = int(val) 

454 else: 

455 val_typed = val 

456 setattr(sec, field_name, val_typed)