Skip to content

Commit d3e9622

Browse files
authored
Merge branch 'main' into docs-deployment-folder
2 parents 163e5ae + e15fddd commit d3e9622

File tree

69 files changed

+437
-116
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+437
-116
lines changed

.github/changes-filter.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ components:
4545
- "src/frontend/tests/extended/integrations/**"
4646
- "src/frontend/tests/extended/features/**"
4747
- "src/frontend/tests/extended/regression/**"
48+
- "src/backend/base/langflow/custom/**"
4849

4950
workspace:
5051
- "src/backend/base/langflow/inputs/**"

src/backend/base/langflow/api/v1/chat.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ async def try_running_celery_task(vertex, user_id):
6969
return vertex
7070

7171

72-
@router.post("/build/{flow_id}/vertices")
72+
@router.post("/build/{flow_id}/vertices", deprecated=True)
7373
async def retrieve_vertices_order(
7474
*,
7575
flow_id: uuid.UUID,
@@ -471,7 +471,7 @@ async def listen_for_disconnect(self, receive: Receive) -> None:
471471
break
472472

473473

474-
@router.post("/build/{flow_id}/vertices/{vertex_id}")
474+
@router.post("/build/{flow_id}/vertices/{vertex_id}", deprecated=True)
475475
async def build_vertex(
476476
*,
477477
flow_id: uuid.UUID,
@@ -713,7 +713,7 @@ async def _stream_vertex(flow_id: str, vertex_id: str, chat_service: ChatService
713713
yield str(StreamData(event="close", data={"message": "Stream closed"}))
714714

715715

716-
@router.get("/build/{flow_id}/{vertex_id}/stream", response_class=StreamingResponse)
716+
@router.get("/build/{flow_id}/{vertex_id}/stream", response_class=StreamingResponse, deprecated=True)
717717
async def build_vertex_stream(
718718
flow_id: uuid.UUID,
719719
vertex_id: str,

src/backend/base/langflow/base/agents/agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class LCAgentComponent(Component):
6969
]
7070

7171
outputs = [
72-
Output(display_name="Agent", name="agent", method="build_agent", hidden=True),
72+
Output(display_name="Agent", name="agent", method="build_agent", hidden=True, tool_mode=False),
7373
Output(display_name="Response", name="response", method="message_response"),
7474
]
7575

src/backend/base/langflow/base/tools/component_tool.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,24 @@ def __init__(self, component: Component, metadata: pd.DataFrame | None = None):
169169
self.component = component
170170
self.metadata = metadata
171171

172+
def _should_skip_output(self, output: Output) -> bool:
173+
"""Determines if an output should be skipped when creating tools.
174+
175+
Args:
176+
output (Output): The output to check.
177+
178+
Returns:
179+
bool: True if the output should be skipped, False otherwise.
180+
181+
The output will be skipped if:
182+
- tool_mode is False (output is not meant to be used as a tool)
183+
- output name matches TOOL_OUTPUT_NAME
184+
- output types contain any of the tool types in TOOL_TYPES_SET
185+
"""
186+
return not output.tool_mode or (
187+
output.name == TOOL_OUTPUT_NAME or any(tool_type in output.types for tool_type in TOOL_TYPES_SET)
188+
)
189+
172190
def get_tools(
173191
self,
174192
tool_name: str | None = None,
@@ -178,7 +196,7 @@ def get_tools(
178196
) -> list[BaseTool]:
179197
tools = []
180198
for output in self.component.outputs:
181-
if output.name == TOOL_OUTPUT_NAME or any(tool_type in output.types for tool_type in TOOL_TYPES_SET):
199+
if self._should_skip_output(output):
182200
continue
183201

184202
if not output.method:

src/backend/base/langflow/components/agents/agent.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
from langflow.components.helpers import CurrentDateComponent
1111
from langflow.components.helpers.memory import MemoryComponent
1212
from langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent
13+
from langflow.custom.custom_component.component import _get_component_toolkit
1314
from langflow.custom.utils import update_component_build_config
15+
from langflow.field_typing import Tool
1416
from langflow.io import BoolInput, DropdownInput, MultilineInput, Output
1517
from langflow.logging import logger
1618
from langflow.schema.dotdict import dotdict
@@ -84,8 +86,7 @@ async def message_response(self) -> Message:
8486
if not isinstance(self.tools, list): # type: ignore[has-type]
8587
self.tools = []
8688
# Convert CurrentDateComponent to a StructuredTool
87-
current_date_tool = (await CurrentDateComponent().to_toolkit()).pop(0)
88-
# current_date_tool = CurrentDateComponent().to_toolkit()[0]
89+
current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)
8990
if isinstance(current_date_tool, StructuredTool):
9091
self.tools.append(current_date_tool)
9192
else:
@@ -122,7 +123,7 @@ async def get_memory_data(self):
122123
# filter out empty values
123124
memory_kwargs = {k: v for k, v in memory_kwargs.items() if v}
124125

125-
return await MemoryComponent().set(**memory_kwargs).retrieve_messages()
126+
return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()
126127

127128
def get_llm(self):
128129
if isinstance(self.agent_llm, str):
@@ -265,3 +266,16 @@ async def update_build_config(
265266
component_class, build_config, field_value, "model_name"
266267
)
267268
return dotdict({k: v.to_dict() if hasattr(v, "to_dict") else v for k, v in build_config.items()})
269+
270+
async def to_toolkit(self) -> list[Tool]:
271+
component_toolkit = _get_component_toolkit()
272+
tools_names = self._build_tools_names()
273+
agent_description = self.get_tool_description()
274+
# TODO: Agent Description Depreciated Feature to be removed
275+
description = f"{agent_description}{tools_names}"
276+
tools = component_toolkit(component=self).get_tools(
277+
tool_name=self.get_tool_name(), tool_description=description, callbacks=self.get_langchain_callbacks()
278+
)
279+
if hasattr(self, "tools_metadata"):
280+
tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)
281+
return tools

src/backend/base/langflow/components/embeddings/text_embedder.py

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,46 +38,26 @@ def generate_embeddings(self) -> Data:
3838
embedding_model: Embeddings = self.embedding_model
3939
message: Message = self.message
4040

41-
# Validate embedding model
42-
if not embedding_model:
43-
msg = "Embedding model not provided"
41+
# Combine validation checks to reduce nesting
42+
if not embedding_model or not hasattr(embedding_model, "embed_documents"):
43+
msg = "Invalid or incompatible embedding model"
4444
raise ValueError(msg)
4545

46-
# Extract the text content from the message
4746
text_content = message.text if message and message.text else ""
4847
if not text_content:
4948
msg = "No text content found in message"
5049
raise ValueError(msg)
5150

52-
# Check if the embedding model has the required attributes
53-
if not hasattr(embedding_model, "client") or not embedding_model.client:
54-
msg = "Embedding model client not properly initialized"
55-
raise ValueError(msg)
56-
57-
# Ensure the base URL has proper protocol
58-
if hasattr(embedding_model.client, "base_url"):
59-
base_url = embedding_model.client.base_url
60-
if not base_url.startswith(("http://", "https://")):
61-
embedding_model.client.base_url = f"https://{base_url}"
62-
63-
# Generate embeddings using the provided embedding model
6451
embeddings = embedding_model.embed_documents([text_content])
65-
66-
# Validate embeddings output
6752
if not embeddings or not isinstance(embeddings, list):
6853
msg = "Invalid embeddings generated"
6954
raise ValueError(msg)
7055

7156
embedding_vector = embeddings[0]
72-
57+
self.status = {"text": text_content, "embeddings": embedding_vector}
58+
return Data(data={"text": text_content, "embeddings": embedding_vector})
7359
except Exception as e:
7460
logging.exception("Error generating embeddings")
75-
# Return empty data with error status
7661
error_data = Data(data={"text": "", "embeddings": [], "error": str(e)})
7762
self.status = {"error": str(e)}
7863
return error_data
79-
80-
# Create a Data object to encapsulate the results
81-
result_data = Data(data={"text": text_content, "embeddings": embedding_vector})
82-
self.status = {"text": text_content, "embeddings": embedding_vector}
83-
return result_data

src/backend/base/langflow/components/langchain_utilities/csv_agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class CSVAgentComponent(LCAgentComponent):
5656

5757
outputs = [
5858
Output(display_name="Response", name="response", method="build_agent_response"),
59-
Output(display_name="Agent", name="agent", method="build_agent", hidden=True),
59+
Output(display_name="Agent", name="agent", method="build_agent", hidden=True, tool_mode=False),
6060
]
6161

6262
def _path(self) -> str:

src/backend/base/langflow/components/langchain_utilities/tool_calling.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from langchain_core.prompts import ChatPromptTemplate
33

44
from langflow.base.agents.agent import LCToolsAgentComponent
5+
from langflow.custom.custom_component.component import _get_component_toolkit
6+
from langflow.field_typing import Tool
57
from langflow.inputs import MessageTextInput
68
from langflow.inputs.inputs import DataInput, HandleInput
79
from langflow.schema import Data
@@ -54,3 +56,11 @@ def create_agent_runnable(self):
5456
except NotImplementedError as e:
5557
message = f"{self.display_name} does not support tool calling. Please try using a compatible model."
5658
raise NotImplementedError(message) from e
59+
60+
async def to_toolkit(self) -> list[Tool]:
61+
component_toolkit = _get_component_toolkit()
62+
toolkit = component_toolkit(component=self)
63+
tools = toolkit.get_tools(callbacks=self.get_langchain_callbacks())
64+
if hasattr(self, "tools_metadata"):
65+
tools = toolkit.update_tools_metadata(tools=tools)
66+
return tools

0 commit comments

Comments
 (0)