import { PromptTemplate, renderTemplate } from "@langchain/core/prompts"; import { LLMChain } from "../../chains/llm_chain.js"; import { Agent } from "../agent.js"; import { deserializeHelper } from "../helpers.js"; import { ZeroShotAgentOutputParser } from "./outputParser.js"; import { FORMAT_INSTRUCTIONS, PREFIX, SUFFIX } from "./prompt.js"; /** * Agent for the MRKL chain. * @augments Agent * @example * ```typescript * * const agent = new ZeroShotAgent({ * llmChain: new LLMChain({ * llm: new ChatOpenAI({ temperature: 0 }), * prompt: ZeroShotAgent.createPrompt([new SerpAPI(), new Calculator()], { * prefix: `Answer the following questions as best you can, but speaking as a pirate might speak. You have access to the following tools:`, * suffix: `Begin! Remember to speak as a pirate when giving your final answer. Use lots of "Args" * Question: {input} * {agent_scratchpad}`, * inputVariables: ["input", "agent_scratchpad"], * }), * }), * allowedTools: ["search", "calculator"], * }); * * const result = await agent.invoke({ * input: `Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?`, * }); * ``` * * @deprecated Use the {@link https://api.js.langchain.com/functions/langchain.agents.createReactAgent.html | createReactAgent method instead}. */ export class ZeroShotAgent extends Agent { static lc_name() { return "ZeroShotAgent"; } constructor(input) { const outputParser = input?.outputParser ?? ZeroShotAgent.getDefaultOutputParser(); super({ ...input, outputParser }); Object.defineProperty(this, "lc_namespace", { enumerable: true, configurable: true, writable: true, value: ["langchain", "agents", "mrkl"] }); } _agentType() { return "zero-shot-react-description"; } observationPrefix() { return "Observation: "; } llmPrefix() { return "Thought:"; } /** * Returns the default output parser for the ZeroShotAgent. * @param fields Optional arguments for the output parser. * @returns An instance of ZeroShotAgentOutputParser. */ static getDefaultOutputParser(fields) { return new ZeroShotAgentOutputParser(fields); } /** * Validates the tools for the ZeroShotAgent. Throws an error if any tool * does not have a description. * @param tools List of tools to validate. */ static validateTools(tools) { const descriptionlessTool = tools.find((tool) => !tool.description); if (descriptionlessTool) { const msg = `Got a tool ${descriptionlessTool.name} without a description.` + ` This agent requires descriptions for all tools.`; throw new Error(msg); } } /** * Create prompt in the style of the zero shot agent. * * @param tools - List of tools the agent will have access to, used to format the prompt. * @param args - Arguments to create the prompt with. * @param args.suffix - String to put after the list of tools. * @param args.prefix - String to put before the list of tools. * @param args.inputVariables - List of input variables the final prompt will expect. */ static createPrompt(tools, args) { const { prefix = PREFIX, suffix = SUFFIX, inputVariables = ["input", "agent_scratchpad"], } = args ?? {}; const toolStrings = tools .map((tool) => `${tool.name}: ${tool.description}`) .join("\n"); const toolNames = tools.map((tool) => tool.name); const formatInstructions = renderTemplate(FORMAT_INSTRUCTIONS, "f-string", { tool_names: toolNames, }); const template = [prefix, toolStrings, formatInstructions, suffix].join("\n\n"); return new PromptTemplate({ template, inputVariables, }); } /** * Creates a ZeroShotAgent from a Large Language Model and a set of tools. * @param llm The Large Language Model to use. * @param tools The tools for the agent to use. * @param args Optional arguments for creating the agent. * @returns A new instance of ZeroShotAgent. */ static fromLLMAndTools(llm, tools, args) { ZeroShotAgent.validateTools(tools); const prompt = ZeroShotAgent.createPrompt(tools, args); const outputParser = args?.outputParser ?? ZeroShotAgent.getDefaultOutputParser(); const chain = new LLMChain({ prompt, llm, callbacks: args?.callbacks ?? args?.callbackManager, }); return new ZeroShotAgent({ llmChain: chain, allowedTools: tools.map((t) => t.name), outputParser, }); } static async deserialize(data) { const { llm, tools, ...rest } = data; return deserializeHelper(llm, tools, rest, (llm, tools, args) => ZeroShotAgent.fromLLMAndTools(llm, tools, { prefix: args.prefix, suffix: args.suffix, inputVariables: args.input_variables, }), (args) => new ZeroShotAgent(args)); } }