mesop-app-maker / templates /basic_chat.txt
Richard
Update prompts + add chat optimized prompt
3d1636d
import random
import time
from dataclasses import dataclass
from typing import Literal
import mesop as me
Role = Literal["user", "bot"]
@dataclass(kw_only=True)
class ChatMessage:
"""Chat message metadata."""
role: Role = "user"
content: str = ""
edited: bool = False
@me.stateclass
class State:
input: str
output: list[ChatMessage]
in_progress: bool
@me.page()
def basic_chat():
state = me.state(State)
with me.box(
style=me.Style(
color=me.theme_var("on-surface"),
background=me.theme_var("surface-container-lowest"),
display="flex",
flex_direction="column",
height="100%",
padding=me.Padding.all(15),
)
):
# This contains the chat messages that have been recorded. This takes 50fr.
# This section can be replaced with other types of chat messages.
# We set overflow to scroll so that the chat input will be fixed at the bottom.
with me.box(style=me.Style(overflow_y="scroll", flex_grow=1)):
for msg in state.output:
# User chat message
if msg.role == "user":
with me.box(
style=me.Style(display="flex", gap=15, margin=me.Margin.all(20))
):
# User avatar/icon box
me.text(
"U",
style=me.Style(
background=me.theme_var("primary"),
border_radius="50%",
color=me.theme_var("on-primary"),
font_size=20,
height=40,
width=40,
text_align="center",
line_height="1",
padding=me.Padding(top=10),
margin=me.Margin(top=16),
),
)
# User query
me.markdown(msg.content)
else:
# Bot chat message
with me.box(
style=me.Style(display="flex", gap=15, margin=me.Margin.all(20))
):
# Bot avatar/icon box
me.text(
"B",
style=me.Style(
background=me.theme_var("secondary"),
border_radius="50%",
color=me.theme_var("on-secondary"),
font_size=20,
height=40,
width="40px",
text_align="center",
line_height="1",
padding=me.Padding(top=10),
margin=me.Margin(top=16),
),
)
# Bot message response
me.markdown(
msg.content,
style=me.Style(color=me.theme_var("on-surface")),
)
# This is for the basic chat input. This is the second row at 1fr.
# This section can be replaced with other types of chat inputs.
with me.box(
style=me.Style(
border_radius=16,
padding=me.Padding.all(8),
background=me.theme_var("surface-container-low"),
display="flex",
width="100%",
)
):
with me.box(
style=me.Style(
flex_grow=1,
)
):
me.native_textarea(
key="chat_input",
value=state.input,
on_blur=on_chat_input,
autosize=True,
min_rows=4,
placeholder="Subtle chat input",
style=me.Style(
color=me.theme_var("on-surface-variant"),
padding=me.Padding(top=16, left=16),
background=me.theme_var("surface-container-low"),
outline="none",
width="100%",
overflow_y="auto",
border=me.Border.all(
me.BorderSide(style="none"),
),
),
)
with me.content_button(
type="icon",
on_click=on_click_submit_chat_msg,
# If we're processing a message prevent new queries from being sent
disabled=state.in_progress,
):
me.icon("send")
def on_chat_input(e: me.InputBlurEvent):
"""Capture chat text input on blur."""
state = me.state(State)
state.input = e.value
def on_click_submit_chat_msg(e: me.ClickEvent):
"""Handles submitting a chat message."""
state = me.state(State)
if state.in_progress or not state.input:
return
input = state.input
# Clear the text input.
state.input = ""
yield
output = state.output
if output is None:
output = []
output.append(ChatMessage(role="user", content=input))
state.in_progress = True
yield
start_time = time.time()
# Send user input and chat history to get the bot response.
output_message = respond_to_chat(input, state.output)
assistant_message = ChatMessage(role="bot")
output.append(assistant_message)
state.output = output
for content in output_message:
assistant_message.content += content
# TODO: 0.25 is an abitrary choice. In the future, consider making this adjustable.
if (time.time() - start_time) >= 0.25:
start_time = time.time()
yield
state.in_progress = False
me.focus_component(key="chat_input")
yield
def respond_to_chat(input: str, history: list[ChatMessage]):
"""Displays random canned text.
Edit this function to process messages with a real chatbot/LLM.
"""
lines = [
"Mesop is a Python-based UI framework designed to simplify web UI development for engineers without frontend experience.",
"It leverages the power of the Angular web framework and Angular Material components, allowing rapid construction of web demos and internal tools.",
"With Mesop, developers can enjoy a fast build-edit-refresh loop thanks to its hot reload feature, making UI tweaks and component integration seamless.",
"Deployment is straightforward, utilizing standard HTTP technologies.",
"Mesop's component library aims for comprehensive Angular Material component coverage, enhancing UI flexibility and composability.",
"It supports custom components for specific use cases, ensuring developers can extend its capabilities to fit their unique requirements.",
"Mesop's roadmap includes expanding its component library and simplifying the onboarding processs.",
]
for line in random.sample(lines, random.randint(3, len(lines) - 1)):
yield line + " "