Skip to content

Commit 11634bb

Browse files
lucaseduoliautofix-ci[bot]Cristhianzl
authored andcommitted
feat: redesign sidebar with new components and features (langflow-ai#4307)
* Added required ShadCN Components * Added required colors * Added required icons * Changed backend to not return beta tag * Added sidebar categories api call * Added required use-mobile hook * Refactored icons to allow sizing * Added type for sidebar category * Allowed no name on shortcut display * Added flow sidebar component that uses ShadCN sidebar * Added SidebarDraggableComponent with the new style * Replaced sidebar with current one on FlowPage * Added sidebar fixed footer with options to go to store and add custom component * Updated sidebar categories * Updated background color for sidebar * Changed size of Components title * Added color to PageComponent * Added required icons * added CustomComponent category and removed custom component from helpers * create hook useAddComponent * Use hook to add components both in PageComponent and flowSidebarComponent * Implement search * Implement searching and filtering by clicking on edge * Added check to see if store is present * Updated colors to match new color schema * Changed styling of filter component * Added Beta and Legacy badges * Implement Show Beta Components and Show Legacy Components * Fixed styling for sidebar config when collapsed * Refactored search to filter for tags * Refactor useeffect * Updated config button styling * Implemented keyboard navigation * Fixed filtering * Updated color of canvas * Implemented disclosure on sidebar settings and fetched bundles * Added temp sidebar bundles * Fixed badge styling * Added bundles to categories response in frontend * Added legacy to components * Added link to store instead of langflow.store * Added required data-testids * Fixed tests to use new data-testids and new sidebar disposition * Fix github star bug * Fixed tests that used the custom component * Changed test to test beta and legacy checkers * added a test for keyboard navigation on sidebar * Added a test to check component add by hover the plus button * [autofix.ci] apply automated fixes * updated sidebar switch change * Removed changes on Backend and used only Frontend constants for categories * merge fix * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * 📝 (custom_component): Add CustomComponent class with input and output definitions 📝 (custom_component): Create CustomComponent class with display name, description, and documentation link 📝 (custom_component): Define input and output properties for CustomComponent class 📝 (custom_component): Implement build_output method in CustomComponent class 📝 (Ollama): Remove unnecessary whitespace in SvgOllama component * formatting * ♻️ (custom_component/__init__.py): refactor import statement to match the correct case of the file name for better consistency and readability * 🔧 (FlowPage/index.tsx): remove FlowToolbar component when view prop is false to improve UI consistency * 📝 (integration-side-bar.spec.ts): Comment out unnecessary code blocks related to API requests and modals to improve test readability and focus on the main test scenarios. * [autofix.ci] apply automated fixes * ✨ (flowSidebarComponent/index.tsx): add data-testid attribute to Sidebar component for testing purposes 🔧 (integration-side-bar.spec.ts): update test to use new data-testid attribute 'shad-sidebar' for Sidebar component to match changes in the codebase * ✨ (stop-building.spec.ts): refactor test case to use a more descriptive test element for clicking on the sidebar custom component button * format * 🐛 (AstraDB): Fix variable naming inconsistency for isDark to isdark in AstraDB component 🐛 (HCD): Fix variable naming inconsistency for isDark to isdark in HCD component 🐛 (index.tsx): Fix variable naming inconsistency for isDark to isdark in index.tsx files 📝 (flowSidebarComponent): Refactor search functionality to normalize search terms and improve metadata search 📝 (filterEdge-shard-1.spec.ts): Update test to check visibility of specific model specs in the sidebar * [autofix.ci] apply automated fixes * ✅ (decisionFlow.spec.ts): add a delay of 500ms to ensure proper timing in the test case execution * ✨ (decisionFlow.spec.ts): Update the X positions of elements in the flow to improve the visual representation and alignment of the elements. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: cristhianzl <[email protected]>
1 parent 8a0e21e commit 11634bb

File tree

122 files changed

+2367
-804
lines changed

Some content is hidden

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

122 files changed

+2367
-804
lines changed

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

+31-13
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,16 @@
66
from uuid import UUID
77

88
import sqlalchemy as sa
9-
from fastapi import APIRouter, BackgroundTasks, Body, Depends, HTTPException, Request, UploadFile, status
9+
from fastapi import (
10+
APIRouter,
11+
BackgroundTasks,
12+
Body,
13+
Depends,
14+
HTTPException,
15+
Request,
16+
UploadFile,
17+
status,
18+
)
1019
from loguru import logger
1120
from sqlmodel import select
1221

@@ -17,7 +26,6 @@
1726
CustomComponentResponse,
1827
InputValueRequest,
1928
RunResponse,
20-
SidebarCategoriesResponse,
2129
SimplifiedAPIRequest,
2230
TaskStatusResponse,
2331
UpdateCustomComponentRequest,
@@ -37,7 +45,9 @@
3745
from langflow.services.cache.utils import save_uploaded_file
3846
from langflow.services.database.models.flow import Flow
3947
from langflow.services.database.models.flow.model import FlowRead
40-
from langflow.services.database.models.flow.utils import get_all_webhook_components_in_flow
48+
from langflow.services.database.models.flow.utils import (
49+
get_all_webhook_components_in_flow,
50+
)
4151
from langflow.services.database.models.user.model import User, UserRead
4252
from langflow.services.deps import (
4353
get_session_service,
@@ -47,7 +57,6 @@
4757
)
4858
from langflow.services.settings.feature_flags import FEATURE_FLAGS
4959
from langflow.services.telemetry.schema import RunPayload
50-
from langflow.utils.constants import SIDEBAR_CATEGORIES
5160
from langflow.utils.version import get_version_info
5261

5362
if TYPE_CHECKING:
@@ -110,7 +119,11 @@ async def simple_run_flow(
110119
graph_data = process_tweaks(graph_data, input_request.tweaks or {}, stream=stream)
111120
graph = Graph.from_payload(graph_data, flow_id=flow_id_str, user_id=str(user_id), flow_name=flow.name)
112121
inputs = [
113-
InputValueRequest(components=[], input_value=input_request.input_value, type=input_request.input_type)
122+
InputValueRequest(
123+
components=[],
124+
input_value=input_request.input_value,
125+
type=input_request.input_type,
126+
)
114127
]
115128
if input_request.output_component:
116129
outputs = [input_request.output_component]
@@ -248,7 +261,10 @@ async def simplified_run_flow(
248261
background_tasks.add_task(
249262
telemetry_service.log_package_run,
250263
RunPayload(
251-
run_is_webhook=False, run_seconds=int(end_time - start_time), run_success=True, run_error_message=""
264+
run_is_webhook=False,
265+
run_seconds=int(end_time - start_time),
266+
run_success=True,
267+
run_error_message="",
252268
),
253269
)
254270

@@ -360,7 +376,11 @@ async def webhook_run_flow(
360376
return {"message": "Task started in the background", "status": "in progress"}
361377

362378

363-
@router.post("/run/advanced/{flow_id}", response_model=RunResponse, response_model_exclude_none=True)
379+
@router.post(
380+
"/run/advanced/{flow_id}",
381+
response_model=RunResponse,
382+
response_model_exclude_none=True,
383+
)
364384
async def experimental_run_flow(
365385
*,
366386
session: DbSession,
@@ -631,11 +651,9 @@ async def get_config():
631651

632652
settings_service: SettingsService = get_settings_service()
633653

634-
return {"feature_flags": FEATURE_FLAGS, **settings_service.settings.model_dump()}
654+
return {
655+
"feature_flags": FEATURE_FLAGS,
656+
**settings_service.settings.model_dump(),
657+
}
635658
except Exception as exc:
636659
raise HTTPException(status_code=500, detail=str(exc)) from exc
637-
638-
639-
@router.get("/sidebar_categories")
640-
async def get_sidebar_categories() -> SidebarCategoriesResponse:
641-
return SidebarCategoriesResponse(categories=SIDEBAR_CATEGORIES)

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

+13-13
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@
44
from typing import Any
55
from uuid import UUID
66

7-
from pydantic import BaseModel, ConfigDict, Field, field_serializer, field_validator, model_serializer
7+
from pydantic import (
8+
BaseModel,
9+
ConfigDict,
10+
Field,
11+
field_serializer,
12+
field_validator,
13+
model_serializer,
14+
)
815

916
from langflow.graph.schema import RunOutputs
1017
from langflow.graph.utils import serialize_field
@@ -316,7 +323,11 @@ class InputValueRequest(BaseModel):
316323
},
317324
{"components": ["Component Name"], "input_value": "input_value"},
318325
{"input_value": "input_value"},
319-
{"components": ["Component Name"], "input_value": "input_value", "session": "session_id"},
326+
{
327+
"components": ["Component Name"],
328+
"input_value": "input_value",
329+
"session": "session_id",
330+
},
320331
{"input_value": "input_value", "session": "session_id"},
321332
{"type": "chat", "input_value": "input_value"},
322333
{"type": "json", "input_value": '{"key": "value"}'},
@@ -357,14 +368,3 @@ class ConfigResponse(BaseModel):
357368
auto_saving_interval: int
358369
health_check_max_retries: int
359370
max_file_size_upload: int
360-
361-
362-
class SidebarCategory(BaseModel):
363-
display_name: str
364-
name: str
365-
icon: str
366-
beta: bool = False
367-
368-
369-
class SidebarCategoriesResponse(BaseModel):
370-
categories: list[SidebarCategory]

src/backend/base/langflow/base/constants.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,15 @@
1010

1111
STREAM_INFO_TEXT = "Stream the response from the model. Streaming works only in Chat."
1212

13-
NODE_FORMAT_ATTRIBUTES = ["beta", "icon", "display_name", "output_types", "edited", "metadata"]
13+
NODE_FORMAT_ATTRIBUTES = [
14+
"beta",
15+
"legacy",
16+
"icon",
17+
"display_name",
18+
"output_types",
19+
"edited",
20+
"metadata",
21+
]
1422

1523

1624
FIELD_FORMAT_ATTRIBUTES = [

src/backend/base/langflow/components/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from . import (
22
agents,
33
chains,
4+
custom_component,
45
documentloaders,
56
embeddings,
67
helpers,
@@ -26,6 +27,7 @@
2627
"helpers",
2728
"inputs",
2829
"link_extractors",
30+
"custom_component",
2931
"memories",
3032
"models",
3133
"output_parsers",

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

+13-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,22 @@ class JsonAgentComponent(LCAgentComponent):
1414
display_name = "JsonAgent"
1515
description = "Construct a json agent from an LLM and tools."
1616
name = "JsonAgent"
17+
legacy: bool = True
1718

1819
inputs = [
1920
*LCAgentComponent._base_inputs,
20-
HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True),
21-
FileInput(name="path", display_name="File Path", file_types=["json", "yaml", "yml"], required=True),
21+
HandleInput(
22+
name="llm",
23+
display_name="Language Model",
24+
input_types=["LanguageModel"],
25+
required=True,
26+
),
27+
FileInput(
28+
name="path",
29+
display_name="File Path",
30+
file_types=["json", "yaml", "yml"],
31+
required=True,
32+
),
2233
]
2334

2435
def build_agent(self) -> AgentExecutor:

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

+13-2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,22 @@ class VectorStoreAgentComponent(LCAgentComponent):
99
display_name = "VectorStoreAgent"
1010
description = "Construct an agent from a Vector Store."
1111
name = "VectorStoreAgent"
12+
legacy: bool = True
1213

1314
inputs = [
1415
*LCAgentComponent._base_inputs,
15-
HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True),
16-
HandleInput(name="vectorstore", display_name="Vector Store", input_types=["VectorStoreInfo"], required=True),
16+
HandleInput(
17+
name="llm",
18+
display_name="Language Model",
19+
input_types=["LanguageModel"],
20+
required=True,
21+
),
22+
HandleInput(
23+
name="vectorstore",
24+
display_name="Vector Store",
25+
input_types=["VectorStoreInfo"],
26+
required=True,
27+
),
1728
]
1829

1930
def build_agent(self) -> AgentExecutor:

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@ class VectorStoreRouterAgentComponent(LCAgentComponent):
99
display_name = "VectorStoreRouterAgent"
1010
description = "Construct an agent from a Vector Store Router."
1111
name = "VectorStoreRouterAgent"
12+
legacy: bool = True
1213

1314
inputs = [
1415
*LCAgentComponent._base_inputs,
15-
HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True),
16+
HandleInput(
17+
name="llm",
18+
display_name="Language Model",
19+
input_types=["LanguageModel"],
20+
required=True,
21+
),
1622
HandleInput(
1723
name="vectorstores",
1824
display_name="Vector Stores",

src/backend/base/langflow/components/chains/conversation.py

+15-3
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,21 @@ class ConversationChainComponent(LCChainComponent):
99
display_name = "ConversationChain"
1010
description = "Chain to have a conversation and load context from memory."
1111
name = "ConversationChain"
12+
legacy: bool = True
1213

1314
inputs = [
1415
MultilineInput(
15-
name="input_value", display_name="Input", info="The input value to pass to the chain.", required=True
16+
name="input_value",
17+
display_name="Input",
18+
info="The input value to pass to the chain.",
19+
required=True,
20+
),
21+
HandleInput(
22+
name="llm",
23+
display_name="Language Model",
24+
input_types=["LanguageModel"],
25+
required=True,
1626
),
17-
HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True),
1827
HandleInput(
1928
name="memory",
2029
display_name="Memory",
@@ -28,7 +37,10 @@ def invoke_chain(self) -> Message:
2837
else:
2938
chain = ConversationChain(llm=self.llm, memory=self.memory)
3039

31-
result = chain.invoke({"input": self.input_value}, config={"callbacks": self.get_langchain_callbacks()})
40+
result = chain.invoke(
41+
{"input": self.input_value},
42+
config={"callbacks": self.get_langchain_callbacks()},
43+
)
3244
if isinstance(result, dict):
3345
result = result.get(chain.output_key, "")
3446

src/backend/base/langflow/components/chains/llm_checker.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,28 @@ class LLMCheckerChainComponent(LCChainComponent):
1010
description = "Chain for question-answering with self-verification."
1111
documentation = "https://python.langchain.com/docs/modules/chains/additional/llm_checker"
1212
name = "LLMCheckerChain"
13+
legacy: bool = True
1314

1415
inputs = [
1516
MultilineInput(
16-
name="input_value", display_name="Input", info="The input value to pass to the chain.", required=True
17+
name="input_value",
18+
display_name="Input",
19+
info="The input value to pass to the chain.",
20+
required=True,
21+
),
22+
HandleInput(
23+
name="llm",
24+
display_name="Language Model",
25+
input_types=["LanguageModel"],
26+
required=True,
1727
),
18-
HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True),
1928
]
2029

2130
def invoke_chain(self) -> Message:
2231
chain = LLMCheckerChain.from_llm(llm=self.llm)
2332
response = chain.invoke(
24-
{chain.input_key: self.input_value}, config={"callbacks": self.get_langchain_callbacks()}
33+
{chain.input_key: self.input_value},
34+
config={"callbacks": self.get_langchain_callbacks()},
2535
)
2636
result = response.get(chain.output_key, "")
2737
result = str(result)

src/backend/base/langflow/components/chains/llm_math.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,30 @@ class LLMMathChainComponent(LCChainComponent):
1111
description = "Chain that interprets a prompt and executes python code to do math."
1212
documentation = "https://python.langchain.com/docs/modules/chains/additional/llm_math"
1313
name = "LLMMathChain"
14+
legacy: bool = True
1415

1516
inputs = [
1617
MultilineInput(
17-
name="input_value", display_name="Input", info="The input value to pass to the chain.", required=True
18+
name="input_value",
19+
display_name="Input",
20+
info="The input value to pass to the chain.",
21+
required=True,
22+
),
23+
HandleInput(
24+
name="llm",
25+
display_name="Language Model",
26+
input_types=["LanguageModel"],
27+
required=True,
1828
),
19-
HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True),
2029
]
2130

2231
outputs = [Output(display_name="Text", name="text", method="invoke_chain")]
2332

2433
def invoke_chain(self) -> Message:
2534
chain = LLMMathChain.from_llm(llm=self.llm)
2635
response = chain.invoke(
27-
{chain.input_key: self.input_value}, config={"callbacks": self.get_langchain_callbacks()}
36+
{chain.input_key: self.input_value},
37+
config={"callbacks": self.get_langchain_callbacks()},
2838
)
2939
result = response.get(chain.output_key, "")
3040
result = str(result)

src/backend/base/langflow/components/chains/retrieval_qa.py

+21-4
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@ class RetrievalQAComponent(LCChainComponent):
99
display_name = "Retrieval QA"
1010
description = "Chain for question-answering querying sources from a retriever."
1111
name = "RetrievalQA"
12+
legacy: bool = True
1213

1314
inputs = [
1415
MultilineInput(
15-
name="input_value", display_name="Input", info="The input value to pass to the chain.", required=True
16+
name="input_value",
17+
display_name="Input",
18+
info="The input value to pass to the chain.",
19+
required=True,
1620
),
1721
DropdownInput(
1822
name="chain_type",
@@ -22,8 +26,18 @@ class RetrievalQAComponent(LCChainComponent):
2226
value="Stuff",
2327
advanced=True,
2428
),
25-
HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True),
26-
HandleInput(name="retriever", display_name="Retriever", input_types=["Retriever"], required=True),
29+
HandleInput(
30+
name="llm",
31+
display_name="Language Model",
32+
input_types=["LanguageModel"],
33+
required=True,
34+
),
35+
HandleInput(
36+
name="retriever",
37+
display_name="Retriever",
38+
input_types=["Retriever"],
39+
required=True,
40+
),
2741
HandleInput(
2842
name="memory",
2943
display_name="Memory",
@@ -52,7 +66,10 @@ def invoke_chain(self) -> Message:
5266
return_source_documents=True,
5367
)
5468

55-
result = runnable.invoke({"query": self.input_value}, config={"callbacks": self.get_langchain_callbacks()})
69+
result = runnable.invoke(
70+
{"query": self.input_value},
71+
config={"callbacks": self.get_langchain_callbacks()},
72+
)
5673

5774
source_docs = self.to_data(result.get("source_documents", keys=[]))
5875
result_str = str(result.get("result", ""))

0 commit comments

Comments
 (0)