Hey there! As I venture into building agentic MEAN apps with LangChain.js, I wanted to take a step back and revisit the core concepts of the MEAN stack. LangChain.js brings AI-powered automation and reasoning capabilities, enabling the development of agentic AI applications such as intelligent chatbots, automated customer support systems, AI-driven recommendation engines, and data analysis pipelines. Understanding how it integrates into the MEAN stack is essential for leveraging its full potential in creating these advanced applications. So, I put together this quick learning blog to share what I’ve revisited.
The MEAN stack is a popular full-stack JavaScript framework that consists of MongoDB, Express.js, Angular, and Node.js. Each component plays a crucial role in developing a seamless web application. Additionally, LangChain.js can be integrated within the MEAN stack to introduce intelligent workflows, AI-driven automation, and enhanced data processing capabilities. In this blog, we’ll break down the MEAN stack architecture and explain how these technologies work together while identifying where LangChain.js fits in.
Angular is a powerful front-end framework used to create dynamic and responsive user interfaces. It runs in the browser and is responsible for rendering UI components and managing user interactions.
Key Features:
To create an Angular project using WebStorm IDE, follow these steps:
ng serve --open
Create or update the app.component.ts file with the following code:
import { Component, OnInit } from '@angular/core';
import { ApiService } from './services/api.service';
import {FormsModule} from '@angular/forms';
import {CommonModule} from '@angular/common';
@Component({
selector: 'app-root',
imports: [FormsModule, CommonModule],
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
userInput: string = ''; // Holds user input
responseMessage: string = ''; // Holds AI response
isLoading: boolean = false; // Show loading state
constructor(private apiService: ApiService) { }
ngOnInit(): void {
}
// Function to send user input to the backend
askQuestion() {
if (!this.userInput.trim()) {
this.responseMessage = 'Please enter a question.';
return;
}
this.isLoading = true; // Show loading indicator
this.responseMessage = '';
this.apiService.askQuery(this.userInput).subscribe(
response => {
this.responseMessage = response.answer; // Extract 'answer' field from JSON
this.isLoading = false;
},
error => {
console.error('Error fetching response:', error);
this.responseMessage = 'Error fetching data. Please try again.';
this.isLoading = false;
}
);
}
}
Add the following code in app.component.html file
<div style="text-align: center; margin-top: 50px;">
<h1>Ask AI a Question</h1>
<input type="text" [(ngModel)]="userInput" placeholder="Enter your question..."
style="width: 60%; padding: 10px; margin: 10px; border-radius: 5px; border: 1px solid #ccc;">
<button (click)="askQuestion()"
style="padding: 10px 20px; background-color: #007BFF; color: white; border: none; border-radius: 5px; cursor: pointer;">
Ask
</button>
<p *ngIf="isLoading" style="color: gray; font-style: italic;">Loading...</p>
<h2 *ngIf="responseMessage">{{ responseMessage }}</h2>
</div>
To enable communication between the Angular frontend and the Express backend, we need to create an api.service.ts file within the src/app/services folder. This service handles HTTP requests to the backend API endpoints.
The apiUrl in the api.service.ts file is set to http://localhost:5000/users. This URL represents the endpoint exposed on the Express server. When the Angular frontend sends a request to this URL, it is received by the users.js file in the Express backend. The server then processes the request and returns a JSON response, which Angular consumes and displays in the UI.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ApiService {
private apiUrl = 'http://localhost:5000/users';
private queryllmUrl = 'http://localhost:5000/queryllm';
constructor(private http: HttpClient) { }
getMessage(): Observable<any> { // Expect JSON, not text
return this.http.get<any>(this.apiUrl);
}
// Function to send user input to the backend
askQuery(question: string): Observable<any> {
return this.http.post<any>(this.queryllmUrl, { question });
}
}
Here is the code for app.config.ts:
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideHttpClient } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideHttpClient()
]
};
Where LangChain.js fits: If you want to incorporate AI-driven suggestions or chatbot interactions in your Angular app, you can make API calls to a LangChain-powered backend (express server) that processes natural language inputs and returns meaningful responses.
Express.js is a minimal and flexible Node.js web framework that is used to build APIs and manage backend logic. It runs on the server and serves as the communication layer between Angular and MongoDB.
When creating a new Express project using WebStorm IDE, the default setup includes two key files: index.js and users.js. The index.js file serves as the main entry point, while users.js handles user-related API requests. For working with LLM, I added third file under routes folder, namely, queryllm.js. Below is an example of how queryllm.js can be structured to generate text response using OpenAI LLM and send back the response to the Angular frontend. Additionally, ensure that the following code exists in app.js on the Express server to properly route requests to queryllm.js:
var queryllmRouter = require("./routes/queryllm");
app.use("/queryllm", queryllmRouter);
This configuration allows Express to correctly handle requests sent to http://localhost:5000/queryllm by forwarding them to users.js. The response from queryllm.js is then sent back to the Angular frontend. The queryllm.js file is found within routes folder.
var express = require("express");
var router = express.Router();
require("dotenv").config();
const { ChatOpenAI } = require("@langchain/openai"); // ✅ Use require instead of import
const model = new ChatOpenAI({
model: "gpt-4o",
temperature: 0, // Adjust as needed
openAIApiKey: process.env.OPENAI_API_KEY,
});
/* POST request to get AI response */router.post("/", async function (req, res) {
try {
const { question } = req.body;
if (!question) {
return res.status(400).json({ error: "Question is required" });
}
const response = await model.invoke(question);
res.json({ answer: response.text });
} catch (error) {
console.error("Error calling OpenAI:", error);
res.status(500).json({ error: "Failed to process request" });
}
});
module.exports = router;
In order for above code to work, make sure to add OPENAI_API_KEY parameter value in “.env” file.
Key Features:
Where LangChain.js fits: LangChain.js can be integrated into Express app thereby creating LLM / Retrieval Augmented Generation (RAG) and agentic AI apps. For example, you can have an Express route that leverages LangChain.js to process user queries and generate responses dynamically.
Once the Express app is created, the following package needs to be installed to interact with MongoDB:
npm install mongoose cors dotenv
Next, create a database in MongoDB. This can be done using a MongoDB client such as MongoDB Compass.
After setting up the database, add the following environment variables in a .env file in the root folder of the Express app:
MONGO_URI=mongodb://localhost:27017/hellolc
PORT=5000
MongoDB is a NoSQL database that stores data in a document-based format (JSON-like structure). It is highly flexible, scalable, and integrates well with JavaScript applications.
Ensure that the following code exists in app.js
to establish a connection between the Express app and MongoDB:
const mongoose = require('mongoose');
require('dotenv').config();
mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
This code reads the MongoDB connection string from the .env file and establishes a connection using Mongoose. If the connection is successful, a message MongoDDB Connected will be logged to the console; otherwise, the error will be logged.
MongoDB is a NoSQL database that stores data in a document-based format (JSON-like structure). It is highly flexible, scalable, and integrates well with JavaScript applications.
Key Features:
Where LangChain.js fits: If you’re working with unstructured or AI-generated data, LangChain.js can store conversation history, embeddings, and metadata in MongoDB for efficient retrieval and further processing.
Node.js is a JavaScript runtime environment that allows developers to run JavaScript code outside the browser. It serves as the backbone of the MEAN stack by running the Express server and connecting the frontend (Angular) with the backend (MongoDB).
Key Features:
Where LangChain.js fits: Node.js can run LangChain.js workflows to integrate AI models, execute reasoning chains, and process user inputs. By setting up LangChain.js in a Node.js backend, your application can include smart decision-making and conversational AI capabilities.
Software-as-a-Service (SaaS) providers have long relied on traditional chatbot solutions like AWS Lex and Google…
Retrieval-Augmented Generation (RAG) is an innovative generative AI method that combines retrieval-based search with large…
The combination of Retrieval-Augmented Generation (RAG) and powerful language models enables the development of sophisticated…
Have you ever wondered how to use OpenAI APIs to create custom chatbots? With advancements…
When building a Retrieval-Augmented Generation (RAG) application powered by Large Language Models (LLMs), which combine…
Last updated: 25th Jan, 2025 Have you ever wondered how to seamlessly integrate the vast…