miscallenous studio (#4293)
* miscallenous studio * chore: upload dataset misc * chore: redudancy studio cleanup * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: adress the pr comments * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: adress comments about recipes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
f44857b2df
commit
e280b0bebc
66 changed files with 3229 additions and 1105 deletions
|
|
@ -0,0 +1,88 @@
|
|||
"use client";
|
||||
|
||||
import { useMessageTiming } from "@assistant-ui/react";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { FC } from "react";
|
||||
|
||||
const formatTimingMs = (ms: number | undefined): string => {
|
||||
if (ms === undefined) return "—";
|
||||
if (ms < 1000) return `${Math.round(ms)}ms`;
|
||||
return `${(ms / 1000).toFixed(2)}s`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows streaming stats (TTFT, total time, chunks) as a badge with a
|
||||
* hover/focus tooltip. Renders nothing until the stream completes.
|
||||
*
|
||||
* Place it inside `ActionBarPrimitive.Root` in your `thread.tsx` so it
|
||||
* inherits the action bar's autohide behaviour:
|
||||
*
|
||||
* ```tsx
|
||||
* import { MessageTiming } from "@/components/assistant-ui/message-timing";
|
||||
*
|
||||
* <ActionBarPrimitive.Root >
|
||||
* <ActionBarPrimitive.Copy />
|
||||
* <ActionBarPrimitive.Reload />
|
||||
* <MessageTiming /> // <-- add this
|
||||
* </ActionBarPrimitive.Root>
|
||||
* ```
|
||||
*
|
||||
* @param side - Side of the tooltip relative to the badge trigger. Defaults to `"right"`.
|
||||
*/
|
||||
export const MessageTiming: FC<{
|
||||
className?: string;
|
||||
side?: "top" | "right" | "bottom" | "left";
|
||||
}> = ({ className, side = "right" }) => {
|
||||
const timing = useMessageTiming();
|
||||
if (timing?.totalStreamTime === undefined) return null;
|
||||
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
data-slot="message-timing-trigger"
|
||||
aria-label="Message timing"
|
||||
className={cn(
|
||||
"flex items-center rounded-md p-1 font-mono text-muted-foreground text-xs tabular-nums transition-colors hover:bg-accent hover:text-accent-foreground",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{formatTimingMs(timing.totalStreamTime)}
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
side={side}
|
||||
sideOffset={8}
|
||||
data-slot="message-timing-popover"
|
||||
className="[&_span>svg]:hidden! rounded-lg border bg-popover px-3 py-2 text-popover-foreground shadow-md"
|
||||
>
|
||||
<div className="grid min-w-35 gap-1.5 text-xs">
|
||||
{timing.firstTokenTime !== undefined && (
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<span className="text-muted-foreground">First token</span>
|
||||
<span className="font-mono tabular-nums">
|
||||
{formatTimingMs(timing.firstTokenTime)}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<span className="text-muted-foreground">Total</span>
|
||||
<span className="font-mono tabular-nums">
|
||||
{formatTimingMs(timing.totalStreamTime)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<span className="text-muted-foreground">Chunks</span>
|
||||
<span className="font-mono tabular-nums">{timing.totalChunks}</span>
|
||||
</div>
|
||||
</div>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
|
@ -6,6 +6,7 @@ import {
|
|||
ComposerAttachments,
|
||||
UserMessageAttachments,
|
||||
} from "@/components/assistant-ui/attachment";
|
||||
import { MessageTiming } from "@/components/assistant-ui/message-timing";
|
||||
import { MarkdownText } from "@/components/assistant-ui/markdown-text";
|
||||
import { Reasoning, ReasoningGroup } from "@/components/assistant-ui/reasoning";
|
||||
import { ToolFallback } from "@/components/assistant-ui/tool-fallback";
|
||||
|
|
@ -401,6 +402,7 @@ const AssistantActionBar: FC = () => {
|
|||
<RefreshCwIcon />
|
||||
</TooltipIconButton>
|
||||
</ActionBarPrimitive.Reload>
|
||||
<MessageTiming side="top" />
|
||||
<ActionBarMorePrimitive.Root>
|
||||
<ActionBarMorePrimitive.Trigger asChild={true}>
|
||||
<TooltipIconButton
|
||||
|
|
|
|||
|
|
@ -63,7 +63,10 @@ export function Navbar() {
|
|||
<header className="relative top-0 z-40 h-16 w-full">
|
||||
<div className="mx-auto grid h-full max-w-7xl grid-cols-[1fr_auto_1fr] items-center px-4 sm:px-6">
|
||||
{/* Left: logo */}
|
||||
<Link to="/studio" className="flex items-center justify-self-start select-none">
|
||||
<Link
|
||||
to="/studio"
|
||||
className="flex items-center justify-self-start gap-2 select-none"
|
||||
>
|
||||
<img
|
||||
src="/blacklogo.png"
|
||||
alt="Unsloth"
|
||||
|
|
@ -74,6 +77,9 @@ export function Navbar() {
|
|||
alt="Unsloth"
|
||||
className="hidden h-9 w-auto dark:block"
|
||||
/>
|
||||
<span className="text-[10px] font-extrabold tracking-[0.12em] text-primary">
|
||||
BETA
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
{/* Center: pill nav */}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,18 @@ import * as React from "react";
|
|||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const THUMB_SIZE_PX = 16;
|
||||
|
||||
function getThumbInBoundsOffset(width: number, percent: number) {
|
||||
const halfWidth = width / 2;
|
||||
const halfPercent = 50;
|
||||
|
||||
if (percent <= 0) return halfWidth;
|
||||
if (percent >= 100) return -halfWidth;
|
||||
|
||||
return halfWidth - (percent / halfPercent) * halfWidth;
|
||||
}
|
||||
|
||||
function Slider({
|
||||
className,
|
||||
defaultValue,
|
||||
|
|
@ -32,11 +44,6 @@ function Slider({
|
|||
},
|
||||
[isControlled, onValueChange],
|
||||
);
|
||||
|
||||
// For single-thumb horizontal sliders, render the fill bar as a sibling of
|
||||
// the track (outside its overflow-hidden container) so it can align flush
|
||||
// with the thumb center without being clipped. The Range inside the track
|
||||
// is hidden in this case to avoid double-painting.
|
||||
const isSingleThumbHorizontal =
|
||||
values.length === 1 && orientation === "horizontal";
|
||||
const fillPercent = isSingleThumbHorizontal
|
||||
|
|
@ -48,6 +55,12 @@ function Slider({
|
|||
),
|
||||
)
|
||||
: null;
|
||||
const fillWidth =
|
||||
fillPercent === null
|
||||
? undefined
|
||||
: fillPercent <= 0
|
||||
? "0%"
|
||||
: `calc(${fillPercent}% + ${getThumbInBoundsOffset(THUMB_SIZE_PX, fillPercent)}px)`;
|
||||
|
||||
return (
|
||||
<SliderPrimitive.Root
|
||||
|
|
@ -75,19 +88,22 @@ function Slider({
|
|||
isSingleThumbHorizontal && "opacity-0",
|
||||
)}
|
||||
/>
|
||||
{isSingleThumbHorizontal && (
|
||||
<div
|
||||
aria-hidden={true}
|
||||
className={cn(
|
||||
"absolute inset-y-0 left-0 bg-primary pointer-events-none",
|
||||
fillPercent === 100 ? "rounded-4xl" : "rounded-l-4xl",
|
||||
)}
|
||||
style={{ width: fillWidth }}
|
||||
/>
|
||||
)}
|
||||
</SliderPrimitive.Track>
|
||||
{isSingleThumbHorizontal && (
|
||||
<div
|
||||
aria-hidden={true}
|
||||
className="absolute inset-y-0 left-0 my-auto h-3 rounded-4xl bg-primary pointer-events-none"
|
||||
style={{ width: `${fillPercent}%` }}
|
||||
/>
|
||||
)}
|
||||
{Array.from({ length: values.length }, (_, index) => (
|
||||
<SliderPrimitive.Thumb
|
||||
data-slot="slider-thumb"
|
||||
key={index}
|
||||
className="border-primary ring-ring/50 size-4 rounded-4xl border bg-white shadow-sm block shrink-0 select-none cursor-pointer disabled:pointer-events-none disabled:opacity-50 transition-transform duration-100 ease-out hover:scale-110 hover:ring-4 active:scale-95 focus-visible:ring-4 focus-visible:outline-hidden"
|
||||
className="border-primary ring-ring/50 relative z-10 size-4 rounded-4xl border bg-white shadow-sm block shrink-0 select-none cursor-pointer disabled:pointer-events-none disabled:opacity-50 transition-transform duration-100 ease-out hover:scale-110 hover:ring-4 active:scale-95 focus-visible:ring-4 focus-visible:outline-hidden"
|
||||
/>
|
||||
))}
|
||||
</SliderPrimitive.Root>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue