新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
This commit is contained in:
@@ -9,7 +9,7 @@ from app.db import get_db
|
|||||||
from app.dependencies import cur_workspace_access_guard, get_current_user
|
from app.dependencies import cur_workspace_access_guard, get_current_user
|
||||||
from app.models import ModelApiKey
|
from app.models import ModelApiKey
|
||||||
from app.models.user_model import User
|
from app.models.user_model import User
|
||||||
from app.repositories import knowledge_repository
|
from app.repositories import knowledge_repository, WorkspaceRepository
|
||||||
from app.schemas.memory_agent_schema import UserInput, Write_UserInput
|
from app.schemas.memory_agent_schema import UserInput, Write_UserInput
|
||||||
from app.schemas.response_schema import ApiResponse
|
from app.schemas.response_schema import ApiResponse
|
||||||
from app.services import task_service, workspace_service
|
from app.services import task_service, workspace_service
|
||||||
@@ -616,8 +616,10 @@ async def get_knowledge_type_stats_api(
|
|||||||
@router.get("/analytics/hot_memory_tags/by_user", response_model=ApiResponse)
|
@router.get("/analytics/hot_memory_tags/by_user", response_model=ApiResponse)
|
||||||
async def get_hot_memory_tags_by_user_api(
|
async def get_hot_memory_tags_by_user_api(
|
||||||
end_user_id: Optional[str] = Query(None, description="用户ID(可选)"),
|
end_user_id: Optional[str] = Query(None, description="用户ID(可选)"),
|
||||||
|
language_type: Optional[str] ="zh",
|
||||||
limit: int = Query(20, description="返回标签数量限制"),
|
limit: int = Query(20, description="返回标签数量限制"),
|
||||||
current_user: User = Depends(get_current_user)
|
current_user: User = Depends(get_current_user),
|
||||||
|
db: Session=Depends(get_db),
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
获取指定用户的热门记忆标签
|
获取指定用户的热门记忆标签
|
||||||
@@ -628,10 +630,22 @@ async def get_hot_memory_tags_by_user_api(
|
|||||||
...
|
...
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
workspace_id=current_user.current_workspace_id
|
||||||
|
workspace_repo = WorkspaceRepository(db)
|
||||||
|
workspace_models = workspace_repo.get_workspace_models_configs(workspace_id)
|
||||||
|
|
||||||
|
if workspace_models:
|
||||||
|
model_id = workspace_models.get("llm", None)
|
||||||
|
else:
|
||||||
|
model_id = None
|
||||||
|
|
||||||
api_logger.info(f"Hot memory tags by user requested: end_user_id={end_user_id}")
|
api_logger.info(f"Hot memory tags by user requested: end_user_id={end_user_id}")
|
||||||
try:
|
try:
|
||||||
result = await memory_agent_service.get_hot_memory_tags_by_user(
|
result = await memory_agent_service.get_hot_memory_tags_by_user(
|
||||||
end_user_id=end_user_id,
|
end_user_id=end_user_id,
|
||||||
|
language_type=language_type,
|
||||||
|
model_id=model_id,
|
||||||
limit=limit
|
limit=limit
|
||||||
)
|
)
|
||||||
return success(data=result, msg="获取热门记忆标签成功")
|
return success(data=result, msg="获取热门记忆标签成功")
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from app.core.logging_config import get_api_logger
|
|||||||
from app.core.response_utils import success, fail
|
from app.core.response_utils import success, fail
|
||||||
from app.core.error_codes import BizCode
|
from app.core.error_codes import BizCode
|
||||||
from app.core.api_key_utils import timestamp_to_datetime
|
from app.core.api_key_utils import timestamp_to_datetime
|
||||||
|
from app.services.memory_base_service import Translation_English
|
||||||
from app.services.user_memory_service import (
|
from app.services.user_memory_service import (
|
||||||
UserMemoryService,
|
UserMemoryService,
|
||||||
analytics_memory_types,
|
analytics_memory_types,
|
||||||
@@ -20,7 +21,7 @@ from app.services.user_memory_service import (
|
|||||||
from app.services.memory_entity_relationship_service import MemoryEntityService,MemoryEmotion,MemoryInteraction
|
from app.services.memory_entity_relationship_service import MemoryEntityService,MemoryEmotion,MemoryInteraction
|
||||||
from app.schemas.response_schema import ApiResponse
|
from app.schemas.response_schema import ApiResponse
|
||||||
from app.schemas.memory_storage_schema import GenerateCacheRequest
|
from app.schemas.memory_storage_schema import GenerateCacheRequest
|
||||||
|
from app.repositories.workspace_repository import WorkspaceRepository
|
||||||
from app.schemas.end_user_schema import (
|
from app.schemas.end_user_schema import (
|
||||||
EndUserProfileResponse,
|
EndUserProfileResponse,
|
||||||
EndUserProfileUpdate,
|
EndUserProfileUpdate,
|
||||||
@@ -44,6 +45,7 @@ router = APIRouter(
|
|||||||
@router.get("/analytics/memory_insight/report", response_model=ApiResponse)
|
@router.get("/analytics/memory_insight/report", response_model=ApiResponse)
|
||||||
async def get_memory_insight_report_api(
|
async def get_memory_insight_report_api(
|
||||||
end_user_id: str,
|
end_user_id: str,
|
||||||
|
language_type: str = "zh",
|
||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
) -> dict:
|
) -> dict:
|
||||||
@@ -53,10 +55,18 @@ async def get_memory_insight_report_api(
|
|||||||
此接口仅查询数据库中已缓存的记忆洞察数据,不执行生成操作。
|
此接口仅查询数据库中已缓存的记忆洞察数据,不执行生成操作。
|
||||||
如需生成新的洞察报告,请使用专门的生成接口。
|
如需生成新的洞察报告,请使用专门的生成接口。
|
||||||
"""
|
"""
|
||||||
|
workspace_id = current_user.current_workspace_id
|
||||||
|
workspace_repo = WorkspaceRepository(db)
|
||||||
|
workspace_models = workspace_repo.get_workspace_models_configs(workspace_id)
|
||||||
|
|
||||||
|
if workspace_models:
|
||||||
|
model_id = workspace_models.get("llm", None)
|
||||||
|
else:
|
||||||
|
model_id = None
|
||||||
api_logger.info(f"记忆洞察报告查询请求: end_user_id={end_user_id}, user={current_user.username}")
|
api_logger.info(f"记忆洞察报告查询请求: end_user_id={end_user_id}, user={current_user.username}")
|
||||||
try:
|
try:
|
||||||
# 调用服务层获取缓存数据
|
# 调用服务层获取缓存数据
|
||||||
result = await user_memory_service.get_cached_memory_insight(db, end_user_id)
|
result = await user_memory_service.get_cached_memory_insight(db, end_user_id,model_id,language_type)
|
||||||
|
|
||||||
if result["is_cached"]:
|
if result["is_cached"]:
|
||||||
api_logger.info(f"成功返回缓存的记忆洞察报告: end_user_id={end_user_id}")
|
api_logger.info(f"成功返回缓存的记忆洞察报告: end_user_id={end_user_id}")
|
||||||
@@ -72,6 +82,7 @@ async def get_memory_insight_report_api(
|
|||||||
@router.get("/analytics/user_summary", response_model=ApiResponse)
|
@router.get("/analytics/user_summary", response_model=ApiResponse)
|
||||||
async def get_user_summary_api(
|
async def get_user_summary_api(
|
||||||
end_user_id: str,
|
end_user_id: str,
|
||||||
|
language_type: str="zh",
|
||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
) -> dict:
|
) -> dict:
|
||||||
@@ -81,10 +92,18 @@ async def get_user_summary_api(
|
|||||||
此接口仅查询数据库中已缓存的用户摘要数据,不执行生成操作。
|
此接口仅查询数据库中已缓存的用户摘要数据,不执行生成操作。
|
||||||
如需生成新的用户摘要,请使用专门的生成接口。
|
如需生成新的用户摘要,请使用专门的生成接口。
|
||||||
"""
|
"""
|
||||||
|
workspace_id = current_user.current_workspace_id
|
||||||
|
workspace_repo = WorkspaceRepository(db)
|
||||||
|
workspace_models = workspace_repo.get_workspace_models_configs(workspace_id)
|
||||||
|
|
||||||
|
if workspace_models:
|
||||||
|
model_id = workspace_models.get("llm", None)
|
||||||
|
else:
|
||||||
|
model_id = None
|
||||||
api_logger.info(f"用户摘要查询请求: end_user_id={end_user_id}, user={current_user.username}")
|
api_logger.info(f"用户摘要查询请求: end_user_id={end_user_id}, user={current_user.username}")
|
||||||
try:
|
try:
|
||||||
# 调用服务层获取缓存数据
|
# 调用服务层获取缓存数据
|
||||||
result = await user_memory_service.get_cached_user_summary(db, end_user_id)
|
result = await user_memory_service.get_cached_user_summary(db, end_user_id,model_id,language_type)
|
||||||
|
|
||||||
if result["is_cached"]:
|
if result["is_cached"]:
|
||||||
api_logger.info(f"成功返回缓存的用户摘要: end_user_id={end_user_id}")
|
api_logger.info(f"成功返回缓存的用户摘要: end_user_id={end_user_id}")
|
||||||
@@ -253,7 +272,6 @@ async def get_graph_data_api(
|
|||||||
depth=depth,
|
depth=depth,
|
||||||
center_node_id=center_node_id
|
center_node_id=center_node_id
|
||||||
)
|
)
|
||||||
|
|
||||||
# 检查是否有错误消息
|
# 检查是否有错误消息
|
||||||
if "message" in result and result["statistics"]["total_nodes"] == 0:
|
if "message" in result and result["statistics"]["total_nodes"] == 0:
|
||||||
api_logger.warning(f"图数据查询返回空结果: {result.get('message')}")
|
api_logger.warning(f"图数据查询返回空结果: {result.get('message')}")
|
||||||
@@ -274,11 +292,18 @@ async def get_graph_data_api(
|
|||||||
@router.get("/read_end_user/profile", response_model=ApiResponse)
|
@router.get("/read_end_user/profile", response_model=ApiResponse)
|
||||||
async def get_end_user_profile(
|
async def get_end_user_profile(
|
||||||
end_user_id: str,
|
end_user_id: str,
|
||||||
|
language_type: str = "zh",
|
||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
) -> dict:
|
) -> dict:
|
||||||
workspace_id = current_user.current_workspace_id
|
workspace_id = current_user.current_workspace_id
|
||||||
|
workspace_repo = WorkspaceRepository(db)
|
||||||
|
workspace_models = workspace_repo.get_workspace_models_configs(workspace_id)
|
||||||
|
|
||||||
|
if workspace_models:
|
||||||
|
model_id = workspace_models.get("llm", None)
|
||||||
|
else:
|
||||||
|
model_id = None
|
||||||
# 检查用户是否已选择工作空间
|
# 检查用户是否已选择工作空间
|
||||||
if workspace_id is None:
|
if workspace_id is None:
|
||||||
api_logger.warning(f"用户 {current_user.username} 尝试查询用户信息但未选择工作空间")
|
api_logger.warning(f"用户 {current_user.username} 尝试查询用户信息但未选择工作空间")
|
||||||
@@ -297,12 +322,19 @@ async def get_end_user_profile(
|
|||||||
api_logger.warning(f"终端用户不存在: end_user_id={end_user_id}")
|
api_logger.warning(f"终端用户不存在: end_user_id={end_user_id}")
|
||||||
return fail(BizCode.INVALID_PARAMETER, "终端用户不存在", f"end_user_id={end_user_id}")
|
return fail(BizCode.INVALID_PARAMETER, "终端用户不存在", f"end_user_id={end_user_id}")
|
||||||
|
|
||||||
|
other_name=end_user.other_name
|
||||||
|
position=end_user.position
|
||||||
|
department=end_user.department
|
||||||
|
if language_type!="zh":
|
||||||
|
other_name=await Translation_English(model_id,other_name)
|
||||||
|
position = await Translation_English(model_id, position)
|
||||||
|
department = await Translation_English(model_id, department)
|
||||||
# 构建响应数据
|
# 构建响应数据
|
||||||
profile_data = EndUserProfileResponse(
|
profile_data = EndUserProfileResponse(
|
||||||
id=end_user.id,
|
id=end_user.id,
|
||||||
other_name=end_user.other_name,
|
other_name=other_name,
|
||||||
position=end_user.position,
|
position=position,
|
||||||
department=end_user.department,
|
department=department,
|
||||||
contact=end_user.contact,
|
contact=end_user.contact,
|
||||||
phone=end_user.phone,
|
phone=end_user.phone,
|
||||||
hire_date=end_user.hire_date,
|
hire_date=end_user.hire_date,
|
||||||
@@ -396,12 +428,21 @@ async def update_end_user_profile(
|
|||||||
return fail(BizCode.INTERNAL_ERROR, "用户信息更新失败", str(e))
|
return fail(BizCode.INTERNAL_ERROR, "用户信息更新失败", str(e))
|
||||||
|
|
||||||
@router.get("/memory_space/timeline_memories", response_model=ApiResponse)
|
@router.get("/memory_space/timeline_memories", response_model=ApiResponse)
|
||||||
async def memory_space_timeline_of_shared_memories(id: str, label: str,
|
async def memory_space_timeline_of_shared_memories(id: str, label: str,language_type: str,
|
||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
):
|
):
|
||||||
|
workspace_id=current_user.current_workspace_id
|
||||||
|
workspace_repo = WorkspaceRepository(db)
|
||||||
|
workspace_models = workspace_repo.get_workspace_models_configs(workspace_id)
|
||||||
|
|
||||||
|
if workspace_models:
|
||||||
|
model_id = workspace_models.get("llm", None)
|
||||||
|
else:
|
||||||
|
model_id = None
|
||||||
MemoryEntity = MemoryEntityService(id, label)
|
MemoryEntity = MemoryEntityService(id, label)
|
||||||
timeline_memories_result = await MemoryEntity.get_timeline_memories_server()
|
timeline_memories_result = await MemoryEntity.get_timeline_memories_server(model_id, language_type)
|
||||||
|
|
||||||
return success(data=timeline_memories_result, msg="共同记忆时间线")
|
return success(data=timeline_memories_result, msg="共同记忆时间线")
|
||||||
@router.get("/memory_space/relationship_evolution", response_model=ApiResponse)
|
@router.get("/memory_space/relationship_evolution", response_model=ApiResponse)
|
||||||
async def memory_space_relationship_evolution(id: str, label: str,
|
async def memory_space_relationship_evolution(id: str, label: str,
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class EndUserProfileResponse(BaseModel):
|
|||||||
updatetime_profile: Optional[datetime.datetime] = Field(description="核心档案信息最后更新时间", default=None)
|
updatetime_profile: Optional[datetime.datetime] = Field(description="核心档案信息最后更新时间", default=None)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class EndUserProfileUpdate(BaseModel):
|
class EndUserProfileUpdate(BaseModel):
|
||||||
"""终端用户基本信息更新请求模型"""
|
"""终端用户基本信息更新请求模型"""
|
||||||
end_user_id: str = Field(description="终端用户ID")
|
end_user_id: str = Field(description="终端用户ID")
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ from app.db import get_db_context
|
|||||||
from app.models.knowledge_model import Knowledge, KnowledgeType
|
from app.models.knowledge_model import Knowledge, KnowledgeType
|
||||||
from app.repositories.neo4j.neo4j_connector import Neo4jConnector
|
from app.repositories.neo4j.neo4j_connector import Neo4jConnector
|
||||||
from app.schemas.memory_config_schema import ConfigurationError
|
from app.schemas.memory_config_schema import ConfigurationError
|
||||||
|
from app.services.memory_base_service import Translation_English
|
||||||
from app.services.memory_config_service import MemoryConfigService
|
from app.services.memory_config_service import MemoryConfigService
|
||||||
from app.services.memory_konwledges_server import (
|
from app.services.memory_konwledges_server import (
|
||||||
write_rag,
|
write_rag,
|
||||||
@@ -692,7 +693,9 @@ class MemoryAgentService:
|
|||||||
async def get_hot_memory_tags_by_user(
|
async def get_hot_memory_tags_by_user(
|
||||||
self,
|
self,
|
||||||
end_user_id: Optional[str] = None,
|
end_user_id: Optional[str] = None,
|
||||||
limit: int = 20
|
limit: int = 20,
|
||||||
|
model_id: Optional[str] = None,
|
||||||
|
language_type: Optional[str] = "zh"
|
||||||
) -> List[Dict[str, Any]]:
|
) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
获取指定用户的热门记忆标签
|
获取指定用户的热门记忆标签
|
||||||
@@ -710,7 +713,14 @@ class MemoryAgentService:
|
|||||||
try:
|
try:
|
||||||
# by_user=False 表示按 group_id 查询(在Neo4j中,group_id就是用户维度)
|
# by_user=False 表示按 group_id 查询(在Neo4j中,group_id就是用户维度)
|
||||||
tags = await get_hot_memory_tags(end_user_id, limit=limit, by_user=False)
|
tags = await get_hot_memory_tags(end_user_id, limit=limit, by_user=False)
|
||||||
payload = [{"name": t, "frequency": f} for t, f in tags]
|
payload=[]
|
||||||
|
for tag, freq in tags:
|
||||||
|
print(tag, freq)
|
||||||
|
if language_type!="zh":
|
||||||
|
tag=await Translation_English(model_id, tag)
|
||||||
|
payload.append({"name": tag, "frequency": freq})
|
||||||
|
else:
|
||||||
|
payload.append({"name": tag, "frequency": freq})
|
||||||
return payload
|
return payload
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"热门记忆标签查询失败: {e}")
|
logger.error(f"热门记忆标签查询失败: {e}")
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -16,6 +16,7 @@ import json
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from app.schemas.memory_episodic_schema import EmotionType
|
from app.schemas.memory_episodic_schema import EmotionType
|
||||||
|
from app.services.memory_base_service import Translation_English
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ class MemoryEntityService:
|
|||||||
self.id = id
|
self.id = id
|
||||||
self.table = table
|
self.table = table
|
||||||
self.connector = Neo4jConnector()
|
self.connector = Neo4jConnector()
|
||||||
async def get_timeline_memories_server(self):
|
async def get_timeline_memories_server(self,model_id, language_type):
|
||||||
"""
|
"""
|
||||||
获取时间线记忆数据
|
获取时间线记忆数据
|
||||||
|
|
||||||
@@ -48,10 +49,10 @@ class MemoryEntityService:
|
|||||||
logger.info(f"获取时间线记忆数据 - ID: {self.id}, Table: {self.table}")
|
logger.info(f"获取时间线记忆数据 - ID: {self.id}, Table: {self.table}")
|
||||||
|
|
||||||
# 根据表类型选择查询
|
# 根据表类型选择查询
|
||||||
if self.table == 'Statement':
|
if self.table == 'Statement':
|
||||||
# Statement只需要输入ID,使用简化查询
|
# Statement只需要输入ID,使用简化查询
|
||||||
results = await self.connector.execute_query(Memory_Timeline_Statement, id=self.id)
|
results = await self.connector.execute_query(Memory_Timeline_Statement, id=self.id)
|
||||||
elif self.table == 'ExtractedEntity':
|
elif self.table == 'ExtractedEntity':
|
||||||
# ExtractedEntity类型查询
|
# ExtractedEntity类型查询
|
||||||
results = await self.connector.execute_query(Memory_Timeline_ExtractedEntity, id=self.id)
|
results = await self.connector.execute_query(Memory_Timeline_ExtractedEntity, id=self.id)
|
||||||
else:
|
else:
|
||||||
@@ -62,7 +63,7 @@ class MemoryEntityService:
|
|||||||
logger.info(f"时间线查询结果类型: {type(results)}, 长度: {len(results) if isinstance(results, list) else 'N/A'}")
|
logger.info(f"时间线查询结果类型: {type(results)}, 长度: {len(results) if isinstance(results, list) else 'N/A'}")
|
||||||
|
|
||||||
# 处理查询结果
|
# 处理查询结果
|
||||||
timeline_data = self._process_timeline_results(results)
|
timeline_data =await self._process_timeline_results(results, model_id, language_type)
|
||||||
|
|
||||||
logger.info(f"成功获取时间线记忆数据: 总计 {len(timeline_data.get('timelines_memory', []))} 条")
|
logger.info(f"成功获取时间线记忆数据: 总计 {len(timeline_data.get('timelines_memory', []))} 条")
|
||||||
|
|
||||||
@@ -71,12 +72,14 @@ class MemoryEntityService:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"获取时间线记忆数据失败: {str(e)}", exc_info=True)
|
logger.error(f"获取时间线记忆数据失败: {str(e)}", exc_info=True)
|
||||||
return str(e)
|
return str(e)
|
||||||
def _process_timeline_results(self, results: List[Dict[str, Any]]) -> Dict[str, Any]:
|
async def _process_timeline_results(self, results: List[Dict[str, Any]], model_id: str, language_type: str) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
处理时间线查询结果
|
处理时间线查询结果
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
results: Neo4j查询结果
|
results: Neo4j查询结果
|
||||||
|
model_id: 模型ID用于翻译
|
||||||
|
language_type: 语言类型 ('zh' 或其他)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
处理后的时间线数据字典
|
处理后的时间线数据字典
|
||||||
@@ -104,19 +107,19 @@ class MemoryEntityService:
|
|||||||
# 处理MemorySummary
|
# 处理MemorySummary
|
||||||
summary = data.get('MemorySummary')
|
summary = data.get('MemorySummary')
|
||||||
if summary is not None:
|
if summary is not None:
|
||||||
processed_summary = self._process_field_value(summary, "MemorySummary")
|
processed_summary = await self._process_field_value(summary, "MemorySummary")
|
||||||
memory_summary_list.extend(processed_summary)
|
memory_summary_list.extend(processed_summary)
|
||||||
|
|
||||||
# 处理Statement
|
# 处理Statement
|
||||||
statement = data.get('statement')
|
statement = data.get('statement')
|
||||||
if statement is not None:
|
if statement is not None:
|
||||||
processed_statement = self._process_field_value(statement, "Statement")
|
processed_statement = await self._process_field_value(statement, "Statement")
|
||||||
statement_list.extend(processed_statement)
|
statement_list.extend(processed_statement)
|
||||||
|
|
||||||
# 处理ExtractedEntity
|
# 处理ExtractedEntity
|
||||||
extracted_entity = data.get('ExtractedEntity')
|
extracted_entity = data.get('ExtractedEntity')
|
||||||
if extracted_entity is not None:
|
if extracted_entity is not None:
|
||||||
processed_entity = self._process_field_value(extracted_entity, "ExtractedEntity")
|
processed_entity = await self._process_field_value(extracted_entity, "ExtractedEntity")
|
||||||
extracted_entity_list.extend(processed_entity)
|
extracted_entity_list.extend(processed_entity)
|
||||||
|
|
||||||
# 去重 - 现在处理的是字典列表,需要更智能的去重
|
# 去重 - 现在处理的是字典列表,需要更智能的去重
|
||||||
@@ -128,6 +131,21 @@ class MemoryEntityService:
|
|||||||
all_timeline_data = memory_summary_list + statement_list
|
all_timeline_data = memory_summary_list + statement_list
|
||||||
all_timeline_data = self._merge_same_text_items(all_timeline_data)
|
all_timeline_data = self._merge_same_text_items(all_timeline_data)
|
||||||
|
|
||||||
|
# 如果需要翻译(非中文),对整个结果进行翻译
|
||||||
|
if language_type != 'zh':
|
||||||
|
# 定义需要翻译的字段
|
||||||
|
fields_to_translate = ['text', 'type']
|
||||||
|
|
||||||
|
# 翻译各个列表
|
||||||
|
if memory_summary_list:
|
||||||
|
memory_summary_list = await self._translate_list(memory_summary_list, model_id, fields_to_translate)
|
||||||
|
if statement_list:
|
||||||
|
statement_list = await self._translate_list(statement_list, model_id, fields_to_translate)
|
||||||
|
if extracted_entity_list:
|
||||||
|
extracted_entity_list = await self._translate_list(extracted_entity_list, model_id, fields_to_translate)
|
||||||
|
if all_timeline_data:
|
||||||
|
all_timeline_data = await self._translate_list(all_timeline_data, model_id, fields_to_translate)
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
"MemorySummary": memory_summary_list,
|
"MemorySummary": memory_summary_list,
|
||||||
"Statement": statement_list,
|
"Statement": statement_list,
|
||||||
@@ -233,7 +251,7 @@ class MemoryEntityService:
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _process_field_value(self, value: Any, field_name: str) -> List[Dict[str, Any]]:
|
async def _process_field_value(self, value: Any, field_name: str) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
处理字段值,支持字符串、列表等类型
|
处理字段值,支持字符串、列表等类型
|
||||||
|
|
||||||
@@ -251,13 +269,13 @@ class MemoryEntityService:
|
|||||||
# 如果是列表,处理每个元素
|
# 如果是列表,处理每个元素
|
||||||
for item in value:
|
for item in value:
|
||||||
if self._is_valid_item(item):
|
if self._is_valid_item(item):
|
||||||
processed_item = self._process_single_item(item)
|
processed_item = await self._process_single_item(item)
|
||||||
if processed_item:
|
if processed_item:
|
||||||
processed_values.append(processed_item)
|
processed_values.append(processed_item)
|
||||||
elif isinstance(value, dict):
|
elif isinstance(value, dict):
|
||||||
# 如果是字典,直接处理
|
# 如果是字典,直接处理
|
||||||
if self._is_valid_item(value):
|
if self._is_valid_item(value):
|
||||||
processed_item = self._process_single_item(value)
|
processed_item = await self._process_single_item(value)
|
||||||
if processed_item:
|
if processed_item:
|
||||||
processed_values.append(processed_item)
|
processed_values.append(processed_item)
|
||||||
elif isinstance(value, str):
|
elif isinstance(value, str):
|
||||||
@@ -304,7 +322,7 @@ class MemoryEntityService:
|
|||||||
return (str(item).strip() != '' and
|
return (str(item).strip() != '' and
|
||||||
"MemorySummaryChunk" not in str(item))
|
"MemorySummaryChunk" not in str(item))
|
||||||
|
|
||||||
def _process_single_item(self, item: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
async def _process_single_item(self, item: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
处理单个项目
|
处理单个项目
|
||||||
|
|
||||||
@@ -369,6 +387,42 @@ class MemoryEntityService:
|
|||||||
logger.warning(f"转换时间格式失败: {e}, 原始值: {dt}")
|
logger.warning(f"转换时间格式失败: {e}, 原始值: {dt}")
|
||||||
return str(dt) if dt is not None else None
|
return str(dt) if dt is not None else None
|
||||||
|
|
||||||
|
async def _translate_list(self, data_list: List[Dict[str, Any]], model_id: str, fields: List[str]) -> List[Dict[str, Any]]:
|
||||||
|
"""
|
||||||
|
翻译列表中每个字典的指定字段
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data_list: 要翻译的字典列表
|
||||||
|
model_id: 模型ID
|
||||||
|
fields: 需要翻译的字段列表
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
翻译后的字典列表
|
||||||
|
"""
|
||||||
|
if not data_list:
|
||||||
|
return data_list
|
||||||
|
|
||||||
|
translated_list = []
|
||||||
|
for item in data_list:
|
||||||
|
if not isinstance(item, dict):
|
||||||
|
translated_list.append(item)
|
||||||
|
continue
|
||||||
|
|
||||||
|
translated_item = item.copy()
|
||||||
|
for field in fields:
|
||||||
|
if field in translated_item and translated_item[field]:
|
||||||
|
try:
|
||||||
|
# 调用Translation_English翻译单个字段
|
||||||
|
translated_value = await Translation_English(model_id, translated_item[field])
|
||||||
|
if translated_value:
|
||||||
|
translated_item[field] = translated_value
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"翻译字段 {field} 失败: {e}")
|
||||||
|
|
||||||
|
translated_list.append(translated_item)
|
||||||
|
|
||||||
|
return translated_list
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -426,15 +480,19 @@ class MemoryEmotion:
|
|||||||
# 如果解析失败,返回原始字符串
|
# 如果解析失败,返回原始字符串
|
||||||
return iso_string
|
return iso_string
|
||||||
|
|
||||||
async def get_emotion(self) -> Dict[str, Any]:
|
async def get_emotion(self, model_id: str = None, language_type: str = 'zh') -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
获取情绪随时间变化数据
|
获取情绪随时间变化数据
|
||||||
|
|
||||||
|
Args:
|
||||||
|
model_id: 模型ID用于翻译
|
||||||
|
language_type: 语言类型 ('zh' 或其他)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
包含情绪数据的字典
|
包含情绪数据的字典
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
logger.info(f"获取情绪数据 - ID: {self.id}, Table: {self.table}")
|
logger.info(f"获取情绪数据 - ID: {self.id}, Table: {self.table}, language_type={language_type}")
|
||||||
|
|
||||||
if self.table == 'Statement':
|
if self.table == 'Statement':
|
||||||
results = await self.connector.execute_query(Memory_Space_Emotion_Statement, id=self.id)
|
results = await self.connector.execute_query(Memory_Space_Emotion_Statement, id=self.id)
|
||||||
@@ -450,6 +508,10 @@ class MemoryEmotion:
|
|||||||
# 转换Neo4j类型
|
# 转换Neo4j类型
|
||||||
final_data = self._convert_neo4j_types(emotion_data)
|
final_data = self._convert_neo4j_types(emotion_data)
|
||||||
|
|
||||||
|
# 如果需要翻译(非中文)
|
||||||
|
if language_type != 'zh' and model_id and final_data:
|
||||||
|
final_data = await self._translate_emotion_data(final_data, model_id)
|
||||||
|
|
||||||
logger.info(f"成功获取 {len(final_data)} 条情绪数据")
|
logger.info(f"成功获取 {len(final_data)} 条情绪数据")
|
||||||
|
|
||||||
return final_data
|
return final_data
|
||||||
@@ -590,16 +652,14 @@ class MemoryInteraction:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
logger.info(f"获取交互数据 - ID: {self.id}, Table: {self.table}")
|
logger.info(f"获取交互数据 - ID: {self.id}, Table: {self.table}")
|
||||||
|
|
||||||
ori_data= await self.connector.execute_query(Memory_Space_Entity, id=self.id)
|
ori_data= await self.connector.execute_query(Memory_Space_Entity, id=self.id)
|
||||||
if ori_data!=[]:
|
if ori_data!=[]:
|
||||||
# name = ori_data[0]['name']
|
# name = ori_data[0]['name']
|
||||||
group_id = ori_data[0]['group_id']
|
group_id = [i['group_id'] for i in ori_data][0]
|
||||||
Space_User = await self.connector.execute_query(Memory_Space_User, group_id=group_id)
|
Space_User = await self.connector.execute_query(Memory_Space_User, group_id=group_id)
|
||||||
if not Space_User:
|
if not Space_User:
|
||||||
return []
|
return []
|
||||||
user_id=Space_User[0]['id']
|
user_id=Space_User[0]['id']
|
||||||
|
|
||||||
results = await self.connector.execute_query(Memory_Space_Associative, id=self.id,user_id=user_id)
|
results = await self.connector.execute_query(Memory_Space_Associative, id=self.id,user_id=user_id)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from app.repositories.end_user_repository import EndUserRepository
|
|||||||
from app.repositories.neo4j.neo4j_connector import Neo4jConnector
|
from app.repositories.neo4j.neo4j_connector import Neo4jConnector
|
||||||
from app.schemas.memory_episodic_schema import EmotionSubject, EmotionType, type_mapping
|
from app.schemas.memory_episodic_schema import EmotionSubject, EmotionType, type_mapping
|
||||||
from app.services.implicit_memory_service import ImplicitMemoryService
|
from app.services.implicit_memory_service import ImplicitMemoryService
|
||||||
from app.services.memory_base_service import MemoryBaseService
|
from app.services.memory_base_service import MemoryBaseService, MemoryTransService, Translation_English
|
||||||
from app.services.memory_config_service import MemoryConfigService
|
from app.services.memory_config_service import MemoryConfigService
|
||||||
from app.services.memory_perceptual_service import MemoryPerceptualService
|
from app.services.memory_perceptual_service import MemoryPerceptualService
|
||||||
from app.services.memory_short_service import ShortService
|
from app.services.memory_short_service import ShortService
|
||||||
@@ -360,7 +360,9 @@ class UserMemoryService:
|
|||||||
async def get_cached_memory_insight(
|
async def get_cached_memory_insight(
|
||||||
self,
|
self,
|
||||||
db: Session,
|
db: Session,
|
||||||
end_user_id: str
|
end_user_id: str,
|
||||||
|
model_id: str,
|
||||||
|
language_type: str
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
从数据库获取缓存的记忆洞察(四个维度)
|
从数据库获取缓存的记忆洞察(四个维度)
|
||||||
@@ -419,11 +421,18 @@ class UserMemoryService:
|
|||||||
key_findings_array = []
|
key_findings_array = []
|
||||||
|
|
||||||
logger.info(f"成功获取 end_user_id {end_user_id} 的缓存记忆洞察(四维度)")
|
logger.info(f"成功获取 end_user_id {end_user_id} 的缓存记忆洞察(四维度)")
|
||||||
|
memory_insight=end_user.memory_insight
|
||||||
|
behavior_pattern=end_user.behavior_pattern
|
||||||
|
growth_trajectory=end_user.growth_trajectory
|
||||||
|
if language_type!='zh':
|
||||||
|
memory_insight=await Translation_English(model_id,memory_insight)
|
||||||
|
behavior_pattern=await Translation_English(model_id,behavior_pattern)
|
||||||
|
growth_trajectory=await Translation_English(model_id,growth_trajectory)
|
||||||
return {
|
return {
|
||||||
"memory_insight": end_user.memory_insight, # 总体概述存储在 memory_insight
|
"memory_insight":memory_insight, # 总体概述存储在 memory_insight
|
||||||
"behavior_pattern": end_user.behavior_pattern,
|
"behavior_pattern":behavior_pattern,
|
||||||
"key_findings": key_findings_array, # 返回数组
|
"key_findings": key_findings_array, # 返回数组
|
||||||
"growth_trajectory": end_user.growth_trajectory,
|
"growth_trajectory": growth_trajectory,
|
||||||
"updated_at": self._datetime_to_timestamp(end_user.memory_insight_updated_at),
|
"updated_at": self._datetime_to_timestamp(end_user.memory_insight_updated_at),
|
||||||
"is_cached": True
|
"is_cached": True
|
||||||
}
|
}
|
||||||
@@ -457,7 +466,9 @@ class UserMemoryService:
|
|||||||
async def get_cached_user_summary(
|
async def get_cached_user_summary(
|
||||||
self,
|
self,
|
||||||
db: Session,
|
db: Session,
|
||||||
end_user_id: str
|
end_user_id: str,
|
||||||
|
model_id:str,
|
||||||
|
language_type:str="zh"
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
从数据库获取缓存的用户摘要(四个部分)
|
从数据库获取缓存的用户摘要(四个部分)
|
||||||
@@ -481,7 +492,6 @@ class UserMemoryService:
|
|||||||
user_uuid = uuid.UUID(end_user_id)
|
user_uuid = uuid.UUID(end_user_id)
|
||||||
repo = EndUserRepository(db)
|
repo = EndUserRepository(db)
|
||||||
end_user = repo.get_by_id(user_uuid)
|
end_user = repo.get_by_id(user_uuid)
|
||||||
|
|
||||||
if not end_user:
|
if not end_user:
|
||||||
logger.warning(f"未找到 end_user_id 为 {end_user_id} 的用户")
|
logger.warning(f"未找到 end_user_id 为 {end_user_id} 的用户")
|
||||||
return {
|
return {
|
||||||
@@ -495,20 +505,29 @@ class UserMemoryService:
|
|||||||
}
|
}
|
||||||
|
|
||||||
# 检查是否有缓存数据(至少有一个字段不为空)
|
# 检查是否有缓存数据(至少有一个字段不为空)
|
||||||
|
user_summary=end_user.user_summary
|
||||||
|
personality_traits=end_user.personality_traits
|
||||||
|
core_values=end_user.core_values
|
||||||
|
one_sentence_summary=end_user.one_sentence_summary
|
||||||
|
if language_type!='zh':
|
||||||
|
user_summary=await Translation_English(model_id, user_summary)
|
||||||
|
personality_traits = await Translation_English(model_id, personality_traits)
|
||||||
|
core_values = await Translation_English(model_id, core_values)
|
||||||
|
one_sentence_summary = await Translation_English(model_id, one_sentence_summary)
|
||||||
has_cache = any([
|
has_cache = any([
|
||||||
end_user.user_summary,
|
user_summary,
|
||||||
end_user.personality_traits,
|
personality_traits,
|
||||||
end_user.core_values,
|
core_values,
|
||||||
end_user.one_sentence_summary
|
one_sentence_summary
|
||||||
])
|
])
|
||||||
|
|
||||||
if has_cache:
|
if has_cache:
|
||||||
logger.info(f"成功获取 end_user_id {end_user_id} 的缓存用户摘要")
|
logger.info(f"成功获取 end_user_id {end_user_id} 的缓存用户摘要")
|
||||||
return {
|
return {
|
||||||
"user_summary": end_user.user_summary,
|
"user_summary": user_summary,
|
||||||
"personality": end_user.personality_traits,
|
"personality": personality_traits,
|
||||||
"core_values": end_user.core_values,
|
"core_values":core_values,
|
||||||
"one_sentence": end_user.one_sentence_summary,
|
"one_sentence": one_sentence_summary,
|
||||||
"updated_at": self._datetime_to_timestamp(end_user.user_summary_updated_at),
|
"updated_at": self._datetime_to_timestamp(end_user.user_summary_updated_at),
|
||||||
"is_cached": True
|
"is_cached": True
|
||||||
}
|
}
|
||||||
@@ -1367,7 +1386,6 @@ async def analytics_memory_types(
|
|||||||
|
|
||||||
return memory_types
|
return memory_types
|
||||||
|
|
||||||
|
|
||||||
async def analytics_graph_data(
|
async def analytics_graph_data(
|
||||||
db: Session,
|
db: Session,
|
||||||
end_user_id: str,
|
end_user_id: str,
|
||||||
@@ -1557,7 +1575,7 @@ async def analytics_graph_data(
|
|||||||
f"成功获取图数据: end_user_id={end_user_id}, "
|
f"成功获取图数据: end_user_id={end_user_id}, "
|
||||||
f"nodes={len(nodes)}, edges={len(edges)}"
|
f"nodes={len(nodes)}, edges={len(edges)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"nodes": nodes,
|
"nodes": nodes,
|
||||||
"edges": edges,
|
"edges": edges,
|
||||||
@@ -1606,11 +1624,7 @@ async def _extract_node_properties(label: str, properties: Dict[str, Any],node_
|
|||||||
|
|
||||||
# 获取该节点类型的白名单字段
|
# 获取该节点类型的白名单字段
|
||||||
allowed_fields = field_whitelist.get(label, [])
|
allowed_fields = field_whitelist.get(label, [])
|
||||||
|
|
||||||
# 如果没有定义白名单,返回空字典(或者可以返回所有字段)
|
|
||||||
# if not allowed_fields:
|
|
||||||
# # 对于未定义的节点类型,只返回基本字段
|
|
||||||
# allowed_fields = ["name", "created_at", "caption"]
|
|
||||||
count_neo4j=f"""MATCH (n)-[r]-(m) WHERE elementId(n) ="{node_id}" RETURN count(r) AS rel_count;"""
|
count_neo4j=f"""MATCH (n)-[r]-(m) WHERE elementId(n) ="{node_id}" RETURN count(r) AS rel_count;"""
|
||||||
node_results = await (_neo4j_connector.execute_query(count_neo4j))
|
node_results = await (_neo4j_connector.execute_query(count_neo4j))
|
||||||
# 提取白名单中的字段
|
# 提取白名单中的字段
|
||||||
@@ -1618,13 +1632,12 @@ async def _extract_node_properties(label: str, properties: Dict[str, Any],node_
|
|||||||
for field in allowed_fields:
|
for field in allowed_fields:
|
||||||
if field in properties:
|
if field in properties:
|
||||||
value = properties[field]
|
value = properties[field]
|
||||||
if str(field) == 'entity_type':
|
if str(field) == 'entity_type':
|
||||||
value=type_mapping.get(value,'')
|
value=type_mapping.get(value,'')
|
||||||
if str(field)=="emotion_type":
|
if str(field)=="emotion_type":
|
||||||
value=EmotionType.EMOTION_MAPPING.get(value)
|
value=EmotionType.EMOTION_MAPPING.get(value)
|
||||||
if str(field)=="emotion_subject":
|
if str(field)=="emotion_subject":
|
||||||
value=EmotionSubject.SUBJECT_MAPPING.get(value)
|
value=EmotionSubject.SUBJECT_MAPPING.get(value)
|
||||||
# 清理 Neo4j 特殊类型
|
|
||||||
filtered_props[field] = _clean_neo4j_value(value)
|
filtered_props[field] = _clean_neo4j_value(value)
|
||||||
filtered_props['associative_memory']=[i['rel_count'] for i in node_results][0]
|
filtered_props['associative_memory']=[i['rel_count'] for i in node_results][0]
|
||||||
return filtered_props
|
return filtered_props
|
||||||
|
|||||||
Reference in New Issue
Block a user