Update docs (#1567)

* Add new documentation files and update package dependencies

* Refactor tweak application logic in process_tweaks function

* Add dynamic function creation and execution helpers

* Refactor build method to be asynchronous

* Add FlowToolComponent to handle flows as tools

* Update RunFlowComponent to include a method for updating build config

* Fix duplicated first layer results

* Refactor vertex building and streaming endpoints

* Add base_name attribute to Vertex class

* Refactor flow.py to generate dynamic flow functions and build schemas

* Refactor FlowToolComponent in FlowTool.py

* Add JSONInputComponent to load JSON object as input

* Update render_tool_description method in XMLAgent.py

* Refactor XMLAgentComponent.render_tool_description() method

* Refactor SearchApi.py to include typing and handle empty records

* Refactor SearchApi class to simplify code

* Add SearchApi and SearchApiTool components

* Refactor ServiceFactory and Dependencies (#1560)

* Update dependencies for OpenTelemetry

* Update service dependency logic and add first version of telemetry service

* Remove telemetry service and related code

* Update cache service references

* Refactor imports in env.py

* Refactor code for initializing services and socketio server

* Refactor parameterComponent to use inline button_text

* Refactor build_vertex method and add RunnableVerticesManager class

* Add import statement and update build_vertex function

* Add import statement for SettingsService in MonitorServiceFactory.create() method

* Refactor build_schema_from_inputs to use display_name and description for field names and descriptions respectively

* Refactor graph building and running logic

* Update input type mappings and function arguments

* Update default values for input types in flow.py

* Remove console.log statement in flowStore.ts

* Add vertices_to_run field to VerticesOrderResponse

* Add input_value parameter to chain components

* Refactor CSVAgent build method to include handle_parse_errors parameter

* Add agent_type parameter to CSVAgent build method

* Update model imports in component files

* Add LCAgentComponent and XMLAgentComponent

* Add "agents" category to NATIVE_CATEGORIES

* Refactor model.py to support chat models

* Add system_message parameter to model components

* Update CSVAgent.py: handle_parsing_errors and agent_type options

* Add ping animation to update button

* Fix encryption and decryption of API keys

* Update CSVAgentComponent constructor

* Refactor inputs parameter to inputs_dict in build_vertex function

* Removes "component" table and drops "flowstyle" table

* Delete component model and init files

* Removes "flowstyle" table and drops "user" table index

* Add typing import to CohereModel.py

* Fix ShareModal rendering issue

* Update models docs

* Changed vector-stores docs

* Update component documentation

* Add AstraDB and AstraDBSearch components for AstraDB Vector Store docs

* Rename GetNotified to Listen

* Update GetNotifiedComponent import

* Remove unused imports in flow-runner.mdx and features.mdx

* Add new documentation files and update existing files

* Update package versions in package-lock.json

* Remove unused files

* Delete run-flow.mdx file

* Update topics

* Add new file run-flow.mdx

---------

Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai>
Co-authored-by: anovazzi1 <otavio2204@gmail.com>
This commit is contained in:
Carlos Coelho 2024-03-26 13:55:54 -03:00 • committed by GitHub
commit 2587849fea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 1733 additions and 245 deletions

View file

@ -2,9 +2,9 @@ from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record
class GetNotifiedComponent(CustomComponent):
display_name = "Get Notified"
description = "A component to get notified by Notify component."
class ListenComponent(CustomComponent):
display_name = "Listen"
description = "A component to listen for a notification."
beta: bool = True
def build_config(self):

View file

@ -1,6 +1,6 @@
from .ClearMessageHistory import ClearMessageHistoryComponent
from .ExtractDataFromRecord import ExtractKeyFromRecordComponent
from .GetNotified import GetNotifiedComponent
from .Listen import GetNotifiedComponent
from .ListFlows import ListFlowsComponent
from .MergeRecords import MergeRecordsComponent
from .Notify import NotifyComponent

View file

@ -106,7 +106,9 @@ def initialize_session_service():
Initialize the session manager.
"""
from langflow.services.cache import factory as cache_factory
from langflow.services.session import factory as session_service_factory # type: ignore
from langflow.services.session import (
factory as session_service_factory,
) # type: ignore
initialize_settings_service()

View file

@ -0,0 +1,70 @@
from typing import List, Union
from langchain.agents import AgentExecutor, BaseMultiActionAgent, BaseSingleActionAgent
from langflow import CustomComponent
from langflow.field_typing import BaseMemory, Text, Tool
class LCAgentComponent(CustomComponent):
def build_config(self):
return {
"lc": {
"display_name": "LangChain",
"info": "The LangChain to interact with.",
},
"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,
},
"output_key": {
"display_name": "Output Key",
"info": "The key to use to get the output from the agent.",
"advanced": True,
},
"memory": {
"display_name": "Memory",
"info": "Memory to use for the agent.",
},
"tools": {
"display_name": "Tools",
"info": "Tools the agent can use.",
},
"input_value": {
"display_name": "Input",
"info": "Input text to pass to the agent.",
},
}
async def run_agent(
self,
agent: Union[BaseSingleActionAgent, BaseMultiActionAgent, AgentExecutor],
inputs: str,
input_variables: list[str],
tools: List[Tool],
memory: BaseMemory = None,
handle_parsing_errors: bool = True,
output_key: str = "output",
) -> Text:
if isinstance(agent, AgentExecutor):
runnable = agent
else:
runnable = AgentExecutor.from_agent_and_tools(
agent=agent, tools=tools, verbose=True, memory=memory, handle_parsing_errors=handle_parsing_errors
)
input_dict = {"input": inputs}
for var in input_variables:
if var not in ["agent_scratchpad", "input"]:
input_dict[var] = ""
result = await runnable.ainvoke(input_dict)
self.status = result
if output_key in result:
return result.get(output_key)
elif "output" not in result:
if output_key != "output":
raise ValueError(f"Output key not found in result. Tried '{output_key}' and 'output'.")
else:
raise ValueError("Output key not found in result. Tried 'output'.")
return result.get("output")

View file

@ -0,0 +1,3 @@
from .model import LCModelComponent
__all__ = ["LCModelComponent"]

View file

@ -0,0 +1,48 @@
from typing import Optional
from langchain_core.language_models.chat_models import BaseChatModel
from langchain_core.language_models.llms import LLM
from langchain_core.messages import HumanMessage, SystemMessage
from langflow import CustomComponent
class LCModelComponent(CustomComponent):
display_name: str = "Model Name"
description: str = "Model Description"
def get_result(self, runnable: LLM, stream: bool, input_value: str):
"""
Retrieves the result from the output of a Runnable object.
Args:
output (Runnable): The output object to retrieve the result from.
stream (bool): Indicates whether to use streaming or invocation mode.
input_value (str): The input value to pass to the output object.
Returns:
The result obtained from the output object.
"""
if stream:
result = runnable.stream(input_value)
else:
message = runnable.invoke(input_value)
result = message.content if hasattr(message, "content") else message
self.status = result
return result
def get_chat_result(
self, runnable: BaseChatModel, stream: bool, input_value: str, system_message: Optional[str] = None
):
messages = []
if input_value:
messages.append(HumanMessage(input_value))
if system_message:
messages.append(SystemMessage(system_message))
if stream:
result = runnable.stream(messages)
else:
message = runnable.invoke(messages)
result = message.content
self.status = result
return result

View file

@ -0,0 +1,85 @@
from typing import Any, List, Optional, Text
from langchain_core.tools import StructuredTool
from loguru import logger
from langflow import CustomComponent
from langflow.field_typing import Tool
from langflow.graph.graph.base import Graph
from langflow.helpers.flow import build_function_and_schema
from langflow.schema.dotdict import dotdict
class FlowToolComponent(CustomComponent):
display_name = "Flow as Tool"
description = "Construct a Tool from a function that runs the loaded Flow."
field_order = ["flow_name", "name", "description", "return_direct"]
def get_flow_names(self) -> List[str]:
flow_records = self.list_flows()
return [flow_record.data["name"] for flow_record in flow_records]
def get_flow(self, flow_name: str) -> Optional[Text]:
"""
Retrieves a flow by its name.
Args:
flow_name (str): The name of the flow to retrieve.
Returns:
Optional[Text]: The flow record if found, None otherwise.
"""
flow_records = self.list_flows()
for flow_record in flow_records:
if flow_record.data["name"] == flow_name:
return flow_record
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()
return build_config
def build_config(self):
return {
"flow_name": {
"display_name": "Flow Name",
"info": "The name of the flow to run.",
"options": [],
"real_time_refresh": True,
"refresh_button": True,
},
"name": {
"display_name": "Name",
"description": "The name of the tool.",
},
"description": {
"display_name": "Description",
"description": "The description of the tool.",
},
"return_direct": {
"display_name": "Return Direct",
"description": "Return the result directly from the Tool.",
"advanced": True,
},
}
async def build(self, flow_name: str, name: str, description: str, return_direct: bool = False) -> Tool:
flow_record = self.get_flow(flow_name)
if not flow_record:
raise ValueError("Flow not found.")
graph = Graph.from_payload(flow_record.data["data"])
dynamic_flow_function, schema = build_function_and_schema(flow_record, graph)
tool = StructuredTool.from_function(
coroutine=dynamic_flow_function,
name=name,
description=description,
return_direct=return_direct,
args_schema=schema,
)
description_repr = repr(tool.description).strip("'")
args_str = "\n".join([f"- {arg_name}: {arg_data['description']}" for arg_name, arg_data in tool.args.items()])
self.status = f"{description_repr}\nArguments:\n{args_str}"
return tool

View file

@ -0,0 +1,37 @@
from langchain_community.tools.searchapi import SearchAPIRun
from langchain_community.utilities.searchapi import SearchApiAPIWrapper
from langflow import CustomComponent
from langflow.field_typing import Tool
class SearchApiToolComponent(CustomComponent):
display_name: str = "SearchApi Tool"
description: str = "Real-time search engine results API."
documentation: str = "https://www.searchapi.io/docs/google"
field_config = {
"engine": {
"display_name": "Engine",
"field_type": "str",
"info": "The search engine to use.",
},
"api_key": {
"display_name": "API Key",
"field_type": "str",
"required": True,
"password": True,
"info": "The API key to use SearchApi.",
},
}
def build(
self,
engine: str,
api_key: str,
) -> Tool:
search_api_wrapper = SearchApiAPIWrapper(engine=engine, searchapi_api_key=api_key)
tool = SearchAPIRun(api_wrapper=search_api_wrapper)
self.status = tool
return tool