avatarJennifer Fu

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

18197

Abstract

response = <span class="hljs-keyword">await</span> executor.<span class="hljs-property">current</span>.<span class="hljs-title function_">call</span>({<span class="hljs-attr">input</span>: value}); <span class="hljs-title function_">setResult</span>(response.<span class="hljs-property">output</span>); <span class="hljs-title function_">setValue</span>(<span class="hljs-string">''</span>); } }, [value] );

<span class="hljs-title class_">React</span>.<span class="hljs-title function_">useEffect</span>(<span class="hljs-function">() =></span> { <span class="hljs-keyword">const</span> <span class="hljs-title function_">init</span> = <span class="hljs-keyword">async</span> (<span class="hljs-params"></span>) => {

  <span class="hljs-comment">// define a model</span>
  <span class="hljs-keyword">const</span> model = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ChatOpenAI</span>({
    <span class="hljs-comment">// use OPENAI_API_KEY</span>
    <span class="hljs-attr">openAIApiKey</span>: <span class="hljs-keyword">import</span>.<span class="hljs-property">meta</span>.<span class="hljs-property">env</span>.<span class="hljs-property">VITE_OPENAI_API_KEY</span>,
    <span class="hljs-comment">// use GPT 4</span>
    <span class="hljs-attr">modelName</span>: <span class="hljs-string">'gpt-4'</span>,
    <span class="hljs-comment">// temperature is a number between 0 and 2, with a default value of </span>
    <span class="hljs-comment">// 1 or 0.7 depending on the selected model. The temperature is used </span>
    <span class="hljs-comment">// to control the randomness of the output. When it is set higher, </span>
    <span class="hljs-comment">// there will be more random outputs.</span>
    <span class="hljs-attr">temperature</span>: <span class="hljs-number">0</span>,
  });

  <span class="hljs-comment">// define two tools</span>
  <span class="hljs-keyword">const</span> tools = [
    <span class="hljs-keyword">new</span> <span class="hljs-title class_">Calculator</span>(),
    <span class="hljs-keyword">new</span> <span class="hljs-title class_">SerpAPI</span>(<span class="hljs-keyword">import</span>.<span class="hljs-property">meta</span>.<span class="hljs-property">env</span>.<span class="hljs-property">VITE_SERPAPI_API_KEY</span>),
  ];

  <span class="hljs-comment">// initialize the agent with two tools</span>
  executor.<span class="hljs-property">current</span> = <span class="hljs-keyword">await</span> <span class="hljs-title function_">initializeAgentExecutorWithOptions</span>(
    tools,
    model,
    {
      <span class="hljs-attr">agentType</span>: <span class="hljs-string">'openai-functions'</span>,
      <span class="hljs-comment">// show verbose information in browser console</span>
      <span class="hljs-attr">verbose</span>: <span class="hljs-literal">true</span>,
    }
  );
};

<span class="hljs-title function_">init</span>();

}, []);

<span class="hljs-keyword">return</span> ( <span class="language-xml"><span class="hljs-tag"><></span> <span class="hljs-tag"><<span class="hljs-name">div</span>></span>Please type your prompt<span class="hljs-tag"></<span class="hljs-name">div</span>></span> <span class="hljs-tag"><<span class="hljs-name">input</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleInput}</span> <span class="hljs-attr">onKeyDown</span>=<span class="hljs-string">{handleKeyDown}</span> /></span> <span class="hljs-tag"><<span class="hljs-name">div</span>></span>Prompt: {prompt}<span class="hljs-tag"></<span class="hljs-name">div</span>></span> <span class="hljs-tag"><<span class="hljs-name">div</span>></span>Result: {result}<span class="hljs-tag"></<span class="hljs-name">div</span>></span> <span class="hljs-tag"></></span></span> ); }

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title class_">App</span>;</pre></div><p id="15d2">Execute <code>yarn dev</code>, and we have the app running.</p><p id="a4d4">Here is the first chat:</p><figure id="2876"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*nS4bvt_kJMfIWP554hT_cw.png"><figcaption>Image by author</figcaption></figure><p id="31d1">The verbose information shows in browser console:</p><div id="927c"><pre>[chain/start] [<span class="hljs-number">1</span>:chain:<span class="hljs-type">AgentExecutor</span>] <span class="hljs-type">Entering</span> <span class="hljs-type">Chain</span> run with input: { <span class="hljs-comment">"input"</span>: <span class="hljs-comment">"Who are you?"</span>, <span class="hljs-comment">"chat_history"</span>: [] } console.js:<span class="hljs-number">123</span> [llm/start] [<span class="hljs-number">1</span>:chain:<span class="hljs-type">AgentExecutor</span> > <span class="hljs-number">2</span>:llm:<span class="hljs-type">ChatOpenAI</span>] <span class="hljs-type">Entering</span> <span class="hljs-type">LLM</span> run with input: { <span class="hljs-comment">"messages"</span>: [ [ { <span class="hljs-comment">"lc"</span>: <span class="hljs-number">1</span>, <span class="hljs-comment">"type"</span>: <span class="hljs-comment">"constructor"</span>, <span class="hljs-comment">"id"</span>: [ <span class="hljs-comment">"langchain"</span>, <span class="hljs-comment">"schema"</span>, <span class="hljs-comment">"SystemMessage"</span> ], <span class="hljs-comment">"kwargs"</span>: { <span class="hljs-comment">"content"</span>: <span class="hljs-comment">"You are a helpful AI assistant."</span>, <span class="hljs-comment">"additional_kwargs"</span>: {} } }, { <span class="hljs-comment">"lc"</span>: <span class="hljs-number">1</span>, <span class="hljs-comment">"type"</span>: <span class="hljs-comment">"constructor"</span>, <span class="hljs-comment">"id"</span>: [ <span class="hljs-comment">"langchain"</span>, <span class="hljs-comment">"schema"</span>, <span class="hljs-comment">"HumanMessage"</span> ], <span class="hljs-comment">"kwargs"</span>: { <span class="hljs-comment">"content"</span>: <span class="hljs-comment">"Who are you?"</span>, <span class="hljs-comment">"additional_kwargs"</span>: {} } } ] ] } console.js:<span class="hljs-number">132</span> [llm/end] [<span class="hljs-number">1</span>:chain:<span class="hljs-type">AgentExecutor</span> > <span class="hljs-number">2</span>:llm:<span class="hljs-type">ChatOpenAI</span>] [<span class="hljs-number">2.64</span>s] <span class="hljs-type">Exiting</span> <span class="hljs-type">LLM</span> run with output: { <span class="hljs-comment">"generations"</span>: [ [ { <span class="hljs-comment">"text"</span>: <span class="hljs-comment">"I am an AI assistant designed to help answer your questions and assist you with various tasks. I can provide information, perform calculations, conduct online searches, and more. How can I assist you today?"</span>, <span class="hljs-comment">"message"</span>: { <span class="hljs-comment">"lc"</span>: <span class="hljs-number">1</span>, <span class="hljs-comment">"type"</span>: <span class="hljs-comment">"constructor"</span>, <span class="hljs-comment">"id"</span>: [ <span class="hljs-comment">"langchain"</span>, <span class="hljs-comment">"schema"</span>, <span class="hljs-comment">"AIMessage"</span> ], <span class="hljs-comment">"kwargs"</span>: { <span class="hljs-comment">"content"</span>: <span class="hljs-comment">"I am an AI assistant designed to help answer your questions and assist you with various tasks. I can provide information, perform calculations, conduct online searches, and more. How can I assist you today?"</span>, <span class="hljs-comment">"additional_kwargs"</span>: {} } }, <span class="hljs-comment">"generationInfo"</span>: { <span class="hljs-comment">"finish_reason"</span>: <span class="hljs-comment">"stop"</span> } } ] ], <span class="hljs-comment">"llmOutput"</span>: { <span class="hljs-comment">"tokenUsage"</span>: { <span class="hljs-comment">"completionTokens"</span>: <span class="hljs-number">41</span>, <span class="hljs-comment">"promptTokens"</span>: <span class="hljs-number">117</span>, <span class="hljs-comment">"totalTokens"</span>: <span class="hljs-number">158</span> } } } console.js:<span class="hljs-number">102</span> [chain/end] [<span class="hljs-number">1</span>:chain:<span class="hljs-type">AgentExecutor</span>] [<span class="hljs-number">2.64</span>s] <span class="hljs-type">Exiting</span> <span class="hljs-type">Chain</span> run with output: { <span class="hljs-comment">"output"</span>: <span class="hljs-comment">"I am an AI assistant designed to help answer your questions and assist you with various tasks. I can provide information, perform calculations, conduct online searches, and more. How can I assist you today?"</span> }</pre></div><p id="3624">Here is the second chat:</p><figure id="139d"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*ijql0kGKo6mHCFNc0VUPpg.png"><figcaption>Image by author</figcaption></figure><p id="9a64">The verbose information shows in browser console:</p><div id="1c5a"><pre>[chain/start] [<span class="hljs-number">1</span>:chain:<span class="hljs-type">AgentExecutor</span>] <span class="hljs-type">Entering</span> <span class="hljs-type">Chain</span> run with input: { <span class="hljs-comment">"input"</span>: <span class="hljs-comment">"How old are you?"</span>, <span class="hljs-comment">"chat_history"</span>: [ { <span class="hljs-comment">"lc"</span>: <span class="hljs-number">1</span>, <span class="hljs-comment">"type"</span>: <span class="hljs-comment">"constructor"</span>, <span class="hljs-comment">"id"</span>: [ <span class="hljs-comment">"langchain"</span>, <span class="hljs-comment">"schema"</span>, <span class="hljs-comment">"HumanMessage"</span> ], <span class="hljs-comment">"kwargs"</span>: { <span class="hljs-comment">"content"</span>: <span class="hljs-comment">"Who are you?"</span>, <span class="hljs-comment">"additional_kwargs"</span>: {} } }, { <span class="hljs-comment">"lc"</span>: <span class="hljs-number">1</span>, <span class="hljs-comment">"type"</span>: <span class="hljs-comment">"constructor"</span>, <span class="hljs-comment">"id"</span>: [ <span class="hljs-comment">"langchain"</span>, <span class="hljs-comment">"schema"</span>, <span class="hljs-comment">"AIMessage"</span> ], <span class="hljs-comment">"kwargs"</span>: { <span class="hljs-comment">"content"</span>: <span class="hljs-comment">"I am an AI assistant designed to help answer your questions and assist you with various tasks. I can provide information, perform calculations, conduct online searches, and more. How can I assist you today?"</span>, <span class="hljs-comment">"additional_kwargs"</span>: {} } } ] } console.js:<span class="hljs-number">123</span> [llm/start] [<span class="hljs-number">1</span>:chain:<span class="hljs-type">AgentExecutor</span> > <span class="hljs-number">2</span>:llm:<span class="hljs-type">ChatOpenAI</span>] <span class="hljs-type">Entering</span> <span class="hljs-type">LLM</span> run with input: { <span class="hljs-comment">"messages"</span>: [ [ { <span class="hljs-comment">"lc"</span>: <span class="hljs-number">1</span>, <span class="hljs-comment">"type"</span>: <span class="hljs-comment">"constructor"</span>, <span class="hljs-comment">"id"</span>: [ <span class="hljs-comment">"langchain"</span>, <span class="hljs-comment">"schema"</span>, <span class="hljs-comment">"SystemMessage"</span> ], <span class="hljs-comment">"kwargs"</span>: { <span class="hljs-comment">"content"</span>: <span class="hljs-comment">"You are a helpful AI assistant."</span>, <span class="hljs-comment">"additional_kwargs"</span>: {} } }, { <span class="hljs-comment">"lc"</span>: <span class="hljs-number">1</span>, <span class="hljs-comment">"type"</span>: <span class="hljs-comment">"constructor"</span>, <span class="hljs-comment">"id"</span>: [ <span class="hljs-comment">"langchain"</span>, <span class="hljs-comment">"schema"</span>, <span class="hljs-comment">"HumanMessage"</span> ], <span class="hljs-comment">"kwargs"</span>: { <span class="hljs-comment">"content"</span>: <span class="hljs-comment">"Who are you?"</span>, <span class="hljs-comment">"additional_kwargs"</span>: {} } }, { <span class="hljs-comment">"lc"</span>: <span class="hljs-number">1</span>, <span class="hljs-comment">"type"</span>: <span class="hljs-comment">"constructor"</span>, <span class="hljs-comment">"id"</span>: [ <span class="hljs-comment">"langchain"</span>, <span class="hljs-comment">"schema"</span>, <span class="hljs-comment">"AIMessage"</span> ], <span class="hljs-comment">"kwargs"</span>: { <span class="hljs-comment">"content"</span>: <span class="hljs-comment">"I am an AI assistant designed to help answer your questions and assist you with various tasks. I can provide information, perform calculations, conduct online searches, and more. How can I assist you today?"</span>, <span class="hljs-comment">"additional_kwargs"</span>: {} } }, { <span class="hljs-comment">"lc"</span>: <span class="hljs-number">1</span>, <span class="hljs-comment">"type"</span>: <span class="hljs-comment">"constructor"</span>, <span class="hljs-comment">"id"</span>: [ <span class="hljs-comment">"langchain"</span>, <span class="hljs-comment">"schema"</span>, <span class="hljs-comment">"HumanMessage"</span> ], <span class="hljs-comment">"kwargs"</span>: { <span class="hljs-comment">"content"</span>: <span class="hljs-comment">"How old are you?"</span>, <span class="hljs-comment">"additional_kwargs"</span>: {} } } ] ] } console.js:<span class="hljs-number">132</span> [llm/end] [<span class="hljs-number">1</span>:chain:<span class="hljs-type">AgentExecutor</span> > <span class="hljs-number">2</span>:llm:<span class="hljs-type">ChatOpenAI</span>] [<span class="hljs-number">3.30</span>s] <span class="hljs-type">Exiting</span> <span class="hljs-type">LLM</span> run with output: { <span class="hljs-comment">"generations"</span>: [ [ { <span class="hljs-comment">"text"</span>: <span class="hljs-comment">"As an artificial intelligence, I don't have a birth date or age in the traditional sense. I was created and updated by a team of engineers and data scientists. My capabilities and knowledge are constantly being updated and improved."</span>, <span class="hljs-comment">"message"</span>: { <span class="hljs-comment">"lc"</span>: <span class="hljs-number">1</span>, <span class="hljs-comment">"type"</span>: <span class="hljs-comment">"constructor"</span>, <span class="hljs-comment">"id"</span>: [ <span class="hljs-comment">"langchain"</span>, <span class="hljs-comment">"schema"</span>, <span class="hljs-comment">"AIMessage"</span> ], <span class="hljs-comment">"kwargs"</span>: { <span class="hljs-comment">"content"</span>: <span class="hljs-comment">"As an artificial intelligence, I don't have a birth date or age in the traditional sense. I was created and updated by a team of engineers and data scientists. My capabilities and knowledge are constantly being updated and improved."</span>, <span class="hljs-comment">"additional_kwargs"</span>: {} } }, <span class="hljs-comment">"generationInfo"</span>: { <span class="hljs-comment">"finish_reason"</span>: <span class="hljs-comment">"stop"</span> } } ] ], <span class="hljs-comment">"llmOutput"</span>: { <span class="hljs-comment">"tokenUsage"</span>: { <span class="hljs-comment">"completionTokens"</span>: <span class="hljs-number">45</span>, <span class="hljs-comment">"promptTokens"</span>: <span class="hljs-number">170</span>, <span class="hljs-comment">"totalTokens"</span>: <span class="hljs-number">215</span> } } } console.js:<span class="hljs-number">102</span> [chain/end] [<span class="hljs-number">1</span>:chain:<span class="hljs-type">AgentExecutor</span>] [<span class="hljs-number">3.30</span>s] <span class="hljs-type">Exiting</span> <span class="hljs-type">Chain</span> run with output: { <span class="hljs-comment">"output"</span>: <span class="hljs-comment">"As an artificial intelligence, I don't have a birth date or age in the traditional sense. I was created and updated by a team of engineers and data scientists. My capabilities and knowledge are constantly being updated and improved."</span> }</pre></div><h1 id="2d9b">Build a Chatbot</h1><p id="b9b9">We have seen how LangChain LLMs and ChatModels work. The above demo displays one conversation each time. It illustrates the concept, but the app itself is not a real chatbot yet.</p><p id="9af6"><a href="https://github.com/FredrikOseberg/react-chatbot-kit"><code>react-chatbot-</code>kit<

