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") memory_id = args.get("memory_id")
version = args.get("version") version = args.get("version")
result = ChatflowMemoryService.get_persistent_memories(
app_model,
MemoryCreatedBy(end_user_id=end_user.id),
version
)
if conversation_id: if conversation_id:
result = [ result = ChatflowMemoryService.get_persistent_memories_with_conversation(
*result, app_model,
*ChatflowMemoryService.get_session_memories( MemoryCreatedBy(end_user_id=end_user.id),
app_model, conversation_id,
MemoryCreatedBy(end_user_id=end_user.id), version
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: if memory_id:
result = [it for it in result if it.spec.id == 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] 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") memory_id = args.get("memory_id")
version = args.get("version") version = args.get("version")
result = ChatflowMemoryService.get_persistent_memories(
app_model,
MemoryCreatedBy(end_user_id=end_user.id),
version
)
if conversation_id: if conversation_id:
result = [ result = ChatflowMemoryService.get_persistent_memories_with_conversation(
*result, app_model,
*ChatflowMemoryService.get_session_memories( MemoryCreatedBy(end_user_id=end_user.id),
app_model, conversation_id,
MemoryCreatedBy(end_user_id=end_user.id), version
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: if memory_id:
result = [it for it in result if it.spec.id == 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] 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""" """Metadata for chatflow conversation with visible message count"""
type: str = "mutable_visible_window" type: str = "mutable_visible_window"
visible_count: int = Field(gt=0, description="Number of visible messages to keep") 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 json
import time
from collections.abc import MutableMapping, Sequence from collections.abc import MutableMapping, Sequence
from typing import Literal, Optional, overload from typing import Literal, Optional, overload
@ -134,6 +133,21 @@ class ChatflowHistoryService:
session.commit() 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 @staticmethod
def _filter_latest_messages(raw_messages: Sequence[ChatflowMessage]) -> Sequence[ChatflowMessage]: def _filter_latest_messages(raw_messages: Sequence[ChatflowMessage]) -> Sequence[ChatflowMessage]:
index_to_message: MutableMapping[int, 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 ( from core.memory.entities import (
MemoryBlock, MemoryBlock,
MemoryBlockSpec, MemoryBlockSpec,
MemoryBlockWithConversation,
MemoryCreatedBy, MemoryCreatedBy,
MemoryScheduleMode, MemoryScheduleMode,
MemoryScope, MemoryScope,
@ -280,7 +281,8 @@ class ChatflowMemoryService:
block=memory_block, block=memory_block,
is_draft=is_draft, is_draft=is_draft,
variable_pool=variable_pool, variable_pool=variable_pool,
visible_messages=visible_messages visible_messages=visible_messages,
conversation_id=conversation_id,
) )
# sync mode: submit a batch update task # sync mode: submit a batch update task
@ -332,7 +334,8 @@ class ChatflowMemoryService:
visible_messages=visible_messages, visible_messages=visible_messages,
memory_block=memory_block, memory_block=memory_block,
variable_pool=variable_pool, variable_pool=variable_pool,
is_draft=is_draft is_draft=is_draft,
conversation_id=conversation_id
) )
else: else:
# Node-level async: execute asynchronously # Node-level async: execute asynchronously
@ -340,7 +343,8 @@ class ChatflowMemoryService:
memory_block=memory_block, memory_block=memory_block,
visible_messages=visible_messages, visible_messages=visible_messages,
variable_pool=variable_pool, variable_pool=variable_pool,
is_draft=is_draft is_draft=is_draft,
conversation_id=conversation_id
) )
return True return True
@ -422,6 +426,7 @@ class ChatflowMemoryService:
block: MemoryBlock, block: MemoryBlock,
visible_messages: Sequence[PromptMessage], visible_messages: Sequence[PromptMessage],
variable_pool: VariablePool, variable_pool: VariablePool,
conversation_id: str,
is_draft: bool is_draft: bool
): ):
thread = threading.Thread( thread = threading.Thread(
@ -430,7 +435,8 @@ class ChatflowMemoryService:
'memory_block': block, 'memory_block': block,
'visible_messages': visible_messages, 'visible_messages': visible_messages,
'variable_pool': variable_pool, 'variable_pool': variable_pool,
'is_draft': is_draft 'is_draft': is_draft,
'conversation_id': conversation_id
}, },
) )
thread.start() thread.start()
@ -478,7 +484,8 @@ class ChatflowMemoryService:
'memory_block': block, 'memory_block': block,
'visible_messages': visible_messages, 'visible_messages': visible_messages,
'variable_pool': variable_pool, 'variable_pool': variable_pool,
'is_draft': is_draft 'is_draft': is_draft,
'conversation_id': conversation_id,
}, },
) )
threads.append(thread) threads.append(thread)
@ -494,13 +501,15 @@ class ChatflowMemoryService:
memory_block: MemoryBlock, memory_block: MemoryBlock,
visible_messages: Sequence[PromptMessage], visible_messages: Sequence[PromptMessage],
variable_pool: VariablePool, variable_pool: VariablePool,
conversation_id: str,
is_draft: bool is_draft: bool
): ):
ChatflowMemoryService._perform_memory_update( ChatflowMemoryService._perform_memory_update(
memory_block=memory_block, memory_block=memory_block,
visible_messages=visible_messages, visible_messages=visible_messages,
variable_pool=variable_pool, variable_pool=variable_pool,
is_draft=is_draft is_draft=is_draft,
conversation_id=conversation_id
) )
@staticmethod @staticmethod
@ -508,6 +517,7 @@ class ChatflowMemoryService:
memory_block: MemoryBlock, memory_block: MemoryBlock,
visible_messages: Sequence[PromptMessage], visible_messages: Sequence[PromptMessage],
variable_pool: VariablePool, variable_pool: VariablePool,
conversation_id: str,
is_draft: bool = False is_draft: bool = False
): ):
thread = threading.Thread( thread = threading.Thread(
@ -516,7 +526,8 @@ class ChatflowMemoryService:
'memory_block': memory_block, 'memory_block': memory_block,
'visible_messages': visible_messages, 'visible_messages': visible_messages,
'variable_pool': variable_pool, 'variable_pool': variable_pool,
'is_draft': is_draft 'is_draft': is_draft,
'conversation_id': conversation_id,
}, },
daemon=True daemon=True
) )
@ -526,6 +537,7 @@ class ChatflowMemoryService:
def _perform_memory_update( def _perform_memory_update(
memory_block: MemoryBlock, memory_block: MemoryBlock,
variable_pool: VariablePool, variable_pool: VariablePool,
conversation_id: str,
visible_messages: Sequence[PromptMessage], visible_messages: Sequence[PromptMessage],
is_draft: bool is_draft: bool
): ):
@ -541,7 +553,7 @@ class ChatflowMemoryService:
value=updated_value, value=updated_value,
spec=memory_block.spec, spec=memory_block.spec,
app_id=memory_block.app_id, app_id=memory_block.app_id,
conversation_id=memory_block.conversation_id, conversation_id=conversation_id,
node_id=memory_block.node_id, node_id=memory_block.node_id,
edited_by_user=False, edited_by_user=False,
created_by=memory_block.created_by, created_by=memory_block.created_by,
@ -549,9 +561,8 @@ class ChatflowMemoryService:
) )
ChatflowMemoryService.save_memory(updated_memory, variable_pool, is_draft) ChatflowMemoryService.save_memory(updated_memory, variable_pool, is_draft)
# 添加以下代码:重置 visible_count 为 preserved_turns
ChatflowHistoryService.update_visible_count( ChatflowHistoryService.update_visible_count(
conversation_id=memory_block.conversation_id, conversation_id=conversation_id,
node_id=memory_block.node_id, node_id=memory_block.node_id,
new_visible_count=memory_block.spec.preserved_turns, new_visible_count=memory_block.spec.preserved_turns,
app_id=memory_block.app_id, app_id=memory_block.app_id,
@ -609,6 +620,44 @@ class ChatflowMemoryService:
session.execute(stmt) session.execute(stmt)
session.commit() 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 @staticmethod
def _format_chat_history(messages: Sequence[PromptMessage]) -> Sequence[tuple[str, str]]: def _format_chat_history(messages: Sequence[PromptMessage]) -> Sequence[tuple[str, str]]:
result = [] result = []