diff --git a/backend/backend/app/api/routers/chat.py b/backend/backend/app/api/routers/chat.py index 3b0aa95..a7b3ba4 100644 --- a/backend/backend/app/api/routers/chat.py +++ b/backend/backend/app/api/routers/chat.py @@ -11,6 +11,7 @@ from pydantic import BaseModel from backend.app.utils import auth +from backend.app.utils.contants import MEMORY_TOKEN_LIMIT from backend.app.utils.index import get_index from backend.app.utils.json import json_to_model @@ -110,7 +111,7 @@ async def chat( memory = ChatMemoryBuffer.from_defaults( chat_history=messages, - token_limit=4096, + token_limit=MEMORY_TOKEN_LIMIT, ) logger.info(f"Memory: {memory.get()}") @@ -121,14 +122,15 @@ async def chat( memory=memory, context_prompt=( "You are a helpful chatbot, able to have normal interactions, as well as answer questions" - " regarding information relating to the Public Sector Standard Conditions Of Contract (PSSCOC) Documents and JTC's Employer Information Requirements (EIR) Documents.\n" - "All the documents are in the context of the construction industry in Singapore.\n" + " regarding information relating but not limited to the Public Sector Standard Conditions Of Contract (PSSCOC) Documents and JTC's Employer Information Requirements (EIR) Documents.\n" + "PSSCOC and EIR documents are in the context of the construction industry in Singapore.\n" "Here are the relevant documents for the context:\n" "{context_str}" "\nInstruction: Based on the above documents, provide a detailed answer for the user question below.\n" "If you cannot answer the question or are unsure of how to answer, inform the user that you do not know.\n" "If you need to clarify the question, ask the user for clarification.\n" - "You are to provide the relevant sources of which you got the information from in the context in brackets." + "You are to provide the relevant sources including but not limited to the file name, and page of which you got the information from in the context in brackets.\n" + "Should there be a full file path, remove the file path and only include the file name in the context." ), ) response = chat_engine.stream_chat( diff --git a/backend/backend/app/utils/contants.py b/backend/backend/app/utils/contants.py index 3c27684..e7eff58 100644 --- a/backend/backend/app/utils/contants.py +++ b/backend/backend/app/utils/contants.py @@ -1,10 +1,15 @@ ######################################################################## # Model Constants for the backend app # ######################################################################## +import os from pathlib import Path from torch.cuda import is_available as is_cuda_available +# ENV variables +USE_LOCAL_LLM = bool(os.getenv("USE_LOCAL_LLM").lower() == "true") +USE_LOCAL_VECTOR_STORE = bool(os.getenv("USE_LOCAL_VECTOR_STORE").lower() == "true") + # Model Constants MAX_NEW_TOKENS = 4096 CONTEXT_SIZE = 3900 # llama2 has a context window of 4096 tokens, but we set it lower to allow for some wiggle room @@ -34,7 +39,10 @@ DEF_EMBED_MODEL_DIMENSIONS = ( 1536 # Default embedding model dimensions used by OpenAI text-embedding-ada-002 ) -EMBED_BATCH_SIZE = 10 # batch size for openai embeddings +EMBED_BATCH_SIZE = 64 # batch size for openai embeddings + +# Chat Memory Buffer Constants +MEMORY_TOKEN_LIMIT = 1500 if USE_LOCAL_LLM else 6144 # Prompt Helper Constants # set maximum input size diff --git a/backend/backend/app/utils/index.py b/backend/backend/app/utils/index.py index 77bd438..3bc8fba 100644 --- a/backend/backend/app/utils/index.py +++ b/backend/backend/app/utils/index.py @@ -41,6 +41,8 @@ MODEL_KWARGS, NUM_OUTPUT, STORAGE_DIR, + USE_LOCAL_LLM, + USE_LOCAL_VECTOR_STORE, ) # from llama_index.vector_stores.supabase import SupabaseVectorStore @@ -49,10 +51,6 @@ load_dotenv() logger = logging.getLogger("uvicorn") -# ENV variables -USE_LOCAL_LLM = bool(os.getenv("USE_LOCAL_LLM").lower() == "true") -USE_LOCAL_VECTOR_STORE = bool(os.getenv("USE_LOCAL_VECTOR_STORE").lower() == "true") - # use local LLM if USE_LOCAL_LLM is set to True, else use openai's API if USE_LOCAL_LLM: diff --git a/frontend/app/api/admin/collections/route.ts b/frontend/app/api/admin/collections/route.ts index 5926cc8..892398d 100644 --- a/frontend/app/api/admin/collections/route.ts +++ b/frontend/app/api/admin/collections/route.ts @@ -38,23 +38,23 @@ export async function PUT(request: NextRequest) { const { collection_id, is_public } = await request.json(); // Update the collection data in the database - const { data, error } = await supabase + const { data: updateData, error: updateError } = await supabase .from('collections') .update({ is_public: is_public }) - .match({ collection_id }); + .eq('collection_id', collection_id); - if (error) { - console.error('Error updating collection data in database:', error.message); - return NextResponse.json({ error: error.message }, { status: 500 }); + if (updateError) { + console.error('Error updating collection data in database:', updateError.message); + return NextResponse.json({ error: updateError.message }, { status: 500 }); } // console.log('Updated collection:', data); // Delete the collection requests data in the database (Since it is manually updated by Admin) const { data: delData, error: delError } = await supabase - .from('collection_requests') + .from('collections_requests') .delete() - .match({ collection_id }); + .eq('collection_id', collection_id); if (delError) { console.error('Error deleting collection requests data in database:', delError.message); diff --git a/frontend/app/api/user/collections/route.ts b/frontend/app/api/user/collections/route.ts index 33ec48b..a70aacd 100644 --- a/frontend/app/api/user/collections/route.ts +++ b/frontend/app/api/user/collections/route.ts @@ -131,8 +131,15 @@ export async function DELETE(request: NextRequest) { authorization = null; // Clear the authorization token } + // Create default delete_vecs variable + let is_delete_vecs = true; // Retrieve the collection_id from the request body - const { collection_id } = await request?.json(); + const { collection_id, delete_vecs } = await request?.json(); + + // if delete_vecs is not undefined, take its value + if (delete_vecs !== undefined) { + is_delete_vecs = delete_vecs; + } // Retrieve the user's ID from the session token const { data: sessionData, error: sessionError } = await supabaseAuth @@ -148,23 +155,24 @@ export async function DELETE(request: NextRequest) { return NextResponse.json({ error: sessionError.message }, { status: 500 }); } - // Delete the vector collection from the vecs schema via POST request to Backend API - const deleteVecsResponse = await fetch(`${process.env.DELETE_SINGLE_COLLECTION_API}?collection_id=${collection_id}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': authorization, - 'X-API-Key': api_key, - } as any, - body: JSON.stringify({ collection_id: collection_id }), - }); - - if (!deleteVecsResponse.ok) { - console.error('Error deleting', collection_id, 'from vecs schema:', deleteVecsResponse.statusText); - return NextResponse.json({ error: deleteVecsResponse.statusText }, { status: deleteVecsResponse.status }); + if (is_delete_vecs === true) { + // Delete the vector collection from the vecs schema via POST request to Backend API + const deleteVecsResponse = await fetch(`${process.env.DELETE_SINGLE_COLLECTION_API}?collection_id=${collection_id}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': authorization, + 'X-API-Key': api_key, + } as any, + body: JSON.stringify({ collection_id: collection_id }), + }); + + if (!deleteVecsResponse.ok) { + console.error('Error deleting', collection_id, 'from vecs schema:', deleteVecsResponse.statusText); + return NextResponse.json({ error: deleteVecsResponse.statusText }, { status: deleteVecsResponse.status }); + } } - // Delete the collection data from the database const { data: deleteData, error: deleteError } = await supabase .from('collections') diff --git a/frontend/app/components/chat-section.tsx b/frontend/app/components/chat-section.tsx index 853fa08..83463ad 100644 --- a/frontend/app/components/chat-section.tsx +++ b/frontend/app/components/chat-section.tsx @@ -6,6 +6,8 @@ import { ChatSelection } from "@/app/components/ui/chat"; import { AutofillQuestion } from "@/app/components/ui/autofill-prompt"; import { useSession } from "next-auth/react"; import { useState } from "react"; +import { ToastContainer } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; export default function ChatSection() { const { data: session } = useSession(); @@ -34,6 +36,7 @@ export default function ChatSection() { return (