fix: external memory returns always empty history (#2980)

* fix: external memory returns always empty history

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Nicolò Boschi 2024-07-26 23:05:48 +02:00 • committed by GitHub
commit 082c71da80
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 82 additions and 36 deletions

View file

@ -14,6 +14,7 @@ from langflow.inputs.inputs import DataInput, InputTypes
from langflow.io import BoolInput, HandleInput, IntInput, MessageTextInput from langflow.io import BoolInput, HandleInput, IntInput, MessageTextInput
from langflow.schema.message import Message from langflow.schema.message import Message
from langflow.template import Output from langflow.template import Output
from langflow.utils.constants import MESSAGE_SENDER_AI
class LCAgentComponent(Component): class LCAgentComponent(Component):
@ -58,7 +59,7 @@ class LCAgentComponent(Component):
if isinstance(result, list): if isinstance(result, list):
result = "\n".join([result_dict["text"] for result_dict in result]) result = "\n".join([result_dict["text"] for result_dict in result])
message = Message(text=result, sender="Machine") message = Message(text=result, sender=MESSAGE_SENDER_AI)
self.status = message self.status = message
return message return message

View file

@ -9,6 +9,7 @@ from langflow.inputs.inputs import HandleInput, InputTypes
from langflow.io import BoolInput, IntInput, Output from langflow.io import BoolInput, IntInput, Output
from langflow.schema.data import Data from langflow.schema.data import Data
from langflow.schema.message import Message from langflow.schema.message import Message
from langflow.utils.constants import MESSAGE_SENDER_AI
class BaseCrewComponent(Component): class BaseCrewComponent(Component):
@ -78,6 +79,6 @@ class BaseCrewComponent(Component):
async def build_output(self) -> Message: async def build_output(self) -> Message:
crew = self.build_crew() crew = self.build_crew()
result = await crew.kickoff_async() result = await crew.kickoff_async()
message = Message(text=result, sender="Machine") message = Message(text=result, sender=MESSAGE_SENDER_AI)
self.status = message self.status = message
return message return message

View file

@ -5,6 +5,7 @@ from langflow.custom import Component
from langflow.memory import store_message from langflow.memory import store_message
from langflow.schema import Data from langflow.schema import Data
from langflow.schema.message import Message from langflow.schema.message import Message
from langflow.utils.constants import MESSAGE_SENDER_USER, MESSAGE_SENDER_AI
class ChatComponent(Component): class ChatComponent(Component):
@ -19,7 +20,7 @@ class ChatComponent(Component):
"multiline": True, "multiline": True,
}, },
"sender": { "sender": {
"options": ["Machine", "User"], "options": [MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],
"display_name": "Sender Type", "display_name": "Sender Type",
"advanced": True, "advanced": True,
}, },

View file

