fix(memory): fix timezone and add generate_cache API endpoint


- Fix episodic memory time filter to use UTC (datetime.fromtimestamp with tz=timezone.utc)
  to match Neo4j stored UTC timestamps
- Add POST /v1/memory/analytics/generate_cache endpoint for cache generation via API Key

Modified files:
- api/app/services/memory_explicit_service.py
- api/app/controllers/service/user_memory_api_controller.py
This commit is contained in:
miao
2026-04-23 19:32:13 +08:00
parent 7ac0eff0b8
commit 4619b40d03
2 changed files with 40 additions and 7 deletions

View File

@@ -9,6 +9,7 @@
5./analytics/memory_insight - 记忆洞察接口 5./analytics/memory_insight - 记忆洞察接口
6./analytics/interest_distribution - 兴趣分布接口 6./analytics/interest_distribution - 兴趣分布接口
7./analytics/end_user_info - 终端用户信息接口 7./analytics/end_user_info - 终端用户信息接口
8./analytics/generate_cache - 缓存生成接口
路由前缀: /memory 路由前缀: /memory
@@ -19,7 +20,7 @@
from typing import Optional from typing import Optional
from fastapi import APIRouter, Depends, Header, Query, Request from fastapi import APIRouter, Depends, Header, Query, Request, Body
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.core.api_key_auth import require_api_key from app.core.api_key_auth import require_api_key
@@ -27,6 +28,7 @@ from app.core.api_key_utils import get_current_user_from_api_key, validate_end_u
from app.core.logging_config import get_business_logger from app.core.logging_config import get_business_logger
from app.db import get_db from app.db import get_db
from app.schemas.api_key_schema import ApiKeyAuth from app.schemas.api_key_schema import ApiKeyAuth
from app.schemas.memory_storage_schema import GenerateCacheRequest
# 包装内部服务 controller # 包装内部服务 controller
from app.controllers import user_memory_controllers, memory_agent_controller from app.controllers import user_memory_controllers, memory_agent_controller
@@ -194,4 +196,35 @@ async def get_end_user_info(
end_user_id=end_user_id, end_user_id=end_user_id,
current_user=current_user, current_user=current_user,
db=db, db=db,
) )
# ==================== 缓存生成 ====================
@router.post("/analytics/generate_cache")
@require_api_key(scopes=["memory"])
async def generate_cache(
request: Request,
api_key_auth: ApiKeyAuth = None,
db: Session = Depends(get_db),
message: str = Body(None, description="Request body"),
language_type: str = Header(default=None, alias="X-Language-Type"),
):
"""Trigger cache generation (user summary + memory insight) for an end user or all workspace users."""
body = await request.json()
cache_request = GenerateCacheRequest(**body)
current_user = get_current_user_from_api_key(db, api_key_auth)
if cache_request.end_user_id:
validate_end_user_in_workspace(db, cache_request.end_user_id, api_key_auth.workspace_id)
return await user_memory_controllers.generate_cache_api(
request=cache_request,
language_type=language_type,
current_user=current_user,
db=db,
)

View File

@@ -201,12 +201,12 @@ class MemoryExplicitService(MemoryBaseService):
where_clauses = ["s.end_user_id = $end_user_id"] where_clauses = ["s.end_user_id = $end_user_id"]
params = {"end_user_id": end_user_id} params = {"end_user_id": end_user_id}
# 时间戳筛选(毫秒时间戳转为 ISO 字符串,使用 Neo4j datetime() 精确比较) # 时间戳筛选(毫秒时间戳转为 UTC ISO 字符串,使用 Neo4j datetime() 精确比较)
if start_date is not None and end_date is not None: if start_date is not None and end_date is not None:
from datetime import datetime from datetime import datetime, timezone
start_dt = datetime.fromtimestamp(start_date / 1000) start_dt = datetime.fromtimestamp(start_date / 1000, tz=timezone.utc)
end_dt = datetime.fromtimestamp(end_date / 1000) end_dt = datetime.fromtimestamp(end_date / 1000, tz=timezone.utc)
# 开始时间取当天 00:00:00结束时间取当天 23:59:59.999999 # 开始时间取当天 UTC 00:00:00结束时间取当天 UTC 23:59:59.999999
start_iso = start_dt.strftime("%Y-%m-%dT") + "00:00:00.000000" start_iso = start_dt.strftime("%Y-%m-%dT") + "00:00:00.000000"
end_iso = end_dt.strftime("%Y-%m-%dT") + "23:59:59.999999" end_iso = end_dt.strftime("%Y-%m-%dT") + "23:59:59.999999"