Chapter 4: Building a Simple Chatbot with Memory
4.2 Creating Interactive User Interfaces
User interfaces are the bridge between your chatbot's intelligence and its users. A well-designed UI can transform a capable AI system into an engaging, accessible tool that users love to interact with. Creating an effective chatbot interface requires careful consideration of user experience principles, visual design elements, and interaction patterns.
This section explores the art and science of building intuitive chatbot interfaces. We'll examine both the technical implementation and design considerations that make a chatbot truly user-friendly. You'll learn how to create interfaces that not only look professional but also provide meaningful feedback, handle errors gracefully, and guide users through natural conversations.
Whether you're building a customer service bot, a virtual assistant, or an AI-powered learning tool, the principles and techniques covered here will help you create interfaces that enhance rather than hinder the user experience. We'll look at implementation approaches using both Streamlit and Flask, giving you the flexibility to choose the tools that best fit your project's needs.
4.2.1 Why UI Matters in a Chatbot
The success of a chatbot heavily depends on its user interface and overall user experience. No matter how sophisticated your AI model might be, users will struggle to engage with it effectively if the interface is difficult to use or unintuitive. This is why creating well-designed, user-friendly interfaces is crucial. We'll focus on building intuitive, responsive, and user-friendly UIs that not only look professional but also create a natural flow of conversation between the user and the AI.
Our approach emphasizes three fundamental aspects of interface design that are critical for creating an effective chatbot:
User Experience (UX)
Creating interfaces that are easy to navigate and understand, with clear visual hierarchies and intuitive interaction patterns. A well-designed UX considers several key aspects:
- Information Architecture: Organizing content in a logical, easy-to-follow structure that matches users' mental models.
- Visual Design: Using consistent color schemes, typography, and spacing to create clear visual hierarchies that guide users' attention.
- Interaction Design: Implementing intuitive controls and navigation patterns that feel familiar and predictable to users.
- Feedback Mechanisms: Providing clear visual and textual cues that help users understand:
- When their message is being processed
- When the chatbot is "thinking"
- If an error occurs
- Whether their input was received successfully
- Cognitive Load Management: Minimizing the mental effort required to use the interface by:
- Breaking complex tasks into smaller steps
- Using familiar design patterns
- Providing clear instructions when needed
- Maintaining consistent behavior throughout the interface
This thoughtful approach to UX design reduces friction, increases user engagement, and makes the chatbot feel natural and effortless to use.
Responsiveness
Ensuring the interface provides immediate feedback and maintains smooth performance across different devices and screen sizes. This involves several key aspects:
- Performance Optimization:
- Implementing efficient loading states that show users their actions are being processed
- Optimizing response times through techniques like request debouncing and caching
- Using progressive loading for chat history to handle large conversations
- Device Compatibility:
- Using responsive design principles to ensure the chatbot works seamlessly across devices
- Implementing fluid layouts that adjust to different screen sizes
- Ensuring touch-friendly interface elements for mobile users
- Testing and optimizing for various browsers and platforms
- Adaptive UI Elements:
- Creating flexible chat bubbles that resize based on content
- Implementing collapsible menus and controls for smaller screens
- Using relative units (em, rem, vh, vw) instead of fixed pixels
- Ensuring proper text wrapping and readability at all sizes
The interface should dynamically adapt to different screen sizes while maintaining functionality and visual appeal, providing a consistent experience whether accessed from a smartphone, tablet, or desktop computer.
Accessibility
Making the chatbot usable for people with different abilities and technical backgrounds is crucial for ensuring inclusive access. This involves several key considerations:
- Screen Reader Compatibility
- Implementing proper ARIA labels and roles to describe UI elements
- Ensuring meaningful heading structure and navigation
- Providing text alternatives for all non-text content
- Keyboard Navigation
- Supporting full keyboard control of all features
- Implementing visible focus indicators
- Creating logical tab order through the interface
- Visual Design
- Maintaining sufficient color contrast ratios (minimum 4.5:1)
- Avoiding color as the only means of conveying information
- Supporting text resizing without loss of functionality
- Technical Considerations
- Following Web Content Accessibility Guidelines (WCAG) 2.1 Level AA standards
- Regular testing with accessibility tools and screen readers
- Providing alternatives for complex interactions
By implementing these accessibility features, you ensure that your chatbot can be effectively used by people with various disabilities, including visual, auditory, motor, and cognitive impairments. This not only complies with legal requirements but also demonstrates a commitment to universal design principles.
To create an effective and user-friendly chatbot interface, we'll explore these essential components in detail:
- Building an Intuitive Chat Interface
- Implementation of clean, modern design principles that prioritize readability and user engagement
- Careful consideration of spacing to create visual breathing room between elements
- Strategic use of typography to establish clear information hierarchy
- Consistent visual elements that guide users through the conversation flow
- Managing Conversation History
- Implementation of efficient chat log storage and retrieval systems
- Integration of timestamp functionality for better conversation tracking
- Creation of distinct visual styles for user and bot messages
- Development of smooth scrolling mechanics for longer conversations
- Optimizing Response Presentation
- Careful selection of fonts and text sizes for maximum readability
- Implementation of consistent spacing patterns between message elements
- Special formatting considerations for different content types (code blocks, lists, etc.)
- Integration of visual indicators for message status and type
- Implementing Robust Feedback Systems
- Creation of subtle but visible loading animations during response generation
- Development of clear error messages that guide users toward solutions
- Implementation of recovery mechanisms for common error scenarios
- Integration of status indicators to keep users informed of system state
You'll get comprehensive examples in both Streamlit and Flask, allowing you to choose the framework that best suits your development style and project requirements. Each example includes detailed explanations and best practices for implementation.
4.2.2 Streamlit Interactive Chat UI
This example demonstrates how to create an interactive chatbot using Streamlit and OpenAI, which we'll build upon further. Using Streamlit, we'll create a user-friendly chat interface that maintains conversation history. This use case showcases key concepts and best practices for building a robust, interactive chatbot.
Step 1: Install Dependencies
pip install streamlit openai python-dotenv
streamlit
: A Python library for creating interactive web applications.openai
: The OpenAI Python library for interacting with the GPT-4o model.python-dotenv
: A library to load environment variables from a.env
file.
Step 2: Create the Streamlit App (chatbot.py)
import streamlit as st
import openai
import os
from dotenv import load_dotenv
import time # For handling potential API errors
from typing import List, Dict # For type hinting
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
# --- Constants ---
DEFAULT_MODEL = "gpt-4o"
SYSTEM_PROMPT = "You are a helpful, friendly, and knowledgeable assistant. Answer all questions clearly, concisely, and in a conversational tone. When appropriate, provide code examples."
SESSION_MESSAGES_KEY = "messages" # Consistent key for session state
DISPLAY_MESSAGES_KEY = "display_messages"
# --- Helper Functions ---
def get_openai_response(messages: List[Dict[str, str]], model: str = DEFAULT_MODEL) -> str:
"""
Sends a message to OpenAI's Chat API and handles potential errors with robust error handling.
Args:
messages (List[Dict[str, str]]): A list of message dictionaries, representing the conversation history.
model (str, optional): The OpenAI model to use. Defaults to DEFAULT_MODEL.
Returns:
str: The assistant's reply, or an error message.
Raises:
openai.error.OpenAIError: If there is an error with the OpenAI API.
Exception: For other unexpected errors.
"""
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=60, # Add a timeout to prevent hanging
)
return response.choices[0].message.content
except openai.error.OpenAIError as e:
st.error(f"OpenAI API Error: {e}")
return f"Sorry, I encountered an error with the OpenAI API: {e}"
except Exception as e:
st.error(f"An unexpected error occurred: {e}")
return "Sorry, I encountered an unexpected error."
def initialize_session_state():
"""
Initializes session state variables. This function should be called
at the beginning of the main() function. It ensures that session
state is initialized even if the user doesn't immediately enter a query.
"""
if SESSION_MESSAGES_KEY not in st.session_state:
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
if DISPLAY_MESSAGES_KEY not in st.session_state:
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}] # Separate list for displayed messages
if "model" not in st.session_state:
st.session_state.model = DEFAULT_MODEL
def clear_chat_history():
"""Clears the chat history and resets to the initial state."""
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state.user_input = "" # Clear the input field
st.rerun() # Force a rerun to update the display
# --- Main App ---
def main():
"""
Main function to run the Streamlit application.
"""
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
st.title("🤖 GPT-4o Assistant")
initialize_session_state() # Initialize session state
# --- Sidebar ---
st.sidebar.header("Settings")
model = st.sidebar.selectbox("Model", ["gpt-4o", "gpt-3.5-turbo"], index=0)
st.session_state.model = model
clear_history_button = st.sidebar.button("Clear Chat", on_click=clear_chat_history) # corrected to clear_chat_history
# Display chat history, রাখা changed to display_messages
for message in st.session_state[DISPLAY_MESSAGES_KEY]:
if message["role"] != "system": # Don't display the system prompt
speaker = "🧑💻 You" if message["role"] == "user" else "🤖 Assistant"
with st.chat_message(message["role"]):
st.markdown(f"**{speaker}:** {message['content']}")
# User input, রাখা outside the conditional block
user_input = st.chat_input("Ask me anything...", key="user_input")
# Process user input
if user_input:
st.session_state[SESSION_MESSAGES_KEY].append({"role": "user", "content": user_input})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "user", "content": user_input})
# Add spinner while GPT-4o thinks
with st.chat_message("assistant"):
placeholder = st.empty() # Reserve a placeholder for the response
with st.spinner("Thinking..."):
reply = get_openai_response(st.session_state[SESSION_MESSAGES_KEY], model=st.session_state.model) #added model
placeholder.markdown(f"**🤖 Assistant:** {reply}") # Replace placeholder with full response
st.session_state[SESSION_MESSAGES_KEY].append({"role": "assistant", "content": reply})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "assistant", "content": reply})
# Clear the input field after sending the message
st.session_state.user_input = ""
st.rerun()
if __name__ == "__main__":
main()
Code Breakdown
Let's break down the code step by step.
Imports:
import streamlit as st
import openai
import os
from dotenv import load_dotenv
import time # For handling potential API errors
from typing import List, Dict # For type hinting
Imports the necessary libraries:
streamlit
: For creating the web interface.openai
: For interacting with the OpenAI API.os
: For accessing environment variables.dotenv
: For loading environment variables from a.env
file.time
: For handling potential API errors by waiting.typing
: For type hinting to improve code readability.
Environment Variables:
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
Loads the OpenAI API key from a .env
file and sets it for the OpenAI library.
Constants:
DEFAULT_MODEL = "gpt-4o"
SYSTEM_PROMPT = "You are a helpful, friendly, and knowledgeable assistant. Answer all questions clearly, concisely, and in a conversational tone. When appropriate, provide code examples."
SESSION_MESSAGES_KEY = "messages" # Consistent key for session state
DISPLAY_MESSAGES_KEY = "display_messages"
DEFAULT_MODEL
: The default OpenAI model used for the chatbot.SYSTEM_PROMPT
: The initial message sent to the OpenAI API to set the behavior of the assistant.SESSION_MESSAGES_KEY
: Key to use for the main conversation history in the session state.DISPLAY_MESSAGES_KEY
: Key to use for the conversation history that is displayed in the UI.
Helper Functions:
get_openai_response()
:
def get_openai_response(messages: List[Dict[str, str]], model: str = DEFAULT_MODEL) -> str:
"""
Sends a message to OpenAI's Chat API and handles potential errors with robust error handling.
Args:
messages (List[Dict[str, str]]): A list of message dictionaries, representing the conversation history.
model (str, optional): The OpenAI model to use. Defaults to DEFAULT_MODEL.
Returns:
str: The assistant's reply, or an error message.
Raises:
openai.error.OpenAIError: If there is an error with the OpenAI API.
Exception: For other unexpected errors.
"""
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=60, # Add a timeout to prevent hanging
)
return response.choices[0].message.content
except openai.error.OpenAIError as e:
st.error(f"OpenAI API Error: {e}")
return f"Sorry, I encountered an error with the OpenAI API: {e}"
except Exception as e:
st.error(f"An unexpected error occurred: {e}")
return "Sorry, I encountered an unexpected error."
Sends the user's input to the OpenAI API and retrieves the response. This function also includes error handling using a try...except
block to catch potential openai.error.OpenAIError
exceptions and a general Exception
for other errors. A timeout is added to prevent the app from hanging indefinitely.
initialize_session_state()
:
def initialize_session_state():
"""
Initializes session state variables. This function should be called
at the beginning of the main() function. It ensures that session
state is initialized even if the user doesn't immediately enter a query.
"""
if SESSION_MESSAGES_KEY not in st.session_state:
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
if DISPLAY_MESSAGES_KEY not in st.session_state:
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}] # Separate list for displayed messages
if "model" not in st.session_state:
st.session_state.model = DEFAULT_MODEL
Initializes the session state variables:
SESSION_MESSAGES_KEY
: Stores the full conversation history.DISPLAY_MESSAGES_KEY
: Stores the conversation history that is displayed to the user.model
: The LLM modelclear_chat_history()
:
def clear_chat_history():
"""Clears the chat history and resets to the initial state."""
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state.user_input = "" # Clear the input field
st.rerun() # Force a rerun to update the display
Clears the chat history when the user clicks the "Clear Chat" button.
Main App:
def main():
"""
Main function to run the Streamlit application.
"""
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
st.title("🤖 GPT-4o Assistant")
initialize_session_state()
# --- Sidebar ---
st.sidebar.header("Settings")
model = st.sidebar.selectbox("Model", ["gpt-4o", "gpt-3.5-turbo"], index=0)
st.session_state.model = model
clear_history_button = st.sidebar.button("Clear Chat", on_click=clear_chat_history)
# Display chat history
for message in st.session_state[DISPLAY_MESSAGES_KEY]:
if message["role"] != "system": # Don't display the system prompt
speaker = "🧑💻 You" if message["role"] == "user" else "🤖 Assistant"
with st.chat_message(message["role"]):
st.markdown(f"**{speaker}:** {message['content']}")
# User input
user_input = st.chat_input("Ask me anything...", key="user_input")
# Process user input
if user_input:
st.session_state[SESSION_MESSAGES_KEY].append({"role": "user", "content": user_input})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "user", "content": user_input})
# Add spinner while GPT-4o thinks
with st.chat_message("assistant"):
placeholder = st.empty() # Reserve a placeholder for the response
with st.spinner("Thinking..."):
reply = get_openai_response(st.session_state[SESSION_MESSAGES_KEY], model=st.session_state.model) # added model
placeholder.markdown(f"**🤖 Assistant:** {reply}") # Replace placeholder with full response
st.session_state[SESSION_MESSAGES_KEY].append({"role": "assistant", "content": reply})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "assistant", "content": reply})
# Clear the input field after sending the message
st.session_state.user_input = ""
st.rerun()
if __name__ == "__main__":
main()
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
: Sets the page title and icon in the browser tab.st.title("🤖 GPT-4o Assistant")
: Sets the title of the Streamlit application.initialize_session_state()
: Initializes the sessionst.sidebar.header("Settings")
: Creates a sidebar section titled "Settings."model = st.sidebar.selectbox(...)
: Creates a dropdown in the sidebar to select the OpenAI model.clear_history_button = st.sidebar.button("Clear Chat", on_click=clear_chat_history)
: Adds a button to the sidebar to clear the chat history.- The chat history is displayed using
st.chat_message
, with different styling for the user and assistant messages. user_input = st.chat_input("Ask me anything...", key="user_input")
: Creates a text input field for the user to type their query. Thekey
argument is important for Streamlit to manage the state of the input field.- The application retrieves the user's input, sends it to the OpenAI API using the
get_openai_response
function, and displays the response. - The conversation history is stored in
st.session_state.messages
as a list of dictionaries. Each dictionary has a "role" (either "user" or "assistant") and "content". st.rerun()
is used to update the display after the assistant responds.- Run the app:
To run the app, save the code to a file named chatbot.py and run the following command in your terminal:
streamlit run chatbot.py
4.2.3 Flask + Custom HTML/CSS Chat UI
This example implements a chatbot using Flask and OpenAI's GPT-4o model, with a focus on allowing developers to customize the chat interface using their own HTML and CSS. This approach provides greater flexibility in styling and layout compared to using pre-built UI components. This code provide a robust and customizable chatbot, explaining key concepts and best practices for intermediate developers.
Step 1: Install Dependencies
pip install flask openai python-dotenv
flask
: A web framework for building the chatbot application.openai
: The OpenAI Python library for interacting with the GPT-4o model.python-dotenv
: A library to load environment variables from a.env
file.
Step 2: Updated Flask Template (templates/chat.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GPT-4o Chat Assistant</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<style>
/* --- General Styles --- */
body {
font-family: 'Inter', sans-serif; /* Modern font */
background-color: #f3f4f6; /* Tailwind's gray-100 */
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
color: #1f2937; /* Tailwind's gray-800 */
}
.container {
max-width: 800px; /* Increased max-width */
width: 100%;
background-color: #fff; /* White background */
padding: 30px;
border-radius: 0.75rem; /* Tailwind's rounded-lg */
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); /* Tailwind's shadow-md */
}
h2 {
font-size: 1.875rem; /* Tailwind's text-2xl */
font-weight: 600; /* Tailwind's font-semibold */
margin-bottom: 2rem; /* Tailwind's mb-8 */
color: #1e293b; /* Tailwind's gray-900 */
text-align: center;
}
/* --- Message Styles --- */
.message {
margin-bottom: 1.5rem; /* Tailwind's mb-6 */
display: flex;
flex-direction: column;
}
.message p {
padding: 1rem; /* Tailwind's p-4 */
border-radius: 1rem; /* Tailwind's rounded-lg */
max-width: 80%; /* Limit message width */
}
.user p {
background-color: #e0f2fe; /* Tailwind's bg-blue-100 */
color: #1d4ed8; /* Tailwind's text-blue-700 */
margin-left: auto; /* Push user message to the right */
}
.assistant p {
background-color: #f0fdf4; /* Tailwind's bg-green-100 */
color: #15803d; /* Tailwind's text-green-700 */
}
.message strong {
font-size: 0.875rem; /* Tailwind's text-sm */
font-weight: 600; /* Tailwind's font-semibold */
margin-bottom: 0.25rem; /* Tailwind's mb-1 */
}
.user strong {
color: #1e40af; /* Tailwind's text-blue-800 */
}
.assistant strong {
color: #16a34a; /* Tailwind's text-green-800 */
}
/* --- Form Styles --- */
form {
margin-top: 2rem; /* Tailwind's mt-8 */
display: flex;
flex-direction: column;
gap: 0.5rem; /* Tailwind's gap-2 */
}
textarea {
width: 100%;
padding: 0.75rem; /* Tailwind's p-3 */
border-radius: 0.5rem; /* Tailwind's rounded-md */
border: 1px solid #d1d5db; /* Tailwind's border-gray-300 */
resize: none;
font-size: 1rem; /* Tailwind's text-base */
line-height: 1.5rem; /* Tailwind's leading-relaxed */
margin-bottom: 0.25rem; /* Tailwind's mb-1 */
box-shadow: inset 0 2px 4px rgba(0,0,0,0.06); /* Inner shadow, more subtle */
}
textarea:focus {
outline: none;
border-color: #3b82f6; /* Tailwind's border-blue-500 */
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15); /* Tailwind's ring-blue-500 with opacity */
}
input[type="submit"] {
padding: 0.75rem 1.5rem; /* Tailwind's px-6 py-3 */
border-radius: 0.5rem; /* Tailwind's rounded-md */
background-color: #3b82f6; /* Tailwind's bg-blue-500 */
color: #fff; /* White text */
font-size: 1rem; /* Tailwind's text-base */
font-weight: 600; /* Tailwind's font-semibold */
cursor: pointer;
transition: background-color 0.3s ease; /* Smooth transition */
border: none;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1); /* Tailwind's shadow-sm */
}
input[type="submit"]:hover {
background-color: #2563eb; /* Tailwind's bg-blue-700 on hover */
}
input[type="submit"]:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3); /* Tailwind's ring-blue-500 with more opacity*/
}
/* --- Responsive Adjustments --- */
@media (max-width: 768px) { /* Medium screens and below (md breakpoint in Tailwind is 768px) */
.container {
padding: 20px;
}
textarea {
height: 100px; /* Make textarea taller on smaller screens */
}
}
</style>
</head>
<body>
<div class="container">
<h2>🧠 GPT-4o Chat Assistant</h2>
{% for msg in history %}
<div class="message {{ msg.role }}">
<p><strong>{{ msg.role.capitalize() }}:</strong> {{ msg.content }}</p>
</div>
{% endfor %}
<form method="post">
<textarea name="user_input" placeholder="Type your message..."></textarea><br>
<input type="submit" value="Send Message">
</form>
</div>
</body>
</html>
HTML template:
- Modern Design: The template features a contemporary design approach inspired by Tailwind CSS. This includes:
- Clean font (Inter)
- Spacious padding and margins
- Rounded corners
- Subtle shadows
- Consistent color palette
- Responsive Design: Added a media query to adjust the layout for smaller screens (tablets and phones).
- Improved Form: The form is styled with a focus state, better margins, and a smooth hover effect.
- Semantic HTML: Uses
lang="en"
in the<html>
tag for better accessibility. - Comments: Added comments to explain the CSS, relating it to Tailwind CSS where applicable, for easier understanding.
Step 3: Updated Flask Backend (app.py)
from flask import Flask, request, render_template, session, redirect, url_for
import openai
import os
from dotenv import load_dotenv
import time
from typing import List, Dict
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
app = Flask(__name__)
app.secret_key = os.urandom(24) # Required for session management
# --- Constants ---
DEFAULT_MODEL = "gpt-4o"
SYSTEM_PROMPT = "You are a helpful, friendly, and knowledgeable assistant. Answer all questions clearly, concisely, and in a conversational tone. When appropriate, provide code examples."
SESSION_MESSAGES_KEY = "conversation" # Consistent key for session
# --- Helper Functions ---
def get_openai_response(messages: List[Dict[str, str]], model: str = DEFAULT_MODEL) -> str:
"""
Sends a message to OpenAI's Chat API and handles potential errors.
Args:
messages: A list of message dictionaries.
model: The OpenAI model to use.
Returns:
The assistant's reply, or an error message.
"""
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=60
)
return response.choices[0].message.content
except openai.error.OpenAIError as e:
# Log the error for debugging
print(f"OpenAI API error: {e}")
return f"Sorry, there was an error communicating with the AI: {e}"
except Exception as e:
print(f"Unexpected error: {e}")
return "Sorry, an unexpected error occurred."
def initialize_session_state():
"""Initializes session state."""
if SESSION_MESSAGES_KEY not in session:
session[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
if "model" not in session:
session["model"] = DEFAULT_MODEL
def clear_conversation():
"""Clears the conversation history from the session."""
session[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
session.modified = True # Ensure session is saved
return redirect(url_for("chat")) # Redirect to the chat route
# --- Routes ---
@app.route("/", methods=["GET", "POST"])
def chat():
initialize_session_state()
conversation = session[SESSION_MESSAGES_KEY]
model = session["model"]
if request.method == "POST":
user_input = request.form["user_input"]
conversation.append({"role": "user", "content": user_input})
reply = get_openai_response(conversation, model)
conversation.append({"role": "assistant", "content": reply})
session[SESSION_MESSAGES_KEY] = conversation
session.modified = True # Important: You need to mark the session as modified
return render_template("chat.html", history=conversation[1:]) # Skip system message
return render_template("chat.html", history=conversation[1:]) # Skip system message
@app.route("/clear", methods=["POST"]) # New route to handle clearing the chat
def clear_chat():
return clear_conversation()
if __name__ == "__main__":
app.run(debug=True)
Let's break down this Flask application code for a chatbot:
1. Imports and Setup
- Essential Flask components and OpenAI integration
- Environment variables loading with python-dotenv
- Secret key generation for session management
2. Core Configuration
- Default model set to "gpt-4o"
- System prompt defining the AI's personality and behavior
- Session management for conversation persistence
3. Helper Functions
- get_openai_response(): Handles API communication with OpenAI, including error handling
- initialize_session_state(): Sets up initial conversation state and model settings
- clear_conversation(): Resets the chat history to initial state
4. Routes
- Main route ("/"):
- Handles both GET and POST requests
- Manages conversation flow and message history
- Renders the chat template with conversation history
- Clear route ("/clear"):
- Provides functionality to reset the conversation
The example implements a robust chatbot that maintains conversation history through Flask sessions, handles OpenAI API communication efficiently, and includes comprehensive error handling for reliability.
4.2.4 Optional Enhancements
Here are some advanced features you can implement to enhance your chatbot's functionality and user experience:
Dark mode toggle using CSS
- Implement a theme switcher that changes the color scheme
- Create a toggle button with smooth transition animations
- Define separate color palettes for light and dark modes
- Use CSS variables for easy theme management
- Define root-level CSS variables for colors, shadows, and backgrounds
- Implement a single source of truth for theme-related styles
- Store user preference in local storage
- Save theme preference using browser's localStorage API
- Automatically apply saved preference on page reload
- Respect system-level dark mode settings using prefers-color-scheme media query
Avatar icons for user and assistant
- Add visual distinction between participants
- Use different colors and shapes to clearly identify messages from users versus the AI assistant
- Include subtle visual cues like message orientation (left/right alignment)
- Use custom images or default profile pictures
- Allow users to upload their own profile pictures
- Provide a default set of professional avatars for users who don't upload custom images
- Generate unique AI assistant avatars that reflect its personality
- Implement smooth transitions between messages
- Add fade-in animations when new messages appear
- Include typing indicators while the AI is generating responses
- Use subtle scaling animations when hovering over messages
Speech-to-text input using browser APIs
- Integrate the Web Speech API for voice recognition
- Use the SpeechRecognition interface to capture audio input
- Implement error handling for cases when the browser doesn't support speech recognition
- Add microphone permission handling and user feedback
- Add real-time transcription feedback
- Display interim results as the user speaks
- Implement visual indicators for active listening state
- Add confidence scores for transcription accuracy
- Handle multiple language support
- Configure recognition for different languages using BCP 47 language tags
- Allow users to switch between languages dynamically
- Implement dialect detection and regional accent handling
Voice replies using OpenAI's TTS output and JavaScript
- Convert chatbot responses to natural-sounding speech
- Use OpenAI's Text-to-Speech API to generate high-quality audio
- Support multiple languages and accents for international users
- Handle text preprocessing for better pronunciation
- Implement playback controls
- Add play/pause, speed control, and volume adjustment
- Include progress bar for longer responses
- Enable keyboard shortcuts for quick control
- Add options for different voices and speaking rates
- Offer selection of voice personalities (casual, professional, etc.)
- Allow customizable speaking speed (0.5x to 2x)
- Implement voice pitch and emphasis controls
In this chapter, we have explored how to transform a basic chatbot into a sophisticated, user-friendly interface that delivers a truly interactive experience. This enhancement can be accomplished through two distinct approaches:
Streamlit: This modern framework excels at rapid development and offers numerous advantages for building chatbots:
- Pre-built chat interface components
- Ready-to-use message bubbles, input fields, and chat layouts
- Built-in components for file uploads and media handling
- Simplified state management
- Automatic handling of session state and caching
- Easy implementation of conversation history
- Quick prototyping capabilities
- Live reloading for rapid development
- Intuitive API for fast iteration
- Minimal setup requirements
- Single-file applications possible
- No complex configuration needed
Flask: This versatile micro-framework provides developers with complete control through:
- Complete control over HTML structure
- Custom templating for precise layout control
- Freedom to implement any design pattern
- Custom CSS styling options
- Full control over styling and animations
- Integration with any CSS framework
- Advanced routing capabilities
- Complex URL patterns and parameters
- RESTful API implementation
- Granular session management
- Custom session handling and storage
- Fine-grained control over user data
We have implemented several key features that transform this basic chatbot into a professional-grade application:
- Robust conversation memory management
- Implements secure session storage for chat history
- Maintains context across multiple interactions
- Handles conversation state cleanup and management
- Intuitive chat history visualization
- Clear message threading and organization
- Distinct visual separation between user and AI responses
- Timestamp and message status indicators
- Smooth response animations and transitions
- Loading states during API calls
- Fade-in effects for new messages
- Smooth scrolling to latest messages
- Professional UI/UX design elements
- Consistent color scheme and typography
- Responsive layout for all screen sizes
- Accessibility-compliant interface elements
These enhancements work together to create a chatbot that not only functions efficiently but also provides an engaging, professional experience that feels natural and responsive to users. Each feature has been carefully implemented to ensure optimal performance while maintaining a seamless user experience throughout the conversation flow.
4.2 Creating Interactive User Interfaces
User interfaces are the bridge between your chatbot's intelligence and its users. A well-designed UI can transform a capable AI system into an engaging, accessible tool that users love to interact with. Creating an effective chatbot interface requires careful consideration of user experience principles, visual design elements, and interaction patterns.
This section explores the art and science of building intuitive chatbot interfaces. We'll examine both the technical implementation and design considerations that make a chatbot truly user-friendly. You'll learn how to create interfaces that not only look professional but also provide meaningful feedback, handle errors gracefully, and guide users through natural conversations.
Whether you're building a customer service bot, a virtual assistant, or an AI-powered learning tool, the principles and techniques covered here will help you create interfaces that enhance rather than hinder the user experience. We'll look at implementation approaches using both Streamlit and Flask, giving you the flexibility to choose the tools that best fit your project's needs.
4.2.1 Why UI Matters in a Chatbot
The success of a chatbot heavily depends on its user interface and overall user experience. No matter how sophisticated your AI model might be, users will struggle to engage with it effectively if the interface is difficult to use or unintuitive. This is why creating well-designed, user-friendly interfaces is crucial. We'll focus on building intuitive, responsive, and user-friendly UIs that not only look professional but also create a natural flow of conversation between the user and the AI.
Our approach emphasizes three fundamental aspects of interface design that are critical for creating an effective chatbot:
User Experience (UX)
Creating interfaces that are easy to navigate and understand, with clear visual hierarchies and intuitive interaction patterns. A well-designed UX considers several key aspects:
- Information Architecture: Organizing content in a logical, easy-to-follow structure that matches users' mental models.
- Visual Design: Using consistent color schemes, typography, and spacing to create clear visual hierarchies that guide users' attention.
- Interaction Design: Implementing intuitive controls and navigation patterns that feel familiar and predictable to users.
- Feedback Mechanisms: Providing clear visual and textual cues that help users understand:
- When their message is being processed
- When the chatbot is "thinking"
- If an error occurs
- Whether their input was received successfully
- Cognitive Load Management: Minimizing the mental effort required to use the interface by:
- Breaking complex tasks into smaller steps
- Using familiar design patterns
- Providing clear instructions when needed
- Maintaining consistent behavior throughout the interface
This thoughtful approach to UX design reduces friction, increases user engagement, and makes the chatbot feel natural and effortless to use.
Responsiveness
Ensuring the interface provides immediate feedback and maintains smooth performance across different devices and screen sizes. This involves several key aspects:
- Performance Optimization:
- Implementing efficient loading states that show users their actions are being processed
- Optimizing response times through techniques like request debouncing and caching
- Using progressive loading for chat history to handle large conversations
- Device Compatibility:
- Using responsive design principles to ensure the chatbot works seamlessly across devices
- Implementing fluid layouts that adjust to different screen sizes
- Ensuring touch-friendly interface elements for mobile users
- Testing and optimizing for various browsers and platforms
- Adaptive UI Elements:
- Creating flexible chat bubbles that resize based on content
- Implementing collapsible menus and controls for smaller screens
- Using relative units (em, rem, vh, vw) instead of fixed pixels
- Ensuring proper text wrapping and readability at all sizes
The interface should dynamically adapt to different screen sizes while maintaining functionality and visual appeal, providing a consistent experience whether accessed from a smartphone, tablet, or desktop computer.
Accessibility
Making the chatbot usable for people with different abilities and technical backgrounds is crucial for ensuring inclusive access. This involves several key considerations:
- Screen Reader Compatibility
- Implementing proper ARIA labels and roles to describe UI elements
- Ensuring meaningful heading structure and navigation
- Providing text alternatives for all non-text content
- Keyboard Navigation
- Supporting full keyboard control of all features
- Implementing visible focus indicators
- Creating logical tab order through the interface
- Visual Design
- Maintaining sufficient color contrast ratios (minimum 4.5:1)
- Avoiding color as the only means of conveying information
- Supporting text resizing without loss of functionality
- Technical Considerations
- Following Web Content Accessibility Guidelines (WCAG) 2.1 Level AA standards
- Regular testing with accessibility tools and screen readers
- Providing alternatives for complex interactions
By implementing these accessibility features, you ensure that your chatbot can be effectively used by people with various disabilities, including visual, auditory, motor, and cognitive impairments. This not only complies with legal requirements but also demonstrates a commitment to universal design principles.
To create an effective and user-friendly chatbot interface, we'll explore these essential components in detail:
- Building an Intuitive Chat Interface
- Implementation of clean, modern design principles that prioritize readability and user engagement
- Careful consideration of spacing to create visual breathing room between elements
- Strategic use of typography to establish clear information hierarchy
- Consistent visual elements that guide users through the conversation flow
- Managing Conversation History
- Implementation of efficient chat log storage and retrieval systems
- Integration of timestamp functionality for better conversation tracking
- Creation of distinct visual styles for user and bot messages
- Development of smooth scrolling mechanics for longer conversations
- Optimizing Response Presentation
- Careful selection of fonts and text sizes for maximum readability
- Implementation of consistent spacing patterns between message elements
- Special formatting considerations for different content types (code blocks, lists, etc.)
- Integration of visual indicators for message status and type
- Implementing Robust Feedback Systems
- Creation of subtle but visible loading animations during response generation
- Development of clear error messages that guide users toward solutions
- Implementation of recovery mechanisms for common error scenarios
- Integration of status indicators to keep users informed of system state
You'll get comprehensive examples in both Streamlit and Flask, allowing you to choose the framework that best suits your development style and project requirements. Each example includes detailed explanations and best practices for implementation.
4.2.2 Streamlit Interactive Chat UI
This example demonstrates how to create an interactive chatbot using Streamlit and OpenAI, which we'll build upon further. Using Streamlit, we'll create a user-friendly chat interface that maintains conversation history. This use case showcases key concepts and best practices for building a robust, interactive chatbot.
Step 1: Install Dependencies
pip install streamlit openai python-dotenv
streamlit
: A Python library for creating interactive web applications.openai
: The OpenAI Python library for interacting with the GPT-4o model.python-dotenv
: A library to load environment variables from a.env
file.
Step 2: Create the Streamlit App (chatbot.py)
import streamlit as st
import openai
import os
from dotenv import load_dotenv
import time # For handling potential API errors
from typing import List, Dict # For type hinting
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
# --- Constants ---
DEFAULT_MODEL = "gpt-4o"
SYSTEM_PROMPT = "You are a helpful, friendly, and knowledgeable assistant. Answer all questions clearly, concisely, and in a conversational tone. When appropriate, provide code examples."
SESSION_MESSAGES_KEY = "messages" # Consistent key for session state
DISPLAY_MESSAGES_KEY = "display_messages"
# --- Helper Functions ---
def get_openai_response(messages: List[Dict[str, str]], model: str = DEFAULT_MODEL) -> str:
"""
Sends a message to OpenAI's Chat API and handles potential errors with robust error handling.
Args:
messages (List[Dict[str, str]]): A list of message dictionaries, representing the conversation history.
model (str, optional): The OpenAI model to use. Defaults to DEFAULT_MODEL.
Returns:
str: The assistant's reply, or an error message.
Raises:
openai.error.OpenAIError: If there is an error with the OpenAI API.
Exception: For other unexpected errors.
"""
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=60, # Add a timeout to prevent hanging
)
return response.choices[0].message.content
except openai.error.OpenAIError as e:
st.error(f"OpenAI API Error: {e}")
return f"Sorry, I encountered an error with the OpenAI API: {e}"
except Exception as e:
st.error(f"An unexpected error occurred: {e}")
return "Sorry, I encountered an unexpected error."
def initialize_session_state():
"""
Initializes session state variables. This function should be called
at the beginning of the main() function. It ensures that session
state is initialized even if the user doesn't immediately enter a query.
"""
if SESSION_MESSAGES_KEY not in st.session_state:
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
if DISPLAY_MESSAGES_KEY not in st.session_state:
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}] # Separate list for displayed messages
if "model" not in st.session_state:
st.session_state.model = DEFAULT_MODEL
def clear_chat_history():
"""Clears the chat history and resets to the initial state."""
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state.user_input = "" # Clear the input field
st.rerun() # Force a rerun to update the display
# --- Main App ---
def main():
"""
Main function to run the Streamlit application.
"""
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
st.title("🤖 GPT-4o Assistant")
initialize_session_state() # Initialize session state
# --- Sidebar ---
st.sidebar.header("Settings")
model = st.sidebar.selectbox("Model", ["gpt-4o", "gpt-3.5-turbo"], index=0)
st.session_state.model = model
clear_history_button = st.sidebar.button("Clear Chat", on_click=clear_chat_history) # corrected to clear_chat_history
# Display chat history, রাখা changed to display_messages
for message in st.session_state[DISPLAY_MESSAGES_KEY]:
if message["role"] != "system": # Don't display the system prompt
speaker = "🧑💻 You" if message["role"] == "user" else "🤖 Assistant"
with st.chat_message(message["role"]):
st.markdown(f"**{speaker}:** {message['content']}")
# User input, রাখা outside the conditional block
user_input = st.chat_input("Ask me anything...", key="user_input")
# Process user input
if user_input:
st.session_state[SESSION_MESSAGES_KEY].append({"role": "user", "content": user_input})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "user", "content": user_input})
# Add spinner while GPT-4o thinks
with st.chat_message("assistant"):
placeholder = st.empty() # Reserve a placeholder for the response
with st.spinner("Thinking..."):
reply = get_openai_response(st.session_state[SESSION_MESSAGES_KEY], model=st.session_state.model) #added model
placeholder.markdown(f"**🤖 Assistant:** {reply}") # Replace placeholder with full response
st.session_state[SESSION_MESSAGES_KEY].append({"role": "assistant", "content": reply})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "assistant", "content": reply})
# Clear the input field after sending the message
st.session_state.user_input = ""
st.rerun()
if __name__ == "__main__":
main()
Code Breakdown
Let's break down the code step by step.
Imports:
import streamlit as st
import openai
import os
from dotenv import load_dotenv
import time # For handling potential API errors
from typing import List, Dict # For type hinting
Imports the necessary libraries:
streamlit
: For creating the web interface.openai
: For interacting with the OpenAI API.os
: For accessing environment variables.dotenv
: For loading environment variables from a.env
file.time
: For handling potential API errors by waiting.typing
: For type hinting to improve code readability.
Environment Variables:
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
Loads the OpenAI API key from a .env
file and sets it for the OpenAI library.
Constants:
DEFAULT_MODEL = "gpt-4o"
SYSTEM_PROMPT = "You are a helpful, friendly, and knowledgeable assistant. Answer all questions clearly, concisely, and in a conversational tone. When appropriate, provide code examples."
SESSION_MESSAGES_KEY = "messages" # Consistent key for session state
DISPLAY_MESSAGES_KEY = "display_messages"
DEFAULT_MODEL
: The default OpenAI model used for the chatbot.SYSTEM_PROMPT
: The initial message sent to the OpenAI API to set the behavior of the assistant.SESSION_MESSAGES_KEY
: Key to use for the main conversation history in the session state.DISPLAY_MESSAGES_KEY
: Key to use for the conversation history that is displayed in the UI.
Helper Functions:
get_openai_response()
:
def get_openai_response(messages: List[Dict[str, str]], model: str = DEFAULT_MODEL) -> str:
"""
Sends a message to OpenAI's Chat API and handles potential errors with robust error handling.
Args:
messages (List[Dict[str, str]]): A list of message dictionaries, representing the conversation history.
model (str, optional): The OpenAI model to use. Defaults to DEFAULT_MODEL.
Returns:
str: The assistant's reply, or an error message.
Raises:
openai.error.OpenAIError: If there is an error with the OpenAI API.
Exception: For other unexpected errors.
"""
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=60, # Add a timeout to prevent hanging
)
return response.choices[0].message.content
except openai.error.OpenAIError as e:
st.error(f"OpenAI API Error: {e}")
return f"Sorry, I encountered an error with the OpenAI API: {e}"
except Exception as e:
st.error(f"An unexpected error occurred: {e}")
return "Sorry, I encountered an unexpected error."
Sends the user's input to the OpenAI API and retrieves the response. This function also includes error handling using a try...except
block to catch potential openai.error.OpenAIError
exceptions and a general Exception
for other errors. A timeout is added to prevent the app from hanging indefinitely.
initialize_session_state()
:
def initialize_session_state():
"""
Initializes session state variables. This function should be called
at the beginning of the main() function. It ensures that session
state is initialized even if the user doesn't immediately enter a query.
"""
if SESSION_MESSAGES_KEY not in st.session_state:
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
if DISPLAY_MESSAGES_KEY not in st.session_state:
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}] # Separate list for displayed messages
if "model" not in st.session_state:
st.session_state.model = DEFAULT_MODEL
Initializes the session state variables:
SESSION_MESSAGES_KEY
: Stores the full conversation history.DISPLAY_MESSAGES_KEY
: Stores the conversation history that is displayed to the user.model
: The LLM modelclear_chat_history()
:
def clear_chat_history():
"""Clears the chat history and resets to the initial state."""
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state.user_input = "" # Clear the input field
st.rerun() # Force a rerun to update the display
Clears the chat history when the user clicks the "Clear Chat" button.
Main App:
def main():
"""
Main function to run the Streamlit application.
"""
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
st.title("🤖 GPT-4o Assistant")
initialize_session_state()
# --- Sidebar ---
st.sidebar.header("Settings")
model = st.sidebar.selectbox("Model", ["gpt-4o", "gpt-3.5-turbo"], index=0)
st.session_state.model = model
clear_history_button = st.sidebar.button("Clear Chat", on_click=clear_chat_history)
# Display chat history
for message in st.session_state[DISPLAY_MESSAGES_KEY]:
if message["role"] != "system": # Don't display the system prompt
speaker = "🧑💻 You" if message["role"] == "user" else "🤖 Assistant"
with st.chat_message(message["role"]):
st.markdown(f"**{speaker}:** {message['content']}")
# User input
user_input = st.chat_input("Ask me anything...", key="user_input")
# Process user input
if user_input:
st.session_state[SESSION_MESSAGES_KEY].append({"role": "user", "content": user_input})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "user", "content": user_input})
# Add spinner while GPT-4o thinks
with st.chat_message("assistant"):
placeholder = st.empty() # Reserve a placeholder for the response
with st.spinner("Thinking..."):
reply = get_openai_response(st.session_state[SESSION_MESSAGES_KEY], model=st.session_state.model) # added model
placeholder.markdown(f"**🤖 Assistant:** {reply}") # Replace placeholder with full response
st.session_state[SESSION_MESSAGES_KEY].append({"role": "assistant", "content": reply})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "assistant", "content": reply})
# Clear the input field after sending the message
st.session_state.user_input = ""
st.rerun()
if __name__ == "__main__":
main()
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
: Sets the page title and icon in the browser tab.st.title("🤖 GPT-4o Assistant")
: Sets the title of the Streamlit application.initialize_session_state()
: Initializes the sessionst.sidebar.header("Settings")
: Creates a sidebar section titled "Settings."model = st.sidebar.selectbox(...)
: Creates a dropdown in the sidebar to select the OpenAI model.clear_history_button = st.sidebar.button("Clear Chat", on_click=clear_chat_history)
: Adds a button to the sidebar to clear the chat history.- The chat history is displayed using
st.chat_message
, with different styling for the user and assistant messages. user_input = st.chat_input("Ask me anything...", key="user_input")
: Creates a text input field for the user to type their query. Thekey
argument is important for Streamlit to manage the state of the input field.- The application retrieves the user's input, sends it to the OpenAI API using the
get_openai_response
function, and displays the response. - The conversation history is stored in
st.session_state.messages
as a list of dictionaries. Each dictionary has a "role" (either "user" or "assistant") and "content". st.rerun()
is used to update the display after the assistant responds.- Run the app:
To run the app, save the code to a file named chatbot.py and run the following command in your terminal:
streamlit run chatbot.py
4.2.3 Flask + Custom HTML/CSS Chat UI
This example implements a chatbot using Flask and OpenAI's GPT-4o model, with a focus on allowing developers to customize the chat interface using their own HTML and CSS. This approach provides greater flexibility in styling and layout compared to using pre-built UI components. This code provide a robust and customizable chatbot, explaining key concepts and best practices for intermediate developers.
Step 1: Install Dependencies
pip install flask openai python-dotenv
flask
: A web framework for building the chatbot application.openai
: The OpenAI Python library for interacting with the GPT-4o model.python-dotenv
: A library to load environment variables from a.env
file.
Step 2: Updated Flask Template (templates/chat.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GPT-4o Chat Assistant</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<style>
/* --- General Styles --- */
body {
font-family: 'Inter', sans-serif; /* Modern font */
background-color: #f3f4f6; /* Tailwind's gray-100 */
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
color: #1f2937; /* Tailwind's gray-800 */
}
.container {
max-width: 800px; /* Increased max-width */
width: 100%;
background-color: #fff; /* White background */
padding: 30px;
border-radius: 0.75rem; /* Tailwind's rounded-lg */
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); /* Tailwind's shadow-md */
}
h2 {
font-size: 1.875rem; /* Tailwind's text-2xl */
font-weight: 600; /* Tailwind's font-semibold */
margin-bottom: 2rem; /* Tailwind's mb-8 */
color: #1e293b; /* Tailwind's gray-900 */
text-align: center;
}
/* --- Message Styles --- */
.message {
margin-bottom: 1.5rem; /* Tailwind's mb-6 */
display: flex;
flex-direction: column;
}
.message p {
padding: 1rem; /* Tailwind's p-4 */
border-radius: 1rem; /* Tailwind's rounded-lg */
max-width: 80%; /* Limit message width */
}
.user p {
background-color: #e0f2fe; /* Tailwind's bg-blue-100 */
color: #1d4ed8; /* Tailwind's text-blue-700 */
margin-left: auto; /* Push user message to the right */
}
.assistant p {
background-color: #f0fdf4; /* Tailwind's bg-green-100 */
color: #15803d; /* Tailwind's text-green-700 */
}
.message strong {
font-size: 0.875rem; /* Tailwind's text-sm */
font-weight: 600; /* Tailwind's font-semibold */
margin-bottom: 0.25rem; /* Tailwind's mb-1 */
}
.user strong {
color: #1e40af; /* Tailwind's text-blue-800 */
}
.assistant strong {
color: #16a34a; /* Tailwind's text-green-800 */
}
/* --- Form Styles --- */
form {
margin-top: 2rem; /* Tailwind's mt-8 */
display: flex;
flex-direction: column;
gap: 0.5rem; /* Tailwind's gap-2 */
}
textarea {
width: 100%;
padding: 0.75rem; /* Tailwind's p-3 */
border-radius: 0.5rem; /* Tailwind's rounded-md */
border: 1px solid #d1d5db; /* Tailwind's border-gray-300 */
resize: none;
font-size: 1rem; /* Tailwind's text-base */
line-height: 1.5rem; /* Tailwind's leading-relaxed */
margin-bottom: 0.25rem; /* Tailwind's mb-1 */
box-shadow: inset 0 2px 4px rgba(0,0,0,0.06); /* Inner shadow, more subtle */
}
textarea:focus {
outline: none;
border-color: #3b82f6; /* Tailwind's border-blue-500 */
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15); /* Tailwind's ring-blue-500 with opacity */
}
input[type="submit"] {
padding: 0.75rem 1.5rem; /* Tailwind's px-6 py-3 */
border-radius: 0.5rem; /* Tailwind's rounded-md */
background-color: #3b82f6; /* Tailwind's bg-blue-500 */
color: #fff; /* White text */
font-size: 1rem; /* Tailwind's text-base */
font-weight: 600; /* Tailwind's font-semibold */
cursor: pointer;
transition: background-color 0.3s ease; /* Smooth transition */
border: none;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1); /* Tailwind's shadow-sm */
}
input[type="submit"]:hover {
background-color: #2563eb; /* Tailwind's bg-blue-700 on hover */
}
input[type="submit"]:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3); /* Tailwind's ring-blue-500 with more opacity*/
}
/* --- Responsive Adjustments --- */
@media (max-width: 768px) { /* Medium screens and below (md breakpoint in Tailwind is 768px) */
.container {
padding: 20px;
}
textarea {
height: 100px; /* Make textarea taller on smaller screens */
}
}
</style>
</head>
<body>
<div class="container">
<h2>🧠 GPT-4o Chat Assistant</h2>
{% for msg in history %}
<div class="message {{ msg.role }}">
<p><strong>{{ msg.role.capitalize() }}:</strong> {{ msg.content }}</p>
</div>
{% endfor %}
<form method="post">
<textarea name="user_input" placeholder="Type your message..."></textarea><br>
<input type="submit" value="Send Message">
</form>
</div>
</body>
</html>
HTML template:
- Modern Design: The template features a contemporary design approach inspired by Tailwind CSS. This includes:
- Clean font (Inter)
- Spacious padding and margins
- Rounded corners
- Subtle shadows
- Consistent color palette
- Responsive Design: Added a media query to adjust the layout for smaller screens (tablets and phones).
- Improved Form: The form is styled with a focus state, better margins, and a smooth hover effect.
- Semantic HTML: Uses
lang="en"
in the<html>
tag for better accessibility. - Comments: Added comments to explain the CSS, relating it to Tailwind CSS where applicable, for easier understanding.
Step 3: Updated Flask Backend (app.py)
from flask import Flask, request, render_template, session, redirect, url_for
import openai
import os
from dotenv import load_dotenv
import time
from typing import List, Dict
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
app = Flask(__name__)
app.secret_key = os.urandom(24) # Required for session management
# --- Constants ---
DEFAULT_MODEL = "gpt-4o"
SYSTEM_PROMPT = "You are a helpful, friendly, and knowledgeable assistant. Answer all questions clearly, concisely, and in a conversational tone. When appropriate, provide code examples."
SESSION_MESSAGES_KEY = "conversation" # Consistent key for session
# --- Helper Functions ---
def get_openai_response(messages: List[Dict[str, str]], model: str = DEFAULT_MODEL) -> str:
"""
Sends a message to OpenAI's Chat API and handles potential errors.
Args:
messages: A list of message dictionaries.
model: The OpenAI model to use.
Returns:
The assistant's reply, or an error message.
"""
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=60
)
return response.choices[0].message.content
except openai.error.OpenAIError as e:
# Log the error for debugging
print(f"OpenAI API error: {e}")
return f"Sorry, there was an error communicating with the AI: {e}"
except Exception as e:
print(f"Unexpected error: {e}")
return "Sorry, an unexpected error occurred."
def initialize_session_state():
"""Initializes session state."""
if SESSION_MESSAGES_KEY not in session:
session[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
if "model" not in session:
session["model"] = DEFAULT_MODEL
def clear_conversation():
"""Clears the conversation history from the session."""
session[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
session.modified = True # Ensure session is saved
return redirect(url_for("chat")) # Redirect to the chat route
# --- Routes ---
@app.route("/", methods=["GET", "POST"])
def chat():
initialize_session_state()
conversation = session[SESSION_MESSAGES_KEY]
model = session["model"]
if request.method == "POST":
user_input = request.form["user_input"]
conversation.append({"role": "user", "content": user_input})
reply = get_openai_response(conversation, model)
conversation.append({"role": "assistant", "content": reply})
session[SESSION_MESSAGES_KEY] = conversation
session.modified = True # Important: You need to mark the session as modified
return render_template("chat.html", history=conversation[1:]) # Skip system message
return render_template("chat.html", history=conversation[1:]) # Skip system message
@app.route("/clear", methods=["POST"]) # New route to handle clearing the chat
def clear_chat():
return clear_conversation()
if __name__ == "__main__":
app.run(debug=True)
Let's break down this Flask application code for a chatbot:
1. Imports and Setup
- Essential Flask components and OpenAI integration
- Environment variables loading with python-dotenv
- Secret key generation for session management
2. Core Configuration
- Default model set to "gpt-4o"
- System prompt defining the AI's personality and behavior
- Session management for conversation persistence
3. Helper Functions
- get_openai_response(): Handles API communication with OpenAI, including error handling
- initialize_session_state(): Sets up initial conversation state and model settings
- clear_conversation(): Resets the chat history to initial state
4. Routes
- Main route ("/"):
- Handles both GET and POST requests
- Manages conversation flow and message history
- Renders the chat template with conversation history
- Clear route ("/clear"):
- Provides functionality to reset the conversation
The example implements a robust chatbot that maintains conversation history through Flask sessions, handles OpenAI API communication efficiently, and includes comprehensive error handling for reliability.
4.2.4 Optional Enhancements
Here are some advanced features you can implement to enhance your chatbot's functionality and user experience:
Dark mode toggle using CSS
- Implement a theme switcher that changes the color scheme
- Create a toggle button with smooth transition animations
- Define separate color palettes for light and dark modes
- Use CSS variables for easy theme management
- Define root-level CSS variables for colors, shadows, and backgrounds
- Implement a single source of truth for theme-related styles
- Store user preference in local storage
- Save theme preference using browser's localStorage API
- Automatically apply saved preference on page reload
- Respect system-level dark mode settings using prefers-color-scheme media query
Avatar icons for user and assistant
- Add visual distinction between participants
- Use different colors and shapes to clearly identify messages from users versus the AI assistant
- Include subtle visual cues like message orientation (left/right alignment)
- Use custom images or default profile pictures
- Allow users to upload their own profile pictures
- Provide a default set of professional avatars for users who don't upload custom images
- Generate unique AI assistant avatars that reflect its personality
- Implement smooth transitions between messages
- Add fade-in animations when new messages appear
- Include typing indicators while the AI is generating responses
- Use subtle scaling animations when hovering over messages
Speech-to-text input using browser APIs
- Integrate the Web Speech API for voice recognition
- Use the SpeechRecognition interface to capture audio input
- Implement error handling for cases when the browser doesn't support speech recognition
- Add microphone permission handling and user feedback
- Add real-time transcription feedback
- Display interim results as the user speaks
- Implement visual indicators for active listening state
- Add confidence scores for transcription accuracy
- Handle multiple language support
- Configure recognition for different languages using BCP 47 language tags
- Allow users to switch between languages dynamically
- Implement dialect detection and regional accent handling
Voice replies using OpenAI's TTS output and JavaScript
- Convert chatbot responses to natural-sounding speech
- Use OpenAI's Text-to-Speech API to generate high-quality audio
- Support multiple languages and accents for international users
- Handle text preprocessing for better pronunciation
- Implement playback controls
- Add play/pause, speed control, and volume adjustment
- Include progress bar for longer responses
- Enable keyboard shortcuts for quick control
- Add options for different voices and speaking rates
- Offer selection of voice personalities (casual, professional, etc.)
- Allow customizable speaking speed (0.5x to 2x)
- Implement voice pitch and emphasis controls
In this chapter, we have explored how to transform a basic chatbot into a sophisticated, user-friendly interface that delivers a truly interactive experience. This enhancement can be accomplished through two distinct approaches:
Streamlit: This modern framework excels at rapid development and offers numerous advantages for building chatbots:
- Pre-built chat interface components
- Ready-to-use message bubbles, input fields, and chat layouts
- Built-in components for file uploads and media handling
- Simplified state management
- Automatic handling of session state and caching
- Easy implementation of conversation history
- Quick prototyping capabilities
- Live reloading for rapid development
- Intuitive API for fast iteration
- Minimal setup requirements
- Single-file applications possible
- No complex configuration needed
Flask: This versatile micro-framework provides developers with complete control through:
- Complete control over HTML structure
- Custom templating for precise layout control
- Freedom to implement any design pattern
- Custom CSS styling options
- Full control over styling and animations
- Integration with any CSS framework
- Advanced routing capabilities
- Complex URL patterns and parameters
- RESTful API implementation
- Granular session management
- Custom session handling and storage
- Fine-grained control over user data
We have implemented several key features that transform this basic chatbot into a professional-grade application:
- Robust conversation memory management
- Implements secure session storage for chat history
- Maintains context across multiple interactions
- Handles conversation state cleanup and management
- Intuitive chat history visualization
- Clear message threading and organization
- Distinct visual separation between user and AI responses
- Timestamp and message status indicators
- Smooth response animations and transitions
- Loading states during API calls
- Fade-in effects for new messages
- Smooth scrolling to latest messages
- Professional UI/UX design elements
- Consistent color scheme and typography
- Responsive layout for all screen sizes
- Accessibility-compliant interface elements
These enhancements work together to create a chatbot that not only functions efficiently but also provides an engaging, professional experience that feels natural and responsive to users. Each feature has been carefully implemented to ensure optimal performance while maintaining a seamless user experience throughout the conversation flow.
4.2 Creating Interactive User Interfaces
User interfaces are the bridge between your chatbot's intelligence and its users. A well-designed UI can transform a capable AI system into an engaging, accessible tool that users love to interact with. Creating an effective chatbot interface requires careful consideration of user experience principles, visual design elements, and interaction patterns.
This section explores the art and science of building intuitive chatbot interfaces. We'll examine both the technical implementation and design considerations that make a chatbot truly user-friendly. You'll learn how to create interfaces that not only look professional but also provide meaningful feedback, handle errors gracefully, and guide users through natural conversations.
Whether you're building a customer service bot, a virtual assistant, or an AI-powered learning tool, the principles and techniques covered here will help you create interfaces that enhance rather than hinder the user experience. We'll look at implementation approaches using both Streamlit and Flask, giving you the flexibility to choose the tools that best fit your project's needs.
4.2.1 Why UI Matters in a Chatbot
The success of a chatbot heavily depends on its user interface and overall user experience. No matter how sophisticated your AI model might be, users will struggle to engage with it effectively if the interface is difficult to use or unintuitive. This is why creating well-designed, user-friendly interfaces is crucial. We'll focus on building intuitive, responsive, and user-friendly UIs that not only look professional but also create a natural flow of conversation between the user and the AI.
Our approach emphasizes three fundamental aspects of interface design that are critical for creating an effective chatbot:
User Experience (UX)
Creating interfaces that are easy to navigate and understand, with clear visual hierarchies and intuitive interaction patterns. A well-designed UX considers several key aspects:
- Information Architecture: Organizing content in a logical, easy-to-follow structure that matches users' mental models.
- Visual Design: Using consistent color schemes, typography, and spacing to create clear visual hierarchies that guide users' attention.
- Interaction Design: Implementing intuitive controls and navigation patterns that feel familiar and predictable to users.
- Feedback Mechanisms: Providing clear visual and textual cues that help users understand:
- When their message is being processed
- When the chatbot is "thinking"
- If an error occurs
- Whether their input was received successfully
- Cognitive Load Management: Minimizing the mental effort required to use the interface by:
- Breaking complex tasks into smaller steps
- Using familiar design patterns
- Providing clear instructions when needed
- Maintaining consistent behavior throughout the interface
This thoughtful approach to UX design reduces friction, increases user engagement, and makes the chatbot feel natural and effortless to use.
Responsiveness
Ensuring the interface provides immediate feedback and maintains smooth performance across different devices and screen sizes. This involves several key aspects:
- Performance Optimization:
- Implementing efficient loading states that show users their actions are being processed
- Optimizing response times through techniques like request debouncing and caching
- Using progressive loading for chat history to handle large conversations
- Device Compatibility:
- Using responsive design principles to ensure the chatbot works seamlessly across devices
- Implementing fluid layouts that adjust to different screen sizes
- Ensuring touch-friendly interface elements for mobile users
- Testing and optimizing for various browsers and platforms
- Adaptive UI Elements:
- Creating flexible chat bubbles that resize based on content
- Implementing collapsible menus and controls for smaller screens
- Using relative units (em, rem, vh, vw) instead of fixed pixels
- Ensuring proper text wrapping and readability at all sizes
The interface should dynamically adapt to different screen sizes while maintaining functionality and visual appeal, providing a consistent experience whether accessed from a smartphone, tablet, or desktop computer.
Accessibility
Making the chatbot usable for people with different abilities and technical backgrounds is crucial for ensuring inclusive access. This involves several key considerations:
- Screen Reader Compatibility
- Implementing proper ARIA labels and roles to describe UI elements
- Ensuring meaningful heading structure and navigation
- Providing text alternatives for all non-text content
- Keyboard Navigation
- Supporting full keyboard control of all features
- Implementing visible focus indicators
- Creating logical tab order through the interface
- Visual Design
- Maintaining sufficient color contrast ratios (minimum 4.5:1)
- Avoiding color as the only means of conveying information
- Supporting text resizing without loss of functionality
- Technical Considerations
- Following Web Content Accessibility Guidelines (WCAG) 2.1 Level AA standards
- Regular testing with accessibility tools and screen readers
- Providing alternatives for complex interactions
By implementing these accessibility features, you ensure that your chatbot can be effectively used by people with various disabilities, including visual, auditory, motor, and cognitive impairments. This not only complies with legal requirements but also demonstrates a commitment to universal design principles.
To create an effective and user-friendly chatbot interface, we'll explore these essential components in detail:
- Building an Intuitive Chat Interface
- Implementation of clean, modern design principles that prioritize readability and user engagement
- Careful consideration of spacing to create visual breathing room between elements
- Strategic use of typography to establish clear information hierarchy
- Consistent visual elements that guide users through the conversation flow
- Managing Conversation History
- Implementation of efficient chat log storage and retrieval systems
- Integration of timestamp functionality for better conversation tracking
- Creation of distinct visual styles for user and bot messages
- Development of smooth scrolling mechanics for longer conversations
- Optimizing Response Presentation
- Careful selection of fonts and text sizes for maximum readability
- Implementation of consistent spacing patterns between message elements
- Special formatting considerations for different content types (code blocks, lists, etc.)
- Integration of visual indicators for message status and type
- Implementing Robust Feedback Systems
- Creation of subtle but visible loading animations during response generation
- Development of clear error messages that guide users toward solutions
- Implementation of recovery mechanisms for common error scenarios
- Integration of status indicators to keep users informed of system state
You'll get comprehensive examples in both Streamlit and Flask, allowing you to choose the framework that best suits your development style and project requirements. Each example includes detailed explanations and best practices for implementation.
4.2.2 Streamlit Interactive Chat UI
This example demonstrates how to create an interactive chatbot using Streamlit and OpenAI, which we'll build upon further. Using Streamlit, we'll create a user-friendly chat interface that maintains conversation history. This use case showcases key concepts and best practices for building a robust, interactive chatbot.
Step 1: Install Dependencies
pip install streamlit openai python-dotenv
streamlit
: A Python library for creating interactive web applications.openai
: The OpenAI Python library for interacting with the GPT-4o model.python-dotenv
: A library to load environment variables from a.env
file.
Step 2: Create the Streamlit App (chatbot.py)
import streamlit as st
import openai
import os
from dotenv import load_dotenv
import time # For handling potential API errors
from typing import List, Dict # For type hinting
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
# --- Constants ---
DEFAULT_MODEL = "gpt-4o"
SYSTEM_PROMPT = "You are a helpful, friendly, and knowledgeable assistant. Answer all questions clearly, concisely, and in a conversational tone. When appropriate, provide code examples."
SESSION_MESSAGES_KEY = "messages" # Consistent key for session state
DISPLAY_MESSAGES_KEY = "display_messages"
# --- Helper Functions ---
def get_openai_response(messages: List[Dict[str, str]], model: str = DEFAULT_MODEL) -> str:
"""
Sends a message to OpenAI's Chat API and handles potential errors with robust error handling.
Args:
messages (List[Dict[str, str]]): A list of message dictionaries, representing the conversation history.
model (str, optional): The OpenAI model to use. Defaults to DEFAULT_MODEL.
Returns:
str: The assistant's reply, or an error message.
Raises:
openai.error.OpenAIError: If there is an error with the OpenAI API.
Exception: For other unexpected errors.
"""
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=60, # Add a timeout to prevent hanging
)
return response.choices[0].message.content
except openai.error.OpenAIError as e:
st.error(f"OpenAI API Error: {e}")
return f"Sorry, I encountered an error with the OpenAI API: {e}"
except Exception as e:
st.error(f"An unexpected error occurred: {e}")
return "Sorry, I encountered an unexpected error."
def initialize_session_state():
"""
Initializes session state variables. This function should be called
at the beginning of the main() function. It ensures that session
state is initialized even if the user doesn't immediately enter a query.
"""
if SESSION_MESSAGES_KEY not in st.session_state:
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
if DISPLAY_MESSAGES_KEY not in st.session_state:
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}] # Separate list for displayed messages
if "model" not in st.session_state:
st.session_state.model = DEFAULT_MODEL
def clear_chat_history():
"""Clears the chat history and resets to the initial state."""
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state.user_input = "" # Clear the input field
st.rerun() # Force a rerun to update the display
# --- Main App ---
def main():
"""
Main function to run the Streamlit application.
"""
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
st.title("🤖 GPT-4o Assistant")
initialize_session_state() # Initialize session state
# --- Sidebar ---
st.sidebar.header("Settings")
model = st.sidebar.selectbox("Model", ["gpt-4o", "gpt-3.5-turbo"], index=0)
st.session_state.model = model
clear_history_button = st.sidebar.button("Clear Chat", on_click=clear_chat_history) # corrected to clear_chat_history
# Display chat history, রাখা changed to display_messages
for message in st.session_state[DISPLAY_MESSAGES_KEY]:
if message["role"] != "system": # Don't display the system prompt
speaker = "🧑💻 You" if message["role"] == "user" else "🤖 Assistant"
with st.chat_message(message["role"]):
st.markdown(f"**{speaker}:** {message['content']}")
# User input, রাখা outside the conditional block
user_input = st.chat_input("Ask me anything...", key="user_input")
# Process user input
if user_input:
st.session_state[SESSION_MESSAGES_KEY].append({"role": "user", "content": user_input})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "user", "content": user_input})
# Add spinner while GPT-4o thinks
with st.chat_message("assistant"):
placeholder = st.empty() # Reserve a placeholder for the response
with st.spinner("Thinking..."):
reply = get_openai_response(st.session_state[SESSION_MESSAGES_KEY], model=st.session_state.model) #added model
placeholder.markdown(f"**🤖 Assistant:** {reply}") # Replace placeholder with full response
st.session_state[SESSION_MESSAGES_KEY].append({"role": "assistant", "content": reply})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "assistant", "content": reply})
# Clear the input field after sending the message
st.session_state.user_input = ""
st.rerun()
if __name__ == "__main__":
main()
Code Breakdown
Let's break down the code step by step.
Imports:
import streamlit as st
import openai
import os
from dotenv import load_dotenv
import time # For handling potential API errors
from typing import List, Dict # For type hinting
Imports the necessary libraries:
streamlit
: For creating the web interface.openai
: For interacting with the OpenAI API.os
: For accessing environment variables.dotenv
: For loading environment variables from a.env
file.time
: For handling potential API errors by waiting.typing
: For type hinting to improve code readability.
Environment Variables:
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
Loads the OpenAI API key from a .env
file and sets it for the OpenAI library.
Constants:
DEFAULT_MODEL = "gpt-4o"
SYSTEM_PROMPT = "You are a helpful, friendly, and knowledgeable assistant. Answer all questions clearly, concisely, and in a conversational tone. When appropriate, provide code examples."
SESSION_MESSAGES_KEY = "messages" # Consistent key for session state
DISPLAY_MESSAGES_KEY = "display_messages"
DEFAULT_MODEL
: The default OpenAI model used for the chatbot.SYSTEM_PROMPT
: The initial message sent to the OpenAI API to set the behavior of the assistant.SESSION_MESSAGES_KEY
: Key to use for the main conversation history in the session state.DISPLAY_MESSAGES_KEY
: Key to use for the conversation history that is displayed in the UI.
Helper Functions:
get_openai_response()
:
def get_openai_response(messages: List[Dict[str, str]], model: str = DEFAULT_MODEL) -> str:
"""
Sends a message to OpenAI's Chat API and handles potential errors with robust error handling.
Args:
messages (List[Dict[str, str]]): A list of message dictionaries, representing the conversation history.
model (str, optional): The OpenAI model to use. Defaults to DEFAULT_MODEL.
Returns:
str: The assistant's reply, or an error message.
Raises:
openai.error.OpenAIError: If there is an error with the OpenAI API.
Exception: For other unexpected errors.
"""
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=60, # Add a timeout to prevent hanging
)
return response.choices[0].message.content
except openai.error.OpenAIError as e:
st.error(f"OpenAI API Error: {e}")
return f"Sorry, I encountered an error with the OpenAI API: {e}"
except Exception as e:
st.error(f"An unexpected error occurred: {e}")
return "Sorry, I encountered an unexpected error."
Sends the user's input to the OpenAI API and retrieves the response. This function also includes error handling using a try...except
block to catch potential openai.error.OpenAIError
exceptions and a general Exception
for other errors. A timeout is added to prevent the app from hanging indefinitely.
initialize_session_state()
:
def initialize_session_state():
"""
Initializes session state variables. This function should be called
at the beginning of the main() function. It ensures that session
state is initialized even if the user doesn't immediately enter a query.
"""
if SESSION_MESSAGES_KEY not in st.session_state:
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
if DISPLAY_MESSAGES_KEY not in st.session_state:
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}] # Separate list for displayed messages
if "model" not in st.session_state:
st.session_state.model = DEFAULT_MODEL
Initializes the session state variables:
SESSION_MESSAGES_KEY
: Stores the full conversation history.DISPLAY_MESSAGES_KEY
: Stores the conversation history that is displayed to the user.model
: The LLM modelclear_chat_history()
:
def clear_chat_history():
"""Clears the chat history and resets to the initial state."""
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state.user_input = "" # Clear the input field
st.rerun() # Force a rerun to update the display
Clears the chat history when the user clicks the "Clear Chat" button.
Main App:
def main():
"""
Main function to run the Streamlit application.
"""
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
st.title("🤖 GPT-4o Assistant")
initialize_session_state()
# --- Sidebar ---
st.sidebar.header("Settings")
model = st.sidebar.selectbox("Model", ["gpt-4o", "gpt-3.5-turbo"], index=0)
st.session_state.model = model
clear_history_button = st.sidebar.button("Clear Chat", on_click=clear_chat_history)
# Display chat history
for message in st.session_state[DISPLAY_MESSAGES_KEY]:
if message["role"] != "system": # Don't display the system prompt
speaker = "🧑💻 You" if message["role"] == "user" else "🤖 Assistant"
with st.chat_message(message["role"]):
st.markdown(f"**{speaker}:** {message['content']}")
# User input
user_input = st.chat_input("Ask me anything...", key="user_input")
# Process user input
if user_input:
st.session_state[SESSION_MESSAGES_KEY].append({"role": "user", "content": user_input})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "user", "content": user_input})
# Add spinner while GPT-4o thinks
with st.chat_message("assistant"):
placeholder = st.empty() # Reserve a placeholder for the response
with st.spinner("Thinking..."):
reply = get_openai_response(st.session_state[SESSION_MESSAGES_KEY], model=st.session_state.model) # added model
placeholder.markdown(f"**🤖 Assistant:** {reply}") # Replace placeholder with full response
st.session_state[SESSION_MESSAGES_KEY].append({"role": "assistant", "content": reply})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "assistant", "content": reply})
# Clear the input field after sending the message
st.session_state.user_input = ""
st.rerun()
if __name__ == "__main__":
main()
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
: Sets the page title and icon in the browser tab.st.title("🤖 GPT-4o Assistant")
: Sets the title of the Streamlit application.initialize_session_state()
: Initializes the sessionst.sidebar.header("Settings")
: Creates a sidebar section titled "Settings."model = st.sidebar.selectbox(...)
: Creates a dropdown in the sidebar to select the OpenAI model.clear_history_button = st.sidebar.button("Clear Chat", on_click=clear_chat_history)
: Adds a button to the sidebar to clear the chat history.- The chat history is displayed using
st.chat_message
, with different styling for the user and assistant messages. user_input = st.chat_input("Ask me anything...", key="user_input")
: Creates a text input field for the user to type their query. Thekey
argument is important for Streamlit to manage the state of the input field.- The application retrieves the user's input, sends it to the OpenAI API using the
get_openai_response
function, and displays the response. - The conversation history is stored in
st.session_state.messages
as a list of dictionaries. Each dictionary has a "role" (either "user" or "assistant") and "content". st.rerun()
is used to update the display after the assistant responds.- Run the app:
To run the app, save the code to a file named chatbot.py and run the following command in your terminal:
streamlit run chatbot.py
4.2.3 Flask + Custom HTML/CSS Chat UI
This example implements a chatbot using Flask and OpenAI's GPT-4o model, with a focus on allowing developers to customize the chat interface using their own HTML and CSS. This approach provides greater flexibility in styling and layout compared to using pre-built UI components. This code provide a robust and customizable chatbot, explaining key concepts and best practices for intermediate developers.
Step 1: Install Dependencies
pip install flask openai python-dotenv
flask
: A web framework for building the chatbot application.openai
: The OpenAI Python library for interacting with the GPT-4o model.python-dotenv
: A library to load environment variables from a.env
file.
Step 2: Updated Flask Template (templates/chat.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GPT-4o Chat Assistant</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<style>
/* --- General Styles --- */
body {
font-family: 'Inter', sans-serif; /* Modern font */
background-color: #f3f4f6; /* Tailwind's gray-100 */
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
color: #1f2937; /* Tailwind's gray-800 */
}
.container {
max-width: 800px; /* Increased max-width */
width: 100%;
background-color: #fff; /* White background */
padding: 30px;
border-radius: 0.75rem; /* Tailwind's rounded-lg */
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); /* Tailwind's shadow-md */
}
h2 {
font-size: 1.875rem; /* Tailwind's text-2xl */
font-weight: 600; /* Tailwind's font-semibold */
margin-bottom: 2rem; /* Tailwind's mb-8 */
color: #1e293b; /* Tailwind's gray-900 */
text-align: center;
}
/* --- Message Styles --- */
.message {
margin-bottom: 1.5rem; /* Tailwind's mb-6 */
display: flex;
flex-direction: column;
}
.message p {
padding: 1rem; /* Tailwind's p-4 */
border-radius: 1rem; /* Tailwind's rounded-lg */
max-width: 80%; /* Limit message width */
}
.user p {
background-color: #e0f2fe; /* Tailwind's bg-blue-100 */
color: #1d4ed8; /* Tailwind's text-blue-700 */
margin-left: auto; /* Push user message to the right */
}
.assistant p {
background-color: #f0fdf4; /* Tailwind's bg-green-100 */
color: #15803d; /* Tailwind's text-green-700 */
}
.message strong {
font-size: 0.875rem; /* Tailwind's text-sm */
font-weight: 600; /* Tailwind's font-semibold */
margin-bottom: 0.25rem; /* Tailwind's mb-1 */
}
.user strong {
color: #1e40af; /* Tailwind's text-blue-800 */
}
.assistant strong {
color: #16a34a; /* Tailwind's text-green-800 */
}
/* --- Form Styles --- */
form {
margin-top: 2rem; /* Tailwind's mt-8 */
display: flex;
flex-direction: column;
gap: 0.5rem; /* Tailwind's gap-2 */
}
textarea {
width: 100%;
padding: 0.75rem; /* Tailwind's p-3 */
border-radius: 0.5rem; /* Tailwind's rounded-md */
border: 1px solid #d1d5db; /* Tailwind's border-gray-300 */
resize: none;
font-size: 1rem; /* Tailwind's text-base */
line-height: 1.5rem; /* Tailwind's leading-relaxed */
margin-bottom: 0.25rem; /* Tailwind's mb-1 */
box-shadow: inset 0 2px 4px rgba(0,0,0,0.06); /* Inner shadow, more subtle */
}
textarea:focus {
outline: none;
border-color: #3b82f6; /* Tailwind's border-blue-500 */
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15); /* Tailwind's ring-blue-500 with opacity */
}
input[type="submit"] {
padding: 0.75rem 1.5rem; /* Tailwind's px-6 py-3 */
border-radius: 0.5rem; /* Tailwind's rounded-md */
background-color: #3b82f6; /* Tailwind's bg-blue-500 */
color: #fff; /* White text */
font-size: 1rem; /* Tailwind's text-base */
font-weight: 600; /* Tailwind's font-semibold */
cursor: pointer;
transition: background-color 0.3s ease; /* Smooth transition */
border: none;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1); /* Tailwind's shadow-sm */
}
input[type="submit"]:hover {
background-color: #2563eb; /* Tailwind's bg-blue-700 on hover */
}
input[type="submit"]:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3); /* Tailwind's ring-blue-500 with more opacity*/
}
/* --- Responsive Adjustments --- */
@media (max-width: 768px) { /* Medium screens and below (md breakpoint in Tailwind is 768px) */
.container {
padding: 20px;
}
textarea {
height: 100px; /* Make textarea taller on smaller screens */
}
}
</style>
</head>
<body>
<div class="container">
<h2>🧠 GPT-4o Chat Assistant</h2>
{% for msg in history %}
<div class="message {{ msg.role }}">
<p><strong>{{ msg.role.capitalize() }}:</strong> {{ msg.content }}</p>
</div>
{% endfor %}
<form method="post">
<textarea name="user_input" placeholder="Type your message..."></textarea><br>
<input type="submit" value="Send Message">
</form>
</div>
</body>
</html>
HTML template:
- Modern Design: The template features a contemporary design approach inspired by Tailwind CSS. This includes:
- Clean font (Inter)
- Spacious padding and margins
- Rounded corners
- Subtle shadows
- Consistent color palette
- Responsive Design: Added a media query to adjust the layout for smaller screens (tablets and phones).
- Improved Form: The form is styled with a focus state, better margins, and a smooth hover effect.
- Semantic HTML: Uses
lang="en"
in the<html>
tag for better accessibility. - Comments: Added comments to explain the CSS, relating it to Tailwind CSS where applicable, for easier understanding.
Step 3: Updated Flask Backend (app.py)
from flask import Flask, request, render_template, session, redirect, url_for
import openai
import os
from dotenv import load_dotenv
import time
from typing import List, Dict
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
app = Flask(__name__)
app.secret_key = os.urandom(24) # Required for session management
# --- Constants ---
DEFAULT_MODEL = "gpt-4o"
SYSTEM_PROMPT = "You are a helpful, friendly, and knowledgeable assistant. Answer all questions clearly, concisely, and in a conversational tone. When appropriate, provide code examples."
SESSION_MESSAGES_KEY = "conversation" # Consistent key for session
# --- Helper Functions ---
def get_openai_response(messages: List[Dict[str, str]], model: str = DEFAULT_MODEL) -> str:
"""
Sends a message to OpenAI's Chat API and handles potential errors.
Args:
messages: A list of message dictionaries.
model: The OpenAI model to use.
Returns:
The assistant's reply, or an error message.
"""
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=60
)
return response.choices[0].message.content
except openai.error.OpenAIError as e:
# Log the error for debugging
print(f"OpenAI API error: {e}")
return f"Sorry, there was an error communicating with the AI: {e}"
except Exception as e:
print(f"Unexpected error: {e}")
return "Sorry, an unexpected error occurred."
def initialize_session_state():
"""Initializes session state."""
if SESSION_MESSAGES_KEY not in session:
session[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
if "model" not in session:
session["model"] = DEFAULT_MODEL
def clear_conversation():
"""Clears the conversation history from the session."""
session[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
session.modified = True # Ensure session is saved
return redirect(url_for("chat")) # Redirect to the chat route
# --- Routes ---
@app.route("/", methods=["GET", "POST"])
def chat():
initialize_session_state()
conversation = session[SESSION_MESSAGES_KEY]
model = session["model"]
if request.method == "POST":
user_input = request.form["user_input"]
conversation.append({"role": "user", "content": user_input})
reply = get_openai_response(conversation, model)
conversation.append({"role": "assistant", "content": reply})
session[SESSION_MESSAGES_KEY] = conversation
session.modified = True # Important: You need to mark the session as modified
return render_template("chat.html", history=conversation[1:]) # Skip system message
return render_template("chat.html", history=conversation[1:]) # Skip system message
@app.route("/clear", methods=["POST"]) # New route to handle clearing the chat
def clear_chat():
return clear_conversation()
if __name__ == "__main__":
app.run(debug=True)
Let's break down this Flask application code for a chatbot:
1. Imports and Setup
- Essential Flask components and OpenAI integration
- Environment variables loading with python-dotenv
- Secret key generation for session management
2. Core Configuration
- Default model set to "gpt-4o"
- System prompt defining the AI's personality and behavior
- Session management for conversation persistence
3. Helper Functions
- get_openai_response(): Handles API communication with OpenAI, including error handling
- initialize_session_state(): Sets up initial conversation state and model settings
- clear_conversation(): Resets the chat history to initial state
4. Routes
- Main route ("/"):
- Handles both GET and POST requests
- Manages conversation flow and message history
- Renders the chat template with conversation history
- Clear route ("/clear"):
- Provides functionality to reset the conversation
The example implements a robust chatbot that maintains conversation history through Flask sessions, handles OpenAI API communication efficiently, and includes comprehensive error handling for reliability.
4.2.4 Optional Enhancements
Here are some advanced features you can implement to enhance your chatbot's functionality and user experience:
Dark mode toggle using CSS
- Implement a theme switcher that changes the color scheme
- Create a toggle button with smooth transition animations
- Define separate color palettes for light and dark modes
- Use CSS variables for easy theme management
- Define root-level CSS variables for colors, shadows, and backgrounds
- Implement a single source of truth for theme-related styles
- Store user preference in local storage
- Save theme preference using browser's localStorage API
- Automatically apply saved preference on page reload
- Respect system-level dark mode settings using prefers-color-scheme media query
Avatar icons for user and assistant
- Add visual distinction between participants
- Use different colors and shapes to clearly identify messages from users versus the AI assistant
- Include subtle visual cues like message orientation (left/right alignment)
- Use custom images or default profile pictures
- Allow users to upload their own profile pictures
- Provide a default set of professional avatars for users who don't upload custom images
- Generate unique AI assistant avatars that reflect its personality
- Implement smooth transitions between messages
- Add fade-in animations when new messages appear
- Include typing indicators while the AI is generating responses
- Use subtle scaling animations when hovering over messages
Speech-to-text input using browser APIs
- Integrate the Web Speech API for voice recognition
- Use the SpeechRecognition interface to capture audio input
- Implement error handling for cases when the browser doesn't support speech recognition
- Add microphone permission handling and user feedback
- Add real-time transcription feedback
- Display interim results as the user speaks
- Implement visual indicators for active listening state
- Add confidence scores for transcription accuracy
- Handle multiple language support
- Configure recognition for different languages using BCP 47 language tags
- Allow users to switch between languages dynamically
- Implement dialect detection and regional accent handling
Voice replies using OpenAI's TTS output and JavaScript
- Convert chatbot responses to natural-sounding speech
- Use OpenAI's Text-to-Speech API to generate high-quality audio
- Support multiple languages and accents for international users
- Handle text preprocessing for better pronunciation
- Implement playback controls
- Add play/pause, speed control, and volume adjustment
- Include progress bar for longer responses
- Enable keyboard shortcuts for quick control
- Add options for different voices and speaking rates
- Offer selection of voice personalities (casual, professional, etc.)
- Allow customizable speaking speed (0.5x to 2x)
- Implement voice pitch and emphasis controls
In this chapter, we have explored how to transform a basic chatbot into a sophisticated, user-friendly interface that delivers a truly interactive experience. This enhancement can be accomplished through two distinct approaches:
Streamlit: This modern framework excels at rapid development and offers numerous advantages for building chatbots:
- Pre-built chat interface components
- Ready-to-use message bubbles, input fields, and chat layouts
- Built-in components for file uploads and media handling
- Simplified state management
- Automatic handling of session state and caching
- Easy implementation of conversation history
- Quick prototyping capabilities
- Live reloading for rapid development
- Intuitive API for fast iteration
- Minimal setup requirements
- Single-file applications possible
- No complex configuration needed
Flask: This versatile micro-framework provides developers with complete control through:
- Complete control over HTML structure
- Custom templating for precise layout control
- Freedom to implement any design pattern
- Custom CSS styling options
- Full control over styling and animations
- Integration with any CSS framework
- Advanced routing capabilities
- Complex URL patterns and parameters
- RESTful API implementation
- Granular session management
- Custom session handling and storage
- Fine-grained control over user data
We have implemented several key features that transform this basic chatbot into a professional-grade application:
- Robust conversation memory management
- Implements secure session storage for chat history
- Maintains context across multiple interactions
- Handles conversation state cleanup and management
- Intuitive chat history visualization
- Clear message threading and organization
- Distinct visual separation between user and AI responses
- Timestamp and message status indicators
- Smooth response animations and transitions
- Loading states during API calls
- Fade-in effects for new messages
- Smooth scrolling to latest messages
- Professional UI/UX design elements
- Consistent color scheme and typography
- Responsive layout for all screen sizes
- Accessibility-compliant interface elements
These enhancements work together to create a chatbot that not only functions efficiently but also provides an engaging, professional experience that feels natural and responsive to users. Each feature has been carefully implemented to ensure optimal performance while maintaining a seamless user experience throughout the conversation flow.
4.2 Creating Interactive User Interfaces
User interfaces are the bridge between your chatbot's intelligence and its users. A well-designed UI can transform a capable AI system into an engaging, accessible tool that users love to interact with. Creating an effective chatbot interface requires careful consideration of user experience principles, visual design elements, and interaction patterns.
This section explores the art and science of building intuitive chatbot interfaces. We'll examine both the technical implementation and design considerations that make a chatbot truly user-friendly. You'll learn how to create interfaces that not only look professional but also provide meaningful feedback, handle errors gracefully, and guide users through natural conversations.
Whether you're building a customer service bot, a virtual assistant, or an AI-powered learning tool, the principles and techniques covered here will help you create interfaces that enhance rather than hinder the user experience. We'll look at implementation approaches using both Streamlit and Flask, giving you the flexibility to choose the tools that best fit your project's needs.
4.2.1 Why UI Matters in a Chatbot
The success of a chatbot heavily depends on its user interface and overall user experience. No matter how sophisticated your AI model might be, users will struggle to engage with it effectively if the interface is difficult to use or unintuitive. This is why creating well-designed, user-friendly interfaces is crucial. We'll focus on building intuitive, responsive, and user-friendly UIs that not only look professional but also create a natural flow of conversation between the user and the AI.
Our approach emphasizes three fundamental aspects of interface design that are critical for creating an effective chatbot:
User Experience (UX)
Creating interfaces that are easy to navigate and understand, with clear visual hierarchies and intuitive interaction patterns. A well-designed UX considers several key aspects:
- Information Architecture: Organizing content in a logical, easy-to-follow structure that matches users' mental models.
- Visual Design: Using consistent color schemes, typography, and spacing to create clear visual hierarchies that guide users' attention.
- Interaction Design: Implementing intuitive controls and navigation patterns that feel familiar and predictable to users.
- Feedback Mechanisms: Providing clear visual and textual cues that help users understand:
- When their message is being processed
- When the chatbot is "thinking"
- If an error occurs
- Whether their input was received successfully
- Cognitive Load Management: Minimizing the mental effort required to use the interface by:
- Breaking complex tasks into smaller steps
- Using familiar design patterns
- Providing clear instructions when needed
- Maintaining consistent behavior throughout the interface
This thoughtful approach to UX design reduces friction, increases user engagement, and makes the chatbot feel natural and effortless to use.
Responsiveness
Ensuring the interface provides immediate feedback and maintains smooth performance across different devices and screen sizes. This involves several key aspects:
- Performance Optimization:
- Implementing efficient loading states that show users their actions are being processed
- Optimizing response times through techniques like request debouncing and caching
- Using progressive loading for chat history to handle large conversations
- Device Compatibility:
- Using responsive design principles to ensure the chatbot works seamlessly across devices
- Implementing fluid layouts that adjust to different screen sizes
- Ensuring touch-friendly interface elements for mobile users
- Testing and optimizing for various browsers and platforms
- Adaptive UI Elements:
- Creating flexible chat bubbles that resize based on content
- Implementing collapsible menus and controls for smaller screens
- Using relative units (em, rem, vh, vw) instead of fixed pixels
- Ensuring proper text wrapping and readability at all sizes
The interface should dynamically adapt to different screen sizes while maintaining functionality and visual appeal, providing a consistent experience whether accessed from a smartphone, tablet, or desktop computer.
Accessibility
Making the chatbot usable for people with different abilities and technical backgrounds is crucial for ensuring inclusive access. This involves several key considerations:
- Screen Reader Compatibility
- Implementing proper ARIA labels and roles to describe UI elements
- Ensuring meaningful heading structure and navigation
- Providing text alternatives for all non-text content
- Keyboard Navigation
- Supporting full keyboard control of all features
- Implementing visible focus indicators
- Creating logical tab order through the interface
- Visual Design
- Maintaining sufficient color contrast ratios (minimum 4.5:1)
- Avoiding color as the only means of conveying information
- Supporting text resizing without loss of functionality
- Technical Considerations
- Following Web Content Accessibility Guidelines (WCAG) 2.1 Level AA standards
- Regular testing with accessibility tools and screen readers
- Providing alternatives for complex interactions
By implementing these accessibility features, you ensure that your chatbot can be effectively used by people with various disabilities, including visual, auditory, motor, and cognitive impairments. This not only complies with legal requirements but also demonstrates a commitment to universal design principles.
To create an effective and user-friendly chatbot interface, we'll explore these essential components in detail:
- Building an Intuitive Chat Interface
- Implementation of clean, modern design principles that prioritize readability and user engagement
- Careful consideration of spacing to create visual breathing room between elements
- Strategic use of typography to establish clear information hierarchy
- Consistent visual elements that guide users through the conversation flow
- Managing Conversation History
- Implementation of efficient chat log storage and retrieval systems
- Integration of timestamp functionality for better conversation tracking
- Creation of distinct visual styles for user and bot messages
- Development of smooth scrolling mechanics for longer conversations
- Optimizing Response Presentation
- Careful selection of fonts and text sizes for maximum readability
- Implementation of consistent spacing patterns between message elements
- Special formatting considerations for different content types (code blocks, lists, etc.)
- Integration of visual indicators for message status and type
- Implementing Robust Feedback Systems
- Creation of subtle but visible loading animations during response generation
- Development of clear error messages that guide users toward solutions
- Implementation of recovery mechanisms for common error scenarios
- Integration of status indicators to keep users informed of system state
You'll get comprehensive examples in both Streamlit and Flask, allowing you to choose the framework that best suits your development style and project requirements. Each example includes detailed explanations and best practices for implementation.
4.2.2 Streamlit Interactive Chat UI
This example demonstrates how to create an interactive chatbot using Streamlit and OpenAI, which we'll build upon further. Using Streamlit, we'll create a user-friendly chat interface that maintains conversation history. This use case showcases key concepts and best practices for building a robust, interactive chatbot.
Step 1: Install Dependencies
pip install streamlit openai python-dotenv
streamlit
: A Python library for creating interactive web applications.openai
: The OpenAI Python library for interacting with the GPT-4o model.python-dotenv
: A library to load environment variables from a.env
file.
Step 2: Create the Streamlit App (chatbot.py)
import streamlit as st
import openai
import os
from dotenv import load_dotenv
import time # For handling potential API errors
from typing import List, Dict # For type hinting
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
# --- Constants ---
DEFAULT_MODEL = "gpt-4o"
SYSTEM_PROMPT = "You are a helpful, friendly, and knowledgeable assistant. Answer all questions clearly, concisely, and in a conversational tone. When appropriate, provide code examples."
SESSION_MESSAGES_KEY = "messages" # Consistent key for session state
DISPLAY_MESSAGES_KEY = "display_messages"
# --- Helper Functions ---
def get_openai_response(messages: List[Dict[str, str]], model: str = DEFAULT_MODEL) -> str:
"""
Sends a message to OpenAI's Chat API and handles potential errors with robust error handling.
Args:
messages (List[Dict[str, str]]): A list of message dictionaries, representing the conversation history.
model (str, optional): The OpenAI model to use. Defaults to DEFAULT_MODEL.
Returns:
str: The assistant's reply, or an error message.
Raises:
openai.error.OpenAIError: If there is an error with the OpenAI API.
Exception: For other unexpected errors.
"""
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=60, # Add a timeout to prevent hanging
)
return response.choices[0].message.content
except openai.error.OpenAIError as e:
st.error(f"OpenAI API Error: {e}")
return f"Sorry, I encountered an error with the OpenAI API: {e}"
except Exception as e:
st.error(f"An unexpected error occurred: {e}")
return "Sorry, I encountered an unexpected error."
def initialize_session_state():
"""
Initializes session state variables. This function should be called
at the beginning of the main() function. It ensures that session
state is initialized even if the user doesn't immediately enter a query.
"""
if SESSION_MESSAGES_KEY not in st.session_state:
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
if DISPLAY_MESSAGES_KEY not in st.session_state:
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}] # Separate list for displayed messages
if "model" not in st.session_state:
st.session_state.model = DEFAULT_MODEL
def clear_chat_history():
"""Clears the chat history and resets to the initial state."""
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state.user_input = "" # Clear the input field
st.rerun() # Force a rerun to update the display
# --- Main App ---
def main():
"""
Main function to run the Streamlit application.
"""
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
st.title("🤖 GPT-4o Assistant")
initialize_session_state() # Initialize session state
# --- Sidebar ---
st.sidebar.header("Settings")
model = st.sidebar.selectbox("Model", ["gpt-4o", "gpt-3.5-turbo"], index=0)
st.session_state.model = model
clear_history_button = st.sidebar.button("Clear Chat", on_click=clear_chat_history) # corrected to clear_chat_history
# Display chat history, রাখা changed to display_messages
for message in st.session_state[DISPLAY_MESSAGES_KEY]:
if message["role"] != "system": # Don't display the system prompt
speaker = "🧑💻 You" if message["role"] == "user" else "🤖 Assistant"
with st.chat_message(message["role"]):
st.markdown(f"**{speaker}:** {message['content']}")
# User input, রাখা outside the conditional block
user_input = st.chat_input("Ask me anything...", key="user_input")
# Process user input
if user_input:
st.session_state[SESSION_MESSAGES_KEY].append({"role": "user", "content": user_input})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "user", "content": user_input})
# Add spinner while GPT-4o thinks
with st.chat_message("assistant"):
placeholder = st.empty() # Reserve a placeholder for the response
with st.spinner("Thinking..."):
reply = get_openai_response(st.session_state[SESSION_MESSAGES_KEY], model=st.session_state.model) #added model
placeholder.markdown(f"**🤖 Assistant:** {reply}") # Replace placeholder with full response
st.session_state[SESSION_MESSAGES_KEY].append({"role": "assistant", "content": reply})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "assistant", "content": reply})
# Clear the input field after sending the message
st.session_state.user_input = ""
st.rerun()
if __name__ == "__main__":
main()
Code Breakdown
Let's break down the code step by step.
Imports:
import streamlit as st
import openai
import os
from dotenv import load_dotenv
import time # For handling potential API errors
from typing import List, Dict # For type hinting
Imports the necessary libraries:
streamlit
: For creating the web interface.openai
: For interacting with the OpenAI API.os
: For accessing environment variables.dotenv
: For loading environment variables from a.env
file.time
: For handling potential API errors by waiting.typing
: For type hinting to improve code readability.
Environment Variables:
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
Loads the OpenAI API key from a .env
file and sets it for the OpenAI library.
Constants:
DEFAULT_MODEL = "gpt-4o"
SYSTEM_PROMPT = "You are a helpful, friendly, and knowledgeable assistant. Answer all questions clearly, concisely, and in a conversational tone. When appropriate, provide code examples."
SESSION_MESSAGES_KEY = "messages" # Consistent key for session state
DISPLAY_MESSAGES_KEY = "display_messages"
DEFAULT_MODEL
: The default OpenAI model used for the chatbot.SYSTEM_PROMPT
: The initial message sent to the OpenAI API to set the behavior of the assistant.SESSION_MESSAGES_KEY
: Key to use for the main conversation history in the session state.DISPLAY_MESSAGES_KEY
: Key to use for the conversation history that is displayed in the UI.
Helper Functions:
get_openai_response()
:
def get_openai_response(messages: List[Dict[str, str]], model: str = DEFAULT_MODEL) -> str:
"""
Sends a message to OpenAI's Chat API and handles potential errors with robust error handling.
Args:
messages (List[Dict[str, str]]): A list of message dictionaries, representing the conversation history.
model (str, optional): The OpenAI model to use. Defaults to DEFAULT_MODEL.
Returns:
str: The assistant's reply, or an error message.
Raises:
openai.error.OpenAIError: If there is an error with the OpenAI API.
Exception: For other unexpected errors.
"""
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=60, # Add a timeout to prevent hanging
)
return response.choices[0].message.content
except openai.error.OpenAIError as e:
st.error(f"OpenAI API Error: {e}")
return f"Sorry, I encountered an error with the OpenAI API: {e}"
except Exception as e:
st.error(f"An unexpected error occurred: {e}")
return "Sorry, I encountered an unexpected error."
Sends the user's input to the OpenAI API and retrieves the response. This function also includes error handling using a try...except
block to catch potential openai.error.OpenAIError
exceptions and a general Exception
for other errors. A timeout is added to prevent the app from hanging indefinitely.
initialize_session_state()
:
def initialize_session_state():
"""
Initializes session state variables. This function should be called
at the beginning of the main() function. It ensures that session
state is initialized even if the user doesn't immediately enter a query.
"""
if SESSION_MESSAGES_KEY not in st.session_state:
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
if DISPLAY_MESSAGES_KEY not in st.session_state:
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}] # Separate list for displayed messages
if "model" not in st.session_state:
st.session_state.model = DEFAULT_MODEL
Initializes the session state variables:
SESSION_MESSAGES_KEY
: Stores the full conversation history.DISPLAY_MESSAGES_KEY
: Stores the conversation history that is displayed to the user.model
: The LLM modelclear_chat_history()
:
def clear_chat_history():
"""Clears the chat history and resets to the initial state."""
st.session_state[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state[DISPLAY_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
st.session_state.user_input = "" # Clear the input field
st.rerun() # Force a rerun to update the display
Clears the chat history when the user clicks the "Clear Chat" button.
Main App:
def main():
"""
Main function to run the Streamlit application.
"""
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
st.title("🤖 GPT-4o Assistant")
initialize_session_state()
# --- Sidebar ---
st.sidebar.header("Settings")
model = st.sidebar.selectbox("Model", ["gpt-4o", "gpt-3.5-turbo"], index=0)
st.session_state.model = model
clear_history_button = st.sidebar.button("Clear Chat", on_click=clear_chat_history)
# Display chat history
for message in st.session_state[DISPLAY_MESSAGES_KEY]:
if message["role"] != "system": # Don't display the system prompt
speaker = "🧑💻 You" if message["role"] == "user" else "🤖 Assistant"
with st.chat_message(message["role"]):
st.markdown(f"**{speaker}:** {message['content']}")
# User input
user_input = st.chat_input("Ask me anything...", key="user_input")
# Process user input
if user_input:
st.session_state[SESSION_MESSAGES_KEY].append({"role": "user", "content": user_input})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "user", "content": user_input})
# Add spinner while GPT-4o thinks
with st.chat_message("assistant"):
placeholder = st.empty() # Reserve a placeholder for the response
with st.spinner("Thinking..."):
reply = get_openai_response(st.session_state[SESSION_MESSAGES_KEY], model=st.session_state.model) # added model
placeholder.markdown(f"**🤖 Assistant:** {reply}") # Replace placeholder with full response
st.session_state[SESSION_MESSAGES_KEY].append({"role": "assistant", "content": reply})
st.session_state[DISPLAY_MESSAGES_KEY].append({"role": "assistant", "content": reply})
# Clear the input field after sending the message
st.session_state.user_input = ""
st.rerun()
if __name__ == "__main__":
main()
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
: Sets the page title and icon in the browser tab.st.title("🤖 GPT-4o Assistant")
: Sets the title of the Streamlit application.initialize_session_state()
: Initializes the sessionst.sidebar.header("Settings")
: Creates a sidebar section titled "Settings."model = st.sidebar.selectbox(...)
: Creates a dropdown in the sidebar to select the OpenAI model.clear_history_button = st.sidebar.button("Clear Chat", on_click=clear_chat_history)
: Adds a button to the sidebar to clear the chat history.- The chat history is displayed using
st.chat_message
, with different styling for the user and assistant messages. user_input = st.chat_input("Ask me anything...", key="user_input")
: Creates a text input field for the user to type their query. Thekey
argument is important for Streamlit to manage the state of the input field.- The application retrieves the user's input, sends it to the OpenAI API using the
get_openai_response
function, and displays the response. - The conversation history is stored in
st.session_state.messages
as a list of dictionaries. Each dictionary has a "role" (either "user" or "assistant") and "content". st.rerun()
is used to update the display after the assistant responds.- Run the app:
To run the app, save the code to a file named chatbot.py and run the following command in your terminal:
streamlit run chatbot.py
4.2.3 Flask + Custom HTML/CSS Chat UI
This example implements a chatbot using Flask and OpenAI's GPT-4o model, with a focus on allowing developers to customize the chat interface using their own HTML and CSS. This approach provides greater flexibility in styling and layout compared to using pre-built UI components. This code provide a robust and customizable chatbot, explaining key concepts and best practices for intermediate developers.
Step 1: Install Dependencies
pip install flask openai python-dotenv
flask
: A web framework for building the chatbot application.openai
: The OpenAI Python library for interacting with the GPT-4o model.python-dotenv
: A library to load environment variables from a.env
file.
Step 2: Updated Flask Template (templates/chat.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GPT-4o Chat Assistant</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<style>
/* --- General Styles --- */
body {
font-family: 'Inter', sans-serif; /* Modern font */
background-color: #f3f4f6; /* Tailwind's gray-100 */
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
color: #1f2937; /* Tailwind's gray-800 */
}
.container {
max-width: 800px; /* Increased max-width */
width: 100%;
background-color: #fff; /* White background */
padding: 30px;
border-radius: 0.75rem; /* Tailwind's rounded-lg */
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); /* Tailwind's shadow-md */
}
h2 {
font-size: 1.875rem; /* Tailwind's text-2xl */
font-weight: 600; /* Tailwind's font-semibold */
margin-bottom: 2rem; /* Tailwind's mb-8 */
color: #1e293b; /* Tailwind's gray-900 */
text-align: center;
}
/* --- Message Styles --- */
.message {
margin-bottom: 1.5rem; /* Tailwind's mb-6 */
display: flex;
flex-direction: column;
}
.message p {
padding: 1rem; /* Tailwind's p-4 */
border-radius: 1rem; /* Tailwind's rounded-lg */
max-width: 80%; /* Limit message width */
}
.user p {
background-color: #e0f2fe; /* Tailwind's bg-blue-100 */
color: #1d4ed8; /* Tailwind's text-blue-700 */
margin-left: auto; /* Push user message to the right */
}
.assistant p {
background-color: #f0fdf4; /* Tailwind's bg-green-100 */
color: #15803d; /* Tailwind's text-green-700 */
}
.message strong {
font-size: 0.875rem; /* Tailwind's text-sm */
font-weight: 600; /* Tailwind's font-semibold */
margin-bottom: 0.25rem; /* Tailwind's mb-1 */
}
.user strong {
color: #1e40af; /* Tailwind's text-blue-800 */
}
.assistant strong {
color: #16a34a; /* Tailwind's text-green-800 */
}
/* --- Form Styles --- */
form {
margin-top: 2rem; /* Tailwind's mt-8 */
display: flex;
flex-direction: column;
gap: 0.5rem; /* Tailwind's gap-2 */
}
textarea {
width: 100%;
padding: 0.75rem; /* Tailwind's p-3 */
border-radius: 0.5rem; /* Tailwind's rounded-md */
border: 1px solid #d1d5db; /* Tailwind's border-gray-300 */
resize: none;
font-size: 1rem; /* Tailwind's text-base */
line-height: 1.5rem; /* Tailwind's leading-relaxed */
margin-bottom: 0.25rem; /* Tailwind's mb-1 */
box-shadow: inset 0 2px 4px rgba(0,0,0,0.06); /* Inner shadow, more subtle */
}
textarea:focus {
outline: none;
border-color: #3b82f6; /* Tailwind's border-blue-500 */
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15); /* Tailwind's ring-blue-500 with opacity */
}
input[type="submit"] {
padding: 0.75rem 1.5rem; /* Tailwind's px-6 py-3 */
border-radius: 0.5rem; /* Tailwind's rounded-md */
background-color: #3b82f6; /* Tailwind's bg-blue-500 */
color: #fff; /* White text */
font-size: 1rem; /* Tailwind's text-base */
font-weight: 600; /* Tailwind's font-semibold */
cursor: pointer;
transition: background-color 0.3s ease; /* Smooth transition */
border: none;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1); /* Tailwind's shadow-sm */
}
input[type="submit"]:hover {
background-color: #2563eb; /* Tailwind's bg-blue-700 on hover */
}
input[type="submit"]:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3); /* Tailwind's ring-blue-500 with more opacity*/
}
/* --- Responsive Adjustments --- */
@media (max-width: 768px) { /* Medium screens and below (md breakpoint in Tailwind is 768px) */
.container {
padding: 20px;
}
textarea {
height: 100px; /* Make textarea taller on smaller screens */
}
}
</style>
</head>
<body>
<div class="container">
<h2>🧠 GPT-4o Chat Assistant</h2>
{% for msg in history %}
<div class="message {{ msg.role }}">
<p><strong>{{ msg.role.capitalize() }}:</strong> {{ msg.content }}</p>
</div>
{% endfor %}
<form method="post">
<textarea name="user_input" placeholder="Type your message..."></textarea><br>
<input type="submit" value="Send Message">
</form>
</div>
</body>
</html>
HTML template:
- Modern Design: The template features a contemporary design approach inspired by Tailwind CSS. This includes:
- Clean font (Inter)
- Spacious padding and margins
- Rounded corners
- Subtle shadows
- Consistent color palette
- Responsive Design: Added a media query to adjust the layout for smaller screens (tablets and phones).
- Improved Form: The form is styled with a focus state, better margins, and a smooth hover effect.
- Semantic HTML: Uses
lang="en"
in the<html>
tag for better accessibility. - Comments: Added comments to explain the CSS, relating it to Tailwind CSS where applicable, for easier understanding.
Step 3: Updated Flask Backend (app.py)
from flask import Flask, request, render_template, session, redirect, url_for
import openai
import os
from dotenv import load_dotenv
import time
from typing import List, Dict
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
app = Flask(__name__)
app.secret_key = os.urandom(24) # Required for session management
# --- Constants ---
DEFAULT_MODEL = "gpt-4o"
SYSTEM_PROMPT = "You are a helpful, friendly, and knowledgeable assistant. Answer all questions clearly, concisely, and in a conversational tone. When appropriate, provide code examples."
SESSION_MESSAGES_KEY = "conversation" # Consistent key for session
# --- Helper Functions ---
def get_openai_response(messages: List[Dict[str, str]], model: str = DEFAULT_MODEL) -> str:
"""
Sends a message to OpenAI's Chat API and handles potential errors.
Args:
messages: A list of message dictionaries.
model: The OpenAI model to use.
Returns:
The assistant's reply, or an error message.
"""
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
timeout=60
)
return response.choices[0].message.content
except openai.error.OpenAIError as e:
# Log the error for debugging
print(f"OpenAI API error: {e}")
return f"Sorry, there was an error communicating with the AI: {e}"
except Exception as e:
print(f"Unexpected error: {e}")
return "Sorry, an unexpected error occurred."
def initialize_session_state():
"""Initializes session state."""
if SESSION_MESSAGES_KEY not in session:
session[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
if "model" not in session:
session["model"] = DEFAULT_MODEL
def clear_conversation():
"""Clears the conversation history from the session."""
session[SESSION_MESSAGES_KEY] = [{"role": "system", "content": SYSTEM_PROMPT}]
session.modified = True # Ensure session is saved
return redirect(url_for("chat")) # Redirect to the chat route
# --- Routes ---
@app.route("/", methods=["GET", "POST"])
def chat():
initialize_session_state()
conversation = session[SESSION_MESSAGES_KEY]
model = session["model"]
if request.method == "POST":
user_input = request.form["user_input"]
conversation.append({"role": "user", "content": user_input})
reply = get_openai_response(conversation, model)
conversation.append({"role": "assistant", "content": reply})
session[SESSION_MESSAGES_KEY] = conversation
session.modified = True # Important: You need to mark the session as modified
return render_template("chat.html", history=conversation[1:]) # Skip system message
return render_template("chat.html", history=conversation[1:]) # Skip system message
@app.route("/clear", methods=["POST"]) # New route to handle clearing the chat
def clear_chat():
return clear_conversation()
if __name__ == "__main__":
app.run(debug=True)
Let's break down this Flask application code for a chatbot:
1. Imports and Setup
- Essential Flask components and OpenAI integration
- Environment variables loading with python-dotenv
- Secret key generation for session management
2. Core Configuration
- Default model set to "gpt-4o"
- System prompt defining the AI's personality and behavior
- Session management for conversation persistence
3. Helper Functions
- get_openai_response(): Handles API communication with OpenAI, including error handling
- initialize_session_state(): Sets up initial conversation state and model settings
- clear_conversation(): Resets the chat history to initial state
4. Routes
- Main route ("/"):
- Handles both GET and POST requests
- Manages conversation flow and message history
- Renders the chat template with conversation history
- Clear route ("/clear"):
- Provides functionality to reset the conversation
The example implements a robust chatbot that maintains conversation history through Flask sessions, handles OpenAI API communication efficiently, and includes comprehensive error handling for reliability.
4.2.4 Optional Enhancements
Here are some advanced features you can implement to enhance your chatbot's functionality and user experience:
Dark mode toggle using CSS
- Implement a theme switcher that changes the color scheme
- Create a toggle button with smooth transition animations
- Define separate color palettes for light and dark modes
- Use CSS variables for easy theme management
- Define root-level CSS variables for colors, shadows, and backgrounds
- Implement a single source of truth for theme-related styles
- Store user preference in local storage
- Save theme preference using browser's localStorage API
- Automatically apply saved preference on page reload
- Respect system-level dark mode settings using prefers-color-scheme media query
Avatar icons for user and assistant
- Add visual distinction between participants
- Use different colors and shapes to clearly identify messages from users versus the AI assistant
- Include subtle visual cues like message orientation (left/right alignment)
- Use custom images or default profile pictures
- Allow users to upload their own profile pictures
- Provide a default set of professional avatars for users who don't upload custom images
- Generate unique AI assistant avatars that reflect its personality
- Implement smooth transitions between messages
- Add fade-in animations when new messages appear
- Include typing indicators while the AI is generating responses
- Use subtle scaling animations when hovering over messages
Speech-to-text input using browser APIs
- Integrate the Web Speech API for voice recognition
- Use the SpeechRecognition interface to capture audio input
- Implement error handling for cases when the browser doesn't support speech recognition
- Add microphone permission handling and user feedback
- Add real-time transcription feedback
- Display interim results as the user speaks
- Implement visual indicators for active listening state
- Add confidence scores for transcription accuracy
- Handle multiple language support
- Configure recognition for different languages using BCP 47 language tags
- Allow users to switch between languages dynamically
- Implement dialect detection and regional accent handling
Voice replies using OpenAI's TTS output and JavaScript
- Convert chatbot responses to natural-sounding speech
- Use OpenAI's Text-to-Speech API to generate high-quality audio
- Support multiple languages and accents for international users
- Handle text preprocessing for better pronunciation
- Implement playback controls
- Add play/pause, speed control, and volume adjustment
- Include progress bar for longer responses
- Enable keyboard shortcuts for quick control
- Add options for different voices and speaking rates
- Offer selection of voice personalities (casual, professional, etc.)
- Allow customizable speaking speed (0.5x to 2x)
- Implement voice pitch and emphasis controls
In this chapter, we have explored how to transform a basic chatbot into a sophisticated, user-friendly interface that delivers a truly interactive experience. This enhancement can be accomplished through two distinct approaches:
Streamlit: This modern framework excels at rapid development and offers numerous advantages for building chatbots:
- Pre-built chat interface components
- Ready-to-use message bubbles, input fields, and chat layouts
- Built-in components for file uploads and media handling
- Simplified state management
- Automatic handling of session state and caching
- Easy implementation of conversation history
- Quick prototyping capabilities
- Live reloading for rapid development
- Intuitive API for fast iteration
- Minimal setup requirements
- Single-file applications possible
- No complex configuration needed
Flask: This versatile micro-framework provides developers with complete control through:
- Complete control over HTML structure
- Custom templating for precise layout control
- Freedom to implement any design pattern
- Custom CSS styling options
- Full control over styling and animations
- Integration with any CSS framework
- Advanced routing capabilities
- Complex URL patterns and parameters
- RESTful API implementation
- Granular session management
- Custom session handling and storage
- Fine-grained control over user data
We have implemented several key features that transform this basic chatbot into a professional-grade application:
- Robust conversation memory management
- Implements secure session storage for chat history
- Maintains context across multiple interactions
- Handles conversation state cleanup and management
- Intuitive chat history visualization
- Clear message threading and organization
- Distinct visual separation between user and AI responses
- Timestamp and message status indicators
- Smooth response animations and transitions
- Loading states during API calls
- Fade-in effects for new messages
- Smooth scrolling to latest messages
- Professional UI/UX design elements
- Consistent color scheme and typography
- Responsive layout for all screen sizes
- Accessibility-compliant interface elements
These enhancements work together to create a chatbot that not only functions efficiently but also provides an engaging, professional experience that feels natural and responsive to users. Each feature has been carefully implemented to ensure optimal performance while maintaining a seamless user experience throughout the conversation flow.