Skip to content

Commit

Permalink
refactor, useeffects, custom hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
dissorial committed Jun 4, 2023
1 parent f01061c commit fa633e5
Show file tree
Hide file tree
Showing 14 changed files with 385 additions and 67 deletions.
2 changes: 1 addition & 1 deletion components/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const Header: React.FC<HeaderProps> = ({ setSidebarOpen }) => {
className="-ml-0.5 h-4 w-4 sm:w-5 sm:h-5"
aria-hidden="true"
/>
Settings
<span>Settings</span>
</button>
</div>
</div>
Expand Down
65 changes: 65 additions & 0 deletions components/keyform/KeyForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { useState } from 'react';

interface KeyFormProps {
keyName: string;
keyValue: string;
setKeyValue: (key: string) => void;
}

import { CheckIcon } from '@heroicons/react/20/solid';

const KeyForm: React.FC<KeyFormProps> = ({
keyName,
keyValue,
setKeyValue,
}) => {
const [isFocused, setIsFocused] = useState(false);

const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
setKeyValue(keyValue);
};

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setKeyValue(event.target.value);
};

const handleFocus = () => {
setIsFocused(true);
};

const handleBlur = () => {
setIsFocused(false);
};

return (
<form onSubmit={handleSubmit}>
<div className="relative">
<p className="text-white text-sm font-medium mb-2">
{keyName.charAt(0).toUpperCase() + keyName.slice(1)}
</p>
<div className="relative">
<input
type="password"
value={keyValue}
onChange={handleChange}
onFocus={handleFocus}
onBlur={handleBlur}
placeholder={`Enter ${keyName}`}
className="w-full pr-10 py-3 text-sm text-gray-300 placeholder-gray-500 bg-gray-800 border border-gray-700 rounded-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"
/>
{isFocused && (
<button
type="submit"
className="absolute inset-y-0 right-0 flex items-center mr-2 focus:outline-none"
>
<CheckIcon className="h-5 w-5 text-green-500 hover:text-green-600 transition-colors duration-200" />
</button>
)}
</div>
</div>
</form>
);
};

