Skip to content
This repository has been archived by the owner on Sep 9, 2024. It is now read-only.

Co-pilot-Citation and Enhancement #179

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
81 changes: 3 additions & 78 deletions packages/ocular-ui/components/chat/chat-helpers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import { toast } from "sonner"
import { v4 as uuidv4 } from "uuid"
import { createReader,readStream } from '@/lib/stream';
import { da, ro } from "date-fns/locale"
import { set } from "nprogress"
import { processStreamChatResponse } from "@/lib/parse-chat-stream"


export const handleChat = async (
Expand Down Expand Up @@ -54,91 +56,14 @@ export const fetchChatResponse = async (
api.chats.sendMessage(chat.id,{message:content,stream:true},cancelTokenSource)
.then(async response => {
console.log("Streaming Copilot Response")
const reader = createReader(response.body);
const chunks = readStream(reader);
for await (const chunk of chunks) {
setChatMessages(prevChatMessages => {
const updatedMessages = [...prevChatMessages];
if (idx=== 0) {
updatedMessages.push({
message: {
chat_id: chunk.metadata?.chat_id,
content: chunk.choices[0].delta.content,
created_at: new Date(),
id: "123",
role: chunk.metadata.role,
updated_at: new Date(),
user_id: chunk.metadata.user_id
},
fileItems: []
});
idx++;
} else {
const lastMessage = updatedMessages[updatedMessages.length - 1];
lastMessage.message.content = chunk.choices[0].delta.content;
lastMessage.message.updated_at = new Date();
}
return updatedMessages;
});
}

// setChatMessages(prevChatMessages => [...prevChatMessages,
// {
// message: {
// chat_id: data.metadata?.chat_id,
// content: data.choices[0].delta.content,
// created_at: new Date(),
// id: "123",
// role: data.metadata.role,
// updated_at: new Date(),
// user_id: data.metadata.user_id
// },
// fileItems: []
// }
// ]);

processStreamChatResponse(response,setChatMessages,chat.id);
})
.catch(error => {
console.error(error);
setIsGenerating(false)
});
}

// lastChatMessage: ChatMessage,
export const processResponse = async (
response: Response,
cancelTokenSource: CancelTokenSource,
setFirstTokenReceived: React.Dispatch<React.SetStateAction<boolean>>,
setChatMessages: React.Dispatch<React.SetStateAction<ChatMessage[]>>,
// setToolInUse: React.Dispatch<React.SetStateAction<string>>
) => {
let fullText = ""
let contentToAdd = ""


if (response) {

router.push(`/dashboard/chat/${response.message.chat_id}`)
setChatMessages(prevChatMessages => [...prevChatMessages,
{
message: {
chat_id: response.message.chat_id,
content: response.message.content,
created_at: response.message.created_at,
id: response.message.id,
role: response.message.role,
updated_at: response.message.updated_at,
user_id: response.message.user_id
},
fileItems: []
}
]);
// return fullText
return response.message.content
} else {
throw new Error("Response body is null")
}
}

export const handleCreateChat = async (
messageContent: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
handleCreateChat,
handleChat,
} from "../chat-helpers/index"
import { v4 as uuidv4 } from 'uuid';



export const useChatHandler = () => {
Expand Down Expand Up @@ -88,12 +90,13 @@ export const useChatHandler = () => {
chat_id: currentChat?.id,
content: messageContent,
created_at: new Date(),
id: "123",
id: uuidv4(),
role: "user",
updated_at: new Date(),
user_id: currentChat?.user_id
},
fileItems: []
fileItems: [],
followUpQuestions:[]
}
]);

Expand Down
71 changes: 62 additions & 9 deletions packages/ocular-ui/components/chat/chat-messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,76 @@ import { ApplicationContext } from "@/context/context"
import { FC, useContext, useState } from "react"
import { Message } from "../messages/message"
import { Message as MessageType } from "@/types/chat"
import { formatLabel } from '@/lib/utils';
import Image from 'next/image';
import { Separator } from "../ui/separator";
import { useChatHandler } from "./chat-hooks/use-chat-handler";
import {v4 as uuidv4} from 'uuid';

interface ChatMessagesProps {}
interface ChatMessagesProps { }

