Skip to content

Commit 9230307

Browse files
committed
fixed chunks
1 parent a74afc2 commit 9230307

7 files changed

Lines changed: 418 additions & 21 deletions

File tree

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ class BulkDeleteRequest(BaseModel):
4747
kb_names: list[str]
4848

4949

50+
class ChunkInfo(BaseModel):
51+
id: str
52+
content: str
53+
char_count: int
54+
metadata: dict | None = None
55+
56+
5057
def get_kb_root_path() -> Path:
5158
"""Get the knowledge bases root path."""
5259
return _get_knowledge_bases_dir()
@@ -385,6 +392,51 @@ async def get_knowledge_base(kb_name: str, current_user: CurrentActiveUser) -> K
385392
raise HTTPException(status_code=500, detail=f"Error getting knowledge base '{kb_name}': {e!s}") from e
386393

387394

395+
@router.get("/{kb_name}/chunks", status_code=HTTPStatus.OK)
396+
async def get_knowledge_base_chunks(kb_name: str, current_user: CurrentActiveUser) -> list[ChunkInfo]:
397+
"""Get all chunks from a specific knowledge base."""
398+
try:
399+
kb_root_path = get_kb_root_path()
400+
kb_user = current_user.username
401+
kb_path = kb_root_path / kb_user / kb_name
402+
403+
if not kb_path.exists() or not kb_path.is_dir():
404+
raise HTTPException(status_code=404, detail=f"Knowledge base '{kb_name}' not found")
405+
406+
# Create vector store
407+
chroma = Chroma(
408+
persist_directory=str(kb_path),
409+
collection_name=kb_name,
410+
)
411+
412+
# Access the raw collection
413+
collection = chroma._collection # noqa: SLF001
414+
415+
# Fetch all documents and metadata
416+
results = collection.get(include=["documents", "metadatas"])
417+
418+
chunks = []
419+
for i, (doc_id, document, metadata) in enumerate(
420+
zip(results["ids"], results["documents"], results["metadatas"], strict=False)
421+
):
422+
content = document or ""
423+
chunks.append(
424+
ChunkInfo(
425+
id=doc_id,
426+
content=content,
427+
char_count=len(content),
428+
metadata=metadata,
429+
)
430+
)
431+
432+
return chunks
433+
434+
except HTTPException:
435+
raise
436+
except Exception as e:
437+
raise HTTPException(status_code=500, detail=f"Error getting chunks for '{kb_name}': {e!s}") from e
438+
439+
388440
@router.delete("/{kb_name}", status_code=HTTPStatus.OK)
389441
async def delete_knowledge_base(kb_name: str, current_user: CurrentActiveUser) -> dict[str, str]:
390442
"""Delete a specific knowledge base."""
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import type { UseQueryResult } from "@tanstack/react-query";
2+
import type { useQueryFunctionType } from "@/types/api";
3+
import { api } from "../../api";
4+
import { getURL } from "../../helpers/constants";
5+
import { UseRequestProcessor } from "../../services/request-processor";
6+
7+
export interface ChunkInfo {
8+
id: string;
9+
content: string;
10+
char_count: number;
11+
metadata: Record<string, unknown> | null;
12+
}
13+
14+
interface GetKnowledgeBaseChunksParams {
15+
kb_name: string;
16+
}
17+
18+
export const useGetKnowledgeBaseChunks: useQueryFunctionType<
19+
GetKnowledgeBaseChunksParams,
20+
ChunkInfo[]
21+
> = (params, options?) => {
22+
const { query } = UseRequestProcessor();
23+
24+
const getChunksFn = async (): Promise<ChunkInfo[]> => {
25+
const res = await api.get(
26+
`${getURL("KNOWLEDGE_BASES")}/${params?.kb_name}/chunks`,
27+
);
28+
return res.data;
29+
};
30+
31+
const queryResult: UseQueryResult<ChunkInfo[], any> = query(
32+
["useGetKnowledgeBaseChunks", params?.kb_name],
33+
getChunksFn,
34+
{
35+
enabled: !!params?.kb_name,
36+
refetchOnWindowFocus: false,
37+
...options,
38+
},
39+
);
40+
41+
return queryResult;
42+
};

src/frontend/src/pages/MainPage/pages/filesPage/components/KnowledgeBasesTab.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,10 @@ const KnowledgeBasesTab = ({
159159
}
160160
};
161161

162-
const columnDefs = createKnowledgeBaseColumns();
162+
const columnDefs = createKnowledgeBaseColumns({
163+
onViewChunks: onRowClick,
164+
onDelete: handleDelete,
165+
});
163166

