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,290 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Schema Cache
|
|
3
|
+
|
|
4
|
+
LRU cache with TTL support for schema lookups.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import time
|
|
8
|
+
from typing import Optional, Dict, Any, Generic, TypeVar
|
|
9
|
+
from collections import OrderedDict
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from threading import Lock
|
|
12
|
+
|
|
13
|
+
T = TypeVar("T")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class CacheEntry(Generic[T]):
|
|
18
|
+
"""
|
|
19
|
+
Cache entry with value and metadata
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
value: Cached value
|
|
23
|
+
timestamp: When the entry was created/updated
|
|
24
|
+
access_count: Number of times accessed
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
value: T
|
|
28
|
+
timestamp: float = field(default_factory=time.time)
|
|
29
|
+
access_count: int = 0
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class CacheMetrics:
|
|
34
|
+
"""
|
|
35
|
+
Cache performance metrics
|
|
36
|
+
|
|
37
|
+
Attributes:
|
|
38
|
+
hits: Number of cache hits
|
|
39
|
+
misses: Number of cache misses
|
|
40
|
+
evictions: Number of entries evicted
|
|
41
|
+
expirations: Number of entries expired
|
|
42
|
+
total_requests: Total number of cache requests
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
hits: int = 0
|
|
46
|
+
misses: int = 0
|
|
47
|
+
evictions: int = 0
|
|
48
|
+
expirations: int = 0
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def total_requests(self) -> int:
|
|
52
|
+
"""Total number of cache requests"""
|
|
53
|
+
return self.hits + self.misses
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def hit_rate(self) -> float:
|
|
57
|
+
"""Cache hit rate (0.0-1.0)"""
|
|
58
|
+
if self.total_requests == 0:
|
|
59
|
+
return 0.0
|
|
60
|
+
return self.hits / self.total_requests
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def miss_rate(self) -> float:
|
|
64
|
+
"""Cache miss rate (0.0-1.0)"""
|
|
65
|
+
return 1.0 - self.hit_rate
|
|
66
|
+
|
|
67
|
+
def reset(self) -> None:
|
|
68
|
+
"""Reset all metrics to zero"""
|
|
69
|
+
self.hits = 0
|
|
70
|
+
self.misses = 0
|
|
71
|
+
self.evictions = 0
|
|
72
|
+
self.expirations = 0
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class LRUCache(Generic[T]):
|
|
76
|
+
"""
|
|
77
|
+
LRU (Least Recently Used) Cache with TTL support
|
|
78
|
+
|
|
79
|
+
Thread-safe cache implementation with:
|
|
80
|
+
- LRU eviction policy
|
|
81
|
+
- TTL (time-to-live) expiration
|
|
82
|
+
- Performance metrics tracking
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
```python
|
|
86
|
+
cache = LRUCache(max_size=100, ttl_seconds=3600)
|
|
87
|
+
|
|
88
|
+
# Set value
|
|
89
|
+
cache.set("key1", value)
|
|
90
|
+
|
|
91
|
+
# Get value
|
|
92
|
+
value = cache.get("key1") # Returns value or None
|
|
93
|
+
|
|
94
|
+
# Check metrics
|
|
95
|
+
print(f"Hit rate: {cache.metrics.hit_rate:.2%}")
|
|
96
|
+
```
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
def __init__(self, max_size: int = 1000, ttl_seconds: Optional[int] = 3600):
|
|
100
|
+
"""
|
|
101
|
+
Initialize LRU cache
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
max_size: Maximum number of entries (default: 1000)
|
|
105
|
+
ttl_seconds: Time-to-live in seconds (default: 3600, None = no expiration)
|
|
106
|
+
"""
|
|
107
|
+
if max_size <= 0:
|
|
108
|
+
raise ValueError("max_size must be positive")
|
|
109
|
+
|
|
110
|
+
self.max_size = max_size
|
|
111
|
+
self.ttl_seconds = ttl_seconds
|
|
112
|
+
self._cache: OrderedDict[str, CacheEntry[T]] = OrderedDict()
|
|
113
|
+
self._lock = Lock()
|
|
114
|
+
self.metrics = CacheMetrics()
|
|
115
|
+
|
|
116
|
+
def get(self, key: str) -> Optional[T]:
|
|
117
|
+
"""
|
|
118
|
+
Get value from cache
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
key: Cache key
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
Cached value or None if not found/expired
|
|
125
|
+
"""
|
|
126
|
+
with self._lock:
|
|
127
|
+
entry = self._cache.get(key)
|
|
128
|
+
|
|
129
|
+
if entry is None:
|
|
130
|
+
self.metrics.misses += 1
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
# Check TTL expiration
|
|
134
|
+
if self._is_expired(entry):
|
|
135
|
+
del self._cache[key]
|
|
136
|
+
self.metrics.expirations += 1
|
|
137
|
+
self.metrics.misses += 1
|
|
138
|
+
return None
|
|
139
|
+
|
|
140
|
+
# Move to end (most recently used)
|
|
141
|
+
self._cache.move_to_end(key)
|
|
142
|
+
entry.access_count += 1
|
|
143
|
+
self.metrics.hits += 1
|
|
144
|
+
|
|
145
|
+
return entry.value
|
|
146
|
+
|
|
147
|
+
def set(self, key: str, value: T) -> None:
|
|
148
|
+
"""
|
|
149
|
+
Set value in cache
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
key: Cache key
|
|
153
|
+
value: Value to cache
|
|
154
|
+
"""
|
|
155
|
+
with self._lock:
|
|
156
|
+
# Update existing entry
|
|
157
|
+
if key in self._cache:
|
|
158
|
+
self._cache[key] = CacheEntry(value=value)
|
|
159
|
+
self._cache.move_to_end(key)
|
|
160
|
+
return
|
|
161
|
+
|
|
162
|
+
# Add new entry
|
|
163
|
+
self._cache[key] = CacheEntry(value=value)
|
|
164
|
+
|
|
165
|
+
# Evict oldest entry if cache is full
|
|
166
|
+
if len(self._cache) > self.max_size:
|
|
167
|
+
self._cache.popitem(last=False) # Remove oldest (first) item
|
|
168
|
+
self.metrics.evictions += 1
|
|
169
|
+
|
|
170
|
+
def delete(self, key: str) -> bool:
|
|
171
|
+
"""
|
|
172
|
+
Delete entry from cache
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
key: Cache key
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
True if entry was deleted, False if not found
|
|
179
|
+
"""
|
|
180
|
+
with self._lock:
|
|
181
|
+
if key in self._cache:
|
|
182
|
+
del self._cache[key]
|
|
183
|
+
return True
|
|
184
|
+
return False
|
|
185
|
+
|
|
186
|
+
def clear(self) -> None:
|
|
187
|
+
"""Clear all entries from cache"""
|
|
188
|
+
with self._lock:
|
|
189
|
+
self._cache.clear()
|
|
190
|
+
|
|
191
|
+
def invalidate_pattern(self, pattern: str) -> int:
|
|
192
|
+
"""
|
|
193
|
+
Invalidate all keys matching a pattern
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
pattern: Pattern to match (simple prefix matching)
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
Number of entries invalidated
|
|
200
|
+
"""
|
|
201
|
+
with self._lock:
|
|
202
|
+
keys_to_delete = [key for key in self._cache.keys() if key.startswith(pattern)]
|
|
203
|
+
|
|
204
|
+
for key in keys_to_delete:
|
|
205
|
+
del self._cache[key]
|
|
206
|
+
|
|
207
|
+
return len(keys_to_delete)
|
|
208
|
+
|
|
209
|
+
def _is_expired(self, entry: CacheEntry[T]) -> bool:
|
|
210
|
+
"""
|
|
211
|
+
Check if cache entry is expired
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
entry: Cache entry to check
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
True if expired, False otherwise
|
|
218
|
+
"""
|
|
219
|
+
if self.ttl_seconds is None:
|
|
220
|
+
return False
|
|
221
|
+
|
|
222
|
+
age = time.time() - entry.timestamp
|
|
223
|
+
return age > self.ttl_seconds
|
|
224
|
+
|
|
225
|
+
def cleanup_expired(self) -> int:
|
|
226
|
+
"""
|
|
227
|
+
Remove all expired entries
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
Number of entries removed
|
|
231
|
+
"""
|
|
232
|
+
with self._lock:
|
|
233
|
+
if self.ttl_seconds is None:
|
|
234
|
+
return 0
|
|
235
|
+
|
|
236
|
+
keys_to_delete = [key for key, entry in self._cache.items() if self._is_expired(entry)]
|
|
237
|
+
|
|
238
|
+
for key in keys_to_delete:
|
|
239
|
+
del self._cache[key]
|
|
240
|
+
|
|
241
|
+
self.metrics.expirations += len(keys_to_delete)
|
|
242
|
+
return len(keys_to_delete)
|
|
243
|
+
|
|
244
|
+
@property
|
|
245
|
+
def size(self) -> int:
|
|
246
|
+
"""Current number of entries in cache"""
|
|
247
|
+
with self._lock:
|
|
248
|
+
return len(self._cache)
|
|
249
|
+
|
|
250
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
251
|
+
"""
|
|
252
|
+
Get cache statistics
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
Dictionary with cache statistics
|
|
256
|
+
"""
|
|
257
|
+
with self._lock:
|
|
258
|
+
return {
|
|
259
|
+
"size": len(self._cache),
|
|
260
|
+
"max_size": self.max_size,
|
|
261
|
+
"ttl_seconds": self.ttl_seconds,
|
|
262
|
+
"hits": self.metrics.hits,
|
|
263
|
+
"misses": self.metrics.misses,
|
|
264
|
+
"evictions": self.metrics.evictions,
|
|
265
|
+
"expirations": self.metrics.expirations,
|
|
266
|
+
"total_requests": self.metrics.total_requests,
|
|
267
|
+
"hit_rate": self.metrics.hit_rate,
|
|
268
|
+
"miss_rate": self.metrics.miss_rate,
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
def reset_metrics(self) -> None:
|
|
272
|
+
"""Reset cache metrics"""
|
|
273
|
+
with self._lock:
|
|
274
|
+
self.metrics.reset()
|
|
275
|
+
|
|
276
|
+
def __len__(self) -> int:
|
|
277
|
+
"""Return number of entries in cache"""
|
|
278
|
+
return self.size
|
|
279
|
+
|
|
280
|
+
def __contains__(self, key: str) -> bool:
|
|
281
|
+
"""Check if key exists in cache (without affecting LRU order)"""
|
|
282
|
+
with self._lock:
|
|
283
|
+
if key not in self._cache:
|
|
284
|
+
return False
|
|
285
|
+
|
|
286
|
+
entry = self._cache[key]
|
|
287
|
+
return not self._is_expired(entry)
|
|
288
|
+
|
|
289
|
+
def __repr__(self) -> str:
|
|
290
|
+
return f"LRUCache(size={self.size}/{self.max_size}, hit_rate={self.metrics.hit_rate:.2%})"
|