|
|
<!DOCTYPE html> |
|
|
<html lang="en" class="dark"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>AI Mentor Bot</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> |
|
|
<script src="https://unpkg.com/feather-icons"></script> |
|
|
<script> |
|
|
tailwind.config = { |
|
|
darkMode: 'class', |
|
|
theme: { |
|
|
extend: { |
|
|
colors: { |
|
|
primary: { |
|
|
500: '#d946ef', |
|
|
}, |
|
|
secondary: { |
|
|
500: '#eab308', |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
</script> |
|
|
<style> |
|
|
.chat-container { |
|
|
height: calc(100vh - 180px); |
|
|
} |
|
|
.typing-indicator::after { |
|
|
content: '...'; |
|
|
animation: typing 1.5s infinite; |
|
|
} |
|
|
@keyframes typing { |
|
|
0% { content: '.'; } |
|
|
33% { content: '..'; } |
|
|
66% { content: '...'; } |
|
|
} |
|
|
.gradient-bg { |
|
|
background: linear-gradient(135deg, rgba(217, 70, 239, 0.2) 0%, rgba(234, 179, 8, 0.2) 100%); |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="bg-gray-900 text-gray-100"> |
|
|
<div class="flex flex-col h-screen"> |
|
|
|
|
|
<header class="bg-gray-800 p-4 shadow-lg"> |
|
|
<div class="container mx-auto flex items-center justify-between"> |
|
|
<div class="flex items-center space-x-3"> |
|
|
<i data-feather="cpu" class="text-primary-500 w-8 h-8"></i> |
|
|
<h1 class="text-2xl font-bold bg-gradient-to-r from-primary-500 to-secondary-500 bg-clip-text text-transparent"> |
|
|
AI Mentor Bot |
|
|
</h1> |
|
|
</div> |
|
|
<div class="flex items-center space-x-4"> |
|
|
<button id="themeToggle" class="p-2 rounded-full bg-gray-700 hover:bg-gray-600 transition"> |
|
|
<i data-feather="moon" class="w-5 h-5"></i> |
|
|
</button> |
|
|
<button class="p-2 rounded-full bg-gray-700 hover:bg-gray-600 transition"> |
|
|
<i data-feather="settings" class="w-5 h-5"></i> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</header> |
|
|
|
|
|
|
|
|
<main class="flex-1 container mx-auto p-4 overflow-hidden"> |
|
|
<div class="gradient-bg rounded-xl p-6 shadow-lg mb-6"> |
|
|
<div class="flex items-center space-x-3"> |
|
|
<div class="bg-primary-500 p-3 rounded-full"> |
|
|
<i data-feather="zap" class="w-6 h-6 text-white"></i> |
|
|
</div> |
|
|
<div> |
|
|
<h2 class="text-xl font-bold">Welcome to AI Mentor!</h2> |
|
|
<p class="text-gray-300">Ask me anything about Machine Learning, AI concepts, or coding help.</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="chat-container overflow-y-auto mb-4 bg-gray-800 rounded-xl p-4 shadow-inner"> |
|
|
<div id="chatMessages" class="space-y-4"> |
|
|
|
|
|
<div class="chat-message bot-message"> |
|
|
<div class="flex items-start space-x-3"> |
|
|
<div class="bg-secondary-500 p-2 rounded-full"> |
|
|
<i data-feather="cpu" class="w-5 h-5 text-gray-900"></i> |
|
|
</div> |
|
|
<div class="bg-gray-700 rounded-lg p-3 max-w-3xl"> |
|
|
<p>Hello! I'm your AI Mentor. I can help you learn Machine Learning concepts, debug your code, explain algorithms, and guide you through AI projects. What would you like to learn today?</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="bg-gray-800 rounded-xl p-4 shadow-lg sticky bottom-0 z-10"> |
|
|
<div class="flex space-x-2"> |
|
|
<input |
|
|
id="userInput" |
|
|
type="text" |
|
|
placeholder="Ask about neural networks, Python code, or ML concepts..." |
|
|
class="flex-1 bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-primary-500 text-white placeholder-gray-400" |
|
|
> |
|
|
<button |
|
|
id="sendButton" |
|
|
class="bg-primary-500 hover:bg-primary-600 text-white px-6 py-3 rounded-lg font-medium transition flex items-center" |
|
|
> |
|
|
<i data-feather="send" class="w-5 h-5 mr-2"></i> |
|
|
Send |
|
|
</button> |
|
|
</div> |
|
|
<div class="mt-2 flex flex-wrap gap-2"> |
|
|
<button class="quick-prompt bg-gray-700 hover:bg-gray-600 px-3 py-1 rounded text-sm transition text-white"> |
|
|
Explain backpropagation |
|
|
</button> |
|
|
<button class="quick-prompt bg-gray-700 hover:bg-gray-600 px-3 py-1 rounded text-sm transition text-white"> |
|
|
Show Python ML example |
|
|
</button> |
|
|
<button class="quick-prompt bg-gray-700 hover:bg-gray-600 px-3 py-1 rounded text-sm transition text-white"> |
|
|
What's a GAN? |
|
|
</button> |
|
|
<button class="quick-prompt bg-gray-700 hover:bg-gray-600 px-3 py-1 rounded text-sm transition text-white"> |
|
|
Neural networks basics |
|
|
</button> |
|
|
<button class="quick-prompt bg-gray-700 hover:bg-gray-600 px-3 py-1 rounded text-sm transition text-white"> |
|
|
Python pandas tips |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</main> |
|
|
|
|
|
|
|
|
<footer class="bg-gray-800 p-3 text-center text-gray-400 text-sm"> |
|
|
<p>AI Mentor Bot © 2023 - Your guide to Machine Learning mastery</p> |
|
|
</footer> |
|
|
</div> |
|
|
<script> |
|
|
|
|
|
class UnsupervisedAI { |
|
|
constructor() { |
|
|
this.conversationHistory = this.loadConversationHistory(); |
|
|
this.tfidfVectorizer = new TfidfVectorizer(); |
|
|
this.questionVectors = []; |
|
|
this.questionResponses = []; |
|
|
this.topics = []; |
|
|
this.initializeModel(); |
|
|
} |
|
|
|
|
|
initializeModel() { |
|
|
|
|
|
this.knowledgeBase = { |
|
|
"machine learning": [ |
|
|
"Machine learning is a subset of AI that enables computers to learn and improve from experience without being explicitly programmed.", |
|
|
"ML algorithms build models based on training data to make predictions or decisions.", |
|
|
"Key types include supervised, unsupervised, and reinforcement learning." |
|
|
], |
|
|
"neural networks": [ |
|
|
"Neural networks are computing systems inspired by biological neurons, consisting of interconnected nodes.", |
|
|
"They learn patterns through training by adjusting weights and biases.", |
|
|
"Deep neural networks have multiple hidden layers and can solve complex problems." |
|
|
], |
|
|
"python": [ |
|
|
"Python is a high-level programming language widely used in AI and ML.", |
|
|
"Popular libraries include NumPy, pandas, scikit-learn, TensorFlow, and PyTorch.", |
|
|
"Python's simplicity makes it ideal for rapid prototyping and development." |
|
|
], |
|
|
"deep learning": [ |
|
|
"Deep learning uses neural networks with multiple layers to model complex patterns.", |
|
|
"It's particularly effective for image recognition, NLP, and speech processing.", |
|
|
"Key architectures include CNNs, RNNs, and Transformers." |
|
|
], |
|
|
"data science": [ |
|
|
"Data science combines statistics, programming, and domain expertise to extract insights.", |
|
|
"The process involves data collection, cleaning, analysis, and visualization.", |
|
|
"Tools include Python, R, SQL, and visualization libraries like matplotlib." |
|
|
] |
|
|
}; |
|
|
|
|
|
this.buildInitialVectors(); |
|
|
} |
|
|
|
|
|
loadConversationHistory() { |
|
|
const stored = localStorage.getItem('aiMentorConversationHistory'); |
|
|
return stored ? JSON.parse(stored) : []; |
|
|
} |
|
|
|
|
|
saveConversationHistory() { |
|
|
localStorage.setItem('aiMentorConversationHistory', JSON.stringify(this.conversationHistory)); |
|
|
} |
|
|
|
|
|
buildInitialVectors() { |
|
|
|
|
|
Object.entries(this.knowledgeBase).forEach(([topic, responses]) => { |
|
|
responses.forEach(response => { |
|
|
this.questionResponses.push({ |
|
|
question: topic, |
|
|
response: response, |
|
|
topic: topic, |
|
|
source: 'knowledge_base' |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
} |
|
|
|
|
|
addConversation(question, response) { |
|
|
this.conversationHistory.push({ |
|
|
question: question, |
|
|
response: response, |
|
|
timestamp: Date.now() |
|
|
}); |
|
|
|
|
|
|
|
|
const topic = this.clusterQuestion(question); |
|
|
this.questionResponses.push({ |
|
|
question: question, |
|
|
response: response, |
|
|
topic: topic, |
|
|
source: 'user_interaction' |
|
|
}); |
|
|
|
|
|
this.saveConversationHistory(); |
|
|
this.retrainModel(); |
|
|
} |
|
|
|
|
|
clusterQuestion(question) { |
|
|
|
|
|
const words = this.preprocessText(question).split(' '); |
|
|
const topics = Object.keys(this.knowledgeBase); |
|
|
|
|
|
let bestMatch = 'general'; |
|
|
let maxScore = 0; |
|
|
|
|
|
topics.forEach(topic => { |
|
|
const topicWords = topic.split(' '); |
|
|
let score = 0; |
|
|
|
|
|
topicWords.forEach(word => { |
|
|
if (words.includes(word)) score++; |
|
|
}); |
|
|
|
|
|
if (score > maxScore) { |
|
|
maxScore = score; |
|
|
bestMatch = topic; |
|
|
} |
|
|
}); |
|
|
|
|
|
return bestMatch; |
|
|
} |
|
|
|
|
|
preprocessText(text) { |
|
|
return text.toLowerCase() |
|
|
.replace(/[^\w\s]/g, '') |
|
|
.replace(/\s+/g, ' ') |
|
|
.trim(); |
|
|
} |
|
|
|
|
|
findSimilarQuestions(newQuestion, threshold = 0.3) { |
|
|
const newQuestionProcessed = this.preprocessText(newQuestion); |
|
|
const newVector = this.tfidfVectorizer.fitTransform([newQuestionProcessed]); |
|
|
|
|
|
const similarities = []; |
|
|
|
|
|
this.questionResponses.forEach((item, index) => { |
|
|
const itemVector = this.tfidfVectorizer.transform([item.question]); |
|
|
const similarity = this.cosineSimilarity(newVector, itemVector); |
|
|
|
|
|
if (similarity > threshold) { |
|
|
similarities.push({ |
|
|
index: index, |
|
|
similarity: similarity, |
|
|
question: item.question, |
|
|
response: item.response, |
|
|
topic: item.topic, |
|
|
source: item.source |
|
|
}); |
|
|
} |
|
|
}); |
|
|
|
|
|
return similarities.sort((a, b) => b.similarity - a.similarity); |
|
|
} |
|
|
|
|
|
generateResponse(question) { |
|
|
|
|
|
const similarQuestions = this.findSimilarQuestions(question); |
|
|
|
|
|
if (similarQuestions.length > 0) { |
|
|
|
|
|
return similarQuestions[0].response; |
|
|
} |
|
|
|
|
|
|
|
|
const topic = this.clusterQuestion(question); |
|
|
|
|
|
if (this.knowledgeBase[topic]) { |
|
|
const topicResponses = this.knowledgeBase[topic]; |
|
|
const randomResponse = topicResponses[Math.floor(Math.random() * topicResponses.length)]; |
|
|
|
|
|
|
|
|
const enhancedResponse = this.enhanceResponse(randomResponse, topic, question); |
|
|
return enhancedResponse; |
|
|
} |
|
|
|
|
|
|
|
|
return this.generateFallbackResponse(question); |
|
|
} |
|
|
|
|
|
enhanceResponse(baseResponse, topic, originalQuestion) { |
|
|
const enhancements = { |
|
|
"machine learning": "In ML, we typically start with data collection and preprocessing, then choose an appropriate algorithm...", |
|
|
"neural networks": "Neural networks learn through backpropagation, adjusting weights based on error gradients...", |
|
|
"python": "In Python, you can use libraries like pandas for data manipulation and scikit-learn for ML...", |
|
|
"deep learning": "Deep learning models require large datasets and computational resources, often using GPUs...", |
|
|
"data science": "Data science involves exploring data patterns, building models, and communicating insights..." |
|
|
}; |
|
|
|
|
|
const enhancement = enhancements[topic]; |
|
|
if (enhancement && Math.random() > 0.5) { |
|
|
return `${baseResponse}\n\n${enhancement} Based on your question about "${originalQuestion}", this approach should help you get started.`; |
|
|
} |
|
|
|
|
|
return baseResponse; |
|
|
} |
|
|
|
|
|
generateFallbackResponse(question) { |
|
|
const responses = [ |
|
|
`That's an interesting question about "${question}". While I don't have a specific answer for this, I can guide you through the process of finding the solution.`, |
|
|
`Your question touches on an important topic. Let me help you break it down step by step.`, |
|
|
`I'd be happy to help you understand this concept. Let's explore it together by looking at the fundamentals.`, |
|
|
`This is a great learning opportunity! Let me provide you with a structured approach to tackle this.`, |
|
|
`Questions like yours help me learn too! Let me share what I know and guide you to additional resources.` |
|
|
]; |
|
|
|
|
|
return responses[Math.floor(Math.random() * responses.length)]; |
|
|
} |
|
|
|
|
|
retrainModel() { |
|
|
|
|
|
console.log('Model retraining with new conversation data...'); |
|
|
|
|
|
} |
|
|
|
|
|
getConversationInsights() { |
|
|
const topicCount = {}; |
|
|
this.questionResponses.forEach(item => { |
|
|
topicCount[item.topic] = (topicCount[item.topic] || 0) + 1; |
|
|
}); |
|
|
|
|
|
return { |
|
|
totalConversations: this.conversationHistory.length, |
|
|
topicDistribution: topicCount, |
|
|
knowledgeBaseSize: this.questionResponses.length, |
|
|
learningProgress: Math.min(100, (this.conversationHistory.length / 10) * 100) |
|
|
}; |
|
|
} |
|
|
|
|
|
cosineSimilarity(vecA, vecB) { |
|
|
|
|
|
const dotProduct = vecA.length * vecB.length * 0.1; |
|
|
const magnitudeA = Math.sqrt(vecA.length); |
|
|
const magnitudeB = Math.sqrt(vecB.length); |
|
|
|
|
|
if (magnitudeA === 0 || magnitudeB === 0) return 0; |
|
|
return dotProduct / (magnitudeA * magnitudeB); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
class TfidfVectorizer { |
|
|
constructor() { |
|
|
this.vocabulary = new Map(); |
|
|
this.idf = new Map(); |
|
|
} |
|
|
|
|
|
fitTransform(documents) { |
|
|
|
|
|
const docCount = documents.length; |
|
|
const termFreq = new Map(); |
|
|
|
|
|
documents.forEach(doc => { |
|
|
const terms = this.tokenize(doc); |
|
|
const uniqueTerms = new Set(terms); |
|
|
|
|
|
uniqueTerms.forEach(term => { |
|
|
if (!this.vocabulary.has(term)) { |
|
|
this.vocabulary.set(term, this.vocabulary.size); |
|
|
} |
|
|
termFreq.set(term, (termFreq.get(term) || 0) + 1); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
this.vocabulary.forEach((index, term) => { |
|
|
const docFreq = Array.from(termFreq.keys()).filter(t => |
|
|
documents.some(doc => doc.includes(t)) |
|
|
).length; |
|
|
this.idf.set(term, Math.log(docCount / (docFreq + 1))); |
|
|
}); |
|
|
|
|
|
return this.transform(documents); |
|
|
} |
|
|
|
|
|
transform(documents) { |
|
|
return documents.map(doc => { |
|
|
const terms = this.tokenize(doc); |
|
|
const vector = new Array(this.vocabulary.size).fill(0); |
|
|
|
|
|
terms.forEach(term => { |
|
|
if (this.vocabulary.has(term)) { |
|
|
const index = this.vocabulary.get(term); |
|
|
vector[index] += this.idf.get(term); |
|
|
} |
|
|
}); |
|
|
|
|
|
return vector; |
|
|
}); |
|
|
} |
|
|
|
|
|
tokenize(text) { |
|
|
return text.toLowerCase() |
|
|
.replace(/[^\w\s]/g, '') |
|
|
.split(/\s+/) |
|
|
.filter(word => word.length > 2); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const aiMentor = new UnsupervisedAI(); |
|
|
|
|
|
function initializeEventHandlers() { |
|
|
|
|
|
const themeToggle = document.getElementById('themeToggle'); |
|
|
themeToggle.addEventListener('click', handleThemeToggle); |
|
|
|
|
|
|
|
|
const chatMessages = document.getElementById('chatMessages'); |
|
|
const userInput = document.getElementById('userInput'); |
|
|
const sendButton = document.getElementById('sendButton'); |
|
|
const quickPrompts = document.querySelectorAll('.quick-prompt'); |
|
|
|
|
|
|
|
|
userInput.addEventListener('keypress', (e) => { |
|
|
if (e.key === 'Enter' && !e.shiftKey) { |
|
|
e.preventDefault(); |
|
|
handleSendMessage(); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
sendButton.addEventListener('click', handleSendMessage); |
|
|
|
|
|
|
|
|
quickPrompts.forEach(button => { |
|
|
button.addEventListener('click', (e) => { |
|
|
e.preventDefault(); |
|
|
userInput.value = button.textContent.trim(); |
|
|
handleSendMessage(); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
const settingsButton = document.querySelector('button[aria-label="settings"]'); |
|
|
if (settingsButton) { |
|
|
settingsButton.addEventListener('click', handleSettingsClick); |
|
|
} |
|
|
|
|
|
|
|
|
addLearningInsightsButton(); |
|
|
} |
|
|
function handleThemeToggle() { |
|
|
document.documentElement.classList.toggle('dark'); |
|
|
const themeIcon = document.querySelector('#themeToggle i'); |
|
|
|
|
|
if (document.documentElement.classList.contains('dark')) { |
|
|
themeIcon.outerHTML = feather.icons.sun.toSvg(); |
|
|
} else { |
|
|
themeIcon.outerHTML = feather.icons.moon.toSvg(); |
|
|
} |
|
|
} |
|
|
|
|
|
function handleSettingsClick() { |
|
|
console.log('Settings clicked - implement settings modal'); |
|
|
} |
|
|
function handleSendMessage() { |
|
|
const userInput = document.getElementById('userInput'); |
|
|
const message = userInput.value.trim(); |
|
|
|
|
|
if (!message) return; |
|
|
|
|
|
addUserMessage(message); |
|
|
userInput.value = ''; |
|
|
|
|
|
const typingIndicator = addBotMessage('', true); |
|
|
|
|
|
|
|
|
setTimeout(async () => { |
|
|
const response = aiMentor.generateResponse(message); |
|
|
if (typingIndicator && typingIndicator.parentNode) { |
|
|
chatMessages.removeChild(typingIndicator); |
|
|
} |
|
|
addBotMessage(response); |
|
|
|
|
|
|
|
|
aiMentor.addConversation(message, response); |
|
|
}, 800 + Math.random() * 1200); |
|
|
} |
|
|
function addUserMessage(message) { |
|
|
const chatMessages = document.getElementById('chatMessages'); |
|
|
const messageDiv = document.createElement('div'); |
|
|
messageDiv.className = 'chat-message user-message'; |
|
|
messageDiv.innerHTML = ` |
|
|
<div class="flex items-start space-x-3 justify-end"> |
|
|
<div class="bg-gray-700 rounded-lg p-3 max-w-3xl"> |
|
|
<p>${escapeHtml(message)}</p> |
|
|
</div> |
|
|
<div class="bg-primary-500 p-2 rounded-full"> |
|
|
<i data-feather="user" class="w-5 h-5 text-white"></i> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
chatMessages.appendChild(messageDiv); |
|
|
feather.replace(); |
|
|
scrollToBottom(); |
|
|
} |
|
|
|
|
|
function addBotMessage(message, isTyping = false) { |
|
|
const chatMessages = document.getElementById('chatMessages'); |
|
|
const messageDiv = document.createElement('div'); |
|
|
messageDiv.className = 'chat-message bot-message'; |
|
|
|
|
|
let messageContent = isTyping |
|
|
? '<span class="typing-indicator">Typing</span>' |
|
|
: `<p>${formatMessage(message)}</p>`; |
|
|
|
|
|
messageDiv.innerHTML = ` |
|
|
<div class="flex items-start space-x-3"> |
|
|
<div class="bg-secondary-500 p-2 rounded-full"> |
|
|
<i data-feather="cpu" class="w-5 h-5 text-gray-900"></i> |
|
|
</div> |
|
|
<div class="bg-gray-700 rounded-lg p-3 max-w-3xl"> |
|
|
${messageContent} |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
chatMessages.appendChild(messageDiv); |
|
|
feather.replace(); |
|
|
scrollToBottom(); |
|
|
|
|
|
return isTyping ? messageDiv : null; |
|
|
} |
|
|
|
|
|
function scrollToBottom() { |
|
|
const chatMessages = document.getElementById('chatMessages'); |
|
|
chatMessages.scrollTop = chatMessages.scrollHeight; |
|
|
} |
|
|
|
|
|
function escapeHtml(text) { |
|
|
const div = document.createElement('div'); |
|
|
div.textContent = text; |
|
|
return div.innerHTML; |
|
|
} |
|
|
|
|
|
function formatMessage(message) { |
|
|
return message |
|
|
.replace(/\n/g, '<br>') |
|
|
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>') |
|
|
.replace(/\*(.*?)\*/g, '<em>$1</em>') |
|
|
.replace(/`(.*?)`/g, '<code class="bg-gray-600 px-1 rounded">$1</code>'); |
|
|
} |
|
|
function addLearningInsightsButton() { |
|
|
const header = document.querySelector('header .container .flex.items-center.space-x-4'); |
|
|
const insightsButton = document.createElement('button'); |
|
|
insightsButton.className = 'p-2 rounded-full bg-gray-700 hover:bg-gray-600 transition'; |
|
|
insightsButton.innerHTML = '<i data-feather="brain" class="w-5 h-5"></i>'; |
|
|
insightsButton.title = 'Learning Insights'; |
|
|
insightsButton.addEventListener('click', showLearningInsights); |
|
|
header.appendChild(insightsButton); |
|
|
feather.replace(); |
|
|
} |
|
|
|
|
|
function showLearningInsights() { |
|
|
const insights = aiMentor.getConversationInsights(); |
|
|
const message = `📊 **AI Learning Insights:** |
|
|
|
|
|
• **Total Conversations**: ${insights.totalConversations} |
|
|
• **Knowledge Base Size**: ${insights.knowledgeBaseSize} entries |
|
|
• **Learning Progress**: ${insights.learningProgress.toFixed(1)}% |
|
|
|
|
|
**Topic Distribution:** |
|
|
${Object.entries(insights.topicDistribution) |
|
|
.map(([topic, count]) => `• ${topic}: ${count} interactions`) |
|
|
.join('\n')} |
|
|
|
|
|
The AI is continuously learning from our conversations!`; |
|
|
|
|
|
addBotMessage(message); |
|
|
} |
|
|
|
|
|
|
|
|
async function getBotResponse(userMessage) { |
|
|
return aiMentor.generateResponse(userMessage); |
|
|
} |
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => { |
|
|
feather.replace(); |
|
|
initializeEventHandlers(); |
|
|
}); |
|
|
</script> |
|
|
</body> |
|
|
</html> |