Skip to content

Commit e0f3d90

Browse files
Merge pull request #34 from basedosdados/chore/ui-improvements
chore: ui improvements
2 parents b8d43d3 + 26fe4a7 commit e0f3d90

File tree

2 files changed

+75
-41
lines changed

2 files changed

+75
-41
lines changed

frontend/components/chat_page.py

Lines changed: 73 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import sqlparse
66
import streamlit as st
77
from loguru import logger
8+
from streamlit.delta_generator import DeltaGenerator
89
from streamlit_extras.stylable_container import stylable_container
910

1011
from frontend.api import APIClient
@@ -279,14 +280,15 @@ def render(self):
279280
with st.chat_message("assistant", avatar=BD_LOGO):
280281
st.empty()
281282

282-
if message_pair.assistant_message is not None:
283-
label, state = "Concluído!", "complete"
284-
else:
285-
label, state = "Erro", "error"
283+
if _has_tool_events(message_pair.events):
284+
if message_pair.assistant_message is not None:
285+
label, state = "Concluído! Clique para ver os detalhes", "complete"
286+
else:
287+
label, state = "Erro", "error"
286288

287-
with st.status(label=label, state=state) as status:
288-
for event in message_pair.events:
289-
_display_tool_event(event)
289+
with st.status(label=label, state=state):
290+
for event in message_pair.events:
291+
_display_tool_event(event)
290292

291293
if message_pair.assistant_message is not None:
292294
st.write(message_pair.formatted_assistant_message)
@@ -319,33 +321,40 @@ def render(self):
319321
# Display assistant response in chat message container
320322
with st.chat_message("assistant", avatar=BD_LOGO):
321323
events = []
322-
assistant_message = None
323324
error_message = None
325+
assistant_message = None
326+
status_placeholder = st.empty()
324327

325-
with st.status("Consultando a Base dos Dados...") as status:
326-
for event in self.api.send_message(
327-
access_token=st.session_state["access_token"],
328-
message=user_prompt,
329-
thread_id=self.thread_id
330-
):
331-
events.append(event)
332-
if event.type == "final_answer":
333-
assistant_message = event.data.content
334-
label, state = "Concluído!", "complete"
335-
elif event.type == "error":
336-
error_message = event.data.error_details.get("message", "Erro")
337-
label, state = "Erro", "error"
338-
elif event.type == "complete":
339-
message_pair = MessagePair(
340-
id=event.data.run_id,
341-
user_message=user_prompt,
342-
assistant_message=assistant_message,
343-
error_message=error_message,
344-
events=events
345-
)
328+
status = status_placeholder.status("Pensando...")
329+
330+
for event in self.api.send_message(
331+
access_token=st.session_state["access_token"],
332+
message=user_prompt,
333+
thread_id=self.thread_id
334+
):
335+
events.append(event)
336+
337+
if event.type == "final_answer":
338+
assistant_message = event.data.content
339+
label, state = "Concluído! Clique para ver os detalhes", "complete"
340+
elif event.type == "error":
341+
error_message = event.data.error_details.get("message", "Erro")
342+
label, state = "Erro", "error"
343+
elif event.type == "complete":
344+
message_pair = MessagePair(
345+
id=event.data.run_id,
346+
user_message=user_prompt,
347+
assistant_message=assistant_message,
348+
error_message=error_message,
349+
events=events
350+
)
351+
if _has_tool_events(message_pair.events):
346352
status.update(label=label, state=state)
347353
else:
348-
_display_tool_event(event)
354+
status_placeholder.empty()
355+
else:
356+
status.update(label="Consultando a Base dos Dados...")
357+
_display_tool_event(event, container=status)
349358

350359
if message_pair.assistant_message is not None:
351360
st.write_stream(message_pair.stream_words)
@@ -402,7 +411,24 @@ def _clear_new_chat_page():
402411
st.session_state[NEW_CHAT] = None
403412

404413

