diff options
Diffstat (limited to 'packages/pipecat-sdk-python/src/supermemory_pipecat/utils.py')
| -rw-r--r-- | packages/pipecat-sdk-python/src/supermemory_pipecat/utils.py | 90 |
1 files changed, 79 insertions, 11 deletions
diff --git a/packages/pipecat-sdk-python/src/supermemory_pipecat/utils.py b/packages/pipecat-sdk-python/src/supermemory_pipecat/utils.py index d0f0e461..a27da256 100644 --- a/packages/pipecat-sdk-python/src/supermemory_pipecat/utils.py +++ b/packages/pipecat-sdk-python/src/supermemory_pipecat/utils.py @@ -1,6 +1,7 @@ """Utility functions for Supermemory Pipecat integration.""" -from typing import Dict, List +from datetime import datetime, timezone +from typing import Any, Dict, List, Union def get_last_user_message(messages: List[Dict[str, str]]) -> str | None: @@ -11,15 +12,58 @@ def get_last_user_message(messages: List[Dict[str, str]]) -> str | None: return None +def format_relative_time(iso_timestamp: str) -> str: + """Convert ISO timestamp to relative time string. + + Format rules: + - [just now] - within 30 minutes + - [Xmins ago] - 30-60 minutes + - [X hrs ago] - less than 1 day + - [Xd ago] - less than 1 week + - [X Jul] - more than 1 week, same year + - [X Jul, 2023] - different year + """ + try: + dt = datetime.fromisoformat(iso_timestamp.replace("Z", "+00:00")) + now = datetime.now(timezone.utc) + diff = now - dt + + seconds = diff.total_seconds() + minutes = seconds / 60 + hours = seconds / 3600 + days = seconds / 86400 + + if minutes < 30: + return "just now" + elif minutes < 60: + return f"{int(minutes)}mins ago" + elif hours < 24: + return f"{int(hours)} hrs ago" + elif days < 7: + return f"{int(days)}d ago" + elif dt.year == now.year: + return f"{dt.day} {dt.strftime('%b')}" + else: + return f"{dt.day} {dt.strftime('%b')}, {dt.year}" + except Exception: + return "" + + def deduplicate_memories( static: List[str], dynamic: List[str], - search_results: List[str], -) -> Dict[str, List[str]]: - """Deduplicate memories. Priority: static > dynamic > search.""" + search_results: List[Dict[str, Any]], +) -> Dict[str, Union[List[str], List[Dict[str, Any]]]]: + """Deduplicate memories. Priority: static > dynamic > search. + + Args: + static: List of static memory strings. + dynamic: List of dynamic memory strings. + search_results: List of search result dicts with 'memory' and 'updatedAt'. + """ seen = set() - def unique(memories): + def unique_strings(memories: List[str]) -> List[str]: out = [] for m in memories: if m not in seen: @@ -27,21 +71,33 @@ def deduplicate_memories( out.append(m) return out + def unique_search(results: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + out = [] + for r in results: + memory = r.get("memory", "") + if memory and memory not in seen: + seen.add(memory) + out.append(r) + return out + return { - "static": unique(static), - "dynamic": unique(dynamic), - "search_results": unique(search_results), + "static": unique_strings(static), + "dynamic": unique_strings(dynamic), + "search_results": unique_search(search_results), } def format_memories_to_text( - memories: Dict[str, List[str]], + memories: Dict[str, Union[List[str], List[Dict[str, Any]]]], system_prompt: str = "Based on previous conversations, I recall:\n\n", include_static: bool = True, include_dynamic: bool = True, include_search: bool = True, ) -> str: - """Format deduplicated memories into a text string for injection.""" + """Format deduplicated memories into a text string for injection. + + Search results include temporal context (e.g., '3d ago') from updatedAt. + """ sections = [] static = memories["static"] @@ -58,7 +114,19 @@ def format_memories_to_text( if include_search and search_results: sections.append("## Relevant Memories") - sections.append("\n".join(f"- {item}" for item in search_results)) + lines = [] + for item in search_results: + if isinstance(item, dict): + memory = item.get("memory", "") + updated_at = item.get("updatedAt", "") + time_str = format_relative_time(updated_at) if updated_at else "" + if time_str: + lines.append(f"- [{time_str}] {memory}") + else: + lines.append(f"- {memory}") + else: + lines.append(f"- {item}") + sections.append("\n".join(lines)) if not sections: return "" |