Skip to content

Commit

Permalink
clean design
Browse files Browse the repository at this point in the history
  • Loading branch information
vincelwt committed Dec 3, 2024
1 parent 6b7ac70 commit 36fed1b
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 36 deletions.
96 changes: 64 additions & 32 deletions packages/frontend/components/SmartViewer/AudioPlayer.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { ActionIcon, Group, Paper, Slider, Text } from "@mantine/core";
import { ActionIcon, Box, Group, Paper, Slider, Text } from "@mantine/core";
import { IconPlayerPause, IconPlayerPlay } from "@tabler/icons-react";
import { useEffect, useRef, useState } from "react";
import classes from "./index.module.css";

interface AudioPlayerProps {
src: string;
src?: string;
compact?: boolean;
transcript?: string;
}

export function AudioPlayer({ src, compact = false }: AudioPlayerProps) {
export function AudioPlayer({
src,
compact = false,
transcript,
}: AudioPlayerProps) {
const [isPlaying, setIsPlaying] = useState(false);
const [currentTime, setCurrentTime] = useState(0);
const [duration, setDuration] = useState(0);
Expand Down Expand Up @@ -56,37 +60,65 @@ export function AudioPlayer({ src, compact = false }: AudioPlayerProps) {
return `${minutes}:${seconds.toString().padStart(2, "0")}`;
};

if (!src) {
return (
<Text size="sm" c="dimmed" fs="italic">
&lt;audio message&gt;
{transcript && (
<>
<br />
<Text size="xs" mt={4}>
{transcript}
</Text>
</>
)}
</Text>
);
}

return (
<Paper className={classes.audioPlayer} p="xs">
<audio ref={audioRef} src={src} />
<Group gap="xs">
<ActionIcon
variant="subtle"
onClick={togglePlay}
size={compact ? "sm" : "md"}
>
{isPlaying ? (
<IconPlayerPause size={16} />
) : (
<IconPlayerPlay size={16} />
)}
</ActionIcon>
<>
<Paper
className={classes.audioPlayer}
maw={compact ? 220 : undefined}
p={compact ? 0 : 6}
>
<audio ref={audioRef} src={src} />
<Group gap={3}>
<ActionIcon
variant="subtle"
onClick={togglePlay}
size={compact ? "sm" : "md"}
>
{isPlaying ? (
<IconPlayerPause size={16} />
) : (
<IconPlayerPlay size={16} />
)}
</ActionIcon>

<Slider
value={currentTime}
onChange={handleSliderChange}
max={duration}
min={0}
size="xs"
style={{ flex: 1 }}
/>
<Slider
value={currentTime}
onChange={handleSliderChange}
max={duration}
min={0}
size="xs"
style={{ flex: 1 }}
/>

{!compact && (
<Text size="xs" c="dimmed" w={45}>
{formatTime(currentTime)}
<Text size="xs" c="dimmed" px={compact ? 6 : 8}>
{currentTime === 0 && !isPlaying
? formatTime(duration)
: formatTime(currentTime)}
</Text>
)}
</Group>
</Paper>
</Group>
</Paper>

{transcript && (
<Text size="xs" mt={compact ? 6 : "sm"} c="gray">
{transcript}
</Text>
)}
</>
);
}
44 changes: 40 additions & 4 deletions packages/frontend/components/SmartViewer/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,11 @@ type ChatMessageBlock =
}
| {
type: "image_url";
image_url: { url: string };
imageUrl: { url: string };
}
| {
type: "input_audio";
input_audio: { data: string; format: "wav" | "mp3" };
inputAudio: { data: string; format: "wav" | "mp3" };
};

function BlockMessage({
Expand All @@ -292,7 +292,7 @@ function BlockMessage({
}) {
return (
<Code className={classes.textMessage}>
<Stack gap={compact ? "5" : "md"}>
<Stack gap={compact ? 4 : "sm"}>
{data.content.map((item, index) => {
if (item.type === "text") {
return <ProtectedText key={index}>{item.text}</ProtectedText>;
Expand All @@ -306,7 +306,7 @@ function BlockMessage({
return (
<AudioPlayer
key={index}
src={`data:audio/${item.input_audio.format};base64,${item.input_audio.data}`}
src={`data:audio/${item.inputAudio.format};base64,${item.inputAudio.data}`}
compact={compact}
/>
);
Expand Down Expand Up @@ -353,6 +353,28 @@ function ChatMessageContent({
const hasBlockContent = Array.isArray(data?.content);
const hasFunctionCall = data?.functionCall;
const hasToolCalls = data?.toolCalls || data?.tool_calls;
const hasAudio = data?.audio;
const hasRefusal = data?.refusal && data?.content === null;

if (hasRefusal) {
return (
<Paper
p="xs"
bg="red.1"
c="red.8"
withBorder
styles={{
root: {
borderColor: "var(--mantine-color-red-3)",
},
}}
>
<Text size="sm" fs="italic">
{data.refusal}
</Text>
</Paper>
);
}

let renderTextMessage = hasTextContent && (!compact || !hasToolCalls);
if (hasTextContent && textContent.length === 0 && !editable) {
Expand Down Expand Up @@ -393,6 +415,20 @@ function ChatMessageContent({
/>
)}

{hasAudio && (
<Code className={classes.textMessage}>
<AudioPlayer
src={
data.audio.data
? `data:audio/${data.audio.format || "wav"};base64,${data.audio.data}`
: undefined
}
compact={compact}
transcript={data.audio.transcript}
/>
</Code>
)}

{hasBlockContent && <BlockMessage data={data} compact={compact} />}

{hasFunctionCall && (
Expand Down
2 changes: 2 additions & 0 deletions packages/frontend/components/SmartViewer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const checkIsMessage = (obj) => {
return (
typeof obj?.text === "string" ||
typeof obj?.content === "string" ||
typeof obj?.refusal === "string" ||
typeof obj?.audio === "object" ||
Array.isArray(obj?.content) ||
typeof obj?.functionCall === "object" ||
typeof obj?.function_call === "object" ||
Expand Down
34 changes: 34 additions & 0 deletions packages/frontend/components/blocks/RunInputOutput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ import {
IconDotsVertical,
IconEye,
IconEyeClosed,
IconFileMusic,
IconInfoCircle,
IconMicrophone,
IconPencilShare,
IconSpeakerphone,
IconTrash,
} from "@tabler/icons-react";
import Link from "next/link";
Expand Down Expand Up @@ -118,9 +121,40 @@ function RenderTools({ tools }) {
const PARAMS = [
{ key: "temperature", name: "Temperature" },
{ key: "maxTokens", name: "Max tokens" },
{ key: "maxCompletionTokens", name: "Max completion tokens" },
{ key: "topP", name: "Top P" },
{ key: "topK", name: "Top K" },
{
key: "audio",
name: "Audio",
render: (value) => (
<Group gap={4}>
{value.voice && (
<Badge
leftSection={<IconSpeakerphone size={14} />}
pl={7}
variant="light"
color="grape"
>
Voice: {value.voice}
</Badge>
)}
{value.format && (
<Badge
leftSection={<IconFileMusic size={14} />}
variant="light"
pl={7}
color="violet"
>
{value.format}
</Badge>
)}
</Group>
),
},
{ key: "modalities", name: "Modalities" },
{ key: "logitBias", name: "Logit bias" },

{ key: "presencePenalty", name: "Presence penalty" },
{ key: "frequencyPenalty", name: "Frequency penalty" },
{ key: "stop", name: "Stop" },
Expand Down

0 comments on commit 36fed1b

Please sign in to comment.