fix: updated ChatOutput component not working with streaming enabled (#6747)

* fix: updated ChatOutput component not working with streaming enabled (#6744)

fixes: 69df913a14

Updated to handle the forgotten Generator case for self.input_value (encountered when streaming is enabled).

Overhauled the chat.py under outputs to (mostly) pass strict type checking, something which could have prevented this bug.

Only this file has been changed. The only type errors in this file are in the safe_convert function and are due to problems in other files.

To prevent further problems in the future, the project should work towards enabling strict type checking permanently after fixing the vast number of type problems.

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* update templates and make sure they support streaming without making breaking chnages

* update templates

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
This commit is contained in:
nicholas-johnson-techxcel 2025-02-22 03:57:49 +08:00 committed by GitHub
commit e82c21825b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 67 additions and 39 deletions

View file

@ -1,3 +1,4 @@
from collections.abc import Generator
from typing import Any
from langflow.base.io.chat import ChatComponent
@ -118,7 +119,6 @@ class ChatOutput(ChatComponent):
async def message_response(self) -> Message:
# First convert the input to string if needed
text = self.convert_to_string()
# Get source properties
source, icon, display_name, source_id = self.get_properties_from_source_component()
background_color = self.background_color
@ -158,8 +158,22 @@ class ChatOutput(ChatComponent):
if self.input_value is None:
msg = "Input data cannot be None"
raise ValueError(msg)
if not isinstance(self.input_value, Data | DataFrame | Message | str | list):
msg = f"Expected Data or DataFrame or Message or str, got {type(self.input_value).__name__}"
if isinstance(self.input_value, list) and not all(
isinstance(item, Message | Data | DataFrame | str) for item in self.input_value
):
invalid_types = [
type(item).__name__
for item in self.input_value
if not isinstance(item, Message | Data | DataFrame | str)
]
msg = f"Expected Data or DataFrame or Message or str, got {invalid_types}"
raise TypeError(msg)
if not isinstance(
self.input_value,
Message | Data | DataFrame | str | list | Generator | type(None),
):
type_name = type(self.input_value).__name__
msg = f"Expected Data or DataFrame or Message or str, Generator or None, got {type_name}"
raise TypeError(msg)
def _safe_convert(self, data: Any) -> str:
@ -188,9 +202,11 @@ class ChatOutput(ChatComponent):
msg = f"Error converting data: {e!s}"
raise ValueError(msg) from e
def convert_to_string(self) -> str:
def convert_to_string(self) -> str | Generator[Any, None, None]:
"""Convert input data to string with proper error handling."""
self._validate_input()
if isinstance(self.input_value, list):
return "\n".join([self._safe_convert(item) for item in self.input_value])
if isinstance(self.input_value, Generator):
return self.input_value
return self._safe_convert(self.input_value)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -94,5 +94,5 @@ class TestChatOutput(ComponentTestBaseWithClient):
await component.message_response()
component.input_value = 123 # Invalid type
with pytest.raises(TypeError, match="Expected Data or DataFrame or Message or str"):
with pytest.raises(TypeError, match="Expected Data or DataFrame or Message or str, Generator or None"):
await component.message_response()