Skip to content

Commit

Permalink
Merge pull request #451 from kreneskyp/agent_reference
Browse files Browse the repository at this point in the history
Nested agents.
  • Loading branch information
kreneskyp authored Feb 16, 2024
2 parents 46fcffc + c8026fc commit 835b966
Show file tree
Hide file tree
Showing 13 changed files with 171 additions and 50 deletions.
7 changes: 7 additions & 0 deletions frontend/chains/AgentSelect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from "react";

import { ChainSelect } from "chains/ChainSelect";

export const AgentSelect = ({ onChange, value }) => {
return <ChainSelect onChange={onChange} value={value} is_agent={true} />;
};
38 changes: 5 additions & 33 deletions frontend/chains/ChainDraggable.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,15 @@
import React from "react";
import { Box } from "@chakra-ui/react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChain } from "@fortawesome/free-solid-svg-icons";
import { DraggableNode } from "chains/editor/DraggableNode";
import { useEditorColorMode } from "chains/editor/useColorMode";
import { DraggableButton } from "chains/DraggableButton";

export const ChainDraggable = ({ chain }) => {
const { isLight } = useEditorColorMode();
const style = isLight
? {
bg: "gray.100",
_hover: { bg: "gray.300" },
}
: {
bg: "whiteAlpha.200",
_hover: { bg: "whiteAlpha.300" },
};

return (
<DraggableNode
<DraggableButton
name={chain.name}
description={chain.description}
config={{ chain_id: chain.id }}
class_path="ix.runnable.flow.load_chain_id"
>
<Box
p={2}
h={8}
borderRadius={5}
borderLeft={"6px solid"}
borderColor={"blue.300"}
fontSize={"sm"}
display={"flex"}
alignItems={"center"}
{...style}
>
<FontAwesomeIcon icon={faChain} style={{ marginRight: "5px" }} />{" "}
Reference
</Box>
</DraggableNode>
label="Reference"
highlight={"blue.400"}
/>
);
};
16 changes: 11 additions & 5 deletions frontend/chains/ChainSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,22 @@ const fetchOptions = async (url, inputValue) => {
}
};

const getOptions = async (inputValue) => {
return fetchOptions(`/api/chains/?is_agent=false&limit=20`, inputValue);
};

const getDetail = async (id) => {
const response = await axios.get(`/api/chains/${id}`);
return toOption(response.data);
};

