diff --git a/api/app/cache/__init__.py b/api/app/cache/__init__.py new file mode 100644 index 00000000..a79d4cb2 --- /dev/null +++ b/api/app/cache/__init__.py @@ -0,0 +1,11 @@ +""" +Cache 缓存模块 + +提供各种缓存功能的统一入口 +""" +from .memory import EmotionMemoryCache, ImplicitMemoryCache + +__all__ = [ + "EmotionMemoryCache", + "ImplicitMemoryCache", +] diff --git a/api/app/cache/memory/__init__.py b/api/app/cache/memory/__init__.py new file mode 100644 index 00000000..4ada3153 --- /dev/null +++ b/api/app/cache/memory/__init__.py @@ -0,0 +1,12 @@ +""" +Memory 缓存模块 + +提供记忆系统相关的缓存功能 +""" +from .emotion_memory import EmotionMemoryCache +from .implicit_memory import ImplicitMemoryCache + +__all__ = [ + "EmotionMemoryCache", + "ImplicitMemoryCache", +] diff --git a/api/app/cache/memory/emotion_memory.py b/api/app/cache/memory/emotion_memory.py new file mode 100644 index 00000000..45ea90de --- /dev/null +++ b/api/app/cache/memory/emotion_memory.py @@ -0,0 +1,134 @@ +""" +Emotion Suggestions Cache + +情绪个性化建议缓存模块 +用于缓存用户的情绪个性化建议数据 +""" +import json +import logging +from typing import Optional, Dict, Any +from datetime import datetime + +from app.aioRedis import aio_redis + +logger = logging.getLogger(__name__) + + +class EmotionMemoryCache: + """情绪建议缓存类""" + + # Key 前缀 + PREFIX = "cache:memory:emotion_memory" + + @classmethod + def _get_key(cls, *parts: str) -> str: + """生成 Redis key + + Args: + *parts: key 的各个部分 + + Returns: + 完整的 Redis key + """ + return ":".join([cls.PREFIX] + list(parts)) + + @classmethod + async def set_emotion_suggestions( + cls, + user_id: str, + suggestions_data: Dict[str, Any], + expire: int = 86400 + ) -> bool: + """设置用户情绪建议缓存 + + Args: + user_id: 用户ID(end_user_id) + suggestions_data: 建议数据字典,包含: + - health_summary: 健康状态摘要 + - suggestions: 建议列表 + - generated_at: 生成时间(可选) + expire: 过期时间(秒),默认24小时(86400秒) + + Returns: + 是否设置成功 + """ + try: + key = cls._get_key("suggestions", user_id) + + # 添加生成时间戳 + if "generated_at" not in suggestions_data: + suggestions_data["generated_at"] = datetime.now().isoformat() + + # 添加缓存标记 + suggestions_data["cached"] = True + + value = json.dumps(suggestions_data, ensure_ascii=False) + await aio_redis.set(key, value, ex=expire) + logger.info(f"设置情绪建议缓存成功: {key}, 过期时间: {expire}秒") + return True + except Exception as e: + logger.error(f"设置情绪建议缓存失败: {e}", exc_info=True) + return False + + @classmethod + async def get_emotion_suggestions(cls, user_id: str) -> Optional[Dict[str, Any]]: + """获取用户情绪建议缓存 + + Args: + user_id: 用户ID(end_user_id) + + Returns: + 建议数据字典,如果不存在或已过期返回 None + """ + try: + key = cls._get_key("suggestions", user_id) + value = await aio_redis.get(key) + + if value: + data = json.loads(value) + logger.info(f"成功获取情绪建议缓存: {key}") + return data + + logger.info(f"情绪建议缓存不存在或已过期: {key}") + return None + except Exception as e: + logger.error(f"获取情绪建议缓存失败: {e}", exc_info=True) + return None + + @classmethod + async def delete_emotion_suggestions(cls, user_id: str) -> bool: + """删除用户情绪建议缓存 + + Args: + user_id: 用户ID(end_user_id) + + Returns: + 是否删除成功 + """ + try: + key = cls._get_key("suggestions", user_id) + result = await aio_redis.delete(key) + logger.info(f"删除情绪建议缓存: {key}, 结果: {result}") + return result > 0 + except Exception as e: + logger.error(f"删除情绪建议缓存失败: {e}", exc_info=True) + return False + + @classmethod + async def get_suggestions_ttl(cls, user_id: str) -> int: + """获取情绪建议缓存的剩余过期时间 + + Args: + user_id: 用户ID(end_user_id) + + Returns: + 剩余秒数,-1表示永不过期,-2表示key不存在 + """ + try: + key = cls._get_key("suggestions", user_id) + ttl = await aio_redis.ttl(key) + logger.debug(f"情绪建议缓存TTL: {key} = {ttl}秒") + return ttl + except Exception as e: + logger.error(f"获取情绪建议缓存TTL失败: {e}") + return -2 diff --git a/api/app/cache/memory/implicit_memory.py b/api/app/cache/memory/implicit_memory.py new file mode 100644 index 00000000..21f08e9a --- /dev/null +++ b/api/app/cache/memory/implicit_memory.py @@ -0,0 +1,136 @@ +""" +Implicit Memory Profile Cache + +隐式记忆用户画像缓存模块 +用于缓存用户的完整画像数据(偏好标签、四维画像、兴趣领域、行为习惯) +""" +import json +import logging +from typing import Optional, Dict, Any +from datetime import datetime + +from app.aioRedis import aio_redis + +logger = logging.getLogger(__name__) + + +class ImplicitMemoryCache: + """隐式记忆用户画像缓存类""" + + # Key 前缀 + PREFIX = "cache:memory:implicit_memory" + + @classmethod + def _get_key(cls, *parts: str) -> str: + """生成 Redis key + + Args: + *parts: key 的各个部分 + + Returns: + 完整的 Redis key + """ + return ":".join([cls.PREFIX] + list(parts)) + + @classmethod + async def set_user_profile( + cls, + user_id: str, + profile_data: Dict[str, Any], + expire: int = 86400 + ) -> bool: + """设置用户完整画像缓存 + + Args: + user_id: 用户ID(end_user_id) + profile_data: 画像数据字典,包含: + - preferences: 偏好标签列表 + - portrait: 四维画像对象 + - interest_areas: 兴趣领域分布对象 + - habits: 行为习惯列表 + - generated_at: 生成时间(可选) + expire: 过期时间(秒),默认24小时(86400秒) + + Returns: + 是否设置成功 + """ + try: + key = cls._get_key("profile", user_id) + + # 添加生成时间戳 + if "generated_at" not in profile_data: + profile_data["generated_at"] = datetime.now().isoformat() + + # 添加缓存标记 + profile_data["cached"] = True + + value = json.dumps(profile_data, ensure_ascii=False) + await aio_redis.set(key, value, ex=expire) + logger.info(f"设置用户画像缓存成功: {key}, 过期时间: {expire}秒") + return True + except Exception as e: + logger.error(f"设置用户画像缓存失败: {e}", exc_info=True) + return False + + @classmethod + async def get_user_profile(cls, user_id: str) -> Optional[Dict[str, Any]]: + """获取用户完整画像缓存 + + Args: + user_id: 用户ID(end_user_id) + + Returns: + 画像数据字典,如果不存在或已过期返回 None + """ + try: + key = cls._get_key("profile", user_id) + value = await aio_redis.get(key) + + if value: + data = json.loads(value) + logger.info(f"成功获取用户画像缓存: {key}") + return data + + logger.info(f"用户画像缓存不存在或已过期: {key}") + return None + except Exception as e: + logger.error(f"获取用户画像缓存失败: {e}", exc_info=True) + return None + + @classmethod + async def delete_user_profile(cls, user_id: str) -> bool: + """删除用户完整画像缓存 + + Args: + user_id: 用户ID(end_user_id) + + Returns: + 是否删除成功 + """ + try: + key = cls._get_key("profile", user_id) + result = await aio_redis.delete(key) + logger.info(f"删除用户画像缓存: {key}, 结果: {result}") + return result > 0 + except Exception as e: + logger.error(f"删除用户画像缓存失败: {e}", exc_info=True) + return False + + @classmethod + async def get_profile_ttl(cls, user_id: str) -> int: + """获取用户画像缓存的剩余过期时间 + + Args: + user_id: 用户ID(end_user_id) + + Returns: + 剩余秒数,-1表示永不过期,-2表示key不存在 + """ + try: + key = cls._get_key("profile", user_id) + ttl = await aio_redis.ttl(key) + logger.debug(f"用户画像缓存TTL: {key} = {ttl}秒") + return ttl + except Exception as e: + logger.error(f"获取用户画像缓存TTL失败: {e}") + return -2 diff --git a/api/app/controllers/emotion_controller.py b/api/app/controllers/emotion_controller.py index 24bdc434..07e50774 100644 --- a/api/app/controllers/emotion_controller.py +++ b/api/app/controllers/emotion_controller.py @@ -231,9 +231,9 @@ async def get_emotion_suggestions( extra={"group_id": request.group_id} ) return fail( - BizCode.RESOURCE_NOT_FOUND, + BizCode.NOT_FOUND, "建议缓存不存在或已过期,请调用 /generate_suggestions 接口生成新建议", - None + "" ) api_logger.info( diff --git a/api/app/controllers/implicit_memory_controller.py b/api/app/controllers/implicit_memory_controller.py index eb7037ff..62d1e428 100644 --- a/api/app/controllers/implicit_memory_controller.py +++ b/api/app/controllers/implicit_memory_controller.py @@ -161,9 +161,9 @@ async def get_preference_tags( if cached_profile is None: api_logger.info(f"用户 {user_id} 的画像缓存不存在或已过期") return fail( - BizCode.RESOURCE_NOT_FOUND, + BizCode.NOT_FOUND, "画像缓存不存在或已过期,请调用 /generate_profile 接口生成新画像", - None + "" ) # Extract preferences from cache @@ -232,9 +232,9 @@ async def get_dimension_portrait( if cached_profile is None: api_logger.info(f"用户 {user_id} 的画像缓存不存在或已过期") return fail( - BizCode.RESOURCE_NOT_FOUND, + BizCode.NOT_FOUND, "画像缓存不存在或已过期,请调用 /generate_profile 接口生成新画像", - None + "" ) # Extract portrait from cache @@ -280,9 +280,9 @@ async def get_interest_area_distribution( if cached_profile is None: api_logger.info(f"用户 {user_id} 的画像缓存不存在或已过期") return fail( - BizCode.RESOURCE_NOT_FOUND, + BizCode.NOT_FOUND, "画像缓存不存在或已过期,请调用 /generate_profile 接口生成新画像", - None + "" ) # Extract interest areas from cache @@ -332,9 +332,9 @@ async def get_behavior_habits( if cached_profile is None: api_logger.info(f"用户 {user_id} 的画像缓存不存在或已过期") return fail( - BizCode.RESOURCE_NOT_FOUND, + BizCode.NOT_FOUND, "画像缓存不存在或已过期,请调用 /generate_profile 接口生成新画像", - None + "" ) # Extract habits from cache diff --git a/api/app/core/config.py b/api/app/core/config.py index 5f4f91c4..01983457 100644 --- a/api/app/core/config.py +++ b/api/app/core/config.py @@ -38,6 +38,7 @@ class Settings: REDIS_PORT: int = int(os.getenv("REDIS_PORT", "6379")) REDIS_DB: int = int(os.getenv("REDIS_DB", "1")) REDIS_PASSWORD: str = os.getenv("REDIS_PASSWORD", "") + # ElasticSearch configuration ELASTICSEARCH_HOST: str = os.getenv("ELASTICSEARCH_HOST", "https://127.0.0.1") diff --git a/api/app/models/__init__.py b/api/app/models/__init__.py index f45991cd..81cc6ead 100644 --- a/api/app/models/__init__.py +++ b/api/app/models/__init__.py @@ -27,8 +27,6 @@ from .tool_model import ( ToolExecution, ToolType, ToolStatus, AuthType, ExecutionStatus ) from .memory_perceptual_model import MemoryPerceptualModel -from .emotion_suggestions_cache_model import EmotionSuggestionsCache -from .implicit_memory_cache_model import ImplicitMemoryCache __all__ = [ "Tenants", @@ -79,6 +77,4 @@ __all__ = [ "AuthType", "ExecutionStatus", "MemoryPerceptualModel", - "EmotionSuggestionsCache", - "ImplicitMemoryCache" ] diff --git a/api/app/models/emotion_suggestions_cache_model.py b/api/app/models/emotion_suggestions_cache_model.py deleted file mode 100644 index 9b32f424..00000000 --- a/api/app/models/emotion_suggestions_cache_model.py +++ /dev/null @@ -1,24 +0,0 @@ -"""情绪建议缓存模型""" - -import uuid -import datetime -from sqlalchemy import Column, String, Text, Integer, DateTime, JSON -from sqlalchemy.dialects.postgresql import UUID -from app.db import Base - - -class EmotionSuggestionsCache(Base): - """情绪建议缓存表 - - 用于缓存个性化情绪建议,减少 LLM 调用成本,提升响应速度。 - """ - __tablename__ = "emotion_suggestions_cache" - - id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True) - end_user_id = Column(String(255), nullable=False, unique=True, index=True, comment="终端用户ID(组ID)") - health_summary = Column(Text, nullable=False, comment="健康状态摘要") - suggestions = Column(JSON, nullable=False, comment="建议列表(JSON格式)") - generated_at = Column(DateTime, nullable=False, default=datetime.datetime.now, comment="生成时间") - expires_at = Column(DateTime, nullable=True, comment="过期时间") - created_at = Column(DateTime, default=datetime.datetime.now) - updated_at = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now) diff --git a/api/app/models/implicit_memory_cache_model.py b/api/app/models/implicit_memory_cache_model.py deleted file mode 100644 index 32defbab..00000000 --- a/api/app/models/implicit_memory_cache_model.py +++ /dev/null @@ -1,27 +0,0 @@ -"""隐性记忆缓存模型""" - -import uuid -import datetime -from sqlalchemy import Column, String, Integer, DateTime, JSON -from sqlalchemy.dialects.postgresql import UUID -from app.db import Base - - -class ImplicitMemoryCache(Base): - """隐性记忆缓存表 - - 用于缓存用户的完整隐性记忆画像,包括偏好标签、四维画像、兴趣领域和行为习惯。 - 减少 LLM 调用成本,提升响应速度。 - """ - __tablename__ = "implicit_memory_cache" - - id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True) - end_user_id = Column(String(255), nullable=False, unique=True, index=True, comment="终端用户ID") - preferences = Column(JSON, nullable=False, comment="偏好标签列表(JSON格式)") - portrait = Column(JSON, nullable=False, comment="四维画像对象(JSON格式)") - interest_areas = Column(JSON, nullable=False, comment="兴趣领域分布对象(JSON格式)") - habits = Column(JSON, nullable=False, comment="行为习惯列表(JSON格式)") - generated_at = Column(DateTime, nullable=False, default=datetime.datetime.now, comment="生成时间") - expires_at = Column(DateTime, nullable=True, comment="过期时间") - created_at = Column(DateTime, default=datetime.datetime.now) - updated_at = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now) diff --git a/api/app/repositories/emotion_suggestions_cache_repository.py b/api/app/repositories/emotion_suggestions_cache_repository.py deleted file mode 100644 index 1c0430d5..00000000 --- a/api/app/repositories/emotion_suggestions_cache_repository.py +++ /dev/null @@ -1,163 +0,0 @@ -"""情绪建议缓存仓储层""" - -from sqlalchemy.orm import Session -from typing import Optional, Dict, Any -import datetime - -from app.models.emotion_suggestions_cache_model import EmotionSuggestionsCache -from app.core.logging_config import get_db_logger - -# 获取数据库专用日志器 -db_logger = get_db_logger() - - -class EmotionSuggestionsCacheRepository: - """情绪建议缓存仓储类""" - - def __init__(self, db: Session): - self.db = db - - def get_by_end_user_id(self, end_user_id: str) -> Optional[EmotionSuggestionsCache]: - """根据终端用户ID获取缓存 - - Args: - end_user_id: 终端用户ID(组ID) - - Returns: - 缓存记录,如果不存在返回 None - """ - try: - cache = ( - self.db.query(EmotionSuggestionsCache) - .filter(EmotionSuggestionsCache.end_user_id == end_user_id) - .first() - ) - if cache: - db_logger.info(f"成功获取用户 {end_user_id} 的情绪建议缓存") - else: - db_logger.info(f"用户 {end_user_id} 的情绪建议缓存不存在") - return cache - except Exception as e: - db_logger.error(f"获取用户 {end_user_id} 的情绪建议缓存失败: {str(e)}") - raise - - def create_or_update( - self, - end_user_id: str, - health_summary: str, - suggestions: list, - expires_hours: int = 24 - ) -> EmotionSuggestionsCache: - """创建或更新缓存 - - Args: - end_user_id: 终端用户ID(组ID) - health_summary: 健康状态摘要 - suggestions: 建议列表 - expires_hours: 过期时间(小时),默认24小时 - - Returns: - 缓存记录 - """ - try: - # 查找现有记录 - cache = self.get_by_end_user_id(end_user_id) - - now = datetime.datetime.now() - expires_at = now + datetime.timedelta(hours=expires_hours) - - if cache: - # 更新现有记录 - cache.health_summary = health_summary - cache.suggestions = suggestions - cache.generated_at = now - cache.expires_at = expires_at - cache.updated_at = now - db_logger.info(f"更新用户 {end_user_id} 的情绪建议缓存") - else: - # 创建新记录 - cache = EmotionSuggestionsCache( - end_user_id=end_user_id, - health_summary=health_summary, - suggestions=suggestions, - generated_at=now, - expires_at=expires_at, - created_at=now, - updated_at=now - ) - self.db.add(cache) - db_logger.info(f"创建用户 {end_user_id} 的情绪建议缓存") - - self.db.commit() - self.db.refresh(cache) - return cache - except Exception as e: - self.db.rollback() - db_logger.error(f"创建或更新用户 {end_user_id} 的情绪建议缓存失败: {str(e)}") - raise - - def delete_by_end_user_id(self, end_user_id: str) -> bool: - """删除缓存 - - Args: - end_user_id: 终端用户ID(组ID) - - Returns: - 是否删除成功 - """ - try: - cache = self.get_by_end_user_id(end_user_id) - if cache: - self.db.delete(cache) - self.db.commit() - db_logger.info(f"删除用户 {end_user_id} 的情绪建议缓存") - return True - return False - except Exception as e: - self.db.rollback() - db_logger.error(f"删除用户 {end_user_id} 的情绪建议缓存失败: {str(e)}") - raise - - @staticmethod - def is_expired(cache: EmotionSuggestionsCache) -> bool: - """检查缓存是否过期 - - Args: - cache: 缓存记录 - - Returns: - 是否过期 - """ - if cache.expires_at is None: - return False - return datetime.datetime.now() > cache.expires_at - - -# 便捷函数 -def get_cache_by_end_user_id(db: Session, end_user_id: str) -> Optional[EmotionSuggestionsCache]: - """根据终端用户ID获取缓存""" - repo = EmotionSuggestionsCacheRepository(db) - return repo.get_by_end_user_id(end_user_id) - - -def create_or_update_cache( - db: Session, - end_user_id: str, - health_summary: str, - suggestions: list, - expires_hours: int = 24 -) -> EmotionSuggestionsCache: - """创建或更新缓存""" - repo = EmotionSuggestionsCacheRepository(db) - return repo.create_or_update(end_user_id, health_summary, suggestions, expires_hours) - - -def delete_cache_by_end_user_id(db: Session, end_user_id: str) -> bool: - """删除缓存""" - repo = EmotionSuggestionsCacheRepository(db) - return repo.delete_by_end_user_id(end_user_id) - - -def is_cache_expired(cache: EmotionSuggestionsCache) -> bool: - """检查缓存是否过期""" - return EmotionSuggestionsCacheRepository.is_expired(cache) diff --git a/api/app/repositories/implicit_memory_cache_repository.py b/api/app/repositories/implicit_memory_cache_repository.py deleted file mode 100644 index 65356980..00000000 --- a/api/app/repositories/implicit_memory_cache_repository.py +++ /dev/null @@ -1,175 +0,0 @@ -"""隐性记忆缓存仓储层""" - -from sqlalchemy.orm import Session -from typing import Optional, Dict, Any -import datetime - -from app.models.implicit_memory_cache_model import ImplicitMemoryCache -from app.core.logging_config import get_db_logger - -# 获取数据库专用日志器 -db_logger = get_db_logger() - - -class ImplicitMemoryCacheRepository: - """隐性记忆缓存仓储类""" - - def __init__(self, db: Session): - self.db = db - - def get_by_end_user_id(self, end_user_id: str) -> Optional[ImplicitMemoryCache]: - """根据终端用户ID获取缓存 - - Args: - end_user_id: 终端用户ID - - Returns: - 缓存记录,如果不存在返回 None - """ - try: - cache = ( - self.db.query(ImplicitMemoryCache) - .filter(ImplicitMemoryCache.end_user_id == end_user_id) - .first() - ) - if cache: - db_logger.info(f"成功获取用户 {end_user_id} 的隐性记忆缓存") - else: - db_logger.info(f"用户 {end_user_id} 的隐性记忆缓存不存在") - return cache - except Exception as e: - db_logger.error(f"获取用户 {end_user_id} 的隐性记忆缓存失败: {str(e)}") - raise - - def create_or_update( - self, - end_user_id: str, - preferences: list, - portrait: dict, - interest_areas: dict, - habits: list, - expires_hours: int = 168 # 默认7天 - ) -> ImplicitMemoryCache: - """创建或更新缓存 - - Args: - end_user_id: 终端用户ID - preferences: 偏好标签列表 - portrait: 四维画像对象 - interest_areas: 兴趣领域分布对象 - habits: 行为习惯列表 - expires_hours: 过期时间(小时),默认168小时(7天) - - Returns: - 缓存记录 - """ - try: - # 查找现有记录 - cache = self.get_by_end_user_id(end_user_id) - - now = datetime.datetime.now() - expires_at = now + datetime.timedelta(hours=expires_hours) - - if cache: - # 更新现有记录 - cache.preferences = preferences - cache.portrait = portrait - cache.interest_areas = interest_areas - cache.habits = habits - cache.generated_at = now - cache.expires_at = expires_at - cache.updated_at = now - db_logger.info(f"更新用户 {end_user_id} 的隐性记忆缓存") - else: - # 创建新记录 - cache = ImplicitMemoryCache( - end_user_id=end_user_id, - preferences=preferences, - portrait=portrait, - interest_areas=interest_areas, - habits=habits, - generated_at=now, - expires_at=expires_at, - created_at=now, - updated_at=now - ) - self.db.add(cache) - db_logger.info(f"创建用户 {end_user_id} 的隐性记忆缓存") - - self.db.commit() - self.db.refresh(cache) - return cache - except Exception as e: - self.db.rollback() - db_logger.error(f"创建或更新用户 {end_user_id} 的隐性记忆缓存失败: {str(e)}") - raise - - def delete_by_end_user_id(self, end_user_id: str) -> bool: - """删除缓存 - - Args: - end_user_id: 终端用户ID - - Returns: - 是否删除成功 - """ - try: - cache = self.get_by_end_user_id(end_user_id) - if cache: - self.db.delete(cache) - self.db.commit() - db_logger.info(f"删除用户 {end_user_id} 的隐性记忆缓存") - return True - return False - except Exception as e: - self.db.rollback() - db_logger.error(f"删除用户 {end_user_id} 的隐性记忆缓存失败: {str(e)}") - raise - - @staticmethod - def is_expired(cache: ImplicitMemoryCache) -> bool: - """检查缓存是否过期 - - Args: - cache: 缓存记录 - - Returns: - 是否过期 - """ - if cache.expires_at is None: - return False - return datetime.datetime.now() > cache.expires_at - - -# 便捷函数 -def get_cache_by_end_user_id(db: Session, end_user_id: str) -> Optional[ImplicitMemoryCache]: - """根据终端用户ID获取缓存""" - repo = ImplicitMemoryCacheRepository(db) - return repo.get_by_end_user_id(end_user_id) - - -def create_or_update_cache( - db: Session, - end_user_id: str, - preferences: list, - portrait: dict, - interest_areas: dict, - habits: list, - expires_hours: int = 168 -) -> ImplicitMemoryCache: - """创建或更新缓存""" - repo = ImplicitMemoryCacheRepository(db) - return repo.create_or_update( - end_user_id, preferences, portrait, interest_areas, habits, expires_hours - ) - - -def delete_cache_by_end_user_id(db: Session, end_user_id: str) -> bool: - """删除缓存""" - repo = ImplicitMemoryCacheRepository(db) - return repo.delete_by_end_user_id(end_user_id) - - -def is_cache_expired(cache: ImplicitMemoryCache) -> bool: - """检查缓存是否过期""" - return ImplicitMemoryCacheRepository.is_expired(cache) diff --git a/api/app/services/emotion_analytics_service.py b/api/app/services/emotion_analytics_service.py index 50773b91..601d2921 100644 --- a/api/app/services/emotion_analytics_service.py +++ b/api/app/services/emotion_analytics_service.py @@ -711,45 +711,32 @@ class EmotionAnalyticsService: end_user_id: str, db: Session, ) -> Optional[Dict[str, Any]]: - """从缓存获取个性化情绪建议 + """从 Redis 缓存获取个性化情绪建议 Args: end_user_id: 宿主ID(用户组ID) - db: 数据库会话 + db: 数据库会话(保留参数以保持接口兼容性) Returns: Dict: 缓存的建议数据,如果不存在或已过期返回 None """ try: - from app.repositories.emotion_suggestions_cache_repository import ( - EmotionSuggestionsCacheRepository, - ) + from app.cache.memory.emotion_memory import EmotionMemoryCache - logger.info(f"尝试从缓存获取情绪建议: user={end_user_id}") + logger.info(f"尝试从 Redis 缓存获取情绪建议: user={end_user_id}") - cache_repo = EmotionSuggestionsCacheRepository(db) - cache = cache_repo.get_by_end_user_id(end_user_id) + # 从 Redis 获取缓存 + cached_data = await EmotionMemoryCache.get_emotion_suggestions(end_user_id) - if cache is None: - logger.info(f"用户 {end_user_id} 的建议缓存不存在") + if cached_data is None: + logger.info(f"用户 {end_user_id} 的建议缓存不存在或已过期") return None - # 检查是否过期 - if cache_repo.is_expired(cache): - logger.info(f"用户 {end_user_id} 的建议缓存已过期") - return None - - logger.info(f"成功从缓存获取建议: user={end_user_id}") - - return { - "health_summary": cache.health_summary, - "suggestions": cache.suggestions, - "generated_at": cache.generated_at.isoformat(), - "cached": True - } + logger.info(f"成功从 Redis 缓存获取建议: user={end_user_id}") + return cached_data except Exception as e: - logger.error(f"从缓存获取建议失败: {str(e)}", exc_info=True) + logger.error(f"从 Redis 缓存获取建议失败: {str(e)}", exc_info=True) return None async def save_suggestions_cache( @@ -759,30 +746,33 @@ class EmotionAnalyticsService: db: Session, expires_hours: int = 24 ) -> None: - """保存建议到缓存 + """保存建议到 Redis 缓存 Args: end_user_id: 宿主ID(用户组ID) suggestions_data: 建议数据 - db: 数据库会话 - expires_hours: 过期时间(小时) + db: 数据库会话(保留参数以保持接口兼容性) + expires_hours: 过期时间(小时),默认24小时 """ try: - from app.repositories.emotion_suggestions_cache_repository import ( - EmotionSuggestionsCacheRepository, + from app.cache.memory.emotion_memory import EmotionMemoryCache + + logger.info(f"保存建议到 Redis 缓存: user={end_user_id}, expires={expires_hours}小时") + + # 计算过期时间(秒) + expire_seconds = expires_hours * 3600 + + # 保存到 Redis + success = await EmotionMemoryCache.set_emotion_suggestions( + user_id=end_user_id, + suggestions_data=suggestions_data, + expire=expire_seconds ) - logger.info(f"保存建议到缓存: user={end_user_id}") - - cache_repo = EmotionSuggestionsCacheRepository(db) - cache_repo.create_or_update( - end_user_id=end_user_id, - health_summary=suggestions_data["health_summary"], - suggestions=suggestions_data["suggestions"], - expires_hours=expires_hours - ) - - logger.info(f"建议缓存保存成功: user={end_user_id}") + if success: + logger.info(f"建议缓存保存成功: user={end_user_id}") + else: + logger.warning(f"建议缓存保存失败: user={end_user_id}") except Exception as e: logger.error(f"保存建议缓存失败: {str(e)}", exc_info=True) diff --git a/api/app/services/implicit_memory_service.py b/api/app/services/implicit_memory_service.py index c98f14bc..106fa808 100644 --- a/api/app/services/implicit_memory_service.py +++ b/api/app/services/implicit_memory_service.py @@ -418,48 +418,32 @@ class ImplicitMemoryService: end_user_id: str, db: Session ) -> Optional[dict]: - """从缓存获取完整用户画像 + """从 Redis 缓存获取完整用户画像 Args: end_user_id: 终端用户ID - db: 数据库会话 + db: 数据库会话(保留参数以保持接口兼容性) Returns: Dict: 缓存的画像数据,如果不存在或已过期返回 None """ try: - from app.repositories.implicit_memory_cache_repository import ( - ImplicitMemoryCacheRepository, - ) + from app.cache.memory.implicit_memory import ImplicitMemoryCache - logger.info(f"尝试从缓存获取用户画像: user={end_user_id}") + logger.info(f"尝试从 Redis 缓存获取用户画像: user={end_user_id}") - cache_repo = ImplicitMemoryCacheRepository(db) - cache = cache_repo.get_by_end_user_id(end_user_id) + # 从 Redis 获取缓存 + cached_data = await ImplicitMemoryCache.get_user_profile(end_user_id) - if cache is None: - logger.info(f"用户 {end_user_id} 的画像缓存不存在") + if cached_data is None: + logger.info(f"用户 {end_user_id} 的画像缓存不存在或已过期") return None - # 检查是否过期 - if cache_repo.is_expired(cache): - logger.info(f"用户 {end_user_id} 的画像缓存已过期") - return None - - logger.info(f"成功从缓存获取用户画像: user={end_user_id}") - - return { - "end_user_id": cache.end_user_id, - "preferences": cache.preferences, - "portrait": cache.portrait, - "interest_areas": cache.interest_areas, - "habits": cache.habits, - "generated_at": cache.generated_at.isoformat(), - "cached": True - } + logger.info(f"成功从 Redis 缓存获取用户画像: user={end_user_id}") + return cached_data except Exception as e: - logger.error(f"从缓存获取用户画像失败: {str(e)}", exc_info=True) + logger.error(f"从 Redis 缓存获取用户画像失败: {str(e)}", exc_info=True) return None async def save_profile_cache( @@ -469,32 +453,33 @@ class ImplicitMemoryService: db: Session, expires_hours: int = 168 # 默认7天 ) -> None: - """保存用户画像到缓存 + """保存用户画像到 Redis 缓存 Args: end_user_id: 终端用户ID profile_data: 画像数据 - db: 数据库会话 + db: 数据库会话(保留参数以保持接口兼容性) expires_hours: 过期时间(小时),默认168小时(7天) """ try: - from app.repositories.implicit_memory_cache_repository import ( - ImplicitMemoryCacheRepository, + from app.cache.memory.implicit_memory import ImplicitMemoryCache + + logger.info(f"保存用户画像到 Redis 缓存: user={end_user_id}, expires={expires_hours}小时") + + # 计算过期时间(秒) + expire_seconds = expires_hours * 3600 + + # 保存到 Redis + success = await ImplicitMemoryCache.set_user_profile( + user_id=end_user_id, + profile_data=profile_data, + expire=expire_seconds ) - logger.info(f"保存用户画像到缓存: user={end_user_id}") - - cache_repo = ImplicitMemoryCacheRepository(db) - cache_repo.create_or_update( - end_user_id=end_user_id, - preferences=profile_data["preferences"], - portrait=profile_data["portrait"], - interest_areas=profile_data["interest_areas"], - habits=profile_data["habits"], - expires_hours=expires_hours - ) - - logger.info(f"用户画像缓存保存成功: user={end_user_id}") + if success: + logger.info(f"用户画像缓存保存成功: user={end_user_id}") + else: + logger.warning(f"用户画像缓存保存失败: user={end_user_id}") except Exception as e: logger.error(f"保存用户画像缓存失败: {str(e)}", exc_info=True)