Skip to content

Commit

Permalink
fix chat streaming
Browse files Browse the repository at this point in the history
  • Loading branch information
zzaym committed Nov 3, 2024
1 parent aebd8bd commit 55a08cf
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 47 deletions.
7 changes: 5 additions & 2 deletions splicing/backend/app/api/endpoints/converse.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,11 @@ async def event_generator():
if chunk:
yield json.dumps(chunk) + CHUNK_DELIMITER

snapshot = await graph.aget_state(config)
logger.debug("CONVERSE - response: %s", snapshot.values["messages"][-1])
# get the new snapshot
snapshot = await graph.aget_state(config)
response = snapshot.values["messages"][-1]

logger.debug("CONVERSE - response: %s", response)

return StreamingResponse(event_generator(), media_type="application/x-ndjson")

Expand Down
2 changes: 1 addition & 1 deletion splicing/frontend/app/project/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default function ProjectPage({ params }: { params: { id: string } }) {
<div className="flex h-screen w-full flex-col">
<Siderbar />
<Header />
<div className="flex flex-col pl-40 pt-14 fixed inset-0">
<div className="flex flex-col pl-40 pt-12 fixed inset-0">
<main className="flex items-start gap-4 p-4 h-[calc(100vh-56px)] max-h-[calc(100vh-56px)]">
<div className="w-full h-full">
<ResizablePanelGroup direction="horizontal" className="h-full">
Expand Down
13 changes: 10 additions & 3 deletions splicing/frontend/components/chat/chat-bottom-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import useProjectStore from "@/store/project";

const ChatBottomBar = () => {
const [message, setMessage] = useState<string>("");
const [isStreamingMessage, setIsStreamingMessage] = useState(false);
const [addMessage, loadingMessage] = useProjectStore((state) => [
state.addMessage,
state.loadingMessage,
Expand All @@ -18,13 +19,18 @@ const ChatBottomBar = () => {
};

const handleSend = async () => {
if (message.trim()) {
if (message.trim() && !isStreamingMessage) {
const newMessage = {
role: "user",
content: message.trim(),
};
setMessage("");
await addMessage(newMessage);
setIsStreamingMessage(true);
try {
await addMessage(newMessage);
} finally {
setIsStreamingMessage(false);
}

if (inputRef.current) {
inputRef.current.focus();
Expand Down Expand Up @@ -92,7 +98,8 @@ const ChatBottomBar = () => {
<Button
variant="ghost"
size="icon"
className="flex items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground"
disabled={isStreamingMessage}
className="flex items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground disabled:opacity-50"
onClick={handleSend}
>
<SendHorizontal className="h-5 w-5" />
Expand Down
79 changes: 40 additions & 39 deletions splicing/frontend/components/chat/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ const Chat = () => {

const scrollToBottom = () => {
if (messagesContainerRef.current) {
messagesContainerRef.current.scrollTo({
top: messagesContainerRef.current.scrollHeight,
behavior: "smooth",
});
messagesContainerRef.current.scrollTop =
messagesContainerRef.current.scrollHeight;
}
};

Expand All @@ -63,45 +61,47 @@ const Chat = () => {
}
} else if (lastMessage.role === "user") {
setHasUserSentMessage(true);
scrollToBottom();
}
}
}, [lastMessage, hasUserSentMessage]);

return (
<div
className="w-full h-full max-h-full border rounded-lg overflow-y-auto overflow-x-hidden justify-between gap-4 flex flex-col"
ref={messagesContainerRef}
>
<div className="flex flex-col justify-start">
<header className="h-10 flex flex-col p-4">
<div className="flex justify-between items-center">
<h3 className="text-xl font-medium leading-none tracking-tight">
Assistant
</h3>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
className="rounded-full w-6 h-6"
size="icon"
variant="ghost"
onClick={handleReset}
>
{reset ? (
<Check className="h-4 w-4" />
) : (
<RotateCcw className="h-4 w-4" />
)}
<span className="sr-only">Reset</span>
</Button>
</TooltipTrigger>
<TooltipContent side="top">Reset</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
<Separator className="my-4" />
</header>
<div className="w-full overflow-y-auto overflow-x-hidden flex flex-col mt-4">
<div className="w-full h-full flex flex-col border rounded-lg">
<header className="flex-none h-10 p-4 z-10 relative">
<div className="flex justify-between items-center">
<h3 className="text-xl font-medium leading-none tracking-tight">
Assistant
</h3>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
className="rounded-full w-6 h-6"
size="icon"
variant="ghost"
onClick={handleReset}
>
{reset ? (
<Check className="h-4 w-4" />
) : (
<RotateCcw className="h-4 w-4" />
)}
<span className="sr-only">Reset</span>
</Button>
</TooltipTrigger>
<TooltipContent side="top">Reset</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
<Separator className="my-4" />
</header>

<div
ref={messagesContainerRef}
className="flex-1 overflow-y-auto min-h-0 scroll-smooth mt-4"
>
<div className="w-full flex flex-col">
<AnimatePresence>
{messages?.map(
(message, index) =>
Expand Down Expand Up @@ -164,7 +164,8 @@ const Chat = () => {
</AnimatePresence>
</div>
</div>
<footer>

<footer className="flex-none bg-background">
<ChatBottomBar />
</footer>
</div>
Expand Down
4 changes: 2 additions & 2 deletions splicing/frontend/store/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,12 +313,12 @@ const useProjectStore = create<ProjectState>((set, get) => ({
responseMessage.content = chunk.data;
}
set((state) => ({
messages: [...state.messages.slice(0, -1), responseMessage!]
messages: [...state.messages.slice(0, -1), { ...responseMessage! }]
}));
}
} else if (chunk.type === 'generate-result') {
const currentSection = get().getCurrentSection();
if (currentSection && currentSection.currentBlockId) {
if (currentSection?.currentBlockId) {
const updatedBlocks = currentSection.blocks.map((block) =>
block.id === currentSection.currentBlockId ? { ...block, generateResult: JSON.parse(chunk.data) } : block
);
Expand Down

0 comments on commit 55a08cf

Please sign in to comment.