Merge branch 'two_edges' of personal:langflow-ai/langflow into two_edges
This commit is contained in:
commit
643772c216
61 changed files with 283 additions and 441 deletions
|
|
@ -44,9 +44,13 @@ Adding or removing any of the below components modifies your Playground so you c
|
||||||
- Text Input
|
- Text Input
|
||||||
- Chat Output
|
- Chat Output
|
||||||
- Text Output
|
- Text Output
|
||||||
- Records Output
|
- Data Output
|
||||||
- Inspect Memory
|
- Inspect Memory
|
||||||
|
|
||||||
You can also select **Options** > **Logs** to see your flow's logs.
|
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";
|
||||||
|
|
|
||||||
|
|
@ -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**
|
**Parameters**
|
||||||
|
|
||||||
- **Records:**
|
- **Data:**
|
||||||
- **Display Name:** Records
|
- **Display Name:** Data
|
||||||
|
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
Provide the records you want to merge.
|
Provide the Data you want to merge.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
#### 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
|
#### Parameters
|
||||||
|
|
||||||
- **Records:** The records to convert to text.
|
- **Data:** The Data 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.
|
- **Template:** The template used for formatting the Data. It can contain keys like `{text}`, `{data}`, or any other key in the record.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
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
|
```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.
|
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.
|
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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ import Admonition from "@theme/Admonition";
|
||||||
|
|
||||||
### Astra DB
|
### 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:**
|
**Parameters:**
|
||||||
|
|
||||||
- **Input:** Documents or records for input.
|
- **Input:** Documents or Data for input.
|
||||||
- **Embedding:** Embedding model Astra DB uses.
|
- **Embedding:** Embedding model Astra DB uses.
|
||||||
- **Collection Name:** Name of the Astra DB collection.
|
- **Collection Name:** Name of the Astra DB collection.
|
||||||
- **Token:** Authentication token for Astra DB.
|
- **Token:** Authentication token for Astra DB.
|
||||||
|
|
@ -99,12 +99,12 @@ For detailed documentation and integration guides, please refer to the [Chroma C
|
||||||
|
|
||||||
### Couchbase
|
### 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:**
|
**Parameters:**
|
||||||
|
|
||||||
- **Embedding:** Model used by Couchbase.
|
- **Embedding:** Model used by Couchbase.
|
||||||
- **Input:** Documents or records.
|
- **Input:** Documents or Data.
|
||||||
- **Couchbase Cluster Connection String:** Cluster Connection string.
|
- **Couchbase Cluster Connection String:** Cluster Connection string.
|
||||||
- **Couchbase Cluster Username:** Cluster Username.
|
- **Couchbase Cluster Username:** Cluster Username.
|
||||||
- **Couchbase Cluster Password:** Cluster Password.
|
- **Couchbase Cluster Password:** Cluster Password.
|
||||||
|
|
@ -165,12 +165,12 @@ For more details, see the [FAISS Component Documentation](https://faiss.ai/index
|
||||||
|
|
||||||
### MongoDB Atlas
|
### 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:**
|
**Parameters:**
|
||||||
|
|
||||||
- **Embedding:** Model used by MongoDB Atlas.
|
- **Embedding:** Model used by MongoDB Atlas.
|
||||||
- **Input:** Documents or records.
|
- **Input:** Documents or Data.
|
||||||
- **Collection Name:** Collection identifier in MongoDB Atlas.
|
- **Collection Name:** Collection identifier in MongoDB Atlas.
|
||||||
- **Database Name:** Database identifier.
|
- **Database Name:** Database identifier.
|
||||||
- **Index Name:** Index identifier.
|
- **Index Name:** Index identifier.
|
||||||
|
|
@ -235,11 +235,11 @@ For more details, see the [PGVector Component Documentation](https://python.lang
|
||||||
|
|
||||||
### Pinecone
|
### 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:**
|
**Parameters:**
|
||||||
|
|
||||||
- **Input:** Documents or records.
|
- **Input:** Documents or Data.
|
||||||
- **Embedding:** Model used.
|
- **Embedding:** Model used.
|
||||||
- **Index Name:** Index identifier.
|
- **Index Name:** Index identifier.
|
||||||
- **Namespace:** Namespace used.
|
- **Namespace:** Namespace used.
|
||||||
|
|
@ -278,7 +278,7 @@ For more details, see the [PGVector Component Documentation](https://python.lang
|
||||||
|
|
||||||
**Parameters:**
|
**Parameters:**
|
||||||
|
|
||||||
- **Input:** Documents or records.
|
- **Input:** Documents or Data.
|
||||||
- **Embedding:** Model used.
|
- **Embedding:** Model used.
|
||||||
- **API Key:** Qdrant API key.
|
- **API Key:** Qdrant API key.
|
||||||
- **Collection Name:** Collection identifier.
|
- **Collection Name:** Collection identifier.
|
||||||
|
|
@ -345,7 +345,7 @@ For detailed documentation, refer to the [Redis Documentation](https://python.la
|
||||||
|
|
||||||
**Parameters:**
|
**Parameters:**
|
||||||
|
|
||||||
- **Input:** Documents or records.
|
- **Input:** Documents or data.
|
||||||
- **Embedding:** Model used.
|
- **Embedding:** Model used.
|
||||||
- **Query Name:** Optional query name.
|
- **Query Name:** Optional query name.
|
||||||
- **Search Kwargs:** Advanced search parameters.
|
- **Search Kwargs:** Advanced search parameters.
|
||||||
|
|
|
||||||
|
|
@ -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.
|
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
|
<div
|
||||||
style={{ marginBottom: "20px", display: "flex", justifyContent: "center" }}
|
style={{ marginBottom: "20px", display: "flex", justifyContent: "center" }}
|
||||||
>
|
>
|
||||||
<ReactPlayer playing controls url="/videos/create_record.mp4" />
|
<ReactPlayer playing controls url="/videos/create_record.mp4" />
|
||||||
</div>
|
</div>
|
||||||
import ThemedImage from "@theme/ThemedImage"; import useBaseUrl from
|
import ThemedImage from "@theme/ThemedImage"; import useBaseUrl from "@docusaurus/useBaseUrl";
|
||||||
"@docusaurus/useBaseUrl"; import ZoomableImage from
|
import ZoomableImage from "/src/theme/ZoomableImage.js"; import ReactPlayer from
|
||||||
"/src/theme/ZoomableImage.js"; import ReactPlayer from "react-player"; import
|
"react-player"; import Admonition from "@theme/Admonition";
|
||||||
Admonition from "@theme/Admonition";
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
- **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
|
- **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
|
- **Astra DB Search** component that retrieves the most relevant Data from the Astra DB database
|
||||||
- **Text Output** component that turns the Records into Text by concatenating them and also displays it in the Playground
|
- **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
|
- 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
|
- **OpenAI** component that generates a response to the prompt
|
||||||
- **Chat Output** component that displays the response in the Playground
|
- **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" }}
|
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
|
<ZoomableImage
|
||||||
alt="Docusaurus themed image"
|
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
|
# Conclusion
|
||||||
|
|
||||||
In this guide, we have learned how to run a RAG application using Astra DB and Langflow.
|
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";
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ class NotionListPages(CustomComponent):
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
results = response.json()
|
results = response.json()
|
||||||
records = []
|
data = []
|
||||||
combined_text = f"Pages found: {len(results['results'])}\n\n"
|
combined_text = f"Pages found: {len(results['results'])}\n\n"
|
||||||
for page in results['results']:
|
for page in results['results']:
|
||||||
page_data = {
|
page_data = {
|
||||||
|
|
@ -127,10 +127,10 @@ class NotionListPages(CustomComponent):
|
||||||
)
|
)
|
||||||
|
|
||||||
combined_text += text
|
combined_text += text
|
||||||
records.append(Data(text=text, data=page_data))
|
data.append(Data(text=text, data=page_data))
|
||||||
|
|
||||||
self.status = combined_text.strip()
|
self.status = combined_text.strip()
|
||||||
return records
|
return data
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.status = f"An error occurred: {str(e)}"
|
self.status = f"An error occurred: {str(e)}"
|
||||||
|
|
|
||||||
|
|
@ -65,14 +65,14 @@ class NotionUserList(CustomComponent):
|
||||||
data = response.json()
|
data = response.json()
|
||||||
results = data['results']
|
results = data['results']
|
||||||
|
|
||||||
records = []
|
data = []
|
||||||
for user in results:
|
for user in results:
|
||||||
id = user['id']
|
id = user['id']
|
||||||
type = user['type']
|
type = user['type']
|
||||||
name = user.get('name', '')
|
name = user.get('name', '')
|
||||||
avatar_url = user.get('avatar_url', '')
|
avatar_url = user.get('avatar_url', '')
|
||||||
|
|
||||||
record_data = {
|
data_dict = {
|
||||||
"id": id,
|
"id": id,
|
||||||
"type": type,
|
"type": type,
|
||||||
"name": name,
|
"name": name,
|
||||||
|
|
@ -80,15 +80,15 @@ class NotionUserList(CustomComponent):
|
||||||
}
|
}
|
||||||
|
|
||||||
output = "User:\n"
|
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 += f"{key.replace('_', ' ').title()}: {value}\n"
|
||||||
output += "________________________\n"
|
output += "________________________\n"
|
||||||
|
|
||||||
record = Data(text=output, data=record_data)
|
record = Data(text=output, data=data_dict)
|
||||||
records.append(record)
|
data.append(record)
|
||||||
|
|
||||||
self.status = "\n".join(record.text for record in records)
|
self.status = "\n".join(record.text for record in data)
|
||||||
return records
|
return data
|
||||||
```
|
```
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ class NotionSearch(CustomComponent):
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
results = response.json()
|
results = response.json()
|
||||||
records = []
|
data = []
|
||||||
combined_text = f"Results found: {len(results['results'])}\n\n"
|
combined_text = f"Results found: {len(results['results'])}\n\n"
|
||||||
for result in results['results']:
|
for result in results['results']:
|
||||||
result_data = {
|
result_data = {
|
||||||
|
|
@ -135,10 +135,10 @@ class NotionSearch(CustomComponent):
|
||||||
|
|
||||||
text += f"type: {result['object']}\nlast_edited_time: {result['last_edited_time']}\n\n"
|
text += f"type: {result['object']}\nlast_edited_time: {result['last_edited_time']}\n\n"
|
||||||
combined_text += text
|
combined_text += text
|
||||||
records.append(Data(text=text, data=result_data))
|
data.append(Data(text=text, data=result_data))
|
||||||
|
|
||||||
self.status = combined_text
|
self.status = combined_text
|
||||||
return records
|
return data
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.status = f"An error occurred: {str(e)}"
|
self.status = f"An error occurred: {str(e)}"
|
||||||
|
|
|
||||||
|
|
@ -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.
|
- **Chat Input** component defines where to put the user input coming from the Playground.
|
||||||
- **OpenAI Embeddings** component generates embeddings from the user input.
|
- **OpenAI Embeddings** component generates embeddings from the user input.
|
||||||
- **Astra DB Search** component retrieves the most relevant Records from the Astra DB database.
|
- **Astra DB Search** component retrieves the most relevant Data from the Astra DB database.
|
||||||
- **Text Output** component turns the Records into Text by concatenating them and also displays it in the Playground.
|
- **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 Records as text and builds a prompt for the OpenAI model.
|
- **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.
|
- **OpenAI** component generates a response to the prompt.
|
||||||
- **Chat Output** component displays the response in the Playground.
|
- **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.
|
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";
|
||||||
|
|
|
||||||
|
|
@ -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
|
- **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
|
- **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
|
- **Astra DB Search** component that retrieves the most relevant Data from the Astra DB database
|
||||||
- **Text Output** component that turns the Records into Text by concatenating them and also displays it in the Playground
|
- **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
|
- 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
|
- **OpenAI** component that generates a response to the prompt
|
||||||
- **Chat Output** component that displays the response in the Playground
|
- **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" }}
|
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
|
<ZoomableImage
|
||||||
alt="Docusaurus themed image"
|
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
|
# Conclusion
|
||||||
|
|
||||||
In this guide, we have learned how to run a RAG application using Astra DB and Langflow.
|
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";
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ def retrieve_file_paths(
|
||||||
|
|
||||||
# ! Removing unstructured dependency until
|
# ! Removing unstructured dependency until
|
||||||
# ! 3.12 is supported
|
# ! 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
|
# # Use the partition function to load the file
|
||||||
# from unstructured.partition.auto import partition # type: ignore
|
# 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])
|
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:
|
try:
|
||||||
if file_path.endswith(".pdf"):
|
if file_path.endswith(".pdf"):
|
||||||
text = parse_pdf_to_text(file_path)
|
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:
|
# if use_multithreading:
|
||||||
# data = parallel_load_data(file_paths, silent_errors, max_concurrency)
|
# data = parallel_load_data(file_paths, silent_errors, max_concurrency)
|
||||||
# else:
|
# 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))
|
# data = list(filter(None, data))
|
||||||
# return data
|
# return data
|
||||||
|
|
||||||
|
|
@ -180,7 +180,7 @@ def parallel_load_data(
|
||||||
file_paths: List[str],
|
file_paths: List[str],
|
||||||
silent_errors: bool,
|
silent_errors: bool,
|
||||||
max_concurrency: int,
|
max_concurrency: int,
|
||||||
load_function: Callable = parse_text_file_to_record,
|
load_function: Callable = parse_text_file_to_data,
|
||||||
) -> List[Optional[Data]]:
|
) -> List[Optional[Data]]:
|
||||||
with futures.ThreadPoolExecutor(max_workers=max_concurrency) as executor:
|
with futures.ThreadPoolExecutor(max_workers=max_concurrency) as executor:
|
||||||
loaded_files = executor.map(
|
loaded_files = executor.map(
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class ChatComponent(Component):
|
||||||
"info": "Return the message as a Message containing the sender, sender_name, and session_id.",
|
"info": "Return the message as a Message containing the sender, sender_name, and session_id.",
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
},
|
},
|
||||||
"record_template": {
|
"data_template": {
|
||||||
"display_name": "Data Template",
|
"display_name": "Data Template",
|
||||||
"multiline": True,
|
"multiline": True,
|
||||||
"info": "In case of Message being a Data, this template will be used to convert it to text.",
|
"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
|
self.status = messages
|
||||||
return messages
|
return messages
|
||||||
|
|
||||||
def build_with_record(
|
def build_with_data(
|
||||||
self,
|
self,
|
||||||
sender: Optional[str] = "User",
|
sender: Optional[str] = "User",
|
||||||
sender_name: Optional[str] = "User",
|
sender_name: Optional[str] = "User",
|
||||||
|
|
@ -74,7 +74,7 @@ class ChatComponent(Component):
|
||||||
|
|
||||||
if isinstance(input_value, Data):
|
if isinstance(input_value, Data):
|
||||||
# Update the data of the record
|
# Update the data of the record
|
||||||
message = Message.from_record(input_value)
|
message = Message.from_data(input_value)
|
||||||
else:
|
else:
|
||||||
message = Message(
|
message = Message(
|
||||||
text=input_value, sender=sender, sender_name=sender_name, files=files, session_id=session_id
|
text=input_value, sender=sender, sender_name=sender_name, files=files, session_id=session_id
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from typing import Optional
|
||||||
|
|
||||||
from langflow.custom import Component
|
from langflow.custom import Component
|
||||||
from langflow.field_typing import Text
|
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
|
from langflow.schema import Data
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -17,7 +17,7 @@ class TextComponent(Component):
|
||||||
"input_types": ["Text", "Data"],
|
"input_types": ["Text", "Data"],
|
||||||
"info": "Text or Data to be passed.",
|
"info": "Text or Data to be passed.",
|
||||||
},
|
},
|
||||||
"record_template": {
|
"data_template": {
|
||||||
"display_name": "Data Template",
|
"display_name": "Data Template",
|
||||||
"multiline": True,
|
"multiline": True,
|
||||||
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
|
"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(
|
def build(
|
||||||
self,
|
self,
|
||||||
input_value: Optional[Text] = "",
|
input_value: Optional[Text] = "",
|
||||||
record_template: Optional[str] = "{text}",
|
data_template: Optional[str] = "{text}",
|
||||||
) -> Text:
|
) -> Text:
|
||||||
if isinstance(input_value, Data):
|
if isinstance(input_value, Data):
|
||||||
if record_template == "":
|
if data_template == "":
|
||||||
# it should be dynamically set to the Data's .text_key value
|
# it should be dynamically set to the Data's .text_key value
|
||||||
# meaning, if text_key = "bacon", then record_template = "{bacon}"
|
# meaning, if text_key = "bacon", then data_template = "{bacon}"
|
||||||
record_template = "{" + input_value.text_key + "}"
|
data_template = "{" + input_value.text_key + "}"
|
||||||
input_value = data_to_text(template=record_template, data=input_value)
|
input_value = data_to_text(template=data_template, data=input_value)
|
||||||
self.status = input_value
|
self.status = input_value
|
||||||
if not input_value:
|
if not input_value:
|
||||||
input_value = ""
|
input_value = ""
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class BaseMemoryComponent(CustomComponent):
|
||||||
"info": "Order of the messages.",
|
"info": "Order of the messages.",
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
},
|
},
|
||||||
"record_template": {
|
"data_template": {
|
||||||
"display_name": "Data Template",
|
"display_name": "Data Template",
|
||||||
"multiline": True,
|
"multiline": True,
|
||||||
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
|
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ from langflow.schema import Data
|
||||||
from langflow.schema.message import Message
|
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.
|
Convert a record to a string.
|
||||||
|
|
||||||
|
|
@ -38,13 +38,13 @@ def dict_values_to_string(d: dict) -> dict:
|
||||||
if isinstance(item, Message):
|
if isinstance(item, Message):
|
||||||
d_copy[key][i] = item.text
|
d_copy[key][i] = item.text
|
||||||
elif isinstance(item, Data):
|
elif isinstance(item, Data):
|
||||||
d_copy[key][i] = record_to_string(item)
|
d_copy[key][i] = data_to_string(item)
|
||||||
elif isinstance(item, Document):
|
elif isinstance(item, Document):
|
||||||
d_copy[key][i] = document_to_string(item)
|
d_copy[key][i] = document_to_string(item)
|
||||||
elif isinstance(value, Message):
|
elif isinstance(value, Message):
|
||||||
d_copy[key] = value.text
|
d_copy[key] = value.text
|
||||||
elif isinstance(value, Data):
|
elif isinstance(value, Data):
|
||||||
d_copy[key] = record_to_string(value)
|
d_copy[key] = data_to_string(value)
|
||||||
elif isinstance(value, Document):
|
elif isinstance(value, Document):
|
||||||
d_copy[key] = document_to_string(value)
|
d_copy[key] = document_to_string(value)
|
||||||
return d_copy
|
return d_copy
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,12 @@ def chroma_collection_to_data(collection_dict: dict):
|
||||||
"""
|
"""
|
||||||
data = []
|
data = []
|
||||||
for i, doc in enumerate(collection_dict["documents"]):
|
for i, doc in enumerate(collection_dict["documents"]):
|
||||||
record_dict = {
|
data_dict = {
|
||||||
"id": collection_dict["ids"][i],
|
"id": collection_dict["ids"][i],
|
||||||
"text": doc,
|
"text": doc,
|
||||||
}
|
}
|
||||||
if "metadatas" in collection_dict:
|
if "metadatas" in collection_dict:
|
||||||
for key, value in collection_dict["metadatas"][i].items():
|
for key, value in collection_dict["metadatas"][i].items():
|
||||||
record_dict[key] = value
|
data_dict[key] = value
|
||||||
data.append(Data(**record_dict))
|
data.append(Data(**data_dict))
|
||||||
return data
|
return data
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from typing import Any, Dict, List, Optional
|
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.custom import CustomComponent
|
||||||
from langflow.schema import Data
|
from langflow.schema import Data
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ class DirectoryComponent(CustomComponent):
|
||||||
if use_multithreading:
|
if use_multithreading:
|
||||||
loaded_data = parallel_load_data(file_paths, silent_errors, max_concurrency)
|
loaded_data = parallel_load_data(file_paths, silent_errors, max_concurrency)
|
||||||
else:
|
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))
|
loaded_data = list(filter(None, loaded_data))
|
||||||
self.status = loaded_data
|
self.status = loaded_data
|
||||||
return loaded_data
|
return loaded_data
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict
|
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.custom import CustomComponent
|
||||||
from langflow.schema import Data
|
from langflow.schema import Data
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ class FileComponent(CustomComponent):
|
||||||
raise ValueError("doc files are not supported. Please save as .docx")
|
raise ValueError("doc files are not supported. Please save as .docx")
|
||||||
if extension not in TEXT_FILE_TYPES:
|
if extension not in TEXT_FILE_TYPES:
|
||||||
raise ValueError(f"Unsupported file type: {extension}")
|
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"
|
self.status = record if record else "No data"
|
||||||
return record or Data()
|
return record or Data()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,16 @@ from langflow.custom import CustomComponent
|
||||||
from langflow.schema import Data
|
from langflow.schema import Data
|
||||||
|
|
||||||
|
|
||||||
class ExtractKeyFromRecordComponent(CustomComponent):
|
class ExtractKeyFromdataComponent(CustomComponent):
|
||||||
display_name = "Extract Key From Data"
|
display_name = "Extract Key From Data"
|
||||||
description = "Extracts a key from a record."
|
description = "Extracts a key from a data."
|
||||||
beta: bool = True
|
beta: bool = True
|
||||||
|
|
||||||
field_config = {
|
field_config = {
|
||||||
"record": {"display_name": "Data"},
|
"data": {"display_name": "Data"},
|
||||||
"keys": {
|
"keys": {
|
||||||
"display_name": "Keys",
|
"display_name": "Keys",
|
||||||
"info": "The keys to extract from the record.",
|
"info": "The keys to extract from the data.",
|
||||||
"input_types": [],
|
"input_types": [],
|
||||||
},
|
},
|
||||||
"silent_error": {
|
"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:
|
Args:
|
||||||
record (Data): The record from which to extract the keys.
|
data (Data): The data from which to extract the keys.
|
||||||
keys (list[str]): The keys to extract from the record.
|
keys (list[str]): The keys to extract from the data.
|
||||||
silent_error (bool): If True, errors will not be raised.
|
silent_error (bool): If True, errors will not be raised.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
@ -36,10 +36,10 @@ class ExtractKeyFromRecordComponent(CustomComponent):
|
||||||
extracted_keys = {}
|
extracted_keys = {}
|
||||||
for key in keys:
|
for key in keys:
|
||||||
try:
|
try:
|
||||||
extracted_keys[key] = getattr(record, key)
|
extracted_keys[key] = getattr(data, key)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
if not silent_error:
|
if not silent_error:
|
||||||
raise KeyError(f"The key '{key}' does not exist in the record.")
|
raise KeyError(f"The key '{key}' does not exist in the data.")
|
||||||
return_record = Data(data=extracted_keys)
|
return_data = Data(data=extracted_keys)
|
||||||
self.status = return_record
|
self.status = return_data
|
||||||
return return_record
|
return return_data
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ class FlowToolComponent(CustomComponent):
|
||||||
|
|
||||||
def get_flow_names(self) -> List[str]:
|
def get_flow_names(self) -> List[str]:
|
||||||
flow_data = self.list_flows()
|
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]:
|
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.
|
Optional[Text]: The flow record if found, None otherwise.
|
||||||
"""
|
"""
|
||||||
flow_data = self.list_flows()
|
flow_data = self.list_flows()
|
||||||
for flow_record in flow_data:
|
for flow_data in flow_data:
|
||||||
if flow_record.data["name"] == flow_name:
|
if flow_data.data["name"] == flow_name:
|
||||||
return flow_record
|
return flow_data
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = 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:
|
async def build(self, flow_name: str, name: str, description: str, return_direct: bool = False) -> Tool:
|
||||||
FlowTool.update_forward_refs()
|
FlowTool.update_forward_refs()
|
||||||
flow_record = self.get_flow(flow_name)
|
flow_data = self.get_flow(flow_name)
|
||||||
if not flow_record:
|
if not flow_data:
|
||||||
raise ValueError("Flow not found.")
|
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)
|
inputs = get_flow_inputs(graph)
|
||||||
tool = FlowTool(
|
tool = FlowTool(
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -80,7 +80,7 @@ class FlowToolComponent(CustomComponent):
|
||||||
graph=graph,
|
graph=graph,
|
||||||
return_direct=return_direct,
|
return_direct=return_direct,
|
||||||
inputs=inputs,
|
inputs=inputs,
|
||||||
flow_id=str(flow_record.id),
|
flow_id=str(flow_data.id),
|
||||||
user_id=str(self._user_id),
|
user_id=str(self._user_id),
|
||||||
)
|
)
|
||||||
description_repr = repr(tool.description).strip("'")
|
description_repr = repr(tool.description).strip("'")
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ from langflow.custom import CustomComponent
|
||||||
from langflow.schema import Data
|
from langflow.schema import Data
|
||||||
|
|
||||||
|
|
||||||
class MergeRecordsComponent(CustomComponent):
|
class MergeDataComponent(CustomComponent):
|
||||||
display_name = "Merge Records"
|
display_name = "Merge Data"
|
||||||
description = "Merges data."
|
description = "Merges data."
|
||||||
beta: bool = True
|
beta: bool = True
|
||||||
|
|
||||||
field_config = {
|
field_config = {
|
||||||
"data": {"display_name": "Records"},
|
"data": {"display_name": "Data"},
|
||||||
}
|
}
|
||||||
|
|
||||||
def build(self, data: list[Data]) -> Data:
|
def build(self, data: list[Data]) -> Data:
|
||||||
|
|
@ -16,14 +16,14 @@ class MergeRecordsComponent(CustomComponent):
|
||||||
return Data()
|
return Data()
|
||||||
if len(data) == 1:
|
if len(data) == 1:
|
||||||
return data[0]
|
return data[0]
|
||||||
merged_record = Data()
|
merged_data = Data()
|
||||||
for value in data:
|
for value in data:
|
||||||
if merged_record is None:
|
if merged_data is None:
|
||||||
merged_record = value
|
merged_data = value
|
||||||
else:
|
else:
|
||||||
merged_record += value
|
merged_data += value
|
||||||
self.status = merged_record
|
self.status = merged_data
|
||||||
return merged_record
|
return merged_data
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
@ -31,6 +31,6 @@ if __name__ == "__main__":
|
||||||
Data(data={"key1": "value1"}),
|
Data(data={"key1": "value1"}),
|
||||||
Data(data={"key2": "value2"}),
|
Data(data={"key2": "value2"}),
|
||||||
]
|
]
|
||||||
component = MergeRecordsComponent()
|
component = MergeDataComponent()
|
||||||
result = component.build(data)
|
result = component.build(data)
|
||||||
print(result)
|
print(result)
|
||||||
|
|
|
||||||
|
|
@ -13,29 +13,29 @@ class NotifyComponent(CustomComponent):
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
return {
|
return {
|
||||||
"name": {"display_name": "Name", "info": "The name of the notification."},
|
"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": {
|
"append": {
|
||||||
"display_name": "Append",
|
"display_name": "Append",
|
||||||
"info": "If True, the record will be appended to the notification.",
|
"info": "If True, the record will be appended to the notification.",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def build(self, name: str, record: Optional[Data] = None, append: bool = False) -> Data:
|
def build(self, name: str, data: Optional[Data] = None, append: bool = False) -> Data:
|
||||||
if record and not isinstance(record, Data):
|
if data and not isinstance(data, Data):
|
||||||
if isinstance(record, str):
|
if isinstance(data, str):
|
||||||
record = Data(text=record)
|
data = Data(text=data)
|
||||||
elif isinstance(record, dict):
|
elif isinstance(data, dict):
|
||||||
record = Data(data=record)
|
data = Data(data=data)
|
||||||
else:
|
else:
|
||||||
record = Data(text=str(record))
|
data = Data(text=str(data))
|
||||||
elif not record:
|
elif not data:
|
||||||
record = Data(text="")
|
data = Data(text="")
|
||||||
if record:
|
if data:
|
||||||
if append:
|
if append:
|
||||||
self.append_state(name, record)
|
self.append_state(name, data)
|
||||||
else:
|
else:
|
||||||
self.update_state(name, record)
|
self.update_state(name, data)
|
||||||
else:
|
else:
|
||||||
self.status = "No record provided."
|
self.status = "No record provided."
|
||||||
self.status = record
|
self.status = data
|
||||||
return record
|
return data
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class RunFlowComponent(CustomComponent):
|
||||||
|
|
||||||
def get_flow_names(self) -> List[str]:
|
def get_flow_names(self) -> List[str]:
|
||||||
flow_data = self.list_flows()
|
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):
|
def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None):
|
||||||
if field_name == "flow_name":
|
if field_name == "flow_name":
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,13 @@ class SubFlowComponent(CustomComponent):
|
||||||
|
|
||||||
def get_flow_names(self) -> List[str]:
|
def get_flow_names(self) -> List[str]:
|
||||||
flow_data = self.list_flows()
|
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]:
|
def get_flow(self, flow_name: str) -> Optional[Data]:
|
||||||
flow_data = self.list_flows()
|
flow_data = self.list_flows()
|
||||||
for flow_record in flow_data:
|
for flow_data in flow_data:
|
||||||
if flow_record.data["name"] == flow_name:
|
if flow_data.data["name"] == flow_name:
|
||||||
return flow_record
|
return flow_data
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = 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]
|
del build_config[key]
|
||||||
if field_value is not None and field_name == "flow_name":
|
if field_value is not None and field_name == "flow_name":
|
||||||
try:
|
try:
|
||||||
flow_record = self.get_flow(field_value)
|
flow_data = self.get_flow(field_value)
|
||||||
if not flow_record:
|
if not flow_data:
|
||||||
raise ValueError(f"Flow {field_value} not found.")
|
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
|
# Get all inputs from the graph
|
||||||
inputs = get_flow_inputs(graph)
|
inputs = get_flow_inputs(graph)
|
||||||
# Add inputs to the build config
|
# Add inputs to the build config
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,24 @@
|
||||||
|
from .AgentComponent import AgentComponent
|
||||||
from .ClearMessageHistory import ClearMessageHistoryComponent
|
from .ClearMessageHistory import ClearMessageHistoryComponent
|
||||||
from .ExtractDataFromRecord import ExtractKeyFromRecordComponent
|
from .ExtractDataFromData import ExtractKeyFromDataComponent
|
||||||
from .FlowTool import FlowToolComponent
|
from .FlowTool import FlowToolComponent
|
||||||
from .ListFlows import ListFlowsComponent
|
|
||||||
from .Listen import ListenComponent
|
from .Listen import ListenComponent
|
||||||
from .MergeRecords import MergeRecordsComponent
|
from .ListFlows import ListFlowsComponent
|
||||||
from .Notify import NotifyComponent
|
from .Notify import NotifyComponent
|
||||||
from .PythonFunction import PythonFunctionComponent
|
from .PythonFunction import PythonFunctionComponent
|
||||||
from .RunFlow import RunFlowComponent
|
from .RunFlow import RunFlowComponent
|
||||||
from .RunnableExecutor import RunnableExecComponent
|
from .RunnableExecutor import RunnableExecComponent
|
||||||
from .SQLExecutor import SQLExecutorComponent
|
from .SQLExecutor import SQLExecutorComponent
|
||||||
from .SubFlow import SubFlowComponent
|
from .SubFlow import SubFlowComponent
|
||||||
from .AgentComponent import AgentComponent
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"AgentComponent",
|
"AgentComponent",
|
||||||
"ClearMessageHistoryComponent",
|
"ClearMessageHistoryComponent",
|
||||||
"ExtractKeyFromRecordComponent",
|
"ExtractKeyFromDataComponent",
|
||||||
"FlowToolComponent",
|
"FlowToolComponent",
|
||||||
"ListFlowsComponent",
|
"ListFlowsComponent",
|
||||||
"ListenComponent",
|
"ListenComponent",
|
||||||
"MergeRecordsComponent",
|
"MergeDataComponent",
|
||||||
"NotifyComponent",
|
"NotifyComponent",
|
||||||
"PythonFunctionComponent",
|
"PythonFunctionComponent",
|
||||||
"RunFlowComponent",
|
"RunFlowComponent",
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from langflow.schema.dotdict import dotdict
|
||||||
from langflow.template.field.base import Input
|
from langflow.template.field.base import Input
|
||||||
|
|
||||||
|
|
||||||
class CreateRecordComponent(CustomComponent):
|
class CreateDataComponent(CustomComponent):
|
||||||
display_name = "Create Data"
|
display_name = "Create Data"
|
||||||
description = "Dynamically create a Data with a specified number of fields."
|
description = "Dynamically create a Data with a specified number of fields."
|
||||||
field_order = ["number_of_fields", "text_key"]
|
field_order = ["number_of_fields", "text_key"]
|
||||||
|
|
@ -22,7 +22,7 @@ class CreateRecordComponent(CustomComponent):
|
||||||
existing_fields = {}
|
existing_fields = {}
|
||||||
if field_value_int > 15:
|
if field_value_int > 15:
|
||||||
build_config["number_of_fields"]["value"] = 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:
|
if len(build_config) > len(default_keys) + field_value_int:
|
||||||
# back up the existing template fields
|
# back up the existing template fields
|
||||||
for key in build_config.copy():
|
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()
|
key: value.get_text() if isinstance(value, Data) else value for key, value in value_dict.items()
|
||||||
}
|
}
|
||||||
data.update(value_dict)
|
data.update(value_dict)
|
||||||
return_record = Data(data=data, text_key=text_key)
|
return_data = Data(data=data, text_key=text_key)
|
||||||
self.status = return_record
|
self.status = return_data
|
||||||
return return_record
|
return return_data
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
from langflow.custom import CustomComponent
|
from langflow.custom import CustomComponent
|
||||||
from langflow.field_typing import Text
|
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
|
from langflow.schema import Data
|
||||||
|
|
||||||
|
|
||||||
class RecordsToTextComponent(CustomComponent):
|
class DataToTextComponent(CustomComponent):
|
||||||
display_name = "Records To Text"
|
display_name = "Data To Text"
|
||||||
description = "Convert Records into plain text following a specified template."
|
description = "Convert Data into plain text following a specified template."
|
||||||
|
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
return {
|
return {
|
||||||
"data": {
|
"data": {
|
||||||
"display_name": "Records",
|
"display_name": "Data",
|
||||||
"info": "The data to convert to text.",
|
"info": "The data to convert to text.",
|
||||||
},
|
},
|
||||||
"template": {
|
"template": {
|
||||||
|
|
@ -6,9 +6,9 @@ from langflow.custom import CustomComponent
|
||||||
from langflow.schema import Data
|
from langflow.schema import Data
|
||||||
|
|
||||||
|
|
||||||
class DocumentToRecordComponent(CustomComponent):
|
class DocumentToDataComponent(CustomComponent):
|
||||||
display_name = "Documents To Records"
|
display_name = "Documents To Data"
|
||||||
description = "Convert LangChain Documents into Records."
|
description = "Convert LangChain Documents into Data."
|
||||||
|
|
||||||
field_config = {
|
field_config = {
|
||||||
"documents": {"display_name": "Documents"},
|
"documents": {"display_name": "Documents"},
|
||||||
|
|
@ -2,7 +2,7 @@ from typing import Optional
|
||||||
|
|
||||||
from langflow.base.memory.memory import BaseMemoryComponent
|
from langflow.base.memory.memory import BaseMemoryComponent
|
||||||
from langflow.field_typing import Text
|
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.memory import get_messages
|
||||||
from langflow.schema.message import Message
|
from langflow.schema.message import Message
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ class MemoryComponent(BaseMemoryComponent):
|
||||||
"info": "Order of the messages.",
|
"info": "Order of the messages.",
|
||||||
"advanced": True,
|
"advanced": True,
|
||||||
},
|
},
|
||||||
"record_template": {
|
"data_template": {
|
||||||
"display_name": "Data Template",
|
"display_name": "Data Template",
|
||||||
"multiline": True,
|
"multiline": True,
|
||||||
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
|
"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,
|
session_id: Optional[str] = None,
|
||||||
n_messages: int = 5,
|
n_messages: int = 5,
|
||||||
order: Optional[str] = "Descending",
|
order: Optional[str] = "Descending",
|
||||||
record_template: Optional[str] = "{sender_name}: {text}",
|
data_template: Optional[str] = "{sender_name}: {text}",
|
||||||
) -> Text:
|
) -> Text:
|
||||||
messages = self.get_messages(
|
messages = self.get_messages(
|
||||||
sender=sender,
|
sender=sender,
|
||||||
|
|
@ -77,6 +77,6 @@ class MemoryComponent(BaseMemoryComponent):
|
||||||
limit=n_messages,
|
limit=n_messages,
|
||||||
order=order,
|
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
|
self.status = messages_str
|
||||||
return messages_str
|
return messages_str
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ from langflow.custom import CustomComponent
|
||||||
from langflow.schema import Data
|
from langflow.schema import Data
|
||||||
|
|
||||||
|
|
||||||
class UpdateRecordComponent(CustomComponent):
|
class UpdateDataComponent(CustomComponent):
|
||||||
display_name = "Update Data"
|
display_name = "Update Data"
|
||||||
description = "Update Data with text-based key/value pairs, similar to updating a Python dictionary."
|
description = "Update Data with text-based key/value pairs, similar to updating a Python dictionary."
|
||||||
|
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
return {
|
return {
|
||||||
"record": {
|
"data": {
|
||||||
"display_name": "Data",
|
"display_name": "Data",
|
||||||
"info": "The record to update.",
|
"info": "The record to update.",
|
||||||
},
|
},
|
||||||
|
|
@ -21,7 +21,7 @@ class UpdateRecordComponent(CustomComponent):
|
||||||
|
|
||||||
def build(
|
def build(
|
||||||
self,
|
self,
|
||||||
record: Data,
|
data: Data,
|
||||||
new_data: dict,
|
new_data: dict,
|
||||||
) -> Data:
|
) -> Data:
|
||||||
"""
|
"""
|
||||||
|
|
@ -34,6 +34,6 @@ class UpdateRecordComponent(CustomComponent):
|
||||||
Returns:
|
Returns:
|
||||||
Data: The updated record.
|
Data: The updated record.
|
||||||
"""
|
"""
|
||||||
record.data.update(new_data)
|
data.data.update(new_data)
|
||||||
self.status = record
|
self.status = data
|
||||||
return record
|
return data
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
from .CreateRecord import CreateRecordComponent
|
from .CreateData import CreateDataComponent
|
||||||
from .CustomComponent import Component
|
from .CustomComponent import Component
|
||||||
from .DocumentToRecord import DocumentToRecordComponent
|
from .DataToText import DataToTextComponent
|
||||||
|
from .DocumentToData import DocumentToDataComponent
|
||||||
from .IDGenerator import UUIDGeneratorComponent
|
from .IDGenerator import UUIDGeneratorComponent
|
||||||
from .MessageHistory import MessageHistoryComponent
|
from .MessageHistory import MessageHistoryComponent
|
||||||
from .UpdateRecord import UpdateRecordComponent
|
from .UpdateData import UpdateDataComponent
|
||||||
from .RecordsToText import RecordsToTextComponent
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Component",
|
"Component",
|
||||||
"UpdateRecordComponent",
|
"UpdateDataComponent",
|
||||||
"DocumentToRecordComponent",
|
"DocumentToDataComponent",
|
||||||
"UUIDGeneratorComponent",
|
"UUIDGeneratorComponent",
|
||||||
"RecordsToTextComponent",
|
"DataToTextComponent",
|
||||||
"CreateRecordComponent",
|
"CreateDataComponent",
|
||||||
"MessageHistoryComponent",
|
"MessageHistoryComponent",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class TextInput(TextComponent):
|
||||||
input_types=["Data", "Text"],
|
input_types=["Data", "Text"],
|
||||||
),
|
),
|
||||||
Input(
|
Input(
|
||||||
name="record_template",
|
name="data_template",
|
||||||
type=str,
|
type=str,
|
||||||
display_name="Data Template",
|
display_name="Data Template",
|
||||||
multiline=True,
|
multiline=True,
|
||||||
|
|
@ -30,4 +30,4 @@ class TextInput(TextComponent):
|
||||||
]
|
]
|
||||||
|
|
||||||
def text_response(self) -> Text:
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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="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),
|
StrInput(name="session_id", display_name="Session ID", info="Session ID for the message.", advanced=True),
|
||||||
BoolInput(
|
BoolInput(
|
||||||
name="record_template",
|
name="data_template",
|
||||||
display_name="Data Template",
|
display_name="Data Template",
|
||||||
value="{text}",
|
value="{text}",
|
||||||
advanced=True,
|
advanced=True,
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,17 @@ from langflow.schema import Data
|
||||||
from langflow.template import Input, Output
|
from langflow.template import Input, Output
|
||||||
|
|
||||||
|
|
||||||
class RecordsOutput(Component):
|
class DataOutput(Component):
|
||||||
display_name = "Records Output"
|
display_name = "Data Output"
|
||||||
description = "Display Records as a Table"
|
description = "Display Data as a Table"
|
||||||
|
|
||||||
inputs = [
|
inputs = [
|
||||||
Input(name="input_value", type=Data, display_name="Data Input"),
|
Input(name="input_value", type=Data, display_name="Data Input"),
|
||||||
]
|
]
|
||||||
outputs = [
|
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
|
self.status = self.input_value
|
||||||
return self.input_value
|
return self.input_value
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class TextOutput(TextComponent):
|
||||||
input_types=["Data", "Text"],
|
input_types=["Data", "Text"],
|
||||||
),
|
),
|
||||||
Input(
|
Input(
|
||||||
name="record_template",
|
name="data_template",
|
||||||
type=str,
|
type=str,
|
||||||
display_name="Data Template",
|
display_name="Data Template",
|
||||||
multiline=True,
|
multiline=True,
|
||||||
|
|
@ -30,4 +30,4 @@ class TextOutput(TextComponent):
|
||||||
]
|
]
|
||||||
|
|
||||||
def text_response(self) -> Text:
|
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)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ from langchain_core.vectorstores import VectorStore
|
||||||
|
|
||||||
from langflow.custom import CustomComponent
|
from langflow.custom import CustomComponent
|
||||||
from langflow.field_typing import Text
|
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
|
from langflow.schema import Data
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ class InterfaceComponentTypes(str, Enum, metaclass=ContainsEnumMeta):
|
||||||
ChatOutput = "ChatOutput"
|
ChatOutput = "ChatOutput"
|
||||||
TextInput = "TextInput"
|
TextInput = "TextInput"
|
||||||
TextOutput = "TextOutput"
|
TextOutput = "TextOutput"
|
||||||
RecordsOutput = "RecordsOutput"
|
DataOutput = "DataOutput"
|
||||||
|
|
||||||
def __contains__(cls, item):
|
def __contains__(cls, item):
|
||||||
try:
|
try:
|
||||||
|
|
@ -65,7 +65,7 @@ class InterfaceComponentTypes(str, Enum, metaclass=ContainsEnumMeta):
|
||||||
|
|
||||||
|
|
||||||
CHAT_COMPONENTS = [InterfaceComponentTypes.ChatInput, InterfaceComponentTypes.ChatOutput]
|
CHAT_COMPONENTS = [InterfaceComponentTypes.ChatInput, InterfaceComponentTypes.ChatOutput]
|
||||||
RECORDS_COMPONENTS = [InterfaceComponentTypes.RecordsOutput]
|
RECORDS_COMPONENTS = [InterfaceComponentTypes.DataOutput]
|
||||||
INPUT_COMPONENTS = [
|
INPUT_COMPONENTS = [
|
||||||
InterfaceComponentTypes.ChatInput,
|
InterfaceComponentTypes.ChatInput,
|
||||||
InterfaceComponentTypes.TextInput,
|
InterfaceComponentTypes.TextInput,
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ from langflow.schema import Data
|
||||||
from langflow.schema.artifact import ArtifactType
|
from langflow.schema.artifact import ArtifactType
|
||||||
from langflow.schema.schema import INPUT_FIELD_NAME, build_logs_from_artifacts
|
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.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
|
from langflow.utils.util import unescape_string
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|
@ -259,7 +259,7 @@ class InterfaceVertex(ComponentVertex):
|
||||||
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
def _process_record_component(self):
|
def _process_data_component(self):
|
||||||
"""
|
"""
|
||||||
Process the record component of the vertex.
|
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)}")
|
logger.error(f"Data expected, but got {value} of type {type(value)}")
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Data expected, but got {value} of type {type(value)}")
|
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
|
return self._built_object
|
||||||
|
|
||||||
async def _run(self, *args, **kwargs):
|
async def _run(self, *args, **kwargs):
|
||||||
|
|
@ -299,9 +299,9 @@ class InterfaceVertex(ComponentVertex):
|
||||||
if self.vertex_type in CHAT_COMPONENTS:
|
if self.vertex_type in CHAT_COMPONENTS:
|
||||||
message = self._process_chat_component()
|
message = self._process_chat_component()
|
||||||
elif self.vertex_type in RECORDS_COMPONENTS:
|
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 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)
|
self._built_object = Data(text=message, data=self.artifacts)
|
||||||
else:
|
else:
|
||||||
self._built_object = message
|
self._built_object = message
|
||||||
|
|
|
||||||
|
|
@ -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"]
|
__all__ = ["docs_to_data", "data_to_text", "messages_to_text"]
|
||||||
|
|
|
||||||
|
|
@ -8,23 +8,23 @@ from langflow.schema.message import Message
|
||||||
|
|
||||||
def docs_to_data(documents: list[Document]) -> list[Data]:
|
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:
|
Args:
|
||||||
documents (list[Document]): The list of Documents to convert.
|
documents (list[Document]): The list of Documents to convert.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list[Data]: The converted list of Records.
|
list[Data]: The converted list of Data.
|
||||||
"""
|
"""
|
||||||
return [Data.from_document(document) for document in documents]
|
return [Data.from_document(document) for document in documents]
|
||||||
|
|
||||||
|
|
||||||
def data_to_text(template: str, data: Union[Data, list[Data]]) -> str:
|
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:
|
Args:
|
||||||
data (list[Data]): The list of Records to convert.
|
data (list[Data]): The list of Data to convert.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list[str]: The converted list of texts.
|
list[str]: The converted list of texts.
|
||||||
|
|
@ -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
|
select(Flow).where(Flow.user_id == user_id).where(Flow.is_component == False) # noqa
|
||||||
).all()
|
).all()
|
||||||
|
|
||||||
flows_data = [flow.to_record() for flow in flows]
|
flows_data = [flow.to_data() for flow in flows]
|
||||||
return flows_data
|
return flows_data
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValueError(f"Error listing flows: {e}")
|
raise ValueError(f"Error listing flows: {e}")
|
||||||
|
|
@ -170,22 +170,22 @@ async def flow_function({func_args}):
|
||||||
|
|
||||||
|
|
||||||
def build_function_and_schema(
|
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]]:
|
) -> Tuple[Callable[..., Awaitable[Any]], Type[BaseModel]]:
|
||||||
"""
|
"""
|
||||||
Builds a dynamic function and schema for a given flow.
|
Builds a dynamic function and schema for a given flow.
|
||||||
|
|
||||||
Args:
|
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.
|
graph (Graph): The graph representing the flow.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple[Callable, BaseModel]: A tuple containing the dynamic function and the schema.
|
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)
|
inputs = get_flow_inputs(graph)
|
||||||
dynamic_flow_function = generate_function_for_flow(inputs, flow_id, user_id=user_id)
|
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
|
return dynamic_flow_function, schema
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -618,7 +618,7 @@
|
||||||
"show": true,
|
"show": true,
|
||||||
"title_case": false,
|
"title_case": false,
|
||||||
"type": "code",
|
"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": {
|
"input_value": {
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
|
|
@ -643,28 +643,6 @@
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"value": ""
|
"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": {
|
"sender": {
|
||||||
"advanced": true,
|
"advanced": true,
|
||||||
"display_name": "Sender Type",
|
"display_name": "Sender Type",
|
||||||
|
|
|
||||||
|
|
@ -520,7 +520,7 @@
|
||||||
"show": true,
|
"show": true,
|
||||||
"title_case": false,
|
"title_case": false,
|
||||||
"type": "code",
|
"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": {
|
"input_value": {
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
|
|
@ -545,28 +545,6 @@
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"value": ""
|
"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": {
|
"sender": {
|
||||||
"advanced": true,
|
"advanced": true,
|
||||||
"display_name": "Sender Type",
|
"display_name": "Sender Type",
|
||||||
|
|
|
||||||
|
|
@ -652,7 +652,7 @@
|
||||||
"show": true,
|
"show": true,
|
||||||
"title_case": false,
|
"title_case": false,
|
||||||
"type": "code",
|
"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": {
|
"input_value": {
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
|
|
@ -677,28 +677,6 @@
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"value": ""
|
"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": {
|
"sender": {
|
||||||
"advanced": true,
|
"advanced": true,
|
||||||
"display_name": "Sender Type",
|
"display_name": "Sender Type",
|
||||||
|
|
|
||||||
|
|
@ -396,7 +396,7 @@
|
||||||
"show": true,
|
"show": true,
|
||||||
"title_case": false,
|
"title_case": false,
|
||||||
"type": "code",
|
"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": {
|
"input_value": {
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
|
|
@ -421,28 +421,6 @@
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"value": ""
|
"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": {
|
"sender": {
|
||||||
"advanced": true,
|
"advanced": true,
|
||||||
"display_name": "Sender Type",
|
"display_name": "Sender Type",
|
||||||
|
|
@ -593,7 +571,7 @@
|
||||||
"show": true,
|
"show": true,
|
||||||
"title_case": false,
|
"title_case": false,
|
||||||
"type": "code",
|
"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": {
|
"n_messages": {
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
|
|
@ -640,28 +618,6 @@
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"value": "Descending"
|
"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": {
|
"sender": {
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
"display_name": "Sender Type",
|
"display_name": "Sender Type",
|
||||||
|
|
|
||||||
|
|
@ -598,7 +598,7 @@
|
||||||
"show": true,
|
"show": true,
|
||||||
"title_case": false,
|
"title_case": false,
|
||||||
"type": "code",
|
"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": {
|
"input_value": {
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
|
|
@ -623,28 +623,6 @@
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"value": ""
|
"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": {
|
"sender": {
|
||||||
"advanced": true,
|
"advanced": true,
|
||||||
"display_name": "Sender Type",
|
"display_name": "Sender Type",
|
||||||
|
|
@ -799,7 +777,7 @@
|
||||||
"show": true,
|
"show": true,
|
||||||
"title_case": false,
|
"title_case": false,
|
||||||
"type": "code",
|
"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": {
|
"input_value": {
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
|
|
@ -824,28 +802,6 @@
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"value": ""
|
"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": {
|
"sender": {
|
||||||
"advanced": true,
|
"advanced": true,
|
||||||
"display_name": "Sender Type",
|
"display_name": "Sender Type",
|
||||||
|
|
@ -983,7 +939,7 @@
|
||||||
"show": true,
|
"show": true,
|
||||||
"title_case": false,
|
"title_case": false,
|
||||||
"type": "code",
|
"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": {
|
"input_value": {
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
|
|
@ -1007,28 +963,6 @@
|
||||||
"title_case": false,
|
"title_case": false,
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"value": ""
|
"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": ""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1652,7 +1652,7 @@
|
||||||
"show": true,
|
"show": true,
|
||||||
"title_case": false,
|
"title_case": false,
|
||||||
"type": "code",
|
"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": {
|
"input_value": {
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
|
|
@ -1677,28 +1677,6 @@
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"value": ""
|
"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": {
|
"sender": {
|
||||||
"advanced": true,
|
"advanced": true,
|
||||||
"display_name": "Sender Type",
|
"display_name": "Sender Type",
|
||||||
|
|
@ -1841,7 +1819,7 @@
|
||||||
"show": true,
|
"show": true,
|
||||||
"title_case": false,
|
"title_case": false,
|
||||||
"type": "code",
|
"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": {
|
"path": {
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from langflow.schema.message import Message
|
||||||
|
|
||||||
class ArtifactType(str, Enum):
|
class ArtifactType(str, Enum):
|
||||||
TEXT = "text"
|
TEXT = "text"
|
||||||
RECORD = "record"
|
DATA = "data"
|
||||||
OBJECT = "object"
|
OBJECT = "object"
|
||||||
ARRAY = "array"
|
ARRAY = "array"
|
||||||
STREAM = "stream"
|
STREAM = "stream"
|
||||||
|
|
@ -19,7 +19,7 @@ def get_artifact_type(value, build_result=None) -> str:
|
||||||
result = ArtifactType.UNKNOWN
|
result = ArtifactType.UNKNOWN
|
||||||
match value:
|
match value:
|
||||||
case Data():
|
case Data():
|
||||||
result = ArtifactType.RECORD
|
result = ArtifactType.DATA
|
||||||
|
|
||||||
case str():
|
case str():
|
||||||
result = ArtifactType.TEXT
|
result = ArtifactType.TEXT
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ from langchain_core.prompt_values import ImagePromptValue
|
||||||
from langchain_core.prompts.image import ImagePromptTemplate
|
from langchain_core.prompts.image import ImagePromptTemplate
|
||||||
from pydantic import BaseModel, BeforeValidator, ConfigDict, Field, field_serializer
|
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.data import Data
|
||||||
|
from langflow.schema.image import Image, get_file_paths, is_image_file
|
||||||
|
|
||||||
|
|
||||||
def _timestamp_to_str(timestamp: datetime) -> str:
|
def _timestamp_to_str(timestamp: datetime) -> str:
|
||||||
|
|
@ -68,7 +68,7 @@ class Message(BaseModel):
|
||||||
return AIMessage(content=self.text)
|
return AIMessage(content=self.text)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_record(cls, record: Data) -> "Message":
|
def from_data(cls, record: Data) -> "Message":
|
||||||
"""
|
"""
|
||||||
Converts a BaseMessage to a Data.
|
Converts a BaseMessage to a Data.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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_id: Optional[UUID] = Field(default=None, foreign_key="folder.id", nullable=True, index=True)
|
||||||
folder: Optional["Folder"] = Relationship(back_populates="flows")
|
folder: Optional["Folder"] = Relationship(back_populates="flows")
|
||||||
|
|
||||||
def to_record(self):
|
def to_data(self):
|
||||||
serialized = self.model_dump()
|
serialized = self.model_dump()
|
||||||
data = {
|
data = {
|
||||||
"id": serialized.pop("id"),
|
"id": serialized.pop("id"),
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ class ChatOutputResponse(BaseModel):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
class RecordOutputResponse(BaseModel):
|
class DataOutputResponse(BaseModel):
|
||||||
"""Data output response schema."""
|
"""Data output response schema."""
|
||||||
|
|
||||||
data: List[Optional[Dict]]
|
data: List[Optional[Dict]]
|
||||||
|
|
|
||||||
|
|
@ -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)
|
avg_length = sum(len(doc.text) for doc in data) / len(data)
|
||||||
return f"""{len(data)} data
|
return f"""{len(data)} data
|
||||||
\nAvg. Data Length (characters): {int(avg_length)}
|
\nAvg. Data Length (characters): {int(avg_length)}
|
||||||
Records: {data[:3]}..."""
|
Data: {data[:3]}..."""
|
||||||
return "0 data"
|
return "0 data"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import RecordsOutputComponent from "../../../../../../components/dataOutputComponent";
|
import DataOutputComponent from "../../../../../../components/dataOutputComponent";
|
||||||
import ForwardedIconComponent from "../../../../../../components/genericIconComponent";
|
import ForwardedIconComponent from "../../../../../../components/genericIconComponent";
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
|
|
@ -29,7 +29,7 @@ const SwitchOutputView: React.FC<SwitchOutputViewProps> = ({
|
||||||
const results = flowPoolNode?.data?.logs[outputName] ?? "";
|
const results = flowPoolNode?.data?.logs[outputName] ?? "";
|
||||||
const resultType = results?.type;
|
const resultType = results?.type;
|
||||||
let resultMessage = results?.message;
|
let resultMessage = results?.message;
|
||||||
const RECORD_TYPES = ["record", "object", "array", "message"];
|
const RECORD_TYPES = ["data", "object", "array", "message"];
|
||||||
if (resultMessage?.raw) {
|
if (resultMessage?.raw) {
|
||||||
resultMessage = resultMessage.raw;
|
resultMessage = resultMessage.raw;
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +47,7 @@ const SwitchOutputView: React.FC<SwitchOutputViewProps> = ({
|
||||||
</Case>
|
</Case>
|
||||||
|
|
||||||
<Case condition={RECORD_TYPES.includes(resultType)}>
|
<Case condition={RECORD_TYPES.includes(resultType)}>
|
||||||
<RecordsOutputComponent
|
<DataOutputComponent
|
||||||
rows={
|
rows={
|
||||||
Array.isArray(resultMessage)
|
Array.isArray(resultMessage)
|
||||||
? (resultMessage as Array<any>).every((item) => item.data)
|
? (resultMessage as Array<any>).every((item) => item.data)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import "ag-grid-community/styles/ag-theme-balham.css"; // Optional Theme applied
|
||||||
import { extractColumnsFromRows } from "../../utils/utils";
|
import { extractColumnsFromRows } from "../../utils/utils";
|
||||||
import TableComponent from "../tableComponent";
|
import TableComponent from "../tableComponent";
|
||||||
|
|
||||||
function RecordsOutputComponent({
|
function DataOutputComponent({
|
||||||
pagination,
|
pagination,
|
||||||
rows,
|
rows,
|
||||||
columnMode = "union",
|
columnMode = "union",
|
||||||
|
|
@ -35,4 +35,4 @@ function RecordsOutputComponent({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default RecordsOutputComponent;
|
export default DataOutputComponent;
|
||||||
|
|
|
||||||
|
|
@ -664,7 +664,7 @@ export const OUTPUT_TYPES = new Set([
|
||||||
"JsonOutput",
|
"JsonOutput",
|
||||||
"KeyPairOutput",
|
"KeyPairOutput",
|
||||||
"StringListOutput",
|
"StringListOutput",
|
||||||
"RecordsOutput",
|
"DataOutput",
|
||||||
"TableOutput",
|
"TableOutput",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { cloneDeep } from "lodash";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import ImageViewer from "../../../../components/ImageViewer";
|
import ImageViewer from "../../../../components/ImageViewer";
|
||||||
import CsvOutputComponent from "../../../../components/csvOutputComponent";
|
import CsvOutputComponent from "../../../../components/csvOutputComponent";
|
||||||
import RecordsOutputComponent from "../../../../components/dataOutputComponent";
|
import DataOutputComponent from "../../../../components/dataOutputComponent";
|
||||||
import InputListComponent from "../../../../components/inputListComponent";
|
import InputListComponent from "../../../../components/inputListComponent";
|
||||||
import PdfViewer from "../../../../components/pdfViewer";
|
import PdfViewer from "../../../../components/pdfViewer";
|
||||||
import { Textarea } from "../../../../components/ui/textarea";
|
import { Textarea } from "../../../../components/ui/textarea";
|
||||||
|
|
@ -245,10 +245,10 @@ export default function IOFieldView({
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
case "RecordsOutput":
|
case "DataOutput":
|
||||||
return (
|
return (
|
||||||
<div className={left ? "h-56" : "h-full"}>
|
<div className={left ? "h-56" : "h-full"}>
|
||||||
<RecordsOutputComponent
|
<DataOutputComponent
|
||||||
pagination={!left}
|
pagination={!left}
|
||||||
rows={
|
rows={
|
||||||
Array.isArray(flowPoolNode?.data?.artifacts)
|
Array.isArray(flowPoolNode?.data?.artifacts)
|
||||||
|
|
|
||||||
|
|
@ -272,7 +272,7 @@ export const nodeColors: { [char: string]: string } = {
|
||||||
retrievers: "#e6b25a",
|
retrievers: "#e6b25a",
|
||||||
unknown: "#9CA3AF",
|
unknown: "#9CA3AF",
|
||||||
custom_components: "#ab11ab",
|
custom_components: "#ab11ab",
|
||||||
Records: "#31a3cc",
|
Data: "#31a3cc",
|
||||||
Data: "#31a3cc",
|
Data: "#31a3cc",
|
||||||
Message: "#4367BF",
|
Message: "#4367BF",
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,31 @@
|
||||||
from langchain_core.documents import Document
|
from langchain_core.documents import Document
|
||||||
|
|
||||||
from langflow.components import helpers
|
from langflow.components import helpers
|
||||||
from langflow.custom.utils import build_custom_component_template
|
from langflow.custom.utils import build_custom_component_template
|
||||||
from langflow.schema import Data
|
from langflow.schema import Data
|
||||||
|
|
||||||
|
|
||||||
def test_update_record_component():
|
def test_update_data_component():
|
||||||
# Arrange
|
# Arrange
|
||||||
update_record_component = helpers.UpdateRecordComponent()
|
update_data_component = helpers.UpdateDataComponent()
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
new_data = {"new_key": "new_value"}
|
new_data = {"new_key": "new_value"}
|
||||||
existing_record = Data(data={"existing_key": "existing_value"})
|
existing_data = Data(data={"existing_key": "existing_value"})
|
||||||
result = update_record_component.build(existing_record, new_data)
|
result = update_data_component.build(existing_data, new_data)
|
||||||
assert result.data == {"existing_key": "existing_value", "new_key": "new_value"}
|
assert result.data == {"existing_key": "existing_value", "new_key": "new_value"}
|
||||||
assert result.existing_key == "existing_value"
|
assert result.existing_key == "existing_value"
|
||||||
assert result.new_key == "new_value"
|
assert result.new_key == "new_value"
|
||||||
|
|
||||||
|
|
||||||
def test_document_to_record_component():
|
def test_document_to_data_component():
|
||||||
# Arrange
|
# Arrange
|
||||||
document_to_record_component = helpers.DocumentToRecordComponent()
|
document_to_data_component = helpers.DocumentToDataComponent()
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
# Replace with your actual test data
|
# Replace with your actual test data
|
||||||
document = Document(page_content="key: value", metadata={"url": "https://example.com"})
|
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
|
# Assert
|
||||||
# Replace with your actual expected result
|
# Replace with your actual expected result
|
||||||
|
|
@ -53,7 +54,7 @@ def test_uuid_generator_component():
|
||||||
|
|
||||||
def test_data_as_text_component():
|
def test_data_as_text_component():
|
||||||
# Arrange
|
# Arrange
|
||||||
data_as_text_component = helpers.RecordsToTextComponent()
|
data_as_text_component = helpers.DataToTextComponent()
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
# Replace with your actual test data
|
# 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"
|
assert result == "Data:{'key': 'value', 'bacon': 'eggs'} -- Bacon:eggs"
|
||||||
|
|
||||||
|
|
||||||
def test_text_to_record_component():
|
def test_text_to_data_component():
|
||||||
# Arrange
|
# Arrange
|
||||||
text_to_record_component = helpers.CreateRecordComponent()
|
text_to_data_component = helpers.CreateDataComponent()
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
# Replace with your actual test data
|
# Replace with your actual test data
|
||||||
dict_with_text = {"field_1": {"key": "value"}}
|
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
|
# Assert
|
||||||
# Replace with your actual expected result
|
# Replace with your actual expected result
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
from langchain_core.documents import Document
|
from langchain_core.documents import Document
|
||||||
|
|
||||||
from langflow.schema import Data
|
from langflow.schema import Data
|
||||||
|
|
||||||
|
|
||||||
def test_record_initialization():
|
def test_data_initialization():
|
||||||
record = Data(text_key="msg", data={"msg": "Hello, World!", "extra": "value"})
|
record = Data(text_key="msg", data={"msg": "Hello, World!", "extra": "value"})
|
||||||
assert record.msg == "Hello, World!"
|
assert record.msg == "Hello, World!"
|
||||||
assert record.extra == "value"
|
assert record.extra == "value"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue