From 56b3677976a2b7b5c62cc1a3e6df3bcbd5108229 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Fri, 17 Mar 2023 13:28:13 -0700 Subject: [PATCH 01/17] Use OpenAIChat class to initialize gpt-4 models --- langchain/src/llms/openai.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langchain/src/llms/openai.ts b/langchain/src/llms/openai.ts index 6b4e4ee6f372..0b7ec5579f54 100644 --- a/langchain/src/llms/openai.ts +++ b/langchain/src/llms/openai.ts @@ -141,7 +141,7 @@ export class OpenAI extends BaseLLM implements OpenAIInput { }, configuration?: ConfigurationParameters ) { - if (fields?.modelName?.startsWith("gpt-3.5-turbo")) { + if (fields?.modelName?.startsWith("gpt-3.5-turbo") || fields?.modelName?.startsWith("gpt-4")) { // eslint-disable-next-line no-constructor-return, @typescript-eslint/no-explicit-any return new OpenAIChat(fields, configuration) as any as OpenAI; } From c5fc36f80b92218b2f4929cd835a3447ab8fc575 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Fri, 17 Mar 2023 14:13:45 -0700 Subject: [PATCH 02/17] Formatting --- langchain/src/llms/openai.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/langchain/src/llms/openai.ts b/langchain/src/llms/openai.ts index 0b7ec5579f54..f862d3016a7e 100644 --- a/langchain/src/llms/openai.ts +++ b/langchain/src/llms/openai.ts @@ -141,7 +141,10 @@ export class OpenAI extends BaseLLM implements OpenAIInput { }, configuration?: ConfigurationParameters ) { - if (fields?.modelName?.startsWith("gpt-3.5-turbo") || fields?.modelName?.startsWith("gpt-4")) { + if ( + fields?.modelName?.startsWith("gpt-3.5-turbo") || + fields?.modelName?.startsWith("gpt-4") + ) { // eslint-disable-next-line no-constructor-return, @typescript-eslint/no-explicit-any return new OpenAIChat(fields, configuration) as any as OpenAI; } From 78df0ca37d02daa3d86a0627c4a629834bd3149a Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Sat, 18 Mar 2023 00:02:00 -0700 Subject: [PATCH 03/17] Adds support for passing a prompt to a ChatConversationalAgent --- langchain/src/agents/chat_convo/index.ts | 17 ++++--- langchain/src/agents/chat_convo/prompt.ts | 8 ++-- langchain/src/agents/executor.ts | 2 + langchain/src/agents/index.ts | 2 +- langchain/src/agents/initialize.ts | 56 ++++++++++++++++++++++- 5 files changed, 73 insertions(+), 12 deletions(-) diff --git a/langchain/src/agents/chat_convo/index.ts b/langchain/src/agents/chat_convo/index.ts index 5fe0ee67e9b4..ff90ab8254a1 100644 --- a/langchain/src/agents/chat_convo/index.ts +++ b/langchain/src/agents/chat_convo/index.ts @@ -8,8 +8,9 @@ import { } from "../../prompts/index.js"; import { interpolateFString } from "../../prompts/template.js"; import { - PREFIX, - SUFFIX, + DEFAULT_PREFIX, + DEFAULT_SUFFIX, + PREFIX_END, FORMAT_INSTRUCTIONS, TEMPLATE_TOOL_RESPONSE, } from "./prompt.js"; @@ -60,6 +61,10 @@ export type CreatePromptArgs = { inputVariables?: string[]; /** Output parser to use for formatting. */ outputParser?: BaseOutputParser; + /** Custom prompt prefix */ + prefix?: string; + /** Custom prompt suffix */ + suffix?: string; }; type ZeroShotAgentInput = AgentInput; @@ -127,11 +132,9 @@ export class ChatConversationalAgent extends Agent { * @param args.prefix - String to put before the list of tools. */ static createPrompt(tools: Tool[], args?: CreatePromptArgs) { - const { - systemMessage = PREFIX, - humanMessage = SUFFIX, - outputParser = new AgentOutputParser(), - } = args ?? {}; + const systemMessage = (args?.prefix ?? args?.systemMessage ?? DEFAULT_PREFIX) + PREFIX_END; + const humanMessage = args?.suffix ?? args?.humanMessage ?? DEFAULT_SUFFIX; + const outputParser = args?.outputParser ?? new AgentOutputParser(); const toolStrings = tools .map((tool) => `${tool.name}: ${tool.description}`) .join("\n"); diff --git a/langchain/src/agents/chat_convo/prompt.ts b/langchain/src/agents/chat_convo/prompt.ts index 89fdfd35971c..6568af9ba67e 100644 --- a/langchain/src/agents/chat_convo/prompt.ts +++ b/langchain/src/agents/chat_convo/prompt.ts @@ -1,4 +1,4 @@ -export const PREFIX = `Assistant is a large language model trained by OpenAI. +export const DEFAULT_PREFIX = `Assistant is a large language model trained by OpenAI. Assistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand. @@ -6,6 +6,8 @@ Assistant is constantly learning and improving, and its capabilities are constan Overall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.`; +export const PREFIX_END = ` However, all responses must adhere to the style of RESPONSE FORMAT INSTRUCTIONS.`; + export const FORMAT_INSTRUCTIONS = `RESPONSE FORMAT INSTRUCTIONS ---------------------------- @@ -32,7 +34,7 @@ Use this if you want to respond directly to the human. Markdown code snippet for }}}} \`\`\``; -export const SUFFIX = `TOOLS +export const DEFAULT_SUFFIX = `TOOLS ------ Assistant can ask the user to use tools to look up information that may be helpful in answering the users original question. The tools the human can use are: @@ -46,7 +48,7 @@ Here is the user's input (remember to respond with a markdown code snippet of a {{{{input}}}}`; -export const TEMPLATE_TOOL_RESPONSE = `TOOL RESPONSE: +export const TEMPLATE_TOOL_RESPONSE = `TOOL RESPONSE: --------------------- {observation} diff --git a/langchain/src/agents/executor.ts b/langchain/src/agents/executor.ts index f803767ea252..aea59ae6ff4a 100644 --- a/langchain/src/agents/executor.ts +++ b/langchain/src/agents/executor.ts @@ -5,6 +5,7 @@ import { StoppingMethod } from "./types.js"; import { SerializedLLMChain } from "../chains/serde.js"; import { AgentFinish, AgentStep, ChainValues } from "../schema/index.js"; import { CallbackManager } from "../callbacks/index.js"; +import { BaseMemory } from "../memory/base.js"; type AgentExecutorInput = { agent: Agent; @@ -12,6 +13,7 @@ type AgentExecutorInput = { returnIntermediateSteps?: boolean; maxIterations?: number; earlyStoppingMethod?: StoppingMethod; + memory?: BaseMemory; verbose?: boolean; callbackManager?: CallbackManager; diff --git a/langchain/src/agents/index.ts b/langchain/src/agents/index.ts index e3464c5a2bb1..fcd87855b596 100644 --- a/langchain/src/agents/index.ts +++ b/langchain/src/agents/index.ts @@ -11,7 +11,7 @@ export { ZeroShotAgent } from "./mrkl/index.js"; export { ChatAgent } from "./chat/index.js"; export { ChatConversationalAgent } from "./chat_convo/index.js"; export { Tool } from "./tools/index.js"; -export { initializeAgentExecutor } from "./initialize.js"; +export { initializeAgentExecutor, initializeAgentExecutorWithOptions } from "./initialize.js"; export { loadAgent } from "./load.js"; diff --git a/langchain/src/agents/initialize.ts b/langchain/src/agents/initialize.ts index 5c92c5c5cfa6..1714f0b94d73 100644 --- a/langchain/src/agents/initialize.ts +++ b/langchain/src/agents/initialize.ts @@ -5,6 +5,7 @@ import { ChatConversationalAgent } from "./chat_convo/index.js"; import { ChatAgent } from "./chat/index.js"; import { BaseLanguageModel } from "../base_language/index.js"; import { CallbackManager, getCallbackManager } from "../callbacks/index.js"; +import { BufferMemory } from "../memory/buffer_memory.js"; export const initializeAgentExecutor = async ( tools: Tool[], @@ -35,9 +36,62 @@ export const initializeAgentExecutor = async ( agent: ChatConversationalAgent.fromLLMAndTools(llm, tools), tools, verbose, - callbackManager, + callbackManager }); default: throw new Error("Unknown agent type"); } }; + +export const initializeAgentExecutorWithOptions = async ( + tools: Tool[], + llm: BaseLanguageModel, + options: { + agentType?: string, + prompt?: string, + verbose?: boolean, + callbackManager?: CallbackManager + } +): Promise => { + const agentType = options.agentType ?? "zero-shot-react-description"; + const verbose = options.verbose ?? false; + const callbackManager = options.callbackManager ?? getCallbackManager(); + switch (agentType) { + case "zero-shot-react-description": { + return AgentExecutor.fromAgentAndTools({ + agent: ZeroShotAgent.fromLLMAndTools(llm, tools), + tools, + returnIntermediateSteps: true, + verbose, + callbackManager, + }); + } + case "chat-zero-shot-react-description": { + return AgentExecutor.fromAgentAndTools({ + agent: ChatAgent.fromLLMAndTools(llm, tools), + tools, + returnIntermediateSteps: true, + verbose, + callbackManager, + }); + } + case "chat-conversational-react-description": { + const executor = AgentExecutor.fromAgentAndTools({ + agent: ChatConversationalAgent.fromLLMAndTools(llm, tools, { + prefix: options.prompt + }), + tools, + verbose, + callbackManager + }); + executor.memory = new BufferMemory({ + returnMessages: true, + memoryKey: "chat_history", + }); + return executor; + } + default: { + throw new Error("Unknown agent type"); + } + } +}; From a82b75c10d6872bf28f6d3230090cf197a6b2f69 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Sat, 18 Mar 2023 00:17:06 -0700 Subject: [PATCH 04/17] Formatting --- langchain/src/agents/chat_convo/index.ts | 3 ++- langchain/src/agents/index.ts | 5 ++++- langchain/src/agents/initialize.ts | 14 +++++++------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/langchain/src/agents/chat_convo/index.ts b/langchain/src/agents/chat_convo/index.ts index ff90ab8254a1..83207d1236f2 100644 --- a/langchain/src/agents/chat_convo/index.ts +++ b/langchain/src/agents/chat_convo/index.ts @@ -132,7 +132,8 @@ export class ChatConversationalAgent extends Agent { * @param args.prefix - String to put before the list of tools. */ static createPrompt(tools: Tool[], args?: CreatePromptArgs) { - const systemMessage = (args?.prefix ?? args?.systemMessage ?? DEFAULT_PREFIX) + PREFIX_END; + const systemMessage = + (args?.prefix ?? args?.systemMessage ?? DEFAULT_PREFIX) + PREFIX_END; const humanMessage = args?.suffix ?? args?.humanMessage ?? DEFAULT_SUFFIX; const outputParser = args?.outputParser ?? new AgentOutputParser(); const toolStrings = tools diff --git a/langchain/src/agents/index.ts b/langchain/src/agents/index.ts index fcd87855b596..de462d3eac77 100644 --- a/langchain/src/agents/index.ts +++ b/langchain/src/agents/index.ts @@ -11,7 +11,10 @@ export { ZeroShotAgent } from "./mrkl/index.js"; export { ChatAgent } from "./chat/index.js"; export { ChatConversationalAgent } from "./chat_convo/index.js"; export { Tool } from "./tools/index.js"; -export { initializeAgentExecutor, initializeAgentExecutorWithOptions } from "./initialize.js"; +export { + initializeAgentExecutor, + initializeAgentExecutorWithOptions, +} from "./initialize.js"; export { loadAgent } from "./load.js"; diff --git a/langchain/src/agents/initialize.ts b/langchain/src/agents/initialize.ts index 1714f0b94d73..625773cb83f5 100644 --- a/langchain/src/agents/initialize.ts +++ b/langchain/src/agents/initialize.ts @@ -36,7 +36,7 @@ export const initializeAgentExecutor = async ( agent: ChatConversationalAgent.fromLLMAndTools(llm, tools), tools, verbose, - callbackManager + callbackManager, }); default: throw new Error("Unknown agent type"); @@ -47,10 +47,10 @@ export const initializeAgentExecutorWithOptions = async ( tools: Tool[], llm: BaseLanguageModel, options: { - agentType?: string, - prompt?: string, - verbose?: boolean, - callbackManager?: CallbackManager + agentType?: string; + prompt?: string; + verbose?: boolean; + callbackManager?: CallbackManager; } ): Promise => { const agentType = options.agentType ?? "zero-shot-react-description"; @@ -78,11 +78,11 @@ export const initializeAgentExecutorWithOptions = async ( case "chat-conversational-react-description": { const executor = AgentExecutor.fromAgentAndTools({ agent: ChatConversationalAgent.fromLLMAndTools(llm, tools, { - prefix: options.prompt + prefix: options.prompt, }), tools, verbose, - callbackManager + callbackManager, }); executor.memory = new BufferMemory({ returnMessages: true, From bde73504216848c185fab224d1c5e84f761e72df Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Sun, 19 Mar 2023 15:01:13 -0700 Subject: [PATCH 05/17] Properly set memory when passed into AgentExecutor constructor, rename arguments to createPrompt method in ChatConversationalAgent --- langchain/src/agents/chat_convo/index.ts | 15 +++++---------- langchain/src/agents/executor.ts | 4 +--- langchain/src/agents/initialize.ts | 24 ++++++++++++++++-------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/langchain/src/agents/chat_convo/index.ts b/langchain/src/agents/chat_convo/index.ts index 83207d1236f2..314bffa5eba1 100644 --- a/langchain/src/agents/chat_convo/index.ts +++ b/langchain/src/agents/chat_convo/index.ts @@ -61,10 +61,6 @@ export type CreatePromptArgs = { inputVariables?: string[]; /** Output parser to use for formatting. */ outputParser?: BaseOutputParser; - /** Custom prompt prefix */ - prefix?: string; - /** Custom prompt suffix */ - suffix?: string; }; type ZeroShotAgentInput = AgentInput; @@ -124,17 +120,16 @@ export class ChatConversationalAgent extends Agent { } /** - * Create prompt in the style of the zero shot agent. + * Create prompt in the style of the ChatConversationAgent. * * @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.systemMessage - String to put after the list of tools. + * @param args.humanMessage - String to put before the list of tools. */ static createPrompt(tools: Tool[], args?: CreatePromptArgs) { - const systemMessage = - (args?.prefix ?? args?.systemMessage ?? DEFAULT_PREFIX) + PREFIX_END; - const humanMessage = args?.suffix ?? args?.humanMessage ?? DEFAULT_SUFFIX; + const systemMessage = (args?.systemMessage ?? DEFAULT_PREFIX) + PREFIX_END; + const humanMessage = args?.humanMessage ?? DEFAULT_SUFFIX; const outputParser = args?.outputParser ?? new AgentOutputParser(); const toolStrings = tools .map((tool) => `${tool.name}: ${tool.description}`) diff --git a/langchain/src/agents/executor.ts b/langchain/src/agents/executor.ts index aea59ae6ff4a..9c08724f031c 100644 --- a/langchain/src/agents/executor.ts +++ b/langchain/src/agents/executor.ts @@ -39,7 +39,7 @@ export class AgentExecutor extends BaseChain { } constructor(input: AgentExecutorInput) { - super(); + super(input.memory, input.verbose, input.callbackManager); this.agent = input.agent; this.tools = input.tools; this.returnIntermediateSteps = @@ -47,8 +47,6 @@ export class AgentExecutor extends BaseChain { this.maxIterations = input.maxIterations ?? this.maxIterations; this.earlyStoppingMethod = input.earlyStoppingMethod ?? this.earlyStoppingMethod; - this.verbose = input.verbose ?? this.verbose; - this.callbackManager = input.callbackManager ?? this.callbackManager; } /** Create from agent and a list of tools. */ diff --git a/langchain/src/agents/initialize.ts b/langchain/src/agents/initialize.ts index 625773cb83f5..3b31bebd22ac 100644 --- a/langchain/src/agents/initialize.ts +++ b/langchain/src/agents/initialize.ts @@ -5,7 +5,7 @@ import { ChatConversationalAgent } from "./chat_convo/index.js"; import { ChatAgent } from "./chat/index.js"; import { BaseLanguageModel } from "../base_language/index.js"; import { CallbackManager, getCallbackManager } from "../callbacks/index.js"; -import { BufferMemory } from "../memory/buffer_memory.js"; +import { BaseMemory, BufferMemory } from "../memory/index.js"; export const initializeAgentExecutor = async ( tools: Tool[], @@ -49,6 +49,7 @@ export const initializeAgentExecutorWithOptions = async ( options: { agentType?: string; prompt?: string; + memory?: BaseMemory; verbose?: boolean; callbackManager?: CallbackManager; } @@ -56,37 +57,44 @@ export const initializeAgentExecutorWithOptions = async ( const agentType = options.agentType ?? "zero-shot-react-description"; const verbose = options.verbose ?? false; const callbackManager = options.callbackManager ?? getCallbackManager(); + switch (agentType) { case "zero-shot-react-description": { return AgentExecutor.fromAgentAndTools({ - agent: ZeroShotAgent.fromLLMAndTools(llm, tools), + agent: ZeroShotAgent.fromLLMAndTools(llm, tools, { + prefix: options.prompt + }), tools, returnIntermediateSteps: true, verbose, callbackManager, + memory: options.memory, }); } case "chat-zero-shot-react-description": { return AgentExecutor.fromAgentAndTools({ - agent: ChatAgent.fromLLMAndTools(llm, tools), + agent: ChatAgent.fromLLMAndTools(llm, tools, { + prefix: options.prompt + }), tools, returnIntermediateSteps: true, verbose, callbackManager, + memory: options.memory, }); } case "chat-conversational-react-description": { const executor = AgentExecutor.fromAgentAndTools({ agent: ChatConversationalAgent.fromLLMAndTools(llm, tools, { - prefix: options.prompt, + systemMessage: options.prompt, }), tools, verbose, callbackManager, - }); - executor.memory = new BufferMemory({ - returnMessages: true, - memoryKey: "chat_history", + memory: options.memory ?? new BufferMemory({ + returnMessages: true, + memoryKey: "chat_history", + }), }); return executor; } From d198eb8561494a781c3c96fa683ea0844de42950 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Sun, 19 Mar 2023 15:01:35 -0700 Subject: [PATCH 06/17] Formatting --- langchain/src/agents/initialize.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/langchain/src/agents/initialize.ts b/langchain/src/agents/initialize.ts index 3b31bebd22ac..dda928a1e6ef 100644 --- a/langchain/src/agents/initialize.ts +++ b/langchain/src/agents/initialize.ts @@ -62,7 +62,7 @@ export const initializeAgentExecutorWithOptions = async ( case "zero-shot-react-description": { return AgentExecutor.fromAgentAndTools({ agent: ZeroShotAgent.fromLLMAndTools(llm, tools, { - prefix: options.prompt + prefix: options.prompt, }), tools, returnIntermediateSteps: true, @@ -74,7 +74,7 @@ export const initializeAgentExecutorWithOptions = async ( case "chat-zero-shot-react-description": { return AgentExecutor.fromAgentAndTools({ agent: ChatAgent.fromLLMAndTools(llm, tools, { - prefix: options.prompt + prefix: options.prompt, }), tools, returnIntermediateSteps: true, @@ -91,10 +91,12 @@ export const initializeAgentExecutorWithOptions = async ( tools, verbose, callbackManager, - memory: options.memory ?? new BufferMemory({ - returnMessages: true, - memoryKey: "chat_history", - }), + memory: + options.memory ?? + new BufferMemory({ + returnMessages: true, + memoryKey: "chat_history", + }), }); return executor; } From 403c22e1256f6b8dd2d5290e625340f42f7d3ed7 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Sun, 19 Mar 2023 15:19:13 -0700 Subject: [PATCH 07/17] Update docs and tests to use new intializeAgentExecutorWithOptions method --- docs/docs/getting-started.md | 10 +++--- .../agents/agents_with_vectorstores.md | 10 +++--- docs/docs/modules/agents/custom_tool.md | 10 +++--- docs/docs/modules/agents/overview.md | 10 +++--- docs/docs/modules/agents/zapier_agent.md | 13 ++++--- docs/docs/tracing.md | 36 ++++++++----------- .../src/agents/chat_convo_with_tracing.ts | 12 +++---- examples/src/agents/chat_mrkl.ts | 10 +++--- examples/src/agents/chat_mrkl_with_tracing.ts | 12 +++---- examples/src/agents/concurrent_mrkl.ts | 24 ++++++------- examples/src/agents/custom_tool.ts | 10 +++--- examples/src/agents/mrkl.ts | 12 +++---- examples/src/agents/mrkl_with_tracing.ts | 12 +++---- examples/src/agents/zapier_mrkl.ts | 13 ++++--- langchain/src/agents/tests/agent.int.test.ts | 10 +++--- .../tests/langchain_tracer.int.test.ts | 12 +++---- 16 files changed, 96 insertions(+), 120 deletions(-) diff --git a/docs/docs/getting-started.md b/docs/docs/getting-started.md index 7dcff8ebe3f7..69a938619ef0 100644 --- a/docs/docs/getting-started.md +++ b/docs/docs/getting-started.md @@ -165,17 +165,15 @@ Now we can get started! ```typescript import { OpenAI } from "langchain"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { SerpAPI, Calculator } from "langchain/tools"; const model = new OpenAI({ temperature: 0 }); const tools = [new SerpAPI(), new Calculator()]; -const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description" -); +const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", +}); console.log("Loaded agent."); const input = diff --git a/docs/docs/modules/agents/agents_with_vectorstores.md b/docs/docs/modules/agents/agents_with_vectorstores.md index 40e6a4ef24fd..ec448df46b45 100644 --- a/docs/docs/modules/agents/agents_with_vectorstores.md +++ b/docs/docs/modules/agents/agents_with_vectorstores.md @@ -8,7 +8,7 @@ First, you want to import the relevant modules ```typescript import { OpenAI } from "langchain"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { SerpAPI, Calculator, ChainTool } from "langchain/tools"; import { VectorDBQAChain } from "langchain/chains"; import { HNSWLib } from "langchain/vectorstores"; @@ -48,11 +48,9 @@ Now we can go about constructing and using the tool as we would any other tool! ```typescript const tools = [new SerpAPI(), new Calculator(), qaTool]; -const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description" -); +const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", +}); console.log("Loaded agent."); const input = `What did biden say about ketanji brown jackson is the state of the union address?`; diff --git a/docs/docs/modules/agents/custom_tool.md b/docs/docs/modules/agents/custom_tool.md index 29d49eb0736b..f8984ba050db 100644 --- a/docs/docs/modules/agents/custom_tool.md +++ b/docs/docs/modules/agents/custom_tool.md @@ -8,7 +8,7 @@ See below for an example of defining and using `DynamicTool`s. ```typescript import { OpenAI } from "langchain"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { DynamicTool } from "langchain/tools"; export const run = async () => { @@ -28,11 +28,9 @@ export const run = async () => { }), ]; - const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description" - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", + }); console.log("Loaded agent."); diff --git a/docs/docs/modules/agents/overview.md b/docs/docs/modules/agents/overview.md index 60c8b8695eb9..d27d6c572ffa 100644 --- a/docs/docs/modules/agents/overview.md +++ b/docs/docs/modules/agents/overview.md @@ -30,17 +30,15 @@ Now we can get started! ```typescript import { OpenAI } from "langchain"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { SerpAPI, Calculator } from "langchain/tools"; const model = new OpenAI({ temperature: 0 }); const tools = [new SerpAPI(), new Calculator()]; -const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description" -); +const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", +}); console.log("Loaded agent."); const input = diff --git a/docs/docs/modules/agents/zapier_agent.md b/docs/docs/modules/agents/zapier_agent.md index b0140b02183e..6ad69758a3ba 100644 --- a/docs/docs/modules/agents/zapier_agent.md +++ b/docs/docs/modules/agents/zapier_agent.md @@ -20,7 +20,10 @@ This example goes over how to use the Zapier integration an Agent. In code, belo ```typescript import { OpenAI } from "langchain"; -import { initializeAgentExecutor, ZapierToolKit } from "langchain/agents"; +import { + initializeAgentExecutorWithOptions, + ZapierToolKit, +} from "langchain/agents"; import { ZapierNLAWrapper } from "langchain/tools"; export const run = async () => { @@ -28,11 +31,13 @@ export const run = async () => { const zapier = new ZapierNLAWrapper(); const toolkit = await ZapierToolKit.fromZapierNLAWrapper(zapier); - const executor = await initializeAgentExecutor( + const executor = await initializeAgentExecutorWithOptions( toolkit.tools, model, - "zero-shot-react-description", - true + { + agentType: "zero-shot-react-description", + verbose: true, + } ); console.log("Loaded agent."); diff --git a/docs/docs/tracing.md b/docs/docs/tracing.md index 8ab0c659cf16..1adb37e65707 100644 --- a/docs/docs/tracing.md +++ b/docs/docs/tracing.md @@ -10,7 +10,7 @@ Here's an example of how to use tracing in `langchain.js`. All that needs to be ```typescript import { OpenAI } from "langchain"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { SerpAPI, Calculator } from "langchain/tools"; import process from "process"; @@ -19,12 +19,10 @@ export const run = async () => { const model = new OpenAI({ temperature: 0 }); const tools = [new SerpAPI(), new Calculator()]; - const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description", - true - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", + verbose: true, + }); console.log("Loaded agent."); const input = `Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?`; @@ -41,7 +39,7 @@ We are actively working on improving tracing to work better with concurrency. Fo ```typescript import { OpenAI } from "langchain"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { SerpAPI, Calculator } from "langchain/tools"; import process from "process"; import { @@ -55,12 +53,10 @@ export const run = async () => { const model = new OpenAI({ temperature: 0 }); const tools = [new SerpAPI(), new Calculator()]; - const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description", - true - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", + verbose: true, + }); console.log("Loaded agent."); const input = `Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?`; @@ -92,13 +88,11 @@ export const run = async () => { for (const tool of tools) { tool.callbackManager = callbackManager; } - const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description", - true, - callbackManager - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", + verbose: true, + callbackManager, + }); executor.agent.llmChain.callbackManager = callbackManager; executors.push(executor); } diff --git a/examples/src/agents/chat_convo_with_tracing.ts b/examples/src/agents/chat_convo_with_tracing.ts index 3994be15f911..eee839692940 100644 --- a/examples/src/agents/chat_convo_with_tracing.ts +++ b/examples/src/agents/chat_convo_with_tracing.ts @@ -1,5 +1,5 @@ import { ChatOpenAI } from "langchain/chat_models"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { SerpAPI, Calculator } from "langchain/tools"; import { BufferMemory } from "langchain/memory"; @@ -8,12 +8,10 @@ export const run = async () => { const model = new ChatOpenAI({ temperature: 0 }); const tools = [new SerpAPI(), new Calculator()]; - const executor = await initializeAgentExecutor( - tools, - model, - "chat-conversational-react-description", - true - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "chat-conversational-react-description", + verbose: true, + }); executor.memory = new BufferMemory({ returnMessages: true, memoryKey: "chat_history", diff --git a/examples/src/agents/chat_mrkl.ts b/examples/src/agents/chat_mrkl.ts index 84835483ad88..053e8e2b2474 100644 --- a/examples/src/agents/chat_mrkl.ts +++ b/examples/src/agents/chat_mrkl.ts @@ -1,16 +1,14 @@ import { ChatOpenAI } from "langchain/chat_models"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { SerpAPI, Calculator } from "langchain/tools"; export const run = async () => { const model = new ChatOpenAI({ temperature: 0 }); const tools = [new SerpAPI(), new Calculator()]; - const executor = await initializeAgentExecutor( - tools, - model, - "chat-zero-shot-react-description" - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "chat-zero-shot-react-description", + }); console.log("Loaded agent."); const input = `Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?`; diff --git a/examples/src/agents/chat_mrkl_with_tracing.ts b/examples/src/agents/chat_mrkl_with_tracing.ts index b8e13035cc55..30d6c5c42ecb 100644 --- a/examples/src/agents/chat_mrkl_with_tracing.ts +++ b/examples/src/agents/chat_mrkl_with_tracing.ts @@ -1,5 +1,5 @@ import { ChatOpenAI } from "langchain/chat_models"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { SerpAPI, Calculator } from "langchain/tools"; export const run = async () => { @@ -7,12 +7,10 @@ export const run = async () => { const model = new ChatOpenAI({ temperature: 0 }); const tools = [new SerpAPI(), new Calculator()]; - const executor = await initializeAgentExecutor( - tools, - model, - "chat-zero-shot-react-description", - true - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "chat-zero-shot-react-description", + verbose: true, + }); console.log("Loaded agent."); const input = `Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?`; diff --git a/examples/src/agents/concurrent_mrkl.ts b/examples/src/agents/concurrent_mrkl.ts index 08cde0101d97..c3985d2bed1c 100644 --- a/examples/src/agents/concurrent_mrkl.ts +++ b/examples/src/agents/concurrent_mrkl.ts @@ -1,5 +1,5 @@ import { OpenAI } from "langchain"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { SerpAPI, Calculator } from "langchain/tools"; import process from "process"; import { @@ -13,12 +13,10 @@ export const run = async () => { const model = new OpenAI({ temperature: 0 }); const tools = [new SerpAPI(), new Calculator()]; - const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description", - true - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", + verbose: true, + }); console.log("Loaded agent."); const input = `Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?`; @@ -50,13 +48,11 @@ export const run = async () => { for (const tool of tools) { tool.callbackManager = callbackManager; } - const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description", - true, - callbackManager - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", + verbose: true, + callbackManager, + }); executor.agent.llmChain.callbackManager = callbackManager; executors.push(executor); } diff --git a/examples/src/agents/custom_tool.ts b/examples/src/agents/custom_tool.ts index a75117d8c327..6dffd8682d31 100644 --- a/examples/src/agents/custom_tool.ts +++ b/examples/src/agents/custom_tool.ts @@ -1,5 +1,5 @@ import { OpenAI } from "langchain"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { DynamicTool } from "langchain/tools"; export const run = async () => { @@ -25,11 +25,9 @@ export const run = async () => { }), ]; - const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description" - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", + }); console.log("Loaded agent."); diff --git a/examples/src/agents/mrkl.ts b/examples/src/agents/mrkl.ts index e720748bc02b..065e747db948 100644 --- a/examples/src/agents/mrkl.ts +++ b/examples/src/agents/mrkl.ts @@ -1,17 +1,15 @@ import { OpenAI } from "langchain"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { SerpAPI, Calculator } from "langchain/tools"; export const run = async () => { const model = new OpenAI({ temperature: 0 }); const tools = [new SerpAPI(), new Calculator()]; - const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description", - true - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", + verbose: true, + }); console.log("Loaded agent."); const input = `Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?`; diff --git a/examples/src/agents/mrkl_with_tracing.ts b/examples/src/agents/mrkl_with_tracing.ts index e472a27042cd..bf8db75677fb 100644 --- a/examples/src/agents/mrkl_with_tracing.ts +++ b/examples/src/agents/mrkl_with_tracing.ts @@ -1,5 +1,5 @@ import { OpenAI } from "langchain"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { SerpAPI, Calculator } from "langchain/tools"; import process from "process"; @@ -8,12 +8,10 @@ export const run = async () => { const model = new OpenAI({ temperature: 0 }); const tools = [new SerpAPI(), new Calculator()]; - const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description", - true - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", + verbose: true, + }); console.log("Loaded agent."); const input = `Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?`; diff --git a/examples/src/agents/zapier_mrkl.ts b/examples/src/agents/zapier_mrkl.ts index fd4ec211faff..4ab38530a2b6 100644 --- a/examples/src/agents/zapier_mrkl.ts +++ b/examples/src/agents/zapier_mrkl.ts @@ -1,5 +1,8 @@ import { OpenAI } from "langchain"; -import { initializeAgentExecutor, ZapierToolKit } from "langchain/agents"; +import { + initializeAgentExecutorWithOptions, + ZapierToolKit, +} from "langchain/agents"; import { ZapierNLAWrapper } from "langchain/tools"; export const run = async () => { @@ -7,11 +10,13 @@ export const run = async () => { const zapier = new ZapierNLAWrapper(); const toolkit = await ZapierToolKit.fromZapierNLAWrapper(zapier); - const executor = await initializeAgentExecutor( + const executor = await initializeAgentExecutorWithOptions( toolkit.tools, model, - "zero-shot-react-description", - true + { + agentType: "zero-shot-react-description", + verbose: true, + } ); console.log("Loaded agent."); diff --git a/langchain/src/agents/tests/agent.int.test.ts b/langchain/src/agents/tests/agent.int.test.ts index 22999477b447..f8fbf53bde9f 100644 --- a/langchain/src/agents/tests/agent.int.test.ts +++ b/langchain/src/agents/tests/agent.int.test.ts @@ -4,7 +4,7 @@ import { loadAgent } from "../load.js"; import { AgentExecutor, Tool } from "../index.js"; import { SerpAPI } from "../tools/serpapi.js"; import { Calculator } from "../tools/calculator.js"; -import { initializeAgentExecutor } from "../initialize.js"; +import { initializeAgentExecutorWithOptions } from "../initialize.js"; test("Run agent from hub", async () => { const model = new OpenAI({ temperature: 0, modelName: "text-babbage-001" }); @@ -29,11 +29,9 @@ test("Run agent locally", async () => { const model = new OpenAI({ temperature: 0, modelName: "text-babbage-001" }); const tools = [new SerpAPI(), new Calculator()]; - const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description" - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", + }); console.log("Loaded agent."); const input = `Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?`; diff --git a/langchain/src/callbacks/tests/langchain_tracer.int.test.ts b/langchain/src/callbacks/tests/langchain_tracer.int.test.ts index b382c3bed5c4..7c7897285288 100644 --- a/langchain/src/callbacks/tests/langchain_tracer.int.test.ts +++ b/langchain/src/callbacks/tests/langchain_tracer.int.test.ts @@ -3,7 +3,7 @@ import { test, expect } from "@jest/globals"; import { LangChainTracer } from "../tracers.js"; import { OpenAI } from "../../llms/index.js"; import { Calculator, SerpAPI } from "../../agents/tools/index.js"; -import { initializeAgentExecutor } from "../../agents/index.js"; +import { initializeAgentExecutorWithOptions } from "../../agents/index.js"; test("Test LangChain tracer", async () => { const tracer = new LangChainTracer(); @@ -27,12 +27,10 @@ test.skip("Test Traced Agent with concurrency (skipped until we fix concurrency) const model = new OpenAI({ temperature: 0 }); const tools = [new SerpAPI(), new Calculator()]; - const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description", - true - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", + verbose: true, + }); const input = `Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?`; From f03cf7b1c0b9617001d9e4280d13a29f3574cc14 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Sun, 19 Mar 2023 15:30:26 -0700 Subject: [PATCH 08/17] Formatting --- langchain/src/agents/chat_convo/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/langchain/src/agents/chat_convo/index.ts b/langchain/src/agents/chat_convo/index.ts index 09daed3f1d08..812037420ecb 100644 --- a/langchain/src/agents/chat_convo/index.ts +++ b/langchain/src/agents/chat_convo/index.ts @@ -134,7 +134,8 @@ export class ChatConversationalAgent extends Agent { static createPrompt(tools: Tool[], args?: CreatePromptArgs) { const systemMessage = (args?.systemMessage ?? DEFAULT_PREFIX) + PREFIX_END; const humanMessage = args?.humanMessage ?? DEFAULT_SUFFIX; - const outputParser = args?.outputParser ?? new ChatConversationalAgentOutputParser(); + const outputParser = + args?.outputParser ?? new ChatConversationalAgentOutputParser(); const toolStrings = tools .map((tool) => `${tool.name}: ${tool.description}`) .join("\n"); From ccaa4ef1dd2a28e37df10087fd4132c79c30d44e Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Mon, 20 Mar 2023 09:57:18 -0700 Subject: [PATCH 09/17] Update docs --- docs/docs/modules/agents/zapier_agent.md | 4 ++-- examples/src/agents/chat_convo_with_tracing.ts | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/docs/modules/agents/zapier_agent.md b/docs/docs/modules/agents/zapier_agent.md index 6ad69758a3ba..171d0b9bac5b 100644 --- a/docs/docs/modules/agents/zapier_agent.md +++ b/docs/docs/modules/agents/zapier_agent.md @@ -2,7 +2,7 @@ Full docs here: https://nla.zapier.com/api/v1/dynamic/docs -**Zapier Natural Language Actions** gives you access to the 5k+ apps, 20k+ actions on Zapier's platform through a natural language API interface. +**Zapier Natural Language Actions** gives you access to the 5k+ apps and 20k+ actions on Zapier's platform through a natural language API interface. NLA supports apps like Gmail, Salesforce, Trello, Slack, Asana, HubSpot, Google Sheets, Microsoft Teams, and thousands more apps: https://zapier.com/apps @@ -16,7 +16,7 @@ User-facing (Oauth): for production scenarios where you are deploying an end-use This quick start will focus on the server-side use case for brevity. Review full docs or reach out to nla@zapier.com for user-facing oauth developer support. -This example goes over how to use the Zapier integration an Agent. In code, below: +The example below demonstrates how to use the Zapier integration as an Agent: ```typescript import { OpenAI } from "langchain"; diff --git a/examples/src/agents/chat_convo_with_tracing.ts b/examples/src/agents/chat_convo_with_tracing.ts index eee839692940..a01f0af1f6ed 100644 --- a/examples/src/agents/chat_convo_with_tracing.ts +++ b/examples/src/agents/chat_convo_with_tracing.ts @@ -11,11 +11,11 @@ export const run = async () => { const executor = await initializeAgentExecutorWithOptions(tools, model, { agentType: "chat-conversational-react-description", verbose: true, - }); - executor.memory = new BufferMemory({ - returnMessages: true, - memoryKey: "chat_history", - inputKey: "input", + memory: new BufferMemory({ + returnMessages: true, + memoryKey: "chat_history", + inputKey: "input", + }), }); console.log("Loaded agent."); From 9352f69236eabceb10f70397be9bf0be24581fd3 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Mon, 27 Mar 2023 19:11:52 -0700 Subject: [PATCH 10/17] Add returnIntermediateSteps, suffix to initializeAgentExecutorWithOptions options, change prompt option to prefix, remove memory default --- langchain/src/agents/chat_convo/index.ts | 17 +++++--- langchain/src/agents/chat_convo/prompt.ts | 2 +- langchain/src/agents/initialize.ts | 30 +++++++------- .../agents/tests/chat_convo_agent.int.test.ts | 39 +++++++++++++++++++ 4 files changed, 67 insertions(+), 21 deletions(-) create mode 100644 langchain/src/agents/tests/chat_convo_agent.int.test.ts diff --git a/langchain/src/agents/chat_convo/index.ts b/langchain/src/agents/chat_convo/index.ts index de4eecbbaca9..a4f02bb8a88d 100644 --- a/langchain/src/agents/chat_convo/index.ts +++ b/langchain/src/agents/chat_convo/index.ts @@ -50,10 +50,14 @@ export class ChatConversationalAgentOutputParser extends BaseOutputParser { } export type CreatePromptArgs = { - /** String to put after the list of tools. */ + /** DEPRECATED: String to put after the list of tools. */ systemMessage?: string; - /** String to put before the list of tools. */ + /** DEPRECATED: String to put before the list of tools. */ humanMessage?: string; + /** String to put after the list of tools. */ + prefix?: string; + /** String to put before the list of tools. */ + suffix?: string; /** List of input variables the final prompt will expect. */ inputVariables?: string[]; /** Output parser to use for formatting. */ @@ -125,12 +129,13 @@ export class ChatConversationalAgent extends 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.systemMessage - String to put after the list of tools. - * @param args.humanMessage - String to put before the list of tools. + * @param args.prefix - String to put before the list of tools. + * @param args.suffix - String to put after the list of tools. */ static createPrompt(tools: Tool[], args?: CreatePromptArgs) { - const systemMessage = (args?.systemMessage ?? DEFAULT_PREFIX) + PREFIX_END; - const humanMessage = args?.humanMessage ?? DEFAULT_SUFFIX; + const systemMessage = + (args?.prefix ?? args?.systemMessage ?? DEFAULT_PREFIX) + PREFIX_END; + const humanMessage = args?.suffix ?? args?.humanMessage ?? DEFAULT_SUFFIX; const outputParser = args?.outputParser ?? new ChatConversationalAgentOutputParser(); const toolStrings = tools diff --git a/langchain/src/agents/chat_convo/prompt.ts b/langchain/src/agents/chat_convo/prompt.ts index 6568af9ba67e..f8a2d4c15a80 100644 --- a/langchain/src/agents/chat_convo/prompt.ts +++ b/langchain/src/agents/chat_convo/prompt.ts @@ -6,7 +6,7 @@ Assistant is constantly learning and improving, and its capabilities are constan Overall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.`; -export const PREFIX_END = ` However, all responses must adhere to the style of RESPONSE FORMAT INSTRUCTIONS.`; +export const PREFIX_END = ` However, above all else, all responses must adhere to the format of RESPONSE FORMAT INSTRUCTIONS.`; export const FORMAT_INSTRUCTIONS = `RESPONSE FORMAT INSTRUCTIONS ---------------------------- diff --git a/langchain/src/agents/initialize.ts b/langchain/src/agents/initialize.ts index a8fd4d89fbc1..e67876d7ed36 100644 --- a/langchain/src/agents/initialize.ts +++ b/langchain/src/agents/initialize.ts @@ -5,7 +5,7 @@ import { ChatConversationalAgent } from "./chat_convo/index.js"; import { ChatAgent } from "./chat/index.js"; import { BaseLanguageModel } from "../base_language/index.js"; import { CallbackManager, getCallbackManager } from "../callbacks/index.js"; -import { BaseMemory, BufferMemory } from "../memory/index.js"; +import { BaseMemory } from "../memory/index.js"; type AgentType = | "zero-shot-react-description" @@ -52,14 +52,17 @@ export const initializeAgentExecutorWithOptions = async ( tools: Tool[], llm: BaseLanguageModel, options: { - agentType?: string; - prompt?: string; + agentType?: AgentType; + prefix?: string; + suffix?: string; memory?: BaseMemory; + returnIntermediateSteps?: boolean; verbose?: boolean; callbackManager?: CallbackManager; } ): Promise => { const agentType = options.agentType ?? "zero-shot-react-description"; + const returnIntermediateSteps = options.returnIntermediateSteps ?? false; const verbose = options.verbose ?? false; const callbackManager = options.callbackManager ?? getCallbackManager(); @@ -67,10 +70,11 @@ export const initializeAgentExecutorWithOptions = async ( case "zero-shot-react-description": { return AgentExecutor.fromAgentAndTools({ agent: ZeroShotAgent.fromLLMAndTools(llm, tools, { - prefix: options.prompt, + prefix: options.prefix, + suffix: options.suffix, }), tools, - returnIntermediateSteps: true, + returnIntermediateSteps, verbose, callbackManager, memory: options.memory, @@ -79,10 +83,11 @@ export const initializeAgentExecutorWithOptions = async ( case "chat-zero-shot-react-description": { return AgentExecutor.fromAgentAndTools({ agent: ChatAgent.fromLLMAndTools(llm, tools, { - prefix: options.prompt, + prefix: options.prefix, + suffix: options.suffix, }), tools, - returnIntermediateSteps: true, + returnIntermediateSteps, verbose, callbackManager, memory: options.memory, @@ -91,17 +96,14 @@ export const initializeAgentExecutorWithOptions = async ( case "chat-conversational-react-description": { const executor = AgentExecutor.fromAgentAndTools({ agent: ChatConversationalAgent.fromLLMAndTools(llm, tools, { - systemMessage: options.prompt, + prefix: options.prefix, + suffix: options.suffix, }), tools, + returnIntermediateSteps, verbose, callbackManager, - memory: - options.memory ?? - new BufferMemory({ - returnMessages: true, - memoryKey: "chat_history", - }), + memory: options.memory, }); return executor; } diff --git a/langchain/src/agents/tests/chat_convo_agent.int.test.ts b/langchain/src/agents/tests/chat_convo_agent.int.test.ts new file mode 100644 index 000000000000..9d1697b27e95 --- /dev/null +++ b/langchain/src/agents/tests/chat_convo_agent.int.test.ts @@ -0,0 +1,39 @@ +import { test } from "@jest/globals"; +import { ChatOpenAI } from "../../chat_models/openai.js"; +import { BufferMemory } from "../../memory/index.js"; +import { Calculator } from "../tools/calculator.js"; +import { initializeAgentExecutorWithOptions } from "../initialize.js"; + +test("Run conversational agent with memory", async () => { + const model = new ChatOpenAI({ modelName: "gpt-3.5-turbo" }); + const tools = [new Calculator()]; + + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "chat-conversational-react-description", + verbose: true, + memory: new BufferMemory({ + returnMessages: true, + memoryKey: "chat_history", + inputKey: "input", + }), + }); + console.log("Loaded agent."); + + const input0 = `"how is your day going?"`; + + const result0 = await executor.call({ input: input0 }); + + console.log(`Got output ${result0.output}`); + + const input1 = `"whats is 9 to the 2nd power?"`; + + const result1 = await executor.call({ input: input1 }); + + console.log(`Got output ${result1.output}`); + + const input2 = `"whats is that result divided by 10?"`; + + const result2 = await executor.call({ input: input2 }); + + console.log(`Got output ${result2.output}`); +}, 30000); From 07c1306bd3e9c59dacd83d30b6e6552aeb2e2bfc Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Mon, 27 Mar 2023 19:16:57 -0700 Subject: [PATCH 11/17] Remove test timeout --- langchain/src/agents/tests/chat_convo_agent.int.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langchain/src/agents/tests/chat_convo_agent.int.test.ts b/langchain/src/agents/tests/chat_convo_agent.int.test.ts index 9d1697b27e95..02f219b54ab8 100644 --- a/langchain/src/agents/tests/chat_convo_agent.int.test.ts +++ b/langchain/src/agents/tests/chat_convo_agent.int.test.ts @@ -36,4 +36,4 @@ test("Run conversational agent with memory", async () => { const result2 = await executor.call({ input: input2 }); console.log(`Got output ${result2.output}`); -}, 30000); +}); From 3d0fbc99704366a912f17c2bb5faf856d11a0822 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Tue, 28 Mar 2023 14:29:11 -0700 Subject: [PATCH 12/17] Revert renames, throw error if memory is passed in for unsupported agent types --- .../src/agents/chat_convo_with_tracing.ts | 10 ++-- langchain/src/agents/chat_convo/index.ts | 17 +++---- langchain/src/agents/initialize.ts | 48 ++++++++++++------- 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/examples/src/agents/chat_convo_with_tracing.ts b/examples/src/agents/chat_convo_with_tracing.ts index a01f0af1f6ed..cfe33e4d9cc0 100644 --- a/examples/src/agents/chat_convo_with_tracing.ts +++ b/examples/src/agents/chat_convo_with_tracing.ts @@ -1,21 +1,19 @@ import { ChatOpenAI } from "langchain/chat_models"; import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { SerpAPI, Calculator } from "langchain/tools"; -import { BufferMemory } from "langchain/memory"; export const run = async () => { process.env.LANGCHAIN_HANDLER = "langchain"; const model = new ChatOpenAI({ temperature: 0 }); const tools = [new SerpAPI(), new Calculator()]; + // Passing "chat-conversational-react-description" as the agent type + // automatically creates and uses BufferMemory with the executor. + // If you would like to override this, you can pass in a custom + // memory option, but the memoryKey set on it must be "chat_history". const executor = await initializeAgentExecutorWithOptions(tools, model, { agentType: "chat-conversational-react-description", verbose: true, - memory: new BufferMemory({ - returnMessages: true, - memoryKey: "chat_history", - inputKey: "input", - }), }); console.log("Loaded agent."); diff --git a/langchain/src/agents/chat_convo/index.ts b/langchain/src/agents/chat_convo/index.ts index a4f02bb8a88d..d434a36c28ff 100644 --- a/langchain/src/agents/chat_convo/index.ts +++ b/langchain/src/agents/chat_convo/index.ts @@ -50,14 +50,10 @@ export class ChatConversationalAgentOutputParser extends BaseOutputParser { } export type CreatePromptArgs = { - /** DEPRECATED: String to put after the list of tools. */ - systemMessage?: string; - /** DEPRECATED: String to put before the list of tools. */ - humanMessage?: string; /** String to put after the list of tools. */ - prefix?: string; + systemMessage?: string; /** String to put before the list of tools. */ - suffix?: string; + humanMessage?: string; /** List of input variables the final prompt will expect. */ inputVariables?: string[]; /** Output parser to use for formatting. */ @@ -129,13 +125,12 @@ export class ChatConversationalAgent extends 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.prefix - String to put before the list of tools. - * @param args.suffix - String to put after the list of tools. + * @param args.systemMessage - String to put before the list of tools. + * @param args.humanMessage - String to put after the list of tools. */ static createPrompt(tools: Tool[], args?: CreatePromptArgs) { - const systemMessage = - (args?.prefix ?? args?.systemMessage ?? DEFAULT_PREFIX) + PREFIX_END; - const humanMessage = args?.suffix ?? args?.humanMessage ?? DEFAULT_SUFFIX; + const systemMessage = (args?.systemMessage ?? DEFAULT_PREFIX) + PREFIX_END; + const humanMessage = args?.humanMessage ?? DEFAULT_SUFFIX; const outputParser = args?.outputParser ?? new ChatConversationalAgentOutputParser(); const toolStrings = tools diff --git a/langchain/src/agents/initialize.ts b/langchain/src/agents/initialize.ts index e67876d7ed36..bb66cb2c7d43 100644 --- a/langchain/src/agents/initialize.ts +++ b/langchain/src/agents/initialize.ts @@ -5,7 +5,7 @@ import { ChatConversationalAgent } from "./chat_convo/index.js"; import { ChatAgent } from "./chat/index.js"; import { BaseLanguageModel } from "../base_language/index.js"; import { CallbackManager, getCallbackManager } from "../callbacks/index.js"; -import { BaseMemory } from "../memory/index.js"; +import { BaseMemory, BufferMemory } from "../memory/index.js"; type AgentType = | "zero-shot-react-description" @@ -53,8 +53,7 @@ export const initializeAgentExecutorWithOptions = async ( llm: BaseLanguageModel, options: { agentType?: AgentType; - prefix?: string; - suffix?: string; + promptArgs?: object; memory?: BaseMemory; returnIntermediateSteps?: boolean; verbose?: boolean; @@ -68,42 +67,55 @@ export const initializeAgentExecutorWithOptions = async ( switch (agentType) { case "zero-shot-react-description": { + if (options.memory) { + throw new Error( + `The "memory" option is only supported for executors with agentType "chat-conversational-react-description".` + ); + } return AgentExecutor.fromAgentAndTools({ - agent: ZeroShotAgent.fromLLMAndTools(llm, tools, { - prefix: options.prefix, - suffix: options.suffix, - }), + agent: ZeroShotAgent.fromLLMAndTools( + llm, + tools, + options.promptArgs ?? {} + ), tools, returnIntermediateSteps, verbose, callbackManager, - memory: options.memory, }); } case "chat-zero-shot-react-description": { + if (options.memory) { + throw new Error( + `The "memory" option is only supported for executors with agentType "chat-conversational-react-description".` + ); + } return AgentExecutor.fromAgentAndTools({ - agent: ChatAgent.fromLLMAndTools(llm, tools, { - prefix: options.prefix, - suffix: options.suffix, - }), + agent: ChatAgent.fromLLMAndTools(llm, tools, options.promptArgs ?? {}), tools, returnIntermediateSteps, verbose, callbackManager, - memory: options.memory, }); } case "chat-conversational-react-description": { const executor = AgentExecutor.fromAgentAndTools({ - agent: ChatConversationalAgent.fromLLMAndTools(llm, tools, { - prefix: options.prefix, - suffix: options.suffix, - }), + agent: ChatConversationalAgent.fromLLMAndTools( + llm, + tools, + options.promptArgs ?? {} + ), tools, returnIntermediateSteps, verbose, callbackManager, - memory: options.memory, + memory: + options.memory ?? + new BufferMemory({ + returnMessages: true, + memoryKey: "chat_history", + inputKey: "input", + }), }); return executor; } From 6b68c5b3cc7e67b1bd9e246f4eb48b18724e7e14 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 17 Apr 2023 16:24:06 +0100 Subject: [PATCH 13/17] Fix import --- langchain/src/agents/tests/chat_convo_agent.int.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langchain/src/agents/tests/chat_convo_agent.int.test.ts b/langchain/src/agents/tests/chat_convo_agent.int.test.ts index 02f219b54ab8..75482ac10b28 100644 --- a/langchain/src/agents/tests/chat_convo_agent.int.test.ts +++ b/langchain/src/agents/tests/chat_convo_agent.int.test.ts @@ -1,7 +1,7 @@ import { test } from "@jest/globals"; import { ChatOpenAI } from "../../chat_models/openai.js"; import { BufferMemory } from "../../memory/index.js"; -import { Calculator } from "../tools/calculator.js"; +import { Calculator } from "../../tools/calculator.js"; import { initializeAgentExecutorWithOptions } from "../initialize.js"; test("Run conversational agent with memory", async () => { From db79b9a341665135b7a597af6a58804d09207b82 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 17 Apr 2023 17:00:12 +0100 Subject: [PATCH 14/17] Do some tsc wizardry to make the initialise function only accept args accepted by the agent specfied --- langchain/src/agents/chat/index.ts | 2 +- langchain/src/agents/chat_convo/index.ts | 5 +- langchain/src/agents/initialize.ts | 85 +++++++++++------------- langchain/src/agents/mrkl/index.ts | 2 +- 4 files changed, 44 insertions(+), 50 deletions(-) diff --git a/langchain/src/agents/chat/index.ts b/langchain/src/agents/chat/index.ts index 6738f27ecff9..c463c03eaa4c 100644 --- a/langchain/src/agents/chat/index.ts +++ b/langchain/src/agents/chat/index.ts @@ -34,7 +34,7 @@ export class ChatAgent extends Agent { } _agentType() { - return "zero-shot-react-description" as const; + return "chat-zero-shot-react-description" as const; } observationPrefix() { diff --git a/langchain/src/agents/chat_convo/index.ts b/langchain/src/agents/chat_convo/index.ts index d5d116ce13b5..cda44b91c9cc 100644 --- a/langchain/src/agents/chat_convo/index.ts +++ b/langchain/src/agents/chat_convo/index.ts @@ -78,9 +78,8 @@ export class ChatConversationalAgent extends Agent { outputParser ?? new ChatConversationalAgentOutputParser(); } - _agentType(): string { - /** Not turning on serialization until more sure of abstractions. */ - throw new Error("Method not implemented."); + _agentType() { + return "chat-conversational-react-description" as const; } observationPrefix() { diff --git a/langchain/src/agents/initialize.ts b/langchain/src/agents/initialize.ts index 09a2d768dae5..c598c3126278 100644 --- a/langchain/src/agents/initialize.ts +++ b/langchain/src/agents/initialize.ts @@ -5,7 +5,7 @@ import { ChatConversationalAgent } from "./chat_convo/index.js"; import { ChatAgent } from "./chat/index.js"; import { BaseLanguageModel } from "../base_language/index.js"; import { CallbackManager, getCallbackManager } from "../callbacks/index.js"; -import { BaseMemory, BufferMemory } from "../memory/index.js"; +import { BufferMemory } from "../memory/index.js"; type AgentType = | "zero-shot-react-description" @@ -51,69 +51,64 @@ export const initializeAgentExecutor = async ( } }; +type AgentExecutorOptions = + | ({ + agentType: "zero-shot-react-description"; + agentArgs?: Parameters[2]; + } & Omit< + Parameters[0], + "agent" | "tools" | "memory" + >) + | ({ + agentType: "chat-zero-shot-react-description"; + agentArgs?: Parameters[2]; + } & Omit< + Parameters[0], + "agent" | "tools" | "memory" + >) + | ({ + agentType: "chat-conversational-react-description"; + agentArgs?: Parameters[2]; + } & Omit< + Parameters[0], + "agent" | "tools" + >); + export const initializeAgentExecutorWithOptions = async ( tools: Tool[], llm: BaseLanguageModel, - options: { - agentType?: AgentType; - promptArgs?: object; - memory?: BaseMemory; - returnIntermediateSteps?: boolean; - verbose?: boolean; - callbackManager?: CallbackManager; + options: AgentExecutorOptions = { + agentType: + llm._modelType() === "base_chat_model" + ? "chat-zero-shot-react-description" + : "zero-shot-react-description", } ): Promise => { - const agentType = options.agentType ?? "zero-shot-react-description"; - const returnIntermediateSteps = options.returnIntermediateSteps ?? false; - const verbose = options.verbose ?? false; - const callbackManager = options.callbackManager ?? getCallbackManager(); - - switch (agentType) { + switch (options.agentType) { case "zero-shot-react-description": { - if (options.memory) { - throw new Error( - `The "memory" option is only supported for executors with agentType "chat-conversational-react-description".` - ); - } + const { agentArgs, ...rest } = options; return AgentExecutor.fromAgentAndTools({ - agent: ZeroShotAgent.fromLLMAndTools( - llm, - tools, - options.promptArgs ?? {} - ), + agent: ZeroShotAgent.fromLLMAndTools(llm, tools, agentArgs), tools, - returnIntermediateSteps, - verbose, - callbackManager, + ...rest, }); } case "chat-zero-shot-react-description": { - if (options.memory) { - throw new Error( - `The "memory" option is only supported for executors with agentType "chat-conversational-react-description".` - ); - } + const { agentArgs, ...rest } = options; return AgentExecutor.fromAgentAndTools({ - agent: ChatAgent.fromLLMAndTools(llm, tools, options.promptArgs ?? {}), + agent: ChatAgent.fromLLMAndTools(llm, tools, agentArgs), tools, - returnIntermediateSteps, - verbose, - callbackManager, + ...rest, }); } case "chat-conversational-react-description": { + const { agentArgs, memory, ...rest } = options; const executor = AgentExecutor.fromAgentAndTools({ - agent: ChatConversationalAgent.fromLLMAndTools( - llm, - tools, - options.promptArgs ?? {} - ), + agent: ChatConversationalAgent.fromLLMAndTools(llm, tools, agentArgs), tools, - returnIntermediateSteps, - verbose, - callbackManager, + ...rest, memory: - options.memory ?? + memory ?? new BufferMemory({ returnMessages: true, memoryKey: "chat_history", diff --git a/langchain/src/agents/mrkl/index.ts b/langchain/src/agents/mrkl/index.ts index fe1bb7e52b91..017c77df7fec 100644 --- a/langchain/src/agents/mrkl/index.ts +++ b/langchain/src/agents/mrkl/index.ts @@ -22,7 +22,7 @@ export type CreatePromptArgs = { inputVariables?: string[]; }; -type ZeroShotAgentInput = AgentInput; +export type ZeroShotAgentInput = AgentInput; /** * Agent for the MRKL chain. From 800e5171fbcb635af553ad7dfcabd34d75055939 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 17 Apr 2023 17:08:06 +0100 Subject: [PATCH 15/17] Lint --- langchain/src/agents/initialize.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langchain/src/agents/initialize.ts b/langchain/src/agents/initialize.ts index 0f8aaa30eedb..c60d0b73e661 100644 --- a/langchain/src/agents/initialize.ts +++ b/langchain/src/agents/initialize.ts @@ -106,7 +106,6 @@ export const initializeAgentExecutorWithOptions = async ( const executor = AgentExecutor.fromAgentAndTools({ agent: ChatConversationalAgent.fromLLMAndTools(llm, tools, agentArgs), tools, - ...rest, memory: memory ?? new BufferMemory({ @@ -114,6 +113,7 @@ export const initializeAgentExecutorWithOptions = async ( memoryKey: "chat_history", inputKey: "input", }), + ...rest, }); return executor; } From 27f376da2489412b096c34c243dfd9ad7c7fc277 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 17 Apr 2023 17:10:21 +0100 Subject: [PATCH 16/17] Update examples added since --- docs/docs/modules/agents/tools/lambda_agent.md | 12 +++++------- examples/src/agents/aiplugin-tool.ts | 7 +++---- examples/src/agents/mrkl_browser.ts | 12 +++++------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/docs/docs/modules/agents/tools/lambda_agent.md b/docs/docs/modules/agents/tools/lambda_agent.md index 4a0fe79c693f..bbdc0d5a2f7f 100644 --- a/docs/docs/modules/agents/tools/lambda_agent.md +++ b/docs/docs/modules/agents/tools/lambda_agent.md @@ -21,10 +21,10 @@ This quick start will demonstrate how an Agent could use a Lambda function to se - The IAM role corresponding to those credentials must have permission to invoke the lambda function. ```typescript -import { OpenAI } from "langchain"; +import { OpenAI } from "langchain/llms/openai"; import { SerpAPI } from "langchain/tools"; import { AWSLambda } from "langchain/tools/aws_lambda"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; const model = new OpenAI({ temperature: 0 }); const emailSenderTool = new AWSLambda({ @@ -38,11 +38,9 @@ const emailSenderTool = new AWSLambda({ functionName: "SendEmailViaSES", // the function name as seen in AWS Console }); const tools = [emailSenderTool, new SerpAPI("api_key_goes_here")]; -const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description" -); +const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", +}); const input = `Find out the capital of Croatia. Once you have it, email the answer to testing123@gmail.com.`; const result = await executor.call({ input }); diff --git a/examples/src/agents/aiplugin-tool.ts b/examples/src/agents/aiplugin-tool.ts index 43e835ca3ec8..02b3ed2c44fa 100644 --- a/examples/src/agents/aiplugin-tool.ts +++ b/examples/src/agents/aiplugin-tool.ts @@ -1,5 +1,5 @@ import { ChatOpenAI } from "langchain/chat_models/openai"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { RequestsGetTool, RequestsPostTool, @@ -14,11 +14,10 @@ export const run = async () => { "https://www.klarna.com/.well-known/ai-plugin.json" ), ]; - const agent = await initializeAgentExecutor( + const agent = await initializeAgentExecutorWithOptions( tools, new ChatOpenAI({ temperature: 0 }), - "chat-zero-shot-react-description", - true + { agentType: "chat-zero-shot-react-description", verbose: true } ); const result = await agent.call({ diff --git a/examples/src/agents/mrkl_browser.ts b/examples/src/agents/mrkl_browser.ts index 09c87df519a3..b25821ece38f 100644 --- a/examples/src/agents/mrkl_browser.ts +++ b/examples/src/agents/mrkl_browser.ts @@ -1,5 +1,5 @@ import { OpenAI } from "langchain/llms/openai"; -import { initializeAgentExecutor } from "langchain/agents"; +import { initializeAgentExecutorWithOptions } from "langchain/agents"; import { OpenAIEmbeddings } from "langchain/embeddings/openai"; import { SerpAPI } from "langchain/tools"; import { Calculator } from "langchain/tools/calculator"; @@ -18,12 +18,10 @@ export const run = async () => { new WebBrowser({ model, embeddings }), ]; - const executor = await initializeAgentExecutor( - tools, - model, - "zero-shot-react-description", - true - ); + const executor = await initializeAgentExecutorWithOptions(tools, model, { + agentType: "zero-shot-react-description", + verbose: true, + }); console.log("Loaded agent."); const input = `What is the word of the day on merriam webster. What is the top result on google for that word`; From ac7ae1fdd83853531bdd6af104c40519521a57c7 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 17 Apr 2023 17:20:10 +0100 Subject: [PATCH 17/17] Fix int tests --- langchain/src/agents/tests/agent.int.test.ts | 1 + .../tests/simple_sequential_chain.int.test.ts | 15 +++++---------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/langchain/src/agents/tests/agent.int.test.ts b/langchain/src/agents/tests/agent.int.test.ts index 596220d1f3ee..613a2c8d2530 100644 --- a/langchain/src/agents/tests/agent.int.test.ts +++ b/langchain/src/agents/tests/agent.int.test.ts @@ -73,6 +73,7 @@ test("Run tool web-browser", async () => { const executor = await initializeAgentExecutorWithOptions(tools, model, { agentType: "zero-shot-react-description", + returnIntermediateSteps: true, }); console.log("Loaded agent."); diff --git a/langchain/src/chains/tests/simple_sequential_chain.int.test.ts b/langchain/src/chains/tests/simple_sequential_chain.int.test.ts index 830b3fc0abec..8b7c29221b51 100644 --- a/langchain/src/chains/tests/simple_sequential_chain.int.test.ts +++ b/langchain/src/chains/tests/simple_sequential_chain.int.test.ts @@ -39,13 +39,9 @@ test("Test SimpleSequentialChain example usage", async () => { verbose: true, }); const review = await overallChain.run("Tragedy at sunset on the beach"); - expect(review.trim()).toMatchInlineSnapshot(` - "Tragedy at Sunset on the Beach is a powerful and moving story of love, loss, and redemption. The play follows the story of two young lovers, Jack and Jill, whose plans for a future together are tragically cut short when Jack is killed in a car accident. The play follows Jill as she struggles to cope with her grief and eventually finds solace in the arms of another man. - - The play is beautifully written and the performances are outstanding. The actors bring the characters to life with their heartfelt performances, and the audience is taken on an emotional journey as Jill is forced to confront her grief and make a difficult decision between her past and her future. The play culminates in a powerful climax that will leave the audience in tears. - - Overall, Tragedy at Sunset on the Beach is a powerful and moving story that will stay with you long after the curtain falls. It is a must-see for anyone looking for an emotionally charged and thought-provoking experience." - `); + expect(review.trim().toLowerCase()).toContain( + "tragedy at sunset on the beach" + ); }); test("Test SimpleSequentialChain serialize/deserialize", async () => { @@ -80,7 +76,6 @@ test("Test SimpleSequentialChain serialize/deserialize", async () => { serializedChain ); expect(deserializedChain.chains.length).toEqual(2); - expect(deserializedChain._chainType).toEqual("simple_sequential_chain"); - const review = await deserializedChain.run("test"); - expect(review.trim()).toMatchInlineSnapshot(`"Test."`); + expect(deserializedChain._chainType()).toEqual("simple_sequential_chain"); + await deserializedChain.run("test"); });