152 lines
4.1 KiB
Python
152 lines
4.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Cache Configuration for Local Timmy
|
|
Issue #103 — Cache Everywhere
|
|
|
|
Configuration for all cache tiers with sensible defaults.
|
|
"""
|
|
|
|
from typing import Dict, Any
|
|
|
|
|
|
# TTL Configuration (in seconds)
|
|
TTL_CONFIG = {
|
|
# Tool result cache TTLs
|
|
"tools": {
|
|
"system_info": 60,
|
|
"disk_usage": 120,
|
|
"git_status": 30,
|
|
"git_log": 300,
|
|
"health_check": 60,
|
|
"gitea_list_issues": 120,
|
|
"file_read": 30,
|
|
"process_list": 30,
|
|
"service_status": 60,
|
|
"http_get": 300,
|
|
"http_post": 0, # Don't cache POSTs by default
|
|
},
|
|
|
|
# Response cache TTLs by query type
|
|
"responses": {
|
|
"status_check": 60, # System status queries
|
|
"factual": 3600, # Factual questions
|
|
"code": 0, # Code generation (never cache)
|
|
"analysis": 600, # Analysis results
|
|
"creative": 0, # Creative writing (never cache)
|
|
},
|
|
|
|
# Embedding cache (no TTL, uses file mtime)
|
|
"embeddings": None,
|
|
|
|
# HTTP cache TTLs
|
|
"http": {
|
|
"gitea_api": 120,
|
|
"static_content": 86400, # 24 hours
|
|
"dynamic_content": 60,
|
|
}
|
|
}
|
|
|
|
|
|
# Cache size limits
|
|
SIZE_LIMITS = {
|
|
"lru_memory_entries": 1000, # In-memory LRU cache
|
|
"response_disk_mb": 100, # Response cache database
|
|
"tool_disk_mb": 50, # Tool cache database
|
|
"embedding_disk_mb": 500, # Embedding cache database
|
|
"http_disk_mb": 50, # HTTP cache database
|
|
}
|
|
|
|
|
|
# Cache paths (relative to ~/.timmy/)
|
|
CACHE_PATHS = {
|
|
"base": "cache",
|
|
"responses": "cache/responses.db",
|
|
"tools": "cache/tool_cache.db",
|
|
"embeddings": "cache/embeddings.db",
|
|
"http": "cache/http_cache.db",
|
|
}
|
|
|
|
|
|
# Tool invalidation rules (which tools invalidate others)
|
|
INVALIDATION_RULES = {
|
|
"git_commit": ["git_status", "git_log"],
|
|
"git_pull": ["git_status", "git_log"],
|
|
"git_push": ["git_status"],
|
|
"file_write": ["file_read"],
|
|
"file_delete": ["file_read"],
|
|
"gitea_create_issue": ["gitea_list_issues"],
|
|
"gitea_comment": ["gitea_list_issues"],
|
|
"gitea_close_issue": ["gitea_list_issues"],
|
|
}
|
|
|
|
|
|
# Refusal patterns for semantic refusal detection
|
|
REFUSAL_PATTERNS = [
|
|
r"I (?:can't|cannot|am unable to|must decline)",
|
|
r"against my (?:guidelines|policy|programming)",
|
|
r"I'm not (?:able|comfortable|designed) to",
|
|
r"I (?:apologize|'m sorry),? but I (?:can't|cannot)",
|
|
r"I don't (?:know|have information about)",
|
|
r"I'm not sure",
|
|
r"I cannot assist",
|
|
]
|
|
|
|
|
|
# Template cache configuration
|
|
TEMPLATE_CONFIG = {
|
|
"paths": {
|
|
"minimal": "~/.timmy/templates/minimal.txt",
|
|
"standard": "~/.timmy/templates/standard.txt",
|
|
"deep": "~/.timmy/templates/deep.txt",
|
|
},
|
|
"auto_load": ["minimal", "standard", "deep"],
|
|
}
|
|
|
|
|
|
# Performance targets
|
|
TARGETS = {
|
|
"tool_cache_hit_rate": 0.30, # 30%
|
|
"response_cache_hit_rate": 0.20, # 20%
|
|
"embedding_cache_hit_rate": 0.80, # 80%
|
|
"max_cache_memory_mb": 100,
|
|
"cleanup_interval_seconds": 3600, # Hourly cleanup
|
|
}
|
|
|
|
|
|
def get_ttl(cache_type: str, key: str) -> int:
|
|
"""Get TTL for a specific cache entry type."""
|
|
if cache_type == "tools":
|
|
return TTL_CONFIG["tools"].get(key, 60)
|
|
elif cache_type == "responses":
|
|
return TTL_CONFIG["responses"].get(key, 300)
|
|
elif cache_type == "http":
|
|
return TTL_CONFIG["http"].get(key, 300)
|
|
return 60
|
|
|
|
|
|
def get_invalidation_deps(tool_name: str) -> list:
|
|
"""Get list of tools to invalidate when this tool runs."""
|
|
return INVALIDATION_RULES.get(tool_name, [])
|
|
|
|
|
|
def is_cacheable(tool_name: str) -> bool:
|
|
"""Check if a tool result should be cached."""
|
|
return tool_name in TTL_CONFIG["tools"] and TTL_CONFIG["tools"][tool_name] > 0
|
|
|
|
|
|
def get_config() -> Dict[str, Any]:
|
|
"""Get complete cache configuration."""
|
|
return {
|
|
"ttl": TTL_CONFIG,
|
|
"sizes": SIZE_LIMITS,
|
|
"paths": CACHE_PATHS,
|
|
"invalidation": INVALIDATION_RULES,
|
|
"templates": TEMPLATE_CONFIG,
|
|
"targets": TARGETS,
|
|
}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import json
|
|
print(json.dumps(get_config(), indent=2))
|