Skip to content

Commit 5f775d2

Browse files
committed
Add another golden
1 parent ad0f7ba commit 5f775d2

File tree

5 files changed

+593
-1
lines changed

5 files changed

+593
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<<<<<<< ORIGINAL
2+
# Header
3+
with me.box(
4+
style=me.Style(
5+
background=me.theme_var("primary"),
6+
padding=me.Padding.all(16),
7+
border_radius=8,
8+
margin=me.Margin(bottom=20),
9+
display="flex",
10+
align_items="center",
11+
)
12+
):
13+
me.icon(
14+
"chat", style=me.Style(color=me.theme_var("on-primary"), font_size=24)
15+
)
16+
me.text(
17+
"AI Chatbot",
18+
style=me.Style(
19+
color=me.theme_var("on-primary"),
20+
font_size=24,
21+
font_weight="bold",
22+
margin=me.Margin(left=12),
23+
),
24+
)
25+
me.text(
26+
"Talk to our intelligent assistant",
27+
style=me.Style(
28+
color=me.theme_var("on-primary"),
29+
font_size=16,
30+
margin=me.Margin(left=12),
31+
),
32+
)
33+
=======
34+
# Header
35+
with me.box(
36+
style=me.Style(
37+
background=me.theme_var("secondary"),
38+
padding=me.Padding.all(16),
39+
border_radius=8,
40+
margin=me.Margin(bottom=20),
41+
display="flex",
42+
align_items="center",
43+
)
44+
):
45+
me.icon(
46+
"chat", style=me.Style(color=me.theme_var("on-secondary"), font_size=24)
47+
)
48+
me.text(
49+
"AI Chatbot",
50+
style=me.Style(
51+
color=me.theme_var("on-secondary"),
52+
font_size=24,
53+
font_weight="bold",
54+
margin=me.Margin(left=12),
55+
),
56+
)
57+
me.text(
58+
"Talk to our intelligent assistant",
59+
style=me.Style(
60+
color=me.theme_var("on-secondary"),
61+
font_size=16,
62+
margin=me.Margin(left=12),
63+
),
64+
)
65+
>>>>>>> UPDATED
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
import random
2+
import time
3+
from dataclasses import dataclass
4+
from typing import Literal
5+
6+
import mesop as me
7+
8+
Role = Literal["user", "bot"]
9+
10+
11+
@dataclass(kw_only=True)
12+
class ChatMessage:
13+
"""Chat message metadata."""
14+
15+
role: Role = "user"
16+
content: str = ""
17+
edited: bool = False
18+
19+
20+
@me.stateclass
21+
class State:
22+
input: str
23+
output: list[ChatMessage]
24+
in_progress: bool
25+
26+
27+
@me.page(path="/ai")
28+
def page():
29+
state = me.state(State)
30+
with me.box(
31+
style=me.Style(
32+
color=me.theme_var("on-surface"),
33+
background=me.theme_var("surface-container-lowest"),
34+
display="flex",
35+
flex_direction="column",
36+
height="100%",
37+
padding=me.Padding.all(15),
38+
)
39+
):
40+
# Header
41+
with me.box(
42+
style=me.Style(
43+
background=me.theme_var("secondary"),
44+
padding=me.Padding.all(16),
45+
border_radius=8,
46+
margin=me.Margin(bottom=20),
47+
display="flex",
48+
align_items="center",
49+
)
50+
):
51+
me.icon(
52+
"chat", style=me.Style(color=me.theme_var("on-secondary"), font_size=24)
53+
)
54+
me.text(
55+
"AI Chatbot",
56+
style=me.Style(
57+
color=me.theme_var("on-secondary"),
58+
font_size=24,
59+
font_weight="bold",
60+
margin=me.Margin(left=12),
61+
),
62+
)
63+
me.text(
64+
"Talk to our intelligent assistant",
65+
style=me.Style(
66+
color=me.theme_var("on-secondary"),
67+
font_size=16,
68+
margin=me.Margin(left=12),
69+
),
70+
)
71+
# This contains the chat messages that have been recorded. This takes 50fr.
72+
# This section can be replaced with other types of chat messages.
73+
74+
# We set overflow to scroll so that the chat input will be fixed at the bottom.
75+
with me.box(style=me.Style(overflow_y="scroll", flex_grow=1)):
76+
for msg in state.output:
77+
# User chat message
78+
if msg.role == "user":
79+
with me.box(
80+
style=me.Style(display="flex", gap=15, margin=me.Margin.all(20))
81+
):
82+
# User avatar/icon box
83+
me.text(
84+
"U",
85+
style=me.Style(
86+
background=me.theme_var("primary"),
87+
border_radius="50%",
88+
color=me.theme_var("on-primary"),
89+
font_size=20,
90+
height=40,
91+
width=40,
92+
text_align="center",
93+
line_height="1",
94+
padding=me.Padding(top=10),
95+
margin=me.Margin(top=16),
96+
),
97+
)
98+
# User query
99+
me.markdown(msg.content)
100+
else:
101+
# Bot chat message
102+
with me.box(
103+
style=me.Style(display="flex", gap=15, margin=me.Margin.all(20))
104+
):
105+
# Bot avatar/icon box
106+
me.text(
107+
"B",
108+
style=me.Style(
109+
background=me.theme_var("secondary"),
110+
border_radius="50%",
111+
color=me.theme_var("on-secondary"),
112+
font_size=20,
113+
height=40,
114+
width="40px",
115+
text_align="center",
116+
line_height="1",
117+
padding=me.Padding(top=10),
118+
margin=me.Margin(top=16),
119+
),
120+
)
121+
with me.box(
122+
style=me.Style(
123+
display="flex",
124+
flex_direction="column",
125+
margin=me.Margin.all(20)
126+
)
127+
):
128+
# Bot message response
129+
me.markdown(
130+
msg.content,
131+
style=me.Style(color=me.theme_var("on-surface")),
132+
)
133+
with me.box(
134+
style=me.Style(
135+
display="flex",
136+
flex_direction="column",
137+
align_items="flex-start", # Align buttons to the start (left)
138+
margin=me.Margin(top=8),
139+
)
140+
):
141+
with me.box(
142+
style=me.Style(
143+
display="flex",
144+
gap=10,
145+
margin=me.Margin(bottom=8),
146+
)
147+
):
148+
with me.content_button(
149+
type="icon",
150+
style=me.Style(
151+
background=me.theme_var("surface-container-low"),
152+
),
153+
):
154+
me.icon("thumb_up")
155+
with me.content_button(
156+
type="icon",
157+
style=me.Style(
158+
background=me.theme_var("surface-container-low"),
159+
),
160+
):
161+
me.icon("thumb_down")
162+
163+
# This is for the basic chat input. This is the second row at 1fr.
164+
# This section can be replaced with other types of chat inputs.
165+
with me.box(
166+
style=me.Style(
167+
border_radius=16,
168+
padding=me.Padding.all(8),
169+
background=me.theme_var("surface-container-low"),
170+
display="flex",
171+
width="100%",
172+
)
173+
):
174+
with me.box(
175+
style=me.Style(
176+
flex_grow=1,
177+
)
178+
):
179+
me.native_textarea(
180+
key="chat_input",
181+
value=state.input,
182+
on_blur=on_chat_input,
183+
autosize=True,
184+
min_rows=4,
185+
placeholder="Subtle chat input",
186+
style=me.Style(
187+
color=me.theme_var("on-surface-variant"),
188+
padding=me.Padding(top=16, left=16),
189+
background=me.theme_var("surface-container-low"),
190+
outline="none",
191+
width="100%",
192+
overflow_y="auto",
193+
border=me.Border.all(
194+
me.BorderSide(style="none"),
195+
),
196+
),
197+
)
198+
with me.content_button(
199+
type="icon",
200+
on_click=on_click_submit_chat_msg,
201+
# If we're processing a message prevent new queries from being sent
202+
disabled=state.in_progress,
203+
):
204+
me.icon("send")
205+
206+
207+
def on_chat_input(e: me.InputBlurEvent):
208+
"""Capture chat text input on blur."""
209+
state = me.state(State)
210+
state.input = e.value
211+
212+
213+
def on_click_submit_chat_msg(e: me.ClickEvent):
214+
"""Handles submitting a chat message."""
215+
state = me.state(State)
216+
if state.in_progress or not state.input:
217+
return
218+
input = state.input
219+
# Clear the text input.
220+
state.input = ""
221+
yield
222+
223+
output = state.output
224+
if output is None:
225+
output = []
226+
output.append(ChatMessage(role="user", content=input))
227+
state.in_progress = True
228+
yield
229+
230+
start_time = time.time()
231+
# Send user input and chat history to get the bot response.
232+
output_message = respond_to_chat(input, state.output)
233+
assistant_message = ChatMessage(role="bot")
234+
output.append(assistant_message)
235+
state.output = output
236+
for content in output_message:
237+
assistant_message.content += content
238+
# TODO: 0.25 is an abitrary choice. In the future, consider making this adjustable.
239+
if (time.time() - start_time) >= 0.25:
240+
start_time = time.time()
241+
yield
242+
243+
state.in_progress = False
244+
me.focus_component(key="chat_input")
245+
yield
246+
247+
248+
def respond_to_chat(input: str, history: list[ChatMessage]):
249+
"""Displays random canned text.
250+
251+
Edit this function to process messages with a real chatbot/LLM.
252+
"""
253+
lines = [
254+
"Mesop is a Python-based UI framework designed to simplify web UI development for engineers without frontend experience.",
255+
"It leverages the power of the Angular web framework and Angular Material components, allowing rapid construction of web demos and internal tools.",
256+
"With Mesop, developers can enjoy a fast build-edit-refresh loop thanks to its hot reload feature, making UI tweaks and component integration seamless.",
257+
"Deployment is straightforward, utilizing standard HTTP technologies.",
258+
"Mesop's component library aims for comprehensive Angular Material component coverage, enhancing UI flexibility and composability.",
259+
"It supports custom components for specific use cases, ensuring developers can extend its capabilities to fit their unique requirements.",
260+
"Mesop's roadmap includes expanding its component library and simplifying the onboarding processs.",
261+
]
262+
for line in random.sample(lines, random.randint(3, len(lines) - 1)):
263+
yield line + " "
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Change the color of the header to be the secondary theme color

0 commit comments

Comments
 (0)