feat(memory): sync user entity aliases and metadata to PostgreSQL
- Add `aliases` and `end_user_id` fields to user entity dicts in `collect_user_entities_for_metadata` so downstream tasks can write them to PostgreSQL - Add `update_aliases_and_metadata` method to `EndUserInfoRepository` for incremental, case-insensitive dedup merge of aliases and structured metadata fields - Add `_sync_end_user_info_pg` helper in tasks.py that writes aliases and extracted metadata to `end_user_info`, and back-fills `end_user.other_name` when empty - Call `_sync_end_user_info_pg` from `extract_metadata_batch_task` after Neo4j write, and also when no new metadata but aliases exist - Filter `meta_data` response in `UserMemoryService.get_end_user_info` to expose only four core fields: goals, traits, interests, core_facts
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
终端用户信息仓储层
|
||||
"""
|
||||
import uuid
|
||||
from typing import List, Optional
|
||||
from typing import Dict, List, Optional
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.models.end_user_info_model import EndUserInfo
|
||||
@@ -69,3 +69,72 @@ class EndUserInfoRepository:
|
||||
self.db.commit()
|
||||
logger.info(f"删除用户所有信息记录: end_user_id={end_user_id}, count={count}")
|
||||
return count
|
||||
|
||||
def update_aliases_and_metadata(
|
||||
self,
|
||||
end_user_id: uuid.UUID,
|
||||
new_aliases: Optional[List[str]] = None,
|
||||
new_metadata: Optional[dict] = None,
|
||||
) -> Optional[EndUserInfo]:
|
||||
"""增量更新用户别名列表和元数据。
|
||||
|
||||
- aliases:将 new_aliases 合并到现有列表(去重,忽略大小写),不覆盖
|
||||
- meta_data:将 new_metadata 的各字段列表合并到现有 meta_data(去重),不覆盖
|
||||
- other_name:若当前为空且 aliases 非空,则取 aliases[0] 作为 other_name
|
||||
|
||||
Args:
|
||||
end_user_id: 终端用户 ID
|
||||
new_aliases: 本次新增的别名列表
|
||||
new_metadata: 本次提取的 extracted_metadata 字典
|
||||
|
||||
Returns:
|
||||
更新后的 EndUserInfo,若记录不存在则返回 None
|
||||
"""
|
||||
end_user_info = self.get_by_end_user_id(end_user_id)
|
||||
if not end_user_info:
|
||||
logger.warning(f"[EndUserInfo] 记录不存在,跳过更新: end_user_id={end_user_id}")
|
||||
return None
|
||||
|
||||
changed = False
|
||||
|
||||
# ── 合并 aliases(去重,忽略大小写)──
|
||||
if new_aliases:
|
||||
existing = list(end_user_info.aliases or [])
|
||||
existing_lower = {a.lower() for a in existing}
|
||||
for alias in new_aliases:
|
||||
alias = alias.strip()
|
||||
if alias and alias.lower() not in existing_lower:
|
||||
existing.append(alias)
|
||||
existing_lower.add(alias.lower())
|
||||
end_user_info.aliases = existing
|
||||
changed = True
|
||||
|
||||
# ── 同步 other_name:取 aliases[0](若当前为空)──
|
||||
if end_user_info.aliases and not (end_user_info.other_name or "").strip():
|
||||
end_user_info.other_name = end_user_info.aliases[0]
|
||||
changed = True
|
||||
|
||||
# ── 合并 meta_data(各字段列表去重追加)──
|
||||
if new_metadata:
|
||||
existing_meta = dict(end_user_info.meta_data or {})
|
||||
for field, values in new_metadata.items():
|
||||
if not isinstance(values, list):
|
||||
continue
|
||||
existing_list = list(existing_meta.get(field) or [])
|
||||
existing_set = {str(v).lower() for v in existing_list}
|
||||
for v in values:
|
||||
if str(v).lower() not in existing_set:
|
||||
existing_list.append(v)
|
||||
existing_set.add(str(v).lower())
|
||||
existing_meta[field] = existing_list
|
||||
end_user_info.meta_data = existing_meta
|
||||
changed = True
|
||||
|
||||
if changed:
|
||||
self.db.commit()
|
||||
self.db.refresh(end_user_info)
|
||||
logger.info(
|
||||
f"[EndUserInfo] 更新完成: end_user_id={end_user_id}, "
|
||||
f"aliases_count={len(end_user_info.aliases or [])}"
|
||||
)
|
||||
return end_user_info
|
||||
|
||||
Reference in New Issue
Block a user