Spaces:
Sleeping
Sleeping
| """ | |
| Memory Tools - Knowledge base operations | |
| """ | |
| from typing import Any, Dict, Optional, List | |
| from app.tools.registry import BaseTool, ToolMetadata, ToolRegistry | |
| from app.utils.database import db | |
| from app.utils.cache import cache | |
| from app.utils.logging import get_logger | |
| logger = get_logger("memory_tools") | |
| class RememberFactTool(BaseTool): | |
| """Store a fact in the knowledge base""" | |
| metadata = ToolMetadata( | |
| name="tool_remember_fact", | |
| description="Store a fact or preference about the user in the knowledge base. Use this to remember important information.", | |
| parameters={ | |
| "content": {"type": "string", "description": "The fact or information to remember"}, | |
| "category": {"type": "string", "description": "Category (e.g., preference, fact, insight)", "default": "fact"}, | |
| "user_id": {"type": "string", "description": "User ID (usually auto-populated)"} | |
| }, | |
| rate_limited=False | |
| ) | |
| async def execute( | |
| self, | |
| content: str, | |
| category: str = "fact", | |
| user_id: str = None | |
| ) -> Dict[str, Any]: | |
| """Store fact in knowledge base""" | |
| try: | |
| if not user_id: | |
| return { | |
| "success": False, | |
| "error": "User ID required" | |
| } | |
| knowledge_data = { | |
| "user_id": user_id, | |
| "content": content, | |
| "content_type": category, | |
| "source_type": "tool", | |
| "confidence_score": 0.9, | |
| "quality_score": 0.9 | |
| } | |
| result = await db.insert("knowledge_base", knowledge_data) | |
| if result: | |
| # Invalidate cache | |
| await cache.delete(f"knowledge_base:{user_id}") | |
| return { | |
| "success": True, | |
| "memory_id": result[0]["id"], | |
| "message": f"Remembered: {content[:100]}..." | |
| } | |
| else: | |
| return { | |
| "success": False, | |
| "error": "Failed to store in database" | |
| } | |
| except Exception as e: | |
| logger.error(f"Remember fact error: {e}") | |
| return { | |
| "success": False, | |
| "error": str(e) | |
| } | |
| class RecallMemoryTool(BaseTool): | |
| """Search and recall memories from knowledge base""" | |
| metadata = ToolMetadata( | |
| name="tool_recall_memory", | |
| description="Search the knowledge base for relevant information. Use this to recall facts about the user.", | |
| parameters={ | |
| "query": {"type": "string", "description": "What to search for"}, | |
| "limit": {"type": "integer", "description": "Max results", "default": 5}, | |
| "user_id": {"type": "string", "description": "User ID (usually auto-populated)"} | |
| }, | |
| rate_limited=False | |
| ) | |
| async def execute( | |
| self, | |
| query: str, | |
| limit: int = 5, | |
| user_id: str = None | |
| ) -> Dict[str, Any]: | |
| """Search knowledge base""" | |
| try: | |
| if not user_id: | |
| return { | |
| "success": False, | |
| "error": "User ID required" | |
| } | |
| # For now, do text-based search (semantic search with embeddings in Phase 2) | |
| results = await db.fetch_many( | |
| "knowledge_base", | |
| filters={"user_id": user_id}, | |
| order_by="created_at", | |
| ascending=False, | |
| limit=limit | |
| ) | |
| # Filter results that contain query terms (simple text match) | |
| query_lower = query.lower() | |
| filtered = [ | |
| r for r in results | |
| if query_lower in r.get("content", "").lower() | |
| ] | |
| return { | |
| "success": True, | |
| "query": query, | |
| "results": [ | |
| { | |
| "id": r["id"], | |
| "content": r["content"], | |
| "category": r.get("category"), | |
| "created_at": r["created_at"] | |
| } | |
| for r in filtered | |
| ], | |
| "result_count": len(filtered) | |
| } | |
| except Exception as e: | |
| logger.error(f"Recall memory error: {e}") | |
| return { | |
| "success": False, | |
| "error": str(e) | |
| } | |
| # Register tools | |
| ToolRegistry.register(RememberFactTool()) | |
| ToolRegistry.register(RecallMemoryTool()) | |