ad
ad
Topview AI logo

Build A Modern AI RAG application with Next.js 14 + LangChain

Howto & Style


Introduction

In this article, we will explore how to create a modern RAG (Retrieval-Augmented Generation) application utilizing Next.js 14 and LangChain. This application will allow you to build a custom chat interface that answers user questions based on your personalized data sources, specifically focusing on PDF documents as the primary data source.

Getting Started

To kick off, we’ll set up an API route named loadDocuments. This route will be responsible for loading documents from your data source and storing them in a vector database. It is essential to understand the data structure and how documents can be loaded into the system.

Loading Documents from Local Storage

The simplest way to load a PDF document is via LangChain's PDFLoader. Here are the general steps:

  1. Install Required Packages: Before diving into coding, ensure you have installed the necessary packages.

  2. Setup PDF Loader: Use the following code snippet to initialize the loader:

    const loader = new PDFLoader('path/to/your/document.pdf');
    

For multiple PDF documents stored locally, you’d utilize the MultiPDFLoader function:

const loader = new MultiFileLoader(['path/to/doc1.pdf', 'path/to/doc2.pdf'], pdfLoaderHandler);

Loading External PDF Documents

If your PDF files are stored externally (for instance, in a database), you would utilize the WebPDFLoader. This approach requires reading the file data as binary data (blob):

const blob = await readFromDatabase(); // Function to fetch blob from your database
const loader = new WebPDFLoader(blob);

However, for multiple PDFs from the database, you would read and load each file, storing them in an array.

Document Splitting and Preprocessing

Once you have your documents loaded, you’ll want to split them into manageable chunks. You can use LangChain's RecursiveTextSplitter to manage the size of chunks and how they overlap. For example, splitting into chunks of 1000 characters with an overlap of 200 characters:

const textSplitter = new RecursiveTextSplitter(( chunkSize: 1000, chunkOverlap: 200 ));
const chunks = textSplitter.splitDocuments(docs);

It's important to sanitize the content to prevent any parsing errors, particularly with characters such as backslashes.

Setting Up the Vector Store

Next, you will need to choose an embedding model and create a vector store for managing your embeddings. If you choose to use the Zeta vector search, ensure you set up the associated database and table:

const zetaClient = new ZetaClient();
const vectorStore = new ZetaVectorStore(zetaClient, 'your-table-name');

Finally, add your documents to the vector store using the addDocuments function.

Creating the Chatbot API

After setting up your document loading and storage, it’s time to create the chatbot API, termed chatbot. This API will handle user interactions and generate responses using a language model.

Function Implementation

In the chatbot route, define necessary constants and helper functions. Key tasks include:

  1. User Authorization: Check if a user is authorized to perform actions.
  2. Message Handling: Structuring messages and formatting them for the language model.
  3. Creating the Prompt: Set up a prompt for the AI model specifying rules for question answering.

This could be accomplished like so:

const promptTemplate = "You're an assistant for Question Answering tasks. Use only the retrieved context and history to answer questions.";

Model Setup and Response Handling

Instantiate your language model, create a retriever from your vector store, and define a retrieval chain. This chain will leverage both your question history and current user inquiries to fetch necessary documents and generate responses.

Streaming Responses

Wrap your output using a streaming text response to handle the real-time chat interface. This allows for a seamless user experience as responses are generated.

Building the User Interface

With the backend API set up, we move to the UI aspect. Using React, create a chat interface:

  1. Message Handling Hooks: Utilize hooks to track the current chat state and handle user inputs.
  2. Automatic Scrolling: Implement functionality for automatically scrolling down as new messages are added.
  3. Styling for Messages: Distinguish between user messages and AI responses through conditional styling.

Here is a simplified example for rendering messages:

messages.map((message, index) => (
   <div key=(index) className=(message.role === 'user' ? 'user-message' : 'ai-message')>
      <span>(message.role)</span>
      <p>(message.content)</p>
   </div>
))

Finally, remember to create a form for user input and submit their queries, linking everything to the chatbot API for interaction.

Running Your Application

To see it in action, start your Next.js application using:

npm run dev

Before using the chatbot, ensure to run the loadDocuments function to populate the vector database. Navigate to /chatbot, where you should see your chat interface ready for interaction.

Conclusion

By following the steps outlined in this article, you can establish a custom RAG application using Next.js and LangChain. This interface allows users to query specific information based on the data you provide, demonstrating the powerful capabilities of combining these technologies.


Keywords

RAG, Next.js, LangChain, API route, PDF documents, vector database, chatbot, user messages, AI responses, embedding model.

FAQ

Q1: What is RAG? A1: RAG stands for Retrieval-Augmented Generation, which combines information retrieval with natural language generation to produce contextually relevant responses.

Q2: How do I load PDF documents into my application? A2: You can use PDFLoader for local documents or WebPDFLoader for external PDFs. For multiple documents, MultiFileLoader can be employed.

Q3: What is a vector store? A3: A vector store is a type of database specifically designed to manage and retrieve vectors generated from document embeddings, making it optimized for searching and analyzing large datasets.

Q4: Can the chatbot answer questions outside its knowledge base? A4: No, the current setup restricts the chatbot to answering questions based solely on the custom data provided through your document sources.

Q5: Is it possible to add more data sources later? A5: Yes, you can extend your application by integrating additional data sources and updating the vector store with new documents as needed.