Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add delete all chats option #2515

Merged
merged 5 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions backend/alembic/versions/35e518e0ddf4_properly_cascade.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
"""properly_cascade

Revision ID: 35e518e0ddf4
Revises: 91a0a4d62b14
Create Date: 2024-09-20 21:24:04.891018

"""
from alembic import op


# revision identifiers, used by Alembic.
revision = "35e518e0ddf4"
down_revision = "91a0a4d62b14"
branch_labels = None
depends_on = None


def upgrade() -> None:
# Update chat_message foreign key constraint
op.drop_constraint(
"chat_message_chat_session_id_fkey", "chat_message", type_="foreignkey"
)
op.create_foreign_key(
"chat_message_chat_session_id_fkey",
"chat_message",
"chat_session",
["chat_session_id"],
["id"],
ondelete="CASCADE",
)

# Update chat_message__search_doc foreign key constraints
op.drop_constraint(
"chat_message__search_doc_chat_message_id_fkey",
"chat_message__search_doc",
type_="foreignkey",
)
op.drop_constraint(
"chat_message__search_doc_search_doc_id_fkey",
"chat_message__search_doc",
type_="foreignkey",
)

op.create_foreign_key(
"chat_message__search_doc_chat_message_id_fkey",
"chat_message__search_doc",
"chat_message",
["chat_message_id"],
["id"],
ondelete="CASCADE",
)
op.create_foreign_key(
"chat_message__search_doc_search_doc_id_fkey",
"chat_message__search_doc",
"search_doc",
["search_doc_id"],
["id"],
ondelete="CASCADE",
)

# Add CASCADE delete for tool_call foreign key
op.drop_constraint("tool_call_message_id_fkey", "tool_call", type_="foreignkey")
op.create_foreign_key(
"tool_call_message_id_fkey",
"tool_call",
"chat_message",
["message_id"],
["id"],
ondelete="CASCADE",
)


def downgrade() -> None:
# Revert chat_message foreign key constraint
op.drop_constraint(
"chat_message_chat_session_id_fkey", "chat_message", type_="foreignkey"
)
op.create_foreign_key(
"chat_message_chat_session_id_fkey",
"chat_message",
"chat_session",
["chat_session_id"],
["id"],
)

# Revert chat_message__search_doc foreign key constraints
op.drop_constraint(
"chat_message__search_doc_chat_message_id_fkey",
"chat_message__search_doc",
type_="foreignkey",
)
op.drop_constraint(
"chat_message__search_doc_search_doc_id_fkey",
"chat_message__search_doc",
type_="foreignkey",
)

op.create_foreign_key(
"chat_message__search_doc_chat_message_id_fkey",
"chat_message__search_doc",
"chat_message",
["chat_message_id"],
["id"],
)
op.create_foreign_key(
"chat_message__search_doc_search_doc_id_fkey",
"chat_message__search_doc",
"search_doc",
["search_doc_id"],
["id"],
)

# Revert tool_call foreign key constraint
op.drop_constraint("tool_call_message_id_fkey", "tool_call", type_="foreignkey")
op.create_foreign_key(
"tool_call_message_id_fkey",
"tool_call",
"chat_message",
["message_id"],
["id"],
)
17 changes: 17 additions & 0 deletions backend/onyx/db/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,23 @@ def update_chat_session(
return chat_session


def delete_all_chat_sessions_for_user(
user: User | None, db_session: Session, hard_delete: bool = HARD_DELETE_CHATS
) -> None:
user_id = user.id if user is not None else None

query = db_session.query(ChatSession).filter(
ChatSession.user_id == user_id, ChatSession.onyxbot_flow.is_(False)
)

if hard_delete:
query.delete(synchronize_session=False)
else:
query.update({ChatSession.deleted: True}, synchronize_session=False)

db_session.commit()


def delete_chat_session(
user_id: UUID | None,
chat_session_id: UUID,
Expand Down
4 changes: 3 additions & 1 deletion backend/onyx/db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,7 @@ class ChatSession(Base):
"ChatFolder", back_populates="chat_sessions"
)
messages: Mapped[list["ChatMessage"]] = relationship(
"ChatMessage", back_populates="chat_session"
"ChatMessage", back_populates="chat_session", cascade="all, delete-orphan"
)
persona: Mapped["Persona"] = relationship("Persona")

Expand Down Expand Up @@ -1076,6 +1076,8 @@ class ChatMessage(Base):
"SearchDoc",
secondary=ChatMessage__SearchDoc.__table__,
back_populates="chat_messages",
cascade="all, delete-orphan",
single_parent=True,
)

