aiecs 1.5.1__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.
- aiecs/__init__.py +72 -0
- aiecs/__main__.py +41 -0
- aiecs/aiecs_client.py +469 -0
- aiecs/application/__init__.py +10 -0
- aiecs/application/executors/__init__.py +10 -0
- aiecs/application/executors/operation_executor.py +363 -0
- aiecs/application/knowledge_graph/__init__.py +7 -0
- aiecs/application/knowledge_graph/builder/__init__.py +37 -0
- aiecs/application/knowledge_graph/builder/document_builder.py +375 -0
- aiecs/application/knowledge_graph/builder/graph_builder.py +356 -0
- aiecs/application/knowledge_graph/builder/schema_mapping.py +531 -0
- aiecs/application/knowledge_graph/builder/structured_pipeline.py +443 -0
- aiecs/application/knowledge_graph/builder/text_chunker.py +319 -0
- aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
- aiecs/application/knowledge_graph/extractors/base.py +100 -0
- aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +327 -0
- aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +349 -0
- aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +244 -0
- aiecs/application/knowledge_graph/fusion/__init__.py +23 -0
- aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +387 -0
- aiecs/application/knowledge_graph/fusion/entity_linker.py +343 -0
- aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +580 -0
- aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +189 -0
- aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
- aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +344 -0
- aiecs/application/knowledge_graph/pattern_matching/query_executor.py +378 -0
- aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
- aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +199 -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 +347 -0
- aiecs/application/knowledge_graph/reasoning/inference_engine.py +504 -0
- aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +167 -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 +630 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +654 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +477 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +390 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +217 -0
- aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +169 -0
- aiecs/application/knowledge_graph/reasoning/query_planner.py +872 -0
- aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +554 -0
- aiecs/application/knowledge_graph/retrieval/__init__.py +19 -0
- aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +596 -0
- aiecs/application/knowledge_graph/search/__init__.py +59 -0
- aiecs/application/knowledge_graph/search/hybrid_search.py +423 -0
- aiecs/application/knowledge_graph/search/reranker.py +295 -0
- aiecs/application/knowledge_graph/search/reranker_strategies.py +553 -0
- aiecs/application/knowledge_graph/search/text_similarity.py +398 -0
- aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
- aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +329 -0
- aiecs/application/knowledge_graph/traversal/path_scorer.py +269 -0
- aiecs/application/knowledge_graph/validators/__init__.py +13 -0
- aiecs/application/knowledge_graph/validators/relation_validator.py +189 -0
- aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
- aiecs/application/knowledge_graph/visualization/graph_visualizer.py +321 -0
- aiecs/common/__init__.py +9 -0
- aiecs/common/knowledge_graph/__init__.py +17 -0
- aiecs/common/knowledge_graph/runnable.py +484 -0
- aiecs/config/__init__.py +16 -0
- aiecs/config/config.py +498 -0
- aiecs/config/graph_config.py +137 -0
- aiecs/config/registry.py +23 -0
- aiecs/core/__init__.py +46 -0
- aiecs/core/interface/__init__.py +34 -0
- aiecs/core/interface/execution_interface.py +152 -0
- aiecs/core/interface/storage_interface.py +171 -0
- aiecs/domain/__init__.py +289 -0
- aiecs/domain/agent/__init__.py +189 -0
- aiecs/domain/agent/base_agent.py +697 -0
- aiecs/domain/agent/exceptions.py +103 -0
- aiecs/domain/agent/graph_aware_mixin.py +559 -0
- aiecs/domain/agent/hybrid_agent.py +490 -0
- aiecs/domain/agent/integration/__init__.py +26 -0
- aiecs/domain/agent/integration/context_compressor.py +222 -0
- aiecs/domain/agent/integration/context_engine_adapter.py +252 -0
- aiecs/domain/agent/integration/retry_policy.py +219 -0
- aiecs/domain/agent/integration/role_config.py +213 -0
- aiecs/domain/agent/knowledge_aware_agent.py +646 -0
- aiecs/domain/agent/lifecycle.py +296 -0
- aiecs/domain/agent/llm_agent.py +300 -0
- aiecs/domain/agent/memory/__init__.py +12 -0
- aiecs/domain/agent/memory/conversation.py +197 -0
- aiecs/domain/agent/migration/__init__.py +14 -0
- aiecs/domain/agent/migration/conversion.py +160 -0
- aiecs/domain/agent/migration/legacy_wrapper.py +90 -0
- aiecs/domain/agent/models.py +317 -0
- aiecs/domain/agent/observability.py +407 -0
- aiecs/domain/agent/persistence.py +289 -0
- aiecs/domain/agent/prompts/__init__.py +29 -0
- aiecs/domain/agent/prompts/builder.py +161 -0
- aiecs/domain/agent/prompts/formatters.py +189 -0
- aiecs/domain/agent/prompts/template.py +255 -0
- aiecs/domain/agent/registry.py +260 -0
- aiecs/domain/agent/tool_agent.py +257 -0
- aiecs/domain/agent/tools/__init__.py +12 -0
- aiecs/domain/agent/tools/schema_generator.py +221 -0
- aiecs/domain/community/__init__.py +155 -0
- aiecs/domain/community/agent_adapter.py +477 -0
- aiecs/domain/community/analytics.py +481 -0
- aiecs/domain/community/collaborative_workflow.py +642 -0
- aiecs/domain/community/communication_hub.py +645 -0
- aiecs/domain/community/community_builder.py +320 -0
- aiecs/domain/community/community_integration.py +800 -0
- aiecs/domain/community/community_manager.py +813 -0
- aiecs/domain/community/decision_engine.py +879 -0
- aiecs/domain/community/exceptions.py +225 -0
- aiecs/domain/community/models/__init__.py +33 -0
- aiecs/domain/community/models/community_models.py +268 -0
- aiecs/domain/community/resource_manager.py +457 -0
- aiecs/domain/community/shared_context_manager.py +603 -0
- aiecs/domain/context/__init__.py +58 -0
- aiecs/domain/context/context_engine.py +989 -0
- aiecs/domain/context/conversation_models.py +354 -0
- aiecs/domain/context/graph_memory.py +467 -0
- aiecs/domain/execution/__init__.py +12 -0
- aiecs/domain/execution/model.py +57 -0
- aiecs/domain/knowledge_graph/__init__.py +19 -0
- aiecs/domain/knowledge_graph/models/__init__.py +52 -0
- aiecs/domain/knowledge_graph/models/entity.py +130 -0
- aiecs/domain/knowledge_graph/models/evidence.py +194 -0
- aiecs/domain/knowledge_graph/models/inference_rule.py +186 -0
- aiecs/domain/knowledge_graph/models/path.py +179 -0
- aiecs/domain/knowledge_graph/models/path_pattern.py +173 -0
- aiecs/domain/knowledge_graph/models/query.py +272 -0
- aiecs/domain/knowledge_graph/models/query_plan.py +187 -0
- aiecs/domain/knowledge_graph/models/relation.py +136 -0
- aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
- aiecs/domain/knowledge_graph/schema/entity_type.py +135 -0
- aiecs/domain/knowledge_graph/schema/graph_schema.py +271 -0
- aiecs/domain/knowledge_graph/schema/property_schema.py +155 -0
- aiecs/domain/knowledge_graph/schema/relation_type.py +171 -0
- aiecs/domain/knowledge_graph/schema/schema_manager.py +496 -0
- aiecs/domain/knowledge_graph/schema/type_enums.py +205 -0
- aiecs/domain/task/__init__.py +13 -0
- aiecs/domain/task/dsl_processor.py +613 -0
- aiecs/domain/task/model.py +62 -0
- aiecs/domain/task/task_context.py +268 -0
- aiecs/infrastructure/__init__.py +24 -0
- aiecs/infrastructure/graph_storage/__init__.py +11 -0
- aiecs/infrastructure/graph_storage/base.py +601 -0
- aiecs/infrastructure/graph_storage/batch_operations.py +449 -0
- aiecs/infrastructure/graph_storage/cache.py +429 -0
- aiecs/infrastructure/graph_storage/distributed.py +226 -0
- aiecs/infrastructure/graph_storage/error_handling.py +390 -0
- aiecs/infrastructure/graph_storage/graceful_degradation.py +306 -0
- aiecs/infrastructure/graph_storage/health_checks.py +378 -0
- aiecs/infrastructure/graph_storage/in_memory.py +514 -0
- aiecs/infrastructure/graph_storage/index_optimization.py +483 -0
- aiecs/infrastructure/graph_storage/lazy_loading.py +410 -0
- aiecs/infrastructure/graph_storage/metrics.py +357 -0
- aiecs/infrastructure/graph_storage/migration.py +413 -0
- aiecs/infrastructure/graph_storage/pagination.py +471 -0
- aiecs/infrastructure/graph_storage/performance_monitoring.py +466 -0
- aiecs/infrastructure/graph_storage/postgres.py +871 -0
- aiecs/infrastructure/graph_storage/query_optimizer.py +635 -0
- aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
- aiecs/infrastructure/graph_storage/sqlite.py +623 -0
- aiecs/infrastructure/graph_storage/streaming.py +495 -0
- aiecs/infrastructure/messaging/__init__.py +13 -0
- aiecs/infrastructure/messaging/celery_task_manager.py +383 -0
- aiecs/infrastructure/messaging/websocket_manager.py +298 -0
- aiecs/infrastructure/monitoring/__init__.py +34 -0
- aiecs/infrastructure/monitoring/executor_metrics.py +174 -0
- aiecs/infrastructure/monitoring/global_metrics_manager.py +213 -0
- aiecs/infrastructure/monitoring/structured_logger.py +48 -0
- aiecs/infrastructure/monitoring/tracing_manager.py +410 -0
- aiecs/infrastructure/persistence/__init__.py +24 -0
- aiecs/infrastructure/persistence/context_engine_client.py +187 -0
- aiecs/infrastructure/persistence/database_manager.py +333 -0
- aiecs/infrastructure/persistence/file_storage.py +754 -0
- aiecs/infrastructure/persistence/redis_client.py +220 -0
- aiecs/llm/__init__.py +86 -0
- aiecs/llm/callbacks/__init__.py +11 -0
- aiecs/llm/callbacks/custom_callbacks.py +264 -0
- aiecs/llm/client_factory.py +420 -0
- aiecs/llm/clients/__init__.py +33 -0
- aiecs/llm/clients/base_client.py +193 -0
- aiecs/llm/clients/googleai_client.py +181 -0
- aiecs/llm/clients/openai_client.py +131 -0
- aiecs/llm/clients/vertex_client.py +437 -0
- aiecs/llm/clients/xai_client.py +184 -0
- aiecs/llm/config/__init__.py +51 -0
- aiecs/llm/config/config_loader.py +275 -0
- aiecs/llm/config/config_validator.py +236 -0
- aiecs/llm/config/model_config.py +151 -0
- aiecs/llm/utils/__init__.py +10 -0
- aiecs/llm/utils/validate_config.py +91 -0
- aiecs/main.py +363 -0
- aiecs/scripts/__init__.py +3 -0
- aiecs/scripts/aid/VERSION_MANAGEMENT.md +97 -0
- aiecs/scripts/aid/__init__.py +19 -0
- aiecs/scripts/aid/version_manager.py +215 -0
- aiecs/scripts/dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md +242 -0
- aiecs/scripts/dependance_check/README_DEPENDENCY_CHECKER.md +310 -0
- aiecs/scripts/dependance_check/__init__.py +17 -0
- aiecs/scripts/dependance_check/dependency_checker.py +938 -0
- aiecs/scripts/dependance_check/dependency_fixer.py +391 -0
- aiecs/scripts/dependance_check/download_nlp_data.py +396 -0
- aiecs/scripts/dependance_check/quick_dependency_check.py +270 -0
- aiecs/scripts/dependance_check/setup_nlp_data.sh +217 -0
- aiecs/scripts/dependance_patch/__init__.py +7 -0
- aiecs/scripts/dependance_patch/fix_weasel/README_WEASEL_PATCH.md +126 -0
- aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
- aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.py +128 -0
- aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.sh +82 -0
- aiecs/scripts/dependance_patch/fix_weasel/patch_weasel_library.sh +188 -0
- aiecs/scripts/dependance_patch/fix_weasel/run_weasel_patch.sh +41 -0
- aiecs/scripts/tools_develop/README.md +449 -0
- aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
- aiecs/scripts/tools_develop/__init__.py +21 -0
- aiecs/scripts/tools_develop/check_type_annotations.py +259 -0
- aiecs/scripts/tools_develop/validate_tool_schemas.py +422 -0
- aiecs/scripts/tools_develop/verify_tools.py +356 -0
- aiecs/tasks/__init__.py +1 -0
- aiecs/tasks/worker.py +172 -0
- aiecs/tools/__init__.py +299 -0
- aiecs/tools/apisource/__init__.py +99 -0
- aiecs/tools/apisource/intelligence/__init__.py +19 -0
- aiecs/tools/apisource/intelligence/data_fusion.py +381 -0
- aiecs/tools/apisource/intelligence/query_analyzer.py +413 -0
- aiecs/tools/apisource/intelligence/search_enhancer.py +388 -0
- aiecs/tools/apisource/monitoring/__init__.py +9 -0
- aiecs/tools/apisource/monitoring/metrics.py +303 -0
- aiecs/tools/apisource/providers/__init__.py +115 -0
- aiecs/tools/apisource/providers/base.py +664 -0
- aiecs/tools/apisource/providers/census.py +401 -0
- aiecs/tools/apisource/providers/fred.py +564 -0
- aiecs/tools/apisource/providers/newsapi.py +412 -0
- aiecs/tools/apisource/providers/worldbank.py +357 -0
- aiecs/tools/apisource/reliability/__init__.py +12 -0
- aiecs/tools/apisource/reliability/error_handler.py +375 -0
- aiecs/tools/apisource/reliability/fallback_strategy.py +391 -0
- aiecs/tools/apisource/tool.py +850 -0
- aiecs/tools/apisource/utils/__init__.py +9 -0
- aiecs/tools/apisource/utils/validators.py +338 -0
- aiecs/tools/base_tool.py +201 -0
- aiecs/tools/docs/__init__.py +121 -0
- aiecs/tools/docs/ai_document_orchestrator.py +599 -0
- aiecs/tools/docs/ai_document_writer_orchestrator.py +2403 -0
- aiecs/tools/docs/content_insertion_tool.py +1333 -0
- aiecs/tools/docs/document_creator_tool.py +1317 -0
- aiecs/tools/docs/document_layout_tool.py +1166 -0
- aiecs/tools/docs/document_parser_tool.py +994 -0
- aiecs/tools/docs/document_writer_tool.py +1818 -0
- aiecs/tools/knowledge_graph/__init__.py +17 -0
- aiecs/tools/knowledge_graph/graph_reasoning_tool.py +734 -0
- aiecs/tools/knowledge_graph/graph_search_tool.py +923 -0
- aiecs/tools/knowledge_graph/kg_builder_tool.py +476 -0
- aiecs/tools/langchain_adapter.py +542 -0
- aiecs/tools/schema_generator.py +275 -0
- aiecs/tools/search_tool/__init__.py +100 -0
- aiecs/tools/search_tool/analyzers.py +589 -0
- aiecs/tools/search_tool/cache.py +260 -0
- aiecs/tools/search_tool/constants.py +128 -0
- aiecs/tools/search_tool/context.py +216 -0
- aiecs/tools/search_tool/core.py +749 -0
- aiecs/tools/search_tool/deduplicator.py +123 -0
- aiecs/tools/search_tool/error_handler.py +271 -0
- aiecs/tools/search_tool/metrics.py +371 -0
- aiecs/tools/search_tool/rate_limiter.py +178 -0
- aiecs/tools/search_tool/schemas.py +277 -0
- aiecs/tools/statistics/__init__.py +80 -0
- aiecs/tools/statistics/ai_data_analysis_orchestrator.py +643 -0
- aiecs/tools/statistics/ai_insight_generator_tool.py +505 -0
- aiecs/tools/statistics/ai_report_orchestrator_tool.py +694 -0
- aiecs/tools/statistics/data_loader_tool.py +564 -0
- aiecs/tools/statistics/data_profiler_tool.py +658 -0
- aiecs/tools/statistics/data_transformer_tool.py +573 -0
- aiecs/tools/statistics/data_visualizer_tool.py +495 -0
- aiecs/tools/statistics/model_trainer_tool.py +487 -0
- aiecs/tools/statistics/statistical_analyzer_tool.py +459 -0
- aiecs/tools/task_tools/__init__.py +86 -0
- aiecs/tools/task_tools/chart_tool.py +732 -0
- aiecs/tools/task_tools/classfire_tool.py +922 -0
- aiecs/tools/task_tools/image_tool.py +447 -0
- aiecs/tools/task_tools/office_tool.py +684 -0
- aiecs/tools/task_tools/pandas_tool.py +635 -0
- aiecs/tools/task_tools/report_tool.py +635 -0
- aiecs/tools/task_tools/research_tool.py +392 -0
- aiecs/tools/task_tools/scraper_tool.py +715 -0
- aiecs/tools/task_tools/stats_tool.py +688 -0
- aiecs/tools/temp_file_manager.py +130 -0
- aiecs/tools/tool_executor/__init__.py +37 -0
- aiecs/tools/tool_executor/tool_executor.py +881 -0
- aiecs/utils/LLM_output_structor.py +445 -0
- aiecs/utils/__init__.py +34 -0
- aiecs/utils/base_callback.py +47 -0
- aiecs/utils/cache_provider.py +695 -0
- aiecs/utils/execution_utils.py +184 -0
- aiecs/utils/logging.py +1 -0
- aiecs/utils/prompt_loader.py +14 -0
- aiecs/utils/token_usage_repository.py +323 -0
- aiecs/ws/__init__.py +0 -0
- aiecs/ws/socket_server.py +52 -0
- aiecs-1.5.1.dist-info/METADATA +608 -0
- aiecs-1.5.1.dist-info/RECORD +302 -0
- aiecs-1.5.1.dist-info/WHEEL +5 -0
- aiecs-1.5.1.dist-info/entry_points.txt +10 -0
- aiecs-1.5.1.dist-info/licenses/LICENSE +225 -0
- aiecs-1.5.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Conversation Memory
|
|
3
|
+
|
|
4
|
+
Multi-turn conversation handling with session management.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Dict, List, Optional
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
|
|
12
|
+
from aiecs.llm import LLMMessage
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class Session:
|
|
19
|
+
"""Conversation session."""
|
|
20
|
+
|
|
21
|
+
session_id: str
|
|
22
|
+
agent_id: str
|
|
23
|
+
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
24
|
+
last_activity: datetime = field(default_factory=datetime.utcnow)
|
|
25
|
+
messages: List[LLMMessage] = field(default_factory=list)
|
|
26
|
+
metadata: Dict = field(default_factory=dict)
|
|
27
|
+
|
|
28
|
+
def add_message(self, role: str, content: str) -> None:
|
|
29
|
+
"""Add message to session."""
|
|
30
|
+
self.messages.append(LLMMessage(role=role, content=content))
|
|
31
|
+
self.last_activity = datetime.utcnow()
|
|
32
|
+
|
|
33
|
+
def get_recent_messages(self, limit: int) -> List[LLMMessage]:
|
|
34
|
+
"""Get recent messages."""
|
|
35
|
+
return self.messages[-limit:] if limit else self.messages
|
|
36
|
+
|
|
37
|
+
def clear(self) -> None:
|
|
38
|
+
"""Clear session messages."""
|
|
39
|
+
self.messages.clear()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class ConversationMemory:
|
|
43
|
+
"""
|
|
44
|
+
Manages multi-turn conversations with session isolation.
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
memory = ConversationMemory(agent_id="agent-1")
|
|
48
|
+
session_id = memory.create_session()
|
|
49
|
+
memory.add_message(session_id, "user", "Hello")
|
|
50
|
+
memory.add_message(session_id, "assistant", "Hi there!")
|
|
51
|
+
history = memory.get_history(session_id)
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(self, agent_id: str, max_sessions: int = 100):
|
|
55
|
+
"""
|
|
56
|
+
Initialize conversation memory.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
agent_id: Agent identifier
|
|
60
|
+
max_sessions: Maximum number of sessions to keep
|
|
61
|
+
"""
|
|
62
|
+
self.agent_id = agent_id
|
|
63
|
+
self.max_sessions = max_sessions
|
|
64
|
+
self._sessions: Dict[str, Session] = {}
|
|
65
|
+
logger.info(f"ConversationMemory initialized for agent {agent_id}")
|
|
66
|
+
|
|
67
|
+
def create_session(self, session_id: Optional[str] = None) -> str:
|
|
68
|
+
"""
|
|
69
|
+
Create a new conversation session.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
session_id: Optional custom session ID
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Session ID
|
|
76
|
+
"""
|
|
77
|
+
if session_id is None:
|
|
78
|
+
session_id = f"session_{datetime.utcnow().timestamp()}"
|
|
79
|
+
|
|
80
|
+
if session_id in self._sessions:
|
|
81
|
+
logger.warning(f"Session {session_id} already exists")
|
|
82
|
+
return session_id
|
|
83
|
+
|
|
84
|
+
self._sessions[session_id] = Session(session_id=session_id, agent_id=self.agent_id)
|
|
85
|
+
|
|
86
|
+
# Cleanup old sessions if limit exceeded
|
|
87
|
+
if len(self._sessions) > self.max_sessions:
|
|
88
|
+
self._cleanup_old_sessions()
|
|
89
|
+
|
|
90
|
+
logger.debug(f"Session {session_id} created")
|
|
91
|
+
return session_id
|
|
92
|
+
|
|
93
|
+
def add_message(self, session_id: str, role: str, content: str) -> None:
|
|
94
|
+
"""
|
|
95
|
+
Add message to session.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
session_id: Session ID
|
|
99
|
+
role: Message role
|
|
100
|
+
content: Message content
|
|
101
|
+
"""
|
|
102
|
+
if session_id not in self._sessions:
|
|
103
|
+
logger.warning(f"Session {session_id} not found, creating it")
|
|
104
|
+
self.create_session(session_id)
|
|
105
|
+
|
|
106
|
+
self._sessions[session_id].add_message(role, content)
|
|
107
|
+
|
|
108
|
+
def get_history(self, session_id: str, limit: Optional[int] = None) -> List[LLMMessage]:
|
|
109
|
+
"""
|
|
110
|
+
Get conversation history for session.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
session_id: Session ID
|
|
114
|
+
limit: Optional limit on number of messages
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
List of messages
|
|
118
|
+
"""
|
|
119
|
+
if session_id not in self._sessions:
|
|
120
|
+
return []
|
|
121
|
+
|
|
122
|
+
session = self._sessions[session_id]
|
|
123
|
+
return session.get_recent_messages(limit) if limit else session.messages.copy()
|
|
124
|
+
|
|
125
|
+
def format_history(self, session_id: str, limit: Optional[int] = None) -> str:
|
|
126
|
+
"""
|
|
127
|
+
Format conversation history as string.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
session_id: Session ID
|
|
131
|
+
limit: Optional limit on number of messages
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
Formatted history string
|
|
135
|
+
"""
|
|
136
|
+
history = self.get_history(session_id, limit)
|
|
137
|
+
lines = []
|
|
138
|
+
for msg in history:
|
|
139
|
+
lines.append(f"{msg.role.upper()}: {msg.content}")
|
|
140
|
+
return "\n".join(lines)
|
|
141
|
+
|
|
142
|
+
def clear_session(self, session_id: str) -> None:
|
|
143
|
+
"""
|
|
144
|
+
Clear session messages.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
session_id: Session ID
|
|
148
|
+
"""
|
|
149
|
+
if session_id in self._sessions:
|
|
150
|
+
self._sessions[session_id].clear()
|
|
151
|
+
logger.debug(f"Session {session_id} cleared")
|
|
152
|
+
|
|
153
|
+
def delete_session(self, session_id: str) -> None:
|
|
154
|
+
"""
|
|
155
|
+
Delete session.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
session_id: Session ID
|
|
159
|
+
"""
|
|
160
|
+
if session_id in self._sessions:
|
|
161
|
+
del self._sessions[session_id]
|
|
162
|
+
logger.debug(f"Session {session_id} deleted")
|
|
163
|
+
|
|
164
|
+
def get_session(self, session_id: str) -> Optional[Session]:
|
|
165
|
+
"""
|
|
166
|
+
Get session object.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
session_id: Session ID
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
Session or None
|
|
173
|
+
"""
|
|
174
|
+
return self._sessions.get(session_id)
|
|
175
|
+
|
|
176
|
+
def list_sessions(self) -> List[str]:
|
|
177
|
+
"""List all session IDs."""
|
|
178
|
+
return list(self._sessions.keys())
|
|
179
|
+
|
|
180
|
+
def _cleanup_old_sessions(self) -> None:
|
|
181
|
+
"""Remove oldest sessions to maintain limit."""
|
|
182
|
+
# Sort by last activity
|
|
183
|
+
sorted_sessions = sorted(self._sessions.items(), key=lambda x: x[1].last_activity)
|
|
184
|
+
|
|
185
|
+
# Remove oldest sessions
|
|
186
|
+
num_to_remove = len(self._sessions) - self.max_sessions
|
|
187
|
+
for session_id, _ in sorted_sessions[:num_to_remove]:
|
|
188
|
+
del self._sessions[session_id]
|
|
189
|
+
logger.debug(f"Removed old session {session_id}")
|
|
190
|
+
|
|
191
|
+
def get_stats(self) -> Dict:
|
|
192
|
+
"""Get memory statistics."""
|
|
193
|
+
return {
|
|
194
|
+
"agent_id": self.agent_id,
|
|
195
|
+
"total_sessions": len(self._sessions),
|
|
196
|
+
"total_messages": sum(len(s.messages) for s in self._sessions.values()),
|
|
197
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Migration Utilities
|
|
3
|
+
|
|
4
|
+
Tools for migrating from legacy agents and LangChain to BaseAIAgent.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .legacy_wrapper import LegacyAgentWrapper
|
|
8
|
+
from .conversion import convert_langchain_prompt, convert_legacy_config
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"LegacyAgentWrapper",
|
|
12
|
+
"convert_langchain_prompt",
|
|
13
|
+
"convert_legacy_config",
|
|
14
|
+
]
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Conversion Utilities
|
|
3
|
+
|
|
4
|
+
Convert legacy configurations and prompts to new format.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Dict, Any
|
|
9
|
+
import re
|
|
10
|
+
|
|
11
|
+
from ..models import AgentConfiguration
|
|
12
|
+
from ..prompts import PromptTemplate, ChatPromptTemplate, MessageTemplate
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def convert_legacy_config(legacy_config: Dict[str, Any]) -> AgentConfiguration:
|
|
18
|
+
"""
|
|
19
|
+
Convert legacy agent configuration to AgentConfiguration.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
legacy_config: Legacy configuration dictionary
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
AgentConfiguration instance
|
|
26
|
+
"""
|
|
27
|
+
# Map legacy fields to new fields
|
|
28
|
+
field_mapping = {
|
|
29
|
+
# Common legacy field names
|
|
30
|
+
"model": "llm_model",
|
|
31
|
+
"model_name": "llm_model",
|
|
32
|
+
"temp": "temperature",
|
|
33
|
+
"max_output_tokens": "max_tokens",
|
|
34
|
+
"enable_memory": "memory_enabled",
|
|
35
|
+
"verbose": "verbose",
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
converted = {}
|
|
39
|
+
for old_field, value in legacy_config.items():
|
|
40
|
+
new_field = field_mapping.get(old_field, old_field)
|
|
41
|
+
converted[new_field] = value
|
|
42
|
+
|
|
43
|
+
# Create AgentConfiguration
|
|
44
|
+
try:
|
|
45
|
+
config = AgentConfiguration(**converted)
|
|
46
|
+
logger.info("Legacy configuration converted successfully")
|
|
47
|
+
return config
|
|
48
|
+
except Exception as e:
|
|
49
|
+
logger.error(f"Failed to convert legacy config: {e}")
|
|
50
|
+
# Return default config with available fields
|
|
51
|
+
return AgentConfiguration(
|
|
52
|
+
llm_model=converted.get("llm_model"),
|
|
53
|
+
temperature=converted.get("temperature", 0.7),
|
|
54
|
+
max_tokens=converted.get("max_tokens"),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def convert_langchain_prompt(langchain_prompt: str) -> PromptTemplate:
|
|
59
|
+
"""
|
|
60
|
+
Convert LangChain prompt template to native PromptTemplate.
|
|
61
|
+
|
|
62
|
+
LangChain uses {variable} syntax, which is compatible with our format.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
langchain_prompt: LangChain prompt string
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
PromptTemplate instance
|
|
69
|
+
"""
|
|
70
|
+
# LangChain and our template use same {variable} syntax
|
|
71
|
+
# Just need to extract variables
|
|
72
|
+
pattern = r"\{(\w+)\}"
|
|
73
|
+
variables = re.findall(pattern, langchain_prompt)
|
|
74
|
+
|
|
75
|
+
return PromptTemplate(template=langchain_prompt, required_variables=variables)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def convert_langchain_chat_prompt(messages: list) -> ChatPromptTemplate:
|
|
79
|
+
"""
|
|
80
|
+
Convert LangChain chat prompt to ChatPromptTemplate.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
messages: List of (role, template) tuples
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
ChatPromptTemplate instance
|
|
87
|
+
"""
|
|
88
|
+
message_templates = []
|
|
89
|
+
|
|
90
|
+
for item in messages:
|
|
91
|
+
if isinstance(item, tuple):
|
|
92
|
+
role, template = item
|
|
93
|
+
elif isinstance(item, dict):
|
|
94
|
+
role = item.get("role", "user")
|
|
95
|
+
template = item.get("content", "")
|
|
96
|
+
else:
|
|
97
|
+
logger.warning(f"Unknown message format: {item}")
|
|
98
|
+
continue
|
|
99
|
+
|
|
100
|
+
message_templates.append(MessageTemplate(role=role, content=template))
|
|
101
|
+
|
|
102
|
+
return ChatPromptTemplate(messages=message_templates)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def migrate_agent_state(legacy_state: Dict[str, Any]) -> Dict[str, Any]:
|
|
106
|
+
"""
|
|
107
|
+
Migrate legacy agent state to new format.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
legacy_state: Legacy state dictionary
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
New state dictionary
|
|
114
|
+
"""
|
|
115
|
+
# Map legacy state fields
|
|
116
|
+
state_mapping = {
|
|
117
|
+
"status": "state",
|
|
118
|
+
"task_history": "interactions",
|
|
119
|
+
"memory": "memory",
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
migrated = {}
|
|
123
|
+
for old_field, value in legacy_state.items():
|
|
124
|
+
new_field = state_mapping.get(old_field, old_field)
|
|
125
|
+
migrated[new_field] = value
|
|
126
|
+
|
|
127
|
+
logger.info("Agent state migrated")
|
|
128
|
+
return migrated
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def validate_migration(legacy_agent: Any, new_agent: Any) -> Dict[str, Any]:
|
|
132
|
+
"""
|
|
133
|
+
Validate migration by comparing legacy and new agent behavior.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
legacy_agent: Legacy agent instance
|
|
137
|
+
new_agent: New agent instance
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
Validation report
|
|
141
|
+
"""
|
|
142
|
+
report = {
|
|
143
|
+
"compatible": True,
|
|
144
|
+
"warnings": [],
|
|
145
|
+
"errors": [],
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
# Check for required methods
|
|
149
|
+
required_methods = ["execute_task"]
|
|
150
|
+
for method in required_methods:
|
|
151
|
+
if not hasattr(new_agent, method):
|
|
152
|
+
report["compatible"] = False
|
|
153
|
+
report["errors"].append(f"Missing required method: {method}")
|
|
154
|
+
|
|
155
|
+
# Check configuration compatibility
|
|
156
|
+
if hasattr(legacy_agent, "config") and hasattr(new_agent, "_config"):
|
|
157
|
+
# Basic compatibility check
|
|
158
|
+
logger.info("Configuration validated")
|
|
159
|
+
|
|
160
|
+
return report
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Legacy Agent Wrapper
|
|
3
|
+
|
|
4
|
+
Compatibility wrapper for gradual migration from legacy agents.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Dict, Any, Optional
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LegacyAgentWrapper:
|
|
14
|
+
"""
|
|
15
|
+
Wrapper for legacy agents to work with BaseAIAgent interface.
|
|
16
|
+
|
|
17
|
+
This enables gradual migration without breaking existing code.
|
|
18
|
+
|
|
19
|
+
Example:
|
|
20
|
+
legacy_agent = SomeLegacyAgent()
|
|
21
|
+
wrapped = LegacyAgentWrapper(legacy_agent)
|
|
22
|
+
result = await wrapped.execute_task(task, context)
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, legacy_agent: Any):
|
|
26
|
+
"""
|
|
27
|
+
Initialize wrapper.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
legacy_agent: Legacy agent instance
|
|
31
|
+
"""
|
|
32
|
+
self.legacy_agent = legacy_agent
|
|
33
|
+
self._is_wrapped = True
|
|
34
|
+
logger.info(f"Legacy agent wrapped: {type(legacy_agent).__name__}")
|
|
35
|
+
|
|
36
|
+
async def execute_task(self, task: Dict[str, Any], context: Dict[str, Any]) -> Dict[str, Any]:
|
|
37
|
+
"""
|
|
38
|
+
Execute task using legacy agent.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
task: Task specification
|
|
42
|
+
context: Execution context
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Result dictionary
|
|
46
|
+
"""
|
|
47
|
+
# Try various legacy interfaces
|
|
48
|
+
if hasattr(self.legacy_agent, "execute_task"):
|
|
49
|
+
return await self.legacy_agent.execute_task(task, context)
|
|
50
|
+
elif hasattr(self.legacy_agent, "run"):
|
|
51
|
+
result = await self.legacy_agent.run(task.get("description", ""))
|
|
52
|
+
return {"output": result, "success": True}
|
|
53
|
+
elif hasattr(self.legacy_agent, "process"):
|
|
54
|
+
result = await self.legacy_agent.process(task)
|
|
55
|
+
return {"output": result, "success": True}
|
|
56
|
+
else:
|
|
57
|
+
raise NotImplementedError(
|
|
58
|
+
f"Legacy agent {type(self.legacy_agent).__name__} has no compatible interface"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
async def process_message(
|
|
62
|
+
self, message: str, sender_id: Optional[str] = None
|
|
63
|
+
) -> Dict[str, Any]:
|
|
64
|
+
"""
|
|
65
|
+
Process message using legacy agent.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
message: Message content
|
|
69
|
+
sender_id: Optional sender ID
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Response dictionary
|
|
73
|
+
"""
|
|
74
|
+
if hasattr(self.legacy_agent, "process_message"):
|
|
75
|
+
return await self.legacy_agent.process_message(message, sender_id)
|
|
76
|
+
elif hasattr(self.legacy_agent, "chat"):
|
|
77
|
+
response = await self.legacy_agent.chat(message)
|
|
78
|
+
return {"response": response}
|
|
79
|
+
else:
|
|
80
|
+
# Fallback to execute_task
|
|
81
|
+
task = {"description": message}
|
|
82
|
+
result = await self.execute_task(task, {"sender_id": sender_id})
|
|
83
|
+
return {"response": result.get("output")}
|
|
84
|
+
|
|
85
|
+
def __getattr__(self, name: str):
|
|
86
|
+
"""Forward attribute access to legacy agent."""
|
|
87
|
+
return getattr(self.legacy_agent, name)
|
|
88
|
+
|
|
89
|
+
def __repr__(self) -> str:
|
|
90
|
+
return f"LegacyAgentWrapper({type(self.legacy_agent).__name__})"
|