Skip to content

Commit

Permalink
add feature to hide messages
Browse files Browse the repository at this point in the history
  • Loading branch information
ericcccsliu committed Mar 29, 2024
1 parent d8ee848 commit a93ed98
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 36 deletions.
Binary file modified api/__pycache__/index.cpython-311.pyc
Binary file not shown.
Binary file modified api/routes/__pycache__/auth_routes.cpython-311.pyc
Binary file not shown.
Binary file modified api/routes/__pycache__/conversation_routes.cpython-311.pyc
Binary file not shown.
16 changes: 14 additions & 2 deletions api/routes/conversation_routes.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from api.models.conversation import Message
from api.utils.conversation_utils import create_conversation, add_message, get_conversation_by_id, rename_conversation, get_conversations_by_user, update_conversation_model
from api.utils.llm_providers.openai import openai_generate_response
from api.utils.conversation_utils import update_conversation_messages, create_conversation, add_message, get_conversation_by_id, get_conversations_by_user, update_conversation_model
from api.utils.llm_utils import generate_response_stream
from api.utils.auth_utils import get_current_user
from api.models.user import User
Expand Down Expand Up @@ -40,6 +40,18 @@ async def add_message_route(conversation_id: str, message_create: MessageCreate,
else:
raise HTTPException(status_code=404, detail="Conversation not found")

@router.put("/conversations/{conversation_id}/messages")
async def update_messages_route(
conversation_id: str,
updated_messages: List[Message],
current_user: User = Depends(get_current_user),
):
success = await update_conversation_messages(conversation_id, updated_messages, current_user.email)
if success:
return {"message": "Messages updated successfully"}
else:
raise HTTPException(status_code=404, detail="Conversation not found")

@router.patch("/conversations/{conversation_id}")
async def update_conversation_route(
conversation_id: str,
Expand Down
Binary file modified api/utils/__pycache__/auth_utils.cpython-311.pyc
Binary file not shown.
Binary file modified api/utils/__pycache__/conversation_utils.cpython-311.pyc
Binary file not shown.
Binary file modified api/utils/__pycache__/db_utils.cpython-311.pyc
Binary file not shown.
Binary file modified api/utils/__pycache__/llm_utils.cpython-311.pyc
Binary file not shown.
17 changes: 16 additions & 1 deletion api/utils/conversation_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from datetime import datetime, timezone
from typing import List

from api.utils.db_utils import get_db
from api.models.conversation import Message, Conversation, LanguageModel
from bson import ObjectId
Expand Down Expand Up @@ -74,4 +76,17 @@ async def update_conversation_model(conversation_id: str, model_provider: str, m
{"$set": update_fields}
)
return result.modified_count > 0
return False
return False

async def update_conversation_messages(conversation_id: str, updated_messages: List[Message], user_email: str):
db = await get_db()
conversations_collection = db["conversations"]
conversation = await get_conversation_by_id(conversation_id, user_email)
if conversation:
await conversations_collection.update_one(
{"_id": ObjectId(conversation_id)},
{"$set": {"messages": [message.dict() for message in updated_messages]}},
)
return True
else:
return False
2 changes: 2 additions & 0 deletions api/utils/llm_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from api.utils.llm_providers.anthropic import anthropic_generate_response, generate_conversation_name

async def generate_response_stream(conversation):
visible_messages = [message for message in conversation.messages if not message.hidden]
conversation.messages = visible_messages
collected_chunks = []
if conversation.model.provider == "openai":
async for chunk in openai_generate_response(conversation):
Expand Down
22 changes: 19 additions & 3 deletions app/components/ConversationMessages.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useEffect, useRef } from "react";
import { Box, Text, VStack } from "@chakra-ui/react";
import { Box, Text, VStack, Button } from "@chakra-ui/react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
Expand All @@ -12,10 +12,12 @@ import { Components } from "react-markdown";
export interface Message {
role: "user" | "assistant";
content: string;
hidden?: boolean;
}

interface ConversationMessagesProps {
messages: Message[];
handleHideMessage: (index: number) => Promise<void>;
userName?: string;
}

Expand All @@ -27,6 +29,7 @@ type MathComponents = {

const ConversationMessages: React.FC<ConversationMessagesProps> = ({
messages,
handleHideMessage,
userName = "User",
}) => {
const messagesEndRef = useRef<HTMLDivElement>(null);
Expand All @@ -43,11 +46,15 @@ const ConversationMessages: React.FC<ConversationMessagesProps> = ({
borderRadius="none"
borderWidth="1px"
p={4}
borderColor="black"
borderColor={message.hidden ? "gray.300" : "black"}
alignSelf={message.role === "user" ? "flex-end" : "flex-start"}
maxWidth="100%"
>
<Text fontWeight="bold" mb={1}>
<Text
fontWeight="bold"
mb={1}
color={message.hidden ? "gray.500" : "inherit"}
>
[{index}] {message.role === "user" ? userName : "Assistant"}
</Text>
<ReactMarkdown
Expand Down Expand Up @@ -87,6 +94,15 @@ const ConversationMessages: React.FC<ConversationMessagesProps> = ({
>
{message.content}
</ReactMarkdown>
<Button
size="xs"
variant="ghost"
onClick={() => handleHideMessage(index)}
ml="auto"
mt={2}
>
hide
</Button>
</Box>
))}
<div ref={messagesEndRef} />
Expand Down
105 changes: 76 additions & 29 deletions app/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import {
DrawerOverlay,
useDisclosure,
IconButton,
Text,
Divider,
} from "@chakra-ui/react";

import { ChevronRightIcon } from "@chakra-ui/icons";
import { ConversationInfo } from "../utils";

Expand All @@ -19,14 +20,34 @@ interface SidebarProps {
setConversationId: (id: string) => void;
}

const handleConversationClick = (
id: string,
setConversationId: (id: string) => void,
onClose: () => void
) => {
setConversationId(id);
onClose();
};

const Sidebar = ({ conversations, setConversationId }: SidebarProps) => {
const { isOpen, onOpen, onClose } = useDisclosure();

const handleConversationClick = (id: string) => {
setConversationId(id);
onClose();
const groupConversationsByDate = (conversations: ConversationInfo[]) => {
const groupedConversations: Record<string, ConversationInfo[]> = {};

conversations.forEach((conversation) => {
const date = new Date(conversation.created_at).toDateString();
if (!groupedConversations[date]) {
groupedConversations[date] = [];
}
groupedConversations[date].push(conversation);
});

return groupedConversations;
};

const groupedConversations = groupConversationsByDate(conversations);

return (
<>
<IconButton
Expand All @@ -39,31 +60,57 @@ const Sidebar = ({ conversations, setConversationId }: SidebarProps) => {
variant="ghost"
height="100px"
/>
<Drawer isOpen={isOpen} onClose={onClose} placement="left" >
{/* <DrawerOverlay> */}
<DrawerContent>
<DrawerBody>
<Box w="100%" h="100vh" bg="white">
<VStack w="100%" align="stretch" spacing={1} pt={5}>
{conversations.map((conversation) => (
<Button
paddingLeft={2}
justifyContent="flex-start"
key={conversation.id}
variant="ghost"
borderRadius="none"
pr={0}
height={8}
onClick={() => handleConversationClick(conversation.id)}
>
{conversation.name}
</Button>
))}
</VStack>
</Box>
</DrawerBody>
</DrawerContent>
{/* </DrawerOverlay> */}
<Drawer isOpen={isOpen} onClose={onClose} placement="left">
<DrawerOverlay>
<DrawerContent>
<DrawerBody>
<Box w="100%" h="100vh" bg="white">
<VStack w="100%" align="stretch" spacing={1} pt={5}>
{Object.entries(groupedConversations).map(
([date, conversationsOnDate]) => (
<Box key={date}>
<Text fontSize="xs" fontWeight="semibold" ml={2} mb={1}>
{date}
</Text>
{conversationsOnDate.map((conversation) => (
<Button
key={conversation.id}
paddingLeft={4}
justifyContent="flex-start"
variant="ghost"
borderRadius="none"
pr={0}
height={8}
width='200px'
onClick={() =>
handleConversationClick(
conversation.id,
setConversationId,
onClose
)
}
>
<Text
fontSize="sm"
fontWeight="semibold"
whiteSpace="nowrap"
overflow="hidden"
textOverflow="ellipsis"
maxW="200px"
>
{conversation.name}
</Text>
</Button>
))}
<Divider />
</Box>
)
)}
</VStack>
</Box>
</DrawerBody>
</DrawerContent>
</DrawerOverlay>
</Drawer>
</>
);
Expand Down
29 changes: 28 additions & 1 deletion app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,30 @@ export default function Home() {
setTextValue(event.target.value);
};

const handleHideMessage = async (index: number) => {
try {
const updatedMessages = messages.map((msg, i) =>
i === index ? { ...msg, hidden: !msg.hidden } : msg
);
await fetch(
`${process.env.BACKEND_URL}/conversations/${conversationId}/messages`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${cookies.token}`,
},
body: JSON.stringify({ messages: updatedMessages }),
mode: "cors",
credentials: "include",
}
);
setMessages(updatedMessages);
} catch (error) {
console.error("Error toggling message visibility:", error);
}
};

useEffect(() => {
const token = searchParams.get("token");

Expand Down Expand Up @@ -139,7 +163,10 @@ export default function Home() {
justify="space-between"
>
<Box width="100%" pt={2} pb={2}>
<ConversationMessages messages={messages} />
<ConversationMessages
messages={messages}
handleHideMessage={handleHideMessage}
/>
</Box>
</VStack>
</Center>
Expand Down

0 comments on commit a93ed98

Please sign in to comment.