Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 30 additions & 6 deletions src/backend/base/langflow/components/knowledge_bases/ingestion.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,34 @@
from langflow.base.models.openai_constants import OPENAI_EMBEDDING_MODEL_NAMES
from langflow.components.processing.converter import convert_to_dataframe
from langflow.custom import Component
from langflow.io import BoolInput, DropdownInput, HandleInput, IntInput, Output, SecretStrInput, StrInput, TableInput
from langflow.io import (
BoolInput,
DropdownInput,
HandleInput,
IntInput,
Output,
SecretStrInput,
StrInput,
TableInput,
)
from langflow.schema.data import Data
from langflow.schema.dotdict import dotdict # noqa: TC001
from langflow.schema.table import EditMode
from langflow.services.auth.utils import decrypt_api_key, encrypt_api_key
from langflow.services.database.models.user.crud import get_user_by_id
from langflow.services.deps import get_settings_service, get_variable_service, session_scope
from langflow.services.deps import (
get_settings_service,
get_variable_service,
session_scope,
)

if TYPE_CHECKING:
from langflow.schema.dataframe import DataFrame

HUGGINGFACE_MODEL_NAMES = ["sentence-transformers/all-MiniLM-L6-v2", "sentence-transformers/all-mpnet-base-v2"]
HUGGINGFACE_MODEL_NAMES = [
"sentence-transformers/all-MiniLM-L6-v2",
"sentence-transformers/all-mpnet-base-v2",
]
COHERE_MODEL_NAMES = ["embed-english-v3.0", "embed-multilingual-v3.0"]

