PDF Chat Bot

Script for the PDF Chat Bot development

9/29/20246 min read

### Complete HTML with JavaScript

Here's a complete HTML page with your chatbot section and the necessary JavaScript code integrated:

```html

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Chatbot Integration</title>

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">

<style>

/* Basic styling for demonstration */

body {

font-family: Arial, sans-serif;

margin: 0;

padding: 20px;

background-color: #f4f4f4;

}

.chatbot-section {

display: flex;

flex-direction: column;

align-items: center;

}

.chatbot-card {

background-color: #fff;

border-radius: 8px;

box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);

width: 400px;

padding: 20px;

position: relative;

}

.chatbot-header {

display: flex;

align-items: center;

justify-content: space-between;

margin-bottom: 20px;

}

.messages {

max-height: 300px;

overflow-y: auto;

margin-bottom: 20px;

}

.bot, .user {

padding: 10px;

border-radius: 5px;

margin: 5px 0;

}

.bot {

background-color: #e0e0e0;

text-align: left;

}

.user {

background-color: #4caf50;

color: white;

text-align: right;

}

#spinner {

display: none; /* Initially hidden */

text-align: center;

margin: 10px 0;

}

#box-container {

display: none; /* Initially hidden */

flex-wrap: wrap;

}

form {

display: flex;

justify-content: space-between;

}

input[type="text"] {

flex: 1;

padding: 10px;

border-radius: 5px;

border: 1px solid #ccc;

margin-right: 10px;

}

button {

padding: 10px;

border-radius: 5px;

background-color: #4caf50;

color: white;

border: none;

cursor: pointer;

}

button:hover {

background-color: #45a049;

}

</style>

</head>

<body>

<div class="chatbot-section">

<div class="chatbot-content">

<div class="left-content">

<div class="process-content">

<h4 class="process-content-title mb-25">Powering Your Business with IntelliBots</h4>

<p class="mb-25">Integrate tools such as IntelliBots to make data-driven decisions for continuous improvement.</p>

<div class="checklist">

<ul>

<li><i class="fas fa-check"></i> Faster Response Time</li>

<li><i class="fas fa-check"></i> Chat Prompt Generation</li>

<li><i class="fas fa-check"></i> Safe and Private</li>

</ul>

</div>

<div class="btn-wrap">

<a href="about.html" class="th-btn style-radius">Get Started Now</a>

</div>

</div>

</div>

<div class="chatbot-card">

<div class="chatbot-header">

<img src="assets/img/logo-white.svg" alt="Logo" class="chatbot-logo" />

<h4>Chat with us!</h4>

</div>

<div class="chatbot-body">

<!-- Initial Bot Message -->

<div class="messages" id="messages">

<div class="bot">Hello! How can I help you today?</div>

</div>

<div id="spinner" class="spinner">Loading...</div>

<div id="box-container" class="box-container"></div>

</div>

<form id="chat-form">

<input type="text" id="user-input" placeholder="Type your message..." autocomplete="off" required />

<button type="submit">Send</button>

</form>

</div>

</div>

</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.9.359/pdf.min.js"></script>

<script>

let promptsGenerated = false; // Flag to track if prompts have been generated

let selectedPrompt = ""; // Store the currently selected prompt

let originalQuestion = ""; // Variable to store the first user input

let pdfData = []; // Array to hold Q&A from PDF

let pdfLoaded = false; // Flag to track PDF loading status

// Load PDF and extract Q&A

async function loadPdfData(pdfPath) {

try {

const loadingTask = pdfjsLib.getDocument(pdfPath);

const pdf = await loadingTask.promise;

for (let i = 1; i <= pdf.numPages; i++) {

const page = await pdf.getPage(i);

const textContent = await page.getTextContent();

const text = textContent.items.map(item => item.str).join(" ");

pdfData.push(text); // Store page text

}

pdfLoaded = true; // Mark PDF as loaded

console.log("PDF data loaded successfully:", pdfData); // Log the loaded PDF data for debugging

} catch (error) {

console.error("Error loading PDF:", error); // Error handling

}

}

// Initialize PDF loading

loadPdfData('C:/Webapp-Development/sassa/assets/document/book1-for-CD.pdf'); // Specify the path to your PDF document

// Event listener for the chat form submission

document.getElementById("chat-form").addEventListener("submit", async function (e) {

e.preventDefault(); // Prevent default form submission behavior

const userInput = document.getElementById("user-input").value.trim(); // Get user input

// Ensure there is either user input or a selected prompt

if (!userInput && !selectedPrompt) return;

if (!originalQuestion) {

originalQuestion = userInput; // Store the first user input

}

displayMessage(userInput || selectedPrompt, true); // Display user input or selected prompt

document.getElementById("user-input").value = ""; // Clear the input field

document.getElementById("spinner").style.display = "block"; // Show loading spinner

// Ensure PDF data has been loaded before checking for answers

if (!pdfLoaded) {

displayMessage("PDF data is still loading. Please try again.", false);

document.getElementById("spinner").style.display = "none"; // Hide loading spinner

return;

}

const pdfResponse = getPdfAnswer(userInput); // Check for answer in the PDF

const isInitialPrompt = !promptsGenerated; // Determine if it's the initial query

if (pdfResponse) {

// If an answer was found in the PDF

displayMessage(pdfResponse, false); // Display PDF answer

} else {

// No answer found in PDF, query the Gemini API

const queryToSend = userInput

? userInput // Use the current user input if it exists

: `${originalQuestion} in the context of ${selectedPrompt}`; // If no current input, use original question with selected prompt

const botMessage = await fetchResponse(queryToSend, isInitialPrompt); // Fetch the bot's response

if (isInitialPrompt) {

// If it's the initial prompt, generate prompt boxes

const promptLines = botMessage

.split("\n")

.map((line) => line.trim())

.map((line) => line.replace(/^\s*[-–]\s*/, "")); // Clean leading dashes

displayPromptBoxes(promptLines);

promptsGenerated = true; // Set the flag to true after generating prompts

} else {

// For subsequent queries, format and display the response

const formattedResponse = formatContent(botMessage);

displayMessage(formattedResponse, false); // Display the formatted bot message

}

}

document.getElementById("spinner").style.display = "none"; // Hide loading spinner after processing

});

// Function to check for answers in the PDF data

function getPdfAnswer(userInput) {

const lowerCaseInput = userInput.toLowerCase();

for (const page of pdfData) {

// Simple keyword matching

if (page.toLowerCase().includes(lowerCaseInput)) {

return `Answer from PDF: ${page}`; // Return the found answer

}

}

return null; // No answer found in PDF

}

// Function to display messages

function displayMessage(message, isUser) {

const messagesDiv = document.getElementById("messages");

const messageDiv = document.createElement("div");

messageDiv.className = isUser ? "user" :

"bot"; // Set class based on sender

messageDiv.textContent = message; // Set message text

messagesDiv.appendChild(messageDiv); // Append message to chat

messagesDiv.scrollTop = messagesDiv.scrollHeight; // Scroll to bottom

}

// Function to fetch response from the API

async function fetchResponse(query, isInitialPrompt) {

try {

const response = await fetch("http://localhost:3000/api/chat", {

method: "POST",

headers: { "Content-Type": "application/json" },

body: JSON.stringify({ query })

});

if (!response.ok) {

throw new Error("Network response was not ok."); // Handle response errors

}

const data = await response.json(); // Parse JSON response

return data.reply; // Return the reply from the API

} catch (error) {

console.error("Error fetching response:", error); // Error handling

return "Sorry, I couldn't get a response."; // Fallback message

}

}

// Function to format content before display

function formatContent(content) {

return content.trim().replace(/\n/g, "<br>"); // Format new lines

}

// Function to display prompt boxes based on bot response

function displayPromptBoxes(prompts) {

const boxContainer = document.getElementById("box-container");

boxContainer.style.display = "flex"; // Show the box container

boxContainer.innerHTML = ""; // Clear existing boxes

prompts.forEach((prompt) => {

const box = document.createElement("div");

box.className = "prompt-box"; // Set class for styling

box.textContent = prompt; // Set prompt text

box.onclick = () => {

selectedPrompt = prompt; // Set selected prompt

displayMessage(prompt, true); // Display the selected prompt

boxContainer.style.display = "none"; // Hide prompt boxes

};

boxContainer.appendChild(box); // Append box to container

});

}

</script>

</body>

</html>

```

# Key Features and Enhancements:

1. User Input Handling: The chatbot captures user inputs and displays them as messages in the chat area.

2. PDF Integration: The chatbot can retrieve answers from a specified PDF file.

3. Prompt Generation: If the chatbot cannot find an answer in the PDF, it will call an API to generate relevant responses.

4. Dynamic Interface: The messages dynamically update, and a loading spinner indicates when the bot is processing user input.

5. Styling: Basic styles have been included for better visuals.

# Instructions to Use:

- Ensure your PDF path is correct in the `loadPdfData` function.

- Replace the API endpoint (`http://localhost:3000/api/chat`) with your actual endpoint for fetching responses.

- Adjust styles as needed to fit your overall design.

  • Modular Functions: The code is broken down into more modular functions to handle different responsibilities, making it easier to read and maintain.

  • Error Handling: Improved error handling during PDF loading and API calls to inform the user of any issues that arise.

  • User Experience Enhancements: The message display logic is simplified to enhance clarity, and the loading spinner is only shown when processing requests.

  • Structured Bullet Points: Bullet points are constructed more logically and cleaned up effectively before rendering.

This setup should provide a solid foundation for your chatbot functionality! Let me know if you need further modifications or additional features.