diff --git a/admin/inertia/components/chat/ChatSidebar.tsx b/admin/inertia/components/chat/ChatSidebar.tsx
index a35e26b..a50cb72 100644
--- a/admin/inertia/components/chat/ChatSidebar.tsx
+++ b/admin/inertia/components/chat/ChatSidebar.tsx
@@ -3,6 +3,8 @@ import StyledButton from '../StyledButton'
import { router } from '@inertiajs/react'
import { ChatSession } from '../../../types/chat'
import { IconMessage } from '@tabler/icons-react'
+import { useState } from 'react'
+import KnowledgeBaseModal from './KnowledgeBaseModal'
interface ChatSidebarProps {
sessions: ChatSession[]
@@ -21,6 +23,8 @@ export default function ChatSidebar({
onClearHistory,
isInModal = false,
}: ChatSidebarProps) {
+ const [isKnowledgeBaseModalOpen, setIsKnowledgeBaseModalOpen] = useState(false)
+
return (
@@ -48,7 +52,7 @@ export default function ChatSidebar({
@@ -101,7 +105,7 @@ export default function ChatSidebar({
{
- router.visit('/knowledge-base')
+ setIsKnowledgeBaseModalOpen(true)
}}
icon="IconBrain"
variant="primary"
@@ -122,6 +126,9 @@ export default function ChatSidebar({
)}
+ {isKnowledgeBaseModalOpen && (
+
setIsKnowledgeBaseModalOpen(false)} />
+ )}
)
}
diff --git a/admin/inertia/components/chat/KnowledgeBaseModal.tsx b/admin/inertia/components/chat/KnowledgeBaseModal.tsx
new file mode 100644
index 0000000..cc569fa
--- /dev/null
+++ b/admin/inertia/components/chat/KnowledgeBaseModal.tsx
@@ -0,0 +1,166 @@
+import { useMutation, useQuery } from '@tanstack/react-query'
+import { useRef, useState } from 'react'
+import FileUploader from '~/components/file-uploader'
+import StyledButton from '~/components/StyledButton'
+import StyledSectionHeader from '~/components/StyledSectionHeader'
+import StyledTable from '~/components/StyledTable'
+import { useNotifications } from '~/context/NotificationContext'
+import api from '~/lib/api'
+import { IconX } from '@tabler/icons-react'
+
+interface KnowledgeBaseModalProps {
+ onClose: () => void
+}
+
+export default function KnowledgeBaseModal({ onClose }: KnowledgeBaseModalProps) {
+ const { addNotification } = useNotifications()
+ const [files, setFiles] = useState
([])
+ const fileUploaderRef = useRef>(null)
+
+ const { data: storedFiles = [], isLoading: isLoadingFiles } = useQuery({
+ queryKey: ['storedFiles'],
+ queryFn: () => api.getStoredRAGFiles(),
+ select: (data) => data || [],
+ })
+
+ const uploadMutation = useMutation({
+ mutationFn: (file: File) => api.uploadDocument(file),
+ onSuccess: (data) => {
+ addNotification({
+ type: 'success',
+ message: data?.message || 'Document uploaded and queued for processing',
+ })
+ setFiles([])
+ if (fileUploaderRef.current) {
+ fileUploaderRef.current.clear()
+ }
+ },
+ onError: (error: any) => {
+ addNotification({
+ type: 'error',
+ message: error?.message || 'Failed to upload document',
+ })
+ },
+ })
+
+ const handleUpload = () => {
+ if (files.length > 0) {
+ uploadMutation.mutate(files[0])
+ }
+ }
+
+ return (
+
+
+
+
Knowledge Base
+
+
+
+
+
+
+
+
{
+ setFiles(Array.from(uploadedFiles))
+ }}
+ />
+
+
+ Upload
+
+
+
+
+
+ Why upload documents to your Knowledge Base?
+
+
+
+
+ 1
+
+
+
+ AI Assistant Knowledge Base Integration
+
+
+ When you upload documents to your Knowledge Base, NOMAD processes and embeds
+ the content, making it directly accessible to the AI Assistant. This allows
+ the AI Assistant to reference your specific documents during conversations,
+ providing more accurate and personalized responses based on your uploaded
+ data.
+
+
+
+
+
+ 2
+
+
+
+ Enhanced Document Processing with OCR
+
+
+ NOMAD includes built-in Optical Character Recognition (OCR) capabilities,
+ allowing it to extract text from image-based documents such as scanned PDFs or
+ photos. This means that even if your documents are not in a standard text
+ format, NOMAD can still process and embed their content for AI access.
+
+
+
+
+
+ 3
+
+
+
+ Information Library Integration
+
+
+ NOMAD will automatically discover and extract any content you save to your
+ Information Library (if installed), making it instantly available to the AI
+ Assistant without any extra steps.
+
+
+
+
+
+
+
+
+
+ className="font-semibold"
+ rowLines={true}
+ columns={[
+ {
+ accessor: 'source',
+ title: 'File Name',
+ render(record) {
+ return {record.source}
+ },
+ },
+ ]}
+ data={storedFiles.map((source) => ({ source }))}
+ loading={isLoadingFiles}
+ />
+
+
+
+
+ )
+}
diff --git a/admin/inertia/pages/home.tsx b/admin/inertia/pages/home.tsx
index 6e731ea..1aababe 100644
--- a/admin/inertia/pages/home.tsx
+++ b/admin/inertia/pages/home.tsx
@@ -1,6 +1,5 @@
import {
IconBolt,
- IconBrain,
IconHelp,
IconMapRoute,
IconPlus,
@@ -12,7 +11,6 @@ import AppLayout from '~/layouts/AppLayout'
import { getServiceLink } from '~/lib/navigation'
import { ServiceSlim } from '../../types/services'
import DynamicIcon, { DynamicIconName } from '~/components/DynamicIcon'
-import { SERVICE_NAMES } from '../../constants/service_names'
import { useUpdateAvailable } from '~/hooks/useUpdateAvailable'
import Alert from '~/components/Alert'
@@ -84,17 +82,6 @@ interface DashboardItem {
poweredBy: string | null
}
-const KNOWLEDGE_BASE_ITEM: DashboardItem = {
- label: 'Knowledge Base',
- to: '/knowledge-base',
- target: '',
- description: 'Upload documents to your personal knowledge base for AI access',
- icon: ,
- installed: true,
- displayOrder: 5,
- poweredBy: null,
-}
-
export default function Home(props: {
system: {
services: ServiceSlim[]
@@ -130,9 +117,6 @@ export default function Home(props: {
// Add system items
items.push(...SYSTEM_ITEMS)
- if (props.system.services.find((s) => s.service_name === SERVICE_NAMES.OLLAMA && s.installed)) {
- items.push(KNOWLEDGE_BASE_ITEM)
- }
// Sort all items by display order
items.sort((a, b) => a.displayOrder - b.displayOrder)
diff --git a/admin/start/routes.ts b/admin/start/routes.ts
index c104b44..336ffca 100644
--- a/admin/start/routes.ts
+++ b/admin/start/routes.ts
@@ -27,7 +27,6 @@ router.get('/', [HomeController, 'index'])
router.get('/home', [HomeController, 'home'])
router.on('/about').renderInertia('about')
router.get('/chat', [ChatsController, 'inertia'])
-router.on('/knowledge-base').renderInertia('knowledge-base')
router.get('/maps', [MapsController, 'index'])
router.get('/easy-setup', [EasySetupController, 'index'])