Tai Truong
fix readme
d202ada
from langchain.memory import ConversationBufferMemory
from langflow.custom import Component
from langflow.field_typing import BaseChatMemory
from langflow.helpers.data import data_to_text
from langflow.inputs import HandleInput
from langflow.io import DropdownInput, IntInput, MessageTextInput, MultilineInput, Output
from langflow.memory import LCBuiltinChatMemory, aget_messages
from langflow.schema import Data
from langflow.schema.message import Message
from langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_USER
class MemoryComponent(Component):
display_name = "Message History"
description = "Retrieves stored chat messages from Langflow tables or an external memory."
icon = "message-square-more"
name = "Memory"
inputs = [
HandleInput(
name="memory",
display_name="External Memory",
input_types=["BaseChatMessageHistory"],
info="Retrieve messages from an external memory. If empty, it will use the Langflow tables.",
),
DropdownInput(
name="sender",
display_name="Sender Type",
options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER, "Machine and User"],
value="Machine and User",
info="Filter by sender type.",
advanced=True,
),
MessageTextInput(
name="sender_name",
display_name="Sender Name",
info="Filter by sender name.",
advanced=True,
),
IntInput(
name="n_messages",
display_name="Number of Messages",
value=100,
info="Number of messages to retrieve.",
advanced=True,
),
MessageTextInput(
name="session_id",
display_name="Session ID",
info="The session ID of the chat. If empty, the current session ID parameter will be used.",
advanced=True,
),
DropdownInput(
name="order",
display_name="Order",
options=["Ascending", "Descending"],
value="Ascending",
info="Order of the messages.",
advanced=True,
tool_mode=True,
),
MultilineInput(
name="template",
display_name="Template",
info="The template to use for formatting the data. "
"It can contain the keys {text}, {sender} or any other key in the message data.",
value="{sender_name}: {text}",
advanced=True,
),
]
outputs = [
Output(display_name="Data", name="messages", method="retrieve_messages"),
Output(display_name="Text", name="messages_text", method="retrieve_messages_as_text"),
]
async def retrieve_messages(self) -> Data:
sender = self.sender
sender_name = self.sender_name
session_id = self.session_id
n_messages = self.n_messages
order = "DESC" if self.order == "Descending" else "ASC"
if sender == "Machine and User":
sender = None
if self.memory:
# override session_id
self.memory.session_id = session_id
stored = await self.memory.aget_messages()
# langchain memories are supposed to return messages in ascending order
if order == "DESC":
stored = stored[::-1]
if n_messages:
stored = stored[:n_messages]
stored = [Message.from_lc_message(m) for m in stored]
if sender:
expected_type = MESSAGE_SENDER_AI if sender == MESSAGE_SENDER_AI else MESSAGE_SENDER_USER
stored = [m for m in stored if m.type == expected_type]
else:
stored = await aget_messages(
sender=sender,
sender_name=sender_name,
session_id=session_id,
limit=n_messages,
order=order,
)
self.status = stored
return stored
async def retrieve_messages_as_text(self) -> Message:
stored_text = data_to_text(self.template, await self.retrieve_messages())
self.status = stored_text
return Message(text=stored_text)
def build_lc_memory(self) -> BaseChatMemory:
chat_memory = self.memory or LCBuiltinChatMemory(flow_id=self.flow_id, session_id=self.session_id)
return ConversationBufferMemory(chat_memory=chat_memory)