Skip to main content
Redhat Developers  Logo
  • AI

    Get started with AI

    • Red Hat AI
      Accelerate the development and deployment of enterprise AI solutions.
    • AI learning hub
      Explore learning materials and tools, organized by task.
    • AI interactive demos
      Click through scenarios with Red Hat AI, including training LLMs and more.
    • AI/ML learning paths
      Expand your OpenShift AI knowledge using these learning resources.
    • AI quickstarts
      Focused AI use cases designed for fast deployment on Red Hat AI platforms.
    • No-cost AI training
      Foundational Red Hat AI training.

    Featured resources

    • OpenShift AI learning
    • Open source AI for developers
    • AI product application development
    • Open source-powered AI/ML for hybrid cloud
    • AI and Node.js cheat sheet

    Red Hat AI Factory with NVIDIA

    • Red Hat AI Factory with NVIDIA is a co-engineered, enterprise-grade AI solution for building, deploying, and managing AI at scale across hybrid cloud environments.
    • Explore the solution
  • Learn

    Self-guided

    • Documentation
      Find answers, get step-by-step guidance, and learn how to use Red Hat products.
    • Learning paths
      Explore curated walkthroughs for common development tasks.
    • Guided learning
      Receive custom learning paths powered by our AI assistant.
    • See all learning

    Hands-on

    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.
    • Interactive labs
      Learn by doing in these hands-on, browser-based experiences.
    • Interactive demos
      Click through product features in these guided tours.

    Browse by topic

    • AI/ML
    • Automation
    • Java
    • Kubernetes
    • Linux
    • See all topics

    Training & certifications

    • Courses and exams
    • Certifications
    • Skills assessments
    • Red Hat Academy
    • Learning subscription
    • Explore training
  • Build

    Get started

    • Red Hat build of Podman Desktop
      A downloadable, local development hub to experiment with our products and builds.
    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.

    Download products

    • Access product downloads to start building and testing right away.
    • Red Hat Enterprise Linux
    • Red Hat AI
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat Developer Toolset

    References

    • E-books
    • Documentation
    • Cheat sheets
    • Architecture center
  • Community

    Get involved

    • Events
    • Live AI events
    • Red Hat Summit
    • Red Hat Accelerators
    • Community discussions

    Follow along

    • Articles & blogs
    • Developer newsletter
    • Videos
    • Github

    Get help

    • Customer service
    • Customer support
    • Regional contacts
    • Find a partner

    Join the Red Hat Developer program

    • Download Red Hat products and project builds, access support documentation, learning content, and more.
    • Explore the benefits

A quick start with Large Language Models and Node.js using Podman AI lab

