1
1
import React , { useState } from 'react'
2
- import { TextField , Button , Box , Typography , Table , TableHead , TableBody , TableRow , TableCell , Paper , IconButton , Dialog , DialogTitle , styled } from '@mui/material'
3
- import apiClient , { postAbortableStream } from '../../util/apiClient'
2
+ import { TextField , Button , Box , Typography , Table , TableHead , TableBody , TableRow , TableCell , Paper , IconButton , Dialog , DialogTitle , styled , LinearProgress } from '@mui/material'
3
+ import apiClient from '../../util/apiClient'
4
4
import { useMutation , useQuery } from '@tanstack/react-query'
5
5
import { CloudUpload , Settings } from '@mui/icons-material'
6
6
import Markdown from '../Banner/Markdown'
7
7
import { useSnackbar } from 'notistack'
8
- import { ProgressReporter } from './ProgressReporter'
8
+ import type { RagFileAttributes } from '../../../server/db/models/ragFile'
9
+ import { orderBy } from 'lodash'
10
+ import { IngestionPipelineStageKeys , IngestionPipelineStages } from '../../../shared/constants'
11
+ import { useNavigate } from 'react-router-dom'
9
12
10
13
type RagResponse = {
11
14
id : string
@@ -19,12 +22,13 @@ type RagResponse = {
19
22
20
23
type RagIndexAttributes = {
21
24
id : number
25
+ createdAt : string
26
+ updatedAt : string
22
27
metadata : {
23
28
name : string
24
29
dim : number
25
30
}
26
- numOfChunks : number
27
- filenames : string [ ]
31
+ ragFileCount : number
28
32
}
29
33
30
34
const useRagIndices = ( ) => {
@@ -38,7 +42,6 @@ const useRagIndices = () => {
38
42
39
43
return { data, ...rest }
40
44
}
41
-
42
45
const useCreateRagIndexMutation = ( ) => {
43
46
const mutation = useMutation ( {
44
47
mutationFn : async ( indexName : string ) => {
@@ -49,65 +52,16 @@ const useCreateRagIndexMutation = () => {
49
52
return mutation
50
53
}
51
54
52
- const useDeleteRagIndexMutation = ( ) => {
53
- const mutation = useMutation ( {
54
- mutationFn : async ( indexId : number ) => {
55
- const response = await apiClient . delete ( `/rag/indices/${ indexId } ` )
56
- return response . data
57
- } ,
58
- } )
59
- return mutation
60
- }
61
-
62
- const useUploadMutation = ( index : RagIndexAttributes | null ) => {
63
- const mutation = useMutation ( {
64
- mutationFn : async ( files : FileList ) => {
65
- if ( ! index ) {
66
- throw new Error ( 'Index is required' )
67
- }
68
- const formData = new FormData ( )
69
- // Append each file individually
70
- Array . from ( files ) . forEach ( ( file ) => {
71
- formData . append ( 'files' , file )
72
- } )
73
-
74
- const { stream } = await postAbortableStream ( `/rag/indices/${ index . id } /upload` , formData )
75
- if ( ! stream ) {
76
- throw new Error ( 'No stream returned from server' )
77
- }
78
-
79
- return stream
80
- } ,
81
- } )
82
- return mutation
83
- }
84
-
85
- const VisuallyHiddenInput = styled ( 'input' ) ( {
86
- clip : 'rect(0 0 0 0)' ,
87
- clipPath : 'inset(50%)' ,
88
- height : 1 ,
89
- overflow : 'hidden' ,
90
- position : 'absolute' ,
91
- bottom : 0 ,
92
- left : 0 ,
93
- whiteSpace : 'nowrap' ,
94
- width : 1 ,
95
- } )
96
-
97
55
const Rag : React . FC = ( ) => {
98
56
const { enqueueSnackbar } = useSnackbar ( )
57
+ const navigate = useNavigate ( )
99
58
const { data : indices , refetch } = useRagIndices ( )
100
59
const createIndexMutation = useCreateRagIndexMutation ( )
101
- const deleteIndexMutation = useDeleteRagIndexMutation ( )
102
60
const [ indexName , setIndexName ] = useState ( '' )
103
61
const [ selectedIndex , setSelectedIndex ] = useState < RagIndexAttributes > ( null )
104
62
const [ inputValue , setInputValue ] = useState ( '' )
105
63
const [ topK , setTopK ] = useState ( 5 )
106
64
const [ response , setResponse ] = useState < RagResponse [ ] | null > ( null )
107
- const uploadMutation = useUploadMutation ( selectedIndex )
108
- const [ modalOpen , setModalOpen ] = useState ( false )
109
- const [ stream , setStream ] = useState < ReadableStream | null > ( null )
110
- const [ filenames , setFilenames ] = useState < string [ ] > ( [ ] )
111
65
112
66
const handleSubmit = async ( event : React . FormEvent ) => {
113
67
event . preventDefault ( )
@@ -130,51 +84,8 @@ const Rag: React.FC = () => {
130
84
setInputValue ( '' )
131
85
}
132
86
133
- const handleUploadError = ( ) => {
134
- setStream ( null )
135
- }
136
-
137
87
return (
138
88
< Box sx = { { display : 'flex' , gap : 2 } } >
139
- < Dialog open = { ! ! selectedIndex && modalOpen } onClose = { ( ) => { setModalOpen ( false ) ; refetch ( ) ; } } fullWidth maxWidth = "md" >
140
- < DialogTitle > Edit { selectedIndex ?. metadata ?. name } </ DialogTitle >
141
- < Box sx = { { padding : 2 } } >
142
- < Box sx = { { display : 'flex' , gap : 2 } } >
143
- < Button component = "label" role = { undefined } variant = "contained" tabIndex = { - 1 } startIcon = { < CloudUpload /> } disabled = { uploadMutation . isPending } >
144
- { uploadMutation . isPending ? 'Uploading...' : 'Upload Files' }
145
- < VisuallyHiddenInput
146
- type = "file"
147
- onChange = { async ( event ) => {
148
- const files = event . target . files
149
- console . log ( 'Files selected:' , files )
150
- if ( files && files . length > 0 ) {
151
- const stream = await uploadMutation . mutateAsync ( files )
152
- setFilenames ( Array . from ( files ) . map ( ( file ) => file . name ) )
153
- setStream ( stream )
154
- }
155
- } }
156
- multiple
157
- />
158
- </ Button >
159
- < Button
160
- variant = "text"
161
- color = "error"
162
- onClick = { async ( ) => {
163
- if ( selectedIndex && window . confirm ( `Are you sure you want to delete index ${ selectedIndex . metadata . name } ?` ) ) {
164
- await deleteIndexMutation . mutateAsync ( selectedIndex . id )
165
- setSelectedIndex ( null )
166
- refetch ( )
167
- }
168
- } }
169
- >
170
- Delete Index
171
- </ Button >
172
- </ Box >
173
- < Box mt = { 2 } >
174
- < ProgressReporter filenames = { filenames } stream = { stream } onError = { handleUploadError } />
175
- </ Box >
176
- </ Box >
177
- </ Dialog >
178
89
< Box >
179
90
< Typography variant = "h4" mb = "1rem" >
180
91
RAG Indices
@@ -185,9 +96,9 @@ const Rag: React.FC = () => {
185
96
variant = "contained"
186
97
color = "primary"
187
98
onClick = { async ( ) => {
188
- await createIndexMutation . mutateAsync ( indexName )
99
+ const newIndex = await createIndexMutation . mutateAsync ( indexName )
189
100
setIndexName ( '' )
190
- refetch ( )
101
+ navigate ( `/rag/ ${ newIndex . id } ` )
191
102
} }
192
103
>
193
104
Create Index
@@ -208,40 +119,23 @@ const Rag: React.FC = () => {
208
119
< TableRow >
209
120
< TableCell > ID</ TableCell >
210
121
< TableCell > Name</ TableCell >
211
- < TableCell > Files</ TableCell >
212
- < TableCell > Dim</ TableCell >
213
- < TableCell > Num chunks</ TableCell >
122
+ < TableCell > Vector Dimensions</ TableCell >
123
+ < TableCell > Number of files</ TableCell >
214
124
</ TableRow >
215
125
</ TableHead >
216
126
< TableBody >
217
127
< TableRow >
218
128
< TableCell > { index . id } </ TableCell >
219
- < TableCell > { index . metadata . name } </ TableCell >
220
- < TableCell >
221
- { index . filenames . length ? (
222
- < >
223
- { index . filenames . map ( ( filename ) => (
224
- < p key = { filename } > { filename } </ p >
225
- ) ) }
226
- </ >
227
- ) : (
228
- 'No files'
229
- ) }
230
- </ TableCell >
231
- < TableCell > { index . metadata . dim } </ TableCell >
232
- < TableCell > { index . numOfChunks } </ TableCell >
129
+ < TableCell > { index . metadata ?. name } </ TableCell >
130
+ < TableCell > { index . metadata ?. dim } </ TableCell >
131
+ < TableCell > { index . ragFileCount } </ TableCell >
233
132
</ TableRow >
234
133
</ TableBody >
235
134
</ Table >
236
135
< Button disabled = { selectedIndex ?. id === index . id } onClick = { ( ) => setSelectedIndex ( index ) } >
237
136
{ selectedIndex ?. id === index . id ? 'Selected' : 'Select' }
238
137
</ Button >
239
- < IconButton
240
- onClick = { ( ) => {
241
- setSelectedIndex ( index )
242
- setModalOpen ( true )
243
- } }
244
- >
138
+ < IconButton href = { `rag/${ index . id } ` } >
245
139
< Settings />
246
140
</ IconButton >
247
141
</ Paper >
0 commit comments