Another batch of renaming Record to Data

This commit is contained in:
ogabrielluiz 2024-06-12 18:18:03 -03:00
commit 16089ea5b2
61 changed files with 283 additions and 441 deletions

View file

@ -44,9 +44,13 @@ Adding or removing any of the below components modifies your Playground so you c
- Text Input
- Chat Output
- Text Output
- Records Output
- Data Output
- Inspect Memory
You can also select **Options** > **Logs** to see your flow's logs.
For more information, see [Inputs and Outputs](../components/inputs-and-outputs.mdx).
For more information, see [Inputs and Outputs](../components/inputs-and-outputs.mdx).import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js";
import ReactPlayer from "react-player";
import Admonition from "@theme/Admonition";

View file

@ -112,18 +112,18 @@ Call this component without parameters to list all flows.
---
## Merge Records
## Merge Data
This component merges a list of records.
This component merges a list of Data.
**Parameters**
- **Records:**
- **Display Name:** Records
- **Data:**
- **Display Name:** Data
**Usage**
Provide the records you want to merge.
Provide the Data you want to merge.
---

View file

@ -59,13 +59,13 @@ Learn more about creating custom components at [Custom Component](http://docs.la
---
### Documents to records
### Documents to Data
Convert LangChain documents into records.
Convert LangChain documents into Data.
#### Parameters
- **Documents:** Documents to be converted into records.
- **Documents:** Documents to be converted into Data.
---
@ -93,14 +93,14 @@ Retrieves stored chat messages based on a specific session ID.
---
### Records to text
### Data to text
Convert records into plain text following a specified template.
Convert Data into plain text following a specified template.
#### Parameters
- **Records:** The records to convert to text.
- **Template:** The template used for formatting the records. It can contain keys like `{text}`, `{data}`, or any other key in the record.
- **Data:** The Data to convert to text.
- **Template:** The template used for formatting the Data. It can contain keys like `{text}`, `{data}`, or any other key in the record.
---

View file

@ -6,11 +6,11 @@ In Langflow 1.0, we added two main input and output types: `Text` and `Data`.
We've created a few components to help you work with these types. Let's see how a few of them work.
## Records To Text
## Data To Text
This is a component that takes in Records and outputs a `Text`. It does this using a template string and concatenating the values of the `Data`, one per line.
This is a component that takes in Data and outputs a `Text`. It does this using a template string and concatenating the values of the `Data`, one per line.
If we have the following Records:
If we have the following Data:
```json
{
@ -36,7 +36,7 @@ John: Hi!
This component allows you to create a `Data` from a number of inputs. You can add as many key-value pairs as you want (as long as it is less than 15). Once you've picked that number you'll need to write the name of the Key and can pass `Text` values from other components to it.
## Documents To Records
## Documents To Data
This component takes in a LangChain `Document` and outputs a `Data`. It does this by extracting the `page_content` and the `metadata` from the `Document` and adding them to the `Data` as text and data respectively.

View file

@ -4,11 +4,11 @@ import Admonition from "@theme/Admonition";
### Astra DB
The `Astra DB` initializes a vector store using Astra DB from records. It creates Astra DB-based vector indexes to efficiently store and retrieve documents.
The `Astra DB` initializes a vector store using Astra DB from Data. It creates Astra DB-based vector indexes to efficiently store and retrieve documents.
**Parameters:**
- **Input:** Documents or records for input.
- **Input:** Documents or Data for input.
- **Embedding:** Embedding model Astra DB uses.
- **Collection Name:** Name of the Astra DB collection.
- **Token:** Authentication token for Astra DB.
@ -99,12 +99,12 @@ For detailed documentation and integration guides, please refer to the [Chroma C
### Couchbase
`Couchbase` builds a Couchbase vector store from records, streamlining the storage and retrieval of documents.
`Couchbase` builds a Couchbase vector store from Data, streamlining the storage and retrieval of documents.
**Parameters:**
- **Embedding:** Model used by Couchbase.
- **Input:** Documents or records.
- **Input:** Documents or Data.
- **Couchbase Cluster Connection String:** Cluster Connection string.
- **Couchbase Cluster Username:** Cluster Username.
- **Couchbase Cluster Password:** Cluster Password.
@ -165,12 +165,12 @@ For more details, see the [FAISS Component Documentation](https://faiss.ai/index
### MongoDB Atlas
`MongoDBAtlas` builds a MongoDB Atlas-based vector store from records, streamlining the storage and retrieval of documents.
`MongoDBAtlas` builds a MongoDB Atlas-based vector store from Data, streamlining the storage and retrieval of documents.
**Parameters:**
- **Embedding:** Model used by MongoDB Atlas.
- **Input:** Documents or records.
- **Input:** Documents or Data.
- **Collection Name:** Collection identifier in MongoDB Atlas.
- **Database Name:** Database identifier.
- **Index Name:** Index identifier.
@ -235,11 +235,11 @@ For more details, see the [PGVector Component Documentation](https://python.lang
### Pinecone
`Pinecone` constructs a Pinecone wrapper from records, setting up Pinecone-based vector indexes for document storage and retrieval.
`Pinecone` constructs a Pinecone wrapper from Data, setting up Pinecone-based vector indexes for document storage and retrieval.
**Parameters:**
- **Input:** Documents or records.
- **Input:** Documents or Data.
- **Embedding:** Model used.
- **Index Name:** Index identifier.
- **Namespace:** Namespace used.
@ -278,7 +278,7 @@ For more details, see the [PGVector Component Documentation](https://python.lang
**Parameters:**
- **Input:** Documents or records.
- **Input:** Documents or Data.
- **Embedding:** Model used.
- **API Key:** Qdrant API key.
- **Collection Name:** Collection identifier.
@ -345,7 +345,7 @@ For detailed documentation, refer to the [Redis Documentation](https://python.la
**Parameters:**
- **Input:** Documents or records.
- **Input:** Documents or data.
- **Embedding:** Model used.
- **Query Name:** Optional query name.
- **Search Kwargs:** Advanced search parameters.

View file

@ -8,14 +8,13 @@ import Admonition from "@theme/Admonition";
In Langflow, a `Data` has a structure very similar to a Python dictionary. It is a key-value pair data structure.
The **Create Data** component allows you to dynamically create a `Data` from a specified number of inputs. You can add as many key-value pairs as you want (as long as it is less than 15 😅). Once you've chosen the number of `Records`, add keys and fill up values, or pass on values from other components to the component using the input handles.
The **Create Data** component allows you to dynamically create a `Data` from a specified number of inputs. You can add as many key-value pairs as you want (as long as it is less than 15 😅). Once you've chosen the number of `Data`, add keys and fill up values, or pass on values from other components to the component using the input handles.
<div
style={{ marginBottom: "20px", display: "flex", justifyContent: "center" }}
>
<ReactPlayer playing controls url="/videos/create_record.mp4" />
</div>
import ThemedImage from "@theme/ThemedImage"; import useBaseUrl from
"@docusaurus/useBaseUrl"; import ZoomableImage from
"/src/theme/ZoomableImage.js"; import ReactPlayer from "react-player"; import
Admonition from "@theme/Admonition";
import ThemedImage from "@theme/ThemedImage"; import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js"; import ReactPlayer from
"react-player"; import Admonition from "@theme/Admonition";

View file

@ -136,10 +136,10 @@ The RAG flow is a bit more complex. It consists of:
- **Chat Input** component that defines where to put the user input coming from the Playground
- **OpenAI Embeddings** component that generates embeddings from the user input
- **Astra DB Search** component that retrieves the most relevant Records from the Astra DB database
- **Text Output** component that turns the Records into Text by concatenating them and also displays it in the Playground
- **Astra DB Search** component that retrieves the most relevant Data from the Astra DB database
- **Text Output** component that turns the Data into Text by concatenating them and also displays it in the Playground
- One interesting point you'll see here is that this component is named `Extracted Chunks`, and that is how it will appear in the Playground
- **Prompt** component that takes in the user input and the retrieved Records as text and builds a prompt for the OpenAI model
- **Prompt** component that takes in the user input and the retrieved Data as text and builds a prompt for the OpenAI model
- **OpenAI** component that generates a response to the prompt
- **Chat Output** component that displays the response in the Playground
@ -176,7 +176,7 @@ Because this flow has a **Chat Input** and a **Text Output** component, the Pane
style={{ width: "80%", margin: "20px auto" }}
/>
Once we interact with it we get a response and the Extracted Chunks section is updated with the retrieved records.
Once we interact with it we get a response and the Extracted Chunks section is updated with the retrieved data.
<ZoomableImage
alt="Docusaurus themed image"
@ -192,4 +192,16 @@ And that's it! You have successfully ran a RAG application using Astra DB and La
# Conclusion
In this guide, we have learned how to run a RAG application using Astra DB and Langflow.
We have seen how to create an Astra DB database, import the Astra DB RAG Flows project into Langflow, and run the ingestion and RAG flows.
We have seen how to create an Astra DB database, import the Astra DB RAG Flows project into Langflow, and run the ingestion and RAG flows.import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js";
import Admonition from "@theme/Admonition";import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js";
import Admonition from "@theme/Admonition";import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js";
import Admonition from "@theme/Admonition";import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js";
import Admonition from "@theme/Admonition";

View file

@ -107,7 +107,7 @@ class NotionListPages(CustomComponent):
response.raise_for_status()
results = response.json()
records = []
data = []
combined_text = f"Pages found: {len(results['results'])}\n\n"
for page in results['results']:
page_data = {
@ -127,10 +127,10 @@ class NotionListPages(CustomComponent):
)
combined_text += text
records.append(Data(text=text, data=page_data))
data.append(Data(text=text, data=page_data))
self.status = combined_text.strip()
return records
return data
except Exception as e:
self.status = f"An error occurred: {str(e)}"

View file

@ -65,14 +65,14 @@ class NotionUserList(CustomComponent):
data = response.json()
results = data['results']
records = []
data = []
for user in results:
id = user['id']
type = user['type']
name = user.get('name', '')
avatar_url = user.get('avatar_url', '')
record_data = {
data_dict = {
"id": id,
"type": type,
"name": name,
@ -80,15 +80,15 @@ class NotionUserList(CustomComponent):
}
output = "User:\n"
for key, value in record_data.items():
for key, value in data_dict.items():
output += f"{key.replace('_', ' ').title()}: {value}\n"
output += "________________________\n"
record = Data(text=output, data=record_data)
records.append(record)
record = Data(text=output, data=data_dict)
data.append(record)
self.status = "\n".join(record.text for record in records)
return records
self.status = "\n".join(record.text for record in data)
return data
```
## Example Usage

View file

@ -113,7 +113,7 @@ class NotionSearch(CustomComponent):
response.raise_for_status()
results = response.json()
records = []
data = []
combined_text = f"Results found: {len(results['results'])}\n\n"
for result in results['results']:
result_data = {
@ -135,10 +135,10 @@ class NotionSearch(CustomComponent):
text += f"type: {result['object']}\nlast_edited_time: {result['last_edited_time']}\n\n"
combined_text += text
records.append(Data(text=text, data=result_data))
data.append(Data(text=text, data=result_data))
self.status = combined_text
return records
return data
except Exception as e:
self.status = f"An error occurred: {str(e)}"

View file

@ -56,9 +56,9 @@ The **query** flow (top of the screen) allows users to chat with the embedded ve
- **Chat Input** component defines where to put the user input coming from the Playground.
- **OpenAI Embeddings** component generates embeddings from the user input.
- **Astra DB Search** component retrieves the most relevant Records from the Astra DB database.
- **Text Output** component turns the Records into Text by concatenating them and also displays it in the Playground.
- **Prompt** component takes in the user input and the retrieved Records as text and builds a prompt for the OpenAI model.
- **Astra DB Search** component retrieves the most relevant Data from the Astra DB database.
- **Text Output** component turns the Data into Text by concatenating them and also displays it in the Playground.
- **Prompt** component takes in the user input and the retrieved Data as text and builds a prompt for the OpenAI model.
- **OpenAI** component generates a response to the prompt.
- **Chat Output** component displays the response in the Playground.
@ -106,4 +106,16 @@ AI
You should use a 3/8 inch wrench to remove the oil drain cap.
```
This is the size the engine manual lists as well. This confirms our flow works, because the query returns the unique knowledge we embedded from the Astra vector store.
This is the size the engine manual lists as well. This confirms our flow works, because the query returns the unique knowledge we embedded from the Astra vector store.import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js";
import ReactPlayer from "react-player";
import Admonition from "@theme/Admonition";import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js";
import ReactPlayer from "react-player";
import Admonition from "@theme/Admonition";import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js";
import ReactPlayer from "react-player";
import Admonition from "@theme/Admonition";

View file

@ -130,10 +130,10 @@ The RAG flow is a bit more complex. It consists of:
- **Chat Input** component that defines where to put the user input coming from the Playground
- **OpenAI Embeddings** component that generates embeddings from the user input
- **Astra DB Search** component that retrieves the most relevant Records from the Astra DB database
- **Text Output** component that turns the Records into Text by concatenating them and also displays it in the Playground
- **Astra DB Search** component that retrieves the most relevant Data from the Astra DB database
- **Text Output** component that turns the Data into Text by concatenating them and also displays it in the Playground
- One interesting point you'll see here is that this component is named `Extracted Chunks`, and that is how it will appear in the Playground
- **Prompt** component that takes in the user input and the retrieved Records as text and builds a prompt for the OpenAI model
- **Prompt** component that takes in the user input and the retrieved Data as text and builds a prompt for the OpenAI model
- **OpenAI** component that generates a response to the prompt
- **Chat Output** component that displays the response in the Playground
@ -170,7 +170,7 @@ Because this flow has a **Chat Input** and a **Text Output** component, the Pane
style={{ width: "80%", margin: "20px auto" }}
/>
Once we interact with it we get a response and the Extracted Chunks section is updated with the retrieved records.
Once we interact with it we get a response and the Extracted Chunks section is updated with the retrieved Data.
<ZoomableImage
alt="Docusaurus themed image"
@ -186,4 +186,16 @@ And that's it! You have successfully ran a RAG application using Astra DB and La
# Conclusion
In this guide, we have learned how to run a RAG application using Astra DB and Langflow.
We have seen how to create an Astra DB database, import the Astra DB RAG Flows project into Langflow, and run the ingestion and RAG flows.
We have seen how to create an Astra DB database, import the Astra DB RAG Flows project into Langflow, and run the ingestion and RAG flows.import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js";
import Admonition from "@theme/Admonition";import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js";
import Admonition from "@theme/Admonition";import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js";
import Admonition from "@theme/Admonition";import ThemedImage from "@theme/ThemedImage";
import useBaseUrl from "@docusaurus/useBaseUrl";
import ZoomableImage from "/src/theme/ZoomableImage.js";
import Admonition from "@theme/Admonition";

View file

@ -82,7 +82,7 @@ def retrieve_file_paths(
# ! Removing unstructured dependency until
# ! 3.12 is supported
# def partition_file_to_record(file_path: str, silent_errors: bool) -> Optional[Data]:
# def partition_file_to_data(file_path: str, silent_errors: bool) -> Optional[Data]:
# # Use the partition function to load the file
# from unstructured.partition.auto import partition # type: ignore
@ -129,7 +129,7 @@ def parse_pdf_to_text(file_path: str) -> str:
return "\n\n".join([page.extract_text() for page in reader.pages])
def parse_text_file_to_record(file_path: str, silent_errors: bool) -> Optional[Data]:
def parse_text_file_to_data(file_path: str, silent_errors: bool) -> Optional[Data]:
try:
if file_path.endswith(".pdf"):
text = parse_pdf_to_text(file_path)
@ -171,7 +171,7 @@ def parse_text_file_to_record(file_path: str, silent_errors: bool) -> Optional[D
# if use_multithreading:
# data = parallel_load_data(file_paths, silent_errors, max_concurrency)
# else:
# data = [partition_file_to_record(file_path, silent_errors) for file_path in file_paths]
# data = [partition_file_to_data(file_path, silent_errors) for file_path in file_paths]
# data = list(filter(None, data))
# return data
@ -180,7 +180,7 @@ def parallel_load_data(
file_paths: List[str],
silent_errors: bool,
max_concurrency: int,
load_function: Callable = parse_text_file_to_record,
load_function: Callable = parse_text_file_to_data,
) -> List[Optional[Data]]:
with futures.ThreadPoolExecutor(max_workers=max_concurrency) as executor:
loaded_files = executor.map(

View file

@ -34,7 +34,7 @@ class ChatComponent(Component):
"info": "Return the message as a Message containing the sender, sender_name, and session_id.",
"advanced": True,
},
"record_template": {
"data_template": {
"display_name": "Data Template",
"multiline": True,
"info": "In case of Message being a Data, this template will be used to convert it to text.",
@ -61,7 +61,7 @@ class ChatComponent(Component):
self.status = messages
return messages
def build_with_record(
def build_with_data(
self,
sender: Optional[str] = "User",
sender_name: Optional[str] = "User",
@ -74,7 +74,7 @@ class ChatComponent(Component):
if isinstance(input_value, Data):
# Update the data of the record
message = Message.from_record(input_value)
message = Message.from_data(input_value)
else:
message = Message(
text=input_value, sender=sender, sender_name=sender_name, files=files, session_id=session_id

View file

@ -2,7 +2,7 @@ from typing import Optional
from langflow.custom import Component
from langflow.field_typing import Text
from langflow.helpers.record import data_to_text
from langflow.helpers.data import data_to_text
from langflow.schema import Data
@ -17,7 +17,7 @@ class TextComponent(Component):
"input_types": ["Text", "Data"],
"info": "Text or Data to be passed.",
},
"record_template": {
"data_template": {
"display_name": "Data Template",
"multiline": True,
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
@ -28,14 +28,14 @@ class TextComponent(Component):
def build(
self,
input_value: Optional[Text] = "",
record_template: Optional[str] = "{text}",
data_template: Optional[str] = "{text}",
) -> Text:
if isinstance(input_value, Data):
if record_template == "":
if data_template == "":
# it should be dynamically set to the Data's .text_key value
# meaning, if text_key = "bacon", then record_template = "{bacon}"
record_template = "{" + input_value.text_key + "}"
input_value = data_to_text(template=record_template, data=input_value)
# meaning, if text_key = "bacon", then data_template = "{bacon}"
data_template = "{" + input_value.text_key + "}"
input_value = data_to_text(template=data_template, data=input_value)
self.status = input_value
if not input_value:
input_value = ""

View file

@ -32,7 +32,7 @@ class BaseMemoryComponent(CustomComponent):
"info": "Order of the messages.",
"advanced": True,
},
"record_template": {
"data_template": {
"display_name": "Data Template",
"multiline": True,
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",

View file

@ -6,7 +6,7 @@ from langflow.schema import Data
from langflow.schema.message import Message
def record_to_string(record: Data) -> str:
def data_to_string(record: Data) -> str:
"""
Convert a record to a string.
@ -38,13 +38,13 @@ def dict_values_to_string(d: dict) -> dict:
if isinstance(item, Message):
d_copy[key][i] = item.text
elif isinstance(item, Data):
d_copy[key][i] = record_to_string(item)
d_copy[key][i] = data_to_string(item)
elif isinstance(item, Document):
d_copy[key][i] = document_to_string(item)
elif isinstance(value, Message):
d_copy[key] = value.text
elif isinstance(value, Data):
d_copy[key] = record_to_string(value)
d_copy[key] = data_to_string(value)
elif isinstance(value, Document):
d_copy[key] = document_to_string(value)
return d_copy

View file

@ -13,12 +13,12 @@ def chroma_collection_to_data(collection_dict: dict):
"""
data = []
for i, doc in enumerate(collection_dict["documents"]):
record_dict = {
data_dict = {
"id": collection_dict["ids"][i],
"text": doc,
}
if "metadatas" in collection_dict:
for key, value in collection_dict["metadatas"][i].items():
record_dict[key] = value
data.append(Data(**record_dict))
data_dict[key] = value
data.append(Data(**data_dict))
return data

View file

@ -1,6 +1,6 @@
from typing import Any, Dict, List, Optional
from langflow.base.data.utils import parallel_load_data, parse_text_file_to_record, retrieve_file_paths
from langflow.base.data.utils import parallel_load_data, parse_text_file_to_data, retrieve_file_paths
from langflow.custom import CustomComponent
from langflow.schema import Data
@ -57,7 +57,7 @@ class DirectoryComponent(CustomComponent):
if use_multithreading:
loaded_data = parallel_load_data(file_paths, silent_errors, max_concurrency)
else:
loaded_data = [parse_text_file_to_record(file_path, silent_errors) for file_path in file_paths]
loaded_data = [parse_text_file_to_data(file_path, silent_errors) for file_path in file_paths]
loaded_data = list(filter(None, loaded_data))
self.status = loaded_data
return loaded_data

View file

@ -1,7 +1,7 @@
from pathlib import Path
from typing import Any, Dict
from langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_record
from langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_data
from langflow.custom import CustomComponent
from langflow.schema import Data
@ -34,7 +34,7 @@ class FileComponent(CustomComponent):
raise ValueError("doc files are not supported. Please save as .docx")
if extension not in TEXT_FILE_TYPES:
raise ValueError(f"Unsupported file type: {extension}")
record = parse_text_file_to_record(resolved_path, silent_errors)
record = parse_text_file_to_data(resolved_path, silent_errors)
self.status = record if record else "No data"
return record or Data()

View file

@ -2,16 +2,16 @@ from langflow.custom import CustomComponent
from langflow.schema import Data
class ExtractKeyFromRecordComponent(CustomComponent):
class ExtractKeyFromdataComponent(CustomComponent):
display_name = "Extract Key From Data"
description = "Extracts a key from a record."
description = "Extracts a key from a data."
beta: bool = True
field_config = {
"record": {"display_name": "Data"},
"data": {"display_name": "Data"},
"keys": {
"display_name": "Keys",
"info": "The keys to extract from the record.",
"info": "The keys to extract from the data.",
"input_types": [],
},
"silent_error": {
@ -21,13 +21,13 @@ class ExtractKeyFromRecordComponent(CustomComponent):
},
}
def build(self, record: Data, keys: list[str], silent_error: bool = True) -> Data:
def build(self, data: Data, keys: list[str], silent_error: bool = True) -> Data:
"""
Extracts the keys from a record.
Extracts the keys from a data.
Args:
record (Data): The record from which to extract the keys.
keys (list[str]): The keys to extract from the record.
data (Data): The data from which to extract the keys.
keys (list[str]): The keys to extract from the data.
silent_error (bool): If True, errors will not be raised.
Returns:
@ -36,10 +36,10 @@ class ExtractKeyFromRecordComponent(CustomComponent):
extracted_keys = {}
for key in keys:
try:
extracted_keys[key] = getattr(record, key)
extracted_keys[key] = getattr(data, key)
except AttributeError:
if not silent_error:
raise KeyError(f"The key '{key}' does not exist in the record.")
return_record = Data(data=extracted_keys)
self.status = return_record
return return_record
raise KeyError(f"The key '{key}' does not exist in the data.")
return_data = Data(data=extracted_keys)
self.status = return_data
return return_data

View file

@ -18,7 +18,7 @@ class FlowToolComponent(CustomComponent):
def get_flow_names(self) -> List[str]:
flow_data = self.list_flows()
return [flow_record.data["name"] for flow_record in flow_data]
return [flow_data.data["name"] for flow_data in flow_data]
def get_flow(self, flow_name: str) -> Optional[Data]:
"""
@ -31,9 +31,9 @@ class FlowToolComponent(CustomComponent):
Optional[Text]: The flow record if found, None otherwise.
"""
flow_data = self.list_flows()
for flow_record in flow_data:
if flow_record.data["name"] == flow_name:
return flow_record
for flow_data in flow_data:
if flow_data.data["name"] == flow_name:
return flow_data
return None
def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None):
@ -69,10 +69,10 @@ class FlowToolComponent(CustomComponent):
async def build(self, flow_name: str, name: str, description: str, return_direct: bool = False) -> Tool:
FlowTool.update_forward_refs()
flow_record = self.get_flow(flow_name)
if not flow_record:
flow_data = self.get_flow(flow_name)
if not flow_data:
raise ValueError("Flow not found.")
graph = Graph.from_payload(flow_record.data["data"])
graph = Graph.from_payload(flow_data.data["data"])
inputs = get_flow_inputs(graph)
tool = FlowTool(
name=name,
@ -80,7 +80,7 @@ class FlowToolComponent(CustomComponent):
graph=graph,
return_direct=return_direct,
inputs=inputs,
flow_id=str(flow_record.id),
flow_id=str(flow_data.id),
user_id=str(self._user_id),
)
description_repr = repr(tool.description).strip("'")

View file

@ -2,13 +2,13 @@ from langflow.custom import CustomComponent
from langflow.schema import Data
class MergeRecordsComponent(CustomComponent):
display_name = "Merge Records"
class MergeDataComponent(CustomComponent):
display_name = "Merge Data"
description = "Merges data."
beta: bool = True
field_config = {
"data": {"display_name": "Records"},
"data": {"display_name": "Data"},
}
def build(self, data: list[Data]) -> Data:
@ -16,14 +16,14 @@ class MergeRecordsComponent(CustomComponent):
return Data()
if len(data) == 1:
return data[0]
merged_record = Data()
merged_data = Data()
for value in data:
if merged_record is None:
merged_record = value
if merged_data is None:
merged_data = value
else:
merged_record += value
self.status = merged_record
return merged_record
merged_data += value
self.status = merged_data
return merged_data
if __name__ == "__main__":
@ -31,6 +31,6 @@ if __name__ == "__main__":
Data(data={"key1": "value1"}),
Data(data={"key2": "value2"}),
]
component = MergeRecordsComponent()
component = MergeDataComponent()
result = component.build(data)
print(result)

View file

@ -13,29 +13,29 @@ class NotifyComponent(CustomComponent):
def build_config(self):
return {
"name": {"display_name": "Name", "info": "The name of the notification."},
"record": {"display_name": "Data", "info": "The record to store."},
"data": {"display_name": "Data", "info": "The data to store."},
"append": {
"display_name": "Append",
"info": "If True, the record will be appended to the notification.",
},
}
def build(self, name: str, record: Optional[Data] = None, append: bool = False) -> Data:
if record and not isinstance(record, Data):
if isinstance(record, str):
record = Data(text=record)
elif isinstance(record, dict):
record = Data(data=record)
def build(self, name: str, data: Optional[Data] = None, append: bool = False) -> Data:
if data and not isinstance(data, Data):
if isinstance(data, str):
data = Data(text=data)
elif isinstance(data, dict):
data = Data(data=data)
else:
record = Data(text=str(record))
elif not record:
record = Data(text="")
if record:
data = Data(text=str(data))
elif not data:
data = Data(text="")
if data:
if append:
self.append_state(name, record)
self.append_state(name, data)
else:
self.update_state(name, record)
self.update_state(name, data)
else:
self.status = "No record provided."
self.status = record
return record
self.status = data
return data

View file

@ -14,7 +14,7 @@ class RunFlowComponent(CustomComponent):
def get_flow_names(self) -> List[str]:
flow_data = self.list_flows()
return [flow_record.data["name"] for flow_record in flow_data]
return [flow_data.data["name"] for flow_data in flow_data]
def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None):
if field_name == "flow_name":

View file

@ -23,13 +23,13 @@ class SubFlowComponent(CustomComponent):
def get_flow_names(self) -> List[str]:
flow_data = self.list_flows()
return [flow_record.data["name"] for flow_record in flow_data]
return [flow_data.data["name"] for flow_data in flow_data]
def get_flow(self, flow_name: str) -> Optional[Data]:
flow_data = self.list_flows()
for flow_record in flow_data:
if flow_record.data["name"] == flow_name:
return flow_record
for flow_data in flow_data:
if flow_data.data["name"] == flow_name:
return flow_data
return None
def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None):
@ -42,10 +42,10 @@ class SubFlowComponent(CustomComponent):
del build_config[key]
if field_value is not None and field_name == "flow_name":
try:
flow_record = self.get_flow(field_value)
if not flow_record:
flow_data = self.get_flow(field_value)
if not flow_data:
raise ValueError(f"Flow {field_value} not found.")
graph = Graph.from_payload(flow_record.data["data"])
graph = Graph.from_payload(flow_data.data["data"])
# Get all inputs from the graph
inputs = get_flow_inputs(graph)
# Add inputs to the build config

View file

@ -1,25 +1,24 @@
from .AgentComponent import AgentComponent
from .ClearMessageHistory import ClearMessageHistoryComponent
from .ExtractDataFromRecord import ExtractKeyFromRecordComponent
from .ExtractDataFromData import ExtractKeyFromDataComponent
from .FlowTool import FlowToolComponent
from .ListFlows import ListFlowsComponent
from .Listen import ListenComponent
from .MergeRecords import MergeRecordsComponent
from .ListFlows import ListFlowsComponent
from .Notify import NotifyComponent
from .PythonFunction import PythonFunctionComponent
from .RunFlow import RunFlowComponent
from .RunnableExecutor import RunnableExecComponent
from .SQLExecutor import SQLExecutorComponent
from .SubFlow import SubFlowComponent
from .AgentComponent import AgentComponent
__all__ = [
"AgentComponent",
"ClearMessageHistoryComponent",
"ExtractKeyFromRecordComponent",
"ExtractKeyFromDataComponent",
"FlowToolComponent",
"ListFlowsComponent",
"ListenComponent",
"MergeRecordsComponent",
"MergeDataComponent",
"NotifyComponent",
"PythonFunctionComponent",
"RunFlowComponent",

View file

@ -7,7 +7,7 @@ from langflow.schema.dotdict import dotdict
from langflow.template.field.base import Input
class CreateRecordComponent(CustomComponent):
class CreateDataComponent(CustomComponent):
display_name = "Create Data"
description = "Dynamically create a Data with a specified number of fields."
field_order = ["number_of_fields", "text_key"]
@ -22,7 +22,7 @@ class CreateRecordComponent(CustomComponent):
existing_fields = {}
if field_value_int > 15:
build_config["number_of_fields"]["value"] = 15
raise ValueError("Number of fields cannot exceed 15. Try using a Component to combine two Records.")
raise ValueError("Number of fields cannot exceed 15. Try using a Component to combine two Data.")
if len(build_config) > len(default_keys) + field_value_int:
# back up the existing template fields
for key in build_config.copy():
@ -76,6 +76,6 @@ class CreateRecordComponent(CustomComponent):
key: value.get_text() if isinstance(value, Data) else value for key, value in value_dict.items()
}
data.update(value_dict)
return_record = Data(data=data, text_key=text_key)
self.status = return_record
return return_record
return_data = Data(data=data, text_key=text_key)
self.status = return_data
return return_data

View file

@ -1,17 +1,17 @@
from langflow.custom import CustomComponent
from langflow.field_typing import Text
from langflow.helpers.record import data_to_text
from langflow.helpers.data import data_to_text
from langflow.schema import Data
class RecordsToTextComponent(CustomComponent):
display_name = "Records To Text"
description = "Convert Records into plain text following a specified template."
class DataToTextComponent(CustomComponent):
display_name = "Data To Text"
description = "Convert Data into plain text following a specified template."
def build_config(self):
return {
"data": {
"display_name": "Records",
"display_name": "Data",
"info": "The data to convert to text.",
},
"template": {

View file

@ -6,9 +6,9 @@ from langflow.custom import CustomComponent
from langflow.schema import Data
class DocumentToRecordComponent(CustomComponent):
display_name = "Documents To Records"
description = "Convert LangChain Documents into Records."
class DocumentToDataComponent(CustomComponent):
display_name = "Documents To Data"
description = "Convert LangChain Documents into Data."
field_config = {
"documents": {"display_name": "Documents"},

View file

@ -2,7 +2,7 @@ from typing import Optional
from langflow.base.memory.memory import BaseMemoryComponent
from langflow.field_typing import Text
from langflow.helpers.record import messages_to_text
from langflow.helpers.data import messages_to_text
from langflow.memory import get_messages
from langflow.schema.message import Message
@ -35,7 +35,7 @@ class MemoryComponent(BaseMemoryComponent):
"info": "Order of the messages.",
"advanced": True,
},
"record_template": {
"data_template": {
"display_name": "Data Template",
"multiline": True,
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
@ -68,7 +68,7 @@ class MemoryComponent(BaseMemoryComponent):
session_id: Optional[str] = None,
n_messages: int = 5,
order: Optional[str] = "Descending",
record_template: Optional[str] = "{sender_name}: {text}",
data_template: Optional[str] = "{sender_name}: {text}",
) -> Text:
messages = self.get_messages(
sender=sender,
@ -77,6 +77,6 @@ class MemoryComponent(BaseMemoryComponent):
limit=n_messages,
order=order,
)
messages_str = messages_to_text(template=record_template or "", messages=messages)
messages_str = messages_to_text(template=data_template or "", messages=messages)
self.status = messages_str
return messages_str

View file

@ -2,13 +2,13 @@ from langflow.custom import CustomComponent
from langflow.schema import Data
class UpdateRecordComponent(CustomComponent):
class UpdateDataComponent(CustomComponent):
display_name = "Update Data"
description = "Update Data with text-based key/value pairs, similar to updating a Python dictionary."
def build_config(self):
return {
"record": {
"data": {
"display_name": "Data",
"info": "The record to update.",
},
@ -21,7 +21,7 @@ class UpdateRecordComponent(CustomComponent):
def build(
self,
record: Data,
data: Data,
new_data: dict,
) -> Data:
"""
@ -34,6 +34,6 @@ class UpdateRecordComponent(CustomComponent):
Returns:
Data: The updated record.
"""
record.data.update(new_data)
self.status = record
return record
data.data.update(new_data)
self.status = data
return data

View file

@ -1,17 +1,17 @@
from .CreateRecord import CreateRecordComponent
from .CreateData import CreateDataComponent
from .CustomComponent import Component
from .DocumentToRecord import DocumentToRecordComponent
from .DataToText import DataToTextComponent
from .DocumentToData import DocumentToDataComponent
from .IDGenerator import UUIDGeneratorComponent
from .MessageHistory import MessageHistoryComponent
from .UpdateRecord import UpdateRecordComponent
from .RecordsToText import RecordsToTextComponent
from .UpdateData import UpdateDataComponent
__all__ = [
"Component",
"UpdateRecordComponent",
"DocumentToRecordComponent",
"UpdateDataComponent",
"DocumentToDataComponent",
"UUIDGeneratorComponent",
"RecordsToTextComponent",
"CreateRecordComponent",
"DataToTextComponent",
"CreateDataComponent",
"MessageHistoryComponent",
]

View file

@ -17,7 +17,7 @@ class TextInput(TextComponent):
input_types=["Data", "Text"],
),
Input(
name="record_template",
name="data_template",
type=str,
display_name="Data Template",
multiline=True,
@ -30,4 +30,4 @@ class TextInput(TextComponent):
]
def text_response(self) -> Text:
return self.build(input_value=self.input_value, record_template=self.record_template)
return self.build(input_value=self.input_value, data_template=self.data_template)

View file

@ -29,7 +29,7 @@ class ChatOutput(ChatComponent):
StrInput(name="sender_name", display_name="Sender Name", info="Name of the sender.", value="AI", advanced=True),
StrInput(name="session_id", display_name="Session ID", info="Session ID for the message.", advanced=True),
BoolInput(
name="record_template",
name="data_template",
display_name="Data Template",
value="{text}",
advanced=True,

View file

@ -3,17 +3,17 @@ from langflow.schema import Data
from langflow.template import Input, Output
class RecordsOutput(Component):
display_name = "Records Output"
description = "Display Records as a Table"
class DataOutput(Component):
display_name = "Data Output"
description = "Display Data as a Table"
inputs = [
Input(name="input_value", type=Data, display_name="Data Input"),
]
outputs = [
Output(display_name="Data", name="record", method="record_response"),
Output(display_name="Data", name="data", method="data_response"),
]
def record_response(self) -> Data:
def data_response(self) -> Data:
self.status = self.input_value
return self.input_value

View file

@ -17,7 +17,7 @@ class TextOutput(TextComponent):
input_types=["Data", "Text"],
),
Input(
name="record_template",
name="data_template",
type=str,
display_name="Data Template",
multiline=True,
@ -30,4 +30,4 @@ class TextOutput(TextComponent):
]
def text_response(self) -> Text:
return self.build(input_value=self.input_value, record_template=self.record_template)
return self.build(input_value=self.input_value, data_template=self.data_template)

View file

@ -6,7 +6,7 @@ from langchain_core.vectorstores import VectorStore
from langflow.custom import CustomComponent
from langflow.field_typing import Text
from langflow.helpers.record import docs_to_data
from langflow.helpers.data import docs_to_data
from langflow.schema import Data

View file

@ -53,7 +53,7 @@ class InterfaceComponentTypes(str, Enum, metaclass=ContainsEnumMeta):
ChatOutput = "ChatOutput"
TextInput = "TextInput"
TextOutput = "TextOutput"
RecordsOutput = "RecordsOutput"
DataOutput = "DataOutput"
def __contains__(cls, item):
try:
@ -65,7 +65,7 @@ class InterfaceComponentTypes(str, Enum, metaclass=ContainsEnumMeta):
CHAT_COMPONENTS = [InterfaceComponentTypes.ChatInput, InterfaceComponentTypes.ChatOutput]
RECORDS_COMPONENTS = [InterfaceComponentTypes.RecordsOutput]
RECORDS_COMPONENTS = [InterfaceComponentTypes.DataOutput]
INPUT_COMPONENTS = [
InterfaceComponentTypes.ChatInput,
InterfaceComponentTypes.TextInput,

View file

@ -12,7 +12,7 @@ from langflow.schema import Data
from langflow.schema.artifact import ArtifactType
from langflow.schema.schema import INPUT_FIELD_NAME, build_logs_from_artifacts
from langflow.services.monitor.utils import log_transaction, log_vertex_build
from langflow.utils.schemas import ChatOutputResponse, RecordOutputResponse
from langflow.utils.schemas import ChatOutputResponse, DataOutputResponse
from langflow.utils.util import unescape_string
if TYPE_CHECKING:
@ -259,7 +259,7 @@ class InterfaceVertex(ComponentVertex):
return message
def _process_record_component(self):
def _process_data_component(self):
"""
Process the record component of the vertex.
@ -291,7 +291,7 @@ class InterfaceVertex(ComponentVertex):
logger.error(f"Data expected, but got {value} of type {type(value)}")
else:
raise ValueError(f"Data expected, but got {value} of type {type(value)}")
self.artifacts = RecordOutputResponse(data=artifacts)
self.artifacts = DataOutputResponse(data=artifacts)
return self._built_object
async def _run(self, *args, **kwargs):
@ -299,9 +299,9 @@ class InterfaceVertex(ComponentVertex):
if self.vertex_type in CHAT_COMPONENTS:
message = self._process_chat_component()
elif self.vertex_type in RECORDS_COMPONENTS:
message = self._process_record_component()
message = self._process_data_component()
if isinstance(self._built_object, (AsyncIterator, Iterator)):
if self.params.get("return_record", False):
if self.params.get("return_data", False):
self._built_object = Data(text=message, data=self.artifacts)
else:
self._built_object = message

View file

@ -1,3 +1,3 @@
from .record import data_to_text, docs_to_data, messages_to_text
from .data import data_to_text, docs_to_data, messages_to_text
__all__ = ["docs_to_data", "data_to_text", "messages_to_text"]

View file

@ -8,23 +8,23 @@ from langflow.schema.message import Message
def docs_to_data(documents: list[Document]) -> list[Data]:
"""
Converts a list of Documents to a list of Records.
Converts a list of Documents to a list of Data.
Args:
documents (list[Document]): The list of Documents to convert.
Returns:
list[Data]: The converted list of Records.
list[Data]: The converted list of Data.
"""
return [Data.from_document(document) for document in documents]
def data_to_text(template: str, data: Union[Data, list[Data]]) -> str:
"""
Converts a list of Records to a list of texts.
Converts a list of Data to a list of texts.
Args:
data (list[Data]): The list of Records to convert.
data (list[Data]): The list of Data to convert.
Returns:
list[str]: The converted list of texts.

View file

@ -31,7 +31,7 @@ def list_flows(*, user_id: Optional[str] = None) -> List[Data]:
select(Flow).where(Flow.user_id == user_id).where(Flow.is_component == False) # noqa
).all()
flows_data = [flow.to_record() for flow in flows]
flows_data = [flow.to_data() for flow in flows]
return flows_data
except Exception as e:
raise ValueError(f"Error listing flows: {e}")
@ -170,22 +170,22 @@ async def flow_function({func_args}):
def build_function_and_schema(
flow_record: Data, graph: "Graph", user_id: str | UUID | None
flow_data: Data, graph: "Graph", user_id: str | UUID | None
) -> Tuple[Callable[..., Awaitable[Any]], Type[BaseModel]]:
"""
Builds a dynamic function and schema for a given flow.
Args:
flow_record (Data): The flow record containing information about the flow.
flow_data (Data): The flow record containing information about the flow.
graph (Graph): The graph representing the flow.
Returns:
Tuple[Callable, BaseModel]: A tuple containing the dynamic function and the schema.
"""
flow_id = flow_record.id
flow_id = flow_data.id
inputs = get_flow_inputs(graph)
dynamic_flow_function = generate_function_for_flow(inputs, flow_id, user_id=user_id)
schema = build_schema_from_inputs(flow_record.name, inputs)
schema = build_schema_from_inputs(flow_data.name, inputs)
return dynamic_flow_function, schema

View file

@ -618,7 +618,7 @@
"show": true,
"title_case": false,
"type": "code",
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"record_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
},
"input_value": {
"advanced": false,
@ -643,28 +643,6 @@
"type": "str",
"value": ""
},
"record_template": {
"advanced": true,
"display_name": "Data Template",
"dynamic": false,
"fileTypes": [],
"file_path": "",
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
"input_types": [
"Text"
],
"list": false,
"load_from_db": false,
"multiline": false,
"name": "record_template",
"password": false,
"placeholder": "",
"required": false,
"show": true,
"title_case": false,
"type": "str",
"value": ""
},
"sender": {
"advanced": true,
"display_name": "Sender Type",

View file

@ -520,7 +520,7 @@
"show": true,
"title_case": false,
"type": "code",
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"record_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
},
"input_value": {
"advanced": false,
@ -545,28 +545,6 @@
"type": "str",
"value": ""
},
"record_template": {
"advanced": true,
"display_name": "Data Template",
"dynamic": false,
"fileTypes": [],
"file_path": "",
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
"input_types": [
"Text"
],
"list": false,
"load_from_db": false,
"multiline": false,
"name": "record_template",
"password": false,
"placeholder": "",
"required": false,
"show": true,
"title_case": false,
"type": "str",
"value": ""
},
"sender": {
"advanced": true,
"display_name": "Sender Type",

View file

@ -652,7 +652,7 @@
"show": true,
"title_case": false,
"type": "code",
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"record_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
},
"input_value": {
"advanced": false,
@ -677,28 +677,6 @@
"type": "str",
"value": ""
},
"record_template": {
"advanced": true,
"display_name": "Data Template",
"dynamic": false,
"fileTypes": [],
"file_path": "",
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
"input_types": [
"Text"
],
"list": false,
"load_from_db": false,
"multiline": false,
"name": "record_template",
"password": false,
"placeholder": "",
"required": false,
"show": true,
"title_case": false,
"type": "str",
"value": ""
},
"sender": {
"advanced": true,
"display_name": "Sender Type",

View file

@ -396,7 +396,7 @@
"show": true,
"title_case": false,
"type": "code",
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"record_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
},
"input_value": {
"advanced": false,
@ -421,28 +421,6 @@
"type": "str",
"value": ""
},
"record_template": {
"advanced": true,
"display_name": "Data Template",
"dynamic": false,
"fileTypes": [],
"file_path": "",
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
"input_types": [
"Text"
],
"list": false,
"load_from_db": false,
"multiline": false,
"name": "record_template",
"password": false,
"placeholder": "",
"required": false,
"show": true,
"title_case": false,
"type": "str",
"value": ""
},
"sender": {
"advanced": true,
"display_name": "Sender Type",
@ -593,7 +571,7 @@
"show": true,
"title_case": false,
"type": "code",
"value": "from typing import Optional\n\nfrom langflow.base.memory.memory import BaseMemoryComponent\nfrom langflow.field_typing import Text\nfrom langflow.helpers.record import messages_to_text\nfrom langflow.memory import get_messages\nfrom langflow.schema.message import Message\n\n\nclass MemoryComponent(BaseMemoryComponent):\n display_name = \"Chat Memory\"\n description = \"Retrieves stored chat messages given a specific Session ID.\"\n beta: bool = True\n icon = \"history\"\n\n def build_config(self):\n return {\n \"sender\": {\n \"options\": [\"Machine\", \"User\", \"Machine and User\"],\n \"display_name\": \"Sender Type\",\n },\n \"sender_name\": {\"display_name\": \"Sender Name\", \"advanced\": True},\n \"n_messages\": {\n \"display_name\": \"Number of Messages\",\n \"info\": \"Number of messages to retrieve.\",\n },\n \"session_id\": {\n \"display_name\": \"Session ID\",\n \"info\": \"Session ID of the chat history.\",\n \"input_types\": [\"Text\"],\n },\n \"order\": {\n \"options\": [\"Ascending\", \"Descending\"],\n \"display_name\": \"Order\",\n \"info\": \"Order of the messages.\",\n \"advanced\": True,\n },\n \"record_template\": {\n \"display_name\": \"Data Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n \"advanced\": True,\n },\n }\n\n def get_messages(self, **kwargs) -> list[Message]:\n # Validate kwargs by checking if it contains the correct keys\n if \"sender\" not in kwargs:\n kwargs[\"sender\"] = None\n if \"sender_name\" not in kwargs:\n kwargs[\"sender_name\"] = None\n if \"session_id\" not in kwargs:\n kwargs[\"session_id\"] = None\n if \"limit\" not in kwargs:\n kwargs[\"limit\"] = 5\n if \"order\" not in kwargs:\n kwargs[\"order\"] = \"Descending\"\n\n kwargs[\"order\"] = \"DESC\" if kwargs[\"order\"] == \"Descending\" else \"ASC\"\n if kwargs[\"sender\"] == \"Machine and User\":\n kwargs[\"sender\"] = None\n return get_messages(**kwargs)\n\n def build(\n self,\n sender: Optional[str] = \"Machine and User\",\n sender_name: Optional[str] = None,\n session_id: Optional[str] = None,\n n_messages: int = 5,\n order: Optional[str] = \"Descending\",\n record_template: Optional[str] = \"{sender_name}: {text}\",\n ) -> Text:\n messages = self.get_messages(\n sender=sender,\n sender_name=sender_name,\n session_id=session_id,\n limit=n_messages,\n order=order,\n )\n messages_str = messages_to_text(template=record_template or \"\", messages=messages)\n self.status = messages_str\n return messages_str\n"
"value": "from typing import Optional\n\nfrom langflow.base.memory.memory import BaseMemoryComponent\nfrom langflow.field_typing import Text\nfrom langflow.helpers.data import messages_to_text\nfrom langflow.memory import get_messages\nfrom langflow.schema.message import Message\n\n\nclass MemoryComponent(BaseMemoryComponent):\n display_name = \"Chat Memory\"\n description = \"Retrieves stored chat messages given a specific Session ID.\"\n beta: bool = True\n icon = \"history\"\n\n def build_config(self):\n return {\n \"sender\": {\n \"options\": [\"Machine\", \"User\", \"Machine and User\"],\n \"display_name\": \"Sender Type\",\n },\n \"sender_name\": {\"display_name\": \"Sender Name\", \"advanced\": True},\n \"n_messages\": {\n \"display_name\": \"Number of Messages\",\n \"info\": \"Number of messages to retrieve.\",\n },\n \"session_id\": {\n \"display_name\": \"Session ID\",\n \"info\": \"Session ID of the chat history.\",\n \"input_types\": [\"Text\"],\n },\n \"order\": {\n \"options\": [\"Ascending\", \"Descending\"],\n \"display_name\": \"Order\",\n \"info\": \"Order of the messages.\",\n \"advanced\": True,\n },\n \"data_template\": {\n \"display_name\": \"Data Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n \"advanced\": True,\n },\n }\n\n def get_messages(self, **kwargs) -> list[Message]:\n # Validate kwargs by checking if it contains the correct keys\n if \"sender\" not in kwargs:\n kwargs[\"sender\"] = None\n if \"sender_name\" not in kwargs:\n kwargs[\"sender_name\"] = None\n if \"session_id\" not in kwargs:\n kwargs[\"session_id\"] = None\n if \"limit\" not in kwargs:\n kwargs[\"limit\"] = 5\n if \"order\" not in kwargs:\n kwargs[\"order\"] = \"Descending\"\n\n kwargs[\"order\"] = \"DESC\" if kwargs[\"order\"] == \"Descending\" else \"ASC\"\n if kwargs[\"sender\"] == \"Machine and User\":\n kwargs[\"sender\"] = None\n return get_messages(**kwargs)\n\n def build(\n self,\n sender: Optional[str] = \"Machine and User\",\n sender_name: Optional[str] = None,\n session_id: Optional[str] = None,\n n_messages: int = 5,\n order: Optional[str] = \"Descending\",\n data_template: Optional[str] = \"{sender_name}: {text}\",\n ) -> Text:\n messages = self.get_messages(\n sender=sender,\n sender_name=sender_name,\n session_id=session_id,\n limit=n_messages,\n order=order,\n )\n messages_str = messages_to_text(template=data_template or \"\", messages=messages)\n self.status = messages_str\n return messages_str\n"
},
"n_messages": {
"advanced": false,
@ -640,28 +618,6 @@
"type": "str",
"value": "Descending"
},
"record_template": {
"advanced": true,
"display_name": "Data Template",
"dynamic": false,
"fileTypes": [],
"file_path": "",
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
"input_types": [
"Text"
],
"list": false,
"load_from_db": false,
"multiline": true,
"name": "record_template",
"password": false,
"placeholder": "",
"required": false,
"show": true,
"title_case": false,
"type": "str",
"value": "{sender_name}: {text}"
},
"sender": {
"advanced": false,
"display_name": "Sender Type",

View file

@ -598,7 +598,7 @@
"show": true,
"title_case": false,
"type": "code",
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"record_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
},
"input_value": {
"advanced": false,
@ -623,28 +623,6 @@
"type": "str",
"value": ""
},
"record_template": {
"advanced": true,
"display_name": "Data Template",
"dynamic": false,
"fileTypes": [],
"file_path": "",
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
"input_types": [
"Text"
],
"list": false,
"load_from_db": false,
"multiline": false,
"name": "record_template",
"password": false,
"placeholder": "",
"required": false,
"show": true,
"title_case": false,
"type": "str",
"value": ""
},
"sender": {
"advanced": true,
"display_name": "Sender Type",
@ -799,7 +777,7 @@
"show": true,
"title_case": false,
"type": "code",
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"record_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
},
"input_value": {
"advanced": false,
@ -824,28 +802,6 @@
"type": "str",
"value": ""
},
"record_template": {
"advanced": true,
"display_name": "Data Template",
"dynamic": false,
"fileTypes": [],
"file_path": "",
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
"input_types": [
"Text"
],
"list": false,
"load_from_db": false,
"multiline": false,
"name": "record_template",
"password": false,
"placeholder": "",
"required": false,
"show": true,
"title_case": false,
"type": "str",
"value": ""
},
"sender": {
"advanced": true,
"display_name": "Sender Type",
@ -983,7 +939,7 @@
"show": true,
"title_case": false,
"type": "code",
"value": "from langflow.base.io.text import TextComponent\nfrom langflow.field_typing import Text\nfrom langflow.template import Input, Output\n\n\nclass TextInput(TextComponent):\n display_name = \"Text Input\"\n description = \"Get text inputs from the Playground.\"\n icon = \"type\"\n\n inputs = [\n Input(\n name=\"input_value\",\n type=str,\n display_name=\"Value\",\n info=\"Text or Data to be passed as input.\",\n input_types=[\"Data\", \"Text\"],\n ),\n Input(\n name=\"record_template\",\n type=str,\n display_name=\"Data Template\",\n multiline=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n advanced=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n ]\n\n def text_response(self) -> Text:\n return self.build(input_value=self.input_value, record_template=self.record_template)\n"
"value": "from langflow.base.io.text import TextComponent\nfrom langflow.field_typing import Text\nfrom langflow.template import Input, Output\n\n\nclass TextInput(TextComponent):\n display_name = \"Text Input\"\n description = \"Get text inputs from the Playground.\"\n icon = \"type\"\n\n inputs = [\n Input(\n name=\"input_value\",\n type=str,\n display_name=\"Value\",\n info=\"Text or Data to be passed as input.\",\n input_types=[\"Data\", \"Text\"],\n ),\n Input(\n name=\"data_template\",\n type=str,\n display_name=\"Data Template\",\n multiline=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n advanced=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n ]\n\n def text_response(self) -> Text:\n return self.build(input_value=self.input_value, data_template=self.data_template)\n"
},
"input_value": {
"advanced": false,
@ -1007,28 +963,6 @@
"title_case": false,
"type": "str",
"value": ""
},
"record_template": {
"advanced": true,
"display_name": "Data Template",
"dynamic": false,
"fileTypes": [],
"file_path": "",
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
"input_types": [
"Text"
],
"list": false,
"load_from_db": false,
"multiline": true,
"name": "record_template",
"password": false,
"placeholder": "",
"required": false,
"show": true,
"title_case": false,
"type": "str",
"value": ""
}
}
},

View file

@ -1652,7 +1652,7 @@
"show": true,
"title_case": false,
"type": "code",
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"record_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.inputs import BoolInput, DropdownInput, StrInput\nfrom langflow.schema.message import Message\nfrom langflow.template import Output\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n\n inputs = [\n StrInput(\n name=\"input_value\",\n display_name=\"Text\",\n multiline=True,\n info=\"Message to be passed as output.\",\n input_types=[\"Text\", \"Message\"],\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[\"Machine\", \"User\"],\n value=\"Machine\",\n advanced=True,\n info=\"Type of sender.\",\n ),\n StrInput(name=\"sender_name\", display_name=\"Sender Name\", info=\"Name of the sender.\", value=\"AI\", advanced=True),\n StrInput(name=\"session_id\", display_name=\"Session ID\", info=\"Session ID for the message.\", advanced=True),\n BoolInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Text\", name=\"text\", method=\"text_response\"),\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def text_response(self) -> Text:\n result = self.input_value\n if self.session_id:\n self.message_response()\n self.status = result\n return result\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if self.session_id and isinstance(message, Message) and isinstance(message.text, str):\n self.store_message(message)\n self.message.value = message\n\n self.status = message\n return message\n"
},
"input_value": {
"advanced": false,
@ -1677,28 +1677,6 @@
"type": "str",
"value": ""
},
"record_template": {
"advanced": true,
"display_name": "Data Template",
"dynamic": false,
"fileTypes": [],
"file_path": "",
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
"input_types": [
"Text"
],
"list": false,
"load_from_db": false,
"multiline": false,
"name": "record_template",
"password": false,
"placeholder": "",
"required": false,
"show": true,
"title_case": false,
"type": "str",
"value": ""
},
"sender": {
"advanced": true,
"display_name": "Sender Type",
@ -1841,7 +1819,7 @@
"show": true,
"title_case": false,
"type": "code",
"value": "from pathlib import Path\nfrom typing import Any, Dict\n\nfrom langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_record\nfrom langflow.custom import CustomComponent\nfrom langflow.schema import Data\n\n\nclass FileComponent(CustomComponent):\n display_name = \"File\"\n description = \"A generic file loader.\"\n icon = \"file-text\"\n\n def build_config(self) -> Dict[str, Any]:\n return {\n \"path\": {\n \"display_name\": \"Path\",\n \"field_type\": \"file\",\n \"file_types\": TEXT_FILE_TYPES,\n \"info\": f\"Supported file types: {', '.join(TEXT_FILE_TYPES)}\",\n },\n \"silent_errors\": {\n \"display_name\": \"Silent Errors\",\n \"advanced\": True,\n \"info\": \"If true, errors will not raise an exception.\",\n },\n }\n\n def load_file(self, path: str, silent_errors: bool = False) -> Data:\n resolved_path = self.resolve_path(path)\n path_obj = Path(resolved_path)\n extension = path_obj.suffix[1:].lower()\n if extension == \"doc\":\n raise ValueError(\"doc files are not supported. Please save as .docx\")\n if extension not in TEXT_FILE_TYPES:\n raise ValueError(f\"Unsupported file type: {extension}\")\n record = parse_text_file_to_record(resolved_path, silent_errors)\n self.status = record if record else \"No data\"\n return record or Data()\n\n def build(\n self,\n path: str,\n silent_errors: bool = False,\n ) -> Data:\n record = self.load_file(path, silent_errors)\n self.status = record\n return record\n"
"value": "from pathlib import Path\nfrom typing import Any, Dict\n\nfrom langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_data\nfrom langflow.custom import CustomComponent\nfrom langflow.schema import Data\n\n\nclass FileComponent(CustomComponent):\n display_name = \"File\"\n description = \"A generic file loader.\"\n icon = \"file-text\"\n\n def build_config(self) -> Dict[str, Any]:\n return {\n \"path\": {\n \"display_name\": \"Path\",\n \"field_type\": \"file\",\n \"file_types\": TEXT_FILE_TYPES,\n \"info\": f\"Supported file types: {', '.join(TEXT_FILE_TYPES)}\",\n },\n \"silent_errors\": {\n \"display_name\": \"Silent Errors\",\n \"advanced\": True,\n \"info\": \"If true, errors will not raise an exception.\",\n },\n }\n\n def load_file(self, path: str, silent_errors: bool = False) -> Data:\n resolved_path = self.resolve_path(path)\n path_obj = Path(resolved_path)\n extension = path_obj.suffix[1:].lower()\n if extension == \"doc\":\n raise ValueError(\"doc files are not supported. Please save as .docx\")\n if extension not in TEXT_FILE_TYPES:\n raise ValueError(f\"Unsupported file type: {extension}\")\n record = parse_text_file_to_data(resolved_path, silent_errors)\n self.status = record if record else \"No data\"\n return record or Data()\n\n def build(\n self,\n path: str,\n silent_errors: bool = False,\n ) -> Data:\n record = self.load_file(path, silent_errors)\n self.status = record\n return record\n"
},
"path": {
"advanced": false,

View file

@ -7,7 +7,7 @@ from langflow.schema.message import Message
class ArtifactType(str, Enum):
TEXT = "text"
RECORD = "record"
DATA = "data"
OBJECT = "object"
ARRAY = "array"
STREAM = "stream"
@ -19,7 +19,7 @@ def get_artifact_type(value, build_result=None) -> str:
result = ArtifactType.UNKNOWN
match value:
case Data():
result = ArtifactType.RECORD
result = ArtifactType.DATA
case str():
result = ArtifactType.TEXT

View file

@ -6,8 +6,8 @@ from langchain_core.prompt_values import ImagePromptValue
from langchain_core.prompts.image import ImagePromptTemplate
from pydantic import BaseModel, BeforeValidator, ConfigDict, Field, field_serializer
from langflow.schema.image import Image, get_file_paths, is_image_file
from langflow.schema.data import Data
from langflow.schema.image import Image, get_file_paths, is_image_file
def _timestamp_to_str(timestamp: datetime) -> str:
@ -68,7 +68,7 @@ class Message(BaseModel):
return AIMessage(content=self.text)
@classmethod
def from_record(cls, record: Data) -> "Message":
def from_data(cls, record: Data) -> "Message":
"""
Converts a BaseMessage to a Data.

View file

@ -142,7 +142,7 @@ class Flow(FlowBase, table=True):
folder_id: Optional[UUID] = Field(default=None, foreign_key="folder.id", nullable=True, index=True)
folder: Optional["Folder"] = Relationship(back_populates="flows")
def to_record(self):
def to_data(self):
serialized = self.model_dump()
data = {
"id": serialized.pop("id"),

View file

@ -97,7 +97,7 @@ class ChatOutputResponse(BaseModel):
return self
class RecordOutputResponse(BaseModel):
class DataOutputResponse(BaseModel):
"""Data output response schema."""
data: List[Optional[Dict]]

View file

@ -415,7 +415,7 @@ def build_loader_repr_from_data(data: List[Data]) -> str:
avg_length = sum(len(doc.text) for doc in data) / len(data)
return f"""{len(data)} data
\nAvg. Data Length (characters): {int(avg_length)}
Records: {data[:3]}..."""
Data: {data[:3]}..."""
return "0 data"

View file

@ -1,4 +1,4 @@
import RecordsOutputComponent from "../../../../../../components/dataOutputComponent";
import DataOutputComponent from "../../../../../../components/dataOutputComponent";
import ForwardedIconComponent from "../../../../../../components/genericIconComponent";
import {
Alert,
@ -29,7 +29,7 @@ const SwitchOutputView: React.FC<SwitchOutputViewProps> = ({
const results = flowPoolNode?.data?.logs[outputName] ?? "";
const resultType = results?.type;
let resultMessage = results?.message;
const RECORD_TYPES = ["record", "object", "array", "message"];
const RECORD_TYPES = ["data", "object", "array", "message"];
if (resultMessage?.raw) {
resultMessage = resultMessage.raw;
}
@ -47,7 +47,7 @@ const SwitchOutputView: React.FC<SwitchOutputViewProps> = ({
</Case>
<Case condition={RECORD_TYPES.includes(resultType)}>
<RecordsOutputComponent
<DataOutputComponent
rows={
Array.isArray(resultMessage)
? (resultMessage as Array<any>).every((item) => item.data)

View file

@ -4,7 +4,7 @@ import "ag-grid-community/styles/ag-theme-balham.css"; // Optional Theme applied
import { extractColumnsFromRows } from "../../utils/utils";
import TableComponent from "../tableComponent";
function RecordsOutputComponent({
function DataOutputComponent({
pagination,
rows,
columnMode = "union",
@ -35,4 +35,4 @@ function RecordsOutputComponent({
);
}
export default RecordsOutputComponent;
export default DataOutputComponent;

View file

@ -654,7 +654,7 @@ export const OUTPUT_TYPES = new Set([
"JsonOutput",
"KeyPairOutput",
"StringListOutput",
"RecordsOutput",
"DataOutput",
"TableOutput",
]);

View file

@ -2,7 +2,7 @@ import { cloneDeep } from "lodash";
import { useState } from "react";
import ImageViewer from "../../../../components/ImageViewer";
import CsvOutputComponent from "../../../../components/csvOutputComponent";
import RecordsOutputComponent from "../../../../components/dataOutputComponent";
import DataOutputComponent from "../../../../components/dataOutputComponent";
import InputListComponent from "../../../../components/inputListComponent";
import PdfViewer from "../../../../components/pdfViewer";
import { Textarea } from "../../../../components/ui/textarea";
@ -245,10 +245,10 @@ export default function IOFieldView({
/>
</>
);
case "RecordsOutput":
case "DataOutput":
return (
<div className={left ? "h-56" : "h-full"}>
<RecordsOutputComponent
<DataOutputComponent
pagination={!left}
rows={
Array.isArray(flowPoolNode?.data?.artifacts)

View file

@ -272,7 +272,7 @@ export const nodeColors: { [char: string]: string } = {
retrievers: "#e6b25a",
unknown: "#9CA3AF",
custom_components: "#ab11ab",
Records: "#31a3cc",
Data: "#31a3cc",
Data: "#31a3cc",
Message: "#4367BF",
};

View file

@ -1,30 +1,31 @@
from langchain_core.documents import Document
from langflow.components import helpers
from langflow.custom.utils import build_custom_component_template
from langflow.schema import Data
def test_update_record_component():
def test_update_data_component():
# Arrange
update_record_component = helpers.UpdateRecordComponent()
update_data_component = helpers.UpdateDataComponent()
# Act
new_data = {"new_key": "new_value"}
existing_record = Data(data={"existing_key": "existing_value"})
result = update_record_component.build(existing_record, new_data)
existing_data = Data(data={"existing_key": "existing_value"})
result = update_data_component.build(existing_data, new_data)
assert result.data == {"existing_key": "existing_value", "new_key": "new_value"}
assert result.existing_key == "existing_value"
assert result.new_key == "new_value"
def test_document_to_record_component():
def test_document_to_data_component():
# Arrange
document_to_record_component = helpers.DocumentToRecordComponent()
document_to_data_component = helpers.DocumentToDataComponent()
# Act
# Replace with your actual test data
document = Document(page_content="key: value", metadata={"url": "https://example.com"})
result = document_to_record_component.build(document)
result = document_to_data_component.build(document)
# Assert
# Replace with your actual expected result
@ -53,7 +54,7 @@ def test_uuid_generator_component():
def test_data_as_text_component():
# Arrange
data_as_text_component = helpers.RecordsToTextComponent()
data_as_text_component = helpers.DataToTextComponent()
# Act
# Replace with your actual test data
@ -66,14 +67,14 @@ def test_data_as_text_component():
assert result == "Data:{'key': 'value', 'bacon': 'eggs'} -- Bacon:eggs"
def test_text_to_record_component():
def test_text_to_data_component():
# Arrange
text_to_record_component = helpers.CreateRecordComponent()
text_to_data_component = helpers.CreateDataComponent()
# Act
# Replace with your actual test data
dict_with_text = {"field_1": {"key": "value"}}
result = text_to_record_component.build(number_of_fields=1, **dict_with_text)
result = text_to_data_component.build(number_of_fields=1, **dict_with_text)
# Assert
# Replace with your actual expected result

View file

@ -1,8 +1,9 @@
from langchain_core.documents import Document
from langflow.schema import Data
def test_record_initialization():
def test_data_initialization():
record = Data(text_key="msg", data={"msg": "Hello, World!", "extra": "value"})
assert record.msg == "Hello, World!"
assert record.extra == "value"