From e7a7e78969d8e8401193766631b7b51d8852fe8a Mon Sep 17 00:00:00 2001 From: pablonyx Date: Wed, 11 Dec 2024 11:10:34 -0800 Subject: [PATCH] clean up csv prompt + frontend (#3393) * clean up csv prompt + frontend * nit * nit * detect uploading * upload --- backend/danswer/llm/utils.py | 43 +++++-------------- web/src/app/chat/ChatPage.tsx | 21 ++++++--- web/src/app/chat/types.ts | 7 ++- web/src/components/tools/CSVContent.tsx | 6 +-- .../tools/ExpandableContentWrapper.tsx | 6 +-- 5 files changed, 36 insertions(+), 47 deletions(-) diff --git a/backend/danswer/llm/utils.py b/backend/danswer/llm/utils.py index 41c6592c6..47175c8d9 100644 --- a/backend/danswer/llm/utils.py +++ b/backend/danswer/llm/utils.py @@ -1,5 +1,4 @@ import copy -import io import json from collections.abc import Callable from collections.abc import Iterator @@ -7,7 +6,6 @@ from typing import Any from typing import cast import litellm # type: ignore -import pandas as pd import tiktoken from langchain.prompts.base import StringPromptValue from langchain.prompts.chat import ChatPromptValue @@ -100,53 +98,32 @@ def litellm_exception_to_error_msg( return error_msg -# Processes CSV files to show the first 5 rows and max_columns (default 40) columns -def _process_csv_file(file: InMemoryChatFile, max_columns: int = 40) -> str: - df = pd.read_csv(io.StringIO(file.content.decode("utf-8"))) - - csv_preview = df.head().to_string(max_cols=max_columns) - - file_name_section = ( - f"CSV FILE NAME: {file.filename}\n" - if file.filename - else "CSV FILE (NO NAME PROVIDED):\n" - ) - return f"{file_name_section}{CODE_BLOCK_PAT.format(csv_preview)}\n\n\n" - - def _build_content( message: str, files: list[InMemoryChatFile] | None = None, ) -> str: """Applies all non-image files.""" - text_files = ( - [file for file in files if file.file_type == ChatFileType.PLAIN_TEXT] - if files - else None - ) + if not files: + return message - csv_files = ( - [file for file in files if file.file_type == ChatFileType.CSV] - if files - else None - ) + text_files = [ + file + for file in files + if file.file_type in (ChatFileType.PLAIN_TEXT, ChatFileType.CSV) + ] - if not text_files and not csv_files: + if not text_files: return message final_message_with_files = "FILES:\n\n" - for file in text_files or []: + for file in text_files: file_content = file.content.decode("utf-8") file_name_section = f"DOCUMENT: {file.filename}\n" if file.filename else "" final_message_with_files += ( f"{file_name_section}{CODE_BLOCK_PAT.format(file_content.strip())}\n\n\n" ) - for file in csv_files or []: - final_message_with_files += _process_csv_file(file) - final_message_with_files += message - - return final_message_with_files + return final_message_with_files + message def build_content_with_imgs( diff --git a/web/src/app/chat/ChatPage.tsx b/web/src/app/chat/ChatPage.tsx index d48063e97..22337a90d 100644 --- a/web/src/app/chat/ChatPage.tsx +++ b/web/src/app/chat/ChatPage.tsx @@ -1080,10 +1080,17 @@ export function ChatPage({ updateCanContinue(false, frozenSessionId); if (currentChatState() != "input") { - setPopup({ - message: "Please wait for the response to complete", - type: "error", - }); + if (currentChatState() == "uploading") { + setPopup({ + message: "Please wait for the content to upload", + type: "error", + }); + } else { + setPopup({ + message: "Please wait for the response to complete", + type: "error", + }); + } return; } @@ -1558,7 +1565,7 @@ export function ChatPage({ } }; - const handleImageUpload = (acceptedFiles: File[]) => { + const handleImageUpload = async (acceptedFiles: File[]) => { const [_, llmModel] = getFinalLLM( llmProviders, liveAssistant, @@ -1598,8 +1605,9 @@ export function ChatPage({ (file) => !tempFileDescriptors.some((newFile) => newFile.id === file.id) ); }; + updateChatState("uploading", currentSessionId()); - uploadFilesForChat(acceptedFiles).then(([files, error]) => { + await uploadFilesForChat(acceptedFiles).then(([files, error]) => { if (error) { setCurrentMessageFiles((prev) => removeTempFiles(prev)); setPopup({ @@ -1610,6 +1618,7 @@ export function ChatPage({ setCurrentMessageFiles((prev) => [...removeTempFiles(prev), ...files]); } }); + updateChatState("input", currentSessionId()); }; const [showHistorySidebar, setShowHistorySidebar] = useState(false); // State to track if sidebar is open diff --git a/web/src/app/chat/types.ts b/web/src/app/chat/types.ts index abbe9b3b8..c430a604c 100644 --- a/web/src/app/chat/types.ts +++ b/web/src/app/chat/types.ts @@ -1,5 +1,10 @@ export type FeedbackType = "like" | "dislike"; -export type ChatState = "input" | "loading" | "streaming" | "toolBuilding"; +export type ChatState = + | "input" + | "loading" + | "streaming" + | "toolBuilding" + | "uploading"; export interface RegenerationState { regenerating: boolean; finalMessageIndex: number; diff --git a/web/src/components/tools/CSVContent.tsx b/web/src/components/tools/CSVContent.tsx index 5dd6dcbf9..05a8fb2bf 100644 --- a/web/src/components/tools/CSVContent.tsx +++ b/web/src/components/tools/CSVContent.tsx @@ -91,9 +91,7 @@ const CsvContent: React.FC = ({ }`} >
@@ -108,7 +106,7 @@ const CsvContent: React.FC = ({ - + {data.length > 0 ? ( data.map((row, rowIndex) => ( diff --git a/web/src/components/tools/ExpandableContentWrapper.tsx b/web/src/components/tools/ExpandableContentWrapper.tsx index 4e7635e08..6a9b2bc11 100644 --- a/web/src/components/tools/ExpandableContentWrapper.tsx +++ b/web/src/components/tools/ExpandableContentWrapper.tsx @@ -102,9 +102,9 @@ const ExpandableContentWrapper: React.FC = ({