tool_call: Mapped["ToolCall"] = relationship(
Expand Down
12 changes: 12 additions & 0 deletions backend/onyx/server/query_and_chat/chat_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from onyx.db.chat import add_chats_to_session_from_slack_thread
from onyx.db.chat import create_chat_session
from onyx.db.chat import create_new_chat_message
from onyx.db.chat import delete_all_chat_sessions_for_user
from onyx.db.chat import delete_chat_session
from onyx.db.chat import duplicate_chat_session_for_user_from_slack
from onyx.db.chat import get_chat_message
Expand Down Expand Up @@ -280,6 +281,17 @@ def patch_chat_session(
return None


@router.delete("/delete-all-chat-sessions")
def delete_all_chat_sessions(
user: User | None = Depends(current_user),
db_session: Session = Depends(get_session),
) -> None:
try:
delete_all_chat_sessions_for_user(user=user, db_session=db_session)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))


@router.delete("/delete-chat-session/{session_id}")
def delete_chat_session_by_id(
session_id: UUID,
Expand Down
5 changes: 5 additions & 0 deletions backend/onyx/server/query_and_chat/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from onyx.configs.constants import DocumentSource
from onyx.configs.constants import MessageType
from onyx.configs.constants import SearchFeedbackType
from onyx.configs.constants import SessionType
from onyx.context.search.models import BaseFilters
from onyx.context.search.models import ChunkContext
from onyx.context.search.models import RerankingDetails
Expand Down Expand Up @@ -151,6 +152,10 @@ class ChatSessionUpdateRequest(BaseModel):
sharing_status: ChatSessionSharedStatus


class DeleteAllSessionsRequest(BaseModel):
session_type: SessionType


class RenameChatSessionResponse(BaseModel):
new_name: str # This is only really useful if the name is generated

Expand Down
39 changes: 33 additions & 6 deletions web/src/app/chat/ChatPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
buildLatestMessageChain,
checkAnyAssistantHasSearch,
createChatSession,
deleteAllChatSessions,
deleteChatSession,
getCitedDocumentsFromMessage,
getHumanAndAIMessageFromMessageNumber,
Expand Down Expand Up @@ -1837,6 +1838,7 @@ export function ChatPage({

const innerSidebarElementRef = useRef<HTMLDivElement>(null);
const [settingsToggled, setSettingsToggled] = useState(false);
const [showDeleteAllModal, setShowDeleteAllModal] = useState(false);

const currentPersona = alternativeAssistant || liveAssistant;
useEffect(() => {
Expand Down Expand Up @@ -1903,11 +1905,6 @@ export function ChatPage({
const showShareModal = (chatSession: ChatSession) => {
setSharedChatSession(chatSession);
};
const [documentSelection, setDocumentSelection] = useState(false);
// const toggleDocumentSelectionAspects = () => {
// setDocumentSelection((documentSelection) => !documentSelection);
// setShowDocSidebar(false);
// };

const toggleDocumentSidebar = () => {
if (!documentSidebarToggled) {
Expand Down Expand Up @@ -1972,6 +1969,32 @@ export function ChatPage({

<ChatPopup />

{showDeleteAllModal && (
<DeleteEntityModal
entityType="All Chats"
entityName="all your chat sessions"
onClose={() => setShowDeleteAllModal(false)}
additionalDetails="This action cannot be undone. All your chat sessions will be deleted."
onSubmit={async () => {
const response = await deleteAllChatSessions("Chat");
if (response.ok) {
setShowDeleteAllModal(false);
setPopup({
message: "All your chat sessions have been deleted.",
type: "success",
});
refreshChatSessions();
router.push("/chat");
} else {
setPopup({
message: "Failed to delete all chat sessions.",
type: "error",
});
}
}}
/>
)}

{currentFeedback && (
<FeedbackModal
feedbackType={currentFeedback[0]}
Expand Down Expand Up @@ -2132,6 +2155,7 @@ export function ChatPage({
removeToggle={removeToggle}
showShareModal={showShareModal}
showDeleteModal={showDeleteModal}
showDeleteAllModal={() => setShowDeleteAllModal(true)}
/>
</div>
</div>
Expand Down Expand Up @@ -2742,6 +2766,10 @@ export function ChatPage({
removeDocs={() => {
clearSelectedDocuments();
}}
showDocs={() => {
setFiltersToggled(false);
setDocumentSidebarToggled(true);
}}
removeFilters={() => {
filterManager.setSelectedSources([]);
filterManager.setSelectedTags([]);
Expand All @@ -2754,7 +2782,6 @@ export function ChatPage({
chatState={currentSessionChatState}
stopGenerating={stopGenerating}
openModelSettings={() => setSettingsToggled(true)}
showDocs={() => setDocumentSelection(true)}
selectedDocuments={selectedDocuments}
// assistant stuff
selectedAssistant={liveAssistant}
Expand Down
15 changes: 2 additions & 13 deletions web/src/app/chat/input/ChatInputBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,7 @@ import { SettingsContext } from "@/components/settings/SettingsProvider";
import { ChatState } from "../types";
import UnconfiguredProviderText from "@/components/chat_search/UnconfiguredProviderText";
import { useAssistants } from "@/components/context/AssistantsContext";
import AnimatedToggle from "@/components/search/SearchBar";
import { Popup } from "@/components/admin/connectors/Popup";
import { AssistantsTab } from "../modal/configuration/AssistantsTab";
import { IconType } from "react-icons";
import { LlmTab } from "../modal/configuration/LlmTab";
import { XIcon } from "lucide-react";
import { FilterPills } from "./FilterPills";
import { Tag } from "@/lib/types";
import FiltersDisplay from "./FilterDisplay";

const MAX_INPUT_HEIGHT = 200;
Expand All @@ -47,7 +40,6 @@ interface ChatInputBarProps {
removeFilters: () => void;
removeDocs: () => void;
openModelSettings: () => void;
showDocs: () => void;
showConfigureAPIKey: () => void;
selectedDocuments: OnyxDocument[];
message: string;
Expand All @@ -57,6 +49,7 @@ interface ChatInputBarProps {
filterManager: FilterManager;
llmOverrideManager: LlmOverrideManager;
chatState: ChatState;
showDocs: () => void;
alternativeAssistant: Persona | null;
// assistants
selectedAssistant: Persona;
Expand All @@ -75,8 +68,8 @@ export function ChatInputBar({
removeFilters,
removeDocs,
openModelSettings,
showDocs,
showConfigureAPIKey,
showDocs,
selectedDocuments,
message,
setMessage,
Expand Down Expand Up @@ -284,10 +277,6 @@ export function ChatInputBar({
</div>
)}

{/* <div>
<SelectedFilterDisplay filterManager={filterManager} />
</div> */}

<UnconfiguredProviderText showConfigureAPIKey={showConfigureAPIKey} />

<div
Expand Down
10 changes: 10 additions & 0 deletions web/src/app/chat/lib.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,16 @@ export async function deleteChatSession(chatSessionId: string) {
return response;
}

export async function deleteAllChatSessions(sessionType: "Chat" | "Search") {
const response = await fetch(`/api/chat/delete-all-chat-sessions`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
});
return response;
}

export async function* simulateLLMResponse(input: string, delay: number = 30) {
// Split the input string into tokens. This is a simple example, and in real use case, tokenization can be more complex.
// Iterate over tokens and yield them one by one
Expand Down
3 changes: 3 additions & 0 deletions web/src/app/chat/sessionSidebar/HistorySidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ interface HistorySidebarProps {
showDeleteModal?: (chatSession: ChatSession) => void;
stopGenerating?: () => void;
explicitlyUntoggle: () => void;
showDeleteAllModal?: () => void;
backgroundToggled?: boolean;
}

Expand All @@ -52,6 +53,7 @@ export const HistorySidebar = forwardRef<HTMLDivElement, HistorySidebarProps>(
stopGenerating = () => null,
showShareModal,
showDeleteModal,
showDeleteAllModal,
backgroundToggled,
},
ref: ForwardedRef<HTMLDivElement>
Expand Down Expand Up @@ -176,6 +178,7 @@ export const HistorySidebar = forwardRef<HTMLDivElement, HistorySidebarProps>(
currentChatId={currentChatId}
folders={folders}
openedFolders={openedFolders}
showDeleteAllModal={showDeleteAllModal}
/>
</div>
</>
Expand Down
Loading
Loading