120 lines
4.8 KiB
JavaScript
120 lines
4.8 KiB
JavaScript
|
import { ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate, } from "@langchain/core/prompts";
|
||
|
import { LLMChain } from "../../chains/llm_chain.js";
|
||
|
import { Agent } from "../agent.js";
|
||
|
import { ChatAgentOutputParser } from "./outputParser.js";
|
||
|
import { FORMAT_INSTRUCTIONS, PREFIX, SUFFIX } from "./prompt.js";
|
||
|
const DEFAULT_HUMAN_MESSAGE_TEMPLATE = "{input}\n\n{agent_scratchpad}";
|
||
|
/**
|
||
|
* Agent for the MRKL chain.
|
||
|
* @augments Agent
|
||
|
*
|
||
|
* @deprecated Use the {@link https://api.js.langchain.com/functions/langchain.agents.createStructuredChatAgent.html | createStructuredChatAgent method instead}.
|
||
|
*/
|
||
|
export class ChatAgent extends Agent {
|
||
|
static lc_name() {
|
||
|
return "ChatAgent";
|
||
|
}
|
||
|
constructor(input) {
|
||
|
const outputParser = input?.outputParser ?? ChatAgent.getDefaultOutputParser();
|
||
|
super({ ...input, outputParser });
|
||
|
Object.defineProperty(this, "lc_namespace", {
|
||
|
enumerable: true,
|
||
|
configurable: true,
|
||
|
writable: true,
|
||
|
value: ["langchain", "agents", "chat"]
|
||
|
});
|
||
|
}
|
||
|
_agentType() {
|
||
|
return "chat-zero-shot-react-description";
|
||
|
}
|
||
|
observationPrefix() {
|
||
|
return "Observation: ";
|
||
|
}
|
||
|
llmPrefix() {
|
||
|
return "Thought:";
|
||
|
}
|
||
|
_stop() {
|
||
|
return ["Observation:"];
|
||
|
}
|
||
|
/**
|
||
|
* Validates that all tools have descriptions. Throws an error if a tool
|
||
|
* without a description is found.
|
||
|
* @param tools Array of Tool instances to validate.
|
||
|
* @returns void
|
||
|
*/
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Returns a default output parser for the ChatAgent.
|
||
|
* @param _fields Optional OutputParserArgs to customize the output parser.
|
||
|
* @returns ChatAgentOutputParser instance
|
||
|
*/
|
||
|
static getDefaultOutputParser(_fields) {
|
||
|
return new ChatAgentOutputParser();
|
||
|
}
|
||
|
/**
|
||
|
* Constructs the agent's scratchpad, which is a string representation of
|
||
|
* the agent's previous steps.
|
||
|
* @param steps Array of AgentStep instances representing the agent's previous steps.
|
||
|
* @returns Promise resolving to a string representing the agent's scratchpad.
|
||
|
*/
|
||
|
async constructScratchPad(steps) {
|
||
|
const agentScratchpad = await super.constructScratchPad(steps);
|
||
|
if (agentScratchpad) {
|
||
|
return `This was your previous work (but I haven't seen any of it! I only see what you return as final answer):\n${agentScratchpad}`;
|
||
|
}
|
||
|
return agentScratchpad;
|
||
|
}
|
||
|
/**
|
||
|
* 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.humanMessageTemplate - String to use directly as the human message template
|
||
|
* @param args.formatInstructions - Formattable string to use as the instructions template
|
||
|
*/
|
||
|
static createPrompt(tools, args) {
|
||
|
const { prefix = PREFIX, suffix = SUFFIX, humanMessageTemplate = DEFAULT_HUMAN_MESSAGE_TEMPLATE, formatInstructions = FORMAT_INSTRUCTIONS, } = args ?? {};
|
||
|
const toolStrings = tools
|
||
|
.map((tool) => `${tool.name}: ${tool.description}`)
|
||
|
.join("\n");
|
||
|
const template = [prefix, toolStrings, formatInstructions, suffix].join("\n\n");
|
||
|
const messages = [
|
||
|
SystemMessagePromptTemplate.fromTemplate(template),
|
||
|
HumanMessagePromptTemplate.fromTemplate(humanMessageTemplate),
|
||
|
];
|
||
|
return ChatPromptTemplate.fromMessages(messages);
|
||
|
}
|
||
|
/**
|
||
|
* Creates a ChatAgent instance using a language model, tools, and
|
||
|
* optional arguments.
|
||
|
* @param llm BaseLanguageModelInterface instance to use in the agent.
|
||
|
* @param tools Array of Tool instances to include in the agent.
|
||
|
* @param args Optional arguments to customize the agent and prompt.
|
||
|
* @returns ChatAgent instance
|
||
|
*/
|
||
|
static fromLLMAndTools(llm, tools, args) {
|
||
|
ChatAgent.validateTools(tools);
|
||
|
const prompt = ChatAgent.createPrompt(tools, args);
|
||
|
const chain = new LLMChain({
|
||
|
prompt,
|
||
|
llm,
|
||
|
callbacks: args?.callbacks ?? args?.callbackManager,
|
||
|
});
|
||
|
const outputParser = args?.outputParser ?? ChatAgent.getDefaultOutputParser();
|
||
|
return new ChatAgent({
|
||
|
llmChain: chain,
|
||
|
outputParser,
|
||
|
allowedTools: tools.map((t) => t.name),
|
||
|
});
|
||
|
}
|
||
|
}
|