| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Educational Research Methods Chatbot</title> |
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> |
| <style> |
| body { |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
| background-color: #f8f9fa; |
| margin: 0; |
| padding: 0; |
| } |
| .chat-container { |
| max-width: 800px; |
| margin: 2rem auto; |
| border-radius: 10px; |
| box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); |
| background-color: #fff; |
| overflow: hidden; |
| } |
| .chat-header { |
| background-color: #4a6fdc; |
| color: white; |
| padding: 1.5rem; |
| text-align: center; |
| } |
| .chat-messages { |
| height: 400px; |
| overflow-y: auto; |
| padding: 1rem; |
| background-color: #f8f9fa; |
| } |
| .message { |
| margin-bottom: 1rem; |
| padding: 0.75rem 1rem; |
| border-radius: 10px; |
| max-width: 80%; |
| } |
| .user-message { |
| background-color: #e9ecef; |
| margin-left: auto; |
| border-bottom-right-radius: 0; |
| } |
| .bot-message { |
| background-color: #4a6fdc; |
| color: white; |
| margin-right: auto; |
| border-bottom-left-radius: 0; |
| } |
| .chat-input { |
| display: flex; |
| padding: 1rem; |
| background-color: #fff; |
| border-top: 1px solid #e9ecef; |
| } |
| .chat-input input { |
| flex-grow: 1; |
| border: 1px solid #ced4da; |
| border-radius: 20px; |
| padding: 0.5rem 1rem; |
| margin-right: 0.5rem; |
| } |
| .chat-input button { |
| background-color: #4a6fdc; |
| color: white; |
| border: none; |
| border-radius: 20px; |
| padding: 0.5rem 1.5rem; |
| cursor: pointer; |
| } |
| .chat-input button:hover { |
| background-color: #3a5bbf; |
| } |
| .citation { |
| font-size: 0.8rem; |
| margin-top: 0.5rem; |
| color: #6c757d; |
| } |
| .citation-list { |
| margin-top: 1rem; |
| padding: 1rem; |
| background-color: #f8f9fa; |
| border-radius: 5px; |
| font-size: 0.9rem; |
| } |
| .typing-indicator { |
| display: none; |
| padding: 0.75rem 1rem; |
| background-color: #e9ecef; |
| border-radius: 10px; |
| margin-bottom: 1rem; |
| width: fit-content; |
| } |
| .typing-indicator span { |
| height: 10px; |
| width: 10px; |
| float: left; |
| margin: 0 1px; |
| background-color: #9E9EA1; |
| display: block; |
| border-radius: 50%; |
| opacity: 0.4; |
| } |
| .typing-indicator span:nth-of-type(1) { |
| animation: 1s blink infinite 0.3333s; |
| } |
| .typing-indicator span:nth-of-type(2) { |
| animation: 1s blink infinite 0.6666s; |
| } |
| .typing-indicator span:nth-of-type(3) { |
| animation: 1s blink infinite 0.9999s; |
| } |
| @keyframes blink { |
| 50% { |
| opacity: 1; |
| } |
| } |
| .model-info { |
| font-size: 0.8rem; |
| text-align: center; |
| margin-top: 1rem; |
| color: #6c757d; |
| } |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <div class="chat-container"> |
| <div class="chat-header"> |
| <h1>Educational Research Methods Chatbot</h1> |
| <p>Ask questions about research methods for educational research</p> |
| </div> |
| <div class="chat-messages" id="chat-messages"> |
| <div class="message bot-message"> |
| Hello! I'm your educational research methods assistant. I can help you choose appropriate research methods for your educational research projects. What would you like to know? |
| </div> |
| <div class="typing-indicator" id="typing-indicator"> |
| <span></span> |
| <span></span> |
| <span></span> |
| </div> |
| </div> |
| <div class="chat-input"> |
| <input type="text" id="user-input" placeholder="Type your question here..."> |
| <button id="send-button">Send</button> |
| </div> |
| <div class="model-info"> |
| Powered by Mistral-7B-v0.1 - Open Source LLM |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| document.addEventListener('DOMContentLoaded', function() { |
| const chatMessages = document.getElementById('chat-messages'); |
| const userInput = document.getElementById('user-input'); |
| const sendButton = document.getElementById('send-button'); |
| const typingIndicator = document.getElementById('typing-indicator'); |
| |
| |
| const API_ENDPOINT = '/.netlify/functions/chat-mistral'; |
| |
| let conversationHistory = []; |
| |
| |
| function addMessage(message, isUser = false) { |
| const messageDiv = document.createElement('div'); |
| messageDiv.classList.add('message'); |
| messageDiv.classList.add(isUser ? 'user-message' : 'bot-message'); |
| |
| |
| if (!isUser && typeof message === 'object') { |
| const messageText = document.createElement('div'); |
| messageText.textContent = message.response; |
| messageDiv.appendChild(messageText); |
| |
| |
| if (message.citations && message.citations.length > 0) { |
| const citationList = document.createElement('div'); |
| citationList.classList.add('citation-list'); |
| citationList.innerHTML = '<strong>References:</strong>'; |
| |
| const citationUl = document.createElement('ul'); |
| message.citations.forEach(citation => { |
| const citationLi = document.createElement('li'); |
| citationLi.textContent = citation.text; |
| citationUl.appendChild(citationLi); |
| }); |
| |
| citationList.appendChild(citationUl); |
| messageDiv.appendChild(citationList); |
| } |
| } else { |
| messageDiv.textContent = message; |
| } |
| |
| chatMessages.appendChild(messageDiv); |
| chatMessages.scrollTop = chatMessages.scrollHeight; |
| } |
| |
| |
| function showTypingIndicator() { |
| typingIndicator.style.display = 'block'; |
| chatMessages.scrollTop = chatMessages.scrollHeight; |
| } |
| |
| |
| function hideTypingIndicator() { |
| typingIndicator.style.display = 'none'; |
| } |
| |
| |
| async function sendMessage(message) { |
| try { |
| showTypingIndicator(); |
| |
| const response = await fetch(API_ENDPOINT, { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json' |
| }, |
| body: JSON.stringify({ |
| message: message, |
| conversation_history: conversationHistory |
| }) |
| }); |
| |
| if (!response.ok) { |
| throw new Error('API request failed'); |
| } |
| |
| const data = await response.json(); |
| hideTypingIndicator(); |
| |
| |
| addMessage(data, false); |
| |
| |
| conversationHistory.push({ |
| message: message, |
| response: data.response |
| }); |
| |
| |
| if (conversationHistory.length > 10) { |
| conversationHistory = conversationHistory.slice(-10); |
| } |
| } catch (error) { |
| hideTypingIndicator(); |
| console.error('Error:', error); |
| addMessage('Sorry, I encountered an error. The Hugging Face Inference API may be temporarily unavailable. Please try again later.', false); |
| } |
| } |
| |
| |
| sendButton.addEventListener('click', function() { |
| const message = userInput.value.trim(); |
| if (message) { |
| addMessage(message, true); |
| userInput.value = ''; |
| sendMessage(message); |
| } |
| }); |
| |
| |
| userInput.addEventListener('keypress', function(e) { |
| if (e.key === 'Enter') { |
| const message = userInput.value.trim(); |
| if (message) { |
| addMessage(message, true); |
| userInput.value = ''; |
| sendMessage(message); |
| } |
| } |
| }); |
| |
| |
| userInput.focus(); |
| }); |
| </script> |
| </body> |
| </html> |
|
|