Skip to content

Commit

Permalink
Fix: revamp knowledge UX based on feedback
Browse files Browse the repository at this point in the history
Signed-off-by: Daishan Peng <[email protected]>
  • Loading branch information
StrongMonkey committed Aug 28, 2024
1 parent 97e615c commit f45ea2c
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 151 deletions.
57 changes: 26 additions & 31 deletions actions/knowledge/knowledge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,25 @@ export async function deleteDataset(datasetID: string): Promise<void> {
return;
}

export async function firstIngestion(
scriptId: string,
files: string[]
): Promise<boolean> {
const dir = path.join(KNOWLEDGE_DIR(), 'script_data', scriptId, 'data');
return !fs.existsSync(dir) && files.length > 0;
}

export async function ensureFilesIngested(
files: string[],
scriptId: string,
token: string
) {
): Promise<string> {
const dir = path.join(KNOWLEDGE_DIR(), 'script_data', scriptId, 'data');
if (!fs.existsSync(dir) && files.length > 0) {
fs.mkdirSync(dir, { recursive: true });
} else if (!fs.existsSync(dir) && files.length === 0) {
// if there are no files in the directory and no dropped files, do nothing
return;
return '';
}

for (const file of files) {
Expand All @@ -57,8 +65,7 @@ export async function ensureFilesIngested(
await fs.promises.copyFile(file, filePath);
}
} catch (error) {
console.error(`Error copying file ${file}:`, error);
throw error;
return `Error copying file ${file}: ${error}`;
}
}

Expand All @@ -74,8 +81,7 @@ export async function ensureFilesIngested(
}
}
} catch (error) {
console.error('Error during cleanup of removed files:', error);
throw error;
return `Error deleting files: ${error}`;
}

try {
Expand All @@ -85,37 +91,31 @@ export async function ensureFilesIngested(
token
);
} catch (error) {
console.error('Error during ingestion:', error);
throw error;
return `Error running knowledge ingestion: ${error}`;
}

return;
return '';
}

