rearrange and remove components

This commit is contained in:
Rodrigo 2024-06-23 19:40:46 -03:00 • committed by Gabriel Luiz Freitas Almeida
commit 0ddb11664f
32 changed files with 309 additions and 15 deletions

View file

@ -1,19 +1,29 @@
from typing import List, cast
from typing import List, Optional
from langchain.agents import AgentExecutor, BaseSingleActionAgent
from langchain.agents.tool_calling_agent.base import create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate
<<<<<<< Updated upstream
from langflow.custom import Component
from langflow.io import BoolInput, HandleInput, MessageTextInput, Output
from langflow.schema import Data
=======
from langchain.agents import AgentExecutor
from langchain_core.messages import BaseMessage
>>>>>>> Stashed changes
from langflow.schema.message import Message
from langflow.custom import Component
from langflow.io import HandleInput, TextInput, BoolInput, Output
from langflow.schema import Data
class ToolCallingAgentComponent(Component):
display_name: str = "Tool Calling Agent"
description: str = "Agent that uses tools. Only models that are compatible with function calling are supported."
description: str = (
"Agent that uses tools. Only models that are compatible with function calling are supported."
)
icon = "LangChain"
beta = True
inputs = [
MessageTextInput(
@ -80,12 +90,12 @@ class ToolCallingAgentComponent(Component):
agent = create_tool_calling_agent(self.llm, self.tools, prompt)
runnable = AgentExecutor.from_agent_and_tools(
agent=cast(BaseSingleActionAgent, agent),
agent=agent,
tools=self.tools,
verbose=True,
handle_parsing_errors=self.handle_parsing_errors,
)
input_dict: dict[str, str | list[dict[str, str]]] = {"input": self.input_value}
input_dict: dict[str, str | list[BaseMessage]] = {"input": self.input_value}
if hasattr(self, "memory") and self.memory:
input_dict["chat_history"] = self.convert_chat_history(self.memory)
result = await runnable.ainvoke(input_dict)
@ -98,7 +108,7 @@ class ToolCallingAgentComponent(Component):
return Message(text=result_string)
def convert_chat_history(self, chat_history: List[Data]) -> List[dict[str, str]]:
def convert_chat_history(self, chat_history: List[Data]) -> List[Dict[str, str]]:
messages = []
for item in chat_history:
role = "user" if item.sender == "User" else "assistant"

View file

@ -0,0 +1,185 @@
from typing import Any, List, Optional, cast
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts.chat import HumanMessagePromptTemplate, SystemMessagePromptTemplate
from langflow.base.agents.agent import LCAgentComponent
from langflow.base.agents.utils import AGENTS, AgentSpec, get_agents_list
from langflow.field_typing import LanguageModel, Text, Tool
from langflow.schema import Data
from langflow.schema.dotdict import dotdict
class AgentComponent(LCAgentComponent):
display_name = "Agent"
description = "Run any LangChain agent using a simplified interface."
field_order = [
"agent_name",
"llm",
"tools",
"prompt",
"tool_template",
"handle_parsing_errors",
"memory",
"input_value",
]
def build_config(self):
return {
"agent_name": {
"display_name": "Agent",
"info": "The agent to use.",
"refresh_button": True,
"real_time_refresh": True,
"options": get_agents_list(),
},
"llm": {"display_name": "LLM"},
"tools": {"display_name": "Tools"},
"user_prompt": {
"display_name": "Prompt",
"multiline": True,
"info": "This prompt must contain 'tools' and 'agent_scratchpad' keys.",
},
"system_message": {
"display_name": "System Message",
"info": "System message to be passed to the LLM.",
"advanced": True,
},
"tool_template": {
"display_name": "Tool Template",
"info": "Template for rendering tools in the prompt. Tools have 'name' and 'description' keys.",
"advanced": True,
},
"handle_parsing_errors": {
"display_name": "Handle Parsing Errors",
"info": "If True, the agent will handle parsing errors. If False, the agent will raise an error.",
"advanced": True,
},
"message_history": {
"display_name": "Message History",
"info": "Message history to pass to the agent.",
},
"input_value": {
"display_name": "Input",
"info": "Input text to pass to the agent.",
},
"langchain_hub_api_key": {
"display_name": "LangChain Hub API Key",
"info": "API key to use for LangChain Hub. If provided, prompts will be fetched from LangChain Hub.",
"advanced": True,
},
}
def get_system_and_user_message_from_prompt(self, prompt: Any):
"""
Extracts the system message and user prompt from a given prompt object.
Args:
prompt (Any): The prompt object from which to extract the system message and user prompt.
Returns:
Tuple[Optional[str], Optional[str]]: A tuple containing the system message and user prompt.
If the prompt object does not have any messages, both values will be None.
"""
if hasattr(prompt, "messages"):
system_message = None
user_prompt = None
for message in prompt.messages:
if isinstance(message, SystemMessagePromptTemplate):
s_prompt = message.prompt
if isinstance(s_prompt, list):
s_template = " ".join([cast(str, s.template) for s in s_prompt if hasattr(s, "template")])
elif hasattr(s_prompt, "template"):
s_template = s_prompt.template
system_message = s_template
elif isinstance(message, HumanMessagePromptTemplate):
h_prompt = message.prompt
if isinstance(h_prompt, list):
h_template = " ".join([cast(str, h.template) for h in h_prompt if hasattr(h, "template")])
elif hasattr(h_prompt, "template"):
h_template = h_prompt.template
user_prompt = h_template
return system_message, user_prompt
return None, None
def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None):
"""
Updates the build configuration based on the provided field value and field name.
Args:
build_config (dotdict): The build configuration to be updated.
field_value (Any): The value of the field being updated.
field_name (Text | None, optional): The name of the field being updated. Defaults to None.
Returns:
dotdict: The updated build configuration.
"""
if field_name == "agent":
build_config["agent"]["options"] = get_agents_list()
if field_value in AGENTS:
# if langchain_hub_api_key is provided, fetch the prompt from LangChain Hub
if build_config["langchain_hub_api_key"]["value"] and AGENTS[field_value].hub_repo:
from langchain import hub
hub_repo: str | None = AGENTS[field_value].hub_repo
if hub_repo:
hub_api_key: str = build_config["langchain_hub_api_key"]["value"]
prompt = hub.pull(hub_repo, api_key=hub_api_key)
system_message, user_prompt = self.get_system_and_user_message_from_prompt(prompt)
if system_message:
build_config["system_message"]["value"] = system_message
if user_prompt:
build_config["user_prompt"]["value"] = user_prompt
if AGENTS[field_value].prompt:
build_config["user_prompt"]["value"] = AGENTS[field_value].prompt
else:
build_config["user_prompt"]["value"] = "{input}"
fields = AGENTS[field_value].fields
for field in ["llm", "tools", "prompt", "tools_renderer"]:
if field not in fields:
build_config[field]["show"] = False
return build_config
async def build(
self,
agent_name: str,
input_value: str,
llm: LanguageModel,
tools: List[Tool],
system_message: str = "You are a helpful assistant. Help the user answer any questions.",
user_prompt: str = "{input}",
message_history: Optional[List[Data]] = None,
tool_template: str = "{name}: {description}",
handle_parsing_errors: bool = True,
) -> Text:
agent_spec: Optional[AgentSpec] = AGENTS.get(agent_name)
if agent_spec is None:
raise ValueError(f"{agent_name} not found.")
def render_tool_description(tools):
return "\n".join(
[tool_template.format(name=tool.name, description=tool.description, args=tool.args) for tool in tools]
)
messages = [
("system", system_message),
(
"placeholder",
"{chat_history}",
),
("human", user_prompt),
("placeholder", "{agent_scratchpad}"),
]
prompt = ChatPromptTemplate.from_messages(messages)
agent_func = agent_spec.func
agent = agent_func(llm, tools, prompt, render_tool_description, True)
result = await self.run_agent(
agent=agent,
inputs=input_value,
tools=tools,
message_history=message_history,
handle_parsing_errors=handle_parsing_errors,
)
self.status = result
return result

View file

@ -0,0 +1,25 @@
import re
from langflow.custom import Component
from langflow.field_typing import Input, Output, Text
class CodeBlockExtractor(Component):
display_name = "Code Block Extractor"
description = "Extracts code block from text."
inputs = [Input(name="text", field_type=Text, description="Text to extract code blocks from.")]
outputs = [Output(name="code_block", display_name="Code Block", method="get_code_block")]
def get_code_block(self) -> Text:
text = self.text.strip()
# Extract code block
# It may start with ``` or ```language
# It may end with ```
pattern = r"^```(?:\w+)?\s*\n(.*?)(?=^```)```"
match = re.search(pattern, text, re.MULTILINE)
code_block = ""
if match:
code_block = match.group(1)
return code_block

View file

@ -0,0 +1,23 @@
from typing import List
from langchain_core.documents import Document
from langflow.custom import CustomComponent
from langflow.schema import Data
class DocumentsToDataComponent(CustomComponent):
display_name = "Documents ⇢ Data"
description = "Convert LangChain Documents into Data."
icon = "LangChain"
field_config = {
"documents": {"display_name": "Documents"},
}
def build(self, documents: List[Document]) -> List[Data]:
if isinstance(documents, Document):
documents = [documents]
data = [Data.from_document(document) for document in documents]
self.status = data
return data

View file

@ -0,0 +1,15 @@
from langflow.custom import CustomComponent
from langflow.field_typing import Embeddings
from langflow.schema import Data
class EmbedComponent(CustomComponent):
display_name = "Embed Texts"
def build_config(self):
return {"texts": {"display_name": "Texts"}, "embbedings": {"display_name": "Embeddings"}}
def build(self, texts: list[str], embbedings: Embeddings) -> Data:
vectors = Data(vector=embbedings.embed_documents(texts))
self.status = vectors
return vectors

View file

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

View file

@ -0,0 +1,21 @@
from typing import List
from langflow.custom import CustomComponent
from langflow.schema import Data
class ListFlowsComponent(CustomComponent):
display_name = "List Flows"
description = "A component to list all available flows."
icon = "ListFlows"
beta: bool = True
def build_config(self):
return {}
def build(
self,
) -> List[Data]:
flows = self.list_flows()
self.status = flows
return flows

View file

@ -0,0 +1,26 @@
from langflow.custom import CustomComponent
from langflow.schema import Data
class MergeDataComponent(CustomComponent):
display_name = "Merge Data"
description = "Merges data."
beta: bool = True
field_config = {
"data": {"display_name": "Data"},
}
def build(self, data: list[Data]) -> Data:
if not data:
return Data()
if len(data) == 1:
return data[0]
merged_data = Data()
for value in data:
if merged_data is None:
merged_data = value
else:
merged_data += value
self.status = merged_data
return merged_data

View file

@ -0,0 +1,38 @@
from typing import Optional
from langflow.custom import CustomComponent
from langflow.schema.message import Message
class MessageComponent(CustomComponent):
display_name = "Message"
description = "Creates a Message object given a Session ID."
def build_config(self):
return {
"sender": {
"options": ["Machine", "User"],
"display_name": "Sender Type",
},
"sender_name": {"display_name": "Sender Name"},
"text": {"display_name": "Text"},
"session_id": {
"display_name": "Session ID",
"info": "Session ID of the chat history.",
"input_types": ["Text"],
},
}
def build(
self,
sender: str = "User",
sender_name: Optional[str] = None,
session_id: Optional[str] = None,
text: str = "",
) -> Message:
message = Message(
text=text, sender=sender, sender_name=sender_name, flow_id=self.graph.flow_id, session_id=session_id
)
self.status = message
return message

View file

@ -0,0 +1,75 @@
from langflow.custom import Component
from langflow.field_typing import Text
from langflow.io import BoolInput, DropdownInput, MessageTextInput, Output
class SelectivePassThroughComponent(Component):
display_name = "Selective Pass Through"
description = "Passes the specified value if a specified condition is met."
icon = "filter"
inputs = [
MessageTextInput(
name="input_value",
display_name="Input Value",
info="The primary input value to evaluate.",
),
MessageTextInput(
name="comparison_value",
display_name="Comparison Value",
info="The value to compare against the input value.",
),
DropdownInput(
name="operator",
display_name="Operator",
options=["equals", "not equals", "contains", "starts with", "ends with"],
info="Condition to evaluate the input value.",
),
MessageTextInput(
name="value_to_pass",
display_name="Value to Pass",
info="The value to pass if the condition is met.",
),
BoolInput(
name="case_sensitive",
display_name="Case Sensitive",
info="If true, the comparison will be case sensitive.",
value=False,
advanced=True,
),
]
outputs = [
Output(display_name="Passed Output", name="passed_output", method="pass_through"),
]
def evaluate_condition(self, input_value: str, comparison_value: str, operator: str, case_sensitive: bool) -> bool:
if not case_sensitive:
input_value = input_value.lower()
comparison_value = comparison_value.lower()
if operator == "equals":
return input_value == comparison_value
elif operator == "not equals":
return input_value != comparison_value
elif operator == "contains":
return comparison_value in input_value
elif operator == "starts with":
return input_value.startswith(comparison_value)
elif operator == "ends with":
return input_value.endswith(comparison_value)
return False
def pass_through(self) -> Text:
input_value = self.input_value
comparison_value = self.comparison_value
operator = self.operator
value_to_pass = self.value_to_pass
case_sensitive = self.case_sensitive
if self.evaluate_condition(input_value, comparison_value, operator, case_sensitive):
self.status = value_to_pass
return value_to_pass
else:
self.status = ""
return ""

View file

@ -0,0 +1,30 @@
from langchain_core.messages import BaseMessage
from langchain_core.prompts import PromptTemplate
from langflow.custom import CustomComponent
from langflow.field_typing import LanguageModel, Text
class ShouldRunNextComponent(CustomComponent):
display_name = "Should Run Next"
description = "Determines if a vertex is runnable."
def build(self, llm: LanguageModel, question: str, context: str, retries: int = 3) -> Text:
template = "Given the following question and the context below, answer with a yes or no.\n\n{error_message}\n\nQuestion: {question}\n\nContext: {context}\n\nAnswer:"
prompt = PromptTemplate.from_template(template)
chain = prompt | llm
error_message = ""
for i in range(retries):
result = chain.invoke(dict(question=question, context=context, error_message=error_message))
if isinstance(result, BaseMessage):
content = result.content
elif isinstance(result, str):
content = result
if isinstance(content, str) and content.lower().strip() in ["yes", "no"]:
break
condition = str(content).lower().strip() == "yes"
self.status = f"Should Run Next: {condition}"
if condition is False:
self.stop()
return context

View file

@ -0,0 +1,69 @@
from typing import List
from langchain_text_splitters import CharacterTextSplitter
from langflow.custom import Component
from langflow.io import HandleInput, IntInput, Output, TextInput
from langflow.schema import Data
from langflow.utils.util import unescape_string
class SplitTextComponent(Component):
display_name: str = "Split Text"
description: str = "Split text into chunks based on specified criteria."
icon = "scissors-line-dashed"
inputs = [
HandleInput(
name="data_inputs",
display_name="Data Inputs",
info="The data to split.",
input_types=["Data"],
is_list=True,
),
IntInput(
name="chunk_overlap",
display_name="Chunk Overlap",
info="Number of characters to overlap between chunks.",
value=200,
),
IntInput(
name="chunk_size",
display_name="Chunk Size",
info="The maximum number of characters in each chunk.",
value=1000,
),
TextInput(
name="separator",
display_name="Separator",
info="The character to split on. Defaults to newline.",
value="\n",
),
]
outputs = [
Output(display_name="Chunks", name="chunks", method="split_text"),
]
def _docs_to_data(self, docs):
data = []
for doc in docs:
data.append(Data(text=doc.page_content, data=doc.metadata))
return data
def split_text(self) -> List[Data]:
separator = unescape_string(self.separator)
documents = []
for _input in self.data_inputs:
if isinstance(_input, Data):
documents.append(_input.to_lc_document())
splitter = CharacterTextSplitter(
chunk_overlap=self.chunk_overlap,
chunk_size=self.chunk_size,
separator=separator,
)
docs = splitter.split_documents(documents)
data = self._docs_to_data(docs)
self.status = data
return data

View file

@ -0,0 +1,22 @@
from langflow.custom import CustomComponent
from langflow.memory import get_messages, store_message
from langflow.schema.message import Message
class StoreMessageComponent(CustomComponent):
display_name = "Store Message"
description = "Stores a chat message."
def build_config(self):
return {
"message": {"display_name": "Message"},
}
def build(
self,
message: Message,
) -> Message:
store_message(message, flow_id=self.graph.flow_id)
self.status = get_messages()
return message

View file

@ -0,0 +1,115 @@
from typing import Any, List, Optional
from langflow.base.flow_processing.utils import build_data_from_result_data
from langflow.custom import CustomComponent
from langflow.graph.graph.base import Graph
from langflow.graph.schema import RunOutputs
from langflow.graph.vertex.base import Vertex
from langflow.helpers.flow import get_flow_inputs
from langflow.schema import Data
from langflow.schema.dotdict import dotdict
from langflow.template.field.base import Input
from loguru import logger
class SubFlowComponent(CustomComponent):
display_name = "Sub Flow"
description = (
"Dynamically Generates a Component from a Flow. The output is a list of data with keys 'result' and 'message'."
)
beta: bool = True
field_order = ["flow_name"]
def get_flow_names(self) -> List[str]:
flow_datas = self.list_flows()
return [flow_data.data["name"] for flow_data in flow_datas]
def get_flow(self, flow_name: str) -> Optional[Data]:
flow_datas = self.list_flows()
for flow_data in flow_datas:
if flow_data.data["name"] == flow_name:
return flow_data
return None
def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None):
logger.debug(f"Updating build config with field value {field_value} and field name {field_name}")
if field_name == "flow_name":
build_config["flow_name"]["options"] = self.get_flow_names()
# Clean up the build config
for key in list(build_config.keys()):
if key not in self.field_order + ["code", "_type", "get_final_results_only"]:
del build_config[key]
if field_value is not None and field_name == "flow_name":
try:
flow_data = self.get_flow(field_value)
if not flow_data:
raise ValueError(f"Flow {field_value} not found.")
graph = Graph.from_payload(flow_data.data["data"])
# Get all inputs from the graph
inputs = get_flow_inputs(graph)
# Add inputs to the build config
build_config = self.add_inputs_to_build_config(inputs, build_config)
except Exception as e:
logger.error(f"Error getting flow {field_value}: {str(e)}")
return build_config
def add_inputs_to_build_config(self, inputs: List[Vertex], build_config: dotdict):
new_fields: list[Input] = []
for vertex in inputs:
field = Input(
display_name=vertex.display_name,
name=vertex.id,
info=vertex.description,
field_type="str",
value=None,
)
new_fields.append(field)
logger.debug(new_fields)
for field in new_fields:
build_config[field.name] = field.to_dict()
return build_config
def build_config(self):
return {
"input_value": {
"display_name": "Input Value",
"multiline": True,
},
"flow_name": {
"display_name": "Flow Name",
"info": "The name of the flow to run.",
"options": [],
"real_time_refresh": True,
"refresh_button": True,
},
"tweaks": {
"display_name": "Tweaks",
"info": "Tweaks to apply to the flow.",
},
"get_final_results_only": {
"display_name": "Get Final Results Only",
"info": "If False, the output will contain all outputs from the flow.",
"advanced": True,
},
}
async def build(self, flow_name: str, get_final_results_only: bool = True, **kwargs) -> List[Data]:
tweaks = {key: {"input_value": value} for key, value in kwargs.items()}
run_outputs: List[Optional[RunOutputs]] = await self.run_flow(
tweaks=tweaks,
flow_name=flow_name,
)
if not run_outputs:
return []
run_output = run_outputs[0]
data = []
if run_output is not None:
for output in run_output.outputs:
if output:
data.extend(build_data_from_result_data(output, get_final_results_only))
self.status = data
logger.debug(data)
return data

