[Feature] compare for 2 diff models (#4356)
* compare for 2 diff models * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * resolving gemini comments * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix(studio): refine model-load toast stop action and compare selector sizing (#4369) Co-authored-by: imagineer99 <samleejackson0@gmail.com> --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Daniel Han <danielhanchen@gmail.com> Co-authored-by: imagineer99 <samleejackson0@gmail.com>
This commit is contained in:
parent
2a8d6b2b82
commit
93ab09d195
3 changed files with 31 additions and 23 deletions
|
|
@ -4,8 +4,10 @@
|
|||
import { Progress } from "@/components/ui/progress";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { XIcon } from "lucide-react";
|
||||
|
||||
type ModelLoadDescriptionProps = {
|
||||
title?: string | null;
|
||||
message?: string | null;
|
||||
progressPercent?: number | null;
|
||||
progressLabel?: string | null;
|
||||
|
|
@ -17,6 +19,7 @@ function clampProgress(value: number): number {
|
|||
}
|
||||
|
||||
export function ModelLoadDescription({
|
||||
title,
|
||||
message,
|
||||
progressPercent,
|
||||
progressLabel,
|
||||
|
|
@ -25,10 +28,14 @@ export function ModelLoadDescription({
|
|||
const hasProgress = typeof progressPercent === "number";
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="flex min-h-12 w-full items-stretch gap-2">
|
||||
<div className="flex h-full shrink-0 items-center self-center">
|
||||
<Spinner className="size-4 text-foreground" />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
{title ? <p className="text-foreground leading-5 font-semibold">{title}</p> : null}
|
||||
{hasProgress ? (
|
||||
<div className="w-[12.5rem] max-w-full">
|
||||
<div className="w-full pt-1">
|
||||
<div className="flex items-center justify-between text-[10px] font-medium tracking-[0.08em] text-muted-foreground/80">
|
||||
<span>{progressLabel}</span>
|
||||
<span>{Math.round(clampProgress(progressPercent))}%</span>
|
||||
|
|
@ -36,18 +43,19 @@ export function ModelLoadDescription({
|
|||
<Progress value={clampProgress(progressPercent)} className="h-1 bg-foreground/[0.08]" />
|
||||
</div>
|
||||
) : message ? (
|
||||
<p className="text-xs leading-relaxed text-muted-foreground">{message}</p>
|
||||
<p className="pt-1 text-xs leading-relaxed text-muted-foreground">{message}</p>
|
||||
) : null}
|
||||
</div>
|
||||
{onStop ? (
|
||||
<Button
|
||||
type="button"
|
||||
size="xs"
|
||||
variant="outline"
|
||||
className="h-5 shrink-0 px-2 text-[10px]"
|
||||
size="icon-sm"
|
||||
variant="ghost"
|
||||
aria-label="Stop model loading"
|
||||
className="h-auto w-10 self-stretch shrink-0 rounded-xl text-muted-foreground hover:bg-destructive/10 hover:text-destructive focus-visible:text-destructive"
|
||||
onClick={onStop}
|
||||
>
|
||||
Stop
|
||||
<XIcon className="size-3.5" />
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
import { createElement, useCallback, useRef, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { ModelLoadDescription } from "../components/model-load-status";
|
||||
import {
|
||||
getDownloadProgress,
|
||||
|
|
@ -34,12 +33,10 @@ type SelectedModelInput = {
|
|||
};
|
||||
|
||||
const MODEL_LOAD_TOAST_CLASSNAMES = {
|
||||
toast: "items-start gap-2.5 pr-8",
|
||||
content: "gap-0.5",
|
||||
toast: "items-start gap-2.5",
|
||||
content: "gap-0.5 flex-1 min-w-0",
|
||||
title: "leading-5",
|
||||
description: "mt-0",
|
||||
closeButton:
|
||||
"!left-auto !right-1.5 !top-1.5 !translate-x-0 !translate-y-0 !border-transparent !bg-transparent !shadow-none hover:!bg-transparent hover:opacity-70",
|
||||
description: "mt-0 w-full",
|
||||
} as const;
|
||||
|
||||
const LORA_SUFFIX_RE = /_(\d{9,})$/;
|
||||
|
|
@ -200,12 +197,14 @@ export function useChatModelRuntime() {
|
|||
|
||||
const renderLoadDescription = useCallback(
|
||||
(
|
||||
title: string,
|
||||
message: string,
|
||||
progressPercent?: number | null,
|
||||
progressLabel?: string | null,
|
||||
onStop?: () => void,
|
||||
) =>
|
||||
createElement(ModelLoadDescription, {
|
||||
title,
|
||||
message,
|
||||
progressPercent,
|
||||
progressLabel,
|
||||
|
|
@ -448,18 +447,19 @@ export function useChatModelRuntime() {
|
|||
}
|
||||
}
|
||||
|
||||
const toastTitle = isDownloaded ? "Starting model…" : "Downloading model…";
|
||||
const toastId = toast(
|
||||
isDownloaded ? "Starting model…" : "Downloading model…",
|
||||
null,
|
||||
{
|
||||
icon: createElement(Spinner, { className: "size-4" }),
|
||||
description: renderLoadDescription(
|
||||
toastTitle,
|
||||
loadingDescription,
|
||||
isDownloaded ? null : 0,
|
||||
isDownloaded ? null : "Preparing download",
|
||||
cancelLoading,
|
||||
),
|
||||
duration: Infinity,
|
||||
closeButton: true,
|
||||
closeButton: false,
|
||||
classNames: MODEL_LOAD_TOAST_CLASSNAMES,
|
||||
onDismiss: (dismissedToast) => {
|
||||
if (loadToastIdRef.current !== dismissedToast.id) {
|
||||
|
|
@ -505,18 +505,18 @@ export function useChatModelRuntime() {
|
|||
});
|
||||
if (loadToastDismissedRef.current) return;
|
||||
toast(
|
||||
"Downloading model…",
|
||||
null,
|
||||
{
|
||||
id: toastId,
|
||||
icon: createElement(Spinner, { className: "size-4" }),
|
||||
description: renderLoadDescription(
|
||||
"Downloading model…",
|
||||
loadingDescription,
|
||||
pct,
|
||||
progressLabel,
|
||||
cancelLoading,
|
||||
),
|
||||
duration: Infinity,
|
||||
closeButton: true,
|
||||
closeButton: false,
|
||||
classNames: MODEL_LOAD_TOAST_CLASSNAMES,
|
||||
onDismiss: (dismissedToast) => {
|
||||
if (loadToastIdRef.current !== dismissedToast.id) return;
|
||||
|
|
@ -542,17 +542,17 @@ export function useChatModelRuntime() {
|
|||
if (progressInterval) clearInterval(progressInterval);
|
||||
return;
|
||||
}
|
||||
toast("Starting model…", {
|
||||
toast(null, {
|
||||
id: toastId,
|
||||
icon: createElement(Spinner, { className: "size-4" }),
|
||||
description: renderLoadDescription(
|
||||
"Starting model…",
|
||||
"Download complete. Loading the model into memory.",
|
||||
100,
|
||||
"Download complete",
|
||||
cancelLoading,
|
||||
),
|
||||
duration: Infinity,
|
||||
closeButton: true,
|
||||
closeButton: false,
|
||||
classNames: MODEL_LOAD_TOAST_CLASSNAMES,
|
||||
onDismiss: (dismissedToast) => {
|
||||
if (loadToastIdRef.current !== dismissedToast.id) return;
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ export function SharedComposer({
|
|||
// Side 1: load → generate → wait
|
||||
if (handle1 && model1?.id) {
|
||||
toast("Loading Model 1…", { id: toastId, description: name1, duration: Infinity });
|
||||
await ensureModelLoaded(model1);
|
||||
const status = await ensureModelLoaded(model1);
|
||||
toast("Generating with Model 1…", { id: toastId, description: name1, duration: Infinity });
|
||||
const done = handle1.waitForRunEnd();
|
||||
handle1.startRun();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue