PDF Chat Bot
Script for the PDF Chat Bot development
### 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.