@ -2,6 +2,7 @@ from typing import Optional
from langflow.custom import CustomComponent from langflow.custom import CustomComponent
from langflow.schema import Data from langflow.schema import Data
from langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_USER
class BaseMemoryComponent(CustomComponent): class BaseMemoryComponent(CustomComponent):
@ -13,7 +14,7 @@ class BaseMemoryComponent(CustomComponent):
def build_config(self): def build_config(self):
return { return {
"sender": { "sender": {
"options": ["Machine", "User", "Machine and User"], "options": [MESSAGE_SENDER_AI, MESSAGE_SENDER_USER, "Machine and User"],
"display_name": "Sender Type", "display_name": "Sender Type",
}, },
"sender_name": {"display_name": "Sender Name", "advanced": True}, "sender_name": {"display_name": "Sender Name", "advanced": True},

View file

@ -2,6 +2,7 @@ from typing import Optional
from langflow.custom import CustomComponent from langflow.custom import CustomComponent
from langflow.schema.message import Message from langflow.schema.message import Message
from langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_USER
class MessageComponent(CustomComponent): class MessageComponent(CustomComponent):
@ -12,7 +13,7 @@ class MessageComponent(CustomComponent):
def build_config(self): def build_config(self):
return { return {
"sender": { "sender": {
"options": ["Machine", "User"], "options": [MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],
"display_name": "Sender Type", "display_name": "Sender Type",
}, },
"sender_name": {"display_name": "Sender Name"}, "sender_name": {"display_name": "Sender Name"},
@ -26,7 +27,7 @@ class MessageComponent(CustomComponent):
def build( def build(
self, self,
sender: str = "User", sender: str = MESSAGE_SENDER_USER,
sender_name: Optional[str] = None, sender_name: Optional[str] = None,
session_id: Optional[str] = None, session_id: Optional[str] = None,
text: str = "", text: str = "",

View file

@ -8,6 +8,8 @@ from langflow.schema.message import Message
from langflow.field_typing import BaseChatMemory from langflow.field_typing import BaseChatMemory
from langchain.memory import ConversationBufferMemory from langchain.memory import ConversationBufferMemory
from langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_USER
class MemoryComponent(Component): class MemoryComponent(Component):
display_name = "Chat Memory" display_name = "Chat Memory"
@ -25,15 +27,15 @@ class MemoryComponent(Component):
DropdownInput( DropdownInput(
name="sender", name="sender",
display_name="Sender Type", display_name="Sender Type",
options=["Machine", "User", "Machine and User"], options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER, "Machine and User"],
value="Machine and User", value="Machine and User",
info="Type of sender.", info="Filter by sender type.",
advanced=True, advanced=True,
), ),
MessageTextInput( MessageTextInput(
name="sender_name", name="sender_name",
display_name="Sender Name", display_name="Sender Name",
info="Name of the sender.", info="Filter by sender name.",
advanced=True, advanced=True,
), ),
IntInput( IntInput(
@ -46,7 +48,7 @@ class MemoryComponent(Component):
MessageTextInput( MessageTextInput(
name="session_id", name="session_id",
display_name="Session ID", display_name="Session ID",
info="Session ID of the chat history.", info="The session ID of the chat. If empty, the current session ID parameter will be used.",
advanced=True, advanced=True,
), ),
DropdownInput( DropdownInput(
@ -87,14 +89,14 @@ class MemoryComponent(Component):
self.memory.session_id = session_id self.memory.session_id = session_id
stored = self.memory.messages stored = self.memory.messages
if sender:
expected_type = "Machine" if sender == "Machine" else "User"
stored = [m for m in stored if m.type == expected_type]
if order == "ASC": if order == "ASC":
stored = stored[::-1] stored = stored[::-1]
if n_messages: if n_messages:
stored = stored[:n_messages] stored = stored[:n_messages]
stored = [Message.from_lc_message(m) for m in stored] 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: else:
stored = get_messages( stored = get_messages(
sender=sender, sender=sender,

View file

@ -3,6 +3,7 @@ from langflow.inputs import MessageInput, StrInput, HandleInput
from langflow.schema.message import Message from langflow.schema.message import Message
from langflow.template import Output from langflow.template import Output
from langflow.memory import get_messages, store_message from langflow.memory import get_messages, store_message
from langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_NAME_AI
class StoreMessageComponent(Component): class StoreMessageComponent(Component):
@ -23,16 +24,20 @@ class StoreMessageComponent(Component):
name="sender", name="sender",
display_name="Sender", display_name="Sender",
info="The sender of the message.", info="The sender of the message.",
value="AI", value=MESSAGE_SENDER_AI,
advanced=True, advanced=True,
), ),
StrInput( StrInput(
name="sender_name", display_name="Sender Name", info="The name of the sender.", value="AI", advanced=True name="sender_name",
display_name="Sender Name",
info="The name of the sender.",
value=MESSAGE_SENDER_NAME_AI,
advanced=True,
), ),
StrInput( StrInput(
name="session_id", name="session_id",
display_name="Session ID", display_name="Session ID",
info="The session ID of the chat.", info="The session ID of the chat. If empty, the current session ID parameter will be used.",
value="", value="",
), ),
] ]

View file

@ -4,6 +4,7 @@ from langflow.inputs import BoolInput
from langflow.io import DropdownInput, FileInput, MessageTextInput, MultilineInput, Output from langflow.io import DropdownInput, FileInput, MessageTextInput, MultilineInput, Output
from langflow.memory import store_message from langflow.memory import store_message
from langflow.schema.message import Message from langflow.schema.message import Message
from langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_USER, MESSAGE_SENDER_NAME_USER
class ChatInput(ChatComponent): class ChatInput(ChatComponent):
@ -29,8 +30,8 @@ class ChatInput(ChatComponent):
DropdownInput( DropdownInput(
name="sender", name="sender",
display_name="Sender Type", display_name="Sender Type",
options=["Machine", "User"], options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],
value="User", value=MESSAGE_SENDER_USER,
info="Type of sender.", info="Type of sender.",
advanced=True, advanced=True,
), ),
@ -38,11 +39,14 @@ class ChatInput(ChatComponent):
name="sender_name", name="sender_name",
display_name="Sender Name", display_name="Sender Name",
info="Name of the sender.", info="Name of the sender.",
value="User", value=MESSAGE_SENDER_NAME_USER,
advanced=True, advanced=True,
), ),
MessageTextInput( MessageTextInput(
name="session_id", display_name="Session ID", info="Session ID for the message.", advanced=True 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,
), ),
FileInput( FileInput(
name="files", name="files",

View file

@ -37,7 +37,10 @@ class AstraDBChatMemory(LCChatMemoryComponent):
advanced=True, advanced=True,
), ),
MessageTextInput( MessageTextInput(
name="session_id", display_name="Session ID", info="Session ID for the message.", advanced=True 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,
), ),
] ]

View file

@ -3,6 +3,7 @@ from langflow.inputs import BoolInput
from langflow.io import DropdownInput, MessageTextInput, Output from langflow.io import DropdownInput, MessageTextInput, Output
from langflow.memory import store_message from langflow.memory import store_message
from langflow.schema.message import Message from langflow.schema.message import Message
from langflow.utils.constants import MESSAGE_SENDER_NAME_AI, MESSAGE_SENDER_USER, MESSAGE_SENDER_AI
class ChatOutput(ChatComponent): class ChatOutput(ChatComponent):
@ -27,16 +28,23 @@ class ChatOutput(ChatComponent):
DropdownInput( DropdownInput(
name="sender", name="sender",
display_name="Sender Type", display_name="Sender Type",
options=["Machine", "User"], options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],
value="Machine", value=MESSAGE_SENDER_AI,
advanced=True, advanced=True,
info="Type of sender.", info="Type of sender.",
), ),
MessageTextInput( MessageTextInput(
name="sender_name", display_name="Sender Name", info="Name of the sender.", value="AI", advanced=True name="sender_name",
display_name="Sender Name",
info="Name of the sender.",
value=MESSAGE_SENDER_NAME_AI,
advanced=True,
), ),
MessageTextInput( MessageTextInput(
name="session_id", display_name="Session ID", info="Session ID for the message.", advanced=True 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,
), ),
MessageTextInput( MessageTextInput(
name="data_template", name="data_template",

View file

@ -8,6 +8,8 @@ from langchain_core.prompt_values import ImagePromptValue
from langchain_core.prompts.image import ImagePromptTemplate from langchain_core.prompts.image import ImagePromptTemplate
from pydantic import BaseModel, model_serializer, model_validator from pydantic import BaseModel, model_serializer, model_validator
from langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_USER
class Data(BaseModel): class Data(BaseModel):
""" """
@ -126,10 +128,10 @@ class Data(BaseModel):
# they are: "text", "sender" # they are: "text", "sender"
if not all(key in self.data for key in ["text", "sender"]): if not all(key in self.data for key in ["text", "sender"]):
raise ValueError(f"Missing required keys ('text', 'sender') in Data: {self.data}") raise ValueError(f"Missing required keys ('text', 'sender') in Data: {self.data}")
sender = self.data.get("sender", "Machine") sender = self.data.get("sender", MESSAGE_SENDER_AI)
text = self.data.get("text", "") text = self.data.get("text", "")
files = self.data.get("files", []) files = self.data.get("files", [])
if sender == "User": if sender == MESSAGE_SENDER_USER:
if files: if files:
contents = [{"type": "text", "text": text}] contents = [{"type": "text", "text": text}]
for file_path in files: for file_path in files:

View file

@ -14,6 +14,12 @@ from pydantic import BeforeValidator, ConfigDict, Field, field_serializer, field
from langflow.base.prompts.utils import dict_values_to_string from langflow.base.prompts.utils import dict_values_to_string
from langflow.schema.data import Data from langflow.schema.data import Data
from langflow.schema.image import Image, get_file_paths, is_image_file from langflow.schema.image import Image, get_file_paths, is_image_file
from langflow.utils.constants import (
MESSAGE_SENDER_USER,
MESSAGE_SENDER_NAME_USER,
MESSAGE_SENDER_NAME_AI,
MESSAGE_SENDER_AI,
)
def _timestamp_to_str(timestamp: datetime) -> str: def _timestamp_to_str(timestamp: datetime) -> str:
@ -91,7 +97,7 @@ class Message(Data):
else: else:
text = self.text text = self.text
if self.sender == "User" or not self.sender: if self.sender == MESSAGE_SENDER_USER or not self.sender:
if self.files: if self.files:
contents = [{"type": "text", "text": text}] contents = [{"type": "text", "text": text}]
contents.extend(self.get_file_content_dicts()) contents.extend(self.get_file_content_dicts())
@ -105,15 +111,19 @@ class Message(Data):
@classmethod @classmethod
def from_lc_message(cls, lc_message: BaseMessage) -> "Message": def from_lc_message(cls, lc_message: BaseMessage) -> "Message":
if lc_message.type == "human": if lc_message.type == "human":
sender = "User" sender = MESSAGE_SENDER_USER
sender_name = MESSAGE_SENDER_NAME_USER
elif lc_message.type == "ai": elif lc_message.type == "ai":
sender = "Machine" sender = MESSAGE_SENDER_AI
sender_name = MESSAGE_SENDER_NAME_AI
elif lc_message.type == "system": elif lc_message.type == "system":
sender = "System" sender = "System"
sender_name = "System"
else: else:
sender = lc_message.type sender = lc_message.type
sender_name = lc_message.type
return cls(text=lc_message.content, sender=sender, sender_name=sender) return cls(text=lc_message.content, sender=sender, sender_name=sender_name)
@classmethod @classmethod
def from_data(cls, data: "Data") -> "Message": def from_data(cls, data: "Data") -> "Message":

View file

@ -177,3 +177,9 @@ LOADERS_INFO: List[Dict[str, Any]] = [
"allowdTypes": ["docx"], "allowdTypes": ["docx"],
}, },
] ]
MESSAGE_SENDER_AI = "Machine"
MESSAGE_SENDER_USER = "User"
MESSAGE_SENDER_NAME_AI = "AI"
MESSAGE_SENDER_NAME_USER = "User"