View file

@ -0,0 +1,33 @@
from .AgentComponent import AgentComponent
from .ConditionalRouter import ConditionalRouterComponent
from .ExtractKeyFromData import ExtractKeyFromDataComponent
from .FlowTool import FlowToolComponent
from .Listen import ListenComponent
from .ListFlows import ListFlowsComponent
from .MergeData import MergeDataComponent
from .Notify import NotifyComponent
from .PythonFunction import PythonFunctionComponent
from .RunFlow import RunFlowComponent
from .RunnableExecutor import RunnableExecComponent
from .SelectivePassThrough import SelectivePassThroughComponent
from .SplitText import SplitTextComponent
from .SQLExecutor import SQLExecutorComponent
from .SubFlow import SubFlowComponent
__all__ = [
"AgentComponent",
"ConditionalRouterComponent",
"ExtractKeyFromDataComponent",
"FlowToolComponent",
"ListenComponent",
"ListFlowsComponent",
"MergeDataComponent",
"NotifyComponent",
"PythonFunctionComponent",
"RunFlowComponent",
"RunnableExecComponent",
"SplitTextComponent",
"SQLExecutorComponent",
"SubFlowComponent",
"SelectivePassThroughComponent",
]

View file

@ -9,6 +9,7 @@ class FilterDataComponent(Component):
display_name = "Filter Data"
description = "Filters a Data object based on a list of keys."
icon = "filter"
beta = True
inputs = [
DataInput(

View file

@ -5,14 +5,12 @@ from langflow.custom import CustomComponent
class UUIDGeneratorComponent(CustomComponent):
documentation: str = "http://docs.langflow.org/components/custom"
display_name = "ID Generator"
description = "Generates a unique ID."
def update_build_config(
self,
build_config: dict,
field_value: Any,
field_name: Optional[str] = None,
):
if field_name == "unique_id":

View file

@ -0,0 +1,26 @@
from langflow.custom import CustomComponent
from langflow.schema import Data
class MergeDataComponent(CustomComponent):
display_name = "Merge Data"
description = "Combines multiple data sources into a single unified Data object."
beta: bool = True
field_config = {
"data": {"display_name": "Data"},
}
def build(self, data: list[Data]) -> Data:
if not data:
return Data()
if len(data) == 1:
return data[0]
merged_data = Data()
for value in data:
if merged_data is None:
merged_data = value
else:
merged_data += value
self.status = merged_data
return merged_data

View file

@ -0,0 +1,70 @@
from typing import List
from langchain_text_splitters import CharacterTextSplitter
from langflow.custom import Component
from langflow.io import HandleInput, IntInput, MessageTextInput, Output
from langflow.schema import Data
from langflow.utils.util import unescape_string
class SplitTextComponent(Component):
display_name: str = "Split Text"
description: str = "Split text into chunks based on specified criteria."
icon = "scissors-line-dashed"
inputs = [
HandleInput(
name="data_inputs",
display_name="Data Inputs",
info="The data to split.",
input_types=["Data"],
is_list=True,
),
IntInput(
name="chunk_overlap",
display_name="Chunk Overlap",
info="Number of characters to overlap between chunks.",
value=200,
),
IntInput(
name="chunk_size",
display_name="Chunk Size",
info="The maximum number of characters in each chunk.",
value=1000,
),
MessageTextInput(
name="separator",
display_name="Separator",
info="The character to split on. Defaults to newline.",
value="\n",
),
]
outputs = [
Output(display_name="Chunks", name="chunks", method="split_text"),
]
def _docs_to_data(self, docs):
data = []
for doc in docs:
data.append(Data(text=doc.page_content, data=doc.metadata))
return data
def split_text(self) -> List[Data]:
separator = unescape_string(self.separator)
documents = []
for _input in self.data_inputs:
if isinstance(_input, Data):
documents.append(_input.to_lc_document())
splitter = CharacterTextSplitter(
chunk_overlap=self.chunk_overlap,
chunk_size=self.chunk_size,
separator=separator,
)
docs = splitter.split_documents(documents)
data = self._docs_to_data(docs)
self.status = data
return data

View file

@ -0,0 +1,22 @@
from langflow.custom import CustomComponent
from langflow.memory import get_messages, store_message
from langflow.schema.message import Message
class StoreMessageComponent(CustomComponent):
display_name = "Store Message"
description = "Stores a chat message."
def build_config(self):
return {
"message": {"display_name": "Message"},
}
def build(
self,
message: Message,
) -> Message:
store_message(message, flow_id=self.graph.flow_id)
self.status = get_messages()
return message

Some files were not shown because too many files have changed in this diff Show more