feat: update MemoryListApi response format with ChatflowConversationMetadata

This commit is contained in:
Stream 2025-09-28 22:36:10 +08:00
parent 15be85514d
commit bb1f1a56a5
No known key found for this signature in database
GPG Key ID: 033728094B100D70
5 changed files with 142 additions and 39 deletions

View File

@ -21,21 +21,27 @@ class MemoryListApi(Resource):
memory_id = args.get("memory_id")
version = args.get("version")
result = ChatflowMemoryService.get_persistent_memories(
app_model,
MemoryCreatedBy(end_user_id=end_user.id),
version
)
if conversation_id:
result = [
*result,
*ChatflowMemoryService.get_session_memories(
app_model,
MemoryCreatedBy(end_user_id=end_user.id),
conversation_id,
version
)
]
result = ChatflowMemoryService.get_persistent_memories_with_conversation(
app_model,
MemoryCreatedBy(end_user_id=end_user.id),
conversation_id,
version
)
session_memories = ChatflowMemoryService.get_session_memories_with_conversation(
app_model,
MemoryCreatedBy(end_user_id=end_user.id),
conversation_id,
version
)
result = [*result, *session_memories]
else:
result = ChatflowMemoryService.get_persistent_memories(
app_model,
MemoryCreatedBy(end_user_id=end_user.id),
version
)
if memory_id:
result = [it for it in result if it.spec.id == memory_id]
return [it for it in result if it.spec.end_user_visible]

View File

@ -20,21 +20,28 @@ class MemoryListApi(WebApiResource):
memory_id = args.get("memory_id")
version = args.get("version")
result = ChatflowMemoryService.get_persistent_memories(
app_model,
MemoryCreatedBy(end_user_id=end_user.id),
version
)
if conversation_id:
result = [
*result,
*ChatflowMemoryService.get_session_memories(
app_model,
MemoryCreatedBy(end_user_id=end_user.id),
conversation_id,
version
)
]
result = ChatflowMemoryService.get_persistent_memories_with_conversation(
app_model,
MemoryCreatedBy(end_user_id=end_user.id),
conversation_id,
version
)
session_memories = ChatflowMemoryService.get_session_memories_with_conversation(
app_model,
MemoryCreatedBy(end_user_id=end_user.id),
conversation_id,
version
)
result = [*result, *session_memories]
else:
result = ChatflowMemoryService.get_persistent_memories(
app_model,
MemoryCreatedBy(end_user_id=end_user.id),
version
)
if memory_id:
result = [it for it in result if it.spec.id == memory_id]
return [it for it in result if it.spec.end_user_visible]

View File

@ -90,3 +90,30 @@ class ChatflowConversationMetadata(BaseModel):
"""Metadata for chatflow conversation with visible message count"""
type: str = "mutable_visible_window"
visible_count: int = Field(gt=0, description="Number of visible messages to keep")
class MemoryBlockWithConversation(MemoryBlock):
"""MemoryBlock with optional conversation metadata for session memories"""
conversation_metadata: ChatflowConversationMetadata = Field(
description="Conversation metadata, only present for session memories"
)
@classmethod
def from_memory_block(
cls,
memory_block: MemoryBlock,
conversation_metadata: ChatflowConversationMetadata
) -> "MemoryBlockWithConversation":
"""Create MemoryBlockWithConversation from MemoryBlock"""
return cls(
spec=memory_block.spec,
tenant_id=memory_block.tenant_id,
value=memory_block.value,
app_id=memory_block.app_id,
conversation_id=memory_block.conversation_id,
node_id=memory_block.node_id,
edited_by_user=memory_block.edited_by_user,
created_by=memory_block.created_by,
version=memory_block.version,
conversation_metadata=conversation_metadata
)

View File

@ -1,5 +1,4 @@
import json
import time
from collections.abc import MutableMapping, Sequence
from typing import Literal, Optional, overload
@ -134,6 +133,21 @@ class ChatflowHistoryService:
session.commit()
@staticmethod
def get_conversation_metadata(
tenant_id: str,
app_id: str,
conversation_id: str,
node_id: Optional[str]
) -> ChatflowConversationMetadata:
with Session(db.engine) as session:
chatflow_conv = ChatflowHistoryService._get_or_create_chatflow_conversation(
session, conversation_id, app_id, tenant_id, node_id, create_if_missing=False
)
if not chatflow_conv:
raise ValueError(f"Conversation not found: {conversation_id}")
return ChatflowConversationMetadata.model_validate_json(chatflow_conv.conversation_metadata)
@staticmethod
def _filter_latest_messages(raw_messages: Sequence[ChatflowMessage]) -> Sequence[ChatflowMessage]:
index_to_message: MutableMapping[int, ChatflowMessage] = {}

View File