export default KeyForm;
15 changes: 8 additions & 7 deletions components/main/EmptyState.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import Button from '../buttons/Button';
import { useRouter } from 'next/router';
interface EmptyStateProps {
nameSpaceHasChats: boolean;
Expand All @@ -19,20 +18,22 @@ const EmptyState: React.FC<EmptyStateProps> = ({

return (
<div className="flex flex-col justify-center px-4 pt-24">
<h1 className="text-xl md:text-3xl text-center font-semibold text-gray-100 mb-4">
<h1 className="text-xl md:text-3xl text-center font-semibold text-gray-100 mb-6">
{!userHasNamespaces
? noNamespacesMessage
: selectedNamespace && !nameSpaceHasChats
? 'Create a new chat to get started.'
: selectNamespaceMessage}
</h1>
{!userHasNamespaces && (
<div>
<Button
buttonType="primary"
buttonText="Create a namespace"
<div className="flex justify-center">
<button
type="button"
className="rounded-md bg-indigo-500 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500"
onClick={() => router.push('/settings')}
/>
>
Create a namespace
</button>
</div>
)}
</div>
Expand Down
15 changes: 10 additions & 5 deletions components/sidebar/ListOfNamespaces.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ const ListOfNamespaces = ({
setSelectedNamespace(namespace);
};

console.log(namespaces);

return (
<Menu as="div" className="w-full relative inline-block text-left">
<div>
Expand All @@ -37,11 +39,14 @@ const ListOfNamespaces = ({
</span>
) : (
<>
{selectedNamespace}
<ChevronDownIcon
className="-mr-1 h-5 w-5 text-gray-400"
aria-hidden="true"
/>
{namespaces.length === 0 ? (
<span>No namespaces found</span>
) : (
<ChevronDownIcon
className="-mr-1 h-5 w-5 text-gray-400"
aria-hidden="true"
/>
)}
</>
)}
</Menu.Button>
Expand Down
53 changes: 53 additions & 0 deletions hooks/useKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useState, useEffect } from 'react';
import { getItem } from '@/libs/localStorageKeys';

interface Keys {
openAIapiKey: string;
setOpenAIapiKey: React.Dispatch<React.SetStateAction<string>>;
pineconeApiKey: string;
setPineconeApiKey: React.Dispatch<React.SetStateAction<string>>;
pineconeEnvironment: string;
setPineconeEnvironment: React.Dispatch<React.SetStateAction<string>>;
pineconeIndexName: string;
setPineconeIndexName: React.Dispatch<React.SetStateAction<string>>;
}

const useApiKeys = (): Keys => {
const [openAIapiKey, setOpenAIapiKey] = useState<string>('');
const [pineconeApiKey, setPineconeApiKey] = useState<string>('');
const [pineconeEnvironment, setPineconeEnvironment] = useState<string>('');
const [pineconeIndexName, setPineconeIndexName] = useState<string>('');

useEffect(() => {
const storedOpenAIKey = getItem('openAIapiKey');
const storedPineconeKey = getItem('pineconeApiKey');
const storedPineconeEnvironment = getItem('pineconeEnvironment');
const storedPineconeIndexName = getItem('pineconeIndexName');

if (storedOpenAIKey) {
setOpenAIapiKey(storedOpenAIKey);
}
if (storedPineconeKey) {
setPineconeApiKey(storedPineconeKey);
}
if (storedPineconeEnvironment) {
setPineconeEnvironment(storedPineconeEnvironment);
}
if (storedPineconeIndexName) {
setPineconeIndexName(storedPineconeIndexName);
}
}, []);

return {
openAIapiKey,
setOpenAIapiKey,
pineconeApiKey,
setPineconeApiKey,
pineconeEnvironment,
setPineconeEnvironment,
pineconeIndexName,
setPineconeIndexName,
};
};

export default useApiKeys;
24 changes: 20 additions & 4 deletions hooks/useNamespaces.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { useState, useEffect } from 'react';
import { useRouter } from 'next/router';

export default function useNamespaces() {
interface useNamespacesProps {
pineconeApiKey: string;
pineconeIndexName: string;
pineconeEnvironment: string;
}

export default function useNamespaces(
pineconeApiKey: string,
pineconeIndexName: string,
pineconeEnvironment: string,
) {
const [namespaces, setNamespaces] = useState<string[]>([]);
const [selectedNamespace, setSelectedNamespace] = useState<string>('');
const [isLoadingNamespaces, setIsLoadingNamespaces] = useState(true);
Expand All @@ -11,14 +21,20 @@ export default function useNamespaces() {
useEffect(() => {
const fetchNamespaces = async () => {
try {
const response = await fetch(`/api/getNamespaces`);
const response = await fetch(`/api/getNamespaces`, {
headers: {
'X-Api-Key': pineconeApiKey,
'X-Index-Name': pineconeIndexName,
'X-Environment': pineconeEnvironment,
},
});
const data = await response.json();

if (response.ok) {
setNamespaces(data);
setIsLoadingNamespaces(false);
if (data.length > 0) {
setSelectedNamespace(data[0]); // Set the first namespace from the list as the selected one
setSelectedNamespace(data[0]);
}
} else {
console.error(data.error);
Expand All @@ -29,7 +45,7 @@ export default function useNamespaces() {
};

fetchNamespaces();
}, []);
}, [pineconeApiKey, pineconeIndexName, pineconeEnvironment]);

useEffect(() => {
const namespaceFromUrl = router.query.namespace;
Expand Down
7 changes: 7 additions & 0 deletions libs/localStorageKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const setItem = (key: string, value: string) => {
window.localStorage.setItem(key, value);
};

export const getItem = (key: string) => {
return window.localStorage.getItem(key);
};
19 changes: 13 additions & 6 deletions pages/api/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { NextApiRequest, NextApiResponse } from 'next';
import { OpenAIEmbeddings } from 'langchain/embeddings/openai';
import { PineconeStore } from 'langchain/vectorstores/pinecone';
import { makeChain } from '@/utils/makechain';
import { pinecone } from '@/utils/pinecone-client';
import { initPinecone } from '@/utils/pinecone-client';

export default async function handler(
req: NextApiRequest,
Expand All @@ -16,11 +16,18 @@ export default async function handler(
returnSourceDocuments,
modelTemperature,
} = req.body;
const PINECONE_INDEX_NAME = process.env.PINECONE_INDEX_NAME ?? '';

const openai_api_key = process.env.OPENAI_API_KEY ?? '';
const pineconeApiKey = req.headers['x-api-key'];
const targetIndex = req.headers['x-index-name'] as string;
const pineconeEnvironment = req.headers['x-environment'];
const openAIapiKey = req.headers['x-openai-key'];

if (!openai_api_key) {
const pinecone = await initPinecone(
pineconeApiKey as string,
pineconeEnvironment as string,
);

if (!openAIapiKey) {
return res.status(500).json({ error: 'OpenAI API key not set' });
}

Expand All @@ -35,11 +42,11 @@ export default async function handler(

const sanitizedQuestion = question.trim().replaceAll('\n', ' ');
try {
const index = pinecone.Index(PINECONE_INDEX_NAME);
const index = pinecone.Index(targetIndex as string);

const vectorStore = await PineconeStore.fromExistingIndex(
new OpenAIEmbeddings({
openAIApiKey: openai_api_key,
openAIApiKey: openAIapiKey as string,
}),
{
pineconeIndex: index,
Expand Down
15 changes: 11 additions & 4 deletions pages/api/consume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,24 @@ import { DocxLoader } from 'langchain/document_loaders/fs/docx';
import { TextLoader } from 'langchain/document_loaders/fs/text';
import { NextApiRequest, NextApiResponse } from 'next';
import fs from 'fs';
import { pinecone } from '@/utils/pinecone-client';
import { initPinecone } from '@/utils/pinecone-client';

const filePath = process.env.NODE_ENV === 'production' ? '/tmp' : 'tmp';

export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
const { namespaceName, chunkSize, overlapSize } = req.query;
const pineconeApiKey = req.headers['x-api-key'];
const targetIndex = req.headers['x-index-name'] as string;
const pineconeEnvironment = req.headers['x-environment'];

const pinecone = await initPinecone(
pineconeApiKey as string,
pineconeEnvironment as string,
);

const PINECONE_INDEX_NAME = process.env.PINECONE_INDEX_NAME ?? '';
const { namespaceName, chunkSize, overlapSize } = req.query;

try {
// Load PDF files from the specified directory
Expand All @@ -41,7 +48,7 @@ export default async function handler(
const embeddings = new OpenAIEmbeddings();

// Get the Pinecone index with the given name
const index = pinecone.Index(PINECONE_INDEX_NAME);
const index = pinecone.Index(targetIndex);

// Store the document chunks in Pinecone with their embeddings
await PineconeStore.fromDocuments(docs, embeddings, {
Expand Down
14 changes: 11 additions & 3 deletions pages/api/deleteNamespace.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { pinecone } from '@/utils/pinecone-client';
import { initPinecone } from '@/utils/pinecone-client';

import { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(
Expand All @@ -9,7 +10,14 @@ export default async function handler(
namespace: string;
};

const targetIndex = process.env.PINECONE_INDEX_NAME ?? '';
const pineconeApiKey = req.headers['x-api-key'];
const targetIndex = req.headers['x-index-name'] as string;
const pineconeEnvironment = req.headers['x-environment'];

const pinecone = await initPinecone(
pineconeApiKey as string,
pineconeEnvironment as string,
);

try {
const index = pinecone.Index(targetIndex);
Expand All @@ -23,6 +31,6 @@ export default async function handler(
res.status(200).json({ message: 'Namespace deleted successfully.' });
} catch (error) {
console.log('error', error);
res.status(500).json({ error: 'Failed to delete the namespace.' });
res.status(500).json({ error: 'Failed to delete namespace.' });
}
}
15 changes: 11 additions & 4 deletions pages/api/getNamespaces.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { pinecone } from '@/utils/pinecone-client';
import { initPinecone } from '@/utils/pinecone-client';

type NamespaceSummary = {
vectorCount: number;
};

const getNamespaces = async (req: NextApiRequest, res: NextApiResponse) => {
const targetIndex = process.env.PINECONE_INDEX_NAME ?? '';
const pineconeApiKey = req.headers['x-api-key'];
const targetIndex = req.headers['x-index-name'] as string;
const pineconeEnvironment = req.headers['x-environment'];

const pinecone = await initPinecone(
pineconeApiKey as string,
pineconeEnvironment as string,
);

try {
const index = pinecone.Index(targetIndex);
Expand All @@ -26,8 +33,8 @@ const getNamespaces = async (req: NextApiRequest, res: NextApiResponse) => {

res.status(200).json(namespaces);
} catch (error) {
console.log('error', error);
res.status(500).json({ message: 'Failed to get namespaces' });
console.log('Error fetching namespaces', error);
res.status(500).json({ message: 'Error fetching namespaces' });
}
};

Expand Down
Loading

0 comments on commit fa633e5

Please sign in to comment.