405-
def _display_code_block(code_block: str, max_lines: int=10, max_height: int=256):
414+
def _has_tool_events(events: list[StreamEvent]) -> bool:
415+
"""Check if there are any tool-related events in the event list.
416+
417+
Args:
418+
events (list[StreamEvent]): List of stream events.
419+
420+
Returns:
421+
bool: True if there are tool_call or tool_output events, False otherwise.
422+
"""
423+
return any(event.type in ("tool_call", "tool_output") for event in events)
424+
425+
426+
def _display_code_block(
427+
code_block: str,
428+
max_lines: int=10,
429+
max_height: int=256,
430+
container: DeltaGenerator | None = None
431+
):
406432
"""Display a code block in Streamlit with adaptive height.
407433
408434
If the code block has more lines than `max_lines`, the display height
@@ -415,15 +441,19 @@ def _display_code_block(code_block: str, max_lines: int=10, max_height: int=256)
415441
before capping the height. Defaults to 10.
416442
max_height (int, optional): Maximum height in pixels for code blocks
417443
exceeding `max_lines`. Defaults to 256.
444+
container (DeltaGenerator | None, optional): Streamlit container
445+
to render into. If None, uses st directly. Defaults to None.
418446
"""
447+
ctx = container if container is not None else st
448+
419449
n_lines = code_block.count("\n") + 1
420450

421451
if n_lines > max_lines:
422452
height = max_height
423453
else:
424454
height = "content"
425455

426-
st.code(code_block, height=height)
456+
ctx.code(code_block, height=height)
427457

428458

429459
def _format_tool_args(args: dict[str, Any]) -> str:
@@ -470,28 +500,32 @@ def _format_tool_outputs(results: str) -> str:
470500
)
471501

472502

473-
def _display_tool_event(event: StreamEvent):
503+
def _display_tool_event(event: StreamEvent, container: DeltaGenerator | None = None):
474504
"""Render a tool-related event in the Streamlit UI.
475505
476506
Displays messages, tool call arguments, and tool outputs
477507
with appropriate formatting and code block sizing.
478508
479509
Args:
480510
event (StreamEvent): The tool event to display.
511+
container (DeltaGenerator | None, optional): Streamlit container
512+
to render into. If None, uses st directly. Defaults to None.
481513
"""
514+
ctx = container if container is not None else st
515+
482516
if event.type == "tool_call":
483517
if event.data.content:
484-
st.markdown(event.data.content)
518+
ctx.markdown(event.data.content)
485519
for tool_call in event.data.tool_calls:
486-
st.markdown(f"**Executando ferramenta** `{tool_call.name}`")
520+
ctx.markdown(f"**Executando ferramenta** `{tool_call.name}`")
487521
tool_args = _format_tool_args(tool_call.args)
488-
_display_code_block(f"Solicitação:\n{tool_args}")
522+
_display_code_block(f"Solicitação:\n{tool_args}", container=ctx)
489523
elif event.type == "tool_output":
490524
for tool_output in event.data.tool_outputs:
491525
if tool_output.status == "error":
492-
st.markdown(f"Erro na execução da ferramenta `{tool_output.tool_name}`")
526+
ctx.markdown(f"Erro na execução da ferramenta `{tool_output.tool_name}`")
493527
else:
494528
if tool_output.metadata and tool_output.metadata.get("truncated"):
495-
st.info("Resposta muito extensa. Exibindo resultados parciais.", icon=":material/info:")
529+
ctx.info("Resposta muito extensa. Exibindo resultados parciais.", icon=":material/info:")
496530
tool_outputs = _format_tool_outputs(tool_output.output)
497-
_display_code_block(f"Resposta:\n{tool_outputs}")
531+
_display_code_block(f"Resposta:\n{tool_outputs}", container=ctx)

frontend/components/three_dots.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
.progress > div {
1111
width: 7px;
1212
height: 7px;
13-
background-color: #fafafa;
13+
background-color: #7c7f84;
1414
border-radius: 100%;
1515
display: inline-block;
1616
animation: wave 1.4s infinite ease-in-out both;
@@ -56,7 +56,7 @@
5656
.progress > div {
5757
width: 7px;
5858
height: 7px;
59-
background-color: #fafafa;
59+
background-color: #7c7f84;
6060
border-radius: 100%;
6161
display: inline-block;
6262
animation: pulse 1.4s infinite ease-in-out both;

0 commit comments

Comments
 (0)