Options

/a> is installed to implement chatbot:</p><div id="d5f8"><pre>% yarn <span class="hljs-built_in">add</span> react-chatbot-kit</pre></div><p id="dbcc">After the installation, <code>react-chatbot-kit</code> becomes part of <code>dependencies</code> in <code>package.json</code>:</p><div id="e8ac"><pre><span class="hljs-attr">"dependencies"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"decamelize"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^6.0.0"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"langchain"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^0.0.154"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"react"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^18.2.0"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"react-chatbot-kit"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^2.1.2"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"react-dom"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^18.2.0"</span> <span class="hljs-punctuation">}</span></pre></div><p id="0943">Here is the chatbot interface:</p><div id="807f"><pre><span class="hljs-keyword">interface</span> <span class="hljs-title class_">IChatbotProps</span> { <span class="hljs-attr">actionProvider</span>: <span class="hljs-built_in">any</span>; <span class="hljs-attr">messageParser</span>: <span class="hljs-built_in">any</span>; <span class="hljs-attr">config</span>: <span class="hljs-title class_">IConfig</span>; headerText?: <span class="hljs-built_in">string</span>; placeholderText?: <span class="hljs-built_in">string</span>; saveMessages?: <span class="hljs-function">(<span class="hljs-params">ref: <span class="hljs-built_in">any</span></span>) =></span> <span class="hljs-built_in">any</span>; messageHistory?: <span class="hljs-title class_">IMessage</span>[] | <span class="hljs-built_in">string</span>; validator?: <span class="hljs-function">(<span class="hljs-params">input: <span class="hljs-built_in">string</span></span>) =></span> <span class="hljs-title class_">Boolean</span>; runInitialMessagesWithHistory?: <span class="hljs-title class_">Boolean</span>; disableScrollToBottom?: <span class="hljs-built_in">boolean</span>; }</pre></div><p id="cc6a">It has three required props, <code>actionProvider</code>, <code>messageParser</code>, and <code>config</code>. Let’s configure these props with LangChain APIs.</p><p id="82f0">Create <code>src/ActionProvider.tsx</code>, which defines the action <code>generateResponse</code> that sets up and invokes LangChain APIs to generate an output based on the user input.</p><div id="2e35"><pre><span class="hljs-keyword">import</span> <span class="hljs-title class_">React</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>; <span class="hljs-keyword">import</span> { <span class="hljs-title class_">ChatOpenAI</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'langchain/chat_models/openai'</span>; <span class="hljs-keyword">import</span> { initializeAgentExecutorWithOptions, <span class="hljs-title class_">AgentExecutor</span>, } <span class="hljs-keyword">from</span> <span class="hljs-string">'langchain/agents'</span>; <span class="hljs-keyword">import</span> { <span class="hljs-title class_">SerpAPI</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'langchain/tools'</span>; <span class="hljs-keyword">import</span> { <span class="hljs-title class_">Calculator</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'langchain/tools/calculator'</span>;

