Skip to content

Commit

Permalink
Improved chat segment markdown rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
salmenus committed May 12, 2024
1 parent c94c330 commit 7df7e8e
Showing 1 changed file with 34 additions and 2 deletions.
36 changes: 34 additions & 2 deletions packages/react/core/src/logic/ChatSegment/ChatSegmentComp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export const ChatSegmentComp: <AiMsg>(
() => new Map<string, RefObject<ChatItemImperativeProps>>(), [],
);

const chatItemsStreamingBuffer = useMemo(
() => new Map<string, Array<string>>(), [],
);

useEffect(() => {
if (chatSegment.items.length === 0) {
chatItemsRef.clear();
Expand Down Expand Up @@ -54,11 +58,21 @@ export const ChatSegmentComp: <AiMsg>(
useImperativeHandle(ref, () => ({
streamChunk: (chatItemId: string, chunk: string) => {
const chatItemCompRef = chatItemsRef.get(chatItemId);
chatItemCompRef?.current?.streamChunk(chunk);
if (chatItemCompRef?.current) {
chatItemCompRef.current.streamChunk(chunk);
} else {
// Buffer the chunk if the chat item is not rendered yet.
const chatItemStreamingBuffer = chatItemsStreamingBuffer.get(chatItemId) ?? [];
chatItemsStreamingBuffer.set(chatItemId, [...chatItemStreamingBuffer, chunk]);
}
},
completeStream: (chatItemId: string) => {
const chatItemCompRef = chatItemsRef.get(chatItemId);
chatItemCompRef?.current?.completeStream();
if (!chatItemCompRef?.current) {
return;
}

chatItemCompRef.current.completeStream();
chatItemsRef.delete(chatItemId);
},
}), []);
Expand All @@ -67,6 +81,24 @@ export const ChatSegmentComp: <AiMsg>(
ChatItemComp<AiMsg>,
), []);

// Every time the chat segment is rendered, we check if there are any streamed chunks buffered waiting for a
// chat item to be rendered. If buffered chunks are found, along with the chat item reference, we stream the chunks
// to the chat item.
useEffect(() => {
if (chatItemsStreamingBuffer.size > 0) {
chatItemsStreamingBuffer.forEach((bufferedChunks, chatItemId) => {
const chatItemCompRef = chatItemsRef.get(chatItemId);
if (chatItemCompRef?.current) {
// A chat item with buffered chunks is found.
bufferedChunks.forEach((chunk) => {
chatItemCompRef?.current?.streamChunk(chunk);
});
chatItemsStreamingBuffer.delete(chatItemId);
}
});
}
}); // No dependencies — We always want to run this effect after every render.

const chatItems = chatSegment.items;
if (chatItems.length === 0) {
return null;
Expand Down

0 comments on commit 7df7e8e

Please sign in to comment.