January 10, 2025
Michael Dawson
Related topics:
Artificial intelligenceData scienceDeveloper productivityDeveloper toolsNode.jsProgramming languages & frameworksRuntimes
Related products:
Podman DesktopRed Hat build of Node.jsRHEL UBI

    Integrating large language models into applications is an important skill for today's developers. In this blog post we will take you through one of the quickest ways to start experimenting and using large language models with Node.js. We will do this by working through the Node.js chatbot example available In Podman AI lab.

    Podman AI lab which integrates with Podman desktop provides everything you need to start developing Node.js applications which integrate large language models and package the components in containers. It includes:

    • A model server to run the large language model
    • The tools need to build and run containers
    • Recipes to get started quickly

    Podman desktop provides tooling with a nice graphical interface to build and run containers on Windows, Mac and Linux. To get started first download and install Podman desktop from the instructions on podman-desktop.io.

    Once you start Podman desktop you should see a suggestion to install Podman AI lab as follows:

    Picture of initial screen for podman desktop after initial description

    Install the Podman AI lab extension as suggested. If the suggestion does not appear automatically, you can install the extension by going to the extension page (the puzzle piece in the navigation bar on the left) and then search for Podman AI lab on the Catalogue tab.

    You should now see an additional icon in the navigation bar on the left:

    Picture of podman desktop left navigation bar with Podman AI lab icon circled.

    Podman AI lab Recipes

    Now that you have Podman AI lab installed you can look at the available recipes. Select the Podman AI lab icon in the left navigation bar and then select Recipes Catalog under AI APPS. This screenshot shows the recipes available Jan 10 2025. As a heads up we are working on adding additional Node.js recipes so you might want to check the available list occasionally.

    Pictures of recipes available in podman desktop on Jan 10 2025

    Each recipe provides an easy way to start building an application in a particular category, along with starter code that will let you run, modify and experiment with that application.

    Node.js based Chatbot Recipe

    The Node.js chatbot recipe lets you quickly get started with an application that integrates a chatbot. Running the recipe will result in two deployed containers:

    • A container running a large large language model (Granite by default)
    • A container running a Next.js based application using Langchain.js and React Chatbotify that implements the LLM enabled chatbot.

    Running the Recipe

    To run the recipe select "More details" on the tile for the recipe,  "start" on the main page for the recipe and then "Start Node.js based Chatbot recipe" on the start recipe page:

     

    Picture of page to start node.js chatbox recipe

    Note that while Granite is used by default you can download and choose other models if you would like to experiment with other models to see how they perform.

    This will build the containers for the application and start them. It may take a little while as it builds the containers. Once started you should see something like this:

    Picture of Node.js Chatbot recipe start page once started.

    We can go to the application from the "Open details" link to get to the summary of the running recipes and then use the link (the box with arrow on the right hand side) to get to the main page of the application:

    Picture of running recipes page with link to go to main application page circled for the Node.js chatbot recipe

    After opening the link you should see something like this:

    Picture of running Node.js chatbot application in browswer

    You can go ahead an interact with the chatbot by asking questions and seeing the responses.

    Looking at the Running Containers

    Now that we've played with the application lets looks at the containers which are running the application. Podman desktop is great because it gives us an easy way to start, run and inspect containers. Switch to the containers view. You should see 2 containers for the application, one with "nodejs-chat-podified" in the name and one with a more random name, in our case it was "clever_herschel":

    Picture of Podman desktop container view with the container for the application and the container running llama_cpp circled.

    The more random named container is running the large language model using llamacpp_python. The one with "nodejs-chat-podified" is running the Next.js application. Podman has built and started the two containers for you and then ran them passing the information required for the application to use the the large language model. This is driven in part through the information provide by one of the files in the recipe which is in ai-lab-yaml:

    version: v1.0
    application:
      type: language
      name: ChatBot_nodejs
      description: Chat with a model service in a web frontend.
      containers:
        - name: llamacpp-server
          contextdir: ../../../model_servers/llamacpp_python
          containerfile: ./base/Containerfile
          model-service: true
          backend:
            - llama-cpp
          arch:
            - arm64
            - amd64
          ports:
            - 8001
          image: quay.io/ai-lab/llamacpp_python:latest
        - name: nodejs-chat-app
          contextdir: app
          containerfile: Containerfile
          arch:
            - arm64
            - amd64
          ports:
            - 8501
          image: quay.io/ai-lab/chatbot-nodejs:latest

    Podman desktop also makes it easy to inspect the containers and view the logs. For example, we can take a look at the application log:

    Picture of Node.js application logs

    This makes it a lot easier to investigate what the application in the container is doing if you have problems. Go ahead and poke around to explore the information that is easily available.

    Looking at the Recipe

    The Node.js chatbot recipe is part of the AI lab recipes. Each recipe includes the same main ingredients: models, model servers, and AI interfaces. These are combined in various ways, packaged as container images, and can be run as pods with Podman. The recipes are grouped into different categories based on the AI functions. The current recipe groups are audio, computer vision, multimodal, and natural language processing.

    The Node.js chatbot recipe is under the "natural language processing" group - nodejs-chatbot.

    The following article dives into the details of recipes and the different ingredients that they contain - AI Lab Recipes. We recommend that you read through that article before looking at the ingredients in the nodejs-chatbot recipe as it will help you understand the common ingredients and let you focus on the Node.js application specifics as you go through the nodejs-chatbot recipe.

    As mentioned before, the recipe for the Node.js chatbot application builds and deploys 2 containers, one for the large language model served by llama_cpp and one for the Next.js based application.

    You can go to the recipe in GitHub () but even easier you can open it in VScode easily from the Start page for the recipe:

    Picture of start page for recipe with "Open in VSCode" button circled.

     If you edit the copy that is opened, you can then easily redeploy the application with your updates through the running recipes page.

    Looking at the Application

    The application is a fairly straight forward Next.js application with React Chatbotify in the front end and LangChain.js being used in the back end to connect to the large language model server.

    The front end (app/page.js) is as follows:

    'use client';
    import io from 'socket.io-client';
    import { lazy, useEffect, useState } from "react";
    const Chatbot = lazy(() => import("react-chatbotify"));
    
    function App() {
      /////////////////////////////////////
      // chatbotify flow definition
      const flow = {
        start: {
          message: 'How can I help you ?',
          path: 'get_question',
        },
        get_question: {
          message: async (params) => {
           return await answerQuestion(params.userInput);
    
          },
          path: 'get_question'
        },
      };
    
      /////////////////////////////////////
      // uses socket.io to relay question to back end
      // service and return the answer  
      async function answerQuestion(question) {
        return new Promise((resolve, reject) => {
          socket.emit('question', question);
          socket.on('answer', (answer) => {
            resolve(answer);
          });
        });
      };
    
      /////////////////////////////////////
      // react/next plubming
      const [isLoaded, setIsLoaded] = useState(false);
      const [socket, setSocket] = useState(undefined);
      useEffect(() => {
        setIsLoaded(true);
    
        // Create a socket connection
        const socket = io({ path: '/api/socket.io'});
        setSocket(socket);
    
        // Clean up the socket connection on unmount
        return () => {
            socket.disconnect();
        };
      }, [])
    
      return (
        <> 
          { isLoaded && (
            <Chatbot options={{theme: {embedded: true, showFooter: false},
                               header: {title: 'chatbot - nodejs'},
                               chatHistory: {storageKey: 'history'}}} flow={flow}/>
          )}
        </>
      );
    };
    
    export default App;

    The front end communicates with the back-end through WebSockets. The backend use LangChain.js to send the questions to the large language model being served with llama_cpp and then returns the response to the front end through the WebSocket. The WebSocket id is used as a session key so that history is maintained separately for each client connected to the chatbot.  The backend is as follows (pages/api/socket.io/index.js) is as follows:

    import { Server } from 'socket.io';
    import { RunnableWithMessageHistory } from '@langchain/core/runnables';
    import { ChatPromptTemplate, MessagesPlaceholder } from '@langchain/core/prompts';
    import { ChatMessageHistory } from 'langchain/stores/message/in_memory';
    import { ChatOpenAI } from '@langchain/openai';
    
    const model_service = process.env.MODEL_ENDPOINT ||
                          'http://localhost:8001';
    
    /////////////////////////////////////
    // Function to check if/which LLM is available
    async function checkingModelService() {
      let server;
      const startTime = new Date();
      while (true) {
        let result = await fetch(`${model_service}/v1/models`);
        if (result.status === 200) {
          server = 'Llamacpp_Python';
          break;
        };
    
        await new Promise(x => setTimeout(x, 100));
      };
    
      const endTime = new Date();
      return { details: `${server} Model Service Available\n` + 
                        `${(endTime.getSeconds() - startTime.getSeconds()) } seconds`,
               server: server
             };
    };
    
    /////////////////////////////////////
    // Functions to interact with the LLM
    
    let chainWithHistory;
    const sessions = {};
    
    function createLLM(server) {
      if (server === 'Llamacpp_Python') {  
        const llm = new ChatOpenAI(
          { openAIApiKey: 'EMPTY' },
          { baseURL: `${model_service}/v1` }
        );
        return llm;
      } else {
        throw new Error('Unknown llm');
      };
    };
    
    function createChain(server) {
      const prompt = ChatPromptTemplate.fromMessages([
        [ 'system',
          'You are a helpful chat agent. ' +
          'Answer any questions asked but if you are not certain of the answer say so. ' +
          'Answer only with plain answer do not include any annotations or qualifiers.'
        ],
        new MessagesPlaceholder('history'),
        [ 'human', '{input}' ]
      ]);
    
      const llm = createLLM(server);
      const chain = prompt.pipe(llm);
    
      chainWithHistory = new RunnableWithMessageHistory({
        runnable: chain,
        getMessageHistory: (sessionId) => {
          if (sessions[sessionId] === undefined) {
            sessions[sessionId] = new ChatMessageHistory();
          }
          return sessions[sessionId];
        },
        inputMessagesKey: 'input',
        historyMessagesKey: 'history',
      });
    };
    
    async function answerQuestion(question, sessionId) {
      const result = await chainWithHistory.invoke(
        { input: question },
        { configurable: { sessionId: sessionId }}
      );
      return result.content;
    };
    
    /////////////////////////////////////
    // socket.io handler that provides the service to which
    // the front end can connect to in order to request
    // answers to questions
    const SocketHandler = async (req, res) => {
      if (res.socket.server.io) {
      } else {
        console.log('Socket is initializing');
        const io = new Server(res.socket.server, { path: '/api/socket.io'});
        res.socket.server.io = io;
    
        io.on('connection', (socket) => {
          socket.on('close', () => {
            sessions[socket.id] = undefined;
          });
          socket.on('question', async (question) => {
            const answer = await answerQuestion(question, socket.id);
            socket.emit('answer', answer);
          });
        });
    
        const result = await checkingModelService();
        console.log(result.details);
        createChain(result.server);
      };
      res.end();
    };
    
    export default SocketHandler;

    This section in particular lets the recipe provide the application with then endpoint for the model server running in the other container:

    const model_service = process.env.MODEL_ENDPOINT ||
                          'http://localhost:8001';

    Running the Application for Development

    The easiest way to run the application is the way we've shown you through Podman AI Lab and podman desktop. While this is great to get up and running, it's probably not what you want to do when you are in the update/test development cycle. In that case it can be useful to use Podman AI Lab to start the recipe, but then start another instance of the application from the command line. You can do this by:

    git clone https://github.com/containers/ai-lab-recipes.git
    cd  ai-lab-recipes/recipes/natural_language_processing/chatbot-nodejs/app
    npm install
    npm run dev

    That will get the application up and running, but the application won't be able to connect to the model server. To fix that use Podman desktop to enter the terminal for the application container that was deployed by the recipe and find the value for MODEL_ENDPOINT by running:

    echo $MODEL_ENDPOINT

    Once you have the model endpoint, stop your local copy of the application and run (or set MODEL_ENDPOINT in the environment for windows):

    export MODEL_ENPOINT=YYYY

    were YYYY is what was displayed when you ran `echo $MODEL_ENDPOINT`.

    You can now restart your local copy of the application and it should connect to the model server. You should then be able to modify the Next.js application and it should be automatically rebuilt/deployed. By default the local copy of the application will be available at http://localhost:8501.

    Wrapping Up

    We hope this post has given you a good introduction to Podman AI Lab, recipes and in particular the Node.js chatbot recipe. You should now be ready to experiment by extending the recipe to build your own application and to build it into containers using the ingredients provided by the recipe.

    If you want to learn more about developing with large language models and Node.js you can look at the articles shared in https://developers.redhat.com/blog/2024/11/20/essential-ai-tutorials-nodejs-developers.

    If you want to learn more about what the Red Hat Node.js team is up to in general check these out:

    • https://developers.redhat.com/topics/nodejs
    • https://developers.redhat.com/topics/nodejs/ai
    • https://developers.redhat.com/e-books/developers-guide-nodejs-reference-architecture
    • https://github.com/nodeshift/nodejs-reference-architecture

     

     

     

    Last updated: January 24, 2025
    Disclaimer: Please note the content in this blog post has not been thoroughly reviewed by the Red Hat Developer editorial team. Any opinions expressed in this post are the author's own and do not necessarily reflect the policies or positions of Red Hat.

    Recent Posts

    • Tekton joins the CNCF as an incubating project

    • Federated identity across the hybrid cloud using zero trust workload identity manager

    • Confidential virtual machine storage attack scenarios

    • Introducing virtualization platform autopilot

    • Integrate zero trust workload identity manager with Red Hat OpenShift GitOps

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Platforms

    • Red Hat AI
    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Build

    • Developer Sandbox
    • Developer tools
    • Interactive tutorials
    • API catalog

    Quicklinks

    • Learning resources
    • E-books
    • Cheat sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site status dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2026 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Chat Support

    Please log in with your Red Hat account to access chat support.