@ -11,6 +11,7 @@ from core.llm_generator.llm_generator import LLMGenerator
from core.memory.entities import (
MemoryBlock,
MemoryBlockSpec,
MemoryBlockWithConversation,
MemoryCreatedBy,
MemoryScheduleMode,
MemoryScope,
@ -280,7 +281,8 @@ class ChatflowMemoryService:
block=memory_block,
is_draft=is_draft,
variable_pool=variable_pool,
visible_messages=visible_messages
visible_messages=visible_messages,
conversation_id=conversation_id,
)
# sync mode: submit a batch update task
@ -332,7 +334,8 @@ class ChatflowMemoryService:
visible_messages=visible_messages,
memory_block=memory_block,
variable_pool=variable_pool,
is_draft=is_draft
is_draft=is_draft,
conversation_id=conversation_id
)
else:
# Node-level async: execute asynchronously
@ -340,7 +343,8 @@ class ChatflowMemoryService:
memory_block=memory_block,
visible_messages=visible_messages,
variable_pool=variable_pool,
is_draft=is_draft
is_draft=is_draft,
conversation_id=conversation_id
)
return True
@ -422,6 +426,7 @@ class ChatflowMemoryService:
block: MemoryBlock,
visible_messages: Sequence[PromptMessage],
variable_pool: VariablePool,
conversation_id: str,
is_draft: bool
):
thread = threading.Thread(
@ -430,7 +435,8 @@ class ChatflowMemoryService:
'memory_block': block,
'visible_messages': visible_messages,
'variable_pool': variable_pool,
'is_draft': is_draft
'is_draft': is_draft,
'conversation_id': conversation_id
},
)
thread.start()
@ -478,7 +484,8 @@ class ChatflowMemoryService:
'memory_block': block,
'visible_messages': visible_messages,
'variable_pool': variable_pool,
'is_draft': is_draft
'is_draft': is_draft,
'conversation_id': conversation_id,
},
)
threads.append(thread)
@ -494,13 +501,15 @@ class ChatflowMemoryService:
memory_block: MemoryBlock,
visible_messages: Sequence[PromptMessage],
variable_pool: VariablePool,
conversation_id: str,
is_draft: bool
):
ChatflowMemoryService._perform_memory_update(
memory_block=memory_block,
visible_messages=visible_messages,
variable_pool=variable_pool,
is_draft=is_draft
is_draft=is_draft,
conversation_id=conversation_id
)
@staticmethod
@ -508,6 +517,7 @@ class ChatflowMemoryService:
memory_block: MemoryBlock,
visible_messages: Sequence[PromptMessage],
variable_pool: VariablePool,
conversation_id: str,
is_draft: bool = False
):
thread = threading.Thread(
@ -516,7 +526,8 @@ class ChatflowMemoryService:
'memory_block': memory_block,
'visible_messages': visible_messages,
'variable_pool': variable_pool,
'is_draft': is_draft
'is_draft': is_draft,
'conversation_id': conversation_id,
},
daemon=True
)
@ -526,6 +537,7 @@ class ChatflowMemoryService:
def _perform_memory_update(
memory_block: MemoryBlock,
variable_pool: VariablePool,
conversation_id: str,
visible_messages: Sequence[PromptMessage],
is_draft: bool
):
@ -541,7 +553,7 @@ class ChatflowMemoryService:
value=updated_value,
spec=memory_block.spec,
app_id=memory_block.app_id,
conversation_id=memory_block.conversation_id,
conversation_id=conversation_id,
node_id=memory_block.node_id,
edited_by_user=False,
created_by=memory_block.created_by,
@ -549,9 +561,8 @@ class ChatflowMemoryService:
)
ChatflowMemoryService.save_memory(updated_memory, variable_pool, is_draft)
# 添加以下代码:重置 visible_count 为 preserved_turns
ChatflowHistoryService.update_visible_count(
conversation_id=memory_block.conversation_id,
conversation_id=conversation_id,
node_id=memory_block.node_id,
new_visible_count=memory_block.spec.preserved_turns,
app_id=memory_block.app_id,
@ -609,6 +620,44 @@ class ChatflowMemoryService:
session.execute(stmt)
session.commit()
@staticmethod
def get_persistent_memories_with_conversation(
app: App,
created_by: MemoryCreatedBy,
conversation_id: str,
version: int | None = None
) -> Sequence[MemoryBlockWithConversation]:
"""Get persistent memories with conversation metadata (always None for persistent)"""
memory_blocks = ChatflowMemoryService.get_persistent_memories(app, created_by, version)
return [
MemoryBlockWithConversation.from_memory_block(
block,
ChatflowHistoryService.get_conversation_metadata(
app.tenant_id, app.id, conversation_id, block.node_id
)
)
for block in memory_blocks
]
@staticmethod
def get_session_memories_with_conversation(
app: App,
created_by: MemoryCreatedBy,
conversation_id: str,
version: int | None = None
) -> Sequence[MemoryBlockWithConversation]:
"""Get session memories with conversation metadata"""
memory_blocks = ChatflowMemoryService.get_session_memories(app, created_by, conversation_id, version)
return [
MemoryBlockWithConversation.from_memory_block(
block,
ChatflowHistoryService.get_conversation_metadata(
app.tenant_id, app.id, conversation_id, block.node_id
)
)
for block in memory_blocks
]
@staticmethod
def _format_chat_history(messages: Sequence[PromptMessage]) -> Sequence[tuple[str, str]]:
result = []