Render all multi artifacts correctly (#976)

This commit is contained in:
Shuchang Zheng
2024-10-15 08:00:25 -07:00
committed by GitHub
parent fc89e3b4e6
commit 37559fc38f
3 changed files with 75 additions and 51 deletions

View File

@@ -2,7 +2,7 @@ import { artifactApiClient } from "@/api/AxiosClient";
import { ArtifactApiResponse } from "@/api/types"; import { ArtifactApiResponse } from "@/api/types";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { useQuery } from "@tanstack/react-query"; import { useQueries } from "@tanstack/react-query";
import axios from "axios"; import axios from "axios";
// https://stackoverflow.com/a/60338028 // https://stackoverflow.com/a/60338028
@@ -27,29 +27,36 @@ function format(html: string) {
} }
type Props = { type Props = {
artifact: ArtifactApiResponse; artifacts: Array<ArtifactApiResponse>;
}; };
function HTMLArtifact({ artifact }: Props) { function HTMLArtifact({ artifacts }: Props) {
const { data, isFetching, isError, error } = useQuery<string>({ function fetchArtifact(artifact: ArtifactApiResponse) {
queryKey: ["artifact", artifact.artifact_id], if (artifact.uri.startsWith("file://")) {
queryFn: async () => { return artifactApiClient
if (artifact.uri.startsWith("file://")) { .get(`/artifact/text`, {
return artifactApiClient params: {
.get(`/artifact/text`, { path: artifact.uri.slice(7),
params: { },
path: artifact.uri.slice(7), })
}, .then((response) => response.data);
}) }
.then((response) => response.data); if (artifact.uri.startsWith("s3://") && artifact.signed_url) {
} return axios.get(artifact.signed_url).then((response) => response.data);
if (artifact.uri.startsWith("s3://") && artifact.signed_url) { }
return axios.get(artifact.signed_url).then((response) => response.data); }
}
}, const results = useQueries({
queries:
artifacts?.map((artifact) => {
return {
queryKey: ["artifact", artifact.artifact_id],
queryFn: () => fetchArtifact(artifact),
};
}) ?? [],
}); });
if (isFetching) { if (results.some((result) => result.isLoading)) {
return <Skeleton className="h-48 w-full" />; return <Skeleton className="h-48 w-full" />;
} }
@@ -57,7 +64,11 @@ function HTMLArtifact({ artifact }: Props) {
<Textarea <Textarea
className="w-full" className="w-full"
rows={15} rows={15}
value={isError ? JSON.stringify(error) : format(data ?? "")} value={
results.some((result) => result.isError)
? JSON.stringify(results.find((result) => result.isError)?.error)
: results.map((result) => format(result.data ?? "")).join(",\n")
}
readOnly readOnly
/> />
); );

View File

@@ -61,12 +61,12 @@ function StepArtifacts({ id, stepProps }: Props) {
(artifact) => artifact.artifact_type === ArtifactType.LLMRequest, (artifact) => artifact.artifact_type === ArtifactType.LLMRequest,
); );
const visibleElementsTreeInPrompt = artifacts?.find( const visibleElementsTreeInPrompt = artifacts?.filter(
(artifact) => (artifact) =>
artifact.artifact_type === ArtifactType.VisibleElementsTreeInPrompt, artifact.artifact_type === ArtifactType.VisibleElementsTreeInPrompt,
); );
const llmPrompt = artifacts?.find( const llmPrompt = artifacts?.filter(
(artifact) => artifact.artifact_type === ArtifactType.LLMPrompt, (artifact) => artifact.artifact_type === ArtifactType.LLMPrompt,
); );
@@ -74,7 +74,7 @@ function StepArtifacts({ id, stepProps }: Props) {
(artifact) => artifact.artifact_type === ArtifactType.LLMResponseParsed, (artifact) => artifact.artifact_type === ArtifactType.LLMResponseParsed,
); );
const htmlRaw = artifacts?.find( const htmlRaw = artifacts?.filter(
(artifact) => artifact.artifact_type === ArtifactType.HTMLScrape, (artifact) => artifact.artifact_type === ArtifactType.HTMLScrape,
); );
@@ -84,8 +84,10 @@ function StepArtifacts({ id, stepProps }: Props) {
<TabsTrigger value="info">Info</TabsTrigger> <TabsTrigger value="info">Info</TabsTrigger>
<TabsTrigger value="screenshot_llm">Annotated Screenshots</TabsTrigger> <TabsTrigger value="screenshot_llm">Annotated Screenshots</TabsTrigger>
<TabsTrigger value="screenshot_action">Action Screenshots</TabsTrigger> <TabsTrigger value="screenshot_action">Action Screenshots</TabsTrigger>
<TabsTrigger value="element_tree_trimmed">Element Tree</TabsTrigger> <TabsTrigger value="element_tree_trimmed">
<TabsTrigger value="html_element_tree">HTML Element Tree</TabsTrigger> HTML Element Tree
</TabsTrigger>
<TabsTrigger value="element_tree">Element Tree</TabsTrigger>
<TabsTrigger value="llm_prompt">Prompt</TabsTrigger> <TabsTrigger value="llm_prompt">Prompt</TabsTrigger>
<TabsTrigger value="llm_response_parsed">Action List</TabsTrigger> <TabsTrigger value="llm_response_parsed">Action List</TabsTrigger>
<TabsTrigger value="html_raw">HTML (Raw)</TabsTrigger> <TabsTrigger value="html_raw">HTML (Raw)</TabsTrigger>
@@ -165,16 +167,16 @@ function StepArtifacts({ id, stepProps }: Props) {
</TabsContent> </TabsContent>
<TabsContent value="element_tree_trimmed"> <TabsContent value="element_tree_trimmed">
{visibleElementsTreeInPrompt ? ( {visibleElementsTreeInPrompt ? (
<HTMLArtifact artifact={visibleElementsTreeInPrompt} /> <HTMLArtifact artifacts={visibleElementsTreeInPrompt} />
) : null} ) : null}
</TabsContent> </TabsContent>
<TabsContent value="html_element_tree"> <TabsContent value="element_tree">
{visibleElementsTree ? ( {visibleElementsTree ? (
<JSONArtifact artifacts={visibleElementsTree} /> <JSONArtifact artifacts={visibleElementsTree} />
) : null} ) : null}
</TabsContent> </TabsContent>
<TabsContent value="llm_prompt"> <TabsContent value="llm_prompt">
{llmPrompt ? <TextArtifact artifact={llmPrompt} /> : null} {llmPrompt ? <TextArtifact artifacts={llmPrompt} /> : null}
</TabsContent> </TabsContent>
<TabsContent value="llm_response_parsed"> <TabsContent value="llm_response_parsed">
{llmResponseParsed ? ( {llmResponseParsed ? (
@@ -182,7 +184,7 @@ function StepArtifacts({ id, stepProps }: Props) {
) : null} ) : null}
</TabsContent> </TabsContent>
<TabsContent value="html_raw"> <TabsContent value="html_raw">
{htmlRaw ? <TextArtifact artifact={htmlRaw} /> : null} {htmlRaw ? <TextArtifact artifacts={htmlRaw} /> : null}
</TabsContent> </TabsContent>
<TabsContent value="llm_request"> <TabsContent value="llm_request">
{llmRequest ? <JSONArtifact artifacts={llmRequest} /> : null} {llmRequest ? <JSONArtifact artifacts={llmRequest} /> : null}

View File

@@ -2,33 +2,40 @@ import { artifactApiClient } from "@/api/AxiosClient";
import { ArtifactApiResponse } from "@/api/types"; import { ArtifactApiResponse } from "@/api/types";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { useQuery } from "@tanstack/react-query"; import { useQueries } from "@tanstack/react-query";
import axios from "axios"; import axios from "axios";
type Props = { type Props = {
artifact: ArtifactApiResponse; artifacts: Array<ArtifactApiResponse>;
}; };
function TextArtifact({ artifact }: Props) { function TextArtifact({ artifacts }: Props) {
const { data, isFetching, isError, error } = useQuery<string>({ function fetchArtifact(artifact: ArtifactApiResponse) {
queryKey: ["artifact", artifact.artifact_id], if (artifact.uri.startsWith("file://")) {
queryFn: async () => { return artifactApiClient
if (artifact.uri.startsWith("file://")) { .get(`/artifact/text`, {
return artifactApiClient params: {
.get(`/artifact/text`, { path: artifact.uri.slice(7),
params: { },
path: artifact.uri.slice(7), })
}, .then((response) => response.data);
}) }
.then((response) => response.data); if (artifact.uri.startsWith("s3://") && artifact.signed_url) {
} return axios.get(artifact.signed_url).then((response) => response.data);
if (artifact.uri.startsWith("s3://") && artifact.signed_url) { }
return axios.get(artifact.signed_url).then((response) => response.data); }
}
}, const results = useQueries({
queries:
artifacts?.map((artifact) => {
return {
queryKey: ["artifact", artifact.artifact_id],
queryFn: () => fetchArtifact(artifact),
};
}) ?? [],
}); });
if (isFetching) { if (results.some((result) => result.isLoading)) {
return <Skeleton className="h-48 w-full" />; return <Skeleton className="h-48 w-full" />;
} }
@@ -36,7 +43,11 @@ function TextArtifact({ artifact }: Props) {
<Textarea <Textarea
className="w-full" className="w-full"
rows={15} rows={15}
value={isError ? JSON.stringify(error) : data} value={
results.some((result) => result.isError)
? JSON.stringify(results.find((result) => result.isError)?.error)
: results.map((result) => result.data).join(",\n")
}
readOnly readOnly
/> />
); );