View file

@ -6,6 +6,7 @@ from pydantic import BaseModel, field_validator, model_validator
from typing_extensions import TypedDict from typing_extensions import TypedDict
from langflow.base.data.utils import IMG_FILE_TYPES, TEXT_FILE_TYPES from langflow.base.data.utils import IMG_FILE_TYPES, TEXT_FILE_TYPES
from langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_NAME_AI
class File(TypedDict): class File(TypedDict):
@ -20,8 +21,8 @@ class ChatOutputResponse(BaseModel):
"""Chat output response schema.""" """Chat output response schema."""
message: Union[str, List[Union[str, Dict]]] message: Union[str, List[Union[str, Dict]]]
sender: Optional[str] = "Machine" sender: Optional[str] = MESSAGE_SENDER_AI
sender_name: Optional[str] = "AI" sender_name: Optional[str] = MESSAGE_SENDER_NAME_AI
session_id: Optional[str] = None session_id: Optional[str] = None
stream_url: Optional[str] = None stream_url: Optional[str] = None
component_id: Optional[str] = None component_id: Optional[str] = None
@ -71,8 +72,8 @@ class ChatOutputResponse(BaseModel):
def from_message( def from_message(
cls, cls,
message: BaseMessage, message: BaseMessage,
sender: Optional[str] = "Machine", sender: Optional[str] = MESSAGE_SENDER_AI,
sender_name: Optional[str] = "AI", sender_name: Optional[str] = MESSAGE_SENDER_NAME_AI,
): ):
"""Build chat output response from message.""" """Build chat output response from message."""
content = message.content content = message.content
@ -87,7 +88,7 @@ class ChatOutputResponse(BaseModel):
# \n\n -> \n\n # \n\n -> \n\n
# \n -> \n\n # \n -> \n\n
if self.sender != "Machine": if self.sender != MESSAGE_SENDER_AI:
return self return self
# We need to make sure we don't duplicate \n # We need to make sure we don't duplicate \n