async function runKnowledgeIngest(
id: string,
knowledgePath: string,
token: string
): Promise<void> {
try {
// Start the ingestion process in the background
await execPromise(
`${process.env.KNOWLEDGE_BIN} ingest --prune --dataset ${id} ./data`,
{
cwd: knowledgePath,
env: { ...process.env, GPTSCRIPT_GATEWAY_API_KEY: token },
}
);

const errorFilePath = path.join(knowledgePath, 'error.log');
if (fs.existsSync(errorFilePath)) {
await fs.promises.rm(errorFilePath);
// Start the ingestion process in the background
await execPromise(
`${process.env.KNOWLEDGE_BIN} ingest --prune --dataset ${id} ./data`,
{
cwd: knowledgePath,
env: { ...process.env, GPTSCRIPT_GATEWAY_API_KEY: token },
}
} catch (error) {
console.log(error);
handleError(knowledgePath, error as Error);
throw error;
);

const errorFilePath = path.join(knowledgePath, 'error.log');
if (fs.existsSync(errorFilePath)) {
await fs.promises.rm(errorFilePath);
}
return;
}

export async function getFiles(scriptId: string): Promise<string[]> {
Expand All @@ -135,8 +135,3 @@ export async function datasetExists(scriptId: string): Promise<boolean> {
export async function getKnowledgeBinaryPath(): Promise<string> {
return process.env.KNOWLEDGE_BIN || 'knowledge';
}

function handleError(dir: string, error: Error): void {
const errorFilePath = path.join(dir, 'error.log');
fs.writeFileSync(errorFilePath, error.message);
}
120 changes: 83 additions & 37 deletions components/edit/configure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Models from '@/components/edit/configure/models';
import Visibility from '@/components/edit/configure/visibility';
import Code from '@/components/edit/configure/code';
import { EditContext, KNOWLEDGE_NAME } from '@/contexts/edit';
import { GoLightBulb } from 'react-icons/go';
import { GoLightBulb, GoTrash } from 'react-icons/go';
import { HiCog } from 'react-icons/hi2';
import { LuCircuitBoard } from 'react-icons/lu';
import {
Expand All @@ -24,11 +24,12 @@ import AssistantNotFound from '@/components/assistant-not-found';
import { useRouter } from 'next/navigation';
import { ChatContext } from '@/contexts/chat';
import Chat from '@/components/chat';
import { GoDatabase } from 'react-icons/go';
import { IoSettingsOutline } from 'react-icons/io5';
import { IoMdAdd } from 'react-icons/io';
import { RiFileSearchLine } from 'react-icons/ri';
import KnowledgeModals from '@/components/knowledge/KnowledgeModals';
import FileSettingModals from '@/components/knowledge/KnowledgeModals';
import { RiFoldersLine } from 'react-icons/ri';
import { MdError } from 'react-icons/md';

interface ConfigureProps {
collapsed?: boolean;
Expand All @@ -51,12 +52,13 @@ const Configure: React.FC<ConfigureProps> = ({ collapsed }) => {
setDependencies,
setDroppedFiles,
droppedFileDetails,
setDroppedFileDetails,
ingesting,
updated,
setUpdated,
ingestionError,
} = useContext(EditContext);
const { restartScript } = useContext(ChatContext);
const fileTableModal = useDisclosure();
const fileSettingModal = useDisclosure();

const abbreviate = (name: string) => {
Expand Down Expand Up @@ -212,40 +214,87 @@ const Configure: React.FC<ConfigureProps> = ({ collapsed }) => {
aria-label="files"
title={<h1>Files</h1>}
startContent={<RiFileSearchLine />}
classNames={{ content: 'pt-1 pb-3' }}
classNames={{ content: collapsed ? 'pt-6 pb-10' : 'p-10 pt-6' }}
>
<div className="flex justify-between items-center">
<Button
isIconOnly
size="sm"
startContent={<GoDatabase />}
onClick={fileTableModal.onOpen}
/>

{droppedFileDetails?.size > 0 && !ingesting && (
<p className="text-sm text-zinc-500 ml-2">{`${droppedFileDetails.size} ${droppedFileDetails.size === 1 ? 'file' : 'files'}, ${Array.from(
droppedFileDetails.values()
<div className="grid grid-cols-1 gap-2 w-full mb-2">
{Array.from(droppedFileDetails.entries()).map(
(fileDetail, i) => (
<div key={i} className="flex space-x-2">
<div className="truncate w-full border-2 dark:border-zinc-700 text-sm pl-2 rounded-lg flex justify-between items-center">
<div className="flex items-center space-x-2">
<RiFileSearchLine />
<p className="capitalize">{fileDetail[1].fileName}</p>
<p className="text-xs text-zinc-400 ml-2">{`${fileDetail[1].size} KB`}</p>
</div>
<Button
variant="light"
isIconOnly
size="sm"
startContent={<GoTrash />}
onPress={() => {
setDroppedFiles((prev) =>
prev.filter((f) => f !== fileDetail[0])
);
const newDetails = new Map(droppedFileDetails);
newDetails.delete(fileDetail[0]);
setDroppedFileDetails(newDetails);
}}
/>
</div>
</div>
)
.reduce((acc, detail) => acc + detail.size, 0)
.toFixed(2)} KB`}</p>
)}
{ingesting && <Spinner size="sm" className="ml-2" />}
<div className="ml-auto flex space-x-2">
<Button
isIconOnly
size="sm"
startContent={<IoSettingsOutline />}
onClick={fileSettingModal.onOpen}
/>
<Button
size="sm"
startContent={<IoMdAdd />}
onClick={handleAddFiles}
>
Files
</Button>
<div className="flex justify-end mt-2">
{droppedFileDetails?.size > 0 &&
!ingesting &&
!ingestionError && (
<div className="flex justify-center">
<RiFoldersLine />
<p className="text-sm text-zinc-500 ml-2">{`${droppedFileDetails.size} ${droppedFileDetails.size === 1 ? 'file' : 'files'}, ${Array.from(
droppedFileDetails.values()
)
.reduce((acc, detail) => acc + detail.size, 0)
.toFixed(2)} KB`}</p>
</div>
)}
{ingesting && !ingestionError && (
<Spinner size="sm" className="ml-2" />
)}
{ingestionError && (
<>
<p className="text-sm text-red-500 ml-2">
{ingestionError}
</p>
</>
)}
</div>
</div>
<div
className={`flex ${collapsed ? 'flex-col space-y-2' : 'space-x-4'} ${droppedFileDetails.size > 0 ? 'pt-4' : ''}`}
>
<Button
className="w-full"
variant="flat"
color="primary"
isIconOnly
size="sm"
startContent={<IoSettingsOutline className="mr-2" />}
onPress={fileSettingModal.onOpen}
>
Settings
</Button>
<Button
className="w-full"
variant="flat"
color="primary"
isIconOnly
size="sm"
startContent={<IoMdAdd className="mr-2" />}
onPress={handleAddFiles}
>
Add Files
</Button>
</div>
</AccordionItem>
<AccordionItem
aria-label="advanced"
Expand Down Expand Up @@ -308,12 +357,9 @@ const Configure: React.FC<ConfigureProps> = ({ collapsed }) => {
: `Click "Refresh Chat" to chat with the updated version of ${placeholderName()}`
}
/>
<KnowledgeModals
<FileSettingModals
isFileSettingOpen={fileSettingModal.isOpen}
onFileSettingClose={fileSettingModal.onClose}
isFileTableOpen={fileTableModal.isOpen}
onFileTableClose={fileTableModal.onClose}
handleAddFiles={handleAddFiles}
/>
</>
);
Expand Down
77 changes: 1 addition & 76 deletions components/knowledge/KnowledgeModals.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,23 @@
import {
Button,
Modal,
ModalBody,
ModalContent,
ModalFooter,
ModalHeader,
Slider,
Table,
TableBody,
TableCell,
TableColumn,
TableHeader,
TableRow,
} from '@nextui-org/react';
import { BiPlus, BiTrash } from 'react-icons/bi';
import { useContext } from 'react';
import { EditContext } from '@/contexts/edit';

interface KnowledgeProps {
isFileSettingOpen: boolean;
onFileSettingClose: () => void;
isFileTableOpen: boolean;
onFileTableClose: () => void;
handleAddFiles: () => void;
}

const KnowledgeModals = ({
isFileSettingOpen,
onFileSettingClose,
isFileTableOpen,
onFileTableClose,
handleAddFiles,
}: KnowledgeProps) => {
const {
topK,
setTopK,
droppedFileDetails,
setDroppedFileDetails,
setDroppedFiles,
} = useContext(EditContext);
const { topK, setTopK } = useContext(EditContext);
return (
<>
<Modal
Expand Down Expand Up @@ -72,60 +51,6 @@ const KnowledgeModals = ({
</ModalBody>
</ModalContent>
</Modal>
<Modal
size="xl"
backdrop="opaque"
isOpen={isFileTableOpen}
onClose={onFileTableClose}
>
<ModalContent>
<ModalHeader>
<h3 id="modal-title">Files</h3>
</ModalHeader>
<ModalBody>
<Table removeWrapper aria-label="File table">
<TableHeader>
<TableColumn>File Name</TableColumn>
<TableColumn>Size</TableColumn>
<TableColumn>{''}</TableColumn>
</TableHeader>
<TableBody>
{Array.from(droppedFileDetails).map((fileDetail, index) => (
<TableRow key={index}>
<TableCell>{fileDetail[1].fileName}</TableCell>
<TableCell>{fileDetail[1].size} KB</TableCell>
<TableCell align="right">
<Button
isIconOnly
size="md"
onClick={() => {
setDroppedFiles((prev) =>
prev.filter((f) => f !== fileDetail[0])
);
const newDetails = new Map(droppedFileDetails);
newDetails.delete(fileDetail[0]);
setDroppedFileDetails(newDetails);
}}
className="bg-white"
startContent={<BiTrash />}
/>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</ModalBody>
<ModalFooter>
<Button
className="w-full"
onClick={handleAddFiles}
startContent={<BiPlus />}
>
Add files
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</>
);
};
Expand Down
Loading

0 comments on commit f45ea2c

Please sign in to comment.