react.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import { AgentExecutor, ChatAgentOutputParser } from "langchain/agents";
  2. import { formatLogToString } from "langchain/agents/format_scratchpad/log";
  3. import { OpenAI } from "langchain/llms/openai";
  4. import { ChatPromptTemplate, PromptTemplate } from "langchain/prompts";
  5. import { AgentStep } from "langchain/schema";
  6. import { RunnableSequence } from "langchain/schema/runnable";
  7. import { SerpAPI } from "langchain/tools";
  8. import { Calculator } from "langchain/tools/calculator";
  9. import { renderTextDescription } from "langchain/tools/render";
  10. import { llm } from "./llm";
  11. (async function () {
  12. /** Create a list of the tools we're providing to the agent */
  13. const tools = [
  14. new SerpAPI(
  15. "03647385acfb9e816d2170d07ae7c84131aa4fb6f732b14ffaa34dc065a2f4f6",
  16. {
  17. location: "Austin,Texas,United States",
  18. hl: "en",
  19. gl: "us",
  20. }
  21. ),
  22. new Calculator(),
  23. ];
  24. /**
  25. * Define our output parser.
  26. * In this case we'll use the default output parser
  27. * for chat agents. `ChatAgentOutputParser`
  28. */
  29. const outputParser = new ChatAgentOutputParser();
  30. /**
  31. * Define our prompts.
  32. * For this example we'll use the same default prompts
  33. * that the `ChatAgent` class uses.
  34. */
  35. const PREFIX = `Answer the following questions as best you can. You have access to the following tools:
  36. {tools}`;
  37. const FORMAT_INSTRUCTIONS = `The way you use the tools is by specifying a json blob, denoted below by $JSON_BLOB
  38. Specifically, this $JSON_BLOB should have a "action" key (with the name of the tool to use) and a "action_input" key (with the input to the tool going here).
  39. The $JSON_BLOB should only contain a SINGLE action, do NOT return a list of multiple actions. Here is an example of a valid $JSON_BLOB:
  40. \`\`\`
  41. {{
  42. "action": "calculator",
  43. "action_input": "1 + 2"
  44. }}
  45. \`\`\`
  46. ALWAYS use the following format:
  47. Question: the input question you must answer
  48. Thought: you should always think about what to do
  49. Action:
  50. \`\`\`
  51. $JSON_BLOB
  52. \`\`\`
  53. Observation: the result of the action
  54. ... (this Thought/Action/Observation can repeat N times)
  55. Thought: I now know the final answer
  56. Final Answer: the final answer to the original input question`;
  57. const SUFFIX = `Begin! Reminder to always use the exact characters \`Final Answer\` when responding.
  58. Thoughts: {agent_scratchpad}`;
  59. const DEFAULT_HUMAN_MESSAGE_TEMPLATE = "Question: {input}";
  60. /**
  61. * Now we can combine all our prompts together, passing
  62. * in the required input variables.
  63. */
  64. // The `renderTextDescription` util function combines
  65. // all tool names and descriptions into a single string.
  66. const toolStrings = renderTextDescription(tools);
  67. const prefixTemplate = PromptTemplate.fromTemplate(PREFIX);
  68. const formattedPrefix = await prefixTemplate.format({ tools: toolStrings });
  69. const template = [formattedPrefix, FORMAT_INSTRUCTIONS, SUFFIX].join(
  70. "\n\n"
  71. );
  72. // Add the template, and human message template to an array of messages.
  73. const prompt = ChatPromptTemplate.fromMessages([
  74. ["ai", template],
  75. ["human", DEFAULT_HUMAN_MESSAGE_TEMPLATE],
  76. ]);
  77. /**
  78. * Combine all our previous steps into a runnable agent.
  79. * We'll use a `RunnableSequence` which takes in an input,
  80. * and the previous steps. We then format the steps into a
  81. * string so it can be passed to the prompt.
  82. */
  83. const runnableAgent = RunnableSequence.from([
  84. {
  85. input: (i: { input: string; steps: AgentStep[] }) => i.input,
  86. agent_scratchpad: (i: { input: string; steps: AgentStep[] }) =>
  87. formatLogToString(i.steps),
  88. },
  89. prompt,
  90. llm,
  91. outputParser,
  92. ]);
  93. /**
  94. * The last step is to pass our agent into the
  95. * AgentExecutor along with the tools.
  96. * The AgentExecutor is responsible for actually
  97. * running the iterations.
  98. */
  99. const executor = AgentExecutor.fromAgentAndTools({
  100. agent: runnableAgent,
  101. tools,
  102. });
  103. console.log("Loaded agent executor");
  104. const input = `Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?`;
  105. console.log(`Calling agent with prompt: ${input}`);
  106. const result = await executor.call({ input });
  107. console.log(result);
  108. })();
  109. /**
  110. Loaded agent executor
  111. Calling agent with prompt: Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?
  112. {
  113. output: "Jason Sudeikis is Olivia Wilde's boyfriend and his current age raised to the 0.23 power is approximately 1.7."
  114. }
  115. */