settings = get_settings_service().settings
Expand Down Expand Up @@ -65,7 +81,11 @@ class NewKnowledgeBaseInput:
"name": "create_knowledge_base",
"description": "Create new knowledge in Langflow.",
"display_name": "Create new knowledge",
"field_order": ["01_new_kb_name", "02_embedding_model", "03_api_key"],
"field_order": [
"01_new_kb_name",
"02_embedding_model",
"03_api_key",
],
"template": {
"01_new_kb_name": StrInput(
name="new_kb_name",
Expand All @@ -75,7 +95,7 @@ class NewKnowledgeBaseInput:
),
"02_embedding_model": DropdownInput(
name="embedding_model",
display_name="Model Name",
display_name="Choose Embedding",
info="Select the embedding model to use for this knowledge base.",
required=True,
options=OPENAI_EMBEDDING_MODEL_NAMES + HUGGINGFACE_MODEL_NAMES + COHERE_MODEL_NAMES,
Expand Down Expand Up @@ -343,7 +363,11 @@ def _build_column_metadata(self, config_list: list[dict[str, Any]], df_source: p
return metadata

async def _create_vector_store(
self, df_source: pd.DataFrame, config_list: list[dict[str, Any]], embedding_model: str, api_key: str
self,
df_source: pd.DataFrame,
config_list: list[dict[str, Any]],
embedding_model: str,
api_key: str,
) -> None:
"""Create vector store following Local DB component pattern."""
try:
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from "react";
import { type Dispatch, type SetStateAction, useState } from "react";
import { useHref } from "react-router-dom";
import IconComponent from "@/components/common/genericIconComponent";
import ShadTooltipComponent from "@/components/common/shadTooltipComponent";
Expand All @@ -23,7 +23,15 @@ import useFlowStore from "@/stores/flowStore";
import useFlowsManagerStore from "@/stores/flowsManagerStore";
import { cn } from "@/utils/utils";

export default function PublishDropdown() {
type PublishDropdownProps = {
openApiModal: boolean;
setOpenApiModal: Dispatch<SetStateAction<boolean>>;
};

export default function PublishDropdown({
openApiModal,
setOpenApiModal,
}: PublishDropdownProps) {
const location = useHref("/");
const domain = window.location.origin + location;
const [openEmbedModal, setOpenEmbedModal] = useState(false);
Expand All @@ -39,7 +47,6 @@ export default function PublishDropdown() {
const isPublished = currentFlow?.access_type === "PUBLIC";
const hasIO = useFlowStore((state) => state.hasIO);
const isAuth = useAuthStore((state) => !!state.autoLogin);
const [openApiModal, setOpenApiModal] = useState(false);
const [openExportModal, setOpenExportModal] = useState(false);

const handlePublishedSwitch = async (checked: boolean) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import { useState } from "react";
import type { Dispatch, SetStateAction } from "react";
import useFlowStore from "@/stores/flowStore";
import PublishDropdown from "./deploy-dropdown";
import PlaygroundButton from "./playground-button";

export default function FlowToolbarOptions() {
const [open, setOpen] = useState<boolean>(false);
type FlowToolbarOptionsProps = {
open: boolean;
setOpen: Dispatch<SetStateAction<boolean>>;
openApiModal: boolean;
setOpenApiModal: Dispatch<SetStateAction<boolean>>;
};
const FlowToolbarOptions = ({
open,
setOpen,
openApiModal,
setOpenApiModal,
}: FlowToolbarOptionsProps) => {
const hasIO = useFlowStore((state) => state.hasIO);

return (
Expand All @@ -17,7 +27,12 @@ export default function FlowToolbarOptions() {
canvasOpen
/>
</div>
<PublishDropdown />
<PublishDropdown
openApiModal={openApiModal}
setOpenApiModal={setOpenApiModal}
/>
</div>
);
}
};

export default FlowToolbarOptions;
33 changes: 17 additions & 16 deletions src/frontend/src/components/core/flowToolbarComponent/index.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
import { Panel } from "@xyflow/react";
import { memo, useEffect, useMemo, useState } from "react";
import { memo, useEffect, useState } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import ShadTooltip from "@/components/common/shadTooltipComponent";
import { track } from "@/customization/utils/analytics";
import ShareModal from "../../../modals/shareModal";
import useFlowStore from "../../../stores/flowStore";
import { useShortcutsStore } from "../../../stores/shortcuts";
import { useStoreStore } from "../../../stores/storeStore";
import { classNames, cn, isThereModal } from "../../../utils/utils";
import ForwardedIconComponent from "../../common/genericIconComponent";
import { cn, isThereModal } from "../../../utils/utils";
import FlowToolbarOptions from "./components/flow-toolbar-options";

const FlowToolbar = memo(function FlowToolbar(): JSX.Element {
const preventDefault = true;
const [open, setOpen] = useState<boolean>(false);
const [openCodeModal, setOpenCodeModal] = useState<boolean>(false);
const [openApiModal, setOpenApiModal] = useState<boolean>(false);
const [openShareModal, setOpenShareModal] = useState<boolean>(false);
function handleAPIWShortcut(e: KeyboardEvent) {
if (isThereModal() && !openCodeModal) return;
setOpenCodeModal((oldOpen) => !oldOpen);
}
const handleAPIWShortcut = (e: KeyboardEvent) => {
if (isThereModal() && !openApiModal) return;
setOpenApiModal((oldOpen) => !oldOpen);
};

function handleChatWShortcut(e: KeyboardEvent) {
const handleChatWShortcut = (e: KeyboardEvent) => {
if (isThereModal() && !open) return;
if (useFlowStore.getState().hasIO) {
setOpen((oldState) => !oldState);
}
}
};

function handleShareWShortcut(e: KeyboardEvent) {
const handleShareWShortcut = (e: KeyboardEvent) => {
if (isThereModal() && !openShareModal) return;
setOpenShareModal((oldState) => !oldState);
}
};

const openPlayground = useShortcutsStore((state) => state.openPlayground);
const api = useShortcutsStore((state) => state.api);
Expand All @@ -55,7 +51,12 @@ const FlowToolbar = memo(function FlowToolbar(): JSX.Element {
"hover:shadow-round-btn-shadow flex h-11 items-center justify-center gap-7 rounded-md border bg-background px-1.5 shadow transition-all",
)}
>
<FlowToolbarOptions />
<FlowToolbarOptions
open={open}
setOpen={setOpen}
openApiModal={openApiModal}
setOpenApiModal={setOpenApiModal}
/>
</div>
</Panel>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import type {
NewValueParams,
RowClickedEvent,
SelectionChangedEvent,
} from "ag-grid-community";
import type { RowClickedEvent, SelectionChangedEvent } from "ag-grid-community";
import type { AgGridReact } from "ag-grid-react";
import { useRef, useState } from "react";
import { useParams } from "react-router-dom";
Expand Down Expand Up @@ -106,12 +102,6 @@ const KnowledgeBasesTab = ({
setIsDeleteModalOpen(false);
};

const handleRename = (params: NewValueParams<any, any>) => {
setSuccessData({
title: "Knowledge Base renamed successfully!",
});
};

const handleDelete = (knowledgeBase: KnowledgeBaseInfo) => {
setKnowledgeBaseToDelete(knowledgeBase);
setIsDeleteModalOpen(true);
Expand Down Expand Up @@ -163,7 +153,7 @@ const KnowledgeBasesTab = ({
}
};

const columnDefs = createKnowledgeBaseColumns(handleRename, handleDelete);
const columnDefs = createKnowledgeBaseColumns();

if (isLoading || !knowledgeBases || !Array.isArray(knowledgeBases)) {
return (
Expand Down Expand Up @@ -211,13 +201,6 @@ const KnowledgeBasesTab = ({
hide_options: true,
}}
suppressRowClickSelection={!isShiftPressed}
editable={[
{
field: "name",
onUpdate: handleRename,
editableCell: true,
},
]}
rowSelection="multiple"
onSelectionChanged={handleSelectionChange}
onRowClicked={handleRowClick}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import type { ColDef, NewValueParams } from "ag-grid-community";
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import { Button } from "@/components/ui/button";
import type { ColDef } from "ag-grid-community";
import { formatFileSize } from "@/utils/stringManipulation";
import {
formatAverageChunkSize,
formatNumber,
} from "../utils/knowledgeBaseUtils";

export const createKnowledgeBaseColumns = (
onRename?: (params: NewValueParams<any, any>) => void,
onDelete?: (knowledgeBase: any) => void,
): ColDef[] => {
export const createKnowledgeBaseColumns = (): ColDef[] => {
const baseCellClass =
"text-muted-foreground cursor-pointer select-text group-[.no-select-cells]:cursor-default group-[.no-select-cells]:select-none";

Expand All @@ -19,9 +14,10 @@ export const createKnowledgeBaseColumns = (
headerName: "Name",
field: "name",
flex: 2,
sortable: false,
headerCheckboxSelection: true,
checkboxSelection: true,
editable: true,
editable: false,
filter: "agTextColumnFilter",
cellClass: baseCellClass,
cellRenderer: (params) => (
Expand All @@ -35,7 +31,8 @@ export const createKnowledgeBaseColumns = (
{
headerName: "Embedding Model",
field: "embedding_provider",
flex: 1.2,
flex: 2,
sortable: false,
filter: "agTextColumnFilter",
editable: false,
cellClass: baseCellClass,
Expand All @@ -45,15 +42,17 @@ export const createKnowledgeBaseColumns = (
{
headerName: "Size",
field: "size",
flex: 0.8,
flex: 1,
sortable: false,
valueFormatter: (params) => formatFileSize(params.value),
editable: false,
cellClass: baseCellClass,
},
{
headerName: "Words",
field: "words",
flex: 0.8,
flex: 1,
sortable: false,
editable: false,
cellClass: baseCellClass,
valueFormatter: (params) => formatNumber(params.value),
Expand All @@ -62,14 +61,16 @@ export const createKnowledgeBaseColumns = (
headerName: "Characters",
field: "characters",
flex: 1,
sortable: false,
editable: false,
cellClass: baseCellClass,
valueFormatter: (params) => formatNumber(params.value),
},
{
headerName: "Chunks",
field: "chunks",
flex: 0.7,
flex: 1,
sortable: false,
editable: false,
cellClass: baseCellClass,
valueFormatter: (params) => formatNumber(params.value),
Expand All @@ -78,38 +79,10 @@ export const createKnowledgeBaseColumns = (
headerName: "Avg Chunks",
field: "avg_chunk_size",
flex: 1,
sortable: false,
editable: false,
cellClass: baseCellClass,
valueFormatter: (params) => formatAverageChunkSize(params.value),
},
{
maxWidth: 60,
editable: false,
resizable: false,
cellClass: "cursor-default",
cellRenderer: (params) => {
const handleDeleteClick = () => {
if (onDelete) {
onDelete(params.data);
}
};

return (
<div className="flex h-full cursor-default items-center justify-center">
<Button
variant="ghost"
size="iconMd"
onClick={handleDeleteClick}
className="hover:bg-destructive/10"
>
<ForwardedIconComponent
name="Trash2"
className="h-4 w-4 text-destructive"
/>
</Button>
</div>
);
},
},
];
};
12 changes: 8 additions & 4 deletions src/frontend/tests/extended/features/mcp-server-tab.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,16 @@ test(
// Verify actions modal is open
await expect(page.getByText("MCP Server Tools")).toBeVisible();

const isCheckedAgainAgain = await page
const persistedCheckbox = page
.locator('input[data-ref="eInput"]')
.first()
.isChecked();
.first();

if (!(await persistedCheckbox.isChecked())) {
await persistedCheckbox.click();
await page.waitForTimeout(300);
}

expect(isCheckedAgainAgain).toBeTruthy();
await expect(persistedCheckbox).toBeChecked();

await page.locator('input[data-ref="eInput"]').first().click();
await page.waitForTimeout(1000);
Expand Down
Loading