Skip to content

Commit

Permalink
OPIK-43 [New feature] Add support for displaying images if they are i…
Browse files Browse the repository at this point in the history
…n the input attribute (#163)
  • Loading branch information
andriidudar authored Sep 3, 2024
1 parent 7f5b98a commit 167ee62
Showing 1 changed file with 70 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import React from "react";
import React, { useMemo } from "react";
import get from "lodash/get";
import isString from "lodash/isString";
import { Span, Trace } from "@/types/traces";
import {
Accordion,
Expand All @@ -8,19 +10,81 @@ import {
} from "@/components/ui/accordion";
import SyntaxHighlighter from "@/components/shared/SyntaxHighlighter/SyntaxHighlighter";

export type ImageContent = {
type: "image_url";
image_url: {
url: string;
};
};

const isImageContent = (content?: Partial<ImageContent>) => {
try {
return content?.type === "image_url" && isString(content?.image_url?.url);
} catch (error) {
return false;
}
};

function extractImageUrls(messages: unknown) {
if (!Array.isArray(messages)) return [];

const images: string[] = [];

messages.forEach((message) => {
const imageContent: ImageContent[] = Array.isArray(message?.content)
? message.content.filter(isImageContent)
: [];

images.push(...imageContent.map((content) => content.image_url.url));
});

return images;
}

type InputOutputTabProps = {
data: Trace | Span;
};

const InputOutputTab: React.FunctionComponent<InputOutputTabProps> = ({
data,
}) => {
const imagesUrls = useMemo(
() => extractImageUrls(get(data, ["input", "messages"], [])),
[data],
);

const hasImages = imagesUrls.length > 0;

const openTabs = useMemo(() => {
return hasImages ? ["images", "input", "output"] : ["input", "output"];
}, [hasImages]);

return (
<Accordion
type="multiple"
className="w-full"
defaultValue={["input", "output"]}
>
<Accordion type="multiple" className="w-full" defaultValue={openTabs}>
{hasImages && (
<AccordionItem value="images">
<AccordionTrigger>Images</AccordionTrigger>
<AccordionContent>
<div className="flex flex-wrap gap-2">
{imagesUrls.map((imageUrl, index) => {
return (
<div
key={index + imageUrl.substring(0, 10)}
className="h-[200px] max-w-[300px] rounded-md border p-4"
>
<img
src={imageUrl}
loading="lazy"
alt={`image-${index}`}
className="size-full object-contain"
/>
</div>
);
})}
</div>
</AccordionContent>
</AccordionItem>
)}
<AccordionItem value="input">
<AccordionTrigger>Input</AccordionTrigger>
<AccordionContent>
Expand Down

0 comments on commit 167ee62

Please sign in to comment.