diff --git a/AI-agents/_studio_dependencies/GlobalVariable/router.js b/AI-agents/_studio_dependencies/GlobalVariable/router.js index 61375a5..7023eb3 100644 --- a/AI-agents/_studio_dependencies/GlobalVariable/router.js +++ b/AI-agents/_studio_dependencies/GlobalVariable/router.js @@ -1,27 +1,125 @@ -const { recognizedObject: r = {} } = this; +const { conversationData: c = {}, recognizedObject: r = {} } = this; class Router { constructor() { - r.router = { - agents: [], - }; + r.router = { logs: [] }; + if (c.router) { + r.router.logs.push("Router Already Initialized"); + } else { + r.router.logs.push("Initializing Router"); + c.router = { + agents: [], + nextAction: "Next", + }; + } } - setAgents(agents) { - r.router.agents = agents; + setNextAction(action) { + c.router.nextAction = action; + } + + getNextAction() { + return c.router.nextAction; } hasNext() { - return r.router.agents.some((agent) => agent.state === "submitted"); + return c.router.agents.some((agent) => agent.state === "submitted"); } next() { - return r.router.agents.find((agent) => agent.state === "submitted"); + return c.router.agents.find((agent) => agent.state === "submitted"); + } + + getActiveAgent() { + return c.router.agents.find((agent) => agent.state === "active"); + } + + log(message) { + if (typeof message === "string" || message instanceof String) { + r.router.logs.push("" + message); + } else { + r.router.logs.push(JSON.stringify(message)); + } + } + + async assignAgents() { + const intents = [ + { + name: "Invoice_Agent", + description: "Answers Questions about Invoices and Orders", + priority: 1, + }, + { + name: "Device_Agent", + description: "Answers Questions about Devices, Models and Setup", + priority: 1, + }, + ]; + const { data } = await request.post("/test", { + modelId: "us.anthropic.claude-3-7-sonnet-20250219-v1:0", + body: { + max_tokens: 1024, + anthropic_version: "bedrock-2023-05-31", + system: [ + { + type: "text", + text: `You are a helpful assistant, designed to classify user utterances and return all matched intents based on their descriptions.\nClassify the following user utterance and return **all matched intents** from the list below.\nIf the input does not match any intents, respond with "UNABLE TO CLASSIFY".\nThis is the list of available intents and their descriptions to match against:\n\n${intents + .map((intent) => `- ${intent.name}: ${intent.description}`) + .join( + "\n" + )}\n\nReturn the matched intents and the part of the input that matched each intent on their own line. For example:\n\nIntent A: partial utterance\nIntent B: partial utterance`, + }, + ], + messages: [ + { + role: "user", + content: [ + { + type: "text", + text: recognizedObject.input, + }, + ], + }, + ], + temperature: 1.0, + }, + credentials: { + accessKeyId: "AKIAXSFOCMMUBXR67SUK", + secretAccessKey: "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", + }, + }); + r.router.logs.push({ agentClassification: data }); + recognizedObject.classifier = data; + const tool = data?.content?.[0]?.text; + if (tool.includes("UNABLE TO CLASSIFY")) { + r.router.logs.push("No intent matched"); + } else { + const list = tool.split("\n").map((line) => line.trim()); + const results = list.map((line) => { + const [intent, utterance] = line.split(":").map((part) => part.trim()); + return { intent, utterance }; + }); + results.sort((a, b) => { + const priorityA = + intents.find((intent) => intent.name === a.intent)?.priority || 0; + const priorityB = + intents.find((intent) => intent.name === b.intent)?.priority || 0; + return priorityA - priorityB; + }); + c.router.agents = results.map((agent) => ({ + id: agent.intent, + input: agent.utterance, + state: "submitted", + })); + } } setState(id, state) { - const agent = r.router.agents.find((agent) => agent.id === id); - if (agent) agent.state = state; + const agent = c.router.agents.find((agent) => agent.id === id); + if (agent) { + agent.state = state; + r.router.logs.push(`router.setState: agent=${JSON.stringify(agent)}`); + } } } diff --git a/AI-agents/snippets/routerLogic.js b/AI-agents/snippets/routerLogic.js new file mode 100644 index 0000000..45508a9 --- /dev/null +++ b/AI-agents/snippets/routerLogic.js @@ -0,0 +1,68 @@ +(async () => { + router.setNextAction("Next"); + + // Did the Model Respond? + if (recognizedObject.answers.length) { + // Yes + router.log("Model Responded"); + router.log({ answers: recognizedObject.answers }); + const activeAgent = router.getActiveAgent(); + if (activeAgent) { + router.log("Model Responded -> Agent Active"); + router.log(activeAgent); + router.setNextAction("ReturnAnswers"); + } else { + router.log("Model Responded -> No Agent Active"); + if (router.hasNext()) { + router.log("Model Responded -> No Agent Active -> Router Has next"); + // Run Next Agent + router.setNextAction("RunNextAgent"); + } else { + router.log("Model Responded -> No Agent Active -> Router Empty"); + // Return Answers + // Run Next Agent + router.setNextAction("ReturnAnswers"); + } + } + } else { + router.log("Model Did Not Respond"); + // No + const activeAgent = router.getActiveAgent(); + if (activeAgent) { + router.log("Model Did Not Respond -> Agent Active"); + router.log("Deactivate Agent because it didn't respond"); + // Deactivate Agent because it didn't respond + activeAgent.state = "Deactivated Agent because it didn't respond"; + } + if (router.hasNext()) { + router.log("Model Did Not Respond -> Router Has next"); + // Assign Agents + // Run Next Agent + router.setNextAction("RunNextAgent"); + } else { + router.log("Model Did Not Respond -> Router Empty"); + router.log("Assign Agents"); + await router.assignAgents(); + + if (router.hasNext()) { + router.log( + "Model Did Not Respond -> Router was Empty -> Router has next" + ); + router.setNextAction("RunNextAgent"); + } else { + router.log( + "Model Did Not Respond -> Router was Empty -> Router still Empty" + ); + // Return Answers + router.setNextAction("Next"); + } + } + } +})() + .catch((e) => { + router.log(e); + }) + .finally(() => { + router.log("Router Next Action: " + router.getNextAction()); + next(); + });