164167
if (isLoading || !knowledgeBases || !Array.isArray(knowledgeBases)) {
165168
return (

src/frontend/src/pages/MainPage/pages/filesPage/config/knowledgeBaseColumns.tsx

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,27 @@
11
import type { ColDef } from "ag-grid-community";
2+
import ForwardedIconComponent from "@/components/common/genericIconComponent";
3+
import { Button } from "@/components/ui/button";
4+
import {
5+
DropdownMenu,
6+
DropdownMenuContent,
7+
DropdownMenuItem,
8+
DropdownMenuTrigger,
9+
} from "@/components/ui/dropdown-menu";
10+
import type { KnowledgeBaseInfo } from "@/controllers/API/queries/knowledge-bases/use-get-knowledge-bases";
211
import { formatFileSize } from "@/utils/stringManipulation";
312
import {
413
formatAverageChunkSize,
514
formatNumber,
615
} from "../utils/knowledgeBaseUtils";
716

8-
export const createKnowledgeBaseColumns = (): ColDef[] => {
17+
export interface KnowledgeBaseColumnsCallbacks {
18+
onViewChunks?: (knowledgeBase: KnowledgeBaseInfo) => void;
19+
onDelete?: (knowledgeBase: KnowledgeBaseInfo) => void;
20+
}
21+
22+
export const createKnowledgeBaseColumns = (
23+
callbacks?: KnowledgeBaseColumnsCallbacks,
24+
): ColDef[] => {
925
const baseCellClass =
1026
"text-muted-foreground cursor-pointer select-text group-[.no-select-cells]:cursor-default group-[.no-select-cells]:select-none";
1127

@@ -38,15 +54,6 @@ export const createKnowledgeBaseColumns = (): ColDef[] => {
3854
cellClass: baseCellClass,
3955
valueGetter: (params) => params.data.type || "—",
4056
},
41-
{
42-
headerName: "Owner",
43-
field: "owner",
44-
flex: 1,
45-
sortable: false,
46-
editable: false,
47-
cellClass: baseCellClass,
48-
valueGetter: (params) => params.data.owner || "—",
49-
},
5057
{
5158
headerName: "Chunks",
5259
field: "chunks",
@@ -71,8 +78,57 @@ export const createKnowledgeBaseColumns = (): ColDef[] => {
7178
flex: 1,
7279
sortable: false,
7380
editable: false,
81+
resizable: false,
7482
cellClass: baseCellClass,
7583
valueGetter: (params) => params.data.status || "—",
7684
},
85+
{
86+
headerName: "",
87+
field: "actions",
88+
width: 65,
89+
minWidth: 65,
90+
sortable: false,
91+
editable: false,
92+
resizable: false,
93+
suppressMovable: true,
94+
cellClass: "flex items-center justify-center",
95+
cellRenderer: (params: { data: KnowledgeBaseInfo }) => (
96+
<DropdownMenu>
97+
<DropdownMenuTrigger asChild>
98+
<Button
99+
variant="ghost"
100+
size="icon"
101+
onClick={(e) => e.stopPropagation()}
102+
>
103+
<ForwardedIconComponent
104+
name="EllipsisVertical"
105+
className="h-4 w-4 text-muted-foreground"
106+
/>
107+
</Button>
108+
</DropdownMenuTrigger>
109+
<DropdownMenuContent align="end">
110+
<DropdownMenuItem
111+
onClick={(e) => {
112+
e.stopPropagation();
113+
callbacks?.onViewChunks?.(params.data);
114+
}}
115+
>
116+
<ForwardedIconComponent name="Layers" className="mr-2 h-4 w-4" />
117+
View Chunks
118+
</DropdownMenuItem>
119+
<DropdownMenuItem
120+
onClick={(e) => {
121+
e.stopPropagation();
122+
callbacks?.onDelete?.(params.data);
123+
}}
124+
className="text-destructive focus:text-destructive"
125+
>
126+
<ForwardedIconComponent name="Trash2" className="mr-2 h-4 w-4" />
127+
Delete
128+
</DropdownMenuItem>
129+
</DropdownMenuContent>
130+
</DropdownMenu>
131+
),
132+
},
77133
];
78134
};

src/frontend/src/pages/MainPage/pages/knowledgePage/index.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from "react";
22
import ForwardedIconComponent from "@/components/common/genericIconComponent";
33
import { SidebarTrigger } from "@/components/ui/sidebar";
44
import type { KnowledgeBaseInfo } from "@/controllers/API/queries/knowledge-bases/use-get-knowledge-bases";
5+
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
56
import KnowledgeBaseDrawer from "../filesPage/components/KnowledgeBaseDrawer";
67
import KnowledgeBasesTab from "../filesPage/components/KnowledgeBasesTab";
78

@@ -16,6 +17,7 @@ export const KnowledgePage = () => {
1617
const [selectedKnowledgeBase, setSelectedKnowledgeBase] =
1718
useState<KnowledgeBaseInfo | null>(null);
1819

20+
const navigate = useCustomNavigate();
1921
const drawerRef = useRef<HTMLDivElement>(null);
2022

2123
useEffect(() => {
@@ -66,12 +68,7 @@ export const KnowledgePage = () => {
6668
}, [isDrawerOpen]);
6769

6870
const handleKnowledgeBaseSelect = (knowledgeBase: KnowledgeBaseInfo) => {
69-
if (isDrawerOpen) {
70-
closeDrawer();
71-
} else {
72-
setSelectedKnowledgeBase(knowledgeBase);
73-
// setIsDrawerOpen(true);
74-
}
71+
navigate(`/assets/knowledge-bases/${knowledgeBase.id}/chunks`);
7572
};
7673

7774
const closeDrawer = () => {

0 commit comments

Comments
 (0)