aiecs 1.0.1__py3-none-any.whl → 1.7.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of aiecs might be problematic. Click here for more details.
- aiecs/__init__.py +13 -16
- aiecs/__main__.py +7 -7
- aiecs/aiecs_client.py +269 -75
- aiecs/application/executors/operation_executor.py +79 -54
- aiecs/application/knowledge_graph/__init__.py +7 -0
- aiecs/application/knowledge_graph/builder/__init__.py +37 -0
- aiecs/application/knowledge_graph/builder/data_quality.py +302 -0
- aiecs/application/knowledge_graph/builder/data_reshaping.py +293 -0
- aiecs/application/knowledge_graph/builder/document_builder.py +369 -0
- aiecs/application/knowledge_graph/builder/graph_builder.py +490 -0
- aiecs/application/knowledge_graph/builder/import_optimizer.py +396 -0
- aiecs/application/knowledge_graph/builder/schema_inference.py +462 -0
- aiecs/application/knowledge_graph/builder/schema_mapping.py +563 -0
- aiecs/application/knowledge_graph/builder/structured_pipeline.py +1384 -0
- aiecs/application/knowledge_graph/builder/text_chunker.py +317 -0
- aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
- aiecs/application/knowledge_graph/extractors/base.py +98 -0
- aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +422 -0
- aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +347 -0
- aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +241 -0
- aiecs/application/knowledge_graph/fusion/__init__.py +78 -0
- aiecs/application/knowledge_graph/fusion/ab_testing.py +395 -0
- aiecs/application/knowledge_graph/fusion/abbreviation_expander.py +327 -0
- aiecs/application/knowledge_graph/fusion/alias_index.py +597 -0
- aiecs/application/knowledge_graph/fusion/alias_matcher.py +384 -0
- aiecs/application/knowledge_graph/fusion/cache_coordinator.py +343 -0
- aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +433 -0
- aiecs/application/knowledge_graph/fusion/entity_linker.py +511 -0
- aiecs/application/knowledge_graph/fusion/evaluation_dataset.py +240 -0
- aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +632 -0
- aiecs/application/knowledge_graph/fusion/matching_config.py +489 -0
- aiecs/application/knowledge_graph/fusion/name_normalizer.py +352 -0
- aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +183 -0
- aiecs/application/knowledge_graph/fusion/semantic_name_matcher.py +464 -0
- aiecs/application/knowledge_graph/fusion/similarity_pipeline.py +534 -0
- aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
- aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +342 -0
- aiecs/application/knowledge_graph/pattern_matching/query_executor.py +366 -0
- aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
- aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +195 -0
- aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
- aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
- aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +341 -0
- aiecs/application/knowledge_graph/reasoning/inference_engine.py +500 -0
- aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +163 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +913 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +866 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +475 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +396 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +208 -0
- aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +170 -0
- aiecs/application/knowledge_graph/reasoning/query_planner.py +855 -0
- aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +518 -0
- aiecs/application/knowledge_graph/retrieval/__init__.py +27 -0
- aiecs/application/knowledge_graph/retrieval/query_intent_classifier.py +211 -0
- aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +592 -0
- aiecs/application/knowledge_graph/retrieval/strategy_types.py +23 -0
- aiecs/application/knowledge_graph/search/__init__.py +59 -0
- aiecs/application/knowledge_graph/search/hybrid_search.py +457 -0
- aiecs/application/knowledge_graph/search/reranker.py +293 -0
- aiecs/application/knowledge_graph/search/reranker_strategies.py +535 -0
- aiecs/application/knowledge_graph/search/text_similarity.py +392 -0
- aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
- aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +305 -0
- aiecs/application/knowledge_graph/traversal/path_scorer.py +271 -0
- aiecs/application/knowledge_graph/validators/__init__.py +13 -0
- aiecs/application/knowledge_graph/validators/relation_validator.py +239 -0
- aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
- aiecs/application/knowledge_graph/visualization/graph_visualizer.py +313 -0
- aiecs/common/__init__.py +9 -0
- aiecs/common/knowledge_graph/__init__.py +17 -0
- aiecs/common/knowledge_graph/runnable.py +471 -0
- aiecs/config/__init__.py +20 -5
- aiecs/config/config.py +762 -31
- aiecs/config/graph_config.py +131 -0
- aiecs/config/tool_config.py +399 -0
- aiecs/core/__init__.py +29 -13
- aiecs/core/interface/__init__.py +2 -2
- aiecs/core/interface/execution_interface.py +22 -22
- aiecs/core/interface/storage_interface.py +37 -88
- aiecs/core/registry/__init__.py +31 -0
- aiecs/core/registry/service_registry.py +92 -0
- aiecs/domain/__init__.py +270 -1
- aiecs/domain/agent/__init__.py +191 -0
- aiecs/domain/agent/base_agent.py +3870 -0
- aiecs/domain/agent/exceptions.py +99 -0
- aiecs/domain/agent/graph_aware_mixin.py +569 -0
- aiecs/domain/agent/hybrid_agent.py +1435 -0
- aiecs/domain/agent/integration/__init__.py +29 -0
- aiecs/domain/agent/integration/context_compressor.py +216 -0
- aiecs/domain/agent/integration/context_engine_adapter.py +587 -0
- aiecs/domain/agent/integration/protocols.py +281 -0
- aiecs/domain/agent/integration/retry_policy.py +218 -0
- aiecs/domain/agent/integration/role_config.py +213 -0
- aiecs/domain/agent/knowledge_aware_agent.py +1892 -0
- aiecs/domain/agent/lifecycle.py +291 -0
- aiecs/domain/agent/llm_agent.py +692 -0
- aiecs/domain/agent/memory/__init__.py +12 -0
- aiecs/domain/agent/memory/conversation.py +1124 -0
- aiecs/domain/agent/migration/__init__.py +14 -0
- aiecs/domain/agent/migration/conversion.py +163 -0
- aiecs/domain/agent/migration/legacy_wrapper.py +86 -0
- aiecs/domain/agent/models.py +884 -0
- aiecs/domain/agent/observability.py +479 -0
- aiecs/domain/agent/persistence.py +449 -0
- aiecs/domain/agent/prompts/__init__.py +29 -0
- aiecs/domain/agent/prompts/builder.py +159 -0
- aiecs/domain/agent/prompts/formatters.py +187 -0
- aiecs/domain/agent/prompts/template.py +255 -0
- aiecs/domain/agent/registry.py +253 -0
- aiecs/domain/agent/tool_agent.py +444 -0
- aiecs/domain/agent/tools/__init__.py +15 -0
- aiecs/domain/agent/tools/schema_generator.py +364 -0
- aiecs/domain/community/__init__.py +155 -0
- aiecs/domain/community/agent_adapter.py +469 -0
- aiecs/domain/community/analytics.py +432 -0
- aiecs/domain/community/collaborative_workflow.py +648 -0
- aiecs/domain/community/communication_hub.py +634 -0
- aiecs/domain/community/community_builder.py +320 -0
- aiecs/domain/community/community_integration.py +796 -0
- aiecs/domain/community/community_manager.py +803 -0
- aiecs/domain/community/decision_engine.py +849 -0
- aiecs/domain/community/exceptions.py +231 -0
- aiecs/domain/community/models/__init__.py +33 -0
- aiecs/domain/community/models/community_models.py +234 -0
- aiecs/domain/community/resource_manager.py +461 -0
- aiecs/domain/community/shared_context_manager.py +589 -0
- aiecs/domain/context/__init__.py +40 -10
- aiecs/domain/context/context_engine.py +1910 -0
- aiecs/domain/context/conversation_models.py +87 -53
- aiecs/domain/context/graph_memory.py +582 -0
- aiecs/domain/execution/model.py +12 -4
- aiecs/domain/knowledge_graph/__init__.py +19 -0
- aiecs/domain/knowledge_graph/models/__init__.py +52 -0
- aiecs/domain/knowledge_graph/models/entity.py +148 -0
- aiecs/domain/knowledge_graph/models/evidence.py +178 -0
- aiecs/domain/knowledge_graph/models/inference_rule.py +184 -0
- aiecs/domain/knowledge_graph/models/path.py +171 -0
- aiecs/domain/knowledge_graph/models/path_pattern.py +171 -0
- aiecs/domain/knowledge_graph/models/query.py +261 -0
- aiecs/domain/knowledge_graph/models/query_plan.py +181 -0
- aiecs/domain/knowledge_graph/models/relation.py +202 -0
- aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
- aiecs/domain/knowledge_graph/schema/entity_type.py +131 -0
- aiecs/domain/knowledge_graph/schema/graph_schema.py +253 -0
- aiecs/domain/knowledge_graph/schema/property_schema.py +143 -0
- aiecs/domain/knowledge_graph/schema/relation_type.py +163 -0
- aiecs/domain/knowledge_graph/schema/schema_manager.py +691 -0
- aiecs/domain/knowledge_graph/schema/type_enums.py +209 -0
- aiecs/domain/task/dsl_processor.py +172 -56
- aiecs/domain/task/model.py +20 -8
- aiecs/domain/task/task_context.py +27 -24
- aiecs/infrastructure/__init__.py +0 -2
- aiecs/infrastructure/graph_storage/__init__.py +11 -0
- aiecs/infrastructure/graph_storage/base.py +837 -0
- aiecs/infrastructure/graph_storage/batch_operations.py +458 -0
- aiecs/infrastructure/graph_storage/cache.py +424 -0
- aiecs/infrastructure/graph_storage/distributed.py +223 -0
- aiecs/infrastructure/graph_storage/error_handling.py +380 -0
- aiecs/infrastructure/graph_storage/graceful_degradation.py +294 -0
- aiecs/infrastructure/graph_storage/health_checks.py +378 -0
- aiecs/infrastructure/graph_storage/in_memory.py +1197 -0
- aiecs/infrastructure/graph_storage/index_optimization.py +446 -0
- aiecs/infrastructure/graph_storage/lazy_loading.py +431 -0
- aiecs/infrastructure/graph_storage/metrics.py +344 -0
- aiecs/infrastructure/graph_storage/migration.py +400 -0
- aiecs/infrastructure/graph_storage/pagination.py +483 -0
- aiecs/infrastructure/graph_storage/performance_monitoring.py +456 -0
- aiecs/infrastructure/graph_storage/postgres.py +1563 -0
- aiecs/infrastructure/graph_storage/property_storage.py +353 -0
- aiecs/infrastructure/graph_storage/protocols.py +76 -0
- aiecs/infrastructure/graph_storage/query_optimizer.py +642 -0
- aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
- aiecs/infrastructure/graph_storage/sqlite.py +1373 -0
- aiecs/infrastructure/graph_storage/streaming.py +487 -0
- aiecs/infrastructure/graph_storage/tenant.py +412 -0
- aiecs/infrastructure/messaging/celery_task_manager.py +92 -54
- aiecs/infrastructure/messaging/websocket_manager.py +51 -35
- aiecs/infrastructure/monitoring/__init__.py +22 -0
- aiecs/infrastructure/monitoring/executor_metrics.py +45 -11
- aiecs/infrastructure/monitoring/global_metrics_manager.py +212 -0
- aiecs/infrastructure/monitoring/structured_logger.py +3 -7
- aiecs/infrastructure/monitoring/tracing_manager.py +63 -35
- aiecs/infrastructure/persistence/__init__.py +14 -1
- aiecs/infrastructure/persistence/context_engine_client.py +184 -0
- aiecs/infrastructure/persistence/database_manager.py +67 -43
- aiecs/infrastructure/persistence/file_storage.py +180 -103
- aiecs/infrastructure/persistence/redis_client.py +74 -21
- aiecs/llm/__init__.py +73 -25
- aiecs/llm/callbacks/__init__.py +11 -0
- aiecs/llm/{custom_callbacks.py → callbacks/custom_callbacks.py} +26 -19
- aiecs/llm/client_factory.py +224 -36
- aiecs/llm/client_resolver.py +155 -0
- aiecs/llm/clients/__init__.py +38 -0
- aiecs/llm/clients/base_client.py +324 -0
- aiecs/llm/clients/google_function_calling_mixin.py +457 -0
- aiecs/llm/clients/googleai_client.py +241 -0
- aiecs/llm/clients/openai_client.py +158 -0
- aiecs/llm/clients/openai_compatible_mixin.py +367 -0
- aiecs/llm/clients/vertex_client.py +897 -0
- aiecs/llm/clients/xai_client.py +201 -0
- aiecs/llm/config/__init__.py +51 -0
- aiecs/llm/config/config_loader.py +272 -0
- aiecs/llm/config/config_validator.py +206 -0
- aiecs/llm/config/model_config.py +143 -0
- aiecs/llm/protocols.py +149 -0
- aiecs/llm/utils/__init__.py +10 -0
- aiecs/llm/utils/validate_config.py +89 -0
- aiecs/main.py +140 -121
- aiecs/scripts/aid/VERSION_MANAGEMENT.md +138 -0
- aiecs/scripts/aid/__init__.py +19 -0
- aiecs/scripts/aid/module_checker.py +499 -0
- aiecs/scripts/aid/version_manager.py +235 -0
- aiecs/scripts/{DEPENDENCY_SYSTEM_SUMMARY.md → dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md} +1 -0
- aiecs/scripts/{README_DEPENDENCY_CHECKER.md → dependance_check/README_DEPENDENCY_CHECKER.md} +1 -0
- aiecs/scripts/dependance_check/__init__.py +15 -0
- aiecs/scripts/dependance_check/dependency_checker.py +1835 -0
- aiecs/scripts/{dependency_fixer.py → dependance_check/dependency_fixer.py} +192 -90
- aiecs/scripts/{download_nlp_data.py → dependance_check/download_nlp_data.py} +203 -71
- aiecs/scripts/dependance_patch/__init__.py +7 -0
- aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
- aiecs/scripts/{fix_weasel_validator.py → dependance_patch/fix_weasel/fix_weasel_validator.py} +21 -14
- aiecs/scripts/{patch_weasel_library.sh → dependance_patch/fix_weasel/patch_weasel_library.sh} +1 -1
- aiecs/scripts/knowledge_graph/__init__.py +3 -0
- aiecs/scripts/knowledge_graph/run_threshold_experiments.py +212 -0
- aiecs/scripts/migrations/multi_tenancy/README.md +142 -0
- aiecs/scripts/tools_develop/README.md +671 -0
- aiecs/scripts/tools_develop/README_CONFIG_CHECKER.md +273 -0
- aiecs/scripts/tools_develop/TOOLS_CONFIG_GUIDE.md +1287 -0
- aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
- aiecs/scripts/tools_develop/__init__.py +21 -0
- aiecs/scripts/tools_develop/check_all_tools_config.py +548 -0
- aiecs/scripts/tools_develop/check_type_annotations.py +257 -0
- aiecs/scripts/tools_develop/pre-commit-schema-coverage.sh +66 -0
- aiecs/scripts/tools_develop/schema_coverage.py +511 -0
- aiecs/scripts/tools_develop/validate_tool_schemas.py +475 -0
- aiecs/scripts/tools_develop/verify_executor_config_fix.py +98 -0
- aiecs/scripts/tools_develop/verify_tools.py +352 -0
- aiecs/tasks/__init__.py +0 -1
- aiecs/tasks/worker.py +115 -47
- aiecs/tools/__init__.py +194 -72
- aiecs/tools/apisource/__init__.py +99 -0
- aiecs/tools/apisource/intelligence/__init__.py +19 -0
- aiecs/tools/apisource/intelligence/data_fusion.py +632 -0
- aiecs/tools/apisource/intelligence/query_analyzer.py +417 -0
- aiecs/tools/apisource/intelligence/search_enhancer.py +385 -0
- aiecs/tools/apisource/monitoring/__init__.py +9 -0
- aiecs/tools/apisource/monitoring/metrics.py +330 -0
- aiecs/tools/apisource/providers/__init__.py +112 -0
- aiecs/tools/apisource/providers/base.py +671 -0
- aiecs/tools/apisource/providers/census.py +397 -0
- aiecs/tools/apisource/providers/fred.py +535 -0
- aiecs/tools/apisource/providers/newsapi.py +409 -0
- aiecs/tools/apisource/providers/worldbank.py +352 -0
- aiecs/tools/apisource/reliability/__init__.py +12 -0
- aiecs/tools/apisource/reliability/error_handler.py +363 -0
- aiecs/tools/apisource/reliability/fallback_strategy.py +376 -0
- aiecs/tools/apisource/tool.py +832 -0
- aiecs/tools/apisource/utils/__init__.py +9 -0
- aiecs/tools/apisource/utils/validators.py +334 -0
- aiecs/tools/base_tool.py +415 -21
- aiecs/tools/docs/__init__.py +121 -0
- aiecs/tools/docs/ai_document_orchestrator.py +607 -0
- aiecs/tools/docs/ai_document_writer_orchestrator.py +2350 -0
- aiecs/tools/docs/content_insertion_tool.py +1320 -0
- aiecs/tools/docs/document_creator_tool.py +1323 -0
- aiecs/tools/docs/document_layout_tool.py +1160 -0
- aiecs/tools/docs/document_parser_tool.py +1011 -0
- aiecs/tools/docs/document_writer_tool.py +1829 -0
- aiecs/tools/knowledge_graph/__init__.py +17 -0
- aiecs/tools/knowledge_graph/graph_reasoning_tool.py +807 -0
- aiecs/tools/knowledge_graph/graph_search_tool.py +944 -0
- aiecs/tools/knowledge_graph/kg_builder_tool.py +524 -0
- aiecs/tools/langchain_adapter.py +300 -138
- aiecs/tools/schema_generator.py +455 -0
- aiecs/tools/search_tool/__init__.py +100 -0
- aiecs/tools/search_tool/analyzers.py +581 -0
- aiecs/tools/search_tool/cache.py +264 -0
- aiecs/tools/search_tool/constants.py +128 -0
- aiecs/tools/search_tool/context.py +224 -0
- aiecs/tools/search_tool/core.py +778 -0
- aiecs/tools/search_tool/deduplicator.py +119 -0
- aiecs/tools/search_tool/error_handler.py +242 -0
- aiecs/tools/search_tool/metrics.py +343 -0
- aiecs/tools/search_tool/rate_limiter.py +172 -0
- aiecs/tools/search_tool/schemas.py +275 -0
- aiecs/tools/statistics/__init__.py +80 -0
- aiecs/tools/statistics/ai_data_analysis_orchestrator.py +646 -0
- aiecs/tools/statistics/ai_insight_generator_tool.py +508 -0
- aiecs/tools/statistics/ai_report_orchestrator_tool.py +684 -0
- aiecs/tools/statistics/data_loader_tool.py +555 -0
- aiecs/tools/statistics/data_profiler_tool.py +638 -0
- aiecs/tools/statistics/data_transformer_tool.py +580 -0
- aiecs/tools/statistics/data_visualizer_tool.py +498 -0
- aiecs/tools/statistics/model_trainer_tool.py +507 -0
- aiecs/tools/statistics/statistical_analyzer_tool.py +472 -0
- aiecs/tools/task_tools/__init__.py +49 -36
- aiecs/tools/task_tools/chart_tool.py +200 -184
- aiecs/tools/task_tools/classfire_tool.py +268 -267
- aiecs/tools/task_tools/image_tool.py +175 -131
- aiecs/tools/task_tools/office_tool.py +226 -146
- aiecs/tools/task_tools/pandas_tool.py +477 -121
- aiecs/tools/task_tools/report_tool.py +390 -142
- aiecs/tools/task_tools/research_tool.py +149 -79
- aiecs/tools/task_tools/scraper_tool.py +339 -145
- aiecs/tools/task_tools/stats_tool.py +448 -209
- aiecs/tools/temp_file_manager.py +26 -24
- aiecs/tools/tool_executor/__init__.py +18 -16
- aiecs/tools/tool_executor/tool_executor.py +364 -52
- aiecs/utils/LLM_output_structor.py +74 -48
- aiecs/utils/__init__.py +14 -3
- aiecs/utils/base_callback.py +0 -3
- aiecs/utils/cache_provider.py +696 -0
- aiecs/utils/execution_utils.py +50 -31
- aiecs/utils/prompt_loader.py +1 -0
- aiecs/utils/token_usage_repository.py +37 -11
- aiecs/ws/socket_server.py +14 -4
- {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/METADATA +52 -15
- aiecs-1.7.6.dist-info/RECORD +337 -0
- aiecs-1.7.6.dist-info/entry_points.txt +13 -0
- aiecs/config/registry.py +0 -19
- aiecs/domain/context/content_engine.py +0 -982
- aiecs/llm/base_client.py +0 -99
- aiecs/llm/openai_client.py +0 -125
- aiecs/llm/vertex_client.py +0 -186
- aiecs/llm/xai_client.py +0 -184
- aiecs/scripts/dependency_checker.py +0 -857
- aiecs/scripts/quick_dependency_check.py +0 -269
- aiecs/tools/task_tools/search_api.py +0 -7
- aiecs-1.0.1.dist-info/RECORD +0 -90
- aiecs-1.0.1.dist-info/entry_points.txt +0 -7
- /aiecs/scripts/{setup_nlp_data.sh → dependance_check/setup_nlp_data.sh} +0 -0
- /aiecs/scripts/{README_WEASEL_PATCH.md → dependance_patch/fix_weasel/README_WEASEL_PATCH.md} +0 -0
- /aiecs/scripts/{fix_weasel_validator.sh → dependance_patch/fix_weasel/fix_weasel_validator.sh} +0 -0
- /aiecs/scripts/{run_weasel_patch.sh → dependance_patch/fix_weasel/run_weasel_patch.sh} +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/WHEEL +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/licenses/LICENSE +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Agent Integration Protocols
|
|
3
|
+
|
|
4
|
+
Defines Protocol interfaces for agent integrations to enable duck typing and flexible integration.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Protocol, Dict, Any, Optional, runtime_checkable, List
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@runtime_checkable
|
|
11
|
+
class ConfigManagerProtocol(Protocol):
|
|
12
|
+
"""
|
|
13
|
+
Protocol for custom configuration managers.
|
|
14
|
+
|
|
15
|
+
This protocol defines the interface for configuration managers that can
|
|
16
|
+
provide dynamic configuration to agents from external sources (databases,
|
|
17
|
+
config servers, environment variables, etc.).
|
|
18
|
+
|
|
19
|
+
Example:
|
|
20
|
+
```python
|
|
21
|
+
class DatabaseConfigManager:
|
|
22
|
+
async def get_config(self, key: str, default: Any = None) -> Any:
|
|
23
|
+
# Fetch from database
|
|
24
|
+
return await db.get_config(key, default)
|
|
25
|
+
|
|
26
|
+
async def set_config(self, key: str, value: Any) -> None:
|
|
27
|
+
# Save to database
|
|
28
|
+
await db.set_config(key, value)
|
|
29
|
+
|
|
30
|
+
async def reload_config(self) -> None:
|
|
31
|
+
# Refresh cache
|
|
32
|
+
await db.refresh_cache()
|
|
33
|
+
|
|
34
|
+
# Use with agents
|
|
35
|
+
agent = HybridAgent(
|
|
36
|
+
config_manager=DatabaseConfigManager(),
|
|
37
|
+
...
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
async def get_config(self, key: str, default: Any = None) -> Any:
|
|
43
|
+
"""
|
|
44
|
+
Get configuration value by key.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
key: Configuration key
|
|
48
|
+
default: Default value if key not found
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Configuration value or default
|
|
52
|
+
"""
|
|
53
|
+
...
|
|
54
|
+
|
|
55
|
+
async def set_config(self, key: str, value: Any) -> None:
|
|
56
|
+
"""
|
|
57
|
+
Set configuration value.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
key: Configuration key
|
|
61
|
+
value: Configuration value
|
|
62
|
+
"""
|
|
63
|
+
...
|
|
64
|
+
|
|
65
|
+
async def reload_config(self) -> None:
|
|
66
|
+
"""
|
|
67
|
+
Reload configuration from source.
|
|
68
|
+
|
|
69
|
+
This method should refresh any cached configuration data.
|
|
70
|
+
"""
|
|
71
|
+
...
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@runtime_checkable
|
|
75
|
+
class CheckpointerProtocol(Protocol):
|
|
76
|
+
"""
|
|
77
|
+
Protocol for custom checkpointers.
|
|
78
|
+
|
|
79
|
+
This protocol defines the interface for checkpointers that can save and
|
|
80
|
+
load agent state for persistence and recovery. Compatible with LangGraph
|
|
81
|
+
checkpointing patterns.
|
|
82
|
+
|
|
83
|
+
Example:
|
|
84
|
+
```python
|
|
85
|
+
class RedisCheckpointer:
|
|
86
|
+
async def save_checkpoint(
|
|
87
|
+
self,
|
|
88
|
+
agent_id: str,
|
|
89
|
+
session_id: str,
|
|
90
|
+
checkpoint_data: Dict[str, Any]
|
|
91
|
+
) -> str:
|
|
92
|
+
# Save to Redis
|
|
93
|
+
checkpoint_id = str(uuid.uuid4())
|
|
94
|
+
await redis.set(f"checkpoint:{checkpoint_id}", json.dumps(checkpoint_data))
|
|
95
|
+
return checkpoint_id
|
|
96
|
+
|
|
97
|
+
async def load_checkpoint(
|
|
98
|
+
self,
|
|
99
|
+
agent_id: str,
|
|
100
|
+
session_id: str,
|
|
101
|
+
checkpoint_id: Optional[str] = None
|
|
102
|
+
) -> Optional[Dict[str, Any]]:
|
|
103
|
+
# Load from Redis
|
|
104
|
+
if checkpoint_id:
|
|
105
|
+
data = await redis.get(f"checkpoint:{checkpoint_id}")
|
|
106
|
+
return json.loads(data) if data else None
|
|
107
|
+
# Load latest
|
|
108
|
+
return await self._load_latest(agent_id, session_id)
|
|
109
|
+
|
|
110
|
+
async def list_checkpoints(
|
|
111
|
+
self,
|
|
112
|
+
agent_id: str,
|
|
113
|
+
session_id: str
|
|
114
|
+
) -> list[str]:
|
|
115
|
+
# List all checkpoint IDs
|
|
116
|
+
return await redis.keys(f"checkpoint:{agent_id}:{session_id}:*")
|
|
117
|
+
|
|
118
|
+
# Use with agents
|
|
119
|
+
agent = HybridAgent(
|
|
120
|
+
checkpointer=RedisCheckpointer(),
|
|
121
|
+
...
|
|
122
|
+
)
|
|
123
|
+
```
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
async def save_checkpoint(self, agent_id: str, session_id: str, checkpoint_data: Dict[str, Any]) -> str:
|
|
127
|
+
"""
|
|
128
|
+
Save checkpoint and return checkpoint ID.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
agent_id: Agent identifier
|
|
132
|
+
session_id: Session identifier
|
|
133
|
+
checkpoint_data: Checkpoint data to save
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Checkpoint ID for later retrieval
|
|
137
|
+
"""
|
|
138
|
+
...
|
|
139
|
+
|
|
140
|
+
async def load_checkpoint(self, agent_id: str, session_id: str, checkpoint_id: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
|
141
|
+
"""
|
|
142
|
+
Load checkpoint data.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
agent_id: Agent identifier
|
|
146
|
+
session_id: Session identifier
|
|
147
|
+
checkpoint_id: Specific checkpoint ID (loads latest if None)
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Checkpoint data or None if not found
|
|
151
|
+
"""
|
|
152
|
+
...
|
|
153
|
+
|
|
154
|
+
async def list_checkpoints(self, agent_id: str, session_id: str) -> list[str]:
|
|
155
|
+
"""
|
|
156
|
+
List all checkpoint IDs for a session.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
agent_id: Agent identifier
|
|
160
|
+
session_id: Session identifier
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
List of checkpoint IDs
|
|
164
|
+
"""
|
|
165
|
+
...
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@runtime_checkable
|
|
169
|
+
class AgentCollaborationProtocol(Protocol):
|
|
170
|
+
"""
|
|
171
|
+
Protocol for agent collaboration.
|
|
172
|
+
|
|
173
|
+
This protocol defines the interface for agents that can collaborate with
|
|
174
|
+
other agents through task delegation, peer review, and consensus-based
|
|
175
|
+
decision making. Enables multi-agent workflows and distributed task execution.
|
|
176
|
+
|
|
177
|
+
**Key Features:**
|
|
178
|
+
- Task delegation to capable agents
|
|
179
|
+
- Peer review of task results
|
|
180
|
+
- Consensus-based decision making
|
|
181
|
+
- Capability-based agent discovery
|
|
182
|
+
- Multi-agent parallel execution
|
|
183
|
+
|
|
184
|
+
**Required Attributes:**
|
|
185
|
+
- agent_id: Unique identifier for the agent
|
|
186
|
+
- name: Human-readable agent name
|
|
187
|
+
- capabilities: List of capability strings (e.g., ["search", "analysis"])
|
|
188
|
+
|
|
189
|
+
**Required Methods:**
|
|
190
|
+
- execute_task: Execute a task and return result
|
|
191
|
+
- review_result: Review another agent's task result
|
|
192
|
+
|
|
193
|
+
Examples:
|
|
194
|
+
# Example 1: Basic collaborative agent implementation
|
|
195
|
+
class CollaborativeAgent(BaseAIAgent):
|
|
196
|
+
agent_id: str
|
|
197
|
+
name: str
|
|
198
|
+
capabilities: List[str]
|
|
199
|
+
|
|
200
|
+
async def execute_task(
|
|
201
|
+
self, task: Dict[str, Any], context: Dict[str, Any]
|
|
202
|
+
) -> Dict[str, Any]:
|
|
203
|
+
# Execute task
|
|
204
|
+
return {"success": True, "output": "result"}
|
|
205
|
+
|
|
206
|
+
async def review_result(
|
|
207
|
+
self, task: Dict[str, Any], result: Dict[str, Any]
|
|
208
|
+
) -> Dict[str, Any]:
|
|
209
|
+
# Review another agent's result
|
|
210
|
+
return {"approved": True, "feedback": "Looks good"}
|
|
211
|
+
|
|
212
|
+
# Example 2: Using with agent registry
|
|
213
|
+
registry = {
|
|
214
|
+
"agent1": CollaborativeAgent(
|
|
215
|
+
agent_id="agent1",
|
|
216
|
+
name="Search Agent",
|
|
217
|
+
capabilities=["search", "web_scraping"]
|
|
218
|
+
),
|
|
219
|
+
"agent2": CollaborativeAgent(
|
|
220
|
+
agent_id="agent2",
|
|
221
|
+
name="Analysis Agent",
|
|
222
|
+
capabilities=["data_analysis", "statistics"]
|
|
223
|
+
),
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
agent = HybridAgent(
|
|
227
|
+
collaboration_enabled=True,
|
|
228
|
+
agent_registry=registry,
|
|
229
|
+
...
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
# Example 3: Delegate task to capable agent
|
|
233
|
+
result = await agent.delegate_task(
|
|
234
|
+
task_description="Search for recent AI papers",
|
|
235
|
+
required_capabilities=["search"]
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
# Example 4: Request peer review
|
|
239
|
+
review = await agent.request_peer_review(
|
|
240
|
+
task=task,
|
|
241
|
+
result=result,
|
|
242
|
+
reviewer_agent_id="agent2"
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# Example 5: Multi-agent collaboration
|
|
246
|
+
result = await agent.collaborate_on_task(
|
|
247
|
+
task=task,
|
|
248
|
+
strategy="parallel", # Execute in parallel
|
|
249
|
+
required_capabilities=["search", "analysis"]
|
|
250
|
+
)
|
|
251
|
+
"""
|
|
252
|
+
|
|
253
|
+
agent_id: str
|
|
254
|
+
name: str
|
|
255
|
+
capabilities: List[str]
|
|
256
|
+
|
|
257
|
+
async def execute_task(self, task: Dict[str, Any], context: Dict[str, Any]) -> Dict[str, Any]:
|
|
258
|
+
"""
|
|
259
|
+
Execute a task.
|
|
260
|
+
|
|
261
|
+
Args:
|
|
262
|
+
task: Task specification
|
|
263
|
+
context: Execution context
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
Task execution result
|
|
267
|
+
"""
|
|
268
|
+
...
|
|
269
|
+
|
|
270
|
+
async def review_result(self, task: Dict[str, Any], result: Dict[str, Any]) -> Dict[str, Any]:
|
|
271
|
+
"""
|
|
272
|
+
Review another agent's task result.
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
task: Original task specification
|
|
276
|
+
result: Task execution result to review
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
Review result with 'approved' (bool) and 'feedback' (str)
|
|
280
|
+
"""
|
|
281
|
+
...
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Enhanced Retry Policy
|
|
3
|
+
|
|
4
|
+
Sophisticated retry logic with exponential backoff and error classification.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import random
|
|
9
|
+
import logging
|
|
10
|
+
from typing import Callable, Any
|
|
11
|
+
from enum import Enum
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ErrorType(Enum):
|
|
17
|
+
"""Error types for classification."""
|
|
18
|
+
|
|
19
|
+
RATE_LIMIT = "rate_limit"
|
|
20
|
+
TIMEOUT = "timeout"
|
|
21
|
+
SERVER_ERROR = "server_error"
|
|
22
|
+
CLIENT_ERROR = "client_error"
|
|
23
|
+
NETWORK_ERROR = "network_error"
|
|
24
|
+
UNKNOWN = "unknown"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ErrorClassifier:
|
|
28
|
+
"""Classifies errors for retry strategy."""
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def classify(error: Exception) -> ErrorType:
|
|
32
|
+
"""
|
|
33
|
+
Classify error type.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
error: Exception to classify
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
ErrorType
|
|
40
|
+
"""
|
|
41
|
+
error_str = str(error).lower()
|
|
42
|
+
error_type_name = type(error).__name__.lower()
|
|
43
|
+
|
|
44
|
+
# Rate limit errors
|
|
45
|
+
if "rate limit" in error_str or "429" in error_str:
|
|
46
|
+
return ErrorType.RATE_LIMIT
|
|
47
|
+
|
|
48
|
+
# Timeout errors
|
|
49
|
+
if "timeout" in error_str or "timed out" in error_str:
|
|
50
|
+
return ErrorType.TIMEOUT
|
|
51
|
+
|
|
52
|
+
# Server errors (5xx)
|
|
53
|
+
if any(code in error_str for code in ["500", "502", "503", "504"]):
|
|
54
|
+
return ErrorType.SERVER_ERROR
|
|
55
|
+
|
|
56
|
+
# Client errors (4xx)
|
|
57
|
+
if any(code in error_str for code in ["400", "401", "403", "404"]):
|
|
58
|
+
return ErrorType.CLIENT_ERROR
|
|
59
|
+
|
|
60
|
+
# Network errors
|
|
61
|
+
if any(term in error_type_name for term in ["connection", "network", "socket"]):
|
|
62
|
+
return ErrorType.NETWORK_ERROR
|
|
63
|
+
|
|
64
|
+
return ErrorType.UNKNOWN
|
|
65
|
+
|
|
66
|
+
@staticmethod
|
|
67
|
+
def is_retryable(error_type: ErrorType) -> bool:
|
|
68
|
+
"""
|
|
69
|
+
Determine if error type should be retried.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
error_type: Error type
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
True if retryable
|
|
76
|
+
"""
|
|
77
|
+
retryable_types = {
|
|
78
|
+
ErrorType.RATE_LIMIT,
|
|
79
|
+
ErrorType.TIMEOUT,
|
|
80
|
+
ErrorType.SERVER_ERROR,
|
|
81
|
+
ErrorType.NETWORK_ERROR,
|
|
82
|
+
}
|
|
83
|
+
return error_type in retryable_types
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class EnhancedRetryPolicy:
|
|
87
|
+
"""
|
|
88
|
+
Enhanced retry policy with exponential backoff and jitter.
|
|
89
|
+
|
|
90
|
+
Example:
|
|
91
|
+
policy = EnhancedRetryPolicy(max_retries=5, base_delay=1.0)
|
|
92
|
+
result = await policy.execute_with_retry(my_async_function, arg1, arg2)
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
def __init__(
|
|
96
|
+
self,
|
|
97
|
+
max_retries: int = 3,
|
|
98
|
+
base_delay: float = 1.0,
|
|
99
|
+
max_delay: float = 60.0,
|
|
100
|
+
exponential_base: float = 2.0,
|
|
101
|
+
jitter: bool = True,
|
|
102
|
+
):
|
|
103
|
+
"""
|
|
104
|
+
Initialize retry policy.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
max_retries: Maximum number of retry attempts
|
|
108
|
+
base_delay: Base delay in seconds
|
|
109
|
+
max_delay: Maximum delay in seconds
|
|
110
|
+
exponential_base: Base for exponential backoff
|
|
111
|
+
jitter: Whether to add random jitter
|
|
112
|
+
"""
|
|
113
|
+
self.max_retries = max_retries
|
|
114
|
+
self.base_delay = base_delay
|
|
115
|
+
self.max_delay = max_delay
|
|
116
|
+
self.exponential_base = exponential_base
|
|
117
|
+
self.jitter = jitter
|
|
118
|
+
|
|
119
|
+
def calculate_delay(self, attempt: int, error_type: ErrorType) -> float:
|
|
120
|
+
"""
|
|
121
|
+
Calculate delay for retry attempt.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
attempt: Retry attempt number (0-indexed)
|
|
125
|
+
error_type: Type of error
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Delay in seconds
|
|
129
|
+
"""
|
|
130
|
+
# Base exponential backoff
|
|
131
|
+
delay = min(self.base_delay * (self.exponential_base**attempt), self.max_delay)
|
|
132
|
+
|
|
133
|
+
# Adjust for error type
|
|
134
|
+
if error_type == ErrorType.RATE_LIMIT:
|
|
135
|
+
# Longer delay for rate limits
|
|
136
|
+
delay *= 2
|
|
137
|
+
|
|
138
|
+
# Add jitter to prevent thundering herd
|
|
139
|
+
if self.jitter:
|
|
140
|
+
delay *= 0.5 + random.random()
|
|
141
|
+
|
|
142
|
+
return delay
|
|
143
|
+
|
|
144
|
+
async def execute_with_retry(self, func: Callable, *args, **kwargs) -> Any:
|
|
145
|
+
"""
|
|
146
|
+
Execute function with retry logic.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
func: Async function to execute
|
|
150
|
+
*args: Function arguments
|
|
151
|
+
**kwargs: Function keyword arguments
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
Function result
|
|
155
|
+
|
|
156
|
+
Raises:
|
|
157
|
+
Exception: If all retries exhausted
|
|
158
|
+
"""
|
|
159
|
+
last_error = None
|
|
160
|
+
|
|
161
|
+
for attempt in range(self.max_retries + 1):
|
|
162
|
+
try:
|
|
163
|
+
result = await func(*args, **kwargs)
|
|
164
|
+
|
|
165
|
+
# Log success after retries
|
|
166
|
+
if attempt > 0:
|
|
167
|
+
logger.info(f"Succeeded after {attempt} retries")
|
|
168
|
+
|
|
169
|
+
return result
|
|
170
|
+
|
|
171
|
+
except Exception as e:
|
|
172
|
+
last_error = e
|
|
173
|
+
|
|
174
|
+
# Classify error
|
|
175
|
+
error_type = ErrorClassifier.classify(e)
|
|
176
|
+
|
|
177
|
+
# Check if we should retry
|
|
178
|
+
if attempt >= self.max_retries:
|
|
179
|
+
logger.error(f"Max retries ({self.max_retries}) exhausted")
|
|
180
|
+
break
|
|
181
|
+
|
|
182
|
+
if not ErrorClassifier.is_retryable(error_type):
|
|
183
|
+
logger.error(f"Non-retryable error: {error_type.value}")
|
|
184
|
+
break
|
|
185
|
+
|
|
186
|
+
# Calculate delay and wait
|
|
187
|
+
delay = self.calculate_delay(attempt, error_type)
|
|
188
|
+
logger.warning(f"Attempt {attempt + 1} failed ({error_type.value}). " f"Retrying in {delay:.2f}s...")
|
|
189
|
+
await asyncio.sleep(delay)
|
|
190
|
+
|
|
191
|
+
# All retries exhausted
|
|
192
|
+
if last_error is None:
|
|
193
|
+
raise RuntimeError("Retry failed but no error was captured")
|
|
194
|
+
raise last_error
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
async def with_retry(
|
|
198
|
+
func: Callable,
|
|
199
|
+
max_retries: int = 3,
|
|
200
|
+
base_delay: float = 1.0,
|
|
201
|
+
*args,
|
|
202
|
+
**kwargs,
|
|
203
|
+
) -> Any:
|
|
204
|
+
"""
|
|
205
|
+
Convenience function for executing with retry.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
func: Async function to execute
|
|
209
|
+
max_retries: Maximum number of retries
|
|
210
|
+
base_delay: Base delay in seconds
|
|
211
|
+
*args: Function arguments
|
|
212
|
+
**kwargs: Function keyword arguments
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
Function result
|
|
216
|
+
"""
|
|
217
|
+
policy = EnhancedRetryPolicy(max_retries=max_retries, base_delay=base_delay)
|
|
218
|
+
return await policy.execute_with_retry(func, *args, **kwargs)
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Role-Based Configuration
|
|
3
|
+
|
|
4
|
+
Load agent configuration from role templates.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import yaml # type: ignore[import-untyped]
|
|
9
|
+
from typing import Dict, Any, Optional
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from ..models import AgentConfiguration
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class RoleConfiguration:
|
|
18
|
+
"""
|
|
19
|
+
Manages role-based agent configurations.
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
role_config = RoleConfiguration.load_from_file("roles/developer.yaml")
|
|
23
|
+
agent_config = role_config.to_agent_config()
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
role_name: str,
|
|
29
|
+
goal: Optional[str] = None,
|
|
30
|
+
backstory: Optional[str] = None,
|
|
31
|
+
domain_knowledge: Optional[str] = None,
|
|
32
|
+
llm_model: Optional[str] = None,
|
|
33
|
+
temperature: float = 0.7,
|
|
34
|
+
max_tokens: Optional[int] = None,
|
|
35
|
+
tools: Optional[list] = None,
|
|
36
|
+
**kwargs,
|
|
37
|
+
):
|
|
38
|
+
"""
|
|
39
|
+
Initialize role configuration.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
role_name: Role name
|
|
43
|
+
goal: Agent goal
|
|
44
|
+
backstory: Agent backstory
|
|
45
|
+
domain_knowledge: Domain knowledge
|
|
46
|
+
llm_model: LLM model to use
|
|
47
|
+
temperature: LLM temperature
|
|
48
|
+
max_tokens: Max tokens
|
|
49
|
+
tools: List of tool names
|
|
50
|
+
**kwargs: Additional configuration
|
|
51
|
+
"""
|
|
52
|
+
self.role_name = role_name
|
|
53
|
+
self.goal = goal
|
|
54
|
+
self.backstory = backstory
|
|
55
|
+
self.domain_knowledge = domain_knowledge
|
|
56
|
+
self.llm_model = llm_model
|
|
57
|
+
self.temperature = temperature
|
|
58
|
+
self.max_tokens = max_tokens
|
|
59
|
+
self.tools = tools or []
|
|
60
|
+
self.additional_config = kwargs
|
|
61
|
+
|
|
62
|
+
def to_agent_config(self) -> AgentConfiguration:
|
|
63
|
+
"""
|
|
64
|
+
Convert to AgentConfiguration.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
AgentConfiguration instance
|
|
68
|
+
"""
|
|
69
|
+
return AgentConfiguration( # type: ignore[call-arg]
|
|
70
|
+
goal=self.goal,
|
|
71
|
+
backstory=self.backstory,
|
|
72
|
+
domain_knowledge=self.domain_knowledge,
|
|
73
|
+
llm_model=self.llm_model,
|
|
74
|
+
temperature=self.temperature,
|
|
75
|
+
max_tokens=self.max_tokens if self.max_tokens is not None else 4096, # type: ignore[arg-type]
|
|
76
|
+
**self.additional_config,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def load_from_file(cls, file_path: str) -> "RoleConfiguration":
|
|
81
|
+
"""
|
|
82
|
+
Load role configuration from YAML file.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
file_path: Path to YAML file
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
RoleConfiguration instance
|
|
89
|
+
"""
|
|
90
|
+
path = Path(file_path)
|
|
91
|
+
|
|
92
|
+
if not path.exists():
|
|
93
|
+
raise FileNotFoundError(f"Role configuration file not found: {file_path}")
|
|
94
|
+
|
|
95
|
+
with open(path, "r") as f:
|
|
96
|
+
data = yaml.safe_load(f)
|
|
97
|
+
|
|
98
|
+
logger.info(f"Loaded role configuration from {file_path}")
|
|
99
|
+
return cls(**data)
|
|
100
|
+
|
|
101
|
+
@classmethod
|
|
102
|
+
def load_from_dict(cls, data: Dict[str, Any]) -> "RoleConfiguration":
|
|
103
|
+
"""
|
|
104
|
+
Load role configuration from dictionary.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
data: Configuration dictionary
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
RoleConfiguration instance
|
|
111
|
+
"""
|
|
112
|
+
return cls(**data)
|
|
113
|
+
|
|
114
|
+
def merge_with(self, other: "RoleConfiguration") -> "RoleConfiguration":
|
|
115
|
+
"""
|
|
116
|
+
Merge with another configuration (other takes precedence).
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
other: Other configuration
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
New merged RoleConfiguration
|
|
123
|
+
"""
|
|
124
|
+
merged_data = {
|
|
125
|
+
"role_name": other.role_name or self.role_name,
|
|
126
|
+
"goal": other.goal or self.goal,
|
|
127
|
+
"backstory": other.backstory or self.backstory,
|
|
128
|
+
"domain_knowledge": other.domain_knowledge or self.domain_knowledge,
|
|
129
|
+
"llm_model": other.llm_model or self.llm_model,
|
|
130
|
+
"temperature": (other.temperature if other.temperature != 0.7 else self.temperature),
|
|
131
|
+
"max_tokens": other.max_tokens or self.max_tokens,
|
|
132
|
+
"tools": other.tools if other.tools else self.tools,
|
|
133
|
+
**{**self.additional_config, **other.additional_config},
|
|
134
|
+
}
|
|
135
|
+
return RoleConfiguration(**merged_data)
|
|
136
|
+
|
|
137
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
138
|
+
"""Convert to dictionary."""
|
|
139
|
+
return {
|
|
140
|
+
"role_name": self.role_name,
|
|
141
|
+
"goal": self.goal,
|
|
142
|
+
"backstory": self.backstory,
|
|
143
|
+
"domain_knowledge": self.domain_knowledge,
|
|
144
|
+
"llm_model": self.llm_model,
|
|
145
|
+
"temperature": self.temperature,
|
|
146
|
+
"max_tokens": self.max_tokens,
|
|
147
|
+
"tools": self.tools,
|
|
148
|
+
**self.additional_config,
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def load_role_config(role_name: str, base_path: str = "./agent_roles") -> RoleConfiguration:
|
|
153
|
+
"""
|
|
154
|
+
Load role configuration by name.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
role_name: Role name
|
|
158
|
+
base_path: Base directory for role configurations
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
RoleConfiguration instance
|
|
162
|
+
"""
|
|
163
|
+
file_path = Path(base_path) / f"{role_name}.yaml"
|
|
164
|
+
return RoleConfiguration.load_from_file(str(file_path))
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
# Predefined role templates
|
|
168
|
+
ROLE_TEMPLATES = {
|
|
169
|
+
"developer": {
|
|
170
|
+
"role_name": "developer",
|
|
171
|
+
"goal": "Write clean, efficient, and maintainable code",
|
|
172
|
+
"backstory": ("You are an experienced software developer with expertise in " "multiple programming languages and best practices"),
|
|
173
|
+
"domain_knowledge": "Software development, design patterns, testing, debugging",
|
|
174
|
+
"temperature": 0.3,
|
|
175
|
+
},
|
|
176
|
+
"researcher": {
|
|
177
|
+
"role_name": "researcher",
|
|
178
|
+
"goal": "Gather, analyze, and synthesize information from various sources",
|
|
179
|
+
"backstory": "You are a meticulous researcher skilled at finding and evaluating information",
|
|
180
|
+
"domain_knowledge": "Research methodologies, critical analysis, information synthesis",
|
|
181
|
+
"temperature": 0.5,
|
|
182
|
+
},
|
|
183
|
+
"analyst": {
|
|
184
|
+
"role_name": "analyst",
|
|
185
|
+
"goal": "Analyze data and provide actionable insights",
|
|
186
|
+
"backstory": "You are a data analyst with strong analytical and problem-solving skills",
|
|
187
|
+
"domain_knowledge": "Data analysis, statistics, visualization, interpretation",
|
|
188
|
+
"temperature": 0.4,
|
|
189
|
+
},
|
|
190
|
+
"creative": {
|
|
191
|
+
"role_name": "creative",
|
|
192
|
+
"goal": "Generate creative and innovative ideas",
|
|
193
|
+
"backstory": "You are a creative thinker with a knack for innovative solutions",
|
|
194
|
+
"domain_knowledge": "Creative thinking, brainstorming, innovation",
|
|
195
|
+
"temperature": 0.9,
|
|
196
|
+
},
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def get_role_template(role_name: str) -> RoleConfiguration:
|
|
201
|
+
"""
|
|
202
|
+
Get predefined role template.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
role_name: Role name
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
RoleConfiguration instance
|
|
209
|
+
"""
|
|
210
|
+
if role_name not in ROLE_TEMPLATES:
|
|
211
|
+
raise ValueError(f"Unknown role template: {role_name}")
|
|
212
|
+
|
|
213
|
+
return RoleConfiguration.load_from_dict(ROLE_TEMPLATES[role_name])
|