<span class="hljs-keyword">const</span> <span class="hljs-title function_">ActionProvider</span> = (<span class="hljs-params">{ createChatBotMessage, setState, children }: <span class="hljs-built_in">any</span></span>) => { <span class="hljs-keyword">const</span> executor = <span class="hljs-title class_">React</span>.<span class="hljs-property">useRef</span><<span class="hljs-title class_">AgentExecutor</span>>();

<span class="hljs-title class_">React</span>.<span class="hljs-title function_">useEffect</span>(<span class="hljs-function">() =></span> { <span class="hljs-keyword">const</span> <span class="hljs-title function_">init</span> = <span class="hljs-keyword">async</span> (<span class="hljs-params"></span>) => { <span class="hljs-comment">// define a model</span> <span class="hljs-keyword">const</span> model = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ChatOpenAI</span>({ <span class="hljs-comment">// use OPENAI_API_KEY</span> <span class="hljs-attr">openAIApiKey</span>: <span class="hljs-keyword">import</span>.<span class="hljs-property">meta</span>.<span class="hljs-property">env</span>.<span class="hljs-property">VITE_OPENAI_API_KEY</span>, <span class="hljs-comment">// use GPT 4</span> <span class="hljs-attr">modelName</span>: <span class="hljs-string">'gpt-4'</span>, <span class="hljs-comment">// temperature is a number between 0 and 2, with a default value of </span> <span class="hljs-comment">// 1 or 0.7 depending on the selected model. The temperature is used </span> <span class="hljs-comment">// to control the randomness of the output. When it is set higher, </span> <span class="hljs-comment">// there will be more random outputs.</span> <span class="hljs-attr">temperature</span>: <span class="hljs-number">0</span>, });

  <span class="hljs-comment">// define two tools</span>
  <span class="hljs-keyword">const</span> tools = [
    <span class="hljs-keyword">new</span> <span class="hljs-title class_">Calculator</span>(),
    <span class="hljs-keyword">new</span> <span class="hljs-title class_">SerpAPI</span>(<span class="hljs-keyword">import</span>.<span class="hljs-property">meta</span>.<span class="hljs-property">env</span>.<span class="hljs-property">VITE_SERPAPI_API_KEY</span>),
  ];

  <span class="hljs-comment">// initialize the agent with two tools</span>
  executor.<span class="hljs-property">current</span> = <span class="hljs-keyword">await</span> <span class="hljs-title function_">initializeAgentExecutorWithOptions</span>(
    tools,
    model,
    {
      <span class="hljs-attr">agentType</span>: <span class="hljs-string">'openai-functions'</span>,
      <span class="hljs-comment">// show verbose information in browser console</span>
      <span class="hljs-attr">verbose</span>: <span class="hljs-literal">true</span>,
    }
  );
};

<span class="hljs-title function_">init</span>();

}, []);

<span class="hljs-keyword">const</span> <span class="hljs-title function_">generateResponse</span> = <span class="hljs-keyword">async</span> (<span class="hljs-params">message: <span class="hljs-built_in">string</span></span>) => { <span class="hljs-keyword">if</span> (executor.<span class="hljs-property">current</span>) { <span class="hljs-comment">// agent takes a list of messages as input and returns a message</span> <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> executor.<span class="hljs-property">current</span>.<span class="hljs-title function_">call</span>({ <span class="hljs-attr">input</span>: message }); <span class="hljs-comment">// the message is converted to a string message</span> <span class="hljs-keyword">const</span> botMessage = <span class="hljs-title function_">createChatBotMessage</span>(response.<span class="hljs-property">output</span>);

  <span class="hljs-title function_">setState</span>(<span class="hljs-function">(<span class="hljs-params">prev: <span class="hljs-built_in">any</span></span>) =&gt;</span> ({
    ...prev,
    <span class="hljs-comment">// combine the previous and new messages</span>
    <span class="hljs-attr">messages</span>: [...prev.<span class="hljs-property">messages</span>, botMessage],
  }));
}

};

<span class="hljs-keyword">return</span> ( <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span> {React.Children.map(children, (child) => { return React.cloneElement(child, { actions: { // define the action generateResponse, }, }); })} <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span> ); };

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title class_">ActionProvider</span>;</pre></div><p id="bd61">Create <code>src/MessageParser.tsx</code>, which invokes <code>generateResponse</code> defined in <code>src/ActionProvider.tsx</code> for parsing messages.</p><div id="af06"><pre><span class="hljs-keyword">import</span> <span class="hljs-title class_">React</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> <span class="hljs-title function_">MessageParser</span> = (<span class="hljs-params">{ children, actions }: <span class="hljs-built_in">any</span></span>) => {

<span class="hljs-keyword">const</span> <span class="hljs-title function_">parse</span> = (<span class="hljs-params">message: <span class="hljs-built_in">string</span></span>) => { <span class="hljs-comment">// generateResponse is defined in src/ActionProvider.tsx</span> actions.<span class="hljs-title function_">generateResponse</span>(message); };

<span class="hljs-keyword">return</span> ( <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span>></span> {React.Children.map(children, (child) => { return React.cloneElement(child, { parse, actions: {}, }); })} <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span> ); };

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title class_">MessageParser</span>;</pre></div><p id="3529">Create <code>src/config.ts</code>, which defines the initial message, bot name, and chatbot styles.</p><div id="f840"><pre><span class="hljs-keyword">import</span> { createChatBotMessage } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-chatbot-kit'</span>;

<span class="hljs-keyword">const</span> config = { <span class="hljs-attr">initialMessages</span>: [<span class="hljs-title function_">createChatBotMessage</span>(<span class="hljs-string">Let's talk</span>, {})], <span class="hljs-attr">botName</span>: <span class="hljs-string">'AI Bot'</span>, <span class="hljs-attr">customStyles</span>: { <span class="hljs-attr">botMessageBox</span>: { <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">'royalblue'</span>, }, <span class="hljs-attr">chatButton</span>: { <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">'gray'</span>, }, }, };

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> config;</pre></div><p id="fddb">Modify <code>src/index.css</code> with <code>react-chatbot-kit</code> specific styles:</p><div id="909b"><pre><span class="hljs-selector-pseudo">:root</span> { <span class="hljs-attribute">font-family</span>: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.5</span>; <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">400</span>;

<span class="hljs-attribute">color</span>-scheme: light dark; <span class="hljs-attribute">color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0.87</span>); <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#242424</span>;

<span class="hljs-attribute">font-synthesis</span>: none; <span class="hljs-attribute">text-rendering</span>: optimizeLegibility; -webkit-<span class="hljs-attribute">font-smoothing</span>: antialiased; -moz-osx-<span class="hljs-attribute">font-smoothing</span>: grayscale; -webkit-text-size-adjust: <span class="hljs-number">100%</span>; }

<span class="hljs-selector-tag">body</span> { <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>; <span class="hljs-attribute">display</span>: flex; place-items: flex-start; <span class="hljs-attribute">min-width</span>: <span class="hljs-number">320px</span>; <span class="hljs-attribute">min-height</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">100vh</span> - <span class="hljs-number">40px</span>); }

<span class="hljs-selector-id">#root</span> { <span class="hljs-attribute">display</span>: flex; <span class="hljs-attribute">flex-direction</span>: column; <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>; <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>; }

<span class="hljs-selector-class">.react-chatbot-kit-chat-container</span> { <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>; }

<span class="hljs-selector-class">.react-chatbot-kit-chat-bot-message</span> { <span class="hljs-attribute">width</span>: auto; }</pre></div><p id="c3b2">Modify <code>src/App.tsx</code> to render the <code>Chatbot</code>:</p><div id="ef6e"><pre><span class="hljs-keyword">import</span> <span class="hljs-title class_">Chatbot</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'react-chatbot-kit'</span>; <span class="hljs-keyword">import</span> <span class="hljs-string">'react-chatbot-kit/build/main.css'</span>;

<span class="hljs-keyword">import</span> config <span class="hljs-keyword">from</span> <span class="hljs-string">'./config'</span>; <span class="hljs-keyword">import</span> <span class="hljs-title class_">MessageParser</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'./MessageParser'</span>; <span class="hljs-keyword">import</span> <span class="hljs-title class_">ActionProvider</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'./ActionProvider'</span>;

<span class="hljs-keyword">function</span> <span class="hljs-title function_">App</span>(<span class="hljs-params"></span>) { <span class="hljs-keyword">return</span> ( <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Chatbot</span> <span class="hljs-attr">config</span>=<span class="hljs-string">{config}</span> <span class="hljs-attr">actionProvider</span>=<span class="hljs-string">{ActionProvider}</span> <span class="hljs-attr">messageParser</span>=<span class="hljs-string">{MessageParser}</span> /></span></span> ); }

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title class_">App</span>;</pre></div><p id="f1dd">Execute <code>yarn dev</code>, and we can chat with LangChain AI:</p> <figure id="1d76"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F7ZWfIJH_ePw&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D7ZWfIJH_ePw&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtu" allowfullscreen="" frameborder="0" height="480" width="854"> </div> </div> </figure></iframe></div></div></figure><p id="b360">This demo is located at <a href="https://github.com/JenniferFuBook/ai-chatbot-langchain">this repository</a>.</p><h1 id="9f91">Conclusion</h1><p id="abe6">LangChain is a framework for developing applications powered by large language models (LLMs). It provides the capability to build AI powered systems using configurable chains, which makes it as easy as possible to develop LLM-powered applications</p><p id="7fd3">We have built the examples of LangChain LLMs and ChatModels in a Vite application. With <code>react-chatbot-kit</code>, LangChain is alive as a chatbot, carrying a conversation with human inputs.</p><p id="da64">Do you want to give it a try? A few lines of code for an LLM-powered application?</p><p id="b3e2">In addition, LangSmith is built on top of LangChain for building production-grade LLM applications, and you can continue reading in <a href="https://ai.plainenglish.io/langsmith-is-for-production-grade-ai-applications-30eafa0fa012">this article</a>.</p><p id="1313">Thanks for reading!</p><blockquote id="e36d"><p>Thanks, Ahmet Gyger and Subir Mansukhani, for working with me on Domino products.</p></blockquote><div id="bd22"><pre>Want to Connect?

If you are interested,<span class="hljs-built_in"> check </span>out my directory of web development articles.</pre></div><h1 id="5677">In Plain English</h1><p id="5a12"><i>Thank you for being a part of our community! Before you go:</i></p><ul><li><i>Be sure to <b>clap</b> and <b>follow</b> the writer! 👏</i></li><li><i>You can find even more content at <a href="https://plainenglish.io/"><b>PlainEnglish.io</b></a><b> 🚀</b></i></li><li><i>Sign up for our <a href="http://newsletter.plainenglish.io/"><b>free weekly newsletter</b></a>. 🗞️</i></li><li><i>Follow us on <a href="https://twitter.com/inPlainEngHQ"><b>Twitter</b></a><b>(X</b></i>), <a href="https://www.linkedin.com/company/inplainenglish/"><b><i>LinkedIn</i></b></a>, <a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><b><i>YouTube</i></b></a>, and <a href="https://discord.gg/XxRS92b2"><b><i>Discord</i></b></a><b><i>.</i></b></li></ul></article></body>

Build an AI Chatbot Using LangChain🦜🔗

A detailed guidance on how to use LangChain LLMs and ChatModels in React

Photo by Nicolas Falgetelli on Unsplash

LangChain is a framework for developing applications powered by large language models (LLMs). LLMs is a type of AI algorithm that uses deep learning techniques and massively large data sets to understand, summarize, generate, and predict new content.

LangChain exists to make it as easy as possible to develop LLM-powered applications. It provides the capability to build AI powered systems using chains, which break down problems into smaller sub-tasks. Each chain performs a specific task, such as parsing user input, calling LLMs, and parsing output. It introduces context and memory into OpenAI completions (responses) by creating intermediate steps and chaining commands together.

In this article, we will take a look at the basic functionality of LangChain that supports two types of language models:

  • LLMs: It takes a string as input and returns a string.
  • ChatModels: It takes a list of messages as input and returns a message.

A chatbot is a software application or web interface that aims to mimic human conversation through text or voice interactions. We will build an AI Chatbot Using LangChain.

LangChain LLMs

We use a Vite application to explore LangChain LLMs. The React-based TypeScript project can be created by the following command:

% yarn create vite react-langchain --template react-ts
% cd react-langchain

decamelize is required by langchain. It is a package that converts a camelized string into a lowercased one with a custom separator. For example: unicornRainbow → unicorn_rainbow.

Install both decamelize and langchain.

% yarn add decamelize langchain

After the installation, they become part of dependencies in package.json:

"dependencies": {
  "decamelize": "^6.0.0",
  "langchain": "^0.0.154",
  "react": "^18.2.0",
  "react-dom": "^18.2.0"
}

langchain/llms/openai is a wrapper of OpenAI LLMs, which requires OPENAI_API_KEY to make API calls. The key can be obtained from OpenAI. It is a free account with $18 credit that can be used during the first 3 months. Afterward, it needs to be continued with a paid model.

It is recommended to set it to an environment variable to keep it handy and safe.

% export OPENAI_API_KEY="<your-openai-key>"

Create .env at root to assign the environment value to VITE_OPENAI_API_KEY:

VITE_OPENAI_API_KEY=$OPENAI_API_KEY

We build an app to respond to the user input prompt. The UI is similar to what we did for the next.js GPT app.

Modify src/App.tsx with OpenAI imported from 'langchain/llms/openai':

import React from 'react';
import { OpenAI } from 'langchain/llms/openai';

function App() {
  const [value, setValue] = React.useState<string>('');
  const [prompt, setPrompt] = React.useState<string>('');
  const [result, setResult] = React.useState<string>('');
  const llmRef = React.useRef<OpenAI>();

  const handleInput = React.useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      setValue(e.target.value);
    },
    []
  );

  const handleKeyDown = React.useCallback(
    async (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (!llmRef.current) {
        return;
      }
      if (e.key === 'Enter') {
        setPrompt(value);
        setResult('Loading...');
        // it takes a string as input and returns a string
        setResult(await llmRef.current.predict(value));
        setValue('');
      }
    },
    [value]
  );

  React.useEffect(() => {
    // create an instance for LangChain LLMs
    llmRef.current = new OpenAI({
      // use OPENAI_API_KEY
      openAIApiKey: import.meta.env.VITE_OPENAI_API_KEY,
    });
  }, []);

  return (
    <>
      <div>Please type your prompt</div>
      <input value={value} onChange={handleInput} onKeyDown={handleKeyDown} />
      <div>Prompt: {prompt}</div>
      <div>Result: {result}</div>
    </>
  );
}

export default App;

Modify src/index.css to style the app:

:root {
  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
  line-height: 1.5;
  font-weight: 400;

  color-scheme: light dark;
  color: rgba(255, 255, 255, 0.87);
  background-color: #242424;

  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  display: flex;
  place-items: flex-start;
  min-width: 320px;
  min-height: calc(100vh - 40px);
}

#root {
  display: flex;
  flex-direction: column;
  padding: 20px;
  width: 100%;
  gap: 20px;
}

input {
  width: 80%;
}

Execute yarn dev, and we have the app running.

Image by author

The above screenshot is the completion of the prompt, What is future of AI?

LangChain ChatModels

Our LangChain ChatModels app is composed by the model—ChatOpenAI, the tools — Calculator and SerpApi, and the agent — initializeAgentExecutorWithOptions.

The model — ChatOpenAI

ChatOpenAI is imported from 'langchain/chat_models/openai', which takes a list of messages as input and returns a message.

The tools — Calculator and SerpApi

Calculator is a tool to evaluate mathematical expressions.

SerpApi is a real-time API to access Google search results. In order to use SerpApi, we need to rigister at https://serpapi.com/ to get SERPAPI_API_KEY. The free account allows 100 searches per month.

Similar to OPENAI_API_KEY, we set up SERPAPI_API_KEY as an environment variable.

% export SERPAPI_API_KEY="<your-serpapi-key>"

In .env, assign the environment value to VITE_SERPAPI_API_KEY:

VITE_OPENAI_API_KEY=$OPENAI_API_KEY
VITE_SERPAPI_API_KEY=$SERPAPI_API_KEY

The agent — initializeAgentExecutorWithOptions

In LangChain, an agent has access to a suite of tools and determines which ones to use based on the user input. For multiple tools, the output of one tool can be the input to the next.

In our example, the agent initializeAgentExecutorWithOptions is invoked, which takes two tools, Calculator and SerpApi.

Modify src/App.tsx with ChatOpenAI imported from 'langchain/chat_models/openai':

import React from 'react';
import { ChatOpenAI } from 'langchain/chat_models/openai';
import { initializeAgentExecutorWithOptions, AgentExecutor } from 'langchain/agents';
import { SerpAPI } from 'langchain/tools';
import { Calculator } from 'langchain/tools/calculator';

function App() {
  const [value, setValue] = React.useState<string>('');
  const [prompt, setPrompt] = React.useState<string>('');
  const [result, setResult] = React.useState<string>('');
  const executor = React.useRef<AgentExecutor>();

  const handleInput = React.useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      setValue(e.target.value);
    },
    []
  );

  const handleKeyDown = React.useCallback(
    async (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (!executor.current) {
        return;
      }
      if (e.key === 'Enter') {
        setPrompt(value);
        setResult('Loading...');
        // agent takes a list of messages as input and returns a message
        const response = await executor.current.call({input: value});
        setResult(response.output);
        setValue('');
      }
    },
    [value]
  );

  React.useEffect(() => {
    const init = async () => {

      // define a model
      const model = new ChatOpenAI({
        // use OPENAI_API_KEY
        openAIApiKey: import.meta.env.VITE_OPENAI_API_KEY,
        // use GPT 4
        modelName: 'gpt-4',
        // temperature is a number between 0 and 2, with a default value of 
        // 1 or 0.7 depending on the selected model. The temperature is used 
        // to control the randomness of the output. When it is set higher, 
        // there will be more random outputs.
        temperature: 0,
      });

      // define two tools
      const tools = [
        new Calculator(),
        new SerpAPI(import.meta.env.VITE_SERPAPI_API_KEY),
      ];

      // initialize the agent with two tools
      executor.current = await initializeAgentExecutorWithOptions(
        tools,
        model,
        {
          agentType: 'openai-functions',
          // show verbose information in browser console
          verbose: true,
        }
      );
    };

    init();
  }, []);

  return (
    <>
      <div>Please type your prompt</div>
      <input value={value} onChange={handleInput} onKeyDown={handleKeyDown} />
      <div>Prompt: {prompt}</div>
      <div>Result: {result}</div>
    </>
  );
}

export default App;

Execute yarn dev, and we have the app running.

Here is the first chat:

Image by author

The verbose information shows in browser console:

[chain/start] [1:chain:AgentExecutor] Entering Chain run with input: {
  "input": "Who are you?",
  "chat_history": []
}
console.js:123 [llm/start] [1:chain:AgentExecutor > 2:llm:ChatOpenAI] Entering LLM run with input: {
  "messages": [
    [
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "SystemMessage"
        ],
        "kwargs": {
          "content": "You are a helpful AI assistant.",
          "additional_kwargs": {}
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "HumanMessage"
        ],
        "kwargs": {
          "content": "Who are you?",
          "additional_kwargs": {}
        }
      }
    ]
  ]
}
console.js:132 [llm/end] [1:chain:AgentExecutor > 2:llm:ChatOpenAI] [2.64s] Exiting LLM run with output: {
  "generations": [
    [
      {
        "text": "I am an AI assistant designed to help answer your questions and assist you with various tasks. I can provide information, perform calculations, conduct online searches, and more. How can I assist you today?",
        "message": {
          "lc": 1,
          "type": "constructor",
          "id": [
            "langchain",
            "schema",
            "AIMessage"
          ],
          "kwargs": {
            "content": "I am an AI assistant designed to help answer your questions and assist you with various tasks. I can provide information, perform calculations, conduct online searches, and more. How can I assist you today?",
            "additional_kwargs": {}
          }
        },
        "generationInfo": {
          "finish_reason": "stop"
        }
      }
    ]
  ],
  "llmOutput": {
    "tokenUsage": {
      "completionTokens": 41,
      "promptTokens": 117,
      "totalTokens": 158
    }
  }
}
console.js:102 [chain/end] [1:chain:AgentExecutor] [2.64s] Exiting Chain run with output: {
  "output": "I am an AI assistant designed to help answer your questions and assist you with various tasks. I can provide information, perform calculations, conduct online searches, and more. How can I assist you today?"
}

Here is the second chat:

Image by author

The verbose information shows in browser console:

[chain/start] [1:chain:AgentExecutor] Entering Chain run with input: {
  "input": "How old are you?",
  "chat_history": [
    {
      "lc": 1,
      "type": "constructor",
      "id": [
        "langchain",
        "schema",
        "HumanMessage"
      ],
      "kwargs": {
        "content": "Who are you?",
        "additional_kwargs": {}
      }
    },
    {
      "lc": 1,
      "type": "constructor",
      "id": [
        "langchain",
        "schema",
        "AIMessage"
      ],
      "kwargs": {
        "content": "I am an AI assistant designed to help answer your questions and assist you with various tasks. I can provide information, perform calculations, conduct online searches, and more. How can I assist you today?",
        "additional_kwargs": {}
      }
    }
  ]
}
console.js:123 [llm/start] [1:chain:AgentExecutor > 2:llm:ChatOpenAI] Entering LLM run with input: {
  "messages": [
    [
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "SystemMessage"
        ],
        "kwargs": {
          "content": "You are a helpful AI assistant.",
          "additional_kwargs": {}
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "HumanMessage"
        ],
        "kwargs": {
          "content": "Who are you?",
          "additional_kwargs": {}
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "AIMessage"
        ],
        "kwargs": {
          "content": "I am an AI assistant designed to help answer your questions and assist you with various tasks. I can provide information, perform calculations, conduct online searches, and more. How can I assist you today?",
          "additional_kwargs": {}
        }
      },
      {
        "lc": 1,
        "type": "constructor",
        "id": [
          "langchain",
          "schema",
          "HumanMessage"
        ],
        "kwargs": {
          "content": "How old are you?",
          "additional_kwargs": {}
        }
      }
    ]
  ]
}
console.js:132 [llm/end] [1:chain:AgentExecutor > 2:llm:ChatOpenAI] [3.30s] Exiting LLM run with output: {
  "generations": [
    [
      {
        "text": "As an artificial intelligence, I don't have a birth date or age in the traditional sense. I was created and updated by a team of engineers and data scientists. My capabilities and knowledge are constantly being updated and improved.",
        "message": {
          "lc": 1,
          "type": "constructor",
          "id": [
            "langchain",
            "schema",
            "AIMessage"
          ],
          "kwargs": {
            "content": "As an artificial intelligence, I don't have a birth date or age in the traditional sense. I was created and updated by a team of engineers and data scientists. My capabilities and knowledge are constantly being updated and improved.",
            "additional_kwargs": {}
          }
        },
        "generationInfo": {
          "finish_reason": "stop"
        }
      }
    ]
  ],
  "llmOutput": {
    "tokenUsage": {
      "completionTokens": 45,
      "promptTokens": 170,
      "totalTokens": 215
    }
  }
}
console.js:102 [chain/end] [1:chain:AgentExecutor] [3.30s] Exiting Chain run with output: {
  "output": "As an artificial intelligence, I don't have a birth date or age in the traditional sense. I was created and updated by a team of engineers and data scientists. My capabilities and knowledge are constantly being updated and improved."
}

Build a Chatbot

We have seen how LangChain LLMs and ChatModels work. The above demo displays one conversation each time. It illustrates the concept, but the app itself is not a real chatbot yet.

react-chatbot-kit is installed to implement chatbot:

% yarn add react-chatbot-kit

After the installation, react-chatbot-kit becomes part of dependencies in package.json:

"dependencies": {
  "decamelize": "^6.0.0",
  "langchain": "^0.0.154",
  "react": "^18.2.0",
  "react-chatbot-kit": "^2.1.2",
  "react-dom": "^18.2.0"
}

Here is the chatbot interface:

interface IChatbotProps {
  actionProvider: any;
  messageParser: any;
  config: IConfig;
  headerText?: string;
  placeholderText?: string;
  saveMessages?: (ref: any) => any;
  messageHistory?: IMessage[] | string;
  validator?: (input: string) => Boolean;
  runInitialMessagesWithHistory?: Boolean;
  disableScrollToBottom?: boolean;
}

It has three required props, actionProvider, messageParser, and config. Let’s configure these props with LangChain APIs.

Create src/ActionProvider.tsx, which defines the action generateResponse that sets up and invokes LangChain APIs to generate an output based on the user input.

import React from 'react';
import { ChatOpenAI } from 'langchain/chat_models/openai';
import {
  initializeAgentExecutorWithOptions,
  AgentExecutor,
} from 'langchain/agents';
import { SerpAPI } from 'langchain/tools';
import { Calculator } from 'langchain/tools/calculator';

const ActionProvider = ({ createChatBotMessage, setState, children }: any) => {
  const executor = React.useRef<AgentExecutor>();

  React.useEffect(() => {
    const init = async () => {
      // define a model
      const model = new ChatOpenAI({
        // use OPENAI_API_KEY
        openAIApiKey: import.meta.env.VITE_OPENAI_API_KEY,
        // use GPT 4
        modelName: 'gpt-4',
        // temperature is a number between 0 and 2, with a default value of 
        // 1 or 0.7 depending on the selected model. The temperature is used 
        // to control the randomness of the output. When it is set higher, 
        // there will be more random outputs.
        temperature: 0,
      });

      // define two tools
      const tools = [
        new Calculator(),
        new SerpAPI(import.meta.env.VITE_SERPAPI_API_KEY),
      ];

      // initialize the agent with two tools
      executor.current = await initializeAgentExecutorWithOptions(
        tools,
        model,
        {
          agentType: 'openai-functions',
          // show verbose information in browser console
          verbose: true,
        }
      );
    };

    init();
  }, []);

  const generateResponse = async (message: string) => {
    if (executor.current) {
      // agent takes a list of messages as input and returns a message
      const response = await executor.current.call({ input: message });
      // the message is converted to a string message
      const botMessage = createChatBotMessage(response.output);

      setState((prev: any) => ({
        ...prev,
        // combine the previous and new messages
        messages: [...prev.messages, botMessage],
      }));
    }
  };

  return (
    <div>
      {React.Children.map(children, (child) => {
        return React.cloneElement(child, {
          actions: {
            // define the action
            generateResponse,
          },
        });
      })}
    </div>
  );
};

export default ActionProvider;

Create src/MessageParser.tsx, which invokes generateResponse defined in src/ActionProvider.tsx for parsing messages.

import React from 'react';

const MessageParser = ({ children, actions }: any) => {

  const parse = (message: string) => {
    // generateResponse is defined in src/ActionProvider.tsx
    actions.generateResponse(message);
  };

  return (
    <div>
      {React.Children.map(children, (child) => {
        return React.cloneElement(child, {
          parse,
          actions: {},
        });
      })}
    </div>
  );
};

export default MessageParser;

Create src/config.ts, which defines the initial message, bot name, and chatbot styles.

import { createChatBotMessage } from 'react-chatbot-kit';

const config = {
  initialMessages: [createChatBotMessage(`Let's talk`, {})],
  botName: 'AI Bot',
  customStyles: {
    botMessageBox: {
      backgroundColor: 'royalblue',
    },
    chatButton: {
      backgroundColor: 'gray',
    },
  },
};

export default config;

Modify src/index.css with react-chatbot-kit specific styles:

:root {
  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
  line-height: 1.5;
  font-weight: 400;

  color-scheme: light dark;
  color: rgba(255, 255, 255, 0.87);
  background-color: #242424;

  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  display: flex;
  place-items: flex-start;
  min-width: 320px;
  min-height: calc(100vh - 40px);
}

#root {
  display: flex;
  flex-direction: column;
  padding: 20px;
  width: 100%;
}

.react-chatbot-kit-chat-container {
  width: 100%;
}

.react-chatbot-kit-chat-bot-message {
  width: auto;
}

Modify src/App.tsx to render the Chatbot:

import Chatbot from 'react-chatbot-kit';
import 'react-chatbot-kit/build/main.css';

import config from './config';
import MessageParser from './MessageParser';
import ActionProvider from './ActionProvider';

function App() {
  return (
    <Chatbot
      config={config}
      actionProvider={ActionProvider}
      messageParser={MessageParser}
    />
  );
}

export default App;

Execute yarn dev, and we can chat with LangChain AI:

This demo is located at this repository.

Conclusion

LangChain is a framework for developing applications powered by large language models (LLMs). It provides the capability to build AI powered systems using configurable chains, which makes it as easy as possible to develop LLM-powered applications

We have built the examples of LangChain LLMs and ChatModels in a Vite application. With react-chatbot-kit, LangChain is alive as a chatbot, carrying a conversation with human inputs.

Do you want to give it a try? A few lines of code for an LLM-powered application?

In addition, LangSmith is built on top of LangChain for building production-grade LLM applications, and you can continue reading in this article.

Thanks for reading!

Thanks, Ahmet Gyger and Subir Mansukhani, for working with me on Domino products.

Want to Connect?

If you are interested, check out my directory of web development articles.

In Plain English

Thank you for being a part of our community! Before you go:

Langchain
Chatbots
AI
React
Web Development
Recommended from ReadMedium