export const ChainSelect = ({ onChange, value, ...props }) => {
export const ChainSelect = ({ onChange, value, is_agent }) => {
const getOptions = React.useCallback(
async (inputValue) => {
return fetchOptions(
`/api/chains/?is_agent=${is_agent === true}&limit=20`,
inputValue
);
},
[is_agent]
);

return (
<AsyncAPIObjectSelect
getOptions={getOptions}
Expand Down
50 changes: 50 additions & 0 deletions frontend/chains/DraggableButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from "react";
import { Box } from "@chakra-ui/react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChain } from "@fortawesome/free-solid-svg-icons";
import { DraggableNode } from "chains/editor/DraggableNode";
import { useEditorColorMode } from "chains/editor/useColorMode";

export const DraggableButton = ({
name,
description,
config,
class_path,
highlight = "blue.300",
label = "Reference",
}) => {
const { isLight } = useEditorColorMode();
const style = isLight
? {
bg: "gray.100",
_hover: { bg: "gray.300" },
}
: {
bg: "whiteAlpha.200",
_hover: { bg: "whiteAlpha.300" },
};

return (
<DraggableNode
name={name}
description={description}
config={config}
class_path={class_path}
>
<Box
p={2}
h={8}
borderRadius={5}
borderLeft={"6px solid"}
borderColor={highlight}
fontSize={"sm"}
display={"flex"}
alignItems={"center"}
{...style}
>
<FontAwesomeIcon icon={faChain} style={{ marginRight: "5px" }} />{" "}
{label}
</Box>
</DraggableNode>
);
};
4 changes: 3 additions & 1 deletion frontend/chains/editor/run_log/ExecutionList.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ const ExecutionBrief = ({ nodes, types, execution, onClick }) => {
>
{type?.type || "unknown"}
</Badge>
<Text>{type?.name || node.class_path.split(".").pop()}</Text>
<Text>
{type?.name || node?.class_path.split(".").pop() || "unknown"}
</Text>
</Box>
</HStack>
);
Expand Down
15 changes: 13 additions & 2 deletions frontend/chains/editor/sidebar/EditorAgentCard.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
import React from "react";

import { HStack } from "@chakra-ui/react";
import { AgentCard } from "agents/AgentCard";
import { ModalClose } from "components/Modal";
import { AgentEditButton } from "agents/AgentEditButton";
import { DraggableButton } from "chains/DraggableButton";

export const EditorAgentCard = ({ agent, ...props }) => {
const close = React.useContext(ModalClose);

return (
<AgentCard agent={agent} {...props}>
<AgentEditButton agent={agent} onClick={close} />
<HStack spacing={2} pt={4} display="flex" justifyContent="flex-end">
<DraggableButton
name={agent.name}
description={agent.description}
config={{ chain_id: agent.chain_id }}
class_path="ix.runnable.flow.load_agent_id"
label="Reference"
highlight={"green.400"}
/>
<AgentEditButton agent={agent} onClick={close} />
</HStack>
</AgentCard>
);
};
4 changes: 3 additions & 1 deletion frontend/chains/flow/NodeMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { Overlay } from "components/Overlay";
import { WithPortal } from "components/WithPortal";

const CHAIN_REFERENCE = "ix.runnable.flow.load_chain_id";
const AGENT_REFERENCE = "ix.runnable.flow.load_agent_id";

const DeleteItem = ({ node }) => {
const api = React.useContext(ChainEditorAPIContext);
Expand Down Expand Up @@ -49,7 +50,8 @@ const DeleteItem = ({ node }) => {

export const NodeMenu = ({ node }) => {
const editor = React.useContext(EditorViewState);
const isReference = node.class_path === CHAIN_REFERENCE;
const isReference =
node.class_path === CHAIN_REFERENCE || node.class_path === AGENT_REFERENCE;
const style = useEditorColorMode();
const { isOpen, onOpen, onClose } = useDisclosure();

Expand Down
8 changes: 3 additions & 5 deletions frontend/components/AsyncAPIObjectSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@ export const AsyncAPIObjectSelect = ({
// load value on initial render
React.useEffect(() => {
const callback = async () => {
if (selected === null && value) {
const selectedValue = await getDetail(value);
setSelected(selectedValue);
}
const selectedValue = await getDetail(value);
setSelected(selectedValue);
};
callback();
}, [value]);
}, [onChange, value]);

const promiseOptions = (inputValue) =>
new Promise((resolve) => {
Expand Down
2 changes: 2 additions & 0 deletions frontend/json_form/JSONSchemaForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { SchemaServerSelect } from "schemas/openapi/SchemaServerSelect";
import { JSONSchemaSelect } from "schemas/json/JSONSchemaSelect";
import { OpenAPISchemaSelect } from "schemas/openapi/OpenAPISchemaSelect";
import { SkillSelect } from "skills/SkillSelect";
import { AgentSelect } from "chains/AgentSelect";

// explicit input types
const INPUTS = {
Expand All @@ -35,6 +36,7 @@ const INPUTS = {
dict: Dict,
list: List,
"IX:chain": APISelect.for_select(ChainSelect),
"IX:agent": APISelect.for_select(AgentSelect),
"IX:json_schema": APISelect.for_select(JSONSchemaSelect),
"IX:openapi_schema": APISelect.for_select(OpenAPISchemaSelect),
"IX:openapi_action": APISelect.for_select(SchemaActionSelect),
Expand Down
24 changes: 22 additions & 2 deletions ix/chains/fixture_src/flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
CHAIN_REF = {
"class_path": CHAIN_REF_CLASS_PATH,
"name": "Chain Reference",
"description": "Embed a chain in another chain. The chain is called as if it were a component in the local flow.",
"description": "Embed a chain in another flow. The chain is called as if it were a component in the local flow.",
"type": "chain",
"context": "context",
"fields": [
Expand All @@ -54,4 +54,24 @@
],
}

FLOW = [ROOT_NODE, CHAIN_REF]

AGENT_REF_CLASS_PATH = "ix.runnable.flow.load_agent_id"
AGENT_REF = {
"class_path": AGENT_REF_CLASS_PATH,
"name": "Agent Reference",
"description": "Embed an agent in another flow. The agent is called as if it were a component in the local flow.",
"type": "agent",
"context": "context",
"fields": [
{
"name": "chain_id",
"label": "Agent",
"type": "string",
"input_type": "IX:agent",
"required": True,
"description": "The agent to embed.",
}
],
}

FLOW = [ROOT_NODE, AGENT_REF, CHAIN_REF]
7 changes: 7 additions & 0 deletions ix/runnable/flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ def load_chain_id(
return chain_obj.load_chain(context=context)


def load_agent_id(
chain_id: UUID, context: IxContext, **kwargs
) -> Runnable[Input, Output]:
"""Load an agent Runnable from a chain_id. Proxy to load_chain_id."""
return load_chain_id(chain_id, context, **kwargs)


class RunnableEachSequential(RunnableSerializable[List[Input], List[Output]]):
"""Runs a flow for each item in a list sequentially."""

Expand Down
44 changes: 44 additions & 0 deletions test_data/snapshots/components/ix.runnable.flow.load_agent_id.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"child_field": null,
"class_path": "ix.runnable.flow.load_agent_id",
"config_schema": {
"display_groups": null,
"properties": {
"chain_id": {
"description": "The agent to embed.",
"input_type": "IX:agent",
"label": "Agent",
"type": "string"
}
},
"required": [
"chain_id"
],
"title": "load_agent_id",
"type": "object"
},
"connectors": null,
"description": "Embed an agent in another flow. The agent is called as if it were a component in the local flow.",
"display_type": "node",
"fields": [
{
"choices": null,
"default": null,
"description": "The agent to embed.",
"init_type": "init",
"input_type": "IX:agent",
"label": "Agent",
"max": null,
"min": null,
"name": "chain_id",
"parent": null,
"required": true,
"secret_key": null,
"step": null,
"style": null,
"type": "string"
}
],
"name": "Agent Reference",
"type": "agent"
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"type": "object"
},
"connectors": null,
"description": "Embed a chain in another chain. The chain is called as if it were a component in the local flow.",
"description": "Embed a chain in another flow. The chain is called as if it were a component in the local flow.",
"display_type": "node",
"fields": [
{
Expand Down

0 comments on commit 835b966

Please sign in to comment.