fix: update step duration display and logic (#4506)

* feat: Add durationStore for managing chat durations and intervals and update duration display logic to use store

* [autofix.ci] apply automated fixes

* Expand `recursive_serialize_or_str` to support `BaseModelV1` subclasses

* fix: Update duration calculation for event handlers

Improve accuracy of duration measurement in event handlers by centralizing the calculation method. This ensures consistent timing across different events and enhances the reliability of event processing.

* refactor: improve duration calculation logic

Enhance the duration calculation by clearly handling both integer and float timestamps. This ensures accurate duration tracking and simplifies the code structure, improving maintainability and readability.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>
This commit is contained in:
anovazzi1 2024-11-12 11:19:13 -03:00 • committed by GitHub
commit f34d57acb7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 105 additions and 35 deletions

View file

@ -17,12 +17,14 @@ interface ContentBlockDisplayProps {
contentBlocks: ContentBlock[];
isLoading?: boolean;
state?: string;
chatId: string;
}
export function ContentBlockDisplay({
contentBlocks,
isLoading,
state,
chatId,
}: ContentBlockDisplayProps) {
const [isExpanded, setIsExpanded] = useState(false);
@ -100,7 +102,7 @@ export function ContentBlockDisplay({
</div>
</div>
<div className="flex items-center gap-2">
<DurationDisplay duration={totalDuration} />
<DurationDisplay duration={totalDuration} chatId={chatId} />
<motion.div
animate={{ rotate: isExpanded ? 180 : 0 }}
transition={{ duration: 0.2, ease: "easeInOut" }}
@ -190,7 +192,10 @@ export function ContentBlockDisplay({
</motion.div>
)}
</AnimatePresence>
<ContentDisplay content={content} />
<ContentDisplay
content={content}
chatId={`${chatId}-${index}`}
/>
</motion.div>
))}
</div>

View file

@ -8,7 +8,13 @@ import SimplifiedCodeTabComponent from "../codeTabsComponent/ChatCodeTabComponen
import ForwardedIconComponent from "../genericIconComponent";
import DurationDisplay from "./DurationDisplay";
export default function ContentDisplay({ content }: { content: ContentType }) {
export default function ContentDisplay({
content,
chatId,
}: {
content: ContentType;
chatId: string;
}) {
// First render the common BaseContent elements if they exist
const renderHeader = content.header && (
<>
@ -36,7 +42,7 @@ export default function ContentDisplay({ content }: { content: ContentType }) {
);
const renderDuration = content.duration !== undefined && (
<div className="absolute right-2 top-4">
<DurationDisplay duration={content.duration} />
<DurationDisplay duration={content.duration} chatId={chatId} />
</div>
);

View file

@ -1,34 +1,45 @@
import { useEffect, useState } from "react";
import { useDurationStore } from "@/stores/durationStore";
import { useEffect } from "react";
import { AnimatedNumber } from "../animatedNumbers";
import ForwardedIconComponent from "../genericIconComponent";
import Loading from "../ui/loading";
export default function DurationDisplay({ duration }: { duration?: number }) {
const [elapsedTime, setElapsedTime] = useState(0);
const [intervalId, setIntervalId] = useState<NodeJS.Timeout | null>(null);
interface DurationDisplayProps {
duration?: number;
chatId: string;
}
export default function DurationDisplay({
duration,
chatId,
}: DurationDisplayProps) {
const {
durations,
setDuration,
incrementDuration,
clearInterval: clearDurationInterval,
setInterval: setDurationInterval,
} = useDurationStore();
useEffect(() => {
if (duration !== undefined && intervalId) {
clearInterval(intervalId);
setIntervalId(null);
if (duration !== undefined) {
setDuration(chatId, duration);
clearDurationInterval(chatId);
return;
}
if (duration === undefined && !intervalId) {
const id = setInterval(() => {
setElapsedTime((prev) => prev + 10);
}, 10);
setIntervalId(id);
}
const intervalId = setInterval(() => {
incrementDuration(chatId);
}, 10);
setDurationInterval(chatId, intervalId);
return () => {
if (intervalId) {
clearInterval(intervalId);
}
clearDurationInterval(chatId);
};
}, [duration]);
}, [duration, chatId]);
const displayTime = duration ?? elapsedTime;
const displayTime = duration ?? durations[chatId] ?? 0;
const secondsValue = displayTime / 1000;
const humanizedTime = `${secondsValue.toFixed(1)}s`;

View file

@ -479,6 +479,7 @@ export default function ChatMessage({
chat.properties?.state === "partial"
}
state={chat.properties?.state}
chatId={chat.id}
/>
)}
{!chat.isSend ? (

View file

@ -0,0 +1,38 @@
import { create } from "zustand";
interface DurationState {
durations: Record<string, number>;
intervals: Record<string, NodeJS.Timeout>;
setDuration: (chatId: string, duration: number) => void;
incrementDuration: (chatId: string) => void;
clearInterval: (chatId: string) => void;
setInterval: (chatId: string, intervalId: NodeJS.Timeout) => void;
}
export const useDurationStore = create<DurationState>((set) => ({
durations: {},
intervals: {},
setDuration: (chatId, duration) =>
set((state) => ({
durations: { ...state.durations, [chatId]: duration },
})),
incrementDuration: (chatId) =>
set((state) => ({
durations: {
...state.durations,
[chatId]: (state.durations[chatId] || 0) + 10,
},
})),
clearInterval: (chatId) =>
set((state) => {
if (state.intervals[chatId]) {
clearInterval(state.intervals[chatId]);
}
const { [chatId]: _, ...rest } = state.intervals;
return { intervals: rest };
}),
setInterval: (chatId, intervalId) =>
set((state) => ({
intervals: { ...state.intervals, [chatId]: intervalId },
})),
}));