parent
60b1927cc5
commit
0b39554795
57 changed files with 351 additions and 359 deletions
|
|
@ -584,8 +584,8 @@ async def custom_component(
|
|||
if raw_code.frontend_node is not None:
|
||||
built_frontend_node = component_instance.post_code_processing(built_frontend_node, raw_code.frontend_node)
|
||||
|
||||
_type = get_instance_name(component_instance)
|
||||
return CustomComponentResponse(data=built_frontend_node, type=_type)
|
||||
type_ = get_instance_name(component_instance)
|
||||
return CustomComponentResponse(data=built_frontend_node, type=type_)
|
||||
|
||||
|
||||
@router.post("/custom_component/update", status_code=HTTPStatus.OK)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ async def create_variable(
|
|||
name=variable.name,
|
||||
value=variable.value,
|
||||
default_fields=variable.default_fields or [],
|
||||
_type=variable.type or GENERIC_TYPE,
|
||||
type_=variable.type or GENERIC_TYPE,
|
||||
session=session,
|
||||
)
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -174,16 +174,16 @@ class BaseCrewComponent(Component):
|
|||
self,
|
||||
) -> Callable:
|
||||
def step_callback(agent_output: AgentFinish | list[tuple[AgentAction, str]]) -> None:
|
||||
_id = self._vertex.id if self._vertex else self.display_name
|
||||
id_ = self._vertex.id if self._vertex else self.display_name
|
||||
if isinstance(agent_output, AgentFinish):
|
||||
messages = agent_output.messages
|
||||
self.log(cast("dict", messages[0].to_json()), name=f"Finish (Agent: {_id})")
|
||||
self.log(cast("dict", messages[0].to_json()), name=f"Finish (Agent: {id_})")
|
||||
elif isinstance(agent_output, list):
|
||||
_messages_dict = {f"Action {i}": action.messages for i, (action, _) in enumerate(agent_output)}
|
||||
messages_dict_ = {f"Action {i}": action.messages for i, (action, _) in enumerate(agent_output)}
|
||||
# Serialize the messages with to_json() to avoid issues with circular references
|
||||
serializable_dict = {k: [m.to_json() for m in v] for k, v in _messages_dict.items()}
|
||||
serializable_dict = {k: [m.to_json() for m in v] for k, v in messages_dict_.items()}
|
||||
messages_dict = {k: v[0] if len(v) == 1 else v for k, v in serializable_dict.items()}
|
||||
self.log(messages_dict, name=f"Step (Agent: {_id})")
|
||||
self.log(messages_dict, name=f"Step (Agent: {id_})")
|
||||
|
||||
return step_callback
|
||||
|
||||
|
|
|
|||
|
|
@ -108,15 +108,15 @@ def partition_file_to_data(file_path: str, *, silent_errors: bool) -> Data | Non
|
|||
|
||||
|
||||
def read_text_file(file_path: str) -> str:
|
||||
_file_path = Path(file_path)
|
||||
raw_data = _file_path.read_bytes()
|
||||
file_path_ = Path(file_path)
|
||||
raw_data = file_path_.read_bytes()
|
||||
result = chardet.detect(raw_data)
|
||||
encoding = result["encoding"]
|
||||
|
||||
if encoding in {"Windows-1252", "Windows-1254", "MacRoman"}:
|
||||
encoding = "utf-8"
|
||||
|
||||
return _file_path.read_text(encoding=encoding)
|
||||
return file_path_.read_text(encoding=encoding)
|
||||
|
||||
|
||||
def read_docx_file(file_path: str) -> str:
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ class ChatComponent(Component):
|
|||
def get_properties_from_source_component(self):
|
||||
if hasattr(self, "_vertex") and hasattr(self._vertex, "incoming_edges") and self._vertex.incoming_edges:
|
||||
source_id = self._vertex.incoming_edges[0].source_id
|
||||
_source_vertex = self.graph.get_vertex(source_id)
|
||||
component = _source_vertex.custom_component
|
||||
source_vertex = self.graph.get_vertex(source_id)
|
||||
component = source_vertex.custom_component
|
||||
source = component.display_name
|
||||
icon = component.icon
|
||||
possible_attributes = ["model_name", "model_id", "model"]
|
||||
|
|
|
|||
|
|
@ -30,12 +30,12 @@ if TYPE_CHECKING:
|
|||
TOOL_TYPES_SET = {"Tool", "BaseTool", "StructuredTool"}
|
||||
|
||||
|
||||
def _get_input_type(_input: InputTypes):
|
||||
if _input.input_types:
|
||||
if len(_input.input_types) == 1:
|
||||
return _input.input_types[0]
|
||||
return " | ".join(_input.input_types)
|
||||
return _input.field_type
|
||||
def _get_input_type(input_: InputTypes):
|
||||
if input_.input_types:
|
||||
if len(input_.input_types) == 1:
|
||||
return input_.input_types[0]
|
||||
return " | ".join(input_.input_types)
|
||||
return input_.field_type
|
||||
|
||||
|
||||
def build_description(component: Component, output: Output) -> str:
|
||||
|
|
|
|||
|
|
@ -87,14 +87,14 @@ class StructuredOutputComponent(Component):
|
|||
msg = "Output schema cannot be empty"
|
||||
raise ValueError(msg)
|
||||
|
||||
_output_model = build_model_from_schema(self.output_schema)
|
||||
output_model_ = build_model_from_schema(self.output_schema)
|
||||
if self.multiple:
|
||||
output_model = create_model(
|
||||
self.schema_name,
|
||||
objects=(list[_output_model], Field(description=f"A list of {self.schema_name}.")), # type: ignore[valid-type]
|
||||
objects=(list[output_model_], Field(description=f"A list of {self.schema_name}.")), # type: ignore[valid-type]
|
||||
)
|
||||
else:
|
||||
output_model = _output_model
|
||||
output_model = output_model_
|
||||
try:
|
||||
llm_with_structured_output = cast("LanguageModel", self.llm).with_structured_output(schema=output_model) # type: ignore[valid-type, attr-defined]
|
||||
|
||||
|
|
|
|||
|
|
@ -79,9 +79,9 @@ class ChatInput(ChatComponent):
|
|||
]
|
||||
|
||||
async def message_response(self) -> Message:
|
||||
_background_color = self.background_color
|
||||
_text_color = self.text_color
|
||||
_icon = self.chat_icon
|
||||
background_color = self.background_color
|
||||
text_color = self.text_color
|
||||
icon = self.chat_icon
|
||||
|
||||
message = await Message.create(
|
||||
text=self.input_value,
|
||||
|
|
@ -89,7 +89,7 @@ class ChatInput(ChatComponent):
|
|||
sender_name=self.sender_name,
|
||||
session_id=self.session_id,
|
||||
files=self.files,
|
||||
properties={"background_color": _background_color, "text_color": _text_color, "icon": _icon},
|
||||
properties={"background_color": background_color, "text_color": text_color, "icon": icon},
|
||||
)
|
||||
if self.session_id and isinstance(message, Message) and self.should_store_message:
|
||||
stored_message = await self.send_message(
|
||||
|
|
|
|||
|
|
@ -123,8 +123,8 @@ class RunnableExecComponent(Component):
|
|||
if self.use_stream:
|
||||
return self.astream_events(input_dict)
|
||||
result = await self.runnable.ainvoke(input_dict)
|
||||
result_value, _status = self.get_output(result, self.input_key, self.output_key)
|
||||
status += _status
|
||||
result_value, status_ = self.get_output(result, self.input_key, self.output_key)
|
||||
status += status_
|
||||
status += f"\n\nOutput: {result_value}\n\nRaw Output: {result}"
|
||||
self.status = status
|
||||
return result_value
|
||||
|
|
|
|||
|
|
@ -80,10 +80,10 @@ class ChatOutput(ChatComponent):
|
|||
),
|
||||
]
|
||||
|
||||
def _build_source(self, _id: str | None, display_name: str | None, source: str | None) -> Source:
|
||||
def _build_source(self, id_: str | None, display_name: str | None, source: str | None) -> Source:
|
||||
source_dict = {}
|
||||
if _id:
|
||||
source_dict["id"] = _id
|
||||
if id_:
|
||||
source_dict["id"] = id_
|
||||
if display_name:
|
||||
source_dict["display_name"] = display_name
|
||||
if source:
|
||||
|
|
@ -91,20 +91,20 @@ class ChatOutput(ChatComponent):
|
|||
return Source(**source_dict)
|
||||
|
||||
async def message_response(self) -> Message:
|
||||
_source, _icon, _display_name, _source_id = self.get_properties_from_source_component()
|
||||
_background_color = self.background_color
|
||||
_text_color = self.text_color
|
||||
source, icon, display_name, source_id = self.get_properties_from_source_component()
|
||||
background_color = self.background_color
|
||||
text_color = self.text_color
|
||||
if self.chat_icon:
|
||||
_icon = self.chat_icon
|
||||
icon = self.chat_icon
|
||||
message = self.input_value if isinstance(self.input_value, Message) else Message(text=self.input_value)
|
||||
message.sender = self.sender
|
||||
message.sender_name = self.sender_name
|
||||
message.session_id = self.session_id
|
||||
message.flow_id = self.graph.flow_id if hasattr(self, "graph") else None
|
||||
message.properties.source = self._build_source(_source_id, _display_name, _source)
|
||||
message.properties.icon = _icon
|
||||
message.properties.background_color = _background_color
|
||||
message.properties.text_color = _text_color
|
||||
message.properties.source = self._build_source(source_id, display_name, source)
|
||||
message.properties.icon = icon
|
||||
message.properties.background_color = background_color
|
||||
message.properties.text_color = text_color
|
||||
if self.session_id and isinstance(message, Message) and self.should_store_message:
|
||||
stored_message = await self.send_message(
|
||||
message,
|
||||
|
|
|
|||
|
|
@ -95,10 +95,10 @@ class CreateDataComponent(Component):
|
|||
for value_dict in self._attributes.values():
|
||||
if isinstance(value_dict, dict):
|
||||
# Check if the value of the value_dict is a Data
|
||||
_value_dict = {
|
||||
value_dict_ = {
|
||||
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 data
|
||||
|
||||
def validate_text_key(self) -> None:
|
||||
|
|
|
|||
|
|
@ -94,9 +94,9 @@ class AstraDBToolComponent(LCToolComponent):
|
|||
if self._cached_collection:
|
||||
return self._cached_collection
|
||||
|
||||
_cached_client = DataAPIClient(self.token)
|
||||
_cached_db = _cached_client.get_database(self.api_endpoint, namespace=self.namespace)
|
||||
self._cached_collection = _cached_db.get_collection(self.collection_name)
|
||||
cached_client = DataAPIClient(self.token)
|
||||
cached_db = cached_client.get_database(self.api_endpoint, namespace=self.namespace)
|
||||
self._cached_collection = cached_db.get_collection(self.collection_name)
|
||||
return self._cached_collection
|
||||
|
||||
def create_args_schema(self) -> dict[str, BaseModel]:
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ class PythonCodeStructuredTool(LCToolComponent):
|
|||
return build_config
|
||||
|
||||
async def build_tool(self) -> Tool:
|
||||
_local_namespace = {} # type: ignore[var-annotated]
|
||||
local_namespace = {} # type: ignore[var-annotated]
|
||||
modules = self._find_imports(self.tool_code)
|
||||
import_code = ""
|
||||
for module in modules["imports"]:
|
||||
|
|
@ -154,7 +154,7 @@ class PythonCodeStructuredTool(LCToolComponent):
|
|||
f"from {from_module.module} import {', '.join([alias.name for alias in from_module.names])}\n"
|
||||
)
|
||||
exec(import_code, globals())
|
||||
exec(self.tool_code, globals(), _local_namespace)
|
||||
exec(self.tool_code, globals(), local_namespace)
|
||||
|
||||
class PythonCodeToolFunc:
|
||||
params: dict = {}
|
||||
|
|
@ -163,23 +163,23 @@ class PythonCodeStructuredTool(LCToolComponent):
|
|||
for key, arg in kwargs.items():
|
||||
if key not in PythonCodeToolFunc.params:
|
||||
PythonCodeToolFunc.params[key] = arg
|
||||
return _local_namespace[self.tool_function](**PythonCodeToolFunc.params)
|
||||
return local_namespace[self.tool_function](**PythonCodeToolFunc.params)
|
||||
|
||||
_globals = globals()
|
||||
_local = {}
|
||||
_local[self.tool_function] = PythonCodeToolFunc
|
||||
_globals.update(_local)
|
||||
globals_ = globals()
|
||||
local = {}
|
||||
local[self.tool_function] = PythonCodeToolFunc
|
||||
globals_.update(local)
|
||||
|
||||
if isinstance(self.global_variables, list):
|
||||
for data in self.global_variables:
|
||||
if isinstance(data, Data):
|
||||
_globals.update(data.data)
|
||||
globals_.update(data.data)
|
||||
elif isinstance(self.global_variables, dict):
|
||||
_globals.update(self.global_variables)
|
||||
globals_.update(self.global_variables)
|
||||
|
||||
classes = json.loads(self._attributes["_classes"])
|
||||
for class_dict in classes:
|
||||
exec("\n".join(class_dict["code"]), _globals)
|
||||
exec("\n".join(class_dict["code"]), globals_)
|
||||
|
||||
named_functions = json.loads(self._attributes["_functions"])
|
||||
schema_fields = {}
|
||||
|
|
@ -199,8 +199,8 @@ class PythonCodeStructuredTool(LCToolComponent):
|
|||
field_description = self._get_value(self._attributes[attr], str)
|
||||
|
||||
if field_annotation:
|
||||
exec(f"temp_annotation_type = {field_annotation}", _globals)
|
||||
schema_annotation = _globals["temp_annotation_type"]
|
||||
exec(f"temp_annotation_type = {field_annotation}", globals_)
|
||||
schema_annotation = globals_["temp_annotation_type"]
|
||||
else:
|
||||
schema_annotation = Any
|
||||
schema_fields[field_name] = (
|
||||
|
|
@ -211,15 +211,15 @@ class PythonCodeStructuredTool(LCToolComponent):
|
|||
),
|
||||
)
|
||||
|
||||
if "temp_annotation_type" in _globals:
|
||||
_globals.pop("temp_annotation_type")
|
||||
if "temp_annotation_type" in globals_:
|
||||
globals_.pop("temp_annotation_type")
|
||||
|
||||
python_code_tool_schema = None
|
||||
if schema_fields:
|
||||
python_code_tool_schema = create_model("PythonCodeToolSchema", **schema_fields)
|
||||
|
||||
return StructuredTool.from_function(
|
||||
func=_local[self.tool_function].run,
|
||||
func=local[self.tool_function].run,
|
||||
args_schema=python_code_tool_schema,
|
||||
name=self.tool_name,
|
||||
description=self.tool_description,
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ class PythonREPLToolComponent(LCToolComponent):
|
|||
return global_dict
|
||||
|
||||
def build_tool(self) -> Tool:
|
||||
_globals = self.get_globals(self.global_imports)
|
||||
python_repl = PythonREPL(_globals=_globals)
|
||||
globals_ = self.get_globals(self.global_imports)
|
||||
python_repl = PythonREPL(_globals=globals_)
|
||||
|
||||
def run_python_code(code: str) -> str:
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -121,10 +121,10 @@ class SearXNGToolComponent(LCToolComponent):
|
|||
SearxSearch._headers = self.search_headers.copy()
|
||||
SearxSearch._max_results = self.max_results
|
||||
|
||||
_globals = globals()
|
||||
_local = {}
|
||||
_local["SearxSearch"] = SearxSearch
|
||||
_globals.update(_local)
|
||||
globals_ = globals()
|
||||
local = {}
|
||||
local["SearxSearch"] = SearxSearch
|
||||
globals_.update(local)
|
||||
|
||||
schema_fields = {
|
||||
"query": (str, Field(..., description="The query to search for.")),
|
||||
|
|
@ -137,7 +137,7 @@ class SearXNGToolComponent(LCToolComponent):
|
|||
searx_search_schema = create_model("SearxSearchSchema", **schema_fields)
|
||||
|
||||
return StructuredTool.from_function(
|
||||
func=_local["SearxSearch"].search,
|
||||
func=local["SearxSearch"].search,
|
||||
args_schema=searx_search_schema,
|
||||
name="searxng_search_tool",
|
||||
description="A tool that searches for tools using SearXNG.\nThe available categories are: "
|
||||
|
|
|
|||
|
|
@ -134,19 +134,19 @@ class ChromaVectorStoreComponent(LCVectorStoreComponent):
|
|||
self.status = ""
|
||||
return
|
||||
|
||||
_stored_documents_without_id = []
|
||||
stored_documents_without_id = []
|
||||
if self.allow_duplicates:
|
||||
stored_data = []
|
||||
else:
|
||||
stored_data = chroma_collection_to_data(vector_store.get(limit=self.limit))
|
||||
for value in deepcopy(stored_data):
|
||||
del value.id
|
||||
_stored_documents_without_id.append(value)
|
||||
stored_documents_without_id.append(value)
|
||||
|
||||
documents = []
|
||||
for _input in self.ingest_data or []:
|
||||
if isinstance(_input, Data):
|
||||
if _input not in _stored_documents_without_id:
|
||||
if _input not in stored_documents_without_id:
|
||||
documents.append(_input.to_lc_document())
|
||||
else:
|
||||
msg = "Vector Store Inputs must be Data objects."
|
||||
|
|
|
|||
|
|
@ -417,20 +417,20 @@ class Component(CustomComponent):
|
|||
for index, output in enumerate(frontend_node["outputs"]):
|
||||
if isinstance(output, dict):
|
||||
try:
|
||||
_output = Output(**output)
|
||||
self._set_output_return_type(_output)
|
||||
_output_dict = _output.model_dump()
|
||||
output_ = Output(**output)
|
||||
self._set_output_return_type(output_)
|
||||
output_dict = output_.model_dump()
|
||||
except ValidationError as e:
|
||||
msg = f"Invalid output: {e}"
|
||||
raise ValueError(msg) from e
|
||||
elif isinstance(output, Output):
|
||||
# we need to serialize it
|
||||
self._set_output_return_type(output)
|
||||
_output_dict = output.model_dump()
|
||||
output_dict = output.model_dump()
|
||||
else:
|
||||
msg = f"Invalid output type: {type(output)}"
|
||||
raise TypeError(msg)
|
||||
frontend_node["outputs"][index] = _output_dict
|
||||
frontend_node["outputs"][index] = output_dict
|
||||
return frontend_node
|
||||
|
||||
def update_outputs(self, frontend_node: dict, field_name: str, field_value: Any) -> dict: # noqa: ARG002
|
||||
|
|
@ -557,7 +557,7 @@ class Component(CustomComponent):
|
|||
return getattr(value, output.method)
|
||||
|
||||
def _process_connection_or_parameter(self, key, value) -> None:
|
||||
_input = self._get_or_create_input(key)
|
||||
input_ = self._get_or_create_input(key)
|
||||
# We need to check if callable AND if it is a method from a class that inherits from Component
|
||||
if isinstance(value, Component):
|
||||
# We need to find the Output that can connect to an input of the current component
|
||||
|
|
@ -570,7 +570,7 @@ class Component(CustomComponent):
|
|||
except ValueError as e:
|
||||
msg = f"Method {value.__name__} is not a valid output of {value.__self__.__class__.__name__}"
|
||||
raise ValueError(msg) from e
|
||||
self._connect_to_component(key, value, _input)
|
||||
self._connect_to_component(key, value, input_)
|
||||
else:
|
||||
self._set_parameter_or_attribute(key, value)
|
||||
|
||||
|
|
@ -589,18 +589,18 @@ class Component(CustomComponent):
|
|||
try:
|
||||
return self._inputs[key]
|
||||
except KeyError:
|
||||
_input = self._get_fallback_input(name=key, display_name=key)
|
||||
self._inputs[key] = _input
|
||||
self.inputs.append(_input)
|
||||
return _input
|
||||
input_ = self._get_fallback_input(name=key, display_name=key)
|
||||
self._inputs[key] = input_
|
||||
self.inputs.append(input_)
|
||||
return input_
|
||||
|
||||
def _connect_to_component(self, key, value, _input) -> None:
|
||||
def _connect_to_component(self, key, value, input_) -> None:
|
||||
component = value.__self__
|
||||
self._components.append(component)
|
||||
output = component.get_output_by_method(value)
|
||||
self._add_edge(component, key, output, _input)
|
||||
self._add_edge(component, key, output, input_)
|
||||
|
||||
def _add_edge(self, component, key, output, _input) -> None:
|
||||
def _add_edge(self, component, key, output, input_) -> None:
|
||||
self._edges.append(
|
||||
{
|
||||
"source": component._id,
|
||||
|
|
@ -615,8 +615,8 @@ class Component(CustomComponent):
|
|||
"targetHandle": {
|
||||
"fieldName": key,
|
||||
"id": self._id,
|
||||
"inputTypes": _input.input_types,
|
||||
"type": _input.field_type,
|
||||
"inputTypes": input_.input_types,
|
||||
"type": input_.field_type,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -785,7 +785,7 @@ class Component(CustomComponent):
|
|||
|
||||
def set_attributes(self, params: dict) -> None:
|
||||
self._validate_inputs(params)
|
||||
_attributes = {}
|
||||
attributes = {}
|
||||
for key, value in params.items():
|
||||
if key in self.__dict__ and value != getattr(self, key):
|
||||
msg = (
|
||||
|
|
@ -793,11 +793,11 @@ class Component(CustomComponent):
|
|||
f"that is a reserved word and cannot be used."
|
||||
)
|
||||
raise ValueError(msg)
|
||||
_attributes[key] = value
|
||||
attributes[key] = value
|
||||
for key, input_obj in self._inputs.items():
|
||||
if key not in _attributes and key not in self._attributes:
|
||||
_attributes[key] = input_obj.value or None
|
||||
self._attributes.update(_attributes)
|
||||
if key not in attributes and key not in self._attributes:
|
||||
attributes[key] = input_obj.value or None
|
||||
self._attributes.update(attributes)
|
||||
|
||||
def _set_outputs(self, outputs: list[dict]) -> None:
|
||||
self.outputs = [Output(**output) for output in outputs]
|
||||
|
|
@ -826,10 +826,10 @@ class Component(CustomComponent):
|
|||
inputs = self.get_trace_as_inputs()
|
||||
metadata = self.get_trace_as_metadata()
|
||||
async with self._tracing_service.trace_context(self, self.trace_name, inputs, metadata):
|
||||
_results, _artifacts = await self._build_results()
|
||||
self._tracing_service.set_outputs(self.trace_name, _results)
|
||||
results, artifacts = await self._build_results()
|
||||
self._tracing_service.set_outputs(self.trace_name, results)
|
||||
|
||||
return _results, _artifacts
|
||||
return results, artifacts
|
||||
|
||||
async def _build_without_tracing(self):
|
||||
return await self._build_results()
|
||||
|
|
@ -864,8 +864,8 @@ class Component(CustomComponent):
|
|||
raise
|
||||
|
||||
async def _build_results(self) -> tuple[dict, dict]:
|
||||
_results = {}
|
||||
_artifacts = {}
|
||||
results = {}
|
||||
artifacts = {}
|
||||
if hasattr(self, "_pre_run_setup"):
|
||||
self._pre_run_setup()
|
||||
if hasattr(self, "outputs"):
|
||||
|
|
@ -885,7 +885,7 @@ class Component(CustomComponent):
|
|||
self._current_output = output.name
|
||||
method: Callable = getattr(self, output.method)
|
||||
if output.cache and output.value != UNDEFINED:
|
||||
_results[output.name] = output.value
|
||||
results[output.name] = output.value
|
||||
result = output.value
|
||||
else:
|
||||
# If the method is asynchronous, we need to await it
|
||||
|
|
@ -900,7 +900,7 @@ class Component(CustomComponent):
|
|||
and self._vertex.graph.flow_id is not None
|
||||
):
|
||||
result.set_flow_id(self._vertex.graph.flow_id)
|
||||
_results[output.name] = result
|
||||
results[output.name] = result
|
||||
output.value = result
|
||||
|
||||
custom_repr = self.custom_repr()
|
||||
|
|
@ -927,15 +927,15 @@ class Component(CustomComponent):
|
|||
artifact_type = get_artifact_type(artifact_value, result)
|
||||
raw, artifact_type = post_process_raw(raw, artifact_type)
|
||||
artifact = {"repr": custom_repr, "raw": raw, "type": artifact_type}
|
||||
_artifacts[output.name] = artifact
|
||||
artifacts[output.name] = artifact
|
||||
self._output_logs[output.name] = self._logs
|
||||
self._logs = []
|
||||
self._current_output = ""
|
||||
self._artifacts = _artifacts
|
||||
self._results = _results
|
||||
self._artifacts = artifacts
|
||||
self._results = results
|
||||
if self._tracing_service:
|
||||
self._tracing_service.set_outputs(self.trace_name, _results)
|
||||
return _results, _artifacts
|
||||
self._tracing_service.set_outputs(self.trace_name, results)
|
||||
return results, artifacts
|
||||
|
||||
def custom_repr(self):
|
||||
if self.repr_value == "":
|
||||
|
|
|
|||
|
|
@ -91,34 +91,34 @@ class DirectoryReader:
|
|||
|
||||
def read_file_content(self, file_path):
|
||||
"""Read and return the content of a file."""
|
||||
_file_path = Path(file_path)
|
||||
if not _file_path.is_file():
|
||||
file_path_ = Path(file_path)
|
||||
if not file_path_.is_file():
|
||||
return None
|
||||
try:
|
||||
with _file_path.open(encoding="utf-8") as file:
|
||||
with file_path_.open(encoding="utf-8") as file:
|
||||
# UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 3069:
|
||||
# character maps to <undefined>
|
||||
return file.read()
|
||||
except UnicodeDecodeError:
|
||||
# This is happening in Windows, so we need to open the file in binary mode
|
||||
# The file is always just a python file, so we can safely read it as utf-8
|
||||
with _file_path.open("rb") as f:
|
||||
with file_path_.open("rb") as f:
|
||||
return f.read().decode("utf-8")
|
||||
|
||||
async def aread_file_content(self, file_path):
|
||||
"""Read and return the content of a file."""
|
||||
_file_path = Path(file_path)
|
||||
if not _file_path.is_file():
|
||||
file_path_ = Path(file_path)
|
||||
if not file_path_.is_file():
|
||||
return None
|
||||
try:
|
||||
async with async_open(_file_path, encoding="utf-8") as file:
|
||||
async with async_open(file_path_, encoding="utf-8") as file:
|
||||
# UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 3069:
|
||||
# character maps to <undefined>
|
||||
return await file.read()
|
||||
except UnicodeDecodeError:
|
||||
# This is happening in Windows, so we need to open the file in binary mode
|
||||
# The file is always just a python file, so we can safely read it as utf-8
|
||||
async with async_open(_file_path, "rb") as f:
|
||||
async with async_open(file_path_, "rb") as f:
|
||||
return (await f.read()).decode("utf-8")
|
||||
|
||||
def get_files(self):
|
||||
|
|
@ -227,16 +227,16 @@ class DirectoryReader:
|
|||
logger.debug("-------------------- Building component menu list --------------------")
|
||||
|
||||
for file_path in file_paths:
|
||||
_file_path = Path(file_path)
|
||||
menu_name = _file_path.parent.name
|
||||
filename = _file_path.name
|
||||
file_path_ = Path(file_path)
|
||||
menu_name = file_path_.parent.name
|
||||
filename = file_path_.name
|
||||
validation_result, result_content = self.process_file(file_path)
|
||||
if not validation_result:
|
||||
logger.error(f"Error while processing file {file_path}")
|
||||
|
||||
menu_result = self.find_menu(response, menu_name) or {
|
||||
"name": menu_name,
|
||||
"path": str(_file_path.parent),
|
||||
"path": str(file_path_.parent),
|
||||
"components": [],
|
||||
}
|
||||
component_name = filename.split(".")[0]
|
||||
|
|
@ -307,16 +307,16 @@ class DirectoryReader:
|
|||
results = await asyncio.gather(*tasks)
|
||||
|
||||
for file_path, (validation_result, result_content) in zip(file_paths, results, strict=True):
|
||||
_file_path = Path(file_path)
|
||||
menu_name = _file_path.parent.name
|
||||
filename = _file_path.name
|
||||
file_path_ = Path(file_path)
|
||||
menu_name = file_path_.parent.name
|
||||
filename = file_path_.name
|
||||
|
||||
if not validation_result:
|
||||
logger.error(f"Error while processing file {file_path}")
|
||||
|
||||
menu_result = self.find_menu(response, menu_name) or {
|
||||
"name": menu_name,
|
||||
"path": str(_file_path.parent),
|
||||
"path": str(file_path_.parent),
|
||||
"components": [],
|
||||
}
|
||||
component_name = filename.split(".")[0]
|
||||
|
|
|
|||
|
|
@ -44,15 +44,15 @@ def add_output_types(frontend_node: CustomComponentFrontendNode, return_types: l
|
|||
},
|
||||
)
|
||||
if return_type is str:
|
||||
_return_type = "Text"
|
||||
return_type_ = "Text"
|
||||
elif hasattr(return_type, "__name__"):
|
||||
_return_type = return_type.__name__
|
||||
return_type_ = return_type.__name__
|
||||
elif hasattr(return_type, "__class__"):
|
||||
_return_type = return_type.__class__.__name__
|
||||
return_type_ = return_type.__class__.__name__
|
||||
else:
|
||||
_return_type = str(return_type)
|
||||
return_type_ = str(return_type)
|
||||
|
||||
frontend_node.add_output_type(_return_type)
|
||||
frontend_node.add_output_type(return_type_)
|
||||
|
||||
|
||||
def reorder_fields(frontend_node: CustomComponentFrontendNode, field_order: list[str]) -> None:
|
||||
|
|
@ -200,7 +200,7 @@ def add_extra_fields(frontend_node, field_config, function_args) -> None:
|
|||
"""Add extra fields to the frontend node."""
|
||||
if not function_args:
|
||||
return
|
||||
_field_config = field_config.copy()
|
||||
field_config_ = field_config.copy()
|
||||
function_args_names = [arg["name"] for arg in function_args]
|
||||
# If kwargs is in the function_args and not all field_config keys are in function_args
|
||||
# then we need to add the extra fields
|
||||
|
|
@ -214,7 +214,7 @@ def add_extra_fields(frontend_node, field_config, function_args) -> None:
|
|||
continue
|
||||
|
||||
field_name, field_type, field_value, field_required = get_field_properties(extra_field)
|
||||
config = _field_config.pop(field_name, {})
|
||||
config = field_config_.pop(field_name, {})
|
||||
frontend_node = add_new_custom_field(
|
||||
frontend_node=frontend_node,
|
||||
field_name=field_name,
|
||||
|
|
@ -224,18 +224,18 @@ def add_extra_fields(frontend_node, field_config, function_args) -> None:
|
|||
field_config=config,
|
||||
)
|
||||
if "kwargs" in function_args_names and not all(key in function_args_names for key in field_config):
|
||||
for field_name, config in _field_config.items():
|
||||
for field_name, config in field_config_.items():
|
||||
if "name" not in config or field_name == "code":
|
||||
continue
|
||||
_config = config.model_dump() if isinstance(config, BaseModel) else config
|
||||
_field_name, field_type, field_value, field_required = get_field_properties(extra_field=_config)
|
||||
config_ = config.model_dump() if isinstance(config, BaseModel) else config
|
||||
field_name_, field_type, field_value, field_required = get_field_properties(extra_field=config_)
|
||||
frontend_node = add_new_custom_field(
|
||||
frontend_node=frontend_node,
|
||||
field_name=_field_name,
|
||||
field_name=field_name_,
|
||||
field_type=field_type,
|
||||
field_value=field_value,
|
||||
field_required=field_required,
|
||||
field_config=_config,
|
||||
field_config=config_,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -55,10 +55,10 @@ class EventManager:
|
|||
msg = "Event name must start with 'on_'"
|
||||
raise ValueError(msg)
|
||||
if callback is None:
|
||||
_callback = partial(self.send_event, event_type=event_type)
|
||||
callback_ = partial(self.send_event, event_type=event_type)
|
||||
else:
|
||||
_callback = partial(callback, manager=self, event_type=event_type)
|
||||
self.events[name] = _callback
|
||||
callback_ = partial(callback, manager=self, event_type=event_type)
|
||||
self.events[name] = callback_
|
||||
|
||||
def send_event(self, *, event_type: Literal["message", "error", "warning", "info", "token"], data: LoggableType):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ class SourceHandle(BaseModel):
|
|||
|
||||
@field_validator("name", mode="before")
|
||||
@classmethod
|
||||
def validate_name(cls, v, _info):
|
||||
if _info.data["data_type"] == "GroupNode":
|
||||
def validate_name(cls, v, info):
|
||||
if info.data["data_type"] == "GroupNode":
|
||||
# 'OpenAIModel-u4iGV_text_output'
|
||||
splits = v.split("_", 1)
|
||||
if len(splits) != 2: # noqa: PLR2004
|
||||
|
|
|
|||
|
|
@ -1183,9 +1183,9 @@ class Graph:
|
|||
for edge in vertex.edges:
|
||||
for vid in [edge.source_id, edge.target_id]:
|
||||
if vid in self.vertex_map:
|
||||
_vertex = self.vertex_map[vid]
|
||||
if not _vertex.frozen:
|
||||
_vertex.build_params()
|
||||
vertex_ = self.vertex_map[vid]
|
||||
if not vertex_.frozen:
|
||||
vertex_.build_params()
|
||||
|
||||
def _add_vertex(self, vertex: Vertex) -> None:
|
||||
"""Adds a vertex to the graph."""
|
||||
|
|
@ -1794,10 +1794,10 @@ class Graph:
|
|||
|
||||
def assert_streaming_sequence(self) -> None:
|
||||
for i in self.edges:
|
||||
_source = self.get_vertex(i.source_id)
|
||||
if "stream" in _source.params and _source.params["stream"] is True:
|
||||
_target = self.get_vertex(i.target_id)
|
||||
if _target.vertex_type != "ChatOutput":
|
||||
source = self.get_vertex(i.source_id)
|
||||
if "stream" in source.params and source.params["stream"] is True:
|
||||
target = self.get_vertex(i.target_id)
|
||||
if target.vertex_type != "ChatOutput":
|
||||
msg = (
|
||||
"Error: A 'streaming' vertex cannot be followed by a non-'chat output' vertex."
|
||||
"Disable streaming to run the flow."
|
||||
|
|
|
|||
|
|
@ -162,15 +162,15 @@ def set_new_target_handle(proxy_id, new_edge, target_handle, node) -> None:
|
|||
None
|
||||
"""
|
||||
new_edge["target"] = proxy_id
|
||||
_type = target_handle.get("type")
|
||||
if _type is None:
|
||||
type_ = target_handle.get("type")
|
||||
if type_ is None:
|
||||
msg = "The 'type' key must be present in target_handle."
|
||||
raise KeyError(msg)
|
||||
|
||||
field = target_handle["proxy"]["field"]
|
||||
new_target_handle = {
|
||||
"fieldName": field,
|
||||
"type": _type,
|
||||
"type": type_,
|
||||
"id": proxy_id,
|
||||
}
|
||||
if node["data"]["node"].get("flow"):
|
||||
|
|
|
|||
|
|
@ -522,7 +522,7 @@ class Vertex:
|
|||
stream_url = artifacts.get("stream_url")
|
||||
files = [{"path": file} if isinstance(file, str) else file for file in artifacts.get("files", [])]
|
||||
component_id = self.id
|
||||
_type = self.artifacts_type
|
||||
type_ = self.artifacts_type
|
||||
|
||||
if isinstance(sender_name, Data | Message):
|
||||
sender_name = sender_name.get_text()
|
||||
|
|
@ -536,7 +536,7 @@ class Vertex:
|
|||
stream_url=stream_url,
|
||||
files=files,
|
||||
component_id=component_id,
|
||||
type=_type,
|
||||
type=type_,
|
||||
).model_dump(exclude_none=True)
|
||||
]
|
||||
except KeyError:
|
||||
|
|
|
|||
|
|
@ -216,16 +216,16 @@ class InterfaceVertex(ComponentVertex):
|
|||
if self.artifacts:
|
||||
# dump as a yaml string
|
||||
if isinstance(self.artifacts, dict):
|
||||
_artifacts = [self.artifacts]
|
||||
artifacts_ = [self.artifacts]
|
||||
elif hasattr(self.artifacts, "data"):
|
||||
_artifacts = self.artifacts.data
|
||||
artifacts_ = self.artifacts.data
|
||||
else:
|
||||
_artifacts = self.artifacts
|
||||
artifacts_ = self.artifacts
|
||||
artifacts = []
|
||||
for artifact in _artifacts:
|
||||
for artifact in artifacts_:
|
||||
# artifacts = {k.title().replace("_", " "): v for k, v in self.artifacts.items() if v is not None}
|
||||
_artifact = {k.title().replace("_", " "): v for k, v in artifact.items() if v is not None}
|
||||
artifacts.append(_artifact)
|
||||
artifact_ = {k.title().replace("_", " "): v for k, v in artifact.items() if v is not None}
|
||||
artifacts.append(artifact_)
|
||||
return yaml.dump(artifacts, default_flow_style=False, allow_unicode=True)
|
||||
return super().built_object_repr()
|
||||
|
||||
|
|
@ -372,16 +372,16 @@ class InterfaceVertex(ComponentVertex):
|
|||
complete_message = ""
|
||||
if is_async:
|
||||
async for message in iterator:
|
||||
_message = message.content if hasattr(message, "content") else message
|
||||
_message = _message.text if hasattr(_message, "text") else _message
|
||||
yield _message
|
||||
complete_message += _message
|
||||
message_ = message.content if hasattr(message, "content") else message
|
||||
message_ = message_.text if hasattr(message_, "text") else message_
|
||||
yield message_
|
||||
complete_message += message_
|
||||
else:
|
||||
for message in iterator:
|
||||
_message = message.content if hasattr(message, "content") else message
|
||||
_message = _message.text if hasattr(_message, "text") else _message
|
||||
yield _message
|
||||
complete_message += _message
|
||||
message_ = message.content if hasattr(message, "content") else message
|
||||
message_ = message_.text if hasattr(message_, "text") else message_
|
||||
yield message_
|
||||
complete_message += message_
|
||||
|
||||
files = self.params.get("files", [])
|
||||
|
||||
|
|
|
|||
|
|
@ -44,14 +44,14 @@ def data_to_text_list(template: str, data: Data | list[Data]) -> tuple[list[str]
|
|||
if isinstance(data, (Data)):
|
||||
data = [data]
|
||||
# Check if there are any format strings in the template
|
||||
_data = [
|
||||
data_ = [
|
||||
# If it is not a record, create one with the key "text"
|
||||
Data(text=value) if not isinstance(value, Data) else value
|
||||
for value in data
|
||||
]
|
||||
|
||||
formatted_text = [template.format(data=value.data, **value.data) for value in _data]
|
||||
return formatted_text, _data
|
||||
formatted_text = [template.format(data=value.data, **value.data) for value in data_]
|
||||
return formatted_text, data_
|
||||
|
||||
|
||||
def data_to_text(template: str, data: Data | list[Data], sep: str = "\n") -> str:
|
||||
|
|
@ -83,13 +83,13 @@ def messages_to_text(template: str, messages: Message | list[Message]) -> str:
|
|||
if isinstance(messages, (Message)):
|
||||
messages = [messages]
|
||||
# Check if there are any format strings in the template
|
||||
_messages = []
|
||||
messages_ = []
|
||||
for message in messages:
|
||||
# If it is not a message, create one with the key "text"
|
||||
if not isinstance(message, Message):
|
||||
msg = "All elements in the list must be of type Message."
|
||||
raise TypeError(msg)
|
||||
_messages.append(message)
|
||||
messages_.append(message)
|
||||
|
||||
formated_messages = [template.format(data=message.model_dump(), **message.model_dump()) for message in _messages]
|
||||
formated_messages = [template.format(data=message.model_dump(), **message.model_dump()) for message in messages_]
|
||||
return "\n".join(formated_messages)
|
||||
|
|
|
|||
|
|
@ -165,8 +165,8 @@ def update_new_output(data):
|
|||
if "sourceHandle" in edge and "targetHandle" in edge:
|
||||
new_source_handle = scape_json_parse(edge["sourceHandle"])
|
||||
new_target_handle = scape_json_parse(edge["targetHandle"])
|
||||
_id = new_source_handle["id"]
|
||||
source_node_index = next((index for (index, d) in enumerate(nodes) if d["id"] == _id), -1)
|
||||
id_ = new_source_handle["id"]
|
||||
source_node_index = next((index for (index, d) in enumerate(nodes) if d["id"] == id_), -1)
|
||||
source_node = nodes[source_node_index] if source_node_index != -1 else None
|
||||
|
||||
if "baseClasses" in new_source_handle:
|
||||
|
|
@ -544,8 +544,8 @@ async def load_flows_from_directory() -> None:
|
|||
msg = "Superuser not found in the database"
|
||||
raise NoResultFound(msg)
|
||||
user_id = user.id
|
||||
_flows_path = Path(flows_path)
|
||||
files = [f for f in _flows_path.iterdir() if f.is_file()]
|
||||
flows_path_ = Path(flows_path)
|
||||
files = [f for f in flows_path_.iterdir() if f.is_file()]
|
||||
for file_path in files:
|
||||
if file_path.suffix != ".json":
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -97,12 +97,12 @@ class StrInput(BaseInputMixin, ListableInputMixin, DatabaseLoadMixin, MetadataTr
|
|||
"""Defines if the field will allow the user to open a text editor. Default is False."""
|
||||
|
||||
@staticmethod
|
||||
def _validate_value(v: Any, _info):
|
||||
def _validate_value(v: Any, info):
|
||||
"""Validates the given value and returns the processed value.
|
||||
|
||||
Args:
|
||||
v (Any): The value to be validated.
|
||||
_info: Additional information about the input.
|
||||
info: Additional information about the input.
|
||||
|
||||
Returns:
|
||||
The processed value.
|
||||
|
|
@ -112,27 +112,27 @@ class StrInput(BaseInputMixin, ListableInputMixin, DatabaseLoadMixin, MetadataTr
|
|||
"""
|
||||
if not isinstance(v, str) and v is not None:
|
||||
# Keep the warning for now, but we should change it to an error
|
||||
if _info.data.get("input_types") and v.__class__.__name__ not in _info.data.get("input_types"):
|
||||
if info.data.get("input_types") and v.__class__.__name__ not in info.data.get("input_types"):
|
||||
warnings.warn(
|
||||
f"Invalid value type {type(v)} for input {_info.data.get('name')}. "
|
||||
f"Expected types: {_info.data.get('input_types')}",
|
||||
f"Invalid value type {type(v)} for input {info.data.get('name')}. "
|
||||
f"Expected types: {info.data.get('input_types')}",
|
||||
stacklevel=4,
|
||||
)
|
||||
else:
|
||||
warnings.warn(
|
||||
f"Invalid value type {type(v)} for input {_info.data.get('name')}.",
|
||||
f"Invalid value type {type(v)} for input {info.data.get('name')}.",
|
||||
stacklevel=4,
|
||||
)
|
||||
return v
|
||||
|
||||
@field_validator("value")
|
||||
@classmethod
|
||||
def validate_value(cls, v: Any, _info):
|
||||
def validate_value(cls, v: Any, info):
|
||||
"""Validates the given value and returns the processed value.
|
||||
|
||||
Args:
|
||||
v (Any): The value to be validated.
|
||||
_info: Additional information about the input.
|
||||
info: Additional information about the input.
|
||||
|
||||
Returns:
|
||||
The processed value.
|
||||
|
|
@ -140,8 +140,8 @@ class StrInput(BaseInputMixin, ListableInputMixin, DatabaseLoadMixin, MetadataTr
|
|||
Raises:
|
||||
ValueError: If the value is not of a valid type or if the input is missing a required key.
|
||||
"""
|
||||
is_list = _info.data["is_list"]
|
||||
return [cls._validate_value(vv, _info) for vv in v] if is_list else cls._validate_value(v, _info)
|
||||
is_list = info.data["is_list"]
|
||||
return [cls._validate_value(vv, info) for vv in v] if is_list else cls._validate_value(v, info)
|
||||
|
||||
|
||||
class MessageInput(StrInput, InputTraceMixin):
|
||||
|
|
@ -176,12 +176,12 @@ class MessageTextInput(StrInput, MetadataTraceMixin, InputTraceMixin, ToolModeMi
|
|||
input_types: list[str] = ["Message"]
|
||||
|
||||
@staticmethod
|
||||
def _validate_value(v: Any, _info):
|
||||
def _validate_value(v: Any, info):
|
||||
"""Validates the given value and returns the processed value.
|
||||
|
||||
Args:
|
||||
v (Any): The value to be validated.
|
||||
_info: Additional information about the input.
|
||||
info: Additional information about the input.
|
||||
|
||||
Returns:
|
||||
The processed value.
|
||||
|
|
@ -201,7 +201,7 @@ class MessageTextInput(StrInput, MetadataTraceMixin, InputTraceMixin, ToolModeMi
|
|||
value = v.data[v.text_key]
|
||||
else:
|
||||
keys = ", ".join(v.data.keys())
|
||||
input_name = _info.data["name"]
|
||||
input_name = info.data["name"]
|
||||
msg = (
|
||||
f"The input to '{input_name}' must contain the key '{v.text_key}'."
|
||||
f"You can set `text_key` to one of the following keys: {keys} "
|
||||
|
|
@ -259,12 +259,12 @@ class SecretStrInput(BaseInputMixin, DatabaseLoadMixin):
|
|||
|
||||
@field_validator("value")
|
||||
@classmethod
|
||||
def validate_value(cls, v: Any, _info):
|
||||
def validate_value(cls, v: Any, info):
|
||||
"""Validates the given value and returns the processed value.
|
||||
|
||||
Args:
|
||||
v (Any): The value to be validated.
|
||||
_info: Additional information about the input.
|
||||
info: Additional information about the input.
|
||||
|
||||
Returns:
|
||||
The processed value.
|
||||
|
|
@ -282,7 +282,7 @@ class SecretStrInput(BaseInputMixin, DatabaseLoadMixin):
|
|||
value = v.data[v.text_key]
|
||||
else:
|
||||
keys = ", ".join(v.data.keys())
|
||||
input_name = _info.data["name"]
|
||||
input_name = info.data["name"]
|
||||
msg = (
|
||||
f"The input to '{input_name}' must contain the key '{v.text_key}'."
|
||||
f"You can set `text_key` to one of the following keys: {keys} "
|
||||
|
|
@ -294,7 +294,7 @@ class SecretStrInput(BaseInputMixin, DatabaseLoadMixin):
|
|||
elif v is None:
|
||||
value = None
|
||||
else:
|
||||
msg = f"Invalid value type `{type(v)}` for input `{_info.data['name']}`"
|
||||
msg = f"Invalid value type `{type(v)}` for input `{info.data['name']}`"
|
||||
raise ValueError(msg)
|
||||
return value
|
||||
|
||||
|
|
@ -313,12 +313,12 @@ class IntInput(BaseInputMixin, ListableInputMixin, RangeMixin, MetadataTraceMixi
|
|||
|
||||
@field_validator("value")
|
||||
@classmethod
|
||||
def validate_value(cls, v: Any, _info):
|
||||
def validate_value(cls, v: Any, info):
|
||||
"""Validates the given value and returns the processed value.
|
||||
|
||||
Args:
|
||||
v (Any): The value to be validated.
|
||||
_info: Additional information about the input.
|
||||
info: Additional information about the input.
|
||||
|
||||
Returns:
|
||||
The processed value.
|
||||
|
|
@ -327,7 +327,7 @@ class IntInput(BaseInputMixin, ListableInputMixin, RangeMixin, MetadataTraceMixi
|
|||
ValueError: If the value is not of a valid type or if the input is missing a required key.
|
||||
"""
|
||||
if v and not isinstance(v, int | float):
|
||||
msg = f"Invalid value type {type(v)} for input {_info.data.get('name')}."
|
||||
msg = f"Invalid value type {type(v)} for input {info.data.get('name')}."
|
||||
raise ValueError(msg)
|
||||
if isinstance(v, float):
|
||||
v = int(v)
|
||||
|
|
@ -348,12 +348,12 @@ class FloatInput(BaseInputMixin, ListableInputMixin, RangeMixin, MetadataTraceMi
|
|||
|
||||
@field_validator("value")
|
||||
@classmethod
|
||||
def validate_value(cls, v: Any, _info):
|
||||
def validate_value(cls, v: Any, info):
|
||||
"""Validates the given value and returns the processed value.
|
||||
|
||||
Args:
|
||||
v (Any): The value to be validated.
|
||||
_info: Additional information about the input.
|
||||
info: Additional information about the input.
|
||||
|
||||
Returns:
|
||||
The processed value.
|
||||
|
|
@ -362,7 +362,7 @@ class FloatInput(BaseInputMixin, ListableInputMixin, RangeMixin, MetadataTraceMi
|
|||
ValueError: If the value is not of a valid type or if the input is missing a required key.
|
||||
"""
|
||||
if v and not isinstance(v, int | float):
|
||||
msg = f"Invalid value type {type(v)} for input {_info.data.get('name')}."
|
||||
msg = f"Invalid value type {type(v)} for input {info.data.get('name')}."
|
||||
raise ValueError(msg)
|
||||
if isinstance(v, int):
|
||||
v = float(v)
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@ from langflow.services.deps import get_settings_service
|
|||
|
||||
|
||||
def load_file_into_dict(file_path: str) -> dict:
|
||||
_file_path = Path(file_path)
|
||||
if not _file_path.exists():
|
||||
file_path_ = Path(file_path)
|
||||
if not file_path_.exists():
|
||||
msg = f"File not found: {file_path}"
|
||||
raise FileNotFoundError(msg)
|
||||
|
||||
# Files names are UUID, so we can't find the extension
|
||||
with _file_path.open(encoding="utf-8") as file:
|
||||
with file_path_.open(encoding="utf-8") as file:
|
||||
try:
|
||||
data = json.load(file)
|
||||
except json.JSONDecodeError:
|
||||
|
|
|
|||
|
|
@ -148,8 +148,8 @@ def apply_tweaks(node: dict[str, Any], node_tweaks: dict[str, Any]) -> None:
|
|||
template_data[tweak_name]["value"] = value
|
||||
elif isinstance(tweak_value, dict):
|
||||
for k, v in tweak_value.items():
|
||||
_k = "file_path" if template_data[tweak_name]["type"] == "file" else k
|
||||
template_data[tweak_name][_k] = v
|
||||
k_ = "file_path" if template_data[tweak_name]["type"] == "file" else k
|
||||
template_data[tweak_name][k_] = v
|
||||
else:
|
||||
key = "file_path" if template_data[tweak_name]["type"] == "file" else "value"
|
||||
template_data[tweak_name][key] = tweak_value
|
||||
|
|
|
|||
|
|
@ -53,13 +53,13 @@ def get_artifact_type(value, build_result=None) -> str:
|
|||
|
||||
|
||||
def _to_list_of_dicts(raw):
|
||||
_raw = []
|
||||
raw_ = []
|
||||
for item in raw:
|
||||
if hasattr(item, "dict") or hasattr(item, "model_dump"):
|
||||
_raw.append(recursive_serialize_or_str(item))
|
||||
raw_.append(recursive_serialize_or_str(item))
|
||||
else:
|
||||
_raw.append(str(item))
|
||||
return _raw
|
||||
raw_.append(str(item))
|
||||
return raw_
|
||||
|
||||
|
||||
def post_process_raw(raw, artifact_type: str):
|
||||
|
|
|
|||
|
|
@ -92,9 +92,9 @@ def build_output_logs(vertex, result) -> dict:
|
|||
payload = component_instance._artifacts
|
||||
output_result = payload.get(output["name"], {}).get("raw")
|
||||
message = get_message(output_result)
|
||||
_type = get_type(output_result)
|
||||
type_ = get_type(output_result)
|
||||
|
||||
match _type:
|
||||
match type_:
|
||||
case LogType.STREAM if "stream_url" in message:
|
||||
message = StreamURL(location=message["stream_url"])
|
||||
|
||||
|
|
@ -112,6 +112,6 @@ def build_output_logs(vertex, result) -> dict:
|
|||
message = message.to_dict(orient="records")
|
||||
message = [recursive_serialize_or_str(item) for item in message]
|
||||
name = output.get("name", f"output_{index}")
|
||||
outputs |= {name: OutputValue(message=message, type=_type).model_dump()}
|
||||
outputs |= {name: OutputValue(message=message, type=type_).model_dump()}
|
||||
|
||||
return outputs
|
||||
|
|
|
|||
|
|
@ -92,11 +92,11 @@ class CacheService(Subject, Service):
|
|||
"image": "png",
|
||||
"pandas": "csv",
|
||||
}
|
||||
_extension = object_extensions[obj_type] if obj_type in object_extensions else type(obj).__name__.lower()
|
||||
extension_ = object_extensions[obj_type] if obj_type in object_extensions else type(obj).__name__.lower()
|
||||
self.current_cache[name] = {
|
||||
"obj": obj,
|
||||
"type": obj_type,
|
||||
"extension": extension or _extension,
|
||||
"extension": extension or extension_,
|
||||
}
|
||||
self.notify()
|
||||
|
||||
|
|
|
|||
|
|
@ -349,19 +349,19 @@ class Settings(BaseSettings):
|
|||
logger.debug(f"Updating {key}")
|
||||
if isinstance(getattr(self, key), list):
|
||||
# value might be a '[something]' string
|
||||
_value = value
|
||||
value_ = value
|
||||
with contextlib.suppress(json.decoder.JSONDecodeError):
|
||||
_value = orjson.loads(str(value))
|
||||
if isinstance(_value, list):
|
||||
for item in _value:
|
||||
_item = str(item) if isinstance(item, Path) else item
|
||||
if _item not in getattr(self, key):
|
||||
getattr(self, key).append(_item)
|
||||
value_ = orjson.loads(str(value))
|
||||
if isinstance(value_, list):
|
||||
for item in value_:
|
||||
item_ = str(item) if isinstance(item, Path) else item
|
||||
if item_ not in getattr(self, key):
|
||||
getattr(self, key).append(item_)
|
||||
logger.debug(f"Extended {key}")
|
||||
else:
|
||||
_value = str(_value) if isinstance(_value, Path) else _value
|
||||
if _value not in getattr(self, key):
|
||||
getattr(self, key).append(_value)
|
||||
value_ = str(value_) if isinstance(value_, Path) else value_
|
||||
if value_ not in getattr(self, key):
|
||||
getattr(self, key).append(value_)
|
||||
logger.debug(f"Appended {key}")
|
||||
|
||||
else:
|
||||
|
|
@ -393,11 +393,11 @@ def load_settings_from_yaml(file_path: str) -> Settings:
|
|||
if "/" not in file_path:
|
||||
# Get current path
|
||||
current_path = Path(__file__).resolve().parent
|
||||
_file_path = Path(current_path) / file_path
|
||||
file_path_ = Path(current_path) / file_path
|
||||
else:
|
||||
_file_path = Path(file_path)
|
||||
file_path_ = Path(file_path)
|
||||
|
||||
with _file_path.open(encoding="utf-8") as f:
|
||||
with file_path_.open(encoding="utf-8") as f:
|
||||
settings_dict = yaml.safe_load(f)
|
||||
settings_dict = {k.upper(): v for k, v in settings_dict.items()}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ class SettingsService(Service):
|
|||
if "/" not in file_path:
|
||||
# Get current path
|
||||
current_path = Path(__file__).resolve().parent
|
||||
_file_path = Path(current_path) / file_path
|
||||
file_path_ = Path(current_path) / file_path
|
||||
else:
|
||||
_file_path = Path(file_path)
|
||||
file_path_ = Path(file_path)
|
||||
|
||||
with _file_path.open(encoding="utf-8") as f:
|
||||
with file_path_.open(encoding="utf-8") as f:
|
||||
settings_dict = yaml.safe_load(f)
|
||||
settings_dict = {k.upper(): v for k, v in settings_dict.items()}
|
||||
|
||||
|
|
|
|||
|
|
@ -276,9 +276,7 @@ class ArizePhoenixTracer(BaseTracer):
|
|||
def _convert_to_arize_phoenix_type(self, value):
|
||||
"""Recursively converts a value to a Arize/Phoenix compatible type."""
|
||||
if isinstance(value, dict):
|
||||
for key, _value in value.copy().items():
|
||||
_value = self._convert_to_arize_phoenix_type(_value)
|
||||
value[key] = _value
|
||||
value = {key: self._convert_to_arize_phoenix_type(val) for key, val in value.items()}
|
||||
|
||||
elif isinstance(value, list):
|
||||
value = [self._convert_to_arize_phoenix_type(v) for v in value]
|
||||
|
|
|
|||
|
|
@ -78,15 +78,15 @@ class LangFuseTracer(BaseTracer):
|
|||
if not self._ready:
|
||||
return
|
||||
|
||||
_metadata: dict = {}
|
||||
_metadata |= {"trace_type": trace_type} if trace_type else {}
|
||||
_metadata |= metadata or {}
|
||||
metadata_: dict = {}
|
||||
metadata_ |= {"trace_type": trace_type} if trace_type else {}
|
||||
metadata_ |= metadata or {}
|
||||
|
||||
_name = trace_name.removesuffix(f" ({trace_id})")
|
||||
name = trace_name.removesuffix(f" ({trace_id})")
|
||||
content_span = {
|
||||
"name": _name,
|
||||
"name": name,
|
||||
"input": inputs,
|
||||
"metadata": _metadata,
|
||||
"metadata": metadata_,
|
||||
"start_time": start_time,
|
||||
}
|
||||
|
||||
|
|
@ -110,11 +110,11 @@ class LangFuseTracer(BaseTracer):
|
|||
|
||||
span = self.spans.get(trace_id, None)
|
||||
if span:
|
||||
_output: dict = {}
|
||||
_output |= outputs or {}
|
||||
_output |= {"error": str(error)} if error else {}
|
||||
_output |= {"logs": list(logs)} if logs else {}
|
||||
content = {"output": _output, "end_time": end_time}
|
||||
output: dict = {}
|
||||
output |= outputs or {}
|
||||
output |= {"error": str(error)} if error else {}
|
||||
output |= {"logs": list(logs)} if logs else {}
|
||||
content = {"output": output, "end_time": end_time}
|
||||
span.update(**content)
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -96,9 +96,7 @@ class LangSmithTracer(BaseTracer):
|
|||
from langflow.schema.message import Message
|
||||
|
||||
if isinstance(value, dict):
|
||||
for key, _value in value.copy().items():
|
||||
_value = self._convert_to_langchain_type(_value)
|
||||
value[key] = _value
|
||||
value = {key: self._convert_to_langchain_type(val) for key, val in value.items()}
|
||||
elif isinstance(value, list):
|
||||
value = [self._convert_to_langchain_type(v) for v in value]
|
||||
elif isinstance(value, Message):
|
||||
|
|
|
|||
|
|
@ -153,9 +153,7 @@ class LangWatchTracer(BaseTracer):
|
|||
from langflow.schema.message import BaseMessage, Message
|
||||
|
||||
if isinstance(value, dict):
|
||||
for key, _value in value.copy().items():
|
||||
_value = self._convert_to_langwatch_type(_value)
|
||||
value[key] = _value
|
||||
value = {key: self._convert_to_langwatch_type(val) for key, val in value.items()}
|
||||
elif isinstance(value, list):
|
||||
value = [self._convert_to_langwatch_type(v) for v in value]
|
||||
elif isinstance(value, Message):
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@ def convert_to_langchain_type(value):
|
|||
from langflow.schema.message import Message
|
||||
|
||||
if isinstance(value, dict):
|
||||
for key, _value in value.copy().items():
|
||||
_value = convert_to_langchain_type(_value)
|
||||
value[key] = _value
|
||||
value = {key: convert_to_langchain_type(val) for key, val in value.items()}
|
||||
elif isinstance(value, list):
|
||||
value = [convert_to_langchain_type(v) for v in value]
|
||||
elif isinstance(value, Message):
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ class VariableService(Service):
|
|||
value: str,
|
||||
*,
|
||||
default_fields: list[str],
|
||||
_type: str,
|
||||
type_: str,
|
||||
session: AsyncSession,
|
||||
) -> Variable:
|
||||
"""Create a variable.
|
||||
|
|
@ -115,7 +115,7 @@ class VariableService(Service):
|
|||
name: The name of the variable.
|
||||
value: The value of the variable.
|
||||
default_fields: The default fields of the variable.
|
||||
_type: The type of the variable.
|
||||
type_: The type of the variable.
|
||||
session: The database session.
|
||||
|
||||
Returns:
|
||||
|
|
|
|||
|
|
@ -163,15 +163,15 @@ class KubernetesSecretService(VariableService, Service):
|
|||
value: str,
|
||||
*,
|
||||
default_fields: list[str],
|
||||
_type: str,
|
||||
type_: str,
|
||||
session: AsyncSession,
|
||||
) -> Variable:
|
||||
secret_name = encode_user_id(user_id)
|
||||
secret_key = name
|
||||
if _type == CREDENTIAL_TYPE:
|
||||
if type_ == CREDENTIAL_TYPE:
|
||||
secret_key = CREDENTIAL_TYPE + "_" + name
|
||||
else:
|
||||
_type = GENERIC_TYPE
|
||||
type_ = GENERIC_TYPE
|
||||
|
||||
await asyncio.to_thread(
|
||||
self.kubernetes_secrets.upsert_secret, secret_name=secret_name, data={secret_key: value}
|
||||
|
|
@ -179,7 +179,7 @@ class KubernetesSecretService(VariableService, Service):
|
|||
|
||||
variable_base = VariableCreate(
|
||||
name=name,
|
||||
type=_type,
|
||||
type=type_,
|
||||
value=auth_utils.encrypt_api_key(value, settings_service=self.settings_service),
|
||||
default_fields=default_fields,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -162,31 +162,31 @@ def encode_user_id(user_id: UUID | str) -> str:
|
|||
return f"uuid-{str(user_id).lower()}"[:253]
|
||||
|
||||
# Convert string to lowercase
|
||||
_user_id = str(user_id).lower()
|
||||
user_id_ = str(user_id).lower()
|
||||
|
||||
# If the user_id looks like an email, replace @ and . with allowed characters
|
||||
if "@" in _user_id or "." in _user_id:
|
||||
_user_id = _user_id.replace("@", "-at-").replace(".", "-dot-")
|
||||
if "@" in user_id_ or "." in user_id_:
|
||||
user_id_ = user_id_.replace("@", "-at-").replace(".", "-dot-")
|
||||
|
||||
# Encode the user_id to base64
|
||||
# encoded = base64.b64encode(user_id.encode("utf-8")).decode("utf-8")
|
||||
|
||||
# Replace characters not allowed in Kubernetes names
|
||||
_user_id = _user_id.replace("+", "-").replace("/", "_").rstrip("=")
|
||||
user_id_ = user_id_.replace("+", "-").replace("/", "_").rstrip("=")
|
||||
|
||||
# Ensure the name starts with an alphanumeric character
|
||||
if not _user_id[0].isalnum():
|
||||
_user_id = "a-" + _user_id
|
||||
if not user_id_[0].isalnum():
|
||||
user_id_ = "a-" + user_id_
|
||||
|
||||
# Truncate to 253 characters (Kubernetes name length limit)
|
||||
_user_id = _user_id[:253]
|
||||
user_id_ = user_id_[:253]
|
||||
|
||||
if not all(c.isalnum() or c in "-_" for c in _user_id):
|
||||
msg = f"Invalid user_id: {_user_id}"
|
||||
if not all(c.isalnum() or c in "-_" for c in user_id_):
|
||||
msg = f"Invalid user_id: {user_id_}"
|
||||
raise ValueError(msg)
|
||||
|
||||
# Ensure the name ends with an alphanumeric character
|
||||
while not _user_id[-1].isalnum():
|
||||
_user_id = _user_id[:-1]
|
||||
while not user_id_[-1].isalnum():
|
||||
user_id_ = user_id_[:-1]
|
||||
|
||||
return _user_id
|
||||
return user_id_
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class DatabaseVariableService(VariableService, Service):
|
|||
name=var_name,
|
||||
value=value,
|
||||
default_fields=[],
|
||||
_type=CREDENTIAL_TYPE,
|
||||
type_=CREDENTIAL_TYPE,
|
||||
session=session,
|
||||
)
|
||||
logger.info(f"Processed {var_name} variable from environment.")
|
||||
|
|
@ -163,12 +163,12 @@ class DatabaseVariableService(VariableService, Service):
|
|||
value: str,
|
||||
*,
|
||||
default_fields: Sequence[str] = (),
|
||||
_type: str = GENERIC_TYPE,
|
||||
type_: str = GENERIC_TYPE,
|
||||
session: AsyncSession,
|
||||
):
|
||||
variable_base = VariableCreate(
|
||||
name=name,
|
||||
type=_type,
|
||||
type=type_,
|
||||
value=auth_utils.encrypt_api_key(value, settings_service=self.settings_service),
|
||||
default_fields=list(default_fields),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -192,10 +192,10 @@ class Output(BaseModel):
|
|||
def to_dict(self):
|
||||
return self.model_dump(by_alias=True, exclude_none=True)
|
||||
|
||||
def add_types(self, _type: list[Any]) -> None:
|
||||
def add_types(self, type_: list[Any]) -> None:
|
||||
if self.types is None:
|
||||
self.types = []
|
||||
self.types.extend([t for t in _type if t not in self.types])
|
||||
self.types.extend([t for t in type_ if t not in self.types])
|
||||
|
||||
def set_selected(self) -> None:
|
||||
if not self.selected and self.types:
|
||||
|
|
|
|||
|
|
@ -50,14 +50,14 @@ class Template(BaseModel):
|
|||
input_type = value.pop("_input_type", None)
|
||||
if input_type:
|
||||
try:
|
||||
_input = instantiate_input(input_type, value)
|
||||
input_ = instantiate_input(input_type, value)
|
||||
except Exception as e:
|
||||
msg = f"Error instantiating input {input_type}: {e}"
|
||||
raise ValueError(msg) from e
|
||||
else:
|
||||
_input = Input(**value)
|
||||
input_ = Input(**value)
|
||||
|
||||
data["fields"].append(_input)
|
||||
data["fields"].append(input_)
|
||||
|
||||
# Necessary for components with no inputs(?)
|
||||
if "fields" not in data:
|
||||
|
|
|
|||
|
|
@ -40,29 +40,29 @@ def extract_uniont_types_from_generic_alias(return_type: GenericAlias) -> list:
|
|||
return list(return_type.__args__)
|
||||
|
||||
|
||||
def post_process_type(_type):
|
||||
def post_process_type(type_):
|
||||
"""Process the return type of a function.
|
||||
|
||||
Args:
|
||||
_type (Any): The return type of the function.
|
||||
type_ (Any): The return type of the function.
|
||||
|
||||
Returns:
|
||||
Union[List[Any], Any]: The processed return type.
|
||||
|
||||
"""
|
||||
if hasattr(_type, "__origin__") and _type.__origin__ in {list, list, SequenceABC}:
|
||||
_type = extract_inner_type_from_generic_alias(_type)
|
||||
if hasattr(type_, "__origin__") and type_.__origin__ in {list, list, SequenceABC}:
|
||||
type_ = extract_inner_type_from_generic_alias(type_)
|
||||
|
||||
# If the return type is not a Union, then we just return it as a list
|
||||
inner_type = _type[0] if isinstance(_type, list) else _type
|
||||
inner_type = type_[0] if isinstance(type_, list) else type_
|
||||
if (not hasattr(inner_type, "__origin__") or inner_type.__origin__ != Union) and (
|
||||
not hasattr(inner_type, "__class__") or inner_type.__class__.__name__ != "UnionType"
|
||||
):
|
||||
return _type if isinstance(_type, list) else [_type]
|
||||
return type_ if isinstance(type_, list) else [type_]
|
||||
# If the return type is a Union, then we need to parse it
|
||||
_type = extract_union_types_from_generic_alias(_type)
|
||||
_type = set(chain.from_iterable([post_process_type(t) for t in _type]))
|
||||
return list(_type)
|
||||
type_ = extract_union_types_from_generic_alias(type_)
|
||||
type_ = set(chain.from_iterable([post_process_type(t) for t in type_]))
|
||||
return list(type_)
|
||||
|
||||
|
||||
def extract_union_types_from_generic_alias(return_type: GenericAlias) -> list:
|
||||
|
|
|
|||
|
|
@ -52,22 +52,22 @@ class ChatOutputResponse(BaseModel):
|
|||
if not name:
|
||||
name = path.split("/")[-1]
|
||||
file["name"] = name
|
||||
_type = file.get("type")
|
||||
if not _type:
|
||||
type_ = file.get("type")
|
||||
if not type_:
|
||||
# get the file type from the path
|
||||
extension = path.split(".")[-1]
|
||||
file_types = set(TEXT_FILE_TYPES + IMG_FILE_TYPES)
|
||||
if extension and extension in file_types:
|
||||
_type = extension
|
||||
type_ = extension
|
||||
else:
|
||||
for file_type in file_types:
|
||||
if file_type in path:
|
||||
_type = file_type
|
||||
type_ = file_type
|
||||
break
|
||||
if not _type:
|
||||
if not type_:
|
||||
msg = "File type is required."
|
||||
raise ValueError(msg)
|
||||
file["type"] = _type
|
||||
file["type"] = type_
|
||||
|
||||
return files
|
||||
|
||||
|
|
|
|||
|
|
@ -35,13 +35,13 @@ def build_template_from_function(name: str, type_to_loader_dict: dict, *, add_fu
|
|||
|
||||
for _type, v in type_to_loader_dict.items():
|
||||
if v.__annotations__["return"].__name__ == name:
|
||||
_class = v.__annotations__["return"]
|
||||
class_ = v.__annotations__["return"]
|
||||
|
||||
# Get the docstring
|
||||
docs = parse(_class.__doc__)
|
||||
docs = parse(class_.__doc__)
|
||||
|
||||
variables = {"_type": _type}
|
||||
for class_field_items, value in _class.model_fields.items():
|
||||
for class_field_items, value in class_.model_fields.items():
|
||||
if class_field_items == "callback_manager":
|
||||
continue
|
||||
variables[class_field_items] = {}
|
||||
|
|
@ -49,7 +49,7 @@ def build_template_from_function(name: str, type_to_loader_dict: dict, *, add_fu
|
|||
if name_ == "default_factory":
|
||||
try:
|
||||
variables[class_field_items]["default"] = get_default_factory(
|
||||
module=_class.__base__.__module__, function=value_
|
||||
module=class_.__base__.__module__, function=value_
|
||||
)
|
||||
except Exception: # noqa: BLE001
|
||||
logger.opt(exception=True).debug(f"Error getting default factory for {value_}")
|
||||
|
|
@ -60,7 +60,7 @@ def build_template_from_function(name: str, type_to_loader_dict: dict, *, add_fu
|
|||
variables[class_field_items]["placeholder"] = docs.params.get(class_field_items, "")
|
||||
# Adding function to base classes to allow
|
||||
# the output to be a function
|
||||
base_classes = get_base_classes(_class)
|
||||
base_classes = get_base_classes(class_)
|
||||
if add_function:
|
||||
base_classes.append("Callable")
|
||||
|
||||
|
|
@ -88,15 +88,15 @@ def build_template_from_method(
|
|||
|
||||
for _type, v in type_to_cls_dict.items():
|
||||
if v.__name__ == class_name:
|
||||
_class = v
|
||||
class_ = v
|
||||
|
||||
# Check if the method exists in this class
|
||||
if not hasattr(_class, method_name):
|
||||
if not hasattr(class_, method_name):
|
||||
msg = f"Method {method_name} not found in class {class_name}"
|
||||
raise ValueError(msg)
|
||||
|
||||
# Get the method
|
||||
method = getattr(_class, method_name)
|
||||
method = getattr(class_, method_name)
|
||||
|
||||
# Get the docstring
|
||||
docs = parse(method.__doc__)
|
||||
|
|
@ -121,7 +121,7 @@ def build_template_from_method(
|
|||
},
|
||||
}
|
||||
|
||||
base_classes = get_base_classes(_class)
|
||||
base_classes = get_base_classes(class_)
|
||||
|
||||
# Adding function to base classes to allow the output to be a function
|
||||
if add_function:
|
||||
|
|
@ -207,17 +207,17 @@ def format_dict(dictionary: dict[str, Any], class_name: str | None = None) -> di
|
|||
if key == "_type":
|
||||
continue
|
||||
|
||||
_type: str | type = get_type(value)
|
||||
type_: str | type = get_type(value)
|
||||
|
||||
if "BaseModel" in str(_type):
|
||||
if "BaseModel" in str(type_):
|
||||
continue
|
||||
|
||||
_type = remove_optional_wrapper(_type)
|
||||
_type = check_list_type(_type, value)
|
||||
_type = replace_mapping_with_dict(_type)
|
||||
_type = get_type_from_union_literal(_type)
|
||||
type_ = remove_optional_wrapper(type_)
|
||||
type_ = check_list_type(type_, value)
|
||||
type_ = replace_mapping_with_dict(type_)
|
||||
type_ = get_type_from_union_literal(type_)
|
||||
|
||||
value["type"] = get_formatted_type(key, _type)
|
||||
value["type"] = get_formatted_type(key, type_)
|
||||
value["show"] = should_show_field(value, key)
|
||||
value["password"] = is_password_field(key)
|
||||
value["multiline"] = is_multiline_field(key)
|
||||
|
|
@ -251,53 +251,53 @@ def get_type(value: Any) -> str | type:
|
|||
The type value.
|
||||
"""
|
||||
# get "type" or "annotation" from the value
|
||||
_type = value.get("type") or value.get("annotation")
|
||||
type_ = value.get("type") or value.get("annotation")
|
||||
|
||||
return _type if isinstance(_type, str) else _type.__name__
|
||||
return type_ if isinstance(type_, str) else type_.__name__
|
||||
|
||||
|
||||
def remove_optional_wrapper(_type: str | type) -> str:
|
||||
def remove_optional_wrapper(type_: str | type) -> str:
|
||||
"""Removes the 'Optional' wrapper from the type string.
|
||||
|
||||
Returns:
|
||||
The type string with the 'Optional' wrapper removed.
|
||||
"""
|
||||
if isinstance(_type, type):
|
||||
_type = str(_type)
|
||||
if "Optional" in _type:
|
||||
_type = _type.replace("Optional[", "")[:-1]
|
||||
if isinstance(type_, type):
|
||||
type_ = str(type_)
|
||||
if "Optional" in type_:
|
||||
type_ = type_.replace("Optional[", "")[:-1]
|
||||
|
||||
return _type
|
||||
return type_
|
||||
|
||||
|
||||
def check_list_type(_type: str, value: dict[str, Any]) -> str:
|
||||
def check_list_type(type_: str, value: dict[str, Any]) -> str:
|
||||
"""Checks if the type is a list type and modifies the value accordingly.
|
||||
|
||||
Returns:
|
||||
The modified type string.
|
||||
"""
|
||||
if any(list_type in _type for list_type in ["List", "Sequence", "Set"]):
|
||||
_type = _type.replace("List[", "").replace("Sequence[", "").replace("Set[", "")[:-1]
|
||||
if any(list_type in type_ for list_type in ["List", "Sequence", "Set"]):
|
||||
type_ = type_.replace("List[", "").replace("Sequence[", "").replace("Set[", "")[:-1]
|
||||
value["list"] = True
|
||||
else:
|
||||
value["list"] = False
|
||||
|
||||
return _type
|
||||
return type_
|
||||
|
||||
|
||||
def replace_mapping_with_dict(_type: str) -> str:
|
||||
def replace_mapping_with_dict(type_: str) -> str:
|
||||
"""Replaces 'Mapping' with 'dict' in the type string.
|
||||
|
||||
Returns:
|
||||
The modified type string.
|
||||
"""
|
||||
if "Mapping" in _type:
|
||||
_type = _type.replace("Mapping", "dict")
|
||||
if "Mapping" in type_:
|
||||
type_ = type_.replace("Mapping", "dict")
|
||||
|
||||
return _type
|
||||
return type_
|
||||
|
||||
|
||||
def get_formatted_type(key: str, _type: str) -> str:
|
||||
def get_formatted_type(key: str, type_: str) -> str:
|
||||
"""Formats the type value based on the given key.
|
||||
|
||||
Returns:
|
||||
|
|
@ -309,7 +309,7 @@ def get_formatted_type(key: str, _type: str) -> str:
|
|||
if key == "max_value_length":
|
||||
return "int"
|
||||
|
||||
return _type
|
||||
return type_
|
||||
|
||||
|
||||
def should_show_field(value: dict[str, Any], key: str) -> bool:
|
||||
|
|
|
|||
|
|
@ -22,16 +22,16 @@ def get_version() -> str:
|
|||
"langflow-nightly",
|
||||
"langflow-base-nightly",
|
||||
]
|
||||
_version = None
|
||||
version = None
|
||||
for pkg_name in pkg_names:
|
||||
with contextlib.suppress(ImportError, metadata.PackageNotFoundError):
|
||||
_version = metadata.version(pkg_name)
|
||||
version = metadata.version(pkg_name)
|
||||
|
||||
if _version is None:
|
||||
if version is None:
|
||||
msg = f"Package not found from options {pkg_names}"
|
||||
raise ValueError(msg)
|
||||
|
||||
return _version
|
||||
return version
|
||||
|
||||
|
||||
def is_pre_release(v: str) -> bool:
|
||||
|
|
|
|||
|
|
@ -222,13 +222,13 @@ def distributed_client_fixture(
|
|||
monkeypatch.undo()
|
||||
|
||||
|
||||
def get_graph(_type="basic"):
|
||||
def get_graph(type_="basic"):
|
||||
"""Get a graph from a json file."""
|
||||
if _type == "basic":
|
||||
if type_ == "basic":
|
||||
path = pytest.BASIC_EXAMPLE_PATH
|
||||
elif _type == "complex":
|
||||
elif type_ == "complex":
|
||||
path = pytest.COMPLEX_EXAMPLE_PATH
|
||||
elif _type == "openapi":
|
||||
elif type_ == "openapi":
|
||||
path = pytest.OPENAPI_EXAMPLE_PATH
|
||||
|
||||
with path.open(encoding="utf-8") as f:
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ async def test_delete_api_key_route(client: AsyncClient, logged_in_headers, acti
|
|||
"api_key": "string",
|
||||
"user_id": str(active_user.id),
|
||||
}
|
||||
_response = await client.post("api/v1/api_key/", json=basic_case, headers=logged_in_headers)
|
||||
_id = _response.json()["id"]
|
||||
response_ = await client.post("api/v1/api_key/", json=basic_case, headers=logged_in_headers)
|
||||
id_ = response_.json()["id"]
|
||||
|
||||
response = await client.delete(f"api/v1/api_key/{_id}", headers=logged_in_headers)
|
||||
response = await client.delete(f"api/v1/api_key/{id_}", headers=logged_in_headers)
|
||||
result = response.json()
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
|
|
|||
|
|
@ -69,9 +69,9 @@ async def test_read_flow(client: AsyncClient, logged_in_headers):
|
|||
"user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||
"folder_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||
}
|
||||
_response = await client.post("api/v1/flows/", json=basic_case, headers=logged_in_headers)
|
||||
_id = _response.json()["id"]
|
||||
response = await client.get(f"api/v1/flows/{_id}", headers=logged_in_headers)
|
||||
response_ = await client.post("api/v1/flows/", json=basic_case, headers=logged_in_headers)
|
||||
id_ = response_.json()["id"]
|
||||
response = await client.get(f"api/v1/flows/{id_}", headers=logged_in_headers)
|
||||
result = response.json()
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
|
@ -109,11 +109,11 @@ async def test_update_flow(client: AsyncClient, logged_in_headers):
|
|||
"folder_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||
}
|
||||
basic_case["name"] = name
|
||||
_response = await client.post("api/v1/flows/", json=basic_case, headers=logged_in_headers)
|
||||
_id = _response.json()["id"]
|
||||
response_ = await client.post("api/v1/flows/", json=basic_case, headers=logged_in_headers)
|
||||
id_ = response_.json()["id"]
|
||||
|
||||
basic_case["name"] = updated_name
|
||||
response = await client.patch(f"api/v1/flows/{_id}", json=basic_case, headers=logged_in_headers)
|
||||
response = await client.patch(f"api/v1/flows/{id_}", json=basic_case, headers=logged_in_headers)
|
||||
result = response.json()
|
||||
|
||||
assert isinstance(result, dict), "The result must be a dictionary"
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ async def test_read_folders(client: AsyncClient, logged_in_headers):
|
|||
|
||||
|
||||
async def test_read_folder(client: AsyncClient, logged_in_headers, basic_case):
|
||||
_response = await client.post("api/v1/folders/", json=basic_case, headers=logged_in_headers)
|
||||
_id = _response.json()["id"]
|
||||
response = await client.get(f"api/v1/folders/{_id}", headers=logged_in_headers)
|
||||
response_ = await client.post("api/v1/folders/", json=basic_case, headers=logged_in_headers)
|
||||
id_ = response_.json()["id"]
|
||||
response = await client.get(f"api/v1/folders/{id_}", headers=logged_in_headers)
|
||||
result = response.json()
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
|
@ -51,9 +51,9 @@ async def test_read_folder(client: AsyncClient, logged_in_headers, basic_case):
|
|||
async def test_update_folder(client: AsyncClient, logged_in_headers, basic_case):
|
||||
update_case = basic_case.copy()
|
||||
update_case["name"] = "Updated Folder"
|
||||
_response = await client.post("api/v1/folders/", json=basic_case, headers=logged_in_headers)
|
||||
_id = _response.json()["id"]
|
||||
response = await client.patch(f"api/v1/folders/{_id}", json=update_case, headers=logged_in_headers)
|
||||
response_ = await client.post("api/v1/folders/", json=basic_case, headers=logged_in_headers)
|
||||
id_ = response_.json()["id"]
|
||||
response = await client.patch(f"api/v1/folders/{id_}", json=update_case, headers=logged_in_headers)
|
||||
result = response.json()
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ async def test_patch_user(client: AsyncClient, logged_in_headers_super_user):
|
|||
name = "string"
|
||||
updated_name = "string2"
|
||||
basic_case = {"username": name, "password": "string"}
|
||||
_response = await client.post("api/v1/users/", json=basic_case)
|
||||
_id = _response.json()["id"]
|
||||
response_ = await client.post("api/v1/users/", json=basic_case)
|
||||
id_ = response_.json()["id"]
|
||||
basic_case["username"] = updated_name
|
||||
response = await client.patch(f"api/v1/users/{_id}", json=basic_case, headers=logged_in_headers_super_user)
|
||||
response = await client.patch(f"api/v1/users/{id_}", json=basic_case, headers=logged_in_headers_super_user)
|
||||
result = response.json()
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
|
@ -69,9 +69,9 @@ async def test_patch_user(client: AsyncClient, logged_in_headers_super_user):
|
|||
|
||||
|
||||
async def test_reset_password(client: AsyncClient, logged_in_headers, active_user):
|
||||
_id = str(active_user.id)
|
||||
id_ = str(active_user.id)
|
||||
basic_case = {"username": "string", "password": "new_password"}
|
||||
response = await client.patch(f"api/v1/users/{_id}/reset-password", json=basic_case, headers=logged_in_headers)
|
||||
response = await client.patch(f"api/v1/users/{id_}/reset-password", json=basic_case, headers=logged_in_headers)
|
||||
result = response.json()
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
|
@ -88,9 +88,9 @@ async def test_reset_password(client: AsyncClient, logged_in_headers, active_use
|
|||
|
||||
async def test_delete_user(client: AsyncClient, logged_in_headers_super_user):
|
||||
basic_case = {"username": "string", "password": "string"}
|
||||
_response = await client.post("api/v1/users/", json=basic_case)
|
||||
_id = _response.json()["id"]
|
||||
response = await client.delete(f"api/v1/users/{_id}", headers=logged_in_headers_super_user)
|
||||
response_ = await client.post("api/v1/users/", json=basic_case)
|
||||
id_ = response_.json()["id"]
|
||||
response = await client.delete(f"api/v1/users/{id_}", headers=logged_in_headers_super_user)
|
||||
result = response.json()
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
|
|
|||
|
|
@ -99,8 +99,8 @@ async def test_get_variable__typeerror(service, session: AsyncSession):
|
|||
name = "name"
|
||||
value = "value"
|
||||
field = "session_id"
|
||||
_type = CREDENTIAL_TYPE
|
||||
await service.create_variable(user_id, name, value, _type=_type, session=session)
|
||||
type_ = CREDENTIAL_TYPE
|
||||
await service.create_variable(user_id, name, value, type_=type_, session=session)
|
||||
|
||||
with pytest.raises(TypeError) as exc:
|
||||
await session.run_sync(_get_variable, service, user_id, name, field)
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ def test_url_component():
|
|||
url_component = data.URLComponent()
|
||||
url_component.set_attributes({"urls": ["https://langflow.org"]})
|
||||
# the url component can be used to load the contents of a website
|
||||
_data = url_component.fetch_content()
|
||||
assert all(value.data for value in _data)
|
||||
assert all(value.text for value in _data)
|
||||
assert all(value.source for value in _data)
|
||||
data_ = url_component.fetch_content()
|
||||
assert all(value.data for value in data_)
|
||||
assert all(value.text for value in data_)
|
||||
assert all(value.source for value in data_)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue