Skip to content

Instantly share code, notes, and snippets.

@Siddhant-Goswami
Created September 18, 2024 14:32
Show Gist options
  • Select an option

  • Save Siddhant-Goswami/e09c0528d28adbfe3ca7b085e57c61da to your computer and use it in GitHub Desktop.

Select an option

Save Siddhant-Goswami/e09c0528d28adbfe3ca7b085e57c61da to your computer and use it in GitHub Desktop.

Prompt:

I want you to develop an implementation plan to be provided to an AI coding assistant that spells out in detail how to implement a the following requirements using @FastHTML :

Requirements

Generate a chatbot UI that borrows it's design style from Discord. The UI should implement the following requirements:

Chat interface to receive messages from the user as well as present messages from the AI assistant A side panel on the left hand side which displays the chat history A dropdown near the top of the UI which allows the user to select an AI model Also near the top left should be a div which allows the user to select from the available tools

Response:

Implementation Plan for Discord-Inspired Chatbot UI Using FastHTML

This implementation plan outlines the steps necessary to develop a Discord-inspired chatbot UI using FastHTML. The UI will feature a chat interface, a side panel for chat history, a dropdown for AI model selection, and a tool selection div. The design will emulate Discord's aesthetic to provide a familiar and user-friendly experience.

Table of Contents

  1. Project Structure
  2. Setting Up the FastHTML Application
  3. Designing the Layout
  4. Implementing UI Components
  5. Styling the UI
  6. Handling Data and State
  7. Server-Side Logic
  8. Testing and Deployment

Project Structure

Organize the project with a clear and maintainable structure. Below is a recommended directory layout:

discord-chatbot/
├── app/
│   ├── components/
│   │   ├── ChatInterface.tsx
│   │   ├── SidePanel.tsx
│   │   ├── ModelDropdown.tsx
│   │   └── ToolSelector.tsx
│   ├── styles/
│   │   └── styles.css
│   ├── main.py
│   └── utils.py
├── data/
│   └── chat_history.db
├── static/
│   └── images/
│       └── logo.png
└── README.md

Setting Up the FastHTML Application

Initialize the FastHTML application with necessary configurations.

from fasthtml.common import *
from app.components.ChatInterface import ChatInterface
from app.components.SidePanel import SidePanel
from app.components.ModelDropdown import ModelDropdown
from app.components.ToolSelector import ToolSelector
from app.styles.styles import styles

app, rt = fast_app(hdrs=(Style(styles),))

@rt("/")
def index():
    return Title("Discord-Inspired Chatbot"), Container(
        Grid(
            SidePanel(),
            Div(
                ModelDropdown(),
                ToolSelector(),
                ChatInterface(),
                cls="main-chat"
            ),
            cls="main-grid"
        )
    )

serve()

Explanation:

  • File Path: app/main.py
  • Components Used:
    • ChatInterface: Handles the chat input and message display.
    • SidePanel: Displays chat history.
    • ModelDropdown: Dropdown for selecting AI models.
    • ToolSelector: Div for selecting available tools.
  • Styles: Applied via Style component importing CSS from app/styles/styles.py.

Designing the Layout

Main Layout

Create a responsive grid layout resembling Discord's interface, with a side panel and main chat area.

from fasthtml.common import *
from SidePanel import SidePanel
from ChatInterface import ChatInterface
from ModelDropdown import ModelDropdown
from ToolSelector import ToolSelector

def MainLayout():
    return Grid(
        SidePanel(),
        Div(
            ModelDropdown(),
            ToolSelector(),
            ChatInterface(),
            cls="main-chat"
        ),
        cls="main-grid"
    )

Explanation:

  • File Path: app/components/MainLayout.tsx
  • Function: MainLayout defines the overall structure using a grid layout.

Side Panel

Implement the side panel to display chat history.

from fasthtml.common import *

def SidePanel():
    return Div(
        H2("Chats"),
        Ul(
            # Dynamically populate chat history
            # Example static items; replace with dynamic content
            Li(A("Chat with AI", href="/chat/ai")),
            Li(A("Project Discussion", href="/chat/project")),
            Li(A("General Chat", href="/chat/general")),
        ),
        cls="side-panel"
    )

Explanation:

  • File Path: app/components/SidePanel.tsx
  • Function: SidePanel lists available chats. Replace static Li items with dynamic content as needed.

Chat Interface

Create the main chat interface for sending and receiving messages.

from fasthtml.common import *

def ChatInterface():
    return Div(
        Div(
            # Messages will be displayed here
            Ul(id="message-list", cls="message-list"),
            cls="messages-container"
        ),
        Form(
            Group(
                Input(name="user_message", placeholder="Type your message...", cls="chat-input"),
                Button("Send", type="submit", cls="send-button")
            ),
            hx_post="/send-message",
            hx_target="#message-list",
            hx_swap="beforeend",
            cls="chat-form"
        ),
        cls="chat-interface"
    )

Explanation:

  • File Path: app/components/ChatInterface.tsx
  • Function: ChatInterface includes a message display area and a form to send messages.
  • HTMX Attributes:
    • hx_post: Sends form data to /send-message endpoint.
    • hx_target: Updates the #message-list with the response.
    • hx_swap: Appends new messages to the end of the list.

Implementing UI Components

AI Model Selection Dropdown

Provide a dropdown menu for selecting different AI models.

from fasthtml.common import *

def ModelDropdown():
    models = ["GPT-3.5", "GPT-4", "Custom Model"]
    return Div(
        Label("Select AI Model:", For="model-select"),
        Select(
            *[Option(model, value=model) for model in models],
            id="model-select",
            name="model",
            cls="model-dropdown"
        ),
        hx_change="/change-model",
        cls="model-selector"
    )

Explanation:

  • File Path: app/components/ModelDropdown.tsx
  • Function: ModelDropdown creates a label and a select dropdown populated with AI model options.
  • HTMX Attribute:
    • hx_change: Triggers a request to /change-model when the selection changes.

Tool Selection Div

Allow users to select from available tools near the top left.

from fasthtml.common import *

def ToolSelector():
    tools = ["Translation", "Summarization", "Sentiment Analysis"]
    return Div(
        Label("Tools:", For="tool-select"),
        Select(
            *[Option(tool, value=tool) for tool in tools],
            id="tool-select",
            name="tool",
            cls="tool-selector-dropdown"
        ),
        hx_change="/select-tool",
        cls="tool-selector"
    )

Explanation:

  • File Path: app/components/ToolSelector.tsx
  • Function: ToolSelector creates a label and a select dropdown for tool selection.
  • HTMX Attribute:
    • hx_change: Triggers a request to /select-tool when a tool is selected.

Styling the UI

Incorporating Discord-Like Styles

Apply CSS to emulate Discord's design aesthetics, focusing on colors, layouts, and component styles.

/* General Styles */
body {
    background-color: #36393f;
    color: #dcddde;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    margin: 0;
    padding: 0;
}

/* Grid Layout */
.main-grid {
    display: grid;
    grid-template-columns: 250px 1fr;
    height: 100vh;
}

/* Side Panel */
.side-panel {
    background-color: #2f3136;
    padding: 20px;
    border-right: 1px solid #202225;
}

.side-panel h2 {
    color: #fff;
}

.side-panel ul {
    list-style: none;
    padding: 0;
}

.side-panel li {
    margin: 15px 0;
}

.side-panel a {
    color: #b9bbbe;
    text-decoration: none;
}

.side-panel a:hover {
    color: #fff;
}

/* Main Chat Interface */
.main-chat {
    display: flex;
    flex-direction: column;
    background-color: #36393f;
    padding: 20px;
}

.message-list {
    flex: 1;
    overflow-y: auto;
    margin-bottom: 20px;
}

.message-list li {
    margin-bottom: 10px;
}

.chat-input {
    width: 80%;
    padding: 10px;
    border: none;
    border-radius: 5px;
}

.send-button {
    padding: 10px 20px;
    background-color: #7289da;
    border: none;
    border-radius: 5px;
    color: #fff;
    cursor: pointer;
}

.send-button:hover {
    background-color: #677bc4;
}

/* Dropdowns */
.model-selector, .tool-selector {
    margin-bottom: 10px;
}

.model-dropdown, .tool-selector-dropdown {
    padding: 5px;
    border-radius: 5px;
    border: none;
}

Explanation:

  • File Path: app/styles/styles.css
  • Styles Applied:
    • Body: Dark background with light text, similar to Discord.
    • Grid Layout: Side panel fixed at 250px width; main chat area flexible.
    • Side Panel: Darker shade with padding and border to separate from main chat.
    • Chat Interface: Flex layout to position messages and input form.
    • Buttons and Inputs: Styled with Discord-like colors and hover effects.
    • Dropdowns: Styled for consistency with the overall theme.

Handling Data and State

Chat History Management

Store and retrieve chat history to display in the side panel and message list.

from fastlite import Database
from dataclasses import dataclass

@dataclass
class Message:
    id: int
    sender: str
    content: str
    timestamp: str

# Initialize database
db = Database("data/chat_history.db")
messages = db.create(Message, pk="id")

def add_message(sender: str, content: str):
    message = Message(
        id=messages.next_id(),
        sender=sender,
        content=content,
        timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    )
    messages.insert(message)

def get_messages():
    return messages.all(order_by="id ASC")

Explanation:

  • File Path: app/utils.py
  • Functions:
    • add_message: Inserts a new message into the database.
    • get_messages: Retrieves all messages ordered by ID.

AI Model Selection

Handle the selection of different AI models based on user input.

@rt("/change-model")
def change_model(model: str):
    # Logic to switch AI models
    current_model = model  # Store the selected model in session or state
    return NotStr(f"<li>{model} model selected.</li>")

Explanation:

  • File Path: app/main.py
  • Function: change_model updates the current AI model based on user selection.
  • HTMX Response: Returns a string to be handled by HTMX; adjust as needed for UI feedback.

Tool Selection

Manage the selection of tools available to the user.

@rt("/select-tool")
def select_tool(tool: str):
    # Logic to activate the selected tool
    selected_tool = tool  # Store the selected tool in session or state
    return NotStr(f"<li>{tool} tool selected.</li>")

Explanation:

  • File Path: app/main.py
  • Function: select_tool activates the chosen tool.
  • HTMX Response: Returns a string indicating the selected tool.

Server-Side Logic

Receiving User Messages

Handle incoming messages from the user and store them.

@rt("/send-message", methods=["POST"])
def send_message(user_message: str):
    add_message(sender="User", content=user_message)
    # Trigger AI response
    ai_response = generate_ai_response(user_message)
    add_message(sender="AI", content=ai_response)
    # Return the AI message to be appended to the message list
    return NotStr(f"<li><strong>AI:</strong> {ai_response}</li>")

Explanation:

  • File Path: app/main.py
  • Function: send_message processes the user's message, stores it, generates an AI response, stores the response, and returns it for display.
  • HTMX Response: Returns the AI's message wrapped in an li element.

Generating AI Responses

Implement the logic to generate responses from the AI assistant.

def generate_ai_response(message: str) -> str:
    # Placeholder for AI response generation logic
    # Integrate with an AI model based on `current_model`
    response = f"Echo: {message}"  # Replace with actual AI integration
    return response

Explanation:

  • File Path: app/utils.py
  • Function: generate_ai_response generates a response based on the user's message. Integrate with actual AI models as needed.

Testing and Deployment

  1. Local Testing:

    • Run the application locally using the command:
      python app/main.py
    • Open the browser at http://127.0.0.1:5001 to interact with the chatbot UI.
    • Test all functionalities:
      • Sending and receiving messages.
      • Selecting different AI models.
      • Selecting tools from the tool selector.
  2. Unit Testing:

    • Write tests for utility functions in app/utils.py.
    • Test route handlers in app/main.py using FastHTML's test client.
  3. Deployment:

    • Deploy the FastHTML application using uvicorn or other ASGI servers.
    • Ensure environment variables and configurations are set appropriately for production.
    • Secure the application and database.
  4. Continuous Integration:

    • Set up CI/CD pipelines to automate testing and deployment.
    • Use tools like GitHub Actions, Travis CI, or Jenkins.

Additional Considerations

  • Session Management:

    • Implement user sessions to maintain state across requests, such as selected AI model and tool.
    • Use FastHTML's session management or integrate with Starlette's session features.
  • Real-Time Updates:

    • Enhance the chat experience with real-time message updates using Server-Sent Events (SSE) or WebSockets if needed.
  • Styling Enhancements:

    • Further refine the UI to closely match Discord's look and feel.
    • Consider using additional CSS frameworks or custom styles for badges, avatars, and other UI elements.
  • Security:

    • Validate and sanitize user inputs to prevent security vulnerabilities.
    • Implement authentication if the application requires secure access.
  • Scalability:

    • Optimize the application for handling multiple concurrent users.
    • Implement efficient database queries and consider using caching mechanisms.

By following this implementation plan, you can develop a robust and aesthetically pleasing Discord-inspired chatbot UI using FastHTML. Adjust and expand upon each section as needed to fit specific project requirements and enhancements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment