feat: logs on component output (#2740)

* Added tabs and passed the type of the table to the SwitchOutputView component

* Added type to SwitchOutputViewProps and changed results based on type

* Removed unused import

* Changed type of VertexDataTypeAPI to include logs

* Added condition where type is Logs to display only table

* Added handling when resultMessage is empty to SwitchOutputView

* Removed return that made Logs not appear when its empty

* Fixed logs not appearing

* feat: Add _output_logs attribute to CustomComponent

The code changes include adding a new attribute `_output_logs` to the `CustomComponent` class. This attribute is a dictionary that stores logs related to output values. This change is necessary to enhance the logging functionality of the component.

Note: Please remove any meta information such as issue references, tags, or author names from the commit message.

* feat: Serialize messages with to_json() in BaseCrewComponent

This commit modifies the `BaseCrewComponent` class in the `crew.py` file. It adds serialization of messages using the `to_json()` method to avoid circular reference issues. The `_messages_dict` dictionary is serialized by converting each message object to JSON format. This change enhances the functionality of the component and improves the logging process.

Note: Please remove any meta information such as issue references, tags, or author names from the commit message.

---------

Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
This commit is contained in:
Lucas Oliveira 2024-07-16 19:36:10 -03:00 • committed by GitHub
commit 0897ee542a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 58 additions and 13 deletions

View file

@ -1,3 +1,4 @@
import { LogsLogType, OutputLogType } from "@/types/api";
import DataOutputComponent from "../../../../../../components/dataOutputComponent";
import ForwardedIconComponent from "../../../../../../components/genericIconComponent";
import {
@ -13,26 +14,28 @@ import ErrorOutput from "./components";
interface SwitchOutputViewProps {
nodeId: string;
outputName: string;
type: "Outputs" | "Logs";
}
const SwitchOutputView: React.FC<SwitchOutputViewProps> = ({
nodeId,
outputName,
type,
}) => {
const flowPool = useFlowStore((state) => state.flowPool);
const flowPoolNode = (flowPool[nodeId] ?? [])[
(flowPool[nodeId]?.length ?? 1) - 1
];
let results = flowPoolNode?.data?.outputs[outputName] ?? "";
if (Array.isArray(results)) {
return;
}
let results: OutputLogType | LogsLogType =
(type === "Outputs"
? flowPoolNode?.data?.outputs[outputName]
: flowPoolNode?.data?.logs[outputName]) ?? {};
const resultType = results?.type;
let resultMessage = results?.message;
let resultMessage = results?.message ?? {};
const RECORD_TYPES = ["data", "object", "array", "message"];
if (resultMessage?.raw) {
resultMessage = resultMessage.raw;
}
return (
return type === "Outputs" ? (
<>
<Case condition={!resultType || resultType === "unknown"}>
<div>NO OUTPUT</div>
@ -54,7 +57,9 @@ const SwitchOutputView: React.FC<SwitchOutputViewProps> = ({
? (resultMessage as Array<any>).every((item) => item.data)
? (resultMessage as Array<any>).map((item) => item.data)
: resultMessage
: [resultMessage]
: Object.keys(resultMessage).length > 0
? [resultMessage]
: []
}
pagination={true}
columnMode="union"
@ -78,6 +83,20 @@ const SwitchOutputView: React.FC<SwitchOutputViewProps> = ({
</div>
</Case>
</>
) : (
<DataOutputComponent
rows={
Array.isArray(results)
? (results as Array<any>).every((item) => item.data)
? (results as Array<any>).map((item) => item.data)
: results
: Object.keys(results).length > 0
? [results]
: []
}
pagination={true}
columnMode="union"
/>
);
};

View file

@ -1,3 +1,5 @@
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useState } from "react";
import { Button } from "../../../../components/ui/button";
import BaseModal from "../../../../modals/baseModal";
import SwitchOutputView from "./components/switchOutputView";
@ -8,15 +10,32 @@ export default function OutputModal({
nodeId,
outputName,
}): JSX.Element {
const [activeTab, setActiveTab] = useState<"Outputs" | "Logs">("Outputs");
return (
<BaseModal open={open} setOpen={setOpen} size="medium-tall">
<BaseModal open={open} setOpen={setOpen} size="large">
<BaseModal.Header description="Inspect the output of the component below.">
<div className="flex items-center">
<span className="pr-2">Component Output</span>
</div>
</BaseModal.Header>
<BaseModal.Content>
<SwitchOutputView nodeId={nodeId} outputName={outputName} />
<Tabs
value={activeTab}
onValueChange={(value) => setActiveTab(value as "Outputs" | "Logs")}
className={
"absolute top-6 flex flex-col self-center overflow-hidden rounded-md border bg-muted text-center"
}
>
<TabsList>
<TabsTrigger value="Outputs">Outputs</TabsTrigger>
<TabsTrigger value="Logs">Logs</TabsTrigger>
</TabsList>
</Tabs>
<SwitchOutputView
nodeId={nodeId}
outputName={outputName}
type={activeTab}
/>
</BaseModal.Content>
<BaseModal.Footer>
<div className="flex w-full justify-end pt-2">

View file

@ -201,12 +201,18 @@ export type OutputLogType = {
message: any | ErrorLogType;
type: string;
};
export type LogsLogType = {
name: string;
message: any | ErrorLogType;
type: string;
};
// data is the object received by the API
// it has results, artifacts, timedelta, duration
export type VertexDataTypeAPI = {
results: { [key: string]: string };
outputs: { [key: string]: OutputLogType };
logs: { [key: string]: LogsLogType };
messages: ChatOutputType[] | ChatInputType[];
inactive?: boolean;
timedelta?: number;