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.schema.message import Message
from langflow.template import Output
from langflow.utils.constants import MESSAGE_SENDER_AI
class LCAgentComponent(Component):
@ -58,7 +59,7 @@ class LCAgentComponent(Component):
if isinstance(result, list):
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
return message

View file

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

View file

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

View file

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

View file

@ -8,6 +8,8 @@ from langflow.schema.message import Message
from langflow.field_typing import BaseChatMemory
from langchain.memory import ConversationBufferMemory
from langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_USER
class MemoryComponent(Component):
display_name = "Chat Memory"
@ -25,15 +27,15 @@ class MemoryComponent(Component):
DropdownInput(
name="sender",
display_name="Sender Type",
options=["Machine", "User", "Machine and User"],
options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER, "Machine and User"],
value="Machine and User",
info="Type of sender.",
info="Filter by sender type.",
advanced=True,
),
MessageTextInput(
name="sender_name",
display_name="Sender Name",
info="Name of the sender.",
info="Filter by sender name.",
advanced=True,
),
IntInput(
@ -46,7 +48,7 @@ class MemoryComponent(Component):
MessageTextInput(
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,
),
DropdownInput(
@ -87,14 +89,14 @@ class MemoryComponent(Component):
self.memory.session_id = session_id
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":
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 = get_messages(
sender=sender,

View file

@ -3,6 +3,7 @@ from langflow.inputs import MessageInput, StrInput, HandleInput
from langflow.schema.message import Message
from langflow.template import Output
from langflow.memory import get_messages, store_message
from langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_NAME_AI
class StoreMessageComponent(Component):
@ -23,16 +24,20 @@ class StoreMessageComponent(Component):
name="sender",
display_name="Sender",
info="The sender of the message.",
value="AI",
value=MESSAGE_SENDER_AI,
advanced=True,
),
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(
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="",
),
]

View file

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

View file

@ -37,7 +37,10 @@ class AstraDBChatMemory(LCChatMemoryComponent):
advanced=True,
),
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.memory import store_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):
@ -27,16 +28,23 @@ class ChatOutput(ChatComponent):
DropdownInput(
name="sender",
display_name="Sender Type",
options=["Machine", "User"],
value="Machine",
options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],
value=MESSAGE_SENDER_AI,
advanced=True,
info="Type of sender.",
),
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(
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(
name="data_template",

View file

@ -8,6 +8,8 @@ from langchain_core.prompt_values import ImagePromptValue
from langchain_core.prompts.image import ImagePromptTemplate
from pydantic import BaseModel, model_serializer, model_validator
from langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_USER
class Data(BaseModel):
"""
@ -126,10 +128,10 @@ class Data(BaseModel):
# they are: "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}")
sender = self.data.get("sender", "Machine")
sender = self.data.get("sender", MESSAGE_SENDER_AI)
text = self.data.get("text", "")
files = self.data.get("files", [])
if sender == "User":
if sender == MESSAGE_SENDER_USER:
if files:
contents = [{"type": "text", "text": text}]
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.schema.data import Data
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:
@ -91,7 +97,7 @@ class Message(Data):
else:
text = self.text
if self.sender == "User" or not self.sender:
if self.sender == MESSAGE_SENDER_USER or not self.sender:
if self.files:
contents = [{"type": "text", "text": text}]
contents.extend(self.get_file_content_dicts())
@ -105,15 +111,19 @@ class Message(Data):
@classmethod
def from_lc_message(cls, lc_message: BaseMessage) -> "Message":
if lc_message.type == "human":
sender = "User"
sender = MESSAGE_SENDER_USER
sender_name = MESSAGE_SENDER_NAME_USER
elif lc_message.type == "ai":
sender = "Machine"
sender = MESSAGE_SENDER_AI
sender_name = MESSAGE_SENDER_NAME_AI
elif lc_message.type == "system":
sender = "System"
sender_name = "System"
else:
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
def from_data(cls, data: "Data") -> "Message":

View file

@ -177,3 +177,9 @@ LOADERS_INFO: List[Dict[str, Any]] = [
"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 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):
@ -20,8 +21,8 @@ class ChatOutputResponse(BaseModel):
"""Chat output response schema."""
message: Union[str, List[Union[str, Dict]]]
sender: Optional[str] = "Machine"
sender_name: Optional[str] = "AI"
sender: Optional[str] = MESSAGE_SENDER_AI
sender_name: Optional[str] = MESSAGE_SENDER_NAME_AI
session_id: Optional[str] = None
stream_url: Optional[str] = None
component_id: Optional[str] = None
@ -71,8 +72,8 @@ class ChatOutputResponse(BaseModel):
def from_message(
cls,
message: BaseMessage,
sender: Optional[str] = "Machine",
sender_name: Optional[str] = "AI",
sender: Optional[str] = MESSAGE_SENDER_AI,
sender_name: Optional[str] = MESSAGE_SENDER_NAME_AI,
):
"""Build chat output response from message."""
content = message.content
@ -87,7 +88,7 @@ class ChatOutputResponse(BaseModel):
# \n\n -> \n\n
# \n -> \n\n
if self.sender != "Machine":
if self.sender != MESSAGE_SENDER_AI:
return self
# We need to make sure we don't duplicate \n