export const ChatMessages: FC<ChatMessagesProps> = ({}) => {
export const ChatMessages: FC<ChatMessagesProps> = ({ }) => {
const { chatMessages } = useContext(ApplicationContext)
const [editingMessage, setEditingMessage] = useState<MessageType>()

const {
chatInputRef,
handleSendMessage,
} = useChatHandler()

return chatMessages
.sort((a, b) => new Date(a.message.created_at).getTime() - new Date(b.message.created_at).getTime())
.sort((a, b) => new Date(a.message.created_at).getTime() - new Date(b.message.created_at).getTime())
.map((chatMessage, index, array) => {
return (
<Message
key={chatMessage.message.id}
message={chatMessage.message}
isEditing={editingMessage?.id === chatMessage.message.id}
isLast={index === array.length - 1}
/>
<div className="flex flex-col justify-center items-center ">
<Message
key={chatMessage.message.id}
message={chatMessage.message}
isEditing={editingMessage?.id === chatMessage.message.id}
isLast={index === array.length - 1}
/>
{chatMessage.message.role === "assistant" && chatMessage.fileItems?.length > 0 && <div className="w-[1000px] ml-2">
<h1 className="font-bold text-xl">Sources</h1>
<Separator />
</div>}
{chatMessage.message.role === "assistant" && <div className={`flex flex-row space-x-5 mt-2 overflow-auto scrollbar-hide transition-all duration-300 justify-start items-center w-[1000px]`}>
{chatMessage.fileItems?.map((fileItem) => {
return (
<div
className="bg-blue-100/50 dark:bg-muted border flex flex-row rounded-2xl p-4 text-xs sm:text-base w-[200px] flex-none justify-center items-center text-left"
key={uuidv4()}
>
<div className="space-y-1 overflow-hidden text-left w-full h-[95px]">
<div className="flex flex-row space-x-0 justify-start items-start text-left w-full">
<Image src={fileItem && `/${fileItem.source}.svg`} alt={fileItem.title} className="mr-4 size-[20px]" width={10} height={10} />
<h3 className="text-sm mb-2 truncate font-semibold text-blue-800 group-hover:underline dark:text-blue-400">
{formatLabel(fileItem.source)}
</h3>
</div>
<p className="font-regular line-clamp-1 text-sm h-full" dangerouslySetInnerHTML={{ __html: fileItem.content }}></p>
</div>
</div>
)
})}
</div>}
{chatMessage.message.role === "assistant" && chatMessage.followUpQuestions?.length > 0 && <div className="w-[1000px] m-2">
<h1 className="font-bold text-xl">Related</h1>
<Separator />
</div>}
{chatMessage.message.role === "assistant" && <div className={`flex flex-col space-y-3 mt-2 overflow-auto scrollbar-hide transition-all duration-300 justify-start items-center w-[1000px]`} >
{chatMessage.followUpQuestions?.map((question, index) => {
return (
<div
className="bg-blue-100/50 dark:bg-muted border flex flex-col rounded-2xl p-3 cursor-pointer text-xs sm:text-base w-full justify-center items-start text-left"
key={uuidv4()}
onClick={() => handleSendMessage(question, false)}
>
<p className="font-regular line-clamp-1 text-sm h-full">{question}</p>
</div>
)
})}
</div>}
</div>
)
})
}
Expand Down
11 changes: 9 additions & 2 deletions packages/ocular-ui/components/chat/chat-ui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ChatMessages } from "./chat-messages"
import { ChatSecondaryButtons } from "./chat-secondary-buttons"

import api from "@/services/api"
import { set } from "nprogress"


interface ChatUIProps {}
Expand All @@ -17,6 +18,7 @@ export const ChatUI: FC<ChatUIProps> = ({}) => {
const params = useParams()

const {
chatMessages,
setChatMessages,
selectedChat,
setSelectedChat,
Expand Down Expand Up @@ -51,7 +53,7 @@ export const ChatUI: FC<ChatUIProps> = ({}) => {
} else {
setLoading(false)
}
}, [params])
}, [params]);

const fetchMessages = async () => {
const fetchedMessages = await api.chats.retrieve(params.chatid as string)
Expand All @@ -60,7 +62,12 @@ export const ChatUI: FC<ChatUIProps> = ({}) => {
message,
}
})
setChatMessages(fetchedChatMessages)
const currentChatMessages = localStorage.getItem(params.chatid as string);
if(currentChatMessages){
setChatMessages(JSON.parse(currentChatMessages));
return;
}
setChatMessages(fetchedChatMessages);
}

const fetchChat = async () => {
Expand Down
11 changes: 7 additions & 4 deletions packages/ocular-ui/components/messages/message-codeblock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useCopyToClipboard } from "@/lib/hooks/use-copy-to-clipboard"
import { IconCheck, IconCopy, IconDownload } from "@tabler/icons-react"
import { FC, memo } from "react"
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism"
import { dracula } from "react-syntax-highlighter/dist/cjs/styles/prism"

interface MessageCodeBlockProps {
language: string
Expand Down Expand Up @@ -86,7 +86,7 @@ export const MessageCodeBlock: FC<MessageCodeBlockProps> = memo(
}

return (
<div className="codeblock relative w-full bg-zinc-950 font-sans">
<div className="codeblock relative w-full bg-zinc-950 font-sans b-2 border border-gray-800 rounded-md">
<div className="flex w-full items-center justify-between bg-zinc-700 px-4 text-white">
<span className="text-xs lowercase">{language}</span>
<div className="flex items-center space-x-1">
Expand All @@ -111,12 +111,15 @@ export const MessageCodeBlock: FC<MessageCodeBlockProps> = memo(
</div>
<SyntaxHighlighter
language={language}
style={oneDark}
style={dracula}
showLineNumbers
customStyle={{
margin: 0,
width: "100%",
background: "transparent"
background: "transparent",
backdropFilter: "blur(10px)",
borderRadius: "8px",
padding: "10px"
}}
codeTagProps={{
style: {
Expand Down
Loading