clean up csv prompt + frontend (#3393)

* clean up csv prompt + frontend

* nit

* nit

* detect uploading

* upload
This commit is contained in:
pablonyx
2024-12-11 11:10:34 -08:00
committed by GitHub
parent e255ff7d23
commit e7a7e78969
5 changed files with 36 additions and 47 deletions

View File

@@ -1,5 +1,4 @@
import copy import copy
import io
import json import json
from collections.abc import Callable from collections.abc import Callable
from collections.abc import Iterator from collections.abc import Iterator
@@ -7,7 +6,6 @@ from typing import Any
from typing import cast from typing import cast
import litellm # type: ignore import litellm # type: ignore
import pandas as pd
import tiktoken import tiktoken
from langchain.prompts.base import StringPromptValue from langchain.prompts.base import StringPromptValue
from langchain.prompts.chat import ChatPromptValue from langchain.prompts.chat import ChatPromptValue
@@ -100,53 +98,32 @@ def litellm_exception_to_error_msg(
return 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( def _build_content(
message: str, message: str,
files: list[InMemoryChatFile] | None = None, files: list[InMemoryChatFile] | None = None,
) -> str: ) -> str:
"""Applies all non-image files.""" """Applies all non-image files."""
text_files = ( if not files:
[file for file in files if file.file_type == ChatFileType.PLAIN_TEXT] return message
if files
else None
)
csv_files = ( text_files = [
[file for file in files if file.file_type == ChatFileType.CSV] file
if files for file in files
else None if file.file_type in (ChatFileType.PLAIN_TEXT, ChatFileType.CSV)
) ]
if not text_files and not csv_files: if not text_files:
return message return message
final_message_with_files = "FILES:\n\n" 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_content = file.content.decode("utf-8")
file_name_section = f"DOCUMENT: {file.filename}\n" if file.filename else "" file_name_section = f"DOCUMENT: {file.filename}\n" if file.filename else ""
final_message_with_files += ( final_message_with_files += (
f"{file_name_section}{CODE_BLOCK_PAT.format(file_content.strip())}\n\n\n" 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 + message
return final_message_with_files
def build_content_with_imgs( def build_content_with_imgs(

View File

@@ -1080,10 +1080,17 @@ export function ChatPage({
updateCanContinue(false, frozenSessionId); updateCanContinue(false, frozenSessionId);
if (currentChatState() != "input") { if (currentChatState() != "input") {
if (currentChatState() == "uploading") {
setPopup({
message: "Please wait for the content to upload",
type: "error",
});
} else {
setPopup({ setPopup({
message: "Please wait for the response to complete", message: "Please wait for the response to complete",
type: "error", type: "error",
}); });
}
return; return;
} }
@@ -1558,7 +1565,7 @@ export function ChatPage({
} }
}; };
const handleImageUpload = (acceptedFiles: File[]) => { const handleImageUpload = async (acceptedFiles: File[]) => {
const [_, llmModel] = getFinalLLM( const [_, llmModel] = getFinalLLM(
llmProviders, llmProviders,
liveAssistant, liveAssistant,
@@ -1598,8 +1605,9 @@ export function ChatPage({
(file) => !tempFileDescriptors.some((newFile) => newFile.id === file.id) (file) => !tempFileDescriptors.some((newFile) => newFile.id === file.id)
); );
}; };
updateChatState("uploading", currentSessionId());
uploadFilesForChat(acceptedFiles).then(([files, error]) => { await uploadFilesForChat(acceptedFiles).then(([files, error]) => {
if (error) { if (error) {
setCurrentMessageFiles((prev) => removeTempFiles(prev)); setCurrentMessageFiles((prev) => removeTempFiles(prev));
setPopup({ setPopup({
@@ -1610,6 +1618,7 @@ export function ChatPage({
setCurrentMessageFiles((prev) => [...removeTempFiles(prev), ...files]); setCurrentMessageFiles((prev) => [...removeTempFiles(prev), ...files]);
} }
}); });
updateChatState("input", currentSessionId());
}; };
const [showHistorySidebar, setShowHistorySidebar] = useState(false); // State to track if sidebar is open const [showHistorySidebar, setShowHistorySidebar] = useState(false); // State to track if sidebar is open

View File

@@ -1,5 +1,10 @@
export type FeedbackType = "like" | "dislike"; export type FeedbackType = "like" | "dislike";
export type ChatState = "input" | "loading" | "streaming" | "toolBuilding"; export type ChatState =
| "input"
| "loading"
| "streaming"
| "toolBuilding"
| "uploading";
export interface RegenerationState { export interface RegenerationState {
regenerating: boolean; regenerating: boolean;
finalMessageIndex: number; finalMessageIndex: number;

View File

@@ -91,9 +91,7 @@ const CsvContent: React.FC<ContentComponentProps> = ({
}`} }`}
> >
<div <div
className={`overflow-y-hidden flex relative ${ className={`flex relative ${expanded ? "max-h-2/3" : "max-h-[300px]"}`}
expanded ? "max-h-2/3" : "max-h-[300px]"
}`}
> >
<Table> <Table>
<TableHeader className="sticky z-[1000] top-0"> <TableHeader className="sticky z-[1000] top-0">
@@ -108,7 +106,7 @@ const CsvContent: React.FC<ContentComponentProps> = ({
</TableRow> </TableRow>
</TableHeader> </TableHeader>
<TableBody className="h-[300px] overflow-y-scroll"> <TableBody className="h-[300px] overflow-y-hidden ">
{data.length > 0 ? ( {data.length > 0 ? (
data.map((row, rowIndex) => ( data.map((row, rowIndex) => (
<TableRow key={rowIndex}> <TableRow key={rowIndex}>

View File

@@ -102,9 +102,9 @@ const ExpandableContentWrapper: React.FC<ExpandableContentWrapperProps> = ({
</div> </div>
</CardHeader> </CardHeader>
<Card <Card
className={`!rounded-none w-full ${ className={`!rounded-none p-0 relative mx-auto w-full ${
expanded ? "max-h-[600px]" : "max-h-[300px] h" expanded ? "max-h-[600px]" : "max-h-[300px] h-full"
} p-0 relative overflow-x-scroll overflow-y-scroll mx-auto`} } `}
> >
<CardContent className="p-0"> <CardContent className="p-0">
<ContentComponent <ContentComponent