Voyager / app.py
npcJensen's picture
Update app.py
672841b verified
from flask import Flask, render_template_string, request, jsonify
from chatbot_memory import get_response
import os
app = Flask(__name__)
# Read the HTML template (you can save the HTML artifact as templates/index.html instead)
def get_html_template():
# For now, we'll include the HTML inline.
# You can move it to templates/index.html later if preferred
return """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Voyager – Your AI Travel Companion</title>
<style>
/* RESET & BASE STYLE */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Poppins', 'Segoe UI', sans-serif;
background: radial-gradient(circle at top, #111827, #0a0f16);
color: #fff;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
/* BACKGROUND MOTION EFFECT */
.background {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
z-index: 0;
}
.gradient-circle {
position: absolute;
border-radius: 50%;
filter: blur(150px);
opacity: 0.5;
animation: float 10s ease-in-out infinite alternate;
}
.circle1 {
background: #4fa2f0;
width: 400px;
height: 400px;
top: -100px;
left: -100px;
}
.circle2 {
background: #00c6ff;
width: 500px;
height: 500px;
bottom: -200px;
right: -150px;
animation-delay: 2s;
}
@keyframes float {
0% {
transform: translateY(0);
}
100% {
transform: translateY(40px);
}
}
/* CHAT CONTAINER */
.chat-container {
position: relative;
width: 90%;
max-width: 900px;
height: 85vh;
display: flex;
flex-direction: column;
backdrop-filter: blur(20px);
background: rgba(255, 255, 255, 0.1);
border-radius: 25px;
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 0 40px rgba(79, 162, 240, 0.2);
z-index: 1;
overflow: hidden;
}
/* HEADER */
.chat-header {
background: linear-gradient(135deg, rgba(79, 162, 240, 0.25), rgba(79, 162, 240, 0.15)); //header background
padding: 25px;
text-align: center;
color: #fff;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.chat-header h1 {
font-size: 2rem;
font-weight: 700;
letter-spacing: 1px;
}
.chat-header h2 {
font-size: 1.1rem;
font-weight: 400;
opacity: 0.8;
}
/* MESSAGES */
.chat-messages {
flex: 1;
padding: 25px;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 20px;
scroll-behavior: smooth;
}
.message {
display: flex;
align-items: flex-start;
gap: 12px;
max-width: 80%;
animation: fadeIn 0.4s ease-out;
}
.message.user {
align-self: flex-end;
flex-direction: row-reverse;
}
.message.bot {
align-self: flex-start;
}
.avatar {
width: 45px;
height: 45px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
color: white;
box-shadow: 0 0 15px rgba(255, 255, 255, 0.1);
}
.avatar.user {
background: linear-gradient(135deg, #4fa2f0, #16425b);
}
.avatar.bot {
background: linear-gradient(135deg, #00c6ff, #0072ff);
}
.message-content {
padding: 15px 20px;
border-radius: 18px;
line-height: 1.6;
font-size: 0.95rem;
word-wrap: break-word;
backdrop-filter: blur(10px);
}
.message.user .message-content {
background: linear-gradient(135deg, #16425b, #4fa2f0);
color: #fff;
box-shadow: 0 0 15px rgba(79, 162, 240, 0.4);
}
.message.bot .message-content {
background: rgba(255, 255, 255, 0.1);
color: #e2e8f0;
border: 1px solid rgba(255, 255, 255, 0.1);
}
/* INPUT AREA */
.chat-input-container {
padding: 20px 25px;
background: rgba(255, 255, 255, 0.08);
border-top: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
gap: 10px;
align-items: center;
}
.chat-input {
flex: 1;
background: rgba(255, 255, 255, 0.15);
color: #fff;
padding: 14px 18px;
border: none;
border-radius: 25px;
font-size: 1rem;
outline: none;
resize: none;
min-height: 24px;
transition: background 0.3s ease;
}
.chat-input::placeholder {
color: #cbd5e1;
}
.chat-input:focus {
background: rgba(255, 255, 255, 0.25);
}
.send-button {
width: 50px;
height: 50px;
border: none;
border-radius: 50%;
background: linear-gradient(135deg, #00c6ff, #0072ff);
color: white;
font-size: 1.4rem;
cursor: pointer;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.send-button:hover {
transform: translateY(-3px);
box-shadow: 0 0 20px rgba(0, 198, 255, 0.5);
}
.typing-indicator {
display: none;
align-items: center;
gap: 8px;
color: #a0aec0;
font-size: 0.9rem;
font-style: italic;
}
.typing-dots {
display: flex;
gap: 4px;
}
.typing-dots span {
width: 6px;
height: 6px;
background: #4fa2f0;
border-radius: 50%;
animation: bounce 1.4s infinite ease-in-out;
}
.typing-dots span:nth-child(1) {
animation-delay: -0.32s;
}
.typing-dots span:nth-child(2) {
animation-delay: -0.16s;
}
.welcome-message {
text-align: center;
color: #e2e8f0;
opacity: 0.9;
line-height: 1.7;
margin-top: 60px;
font-size: 1.1rem;
}
.welcome-message h2 {
color: #fff;
margin-bottom: 12px;
font-size: 1.4rem;
letter-spacing: 0.5px;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes bounce {
0%, 80%, 100% {
transform: scale(0);
}
40% {
transform: scale(1);
}
}
@media (max-width: 768px) {
.chat-container {
height: 100vh;
border-radius: 0;
}
.chat-header h1 {
font-size: 1.6rem;
}
.message {
max-width: 90%;
}
}
</style>
</head>
<body>
<div class="background">
<div class="gradient-circle circle1"></div>
<div class="gradient-circle circle2"></div>
</div>
<div class="chat-container">
<div class="chat-header">
<h1>🌍 Voyager</h1>
<h2>Your AI Travel Companion</h2>
</div>
<div class="chat-messages" id="chatMessages">
<div class="welcome-message">
<h2>Welcome to Voyager!</h2>
<p>Plan your next adventure effortlessly.
Just tell me your destination! ✈️</p>
</div>
</div>
<div class="typing-indicator" id="typingIndicator">
<span>Voyager is thinking</span>
<div class="typing-dots">
<span></span><span></span><span></span>
</div>
</div>
<div class="chat-input-container">
<textarea
class="chat-input"
id="chatInput"
placeholder="Type your travel idea..."
rows="1"
></textarea>
<button class="send-button" id="sendButton" onclick="sendMessage()">➤</button>
</div>
</div>
<script>
let chatHistory = [];
const chatInput = document.getElementById('chatInput');
chatInput.addEventListener('input', function() {
this.style.height = 'auto';
this.style.height = Math.min(this.scrollHeight, 120) + 'px';
});
chatInput.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
});
function addMessage(content, isUser = false) {
const messagesContainer = document.getElementById('chatMessages');
const welcomeMessage = messagesContainer.querySelector('.welcome-message');
if (welcomeMessage && isUser) welcomeMessage.remove();
const messageDiv = document.createElement('div');
messageDiv.className = `message ${isUser ? 'user' : 'bot'}`;
messageDiv.innerHTML = `
<div class="avatar ${isUser ? 'user' : 'bot'}">${isUser ? 'U' : '🤖'}</div>
<div class="message-content">${content}</div>
`;
messagesContainer.appendChild(messageDiv);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
return messageDiv;
}
function showTypingIndicator() {
document.getElementById('typingIndicator').style.display = 'flex';
document.getElementById('chatMessages').scrollTop =
document.getElementById('chatMessages').scrollHeight;
}
function hideTypingIndicator() {
document.getElementById('typingIndicator').style.display = 'none';
}
async function sendMessage() {
const input = document.getElementById('chatInput');
const sendButton = document.getElementById('sendButton');
const message = input.value.trim();
if (!message) return;
addMessage(message, true);
input.value = '';
input.style.height = 'auto';
sendButton.disabled = true;
showTypingIndicator();
try {
const response = await fetch('/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message, history: chatHistory }),
});
if (!response.ok) throw new Error('Network error');
const data = await response.json();
addMessage(data.response);
chatHistory.push({ role: 'user', content: message });
chatHistory.push({ role: 'assistant', content: data.response });
} catch (error) {
console.error(error);
addMessage('⚠️ Oops! Something went wrong. Please try again.');
} finally {
hideTypingIndicator();
sendButton.disabled = false;
input.focus();
}
}
window.addEventListener('load', () => chatInput.focus());
</script>
</body>
</html>
"""
@app.route('/')
def home():
return render_template_string(get_html_template())
@app.route('/chat', methods=['POST'])
def chat():
try:
data = request.get_json()
message = data.get('message', '')
history = data.get('history', [])
# Get response from your existing chatbot_memory module
response = get_response(message, history)
response = response.replace('\n', '<br>')
return jsonify({'response': response})
except Exception as e:
print(f"Error: {e}")
return jsonify({'error': 'Something went wrong'}), 500
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=7860)#7860 in hugging face and 5000 in github