From b542388053ffe21cea09cb2be826468f569ae05c Mon Sep 17 00:00:00 2001 From: minwang Date: Fri, 1 May 2026 14:57:36 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E5=A4=8DPowerMem?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=94=BB=E5=83=8F=E6=9F=A5=E8=AF=A2=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E7=A9=BA=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 get_user_profile() 方法在缓存未命中时主动从 SDK 获取用户画 像,支持 profile_content 和 topics 两种格式,解决新对话中用户画像无法显示的问题 Co-Authored-By: Claude Sonnet 4.6 --- .../providers/memory/powermem/powermem.py | 53 +++++++++++++++++-- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/main/xiaozhi-server/core/providers/memory/powermem/powermem.py b/main/xiaozhi-server/core/providers/memory/powermem/powermem.py index cd55caf8..b3416e3a 100644 --- a/main/xiaozhi-server/core/providers/memory/powermem/powermem.py +++ b/main/xiaozhi-server/core/providers/memory/powermem/powermem.py @@ -319,9 +319,12 @@ class MemoryProvider(MemoryProviderBase): async def get_user_profile(self) -> str: """ Get user profile from PowerMem (only available in UserMemory mode). - - In PowerMem 0.3.0+, user profile is automatically extracted during add() - and cached in last_profile_content. + + Uses a cache-first strategy: + 1. Check if last_profile_content is already cached + 2. If cached, return immediately (performance optimization) + 3. If cache is empty, fetch from PowerMem SDK + 4. Store fetched profile in cache for next query Returns: Formatted user profile string or empty string if not available @@ -333,9 +336,49 @@ class MemoryProvider(MemoryProviderBase): logger.bind(tag=TAG).debug("User profile mode is not enabled") return "" - # Return cached profile content from last add() operation + # Return cached profile content if available (fast path) if self.last_profile_content: + logger.bind(tag=TAG).debug("Returning cached user profile") return self.last_profile_content - return "" + # Cache is empty, fetch from PowerMem SDK + logger.bind(tag=TAG).info("Cache miss, fetching user profile from PowerMem SDK") + try: + # Call UserMemory.profile() to get profile data + profile_data = await asyncio.to_thread( + self.memory_client.profile, + self.role_id + ) + + if not profile_data: + logger.bind(tag=TAG).warning("PowerMem SDK returned empty profile data") + return "" + + # Try to use profile_content first + profile_content = profile_data.get("profile_content") + if profile_content: + # Update cache with fetched profile_content + self.last_profile_content = profile_content + logger.bind(tag=TAG).info(f"Successfully fetched and cached user profile from profile_content (length: {len(self.last_profile_content)})") + logger.bind(tag=TAG).debug(f"User profile content: {self.last_profile_content}") + return self.last_profile_content + + # If profile_content is empty, fallback to topics + topics = profile_data.get("topics") + if topics: + import json + # Serialize topics dict to JSON string for structured profile + self.last_profile_content = json.dumps(topics, ensure_ascii=False, indent=2) + logger.bind(tag=TAG).info(f"Successfully fetched and cached user profile from topics (length: {len(self.last_profile_content)})") + logger.bind(tag=TAG).debug(f"User profile topics: {self.last_profile_content}") + return self.last_profile_content + + # Both profile_content and topics are empty + logger.bind(tag=TAG).warning("PowerMem SDK returned profile with empty profile_content and topics") + return "" + + except Exception as e: + logger.bind(tag=TAG).error(f"Failed to fetch user profile from SDK: {str(e)}") + logger.bind(tag=TAG).debug(f"Detailed error: {traceback.format_exc()}") + return ""